summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/core.meta.slang104
-rw-r--r--source/slang/glsl.meta.slang54
-rw-r--r--source/slang/hlsl.meta.slang921
-rw-r--r--source/slang/slang-ast-print.cpp15
-rw-r--r--source/slang/slang-ast-print.h5
-rw-r--r--source/slang/slang-capability.cpp19
-rwxr-xr-xsource/slang/slang-compiler.h1
-rw-r--r--source/slang/slang-diagnostic-defs.h3
-rw-r--r--source/slang/slang-doc-ast.h2
-rw-r--r--source/slang/slang-doc-markdown-writer.cpp2437
-rw-r--r--source/slang/slang-doc-markdown-writer.h167
-rw-r--r--source/slang/slang-language-server-completion.cpp12
-rw-r--r--source/slang/slang.cpp91
13 files changed, 2988 insertions, 843 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 62c9a2800..d0f0fcee2 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -1,15 +1,24 @@
// Slang `core` library
// Aliases for base types
+/// @category scalar_types Scalar types
typedef half float16_t;
+/// @category scalar_types
typedef float float32_t;
+/// @category scalar_types
typedef double float64_t;
+/// @category scalar_types
typedef int int32_t;
+
+/// @category scalar_types
typedef uint uint32_t;
+/// @category scalar_types
typedef uintptr_t size_t;
-typedef uintptr_t usize_t
+/// @category scalar_types
+typedef uintptr_t usize_t;
+/// @category scalar_types
typedef intptr_t ssize_t;
// Modifier for variables that must resolve to compile-time constants
@@ -446,6 +455,7 @@ interface IRWArray<T> : IArray<T>
// argument. The left-to-right evaluation order guaranteed by Slang then ensures that
// `left` is evaluated before `right`.
//
+//@hidden:
__generic<T,U>
[__unsafeForceInlineEarly]
U operator,(T left, U right)
@@ -457,20 +467,29 @@ U operator,(T left, U right)
// follow that definition for the scalar condition overload, so this declaration just serves
// for type-checking purpose only.
-__generic<T> __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse);
+//@hidden:
+__generic<T> __intrinsic_op(select) T operator?: (bool condition, T ifTrue, T ifFalse);
+
+//@hidden:
__generic<T, let N : int> __intrinsic_op(select) vector<T,N> operator?:(vector<bool,N> condition, vector<T,N> ifTrue, vector<T,N> ifFalse);
// Users are advised to use `select` instead if non-short-circuiting behavior is intended.
+//@public:
__generic<T> __intrinsic_op(select) T select(bool condition, T ifTrue, T ifFalse);
__generic<T, let N : int> __intrinsic_op(select) vector<T,N> select(vector<bool,N> condition, vector<T,N> ifTrue, vector<T,N> ifFalse);
// Allow real-number types to be cast into each other
+//@hidden:
__intrinsic_op($(kIROp_FloatCast))
T __realCast<T : __BuiltinRealType, U : __BuiltinRealType>(U val);
+//@hidden:
__intrinsic_op($(kIROp_CastIntToFloat))
- T __realCast<T : __BuiltinRealType, U : __BuiltinIntegerType>(U val);
+T __realCast<T : __BuiltinRealType, U : __BuiltinIntegerType>(U val);
+//@hidden:
__intrinsic_op($(kIROp_IntCast))
- T __intCast<T : __BuiltinType, U : __BuiltinType>(U val);
+T __intCast<T : __BuiltinType, U : __BuiltinType>(U val);
+
+//@hidden:
${{{{
// We are going to use code generation to produce the
// declarations for all of our base types.
@@ -716,17 +735,20 @@ ${{{{
// (eventually we can have the traditional syntax sugar for this)
}}}}
+//@hidden:
__magic_type(NullPtrType)
struct NullPtr
{
};
+//@hidden:
__magic_type(NoneType)
__intrinsic_type($(kIROp_VoidType))
struct __none_t
{
};
+//@public:
__generic<T, let addrSpace : uint64_t = $( (uint64_t)AddressSpace::UserPointer)ULL>
__magic_type(PtrType)
__intrinsic_type($(kIROp_PtrType))
@@ -752,6 +774,7 @@ struct Ptr
}
};
+//@hidden:
__intrinsic_op($(kIROp_Load))
T __load<T, let addrSpace : uint64_t>(Ptr<T, addrSpace> ptr);
@@ -788,6 +811,7 @@ __generic<T, let addrSpace : uint64_t>
__intrinsic_op($(kIROp_Eql))
bool operator ==(Ptr<T, addrSpace> p1, Ptr<T, addrSpace> p2);
+//@public:
extension bool : IRangedValue
{
__generic<T, let addrSpace : uint64_t>
@@ -847,6 +871,7 @@ extension uintptr_t : IRangedValue
static const int size = $(SLANG_PROCESSOR_X86_64?"8":"4");
}
+//@hidden:
__generic<T>
__magic_type(OutType)
__intrinsic_type($(kIROp_OutType))
@@ -873,6 +898,7 @@ struct ConstRef
typealias __Addr<T> = Ptr<T, $( (uint64_t)AddressSpace::Generic)ULL>;
+//@public:
__generic<T>
__magic_type(OptionalType)
__intrinsic_type($(kIROp_OptionalType))
@@ -895,6 +921,7 @@ struct Optional
__init(T val);
};
+//@hidden:
__generic<T>
[__unsafeForceInlineEarly]
bool operator==(Optional<T> val, __none_t noneVal)
@@ -920,6 +947,7 @@ bool operator!=(__none_t noneVal, Optional<T> val)
return val.hasValue;
}
+//@public:
__generic<each T>
__magic_type(TupleType)
struct Tuple
@@ -936,7 +964,7 @@ Tuple<T, U> concat<each T, each U>(Tuple<T> t, Tuple<U> u)
return makeTuple(expand each t, expand each u);
}
-
+//@hidden:
[__unsafeForceInlineEarly]
bool __assign(inout bool v, bool newVal)
{
@@ -978,6 +1006,7 @@ void __tupleGreaterKernel<T : IComparable>(inout bool result, inout bool exit, T
}
}
+//@public:
__generic<each T : IComparable>
extension Tuple<T> : IComparable
{
@@ -1027,6 +1056,7 @@ interface IDifferentiableFunc<TR : IDifferentiable, each TP : IDifferentiable> :
TR operator()(expand each TP p);
}
+//@hidden:
__generic<T>
__magic_type(NativeRefType)
__intrinsic_type($(kIROp_NativePtrType))
@@ -1049,6 +1079,7 @@ T __attachToNativeRef(NativeRef<T> nativeVal)
return result;
}
+//@public:
__magic_type(StringType)
__intrinsic_type($(kIROp_StringType))
struct String
@@ -1086,8 +1117,10 @@ struct String
}
};
+/// @category misc_types
typedef String string;
+/// @category misc_types
__magic_type(NativeStringType)
__intrinsic_type($(kIROp_NativeStringType))
struct NativeString
@@ -1133,11 +1166,14 @@ extension Ptr<void>
__init(NativeRef<T> ptr);
}
+//@hidden:
__magic_type(DynamicType)
__intrinsic_type($(kIROp_DynamicType))
struct __Dynamic
{};
+//@public:
+
extension half : IRangedValue
{
static const half maxValue = half(65504);
@@ -1200,7 +1236,9 @@ struct Array : IRWArray<T>
__intrinsic_op($(kIROp_GetArrayLength))
int getCount();
}
- /// An `N` component vector with elements of type `T`.
+
+/// @category math_types Math types
+/// An `N` component vector with elements of type `T`.
__generic<T = float, let N : int = 4>
__magic_type(VectorExpressionType)
struct vector : IRWArray<T>
@@ -1225,10 +1263,13 @@ struct vector : IRWArray<T>
int getCount() { return N; }
}
-const int kRowMajorMatrixLayout = $(SLANG_MATRIX_LAYOUT_ROW_MAJOR);
-const int kColumnMajorMatrixLayout = $(SLANG_MATRIX_LAYOUT_COLUMN_MAJOR);
+//@hidden:
+static const int kRowMajorMatrixLayout = $(SLANG_MATRIX_LAYOUT_ROW_MAJOR);
+static const int kColumnMajorMatrixLayout = $(SLANG_MATRIX_LAYOUT_COLUMN_MAJOR);
- /// A matrix with `R` rows and `C` columns, with elements of type `T`.
+//@public:
+/// A matrix with `R` rows and `C` columns, with elements of type `T`.
+/// @category math_types Math types
__generic<T = float, let R : int = 4, let C : int = 4, let L : int = $(SLANG_MATRIX_LAYOUT_MODE_UNKNOWN)>
__magic_type(MatrixExpressionType)
struct matrix : IRWArray<vector<T,C>>
@@ -1248,9 +1289,11 @@ struct matrix : IRWArray<vector<T,C>>
int getCount() { return R; }
}
+//@hidden:
__intrinsic_op($(kIROp_Eql))
-vector<bool, N> __vectorEql<T, let N:int>(vector<T, N> left, vector<T,N> right);
+vector<bool, N> __vectorEql<T, let N : int>(vector<T, N> left, vector<T, N> right);
+//@public:
__generic<T:__BuiltinFloatingPointType, let N : int>
extension vector<T,N> : IFloat
{
@@ -1360,10 +1403,12 @@ extension matrix<int16_t,R,C,L>
__init(int value) { this = matrix<T,R,C,L>(T(value)); }
}
+//@hidden:
__intrinsic_op(makeVector)
__generic<T, let N:int>
vector<T,N*2> __makeVector(vector<T,N> vec1, vector<T,N> vec2);
+//@public:
__generic<T>
extension vector<T, 4>
{
@@ -1385,6 +1430,7 @@ extension matrix<T, 2, 2, L>
}
}
+//@hidden:
${{{{
static const struct {
char const* name;
@@ -1458,6 +1504,7 @@ __intrinsic_type($(kIROp_ConstantBufferType))
__magic_type(ConstantBufferType)
struct ConstantBuffer {}
+///@category texture_types
__generic<T>
__intrinsic_type($(kIROp_TextureBufferType))
__magic_type(TextureBufferType)
@@ -1468,6 +1515,7 @@ __intrinsic_type($(kIROp_ParameterBlockType))
__magic_type(ParameterBlockType)
struct ParameterBlock {}
+/// @category stage_io
__generic<T, let MAX_VERTS : uint>
__magic_type(VerticesType)
__intrinsic_type($(kIROp_VerticesType))
@@ -1507,6 +1555,7 @@ struct OutputVertices
}
};
+/// @category stage_io
__generic<T, let MAX_PRIMITIVES : uint>
__magic_type(IndicesType)
__intrinsic_type($(kIROp_IndicesType))
@@ -1539,6 +1588,7 @@ struct OutputIndices
}
};
+/// @category stage_io
__generic<T, let MAX_PRIMITIVES : uint>
__magic_type(PrimitivesType)
__intrinsic_type($(kIROp_PrimitivesType))
@@ -1573,7 +1623,7 @@ struct OutputPrimitives
}
};
-//@ hidden:
+//@ public:
// Need to add constructors to the types above
@@ -1757,6 +1807,7 @@ ${{{{
}
}}}}
+//@ hidden:
__generic<T, U>
__intrinsic_op(0)
T __slang_noop_cast(U u);
@@ -1764,14 +1815,16 @@ T __slang_noop_cast(U u);
//@ public:
- /// Sampling state for filtered texture fetches.
+/// Sampling state for filtered texture fetches.
+/// @category sampler_types Sampler types
__magic_type(SamplerStateType, $(int(SamplerStateFlavor::SamplerState)))
__intrinsic_type($(kIROp_SamplerStateType))
struct SamplerState
{
}
- /// Sampling state for filtered texture fetches that include a comparison operation before filtering.
+/// Sampling state for filtered texture fetches that include a comparison operation before filtering.
+/// @category sampler_types
__magic_type(SamplerStateType, $(int(SamplerStateFlavor::SamplerComparisonState)))
__intrinsic_type($(kIROp_SamplerComparisonStateType))
struct SamplerComparisonState
@@ -2212,7 +2265,9 @@ ${{{{
//@ public:
-// Bit cast
+/// Bit cast between types. `T` and `U` must have the same size.
+/// They can be any scalar, vector, matrix, struct or array types.
+/// @category conversion
__generic<T, U>
[__unsafeForceInlineEarly]
__intrinsic_op($(kIROp_BitCast))
@@ -2224,15 +2279,16 @@ __generic<T, U>
__intrinsic_op($(kIROp_CreateExistentialObject))
T createDynamicObject(uint typeId, U value);
-// Reinterpret
+/// Reinterpret type `U` as type `T`. `T` and `U`
+/// can be any scalar, vector, matrix, struct or array types.
+/// @category conversion
__generic<T, U>
[__unsafeForceInlineEarly]
__intrinsic_op($(kIROp_Reinterpret))
T reinterpret(U value);
-// Use an otherwise unused value
-//
-// This can be used to silence the warning about returning before initializing an out paramter.
+/// Use an otherwise unused value
+/// This can be used to silence the warning about returning before initializing an out paramter.
__generic<T>
[__readNone]
[ForceInline]
@@ -2267,6 +2323,8 @@ int __SyntaxError()
}
}
+//@ hidden:
+
/// For downstream compilers that allow sizeof/alignof/offsetof
/// Can't be called in the C/C++ style. Need to use __size_of<some_type>() as opposed to sizeof(some_type).
__generic<T>
@@ -2350,7 +2408,7 @@ __generic<E : __EnumType>
__intrinsic_op($(kIROp_Neq))
bool operator!=(E left, E right);
-//@ public:
+//@ hidden:
// public interfaces for generic arithmetic types.
@@ -2722,8 +2780,8 @@ __Addr<T> __getLegalizedSPIRVGlobalParamAddr(T val);
__intrinsic_op($(kIROp_RequireComputeDerivative))
void __requireComputeDerivative();
-// Atomic<T>
-
+//@ public:
+/// @category misc_types
enum MemoryOrder
{
Relaxed = $(kIRMemoryOrder_Relaxed),
@@ -2767,6 +2825,7 @@ struct Atomic<T : IAtomicable>
MemoryOrder failOrder = MemoryOrder.Relaxed);
}
+/// These addtional members are only available when `T` conforms to `IArithmeticAtomicable`.
extension<T : IArithmeticAtomicable> Atomic<T>
{
__intrinsic_op($(kIROp_AtomicAdd))
@@ -2779,6 +2838,7 @@ extension<T : IArithmeticAtomicable> Atomic<T>
[__ref] T min(T value, MemoryOrder order = MemoryOrder.Relaxed); // returns original value
}
+/// These addtional members are only available when `T` conforms to `IBitAtomicable`.
extension<T : IBitAtomicable> Atomic<T>
{
__intrinsic_op($(kIROp_AtomicAnd))
@@ -2793,6 +2853,8 @@ extension<T : IBitAtomicable> Atomic<T>
[__ref] T decrement(MemoryOrder order = MemoryOrder.Relaxed);
}
+//@ hidden:
+
__generic<T : IArithmeticAtomicable>
[ForceInline]
T operator +=(__ref Atomic<T> v, T value)
diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang
index 0078d39cb..ada908306 100644
--- a/source/slang/glsl.meta.slang
+++ b/source/slang/glsl.meta.slang
@@ -1535,7 +1535,7 @@ public typealias isamplerCube = SamplerCube<int4>;
public typealias samplerCube = SamplerCube<float4>;
__generic<let sampleCount:int=0, let format:int=0>
-public typealias sampler1DShadow = __TextureImpl<
+public typealias sampler1DShadow = _Texture<
float,
__Shape1D,
0, // isArray
@@ -1548,7 +1548,7 @@ public typealias sampler1DShadow = __TextureImpl<
>;
__generic<let sampleCount:int=0, let format:int=0>
-public typealias sampler2DShadow = __TextureImpl<
+public typealias sampler2DShadow = _Texture<
float,
__Shape2D,
0, // isArray
@@ -1561,7 +1561,7 @@ public typealias sampler2DShadow = __TextureImpl<
>;
__generic<let sampleCount:int=0, let format:int=0>
-public typealias samplerCubeShadow = __TextureImpl<
+public typealias samplerCubeShadow = _Texture<
float,
__ShapeCube,
0, // isArray
@@ -1586,7 +1586,7 @@ public typealias isamplerCubeArray = SamplerCubeArray<int4>;
public typealias samplerCubeArray = SamplerCubeArray<float4>;
__generic<let sampleCount:int=0, let format:int=0>
-public typealias sampler1DArrayShadow = __TextureImpl<
+public typealias sampler1DArrayShadow = _Texture<
float,
__Shape1D,
1, // isArray
@@ -1599,7 +1599,7 @@ public typealias sampler1DArrayShadow = __TextureImpl<
>;
__generic<let sampleCount:int=0, let format:int=0>
-public typealias sampler2DArrayShadow = __TextureImpl<
+public typealias sampler2DArrayShadow = _Texture<
float,
__Shape2D,
1, // isArray
@@ -1612,7 +1612,7 @@ public typealias sampler2DArrayShadow = __TextureImpl<
>;
__generic<let sampleCount:int=0, let format:int=0>
-public typealias samplerCubeArrayShadow = __TextureImpl<
+public typealias samplerCubeArrayShadow = _Texture<
float,
__ShapeCube,
1, // isArray
@@ -1633,13 +1633,13 @@ public typealias isampler2DMSArray = Sampler2DMSArray<int4>;
public typealias usampler2DMSArray = Sampler2DMSArray<uint4>;
__generic<T=float4, let sampleCount:int=0, let format:int=0>
-public typealias Sampler2DRect = __TextureImpl<T, __Shape2D, 0, 0, sampleCount, 0, 0, 1, format>;
+public typealias Sampler2DRect = _Texture<T, __Shape2D, 0, 0, sampleCount, 0, 0, 1, format>;
public typealias sampler2DRect = Sampler2DRect<float4>;
public typealias isampler2DRect = Sampler2DRect<int4>;
public typealias usampler2DRect = Sampler2DRect<uint4>;
__generic<let sampleCount:int=0, let format:int=0>
-public typealias sampler2DRectShadow = __TextureImpl<
+public typealias sampler2DRectShadow = _Texture<
float,
__Shape2D,
0, // isArray
@@ -1652,7 +1652,7 @@ public typealias sampler2DRectShadow = __TextureImpl<
>;
__generic<T, let format:int=0>
-public typealias SamplerBuffer = __TextureImpl<
+public typealias SamplerBuffer = _Texture<
T,
__ShapeBuffer,
0, // isArray
@@ -1871,7 +1871,7 @@ public ivec3 textureSize(Sampler2DMSArray<vector<T,N>,sampleCount> sampler)
__generic<T, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>
[ForceInline]
[require(glsl_hlsl_metal_spirv, texture_querylod)]
-public vec2 textureQueryLod(__TextureImpl<
+public vec2 textureQueryLod(_Texture<
T,
__Shape1D,
isArray,
@@ -1904,7 +1904,7 @@ public vec2 textureQueryLod(__TextureImpl<
__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>
[ForceInline]
[require(glsl_hlsl_metal_spirv, texture_querylod)]
-public vec2 textureQueryLod(__TextureImpl<
+public vec2 textureQueryLod(_Texture<
T,
Shape,
isArray,
@@ -2130,7 +2130,7 @@ public vector<T,4> texture(Sampler1D<vector<T,N>> sampler, float p, constexpr fl
__generic<T:__BuiltinArithmeticType, let N:int, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(cpp_glsl_hlsl_spirv, texture_sm_4_0_fragment)]
-public vector<T,4> texture(__TextureImpl<
+public vector<T,4> texture(_Texture<
vector<T,N>,
Shape,
isArray,
@@ -2148,7 +2148,7 @@ public vector<T,4> texture(__TextureImpl<
__generic<T:__BuiltinArithmeticType, let N:int, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(cpp_glsl_hlsl_spirv, texture_sm_4_0_fragment)]
-public vector<T,4> texture(__TextureImpl<
+public vector<T,4> texture(_Texture<
vector<T,N>,
Shape,
isArray,
@@ -2566,7 +2566,7 @@ public vector<T,4> textureLod(Sampler1D<vector<T,N>> sampler, float p, float lod
__generic<T:__BuiltinArithmeticType, let N:int, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(cpp_cuda_glsl_hlsl_spirv, texture_sm_4_0_fragment)]
-public vector<T,4> textureLod(__TextureImpl<
+public vector<T,4> textureLod(_Texture<
vector<T,N>,
Shape,
isArray,
@@ -2814,7 +2814,7 @@ public vector<T,4> texelFetch(Sampler1D<vector<T,N>> sampler, int p, int lod)
__generic<T:__BuiltinArithmeticType, let N:int, Shape:__ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(cpp_glsl_hlsl_spirv, texture_sm_4_1_samplerless)]
-public vector<T,4> texelFetch(__TextureImpl<
+public vector<T,4> texelFetch(_Texture<
vector<T,N>,
Shape,
isArray,
@@ -2848,7 +2848,7 @@ public vector<T,4> texelFetch(SamplerBuffer<vector<T,N>,format> sampler, int p)
__generic<T:__BuiltinArithmeticType, let N:int, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(cpp_glsl_hlsl_spirv, texture_sm_4_1_samplerless)]
-public vector<T,4> texelFetch(__TextureImpl<
+public vector<T,4> texelFetch(_Texture<
vector<T,N>,
__Shape2D,
isArray,
@@ -2884,7 +2884,7 @@ public vector<T,4> texelFetchOffset(Sampler1D<vector<T,N>> sampler, int p, int l
__generic<T:__BuiltinArithmeticType, let N:int, Shape:__ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(cpp_glsl_hlsl_spirv, texture_sm_4_1_samplerless)]
-public vector<T,4> texelFetchOffset(__TextureImpl<
+public vector<T,4> texelFetchOffset(_Texture<
vector<T,N>,
Shape,
isArray,
@@ -3196,7 +3196,7 @@ public vector<T,4> textureLodOffset(Sampler1D<vector<T,N>> sampler, float p, flo
__generic<T:__BuiltinArithmeticType, let N:int, Shape:__ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(cpp_glsl_hlsl_spirv, texture_sm_4_0)]
-public vector<T,4> textureLodOffset(__TextureImpl<
+public vector<T,4> textureLodOffset(_Texture<
vector<T,N>,
Shape,
isArray,
@@ -3551,7 +3551,7 @@ public vector<T,4> textureGrad(Sampler1D<vector<T,N>> sampler, float p, float dP
__generic<T:__BuiltinArithmeticType, let N:int, Shape:__ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(cpp_glsl_hlsl_spirv, texture_sm_4_1)]
-public vector<T,4> textureGrad(__TextureImpl<
+public vector<T,4> textureGrad(_Texture<
vector<T,N>,
Shape,
isArray,
@@ -3666,7 +3666,7 @@ public vector<T,4> textureGradOffset(Sampler1D<vector<T,N>> sampler, float p, fl
__generic<T:__BuiltinArithmeticType, let N:int, Shape:__ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[require(cpp_glsl_hlsl_spirv, texture_sm_4_1)]
[ForceInline]
-public vector<T,4> textureGradOffset(__TextureImpl<
+public vector<T,4> textureGradOffset(_Texture<
vector<T,N>,
Shape,
isArray,
@@ -4024,7 +4024,7 @@ public float textureProjGradOffset(sampler2DShadow sampler, vec4 p, vec2 dPdx, v
__generic<T:__BuiltinArithmeticType, let N:int, Shape:__ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(glsl_hlsl_spirv, texture_gather)]
-public vector<T,4> textureGather(__TextureImpl<
+public vector<T,4> textureGather(_Texture<
vector<T,N>,
Shape,
isArray,
@@ -4048,7 +4048,7 @@ public vector<T,4> textureGather(__TextureImpl<
__generic<Shape:__ITextureShape, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(glsl_hlsl_spirv, texture_gather)]
-public vec4 textureGather(__TextureImpl<
+public vec4 textureGather(_Texture<
float,
Shape,
isArray,
@@ -4070,7 +4070,7 @@ public vec4 textureGather(__TextureImpl<
__generic<T:__BuiltinArithmeticType, let N:int, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(glsl_hlsl_spirv, texture_gather)]
-public vector<T,4> textureGatherOffset(__TextureImpl<
+public vector<T,4> textureGatherOffset(_Texture<
vector<T,N>,
__Shape2D,
isArray,
@@ -4094,7 +4094,7 @@ public vector<T,4> textureGatherOffset(__TextureImpl<
__generic<let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(glsl_hlsl_spirv, texture_gather)]
-public vec4 textureGatherOffset(__TextureImpl<
+public vec4 textureGatherOffset(_Texture<
float,
__Shape2D,
isArray,
@@ -4116,7 +4116,7 @@ public vec4 textureGatherOffset(__TextureImpl<
__generic<T:__BuiltinArithmeticType, let N:int, let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(glsl_hlsl_spirv, texture_gather)]
-public vector<T,4> textureGatherOffsets(__TextureImpl<
+public vector<T,4> textureGatherOffsets(_Texture<
vector<T,N>,
__Shape2D,
isArray,
@@ -4140,7 +4140,7 @@ public vector<T,4> textureGatherOffsets(__TextureImpl<
__generic<let isArray:int, let sampleCount:int, let format:int>
[ForceInline]
[require(glsl_hlsl_spirv, texture_gather)]
-public vec4 textureGatherOffsets(__TextureImpl<
+public vec4 textureGatherOffsets(_Texture<
float,
__Shape2D,
isArray,
@@ -4574,7 +4574,7 @@ ${{{{
}}}}
__generic<let format:int=0>
- public typealias $(fullTypeName) = __TextureImpl<
+ public typealias $(fullTypeName) = _Texture<
$(targetType.type),
$(targetShape.shape),
$(targetShape.isArray), // isArray
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index b0553aa19..ed1c9fcb6 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -1,35 +1,42 @@
// Slang HLSL compatibility library
+//@hidden:
typedef uint UINT;
__intrinsic_op($(kIROp_RequireGLSLExtension))
void __requireGLSLExtension(String extensionName);
+//@public:
[sealed]
interface IBufferDataLayout
{
}
+/// @category misc_types
__intrinsic_type($(kIROp_DefaultBufferLayoutType))
struct DefaultDataLayout : IBufferDataLayout
{};
+/// @category misc_types
__intrinsic_type($(kIROp_Std140BufferLayoutType))
[require(spirv)]
[require(glsl)]
struct Std140DataLayout : IBufferDataLayout
{};
+/// @category misc_types
__intrinsic_type($(kIROp_Std430BufferLayoutType))
[require(spirv)]
[require(glsl)]
struct Std430DataLayout : IBufferDataLayout
{};
+/// @category misc_types
__intrinsic_type($(kIROp_ScalarBufferLayoutType))
struct ScalarDataLayout : IBufferDataLayout
{};
+//@hidden:
__generic<T, L : IBufferDataLayout = DefaultDataLayout>
__intrinsic_type($(kIROp_GLSLShaderStorageBufferType))
__magic_type(GLSLShaderStorageBufferType)
@@ -57,6 +64,26 @@ __intrinsic_op($(kIROp_StructuredBufferGetDimensions))
[require(cpp_cuda_glsl_hlsl_metal_spirv, structuredbuffer_rw)]
uint2 __structuredBufferGetDimensions<T,L:IBufferDataLayout>(RasterizerOrderedStructuredBuffer<T,L> buffer);
+//@public:
+/**
+Represents an opaque handle to an append structured buffer allocated in global memory.
+A structured buffer can be viewed as an array of the specified element type.
+An append structure buffer internally maintains an atomic counter to keep track of the number of elements in the buffer,
+and provide an atomic operation to append a new element to the buffer.
+ @param T The element type of the buffer.
+ @param L The memory layout of the buffer.
+ @remarks
+This type is supported natively when targeting HLSL.
+When generating code for other targets, this type is translated into a pair or an ordinary `RWStructuredBuffer` and
+a separate `RWStructuredBuffer` that holds the atomic counter.
+The `L` generic parameter is used to specify the memory layout of the buffer when
+generating SPIRV.
+`L` must be one of `DefaultDataLayout`, `Std140DataLayout`, `Std430DataLayout` or `ScalarDataLayout`.
+The default value is `DefaultDataLayout`.
+When generating code for other targets, this parameter is ignored and has no effect on the generated code.
+ @see `RWStructuredBuffer`, `ConsumeStructuredBuffer`, `RasterizerOrderedStructuredBuffer`.
+ @category buffer_types
+*/
__generic<T, L:IBufferDataLayout=DefaultDataLayout>
__magic_type(HLSLAppendStructuredBufferType)
__intrinsic_type($(kIROp_HLSLAppendStructuredBufferType))
@@ -77,6 +104,7 @@ struct AppendStructuredBuffer
}
};
+/// @category buffer_types
__magic_type(HLSLByteAddressBufferType)
__intrinsic_type($(kIROp_HLSLByteAddressBufferType))
[require(cpp_cuda_glsl_hlsl_metal_spirv, byteaddressbuffer)]
@@ -309,6 +337,8 @@ interface __ITextureShape
interface __ITextureShape1D2D3D : __ITextureShape
{
}
+
+/// @category misc_types Miscelaneous types
__magic_type(TextureShape1DType)
__intrinsic_type($(kIROp_TextureShape1DType))
struct __Shape1D : __ITextureShape1D2D3D
@@ -317,6 +347,7 @@ struct __Shape1D : __ITextureShape1D2D3D
static const int dimensions = 1;
static const int planeDimensions = 1;
}
+/// @category misc_types
__magic_type(TextureShape2DType)
__intrinsic_type($(kIROp_TextureShape2DType))
struct __Shape2D : __ITextureShape1D2D3D
@@ -325,6 +356,7 @@ struct __Shape2D : __ITextureShape1D2D3D
static const int dimensions = 2;
static const int planeDimensions = 2;
}
+/// @category misc_types
__magic_type(TextureShape3DType)
__intrinsic_type($(kIROp_TextureShape3DType))
struct __Shape3D : __ITextureShape1D2D3D
@@ -333,6 +365,7 @@ struct __Shape3D : __ITextureShape1D2D3D
static const int dimensions = 3;
static const int planeDimensions = 3;
}
+/// @category misc_types
__magic_type(TextureShapeCubeType)
__intrinsic_type($(kIROp_TextureShapeCubeType))
struct __ShapeCube : __ITextureShape
@@ -341,6 +374,7 @@ struct __ShapeCube : __ITextureShape
static const int dimensions = 3;
static const int planeDimensions = 2;
}
+/// @category misc_types
__magic_type(TextureShapeBufferType)
__intrinsic_type($(kIROp_TextureShapeBufferType))
struct __ShapeBuffer : __ITextureShape
@@ -349,6 +383,8 @@ struct __ShapeBuffer : __ITextureShape
static const int dimensions = 1;
static const int planeDimensions = 1;
}
+
+//@hidden:
__intrinsic_op(vectorReshape)
vector<T,N> __vectorReshape<let N : int, T, let M : int>(vector<T,M> vin);
@@ -356,14 +392,90 @@ __intrinsic_op(makeVector)
__generic<T, let N:int>
vector<T,N+1> __makeVector(vector<T,N> vec, T scalar);
-
+//@public:
+/// A parameterized type that represents all flavors of texture types supported by the Slang language.
+/// Please note that this type is not intended to be used directly in user code, and not all combinations
+/// of the generic arguments are valid.
+/// Instead, use the specific texture types such as `Texture1D`, `Texture2DArray` and `Sampler2D` etc.
+/// This documentation is provided for reference purposes only.
+/// @param T The element type of the texture. Must be a scalar or vector type.
+/// @param Shape The shape of the texture. Must be one of `__Shape1D`, `__Shape2D`, `__Shape3D`, `__ShapeCube` or `__ShapeBuffer`.
+/// @param isArray Indicates whether the texture is an array texture.
+/// @param isMS Indicates whether the texture is a multisampled texture.
+/// @param sampleCount The number of samples of a multisampled texture.
+/// @param access The access mode of the texture. 0 for read-only, 1 for read-write, 2 for rasterizer-ordered, 3 for feedback.
+/// @param isShadow Indicates whether the texture is a shadow texture (for combined texture-sampler only).
+/// @param isCombined Indicates whether the texture is a combined texture-sampler.
+/// @param format The storage format of the texture. Users should specify the format using an `[format("...")]` attribute instead.
+/// @see `Texture1D`, `Texture2D`, `Texture3D`, `TextureCube`, `Texture1DArray`,
+/// `Texture2DArray`, `TextureCubeArray`, `Sampler1D`, `Sampler2D`, `Sampler3D`, `SamplerCube`, `Sampler1DArray`, `Sampler2DArray`, `SamplerCubeArray`,
+/// `Texture2DMS`, `Texture2DMSArray`, `RWTexture1D`, `RWTexture2D`, `RWTexture3D`, `RWTexture1DArray`, `RWTexture2DArray`,
+/// `RWTexture2DMS`, `RWTexture2DMSArray`, `Buffer`, `RWBuffer`, `FeedbackTexture2D`, `FeedbackTexture2DArray`.
+/// @remarks
+/// HLSL texture types are implemented as typealiases to the builtin `_Texture` type. Users
+/// are advised to use the HLSL-specific texture types instead of `_Texture` directly.
+///
+/// For read-write textures, Slang will automatically infer `format` from `T`.
+/// To explicitly specify texel storage formats for read-write textures,
+/// use the `[format("formatString")]` attribute on the texture parameter declaration.
+/// Allowed `formatString` values are:
+///
+/// |id | Format string | Meaning |
+/// |:--|:---------------------|:------------------|
+/// |1 |`"rgba32f"` | 4 channel 32-bit floating point texture |
+/// |2 |`"rgba16f"` | 4 channel 16-bit floating point texture |
+/// |3 |`"rg32f"` | 2 channel 32-bit floating point texture |
+/// |4 |`"rg16f"` | 2 channel 16-bit floating point texture |
+/// |5 |`"r11f_g11f_b10f"` | 3 channel 11/11/10-bit floating point texture |
+/// |6 |`"r32f"` | 1 channel 32-bit floating point texture |
+/// |7 |`"r16f"` | 1 channel 16-bit floating point texture |
+/// |8 |`"rgba16"` | 4 channel 16-bit normalized unsigned integer texture |
+/// |9 |`"rgb10_a2"` | 4 channel 10/10/10/2-bit signed integer texture |
+/// |10 |`"rgba8"` | 4 channel 8-bit normalized unsigned integer texture |
+/// |11 |`"rg16"` | 2 channel 16-bit normalized unsigned integer texture |
+/// |12 |`"rg8"` | 2 channel 8-bit normalized unsigned integer texture |
+/// |13 |`"r16"` | 1 channel 16-bit normalized unsigned integer texture |
+/// |14 |`"r8"` | 1 channel 8-bit normalized unsigned integer texture |
+/// |15 |`"rgba16_snorm"` | 4 channel 16-bit normalized signed integer texture |
+/// |16 |`"rgba8_snorm"` | 4 channel 8-bit normalized signed integer texture |
+/// |17 |`"rg16_snorm"` | 2 channel 16-bit normalized signed integer texture |
+/// |18 |`"rg8_snorm"` | 2 channel 8-bit normalized signed integer texture |
+/// |19 |`"r16_snorm"` | 1 channel 16-bit normalized signed integer texture |
+/// |20 |`"r8_snorm"` | 1 channel 8-bit normalized signed integer texture |
+/// |21 |`"rgba32i"` | 4 channel 32-bit signed integer texture |
+/// |22 |`"rgba16i"` | 4 channel 16-bit signed integer texture |
+/// |23 |`"rgba8i"` | 4 channel 8-bit signed integer texture |
+/// |24 |`"rg32i"` | 2 channel 32-bit signed integer texture |
+/// |25 |`"rg16i"` | 2 channel 16-bit signed integer texture |
+/// |26 |`"rg8i"` | 2 channel 8-bit signed integer texture |
+/// |27 |`"r32i"` | 1 channel 32-bit signed integer texture |
+/// |28 |`"r16i"` | 1 channel 16-bit signed integer texture |
+/// |29 |`"r8i"` | 1 channel 8-bit signed integer texture |
+/// |30 |`"rgba32ui"` | 4 channel 32-bit unsigned integer texture |
+/// |31 |`"rgba16ui"` | 4 channel 16-bit unsigned integer texture |
+/// |32 |`"rgb10_a2ui"` | 4 channel 10/10/10/2-bit unsigned integer texture |
+/// |33 |`"rgba8ui"` | 4 channel 8-bit unsigned integer texture |
+/// |34 |`"rg32ui"` | 2 channel 32-bit unsigned integer texture |
+/// |35 |`"rg16ui"` | 2 channel 16-bit unsigned integer texture |
+/// |36 |`"rg8ui"` | 2 channel 8-bit unsigned integer texture |
+/// |37 |`"r32ui"` | 1 channel 32-bit unsigned integer texture |
+/// |38 |`"r16ui"` | 1 channel 16-bit unsigned integer texture |
+/// |39 |`"r8ui"` | 1 channel 8-bit unsigned integer texture |
+/// |40 |`"r64ui"` | 1 channel 64-bit unsigned integer texture |
+/// |41 |`"r64i"` | 1 channel 64-bit signed integer texture |
+///
+/// When targeting Vulkan, a combined-texture-sampler type (`isCombined==1`) translates to a `OpTypeSampledImage` type in SPIR-V.
+/// For other targets, the combined-texture-sampler type is translated to a pair of a `Texture` and `SamplerState`.
+/// `isShadow` is only applicable to combined-texture-sampler types and must be `0` for non-combined texture types.
+/// @internal
+/// @category texture_types Texture types
__magic_type(TextureType)
__intrinsic_type($(kIROp_TextureType))
-struct __TextureImpl<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>
+struct _Texture<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>
{
}
-
+//@hidden:
// Combined texture sampler specific functions
[require(glsl, texture_sm_4_1)]
@@ -542,15 +654,19 @@ float __glsl_texture_offset_level_zero_1d_shadow<TTexture, TCoord, TOffset>(TTex
}
}
+//@public:
+
__generic<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let isShadow:int, let format:int>
-extension __TextureImpl<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format>
+extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format>
{
+ //@hidden:
static const int access = 0;
+ //@public:
typealias TextureCoord = vector<float, Shape.dimensions>;
__intrinsic_op($(kIROp_CombinedTextureSamplerGetTexture))
- __TextureImpl<T, Shape, isArray, isMS, sampleCount, 0, isShadow, 0, format> __getTexture();
+ _Texture<T, Shape, isArray, isMS, sampleCount, 0, isShadow, 0, format> __getTexture();
__intrinsic_op($(kIROp_CombinedTextureSamplerGetSampler))
SamplerState __getSampler();
@@ -608,6 +724,26 @@ extension __TextureImpl<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format>
}
}
+ /// Samples the texture at the given location.
+ ///
+ ///@param s The `SamplerState` to use for the sampling operation. This parameter is omitted when `this` is a combined texture sampler type (`isCombined == 0`).
+ ///@param location The location to sample the texture at.
+ ///@param offset Texel offset to apply.
+ ///@param clamp The max level of detail to use.
+ ///@param[out] status The result status of the operation.
+ /// This parameter is currently only used when targeting HLSL.
+ /// For other targets, the result status is always 0.
+ ///@return The sampled texture value.
+ ///@see `SampleBias`, `SampleLevel`, `SampleGrad`, `SampleCmp`, `SampleCmpLevelZero`.
+ ///@remarks
+ /// The `Sample` function is defined for all read-only texture types, including
+ /// `Texture1D`, `Texture2D`, `Texture3D`, `TextureCube`,
+ /// `Texture1DArray`, `Texture2DArray` and `TextureCubeArray`.
+ ///
+ /// The function is not available for read-write texture types.
+ ///
+ /// For HLSL/D3D targets, the texture element type must be a scalar or vector of float or half types.
+ ///
[__readNone]
[ForceInline]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)]
@@ -1114,8 +1250,9 @@ extension __TextureImpl<T,Shape,isArray,isMS,sampleCount,0,isShadow,1,format>
}
// Non-combined texture types specific functions
+
__generic<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let format:int>
-extension __TextureImpl<T,Shape,isArray,isMS,sampleCount,access,isShadow,0,format>
+extension _Texture<T,Shape,isArray,isMS,sampleCount,access,isShadow,0,format>
{
typealias TextureCoord = vector<float, Shape.dimensions>;
@@ -1165,7 +1302,7 @@ extension __TextureImpl<T,Shape,isArray,isMS,sampleCount,access,isShadow,0,forma
}
__generic<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let isShadow:int, let format:int>
-extension __TextureImpl<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format>
+extension _Texture<T,Shape,isArray,isMS,sampleCount,0,isShadow,0,format>
{
[__readNone]
[ForceInline]
@@ -2166,7 +2303,7 @@ for (int isMS = 0; isMS <= 1; isMS++) {
}}}}
__generic<T, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>
-extension __TextureImpl<T,$(shapeTypeName),$(isArray),$(isMS),sampleCount,access,isShadow,isCombined,format>
+extension _Texture<T,$(shapeTypeName),$(isArray),$(isMS),sampleCount,access,isShadow,isCombined,format>
{
${{{{
textureTypeInfo.writeGetDimensionFunctions();
@@ -2179,7 +2316,7 @@ ${{{{
// Texture.GetSamplePosition(int s);
__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>
-extension __TextureImpl<T,Shape,isArray,1,sampleCount,access,isShadow,isCombined,format>
+extension _Texture<T,Shape,isArray,1,sampleCount,access,isShadow,isCombined,format>
{
[require(cpp_cuda_glsl_hlsl_spirv, texture_sm_4_1_vertex_fragment_geometry)]
float2 GetSamplePosition(int s);
@@ -2194,7 +2331,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_metal_spirv_wgsl, texture_gather)]
vector<TElement,4> __texture_gather(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
SamplerState s,
vector<float, Shape.dimensions+isArray> location,
int component)
@@ -2263,7 +2400,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_spirv, texture_gather)]
vector<TElement,4> __texture_gather(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
vector<float, Shape.dimensions+isArray> location,
int component)
{
@@ -2282,7 +2419,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_metal_spirv_wgsl, texture_gather)]
vector<TElement,4> __texture_gather_offset(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
SamplerState s,
constexpr vector<float, Shape.dimensions+isArray> location,
constexpr vector<int, Shape.planeDimensions> offset,
@@ -2343,7 +2480,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_spirv, texture_gather)]
vector<TElement,4> __texture_gather_offset(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
vector<float, Shape.dimensions+isArray> location,
constexpr vector<int, Shape.planeDimensions> offset,
int component)
@@ -2363,7 +2500,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_spirv, texture_gather)]
vector<TElement,4> __texture_gather_offsets(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
SamplerState s,
vector<float, Shape.dimensions+isArray> location,
constexpr vector<int, Shape.planeDimensions> offset1,
@@ -2390,7 +2527,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_spirv, texture_gather)]
vector<TElement,4> __texture_gather_offsets(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
vector<float, Shape.dimensions+isArray> location,
constexpr vector<int, Shape.planeDimensions> offset1,
constexpr vector<int, Shape.planeDimensions> offset2,
@@ -2415,7 +2552,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_metal_spirv_wgsl, texture_gather)]
vector<TElement,4> __texture_gatherCmp(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
SamplerComparisonState s,
vector<float, Shape.dimensions+isArray> location,
TElement compareValue)
@@ -2465,7 +2602,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_spirv, texture_gather)]
vector<TElement,4> __texture_gatherCmp(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
vector<float, Shape.dimensions+isArray> location,
TElement compareValue)
{
@@ -2484,7 +2621,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_metal_spirv_wgsl, texture_gather)]
vector<TElement,4> __texture_gatherCmp_offset(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
SamplerComparisonState s,
vector<float, Shape.dimensions+isArray> location,
TElement compareValue,
@@ -2531,7 +2668,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_spirv, texture_gather)]
vector<TElement,4> __texture_gatherCmp_offset(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
vector<float, Shape.dimensions+isArray> location,
TElement compareValue,
constexpr vector<int, Shape.planeDimensions> offset)
@@ -2551,7 +2688,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_spirv, texture_gather)]
vector<TElement,4> __texture_gatherCmp_offsets(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 0, format> texture,
SamplerComparisonState s,
vector<float, Shape.dimensions+isArray> location,
TElement compareValue,
@@ -2578,7 +2715,7 @@ __generic<TElement, T, Shape: __ITextureShape, let isArray:int, let sampleCount:
[ForceInline]
[require(glsl_spirv, texture_gather)]
vector<TElement,4> __texture_gatherCmp_offsets(
- __TextureImpl<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
+ _Texture<T, Shape, isArray, 0, sampleCount, access, isShadow, 1, format> sampler,
vector<float, Shape.dimensions+isArray> location,
TElement compareValue,
vector<int, Shape.planeDimensions> offset1,
@@ -2608,8 +2745,9 @@ for (int isScalarTexture = 0; isScalarTexture < 2; isScalarTexture++)
}}}}
// Gather for [TextureType = $(extTexType), isCombined = $(isCombined)]
+
__generic<T:__BuiltinArithmeticType $(extSizeParam), Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>
-extension __TextureImpl<$(extTexType),Shape,isArray,0,sampleCount,0,isShadow,$(isCombined),format>
+extension _Texture<$(extTexType),Shape,isArray,0,sampleCount,0,isShadow,$(isCombined),format>
{
${{{{
for (int isShadow = 0; isShadow < 2; isShadow++)
@@ -2768,11 +2906,12 @@ ${{{{
// Load/Subscript for readonly, no MS textures
__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let isCombined:int, let format:int>
-extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow,isCombined,format>
+extension _Texture<T,Shape,isArray,0,sampleCount,0,isShadow,isCombined,format>
{
+//@hidden:
static const int isMS = 0;
static const int access = $(kStdlibResourceAccessReadOnly);
-
+//@public:
__glsl_extension(GL_EXT_samplerless_texture_functions)
[__readNone]
[require(glsl, texture_sm_4_1_samplerless)]
@@ -3001,11 +3140,12 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow,isCombined,form
// Texture Load/Subscript for readonly, MS textures
__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let isCombined:int, let format:int>
-extension __TextureImpl<T,Shape,isArray,1,sampleCount,0,isShadow,isCombined,format>
+extension _Texture<T,Shape,isArray,1,sampleCount,0,isShadow,isCombined,format>
{
+//@hidden:
static const int access = $(kStdlibResourceAccessReadOnly);
static const int isMS = 1;
-
+//@public:
__glsl_extension(GL_EXT_samplerless_texture_functions)
[__readNone]
[ForceInline]
@@ -3183,8 +3323,9 @@ ${{{{
const char* glslIntrinsicMS = "$cimageLoad($0, $1, $2)$z";
const char* glslIntrinsicMSOffset = "$cimageLoad($0, ($1)+($3), $2)$z";
}}}}
+
__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>
-extension __TextureImpl<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,format>
+extension _Texture<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,format>
{
[__readNone]
[ForceInline]
@@ -3527,9 +3668,11 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,form
${{{{
if (access == kStdlibResourceAccessReadWrite) {
}}}}
+
// RW MS textures.
+
__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>
-extension __TextureImpl<T,Shape,isArray,1,sampleCount,$(access),isShadow, 0,format>
+extension _Texture<T,Shape,isArray,1,sampleCount,$(access),isShadow, 0,format>
{
[__readNone]
[ForceInline]
@@ -3683,7 +3826,7 @@ ${{{{
// Definitions to support the legacy texture .mips[][] operator.
struct __TextureMip<T, Shape : __ITextureShape, let isArray : int, let isCombined : int, let format : int>
{
- __TextureImpl<T, Shape, isArray, 0 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format> tex;
+ _Texture<T, Shape, isArray, 0 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format> tex;
int mip;
__subscript(vector<int, isArray + Shape.dimensions> pos)->T
{
@@ -3694,7 +3837,7 @@ struct __TextureMip<T, Shape : __ITextureShape, let isArray : int, let isCombine
struct __TextureMips<T, Shape : __ITextureShape, let isArray : int, let isCombined : int, let format : int>
{
- __TextureImpl<T, Shape, isArray, 0 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format> tex;
+ _Texture<T, Shape, isArray, 0 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format> tex;
__subscript(int mip)->__TextureMip<T, Shape, isArray, isCombined, format>
{
[__unsafeForceInlineEarly]
@@ -3702,8 +3845,9 @@ struct __TextureMips<T, Shape : __ITextureShape, let isArray : int, let isCombin
}
}
+//@hidden:
__generic<T, Shape : __ITextureShape, let isArray : int, let isCombined : int, let format : int>
-extension __TextureImpl<T, Shape, isArray, 0 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format>
+extension _Texture<T, Shape, isArray, 0 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format>
{
property __TextureMips<T, Shape, isArray, isCombined, format> mips
{
@@ -3715,7 +3859,7 @@ extension __TextureImpl<T, Shape, isArray, 0 /*isMS*/, 0 /*sampleCount*/, 0 /*ac
// Definitions to support the .sample[][] operator.
struct __TextureSample<T, Shape : __ITextureShape, let isArray : int, let isCombined : int, let format : int>
{
- __TextureImpl<T, Shape, isArray, 1 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format> tex;
+ _Texture<T, Shape, isArray, 1 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format> tex;
int sample;
__subscript(vector<int, isArray + Shape.dimensions> pos)->T
{
@@ -3726,7 +3870,7 @@ struct __TextureSample<T, Shape : __ITextureShape, let isArray : int, let isComb
struct __TextureSampleMS<T, Shape : __ITextureShape, let isArray : int, let isCombined : int, let format : int>
{
- __TextureImpl<T, Shape, isArray, 1 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format> tex;
+ _Texture<T, Shape, isArray, 1 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format> tex;
__subscript(int sample)->__TextureSample<T, Shape, isArray, isCombined, format>
{
[__unsafeForceInlineEarly]
@@ -3735,7 +3879,7 @@ struct __TextureSampleMS<T, Shape : __ITextureShape, let isArray : int, let isCo
}
__generic<T, Shape : __ITextureShape, let isArray : int, let isCombined : int, let format : int>
-extension __TextureImpl<T, Shape, isArray, 1 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format>
+extension _Texture<T, Shape, isArray, 1 /*isMS*/, 0 /*sampleCount*/, 0 /*access*/, 0 /*isShadow*/, isCombined, format>
{
property __TextureSampleMS<T, Shape, isArray, isCombined, format> sample
{
@@ -3744,6 +3888,8 @@ extension __TextureImpl<T, Shape, isArray, 1 /*isMS*/, 0 /*sampleCount*/, 0 /*ac
}
}
+//@public:
+
// Texture type aliases.
// T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int
${{{{
@@ -3782,7 +3928,8 @@ ${{{{
continue;
const char* textureTypeName = isCombined ? "Sampler" : "Texture";
}}}}
-typealias $(accessPrefix[access])$(textureTypeName)$(shapeTypeNames[shape])$(msPostFix[isMS])$(arrayPostFix[isArray])<T=float4, let sampleCount:int=0, let format:int=0> = __TextureImpl<T, __Shape$(shapeTypeNames[shape]), $(isArray), $(isMS), sampleCount, $(access), 0, $(isCombined), format>;
+/// @category texture_types
+typealias $(accessPrefix[access])$(textureTypeName)$(shapeTypeNames[shape])$(msPostFix[isMS])$(arrayPostFix[isArray])<T=float4, let sampleCount:int=0, let format:int=0> = _Texture<T, __Shape$(shapeTypeNames[shape]), $(isArray), $(isMS), sampleCount, $(access), 0, $(isCombined), format>;
${{{{
}
}}}}
@@ -4293,6 +4440,20 @@ __intrinsic_op($(kIROp_ByteAddressBufferStore))
[require(cpp_cuda_glsl_hlsl_metal_spirv, byteaddressbuffer_rw)]
void __byteAddressBufferStore<T>(RasterizerOrderedByteAddressBuffer buffer, int offset, int alignment, T value);
+/**
+Represents an opaque handle to a read-only structured buffer allocated in global memory.
+A structured buffer can be viewed as an array of the specified element type.
+@param T The element type of the buffer.
+@param L The memory layout of the buffer.
+@remarks
+The `L` generic parameter is used to specify the memory layout of the buffer when
+generating SPIRV.
+`L` must be one of `DefaultDataLayout`, `Std140DataLayout`, `Std430DataLayout` or `ScalarDataLayout`.
+The default value is `DefaultDataLayout`.
+When generating code for other targets, this parameter is ignored and has no effect on the generated code.
+@see `RWStructuredBuffer`, `AppendStructuredBuffer`, `ConsumeStructuredBuffer`, `RasterizerOrderedStructuredBuffer`.
+@category buffer_types Buffer types
+**/
__generic<T, L:IBufferDataLayout=DefaultDataLayout>
__magic_type(HLSLStructuredBufferType)
__intrinsic_type($(kIROp_HLSLStructuredBufferType))
@@ -4328,6 +4489,25 @@ struct StructuredBuffer
};
};
+/**
+Represents an opaque handle to a consume structured buffer allocated in global memory.
+A structured buffer can be viewed as an array of the specified element type.
+An append structure buffer internally maintains an atomic counter to keep track of the number of elements in the buffer,
+and provide an atomic operation to append a new element to the buffer.
+@param T The element type of the buffer.
+@param L The memory layout of the buffer.
+@remarks
+This type is supported natively when targeting HLSL.
+When generating code for other targets, this type is translated into a pair or an ordinary `StructuredBuffer` and
+a separate `RWStructuredBuffer` that holds the atomic counter.
+The `L` generic parameter is used to specify the memory layout of the buffer when
+generating SPIRV.
+`L` must be one of `DefaultDataLayout`, `Std140DataLayout`, `Std430DataLayout` or `ScalarDataLayout`.
+The default value is `DefaultDataLayout`.
+When generating code for other targets, this parameter is ignored and has no effect on the generated code.
+@see `StructuredBuffer`, `AppendStructuredBuffer`, `RWStructuredBuffer`, `RasterizerOrderedStructuredBuffer`.
+@category buffer_types
+*/
__generic<T, L:IBufferDataLayout=DefaultDataLayout>
__magic_type(HLSLConsumeStructuredBufferType)
__intrinsic_type($(kIROp_HLSLConsumeStructuredBufferType))
@@ -4351,6 +4531,7 @@ struct ConsumeStructuredBuffer
__intrinsic_op($(kIROp_GetElement))
T __getElement<T, U, I>(U collection, I index);
+/// @category stage_io Stage IO types
__generic<T, let N : int>
[require(glsl_hlsl_spirv, hull)]
__magic_type(HLSLInputPatchType)
@@ -4374,6 +4555,7 @@ struct InputPatch
}
};
+/// @category stage_io
__generic<T, let N : int>
[require(glsl_hlsl_spirv, domain_hull)]
__magic_type(HLSLOutputPatchType)
@@ -4409,6 +4591,7 @@ static const struct {
for(auto item : kMutableByteAddressBufferCases) {
}}}}
+/// @category buffer_types
__magic_type(HLSL$(item.name)Type)
__intrinsic_type($(item.op))
struct $(item.name)
@@ -5740,6 +5923,20 @@ __generic<T, L:IBufferDataLayout=DefaultDataLayout>
__magic_type(HLSL$(item.name)Type)
__intrinsic_type($(item.op))
[require(cpp_cuda_glsl_hlsl_metal_spirv, structuredbuffer_rw)]
+/**
+Represents an opaque handle to a mutable structured buffer allocated in global memory.
+A structured buffer can be viewed as an array of the specified element type.
+ @param T The element type of the buffer.
+ @param L The memory layout of the buffer.
+ @remarks
+The `L` generic parameter is used to specify the memory layout of the buffer when
+generating SPIRV.
+`L` must be one of `DefaultDataLayout`, `Std140DataLayout`, `Std430DataLayout` or `ScalarDataLayout`.
+The default value is `DefaultDataLayout`.
+When generating code for other targets, this parameter is ignored and has no effect on the generated code.
+ @see `StructuredBuffer`, `AppendStructuredBuffer`, `ConsumeStructuredBuffer`
+ @category buffer_types
+**/
struct $(item.name)
{
uint DecrementCounter();
@@ -5788,6 +5985,7 @@ ${{{{
}
}}}}
+/// @category stage_io
__generic<T>
[require(glsl_hlsl_spirv, geometry)]
__magic_type(HLSLPointStreamType)
@@ -5817,6 +6015,7 @@ struct PointStream
}
};
+/// @category stage_io
__generic<T>
[require(glsl_hlsl_spirv, geometry)]
__magic_type(HLSLLineStreamType)
@@ -5846,6 +6045,7 @@ struct LineStream
}
};
+/// @category stage_io
__generic<T>
[require(glsl_hlsl_spirv, geometry)]
__magic_type(HLSLTriangleStreamType)
@@ -5893,11 +6093,13 @@ struct TriangleStream
#define MATRIX_MAP_TRINARY(TYPE, ROWS, COLS, FUNC, A, B, C) \
matrix<TYPE,ROWS,COLS> result; for(int i = 0; i < ROWS; ++i) { result[i] = FUNC(A[i], B[i], C[i]); } return result
-// Try to terminate the current draw or dispatch call (HLSL SM 4.0)
-void abort();
+//@public:
-// Absolute value (HLSL SM 1.0)
+/// Try to terminate the current draw or dispatch call (HLSL SM 4.0)
+void abort();
+/// Absolute value (HLSL SM 1.0)
+/// @category math
__generic<T : __BuiltinIntegerType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -6003,6 +6205,8 @@ matrix<T,N,M> abs(matrix<T,N,M> x)
}
}
+/// Absolute value (HLSL SM 1.0)
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -6032,8 +6236,8 @@ vector<T, N> fabs(vector<T, N> x)
}
-// Inverse cosine (HLSL SM 1.0)
-
+/// Inverse cosine (HLSL SM 1.0)
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -6085,8 +6289,8 @@ matrix<T, N, M> acos(matrix<T, N, M> x)
}
}
-// Inverse hyperbolic cosine
-
+/// Inverse hyperbolic cosine
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -6228,7 +6432,8 @@ bool all(matrix<T,N,M> x)
}
}
-// Barrier for writes to all memory spaces (HLSL SM 5.0)
+/// Barrier for writes to all memory spaces (HLSL SM 5.0)
+/// @category barrier Memory and control barriers
__glsl_extension(GL_KHR_memory_scope_semantics)
[require(cuda_glsl_hlsl_metal_spirv_wgsl, memorybarrier)]
void AllMemoryBarrier()
@@ -6247,7 +6452,8 @@ void AllMemoryBarrier()
}
}
-// Thread-group sync and barrier for writes to all memory spaces (HLSL SM 5.0)
+/// Thread-group sync and barrier for writes to all memory spaces (HLSL SM 5.0)
+/// @category barrier
__glsl_extension(GL_KHR_memory_scope_semantics)
[require(cuda_glsl_hlsl_metal_spirv_wgsl, memorybarrier)]
void AllMemoryBarrierWithGroupSync()
@@ -6372,8 +6578,8 @@ bool any(matrix<T, N, M> x)
}
-// Reinterpret bits as a double (HLSL SM 5.0)
-
+/// Reinterpret bits as a double (HLSL SM 5.0)
+/// @category conversion
__glsl_extension(GL_ARB_gpu_shader5)
[__readNone]
[require(cpp_cuda_glsl_hlsl_spirv, shader5_sm_5_0)]
@@ -6406,8 +6612,8 @@ double2 asdouble(uint2 lowbits, uint2 highbits)
}
}
-// Reinterpret bits as a float (HLSL SM 4.0)
-
+/// Reinterpret bits as a float (HLSL SM 4.0)
+/// @category conversion
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)]
float asfloat(int x)
@@ -6508,7 +6714,6 @@ matrix<float,N,M> asfloat(matrix<uint,N,M> x)
}
}
-// No op
[__unsafeForceInlineEarly]
[__readNone]
float asfloat(float x)
@@ -6526,7 +6731,8 @@ __generic<let N : int, let M : int>
matrix<float,N,M> asfloat(matrix<float,N,M> x)
{ return x; }
-// Inverse sine (HLSL SM 1.0)
+/// Inverse sine (HLSL SM 1.0)
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -6578,8 +6784,8 @@ matrix<T, N, M> asin(matrix<T, N, M> x)
}
}
-// Inverse hyperbolic sine
-
+/// Inverse hyperbolic sine.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -6620,8 +6826,8 @@ vector<T,N> asinh(vector<T,N> x)
}
}
-// Reinterpret bits as an int (HLSL SM 4.0)
-
+/// Reinterpret bits as an int (HLSL SM 4.0)
+/// @category conversion
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_4_0)]
int asint(float x)
@@ -6742,8 +6948,8 @@ __generic<let N : int, let M : int>
matrix<int,N,M> asint(matrix<int,N,M> x)
{ return x; }
-// Reinterpret bits of double as a uint (HLSL SM 5.0)
-
+/// Reinterpret bits of double as a uint (HLSL SM 5.0)
+/// @category conversion
__glsl_extension(GL_ARB_gpu_shader5)
[__readNone]
[require(cpp_cuda_glsl_hlsl_spirv, shader5_sm_4_0)]
@@ -6897,14 +7103,20 @@ matrix<uint,N,M> asuint(matrix<uint,N,M> x)
// Identity cases:
+/// Reinterpret bits as a float16 (HLSL SM 6.2).
+/// @category conversion
[__unsafeForceInlineEarly][__readNone] float16_t asfloat16(float16_t value) { return value; }
[__unsafeForceInlineEarly][__readNone] vector<float16_t,N> asfloat16<let N : int>(vector<float16_t,N> value) { return value; }
[__unsafeForceInlineEarly][__readNone] matrix<float16_t,R,C> asfloat16<let R : int, let C : int>(matrix<float16_t,R,C> value) { return value; }
+/// Reinterpret bits as a int16_t (HLSL SM 6.2).
+/// @category conversion
[__unsafeForceInlineEarly][__readNone] int16_t asint16(int16_t value) { return value; }
[__unsafeForceInlineEarly][__readNone] vector<int16_t,N> asint16<let N : int>(vector<int16_t,N> value) { return value; }
[__unsafeForceInlineEarly][__readNone] matrix<int16_t,R,C> asint16<let R : int, let C : int>(matrix<int16_t,R,C> value) { return value; }
+/// Reinterpret bits as a uint16_t (HLSL SM 6.2).
+/// @category conversion
[__unsafeForceInlineEarly][__readNone] uint16_t asuint16(uint16_t value) { return value; }
[__unsafeForceInlineEarly][__readNone] vector<uint16_t,N> asuint16<let N : int>(vector<uint16_t,N> value) { return value; }
[__unsafeForceInlineEarly][__readNone] matrix<uint16_t,R,C> asuint16<let R : int, let C : int>(matrix<uint16_t,R,C> value) { return value; }
@@ -7081,7 +7293,8 @@ matrix<float16_t,R,C> asfloat16<let R : int, let C : int>(matrix<int16_t,R,C> va
}
}
-// Inverse tangent (HLSL SM 1.0)
+/// Inverse tangent (HLSL SM 1.0).
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -7133,6 +7346,8 @@ matrix<T, N, M> atan(matrix<T, N, M> x)
}
}
+/// Inverse tangent (HLSL SM 1.0).
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -7184,8 +7399,8 @@ matrix<T,N,M> atan2(matrix<T,N,M> y, matrix<T,N,M> x)
}
}
-// Hyperbolic inverse tangent
-
+/// Hyperbolic inverse tangent
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -7226,7 +7441,8 @@ vector<T,N> atanh(vector<T,N> x)
}
}
-// Ceiling (HLSL SM 1.0)
+/// Ceiling (HLSL SM 1.0).
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -7279,7 +7495,7 @@ matrix<T, N, M> ceil(matrix<T, N, M> x)
}
// Copy-sign
-
+/// @category math
__generic<let N: int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv)]
@@ -7292,6 +7508,7 @@ vector<half,N> copysign_half(vector<half,N> x, vector<half,N> y)
return reinterpret<vector<half,N>>(newX);
}
+/// @category math
__generic<let N: int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv)]
@@ -7304,6 +7521,7 @@ vector<float,N> copysign_float(vector<float,N> x, vector<float,N> y)
return reinterpret<vector<float,N>>(newX);
}
+/// @category math
__generic<let N: int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv)]
@@ -7320,6 +7538,7 @@ __generic<T:__BuiltinFloatingPointType, U:__BuiltinFloatingPointType, let N : in
__intrinsic_op($(kIROp_FloatCast))
vector<T,N> __real_cast(vector<U,N> val);
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N: int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv)]
@@ -7371,7 +7590,8 @@ bool CheckAccessFullyMapped(out uint status)
}
}
-// Clamp (HLSL SM 1.0)
+/// Clamp (HLSL SM 1.0).
+/// @category math
__generic<T : __BuiltinIntegerType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -7486,7 +7706,7 @@ matrix<T,N,M> clamp(matrix<T,N,M> x, matrix<T,N,M> minBound, matrix<T,N,M> maxBo
}
}
-// Clip (discard) fragment conditionally
+/// Clip (discard) fragment conditionally
__generic<T : __BuiltinFloatingPointType>
[require(cpp_cuda_glsl_hlsl_spirv, fragment)]
void clip(T x)
@@ -7523,7 +7743,7 @@ void clip(matrix<T,N,M> x)
}
}
-// Cosine
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -7575,7 +7795,8 @@ matrix<T, N, M> cos(matrix<T, N, M> x)
}
}
-// Hyperbolic cosine
+/// Hyperbolic cosine.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -7627,8 +7848,8 @@ matrix<T, N, M> cosh(matrix<T, N, M> x)
}
}
-// Cosine degree
-
+/// Compute the cosine of an angle in degrees.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -7656,7 +7877,8 @@ vector<T,N> cospi(vector<T,N> x)
}
-// Population count
+/// Population count.
+/// @category bitops
[__readNone]
[ForceInline]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)]
@@ -7703,13 +7925,14 @@ vector<uint, N> countbits(vector<uint, N> value)
}
}
-// Cross product
-// TODO: SPIRV does not support integer vectors.
+/// Cross product
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
vector<T,3> cross(vector<T,3> left, vector<T,3> right)
{
+ // TODO: SPIRV does not support integer vectors.
__target_switch
{
case glsl: __intrinsic_asm "cross";
@@ -7768,6 +7991,7 @@ ${{{{
const char* diffDimensions[2] = {"x", "y"};
for (auto xOrY : diffDimensions) {
}}}}
+/// @category derivative Derivative functions
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, fragmentprocessing)]
@@ -7829,6 +8053,7 @@ matrix<T, N, M> dd$(xOrY)(matrix<T, N, M> x)
}
}
+/// @category derivative
__generic<T : __BuiltinFloatingPointType>
__glsl_extension(GL_ARB_derivative_control)
[__readNone]
@@ -7874,6 +8099,7 @@ matrix<T, N, M> dd$(xOrY)_coarse(matrix<T, N, M> x)
}
}
+/// @category derivative
__generic<T : __BuiltinFloatingPointType>
__glsl_extension(GL_ARB_derivative_control)
[__readNone]
@@ -7924,8 +8150,8 @@ ${{{{
}}}}
-// Radians to degrees
-
+/// Convert radians to degrees.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl)]
@@ -7975,8 +8201,8 @@ matrix<T, N, M> degrees(matrix<T, N, M> x)
}
}
-// Matrix determinant
-
+/// Compute matrix determinant.
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int>
[__readNone]
[PreferCheckpoint]
@@ -7995,7 +8221,8 @@ T determinant(matrix<T,N,N> m)
}
}
-// Barrier for device memory
+/// Barrier for device memory.
+/// @category barrier
__glsl_extension(GL_KHR_memory_scope_semantics)
[require(cuda_glsl_hlsl_metal_spirv_wgsl, memorybarrier)]
void DeviceMemoryBarrier()
@@ -8014,6 +8241,8 @@ void DeviceMemoryBarrier()
}
}
+/// @category barrier
+/// Barrier for device memory with group synchronization.
__glsl_extension(GL_KHR_memory_scope_semantics)
[require(cuda_glsl_hlsl_metal_spirv_wgsl, memorybarrier)]
void DeviceMemoryBarrierWithGroupSync()
@@ -8033,7 +8262,7 @@ void DeviceMemoryBarrierWithGroupSync()
}
// Vector distance
-
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -8070,8 +8299,8 @@ T distance(T x, T y)
}
}
-// fdim
-
+/// Computes `max(0, x-y)`.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -8099,7 +8328,7 @@ vector<T,N> fdim(vector<T,N> x, vector<T,N> y)
}
// divide
-
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv)]
@@ -8126,9 +8355,8 @@ vector<T,N> divide(vector<T,N> x, vector<T,N> y)
}
}
-
-// Vector dot product
-
+/// Vector dot product
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -8184,9 +8412,9 @@ T dot(vector<T, N> x, vector<T, N> y)
}
}
-
-// Helper for computing distance terms for lighting (obsolete)
-
+/// Helper for computing distance terms for lighting (obsolete)
+/// @category math
+/// @deprecated
__generic<T : __BuiltinFloatingPointType> vector<T,4> dst(vector<T,4> x, vector<T,4> y);
// Given a RWByteAddressBuffer allow it to be interpreted as a RWStructuredBuffer
@@ -8356,8 +8584,8 @@ matrix<T,N,M> EvaluateAttributeSnapped(matrix<T,N,M> x, int2 offset)
}
}
-// Base-e exponent
-
+/// Computes base-e exponent.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -8377,6 +8605,7 @@ T exp(T x)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -8396,6 +8625,7 @@ vector<T, N> exp(vector<T, N> x)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -8409,8 +8639,8 @@ matrix<T, N, M> exp(matrix<T, N, M> x)
}
}
-// Base-2 exponent
-
+/// Computes base-2 exponent
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -8478,8 +8708,8 @@ matrix<T,N,M> exp2(matrix<T,N,M> x)
}
}
-// Base-10 exponent
-
+/// Computes base-10 exponent
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -8509,7 +8739,8 @@ vector<T,N> exp10(vector<T,N> x)
}
-// Convert 16-bit float stored in low bits of integer
+/// Convert 16-bit float stored in low bits of integer
+/// @category conversion Conversion functions
__glsl_version(420)
__cuda_sm_version(6.0)
[__readNone]
@@ -8556,9 +8787,8 @@ vector<float, N> f16tof32(vector<uint, N> value)
}
}
-
-
-// Convert to 16-bit float stored in low bits of integer
+/// Convert to 16-bit float stored in low bits of integer.
+/// @category conversion
__glsl_version(420)
__cuda_sm_version(6.0)
[__readNone]
@@ -8650,7 +8880,8 @@ vector<float, N> f16tof32(vector<float16_t, N> value)
}
}
-// Convert to float16_t
+/// Convert to float16_t.
+/// @category conversion
__glsl_version(420)
[__readNone]
[require(cuda_glsl_metal_spirv_wgsl, shader5_sm_5_0)]
@@ -8687,7 +8918,8 @@ vector<float16_t, N> f32tof16_(vector<float, N> value)
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-// Flip surface normal to face forward, if needed
+/// Flip surface normal to face forward, if needed.
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -8707,7 +8939,8 @@ vector<T,N> faceforward(vector<T,N> n, vector<T,N> i, vector<T,N> ng)
}
}
-// Find first set bit starting at high bit and working down
+/// Find first set bit starting at high bit and working down.
+/// @category bitops Bit operation functions
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)]
int firstbithigh(int value)
@@ -8782,7 +9015,8 @@ vector<uint,N> firstbithigh(vector<uint,N> value)
}
}
-// Find first set bit starting at low bit and working up
+/// Find first set bit starting at low bit and working up.
+/// @category bitops
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)]
int firstbitlow(int value)
@@ -8857,8 +9091,8 @@ vector<uint,N> firstbitlow(vector<uint,N> value)
}
}
-// Floor (HLSL SM 1.0)
-
+/// Floor (HLSL SM 1.0).
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -8910,7 +9144,8 @@ matrix<T, N, M> floor(matrix<T, N, M> x)
}
}
-// Fused multiply-add
+/// Fused multiply-add.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)]
@@ -8968,7 +9203,11 @@ matrix<T, N, M> fma(matrix<T, N, M> a, matrix<T, N, M> b, matrix<T, N, M> c)
}
}
-// Floating point remainder of x/y
+/// Floating point remainder of x/y.
+/// The floating-point remainder is calculated such that x = i * y + f,
+/// where i is an integer, f has the same sign as x, and the absolute value
+/// of f is less than the absolute value of y.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -9073,7 +9312,8 @@ matrix<T, N, M> fmod(matrix<T, N, M> x, matrix<T, N, M> y)
}
}
-// Fractional part
+/// Extract the fractional part of a floating-point number.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -9119,6 +9359,8 @@ matrix<T, N, M> frac(matrix<T, N, M> x)
MATRIX_MAP_UNARY(T, N, M, frac, x);
}
+/// Extract the fractional part of a floating-point number.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -9137,8 +9379,8 @@ vector<T, N> fract(vector<T, N> x)
return frac(x);
}
-
-// Split float into mantissa and exponent
+/// Split float into mantissa and exponent.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -9217,7 +9459,8 @@ matrix<T, N, M> frexp(matrix<T, N, M> x, out matrix<int, N, M, L> exp)
}
}
-// Texture filter width
+/// Texture filter width.
+/// @category derivative
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(glsl_hlsl_metal_spirv_wgsl, fragmentprocessing)]
@@ -9406,7 +9649,8 @@ float2 GetRenderTargetSamplePosition(int Index)
}
}
-// Group memory barrier
+/// Group memory barrier. Ensures that all memory accesses in the group are visible to all threads in the group.
+/// @category barrier
__glsl_extension(GL_KHR_memory_scope_semantics)
[require(cuda_glsl_hlsl_metal_spirv_wgsl, memorybarrier)]
void GroupMemoryBarrier()
@@ -9443,6 +9687,8 @@ void __subgroupBarrier()
}
}
+/// Group memory barrier. Ensures that all memory accesses in the group are visible to all threads in the group.
+/// @category barrier
__glsl_extension(GL_KHR_memory_scope_semantics)
[require(cuda_glsl_hlsl_metal_spirv_wgsl, memorybarrier)]
void GroupMemoryBarrierWithGroupSync()
@@ -10018,6 +10264,7 @@ ${{{{
for(const char* T : {"int64_t", "uint64_t"})
{
}}}}
+/// @category atomic Atomic functions
[ForceInline]
[require(cuda_glsl_hlsl_spirv, atomic_glsl_hlsl_cuda_metal)]
void InterlockedAdd(__ref $(T) dest, $(T) value)
@@ -10058,6 +10305,7 @@ void InterlockedAdd(__ref $(T) dest, $(T) value, out $(T) original_value)
}
}
+/// @category atomic
[ForceInline]
void InterlockedAnd(__ref $(T) dest, $(T) value)
{
@@ -10076,6 +10324,7 @@ void InterlockedAnd(__ref $(T) dest, $(T) value, out $(T) original_value)
}
}
+/// @category atomic
[ForceInline]
void InterlockedCompareExchange(__ref $(T) dest, $(T) compare_value, $(T) value)
{
@@ -10103,6 +10352,7 @@ void InterlockedCompareStore(__ref $(T) dest, $(T) compare_value, $(T) value);
}
}
+/// @category atomic
[ForceInline]
void InterlockedExchange(__ref $(T) dest, $(T) value)
{
@@ -10121,6 +10371,7 @@ void InterlockedExchange(__ref $(T) dest, $(T) value, out $(T) original_value)
}
}
+/// @category atomic
[ForceInline]
void InterlockedMax(__ref $(T) dest, $(T) value)
{
@@ -10139,6 +10390,7 @@ void InterlockedMax(__ref $(T) dest, $(T) value, out $(T) original_value)
}
}
+/// @category atomic
[ForceInline]
void InterlockedMin(__ref $(T) dest, $(T) value)
{
@@ -10157,6 +10409,7 @@ void InterlockedMin(__ref $(T) dest, $(T) value, out $(T) original_value)
}
}
+/// @category atomic
[ForceInline]
void InterlockedOr(__ref $(T) dest, $(T) value)
{
@@ -10175,6 +10428,7 @@ void InterlockedOr(__ref $(T) dest, $(T) value, out $(T) original_value)
}
}
+/// @category atomic
[ForceInline]
void InterlockedXor(__ref $(T) dest, $(T) value)
{
@@ -10197,6 +10451,7 @@ ${{{{
} // for(const char* T : {"int64_t", "uint64_t"})
}}}}
+/// @category atomic
[ForceInline]
__glsl_version(430)
[require(cuda_glsl_hlsl_metal_spirv, atomic_glsl_hlsl_cuda_metal)]
@@ -10267,6 +10522,7 @@ void InterlockedCompareExchange(__ref uint dest, uint compare_value, uint value,
}
}
+/// @category atomic
[ForceInline]
void InterlockedCompareExchangeFloatBitwise(__ref float dest, float compare_value, float value)
{
@@ -10295,6 +10551,7 @@ void InterlockedCompareExchangeFloatBitwise(__ref float dest, float compare_val
}
}
+/// @category atomic
[ForceInline]
__glsl_version(430)
[require(cuda_glsl_hlsl_metal_spirv, atomic_glsl_hlsl_cuda_metal)]
@@ -10376,6 +10633,7 @@ void InterlockedCompareStore(__ref uint dest, uint compare_value, uint value)
}
}
+/// @category atomic
[ForceInline]
void InterlockedCompareStoreFloatBitwise(__ref float dest, float compare_value, float value)
{
@@ -10385,7 +10643,7 @@ void InterlockedCompareStoreFloatBitwise(__ref float dest, float compare_value
}
}
-
+/// @category atomic
[ForceInline]
void InterlockedExchange(__ref float dest, float value)
{
@@ -10416,8 +10674,8 @@ void InterlockedExchange(__ref float dest, float value, out float original_va
-// Is floating-point value finite?
-
+/// Test if a floating-point value finite.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -10467,7 +10725,8 @@ matrix<bool, N, M> isfinite(matrix<T, N, M> x)
}
}
-// Is floating-point value infinite?
+/// Test if a floating-point value infinite.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -10518,7 +10777,8 @@ matrix<bool, N, M> isinf(matrix<T, N, M> x)
}
}
-// Is floating-point value not-a-number?
+/// Test if a floating-point value is not-a-number.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -10569,8 +10829,8 @@ matrix<bool, N, M> isnan(matrix<T, N, M> x)
}
}
-// Construct float from mantissa and exponent
-
+/// Construct float from mantissa and exponent.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -10655,7 +10915,8 @@ vector<T, N> ldexp(vector<T, N> x, vector<E, N> exp)
}
-// Vector length
+/// Compute the length of a vector.
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -10675,7 +10936,6 @@ T length(vector<T, N> x)
}
}
-// Scalar float length
__generic<T : __BuiltinFloatingPointType>
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
T length(T x)
@@ -10692,7 +10952,9 @@ T length(T x)
}
}
-// Linear interpolation
+/// Computes linear interpolation.
+/// @return Returns `x+(y-x)*s`.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -10743,6 +11005,8 @@ matrix<T,N,M> lerp(matrix<T,N,M> x, matrix<T,N,M> y, matrix<T,N,M> s)
}
// Legacy lighting function (obsolete)
+/// @category math
+/// @deprecated
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
float4 lit(float n_dot_l, float n_dot_h, float m)
@@ -10758,7 +11022,8 @@ float4 lit(float n_dot_l, float n_dot_h, float m)
}
}
-// Base-e logarithm
+/// Compute base-e logarithm.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -10810,7 +11075,8 @@ matrix<T, N, M> log(matrix<T, N, M> x)
}
}
-// Base-10 logarithm
+/// Compute base-10 logarithm.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -10870,7 +11136,8 @@ matrix<T,N,M> log10(matrix<T,N,M> x)
}
}
-// Base-2 logarithm
+/// Compute base-2 logarithm.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -10922,8 +11189,8 @@ matrix<T,N,M> log2(matrix<T,N,M> x)
}
}
-// multiply-add
-
+/// Computes multiply-add.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, shader5_sm_5_0)]
@@ -11020,8 +11287,8 @@ matrix<T, N, M> mad(matrix<T, N, M> mvalue, matrix<T, N, M> avalue, matrix<T, N,
}
}
-
// maximum
+/// @category math
__generic<T : __BuiltinIntegerType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -11058,6 +11325,7 @@ T max(T x, T y)
}
}
+/// @category math
__generic<T : __BuiltinIntegerType, let N : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -11089,6 +11357,7 @@ vector<T, N> max(vector<T, N> x, vector<T, N> y)
}
}
+/// @category math
__generic<T : __BuiltinIntegerType, let N : int, let M : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -11153,6 +11422,7 @@ matrix<T, N, M> max(matrix<T, N, M> x, matrix<T, N, M> y)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -11179,6 +11449,7 @@ vector<T,N> max3(vector<T,N> x, vector<T,N> y, vector<T,N> z)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -11206,6 +11477,7 @@ vector<T,N> fmax(vector<T,N> x, vector<T,N> y)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -11253,8 +11525,8 @@ vector<T,N> fmax3(vector<T,N> x, vector<T,N> y, vector<T,N> z)
}
}
-
// minimum
+/// @category math
__generic<T : __BuiltinIntegerType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -11388,6 +11660,7 @@ T min3(T x, T y, T z)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -11401,6 +11674,7 @@ vector<T,N> min3(vector<T,N> x, vector<T,N> y, vector<T,N> z)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -11428,7 +11702,7 @@ vector<T,N> fmin(vector<T,N> x, vector<T,N> y)
}
}
-
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -11476,8 +11750,8 @@ vector<T,N> fmin3(vector<T,N> x, vector<T,N> y, vector<T,N> z)
}
}
-
// Median
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -11506,6 +11780,7 @@ T median3(T x, T y, T z)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N: int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -11525,6 +11800,7 @@ vector<T,N> median3(vector<T,N> x, vector<T,N> y, vector<T,N> z)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv, sm_4_0_version)]
@@ -11567,8 +11843,8 @@ vector<T,N> fmedian3(vector<T,N> x, vector<T,N> y, vector<T,N> z)
}
}
-
-// split into integer and fractional parts (both with same sign)
+/// Split into integer and fractional parts (both with same sign).
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -11648,6 +11924,7 @@ matrix<T,N,M> modf(matrix<T,N,M> x, out matrix<T,N,M,L> ip)
}
// msad4 (whatever that is)
+/// @category math
[__readNone]
[require(cpp_cuda_glsl_hlsl_spirv, sm_4_0_version)]
uint4 msad4(uint reference, uint2 source, uint4 accum)
@@ -11674,6 +11951,7 @@ uint4 msad4(uint reference, uint2 source, uint4 accum)
// General inner products
// scalar-scalar
+/// @category math
__generic<T : __BuiltinArithmeticType>
__intrinsic_op($(kIROp_Mul))
[__readNone]
@@ -11707,6 +11985,7 @@ __intrinsic_op($(kIROp_Mul))
matrix<T, N, M> mul(T x, matrix<T, N, M> y);
// vector-vector (dot product)
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12022,9 +12301,8 @@ vector<T,N> nextafter(vector<T,N> x, vector<T,N> y)
}
}
-
-// noise (deprecated)
-
+/// @deprecated
+/// @category math
[__readNone]
[deprecated("Always returns 0")]
float noise(float x)
@@ -12084,6 +12362,7 @@ T NonUniformResourceIndex(T index);
T NonUniformResourceIndex<T>(T value) { return value; }
// Normalize a vector
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12123,6 +12402,7 @@ T normalize(T x)
}
// Raise to a power
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12174,6 +12454,7 @@ matrix<T,N,M> pow(matrix<T,N,M> x, matrix<T,N,M> y)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12252,7 +12533,7 @@ ${{{{
}}}}
// Tessellation factor fixup routines
-
+/// @category tessellation Tessellation functions
[require(hlsl, sm_5_0)]
void Process2DQuadTessFactorsAvg(
in float4 RawEdgeFactors,
@@ -12261,6 +12542,7 @@ void Process2DQuadTessFactorsAvg(
out float2 RoundedInsideTessFactors,
out float2 UnroundedInsideTessFactors);
+/// @category tessellation
[require(hlsl, sm_5_0)]
void Process2DQuadTessFactorsMax(
in float4 RawEdgeFactors,
@@ -12269,6 +12551,7 @@ void Process2DQuadTessFactorsMax(
out float2 RoundedInsideTessFactors,
out float2 UnroundedInsideTessFactors);
+/// @category tessellation
[require(hlsl, sm_5_0)]
void Process2DQuadTessFactorsMin(
in float4 RawEdgeFactors,
@@ -12277,6 +12560,7 @@ void Process2DQuadTessFactorsMin(
out float2 RoundedInsideTessFactors,
out float2 UnroundedInsideTessFactors);
+/// @category tessellation
[require(hlsl, sm_5_0)]
void ProcessIsolineTessFactors(
in float RawDetailFactor,
@@ -12284,6 +12568,7 @@ void ProcessIsolineTessFactors(
out float RoundedDetailFactor,
out float RoundedDensityFactor);
+/// @category tessellation
[require(hlsl, sm_5_0)]
void ProcessQuadTessFactorsAvg(
in float4 RawEdgeFactors,
@@ -12292,6 +12577,7 @@ void ProcessQuadTessFactorsAvg(
out float2 RoundedInsideTessFactors,
out float2 UnroundedInsideTessFactors);
+/// @category tessellation
[require(hlsl, sm_5_0)]
void ProcessQuadTessFactorsMax(
in float4 RawEdgeFactors,
@@ -12300,6 +12586,7 @@ void ProcessQuadTessFactorsMax(
out float2 RoundedInsideTessFactors,
out float2 UnroundedInsideTessFactors);
+/// @category tessellation
[require(hlsl, sm_5_0)]
void ProcessQuadTessFactorsMin(
in float4 RawEdgeFactors,
@@ -12308,6 +12595,7 @@ void ProcessQuadTessFactorsMin(
out float2 RoundedInsideTessFactors,
out float2 UnroundedInsideTessFactors);
+/// @category tessellation
[require(hlsl, sm_5_0)]
void ProcessTriTessFactorsAvg(
in float3 RawEdgeFactors,
@@ -12316,6 +12604,7 @@ void ProcessTriTessFactorsAvg(
out float RoundedInsideTessFactor,
out float UnroundedInsideTessFactor);
+/// @category tessellation
[require(hlsl, sm_5_0)]
void ProcessTriTessFactorsMax(
in float3 RawEdgeFactors,
@@ -12324,6 +12613,7 @@ void ProcessTriTessFactorsMax(
out float RoundedInsideTessFactor,
out float UnroundedInsideTessFactor);
+/// @category tessellation
[require(hlsl, sm_5_0)]
void ProcessTriTessFactorsMin(
in float3 RawEdgeFactors,
@@ -12332,7 +12622,8 @@ void ProcessTriTessFactorsMin(
out float RoundedInsideTessFactors,
out float UnroundedInsideTessFactors);
-// Degrees to radians
+/// Convert degrees to radians.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12382,7 +12673,8 @@ matrix<T, N, M> radians(matrix<T, N, M> x)
}
}
-// Approximate reciprocal
+/// Compute approximate reciprocal of `x`.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12426,7 +12718,8 @@ matrix<T, N, M> rcp(matrix<T, N, M> x)
}
}
-// Reflect incident vector across plane with given normal
+/// Reflect incident vector across plane with given normal.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12465,7 +12758,8 @@ vector<T,N> reflect(vector<T,N> i, vector<T,N> n)
}
}
-// Refract incident vector given surface normal and index of refraction
+/// Refract incident vector given surface normal and index of refraction.
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12510,7 +12804,8 @@ T refract(T i, T n, T eta)
}
}
-// Reverse order of bits
+/// Reverse order of bits.
+/// @category bitops
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, shader5_sm_5_0)]
uint reversebits(uint value)
@@ -12551,7 +12846,8 @@ vector<uint, N> reversebits(vector<uint, N> value)
}
}
-// round even
+/// Round even.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -12601,7 +12897,8 @@ vector<T,N> rint(vector<T,N> x)
}
}
-// Round-to-nearest
+/// Round-to-nearest.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12653,7 +12950,8 @@ matrix<T,N,M> round(matrix<T,N,M> x)
}
}
-// Reciprocal of square root
+/// Reciprocal of square root.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12705,8 +13003,8 @@ matrix<T, N, M> rsqrt(matrix<T, N, M> x)
}
}
-// Clamp value to [0,1] range
-
+/// Clamp value to [0,1] range.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12760,7 +13058,8 @@ __generic<T:__BuiltinArithmeticType, U:__BuiltinArithmeticType, let N : int>
__intrinsic_op($(kIROp_IntCast))
vector<T,N> __int_cast(vector<U,N> val);
-// Extract sign of value
+/// Extract sign of value.
+/// @category math Math functions
__generic<T : __BuiltinSignedArithmeticType>
[__readNone]
int sign(T x)
@@ -12826,7 +13125,7 @@ matrix<int, N, M> sign(matrix<T, N, M> x)
}
// Sine
-
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -12901,6 +13200,7 @@ vector<T,N> __sincos_metal(vector<T,N> x, out vector<T,N> c)
}
}
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[ForceInline]
@@ -12955,7 +13255,8 @@ void sincos(matrix<T,N,M> x, out matrix<T,N,M,L1> s, out matrix<T,N,M,L2> c)
}
}
-// Hyperbolic Sine
+/// Hyperbolic sine.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -13007,8 +13308,8 @@ matrix<T, N, M> sinh(matrix<T, N, M> x)
}
}
-// Sine degree
-
+/// Compute the sine of an angle in degrees.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -13036,7 +13337,8 @@ vector<T,N> sinpi(vector<T,N> x)
}
-// Smooth step (Hermite interpolation)
+/// Smooth step (Hermite interpolation).
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -13089,7 +13391,8 @@ matrix<T, N, M> smoothstep(matrix<T, N, M> min, matrix<T, N, M> max, matrix<T, N
}
}
-// Square root
+/// Compute the square root of `x`.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -13141,7 +13444,8 @@ matrix<T, N, M> sqrt(matrix<T, N, M> x)
}
}
-// Step function
+/// Step function.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -13193,7 +13497,8 @@ matrix<T, N, M> step(matrix<T, N, M> y, matrix<T, N, M> x)
}
}
-// Tangent
+/// Compute the tangent of `x`.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -13245,7 +13550,8 @@ matrix<T, N, M> tan(matrix<T, N, M> x)
}
}
-// Hyperbolic tangent
+/// Compute the hyperbolic tangent of `x`.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -13297,8 +13603,8 @@ matrix<T,N,M> tanh(matrix<T,N,M> x)
}
}
-// Tangent degree
-
+/// Compute the tangent of `x` in degrees.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -13326,7 +13632,8 @@ vector<T,N> tanpi(vector<T,N> x)
}
-// Matrix transpose
+/// Matrix transpose.
+/// @category math
__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
[__readNone]
[require(cpp_cuda_glsl_hlsl_spirv_wgsl, sm_4_0_version)]
@@ -13395,7 +13702,8 @@ matrix<T, M, N> transpose(matrix<T, N, M> x)
}
}
-// Truncate to integer
+/// Truncate to integer.
+/// @category math
__generic<T : __BuiltinFloatingPointType>
[__readNone]
[require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, sm_4_0_version)]
@@ -13449,6 +13757,7 @@ matrix<T, N, M> trunc(matrix<T, N, M> x)
// Slang Specific 'Mask' Wave Intrinsics
+//@hidden:
typedef uint WaveMask;
__glsl_extension(GL_KHR_shader_subgroup_ballot)
@@ -14653,11 +14962,14 @@ matrix<T,N,M> WaveMaskPrefixBitXor(WaveMask mask, matrix<T,N,M> expr)
}
}
+//@public:
+
// Shader model 6.0 stuff
// Information for GLSL wave/subgroup support
// https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_shader_subgroup.txt
+/// @category wave
__generic<T : __BuiltinType>
__glsl_extension(GL_KHR_shader_subgroup_quad)
__spirv_version(1.3)
@@ -14698,7 +15010,7 @@ vector<T,N> QuadReadLaneAt(vector<T,N> sourceValue, uint quadLaneID)
}
__generic<T : __BuiltinType, let N : int, let M : int> matrix<T,N,M> QuadReadLaneAt(matrix<T,N,M> sourceValue, uint quadLaneID);
-
+/// @category wave
__generic<T : __BuiltinType>
__glsl_extension(GL_KHR_shader_subgroup_quad)
__spirv_version(1.3)
@@ -14742,6 +15054,7 @@ vector<T,N> QuadReadAcrossX(vector<T,N> localValue)
}
__generic<T : __BuiltinType, let N : int, let M : int> matrix<T,N,M> QuadReadAcrossX(matrix<T,N,M> localValue);
+/// @category wave
__generic<T : __BuiltinType>
__glsl_extension(GL_KHR_shader_subgroup_quad)
__spirv_version(1.3)
@@ -14785,6 +15098,7 @@ vector<T,N> QuadReadAcrossY(vector<T,N> localValue)
__generic<T : __BuiltinType, let N : int, let M : int> matrix<T,N,M> QuadReadAcrossY(matrix<T,N,M> localValue);
+/// @category wave
__generic<T : __BuiltinType>
__glsl_extension(GL_KHR_shader_subgroup_quad)
__spirv_version(1.3)
@@ -14833,7 +15147,7 @@ struct WaveActiveBitOpEntry { const char* hlslName; const char* glslName; const
const WaveActiveBitOpEntry kWaveActiveBitOpEntries[] = {{"BitAnd", "And", "BitwiseAnd"}, {"BitOr", "Or", "BitwiseOr"}, {"BitXor", "Xor", "BitwiseXor"}};
for (auto opName : kWaveActiveBitOpEntries) {
}}}}
-
+/// @category wave Wave and quad functions
__generic<T : __BuiltinIntegerType>
__glsl_extension(GL_KHR_shader_subgroup_arithmetic)
__spirv_version(1.3)
@@ -14895,7 +15209,7 @@ ${{{{
const char* kWaveActiveMinMaxNames[] = {"Min", "Max"};
for (const char* opName : kWaveActiveMinMaxNames) {
}}}}
-
+/// @category wave
__generic<T : __BuiltinArithmeticType>
__glsl_extension(GL_KHR_shader_subgroup_arithmetic)
__spirv_version(1.3)
@@ -14969,7 +15283,7 @@ struct WaveActiveProductSumEntry { const char* hlslName; const char* glslName; }
const WaveActiveProductSumEntry kWaveActivProductSumNames[] = {{"Product", "Mul"}, {"Sum", "Add"}};
for (auto opName : kWaveActivProductSumNames) {
}}}}
-
+/// @category wave
__generic<T : __BuiltinArithmeticType>
__glsl_extension(GL_KHR_shader_subgroup_arithmetic)
__spirv_version(1.3)
@@ -15055,7 +15369,7 @@ matrix<T, N, M> WaveActive$(opName.hlslName)(matrix<T, N, M> expr)
${{{{
} // WaveActiveProduct/WaveActiveProductSum.
}}}}
-
+/// @category wave
__generic<T : __BuiltinType>
__glsl_extension(GL_KHR_shader_subgroup_vote)
__spirv_version(1.3)
@@ -15114,6 +15428,7 @@ bool WaveActiveAllEqual(matrix<T, N, M> value)
}
}
+/// @category wave
__glsl_extension(GL_KHR_shader_subgroup_vote)
__spirv_version(1.3)
[require(cuda_glsl_hlsl_spirv, subgroup_vote)]
@@ -15136,6 +15451,7 @@ bool WaveActiveAllTrue(bool condition)
}
}
+/// @category wave
__glsl_extension(GL_KHR_shader_subgroup_vote)
__spirv_version(1.3)
[require(cuda_glsl_hlsl_spirv, subgroup_vote)]
@@ -15158,6 +15474,7 @@ bool WaveActiveAnyTrue(bool condition)
}
}
+/// @category wave
__glsl_extension(GL_KHR_shader_subgroup_ballot)
__spirv_version(1.3)
[NonUniformReturn]
@@ -15181,6 +15498,7 @@ uint4 WaveActiveBallot(bool condition)
}
}
+/// @category wave
[require(cuda_glsl_hlsl_spirv, subgroup_basic_ballot)]
uint WaveActiveCountBits(bool value)
{
@@ -15195,6 +15513,7 @@ uint WaveActiveCountBits(bool value)
}
}
+/// @category wave
__glsl_extension(GL_KHR_shader_subgroup_basic)
__spirv_version(1.3)
[NonUniformReturn]
@@ -15215,6 +15534,7 @@ uint WaveGetLaneCount()
}
}
+/// @category wave
__glsl_extension(GL_KHR_shader_subgroup_basic)
__spirv_version(1.3)
[NonUniformReturn]
@@ -15235,6 +15555,7 @@ uint WaveGetLaneIndex()
}
}
+/// @category wave
__glsl_extension(GL_KHR_shader_subgroup_basic)
__spirv_version(1.3)
[NonUniformReturn]
@@ -15260,6 +15581,7 @@ bool WaveIsFirstLane()
// It's useful to have a wave uint4 version of countbits, because some wave functions return uint4.
// This implementation tries to limit the amount of work required by the actual lane count.
+/// @category wave
__spirv_version(1.3)
[require(cpp_cuda_glsl_hlsl_spirv, subgroup_basic_ballot)]
uint _WaveCountBits(uint4 value)
@@ -15286,9 +15608,8 @@ uint _WaveCountBits(uint4 value)
}
}
-
// Prefix
-
+/// @category wave
__generic<T : __BuiltinArithmeticType>
__glsl_extension(GL_KHR_shader_subgroup_arithmetic)
__spirv_version(1.3)
@@ -15321,7 +15642,7 @@ T WavePrefixProduct(T expr)
}
}
-
+/// @category wave
__generic<T : __BuiltinArithmeticType, let N : int>
__glsl_extension(GL_KHR_shader_subgroup_arithmetic)
__spirv_version(1.3)
@@ -15350,7 +15671,7 @@ vector<T,N> WavePrefixProduct(vector<T,N> expr)
return WaveMaskPrefixProduct(WaveGetActiveMask(), expr);
}
}
-
+/// @category wave
__generic<T : __BuiltinArithmeticType, let N : int, let M : int>
[require(cuda_glsl_hlsl_spirv, subgroup_arithmetic)]
matrix<T, N, M> WavePrefixProduct(matrix<T, N, M> expr)
@@ -15369,6 +15690,7 @@ matrix<T, N, M> WavePrefixProduct(matrix<T, N, M> expr)
}
}
+/// @category wave
__generic<T : __BuiltinArithmeticType>
__glsl_extension(GL_KHR_shader_subgroup_arithmetic)
__spirv_version(1.3)
@@ -15445,6 +15767,7 @@ matrix<T,N,M> WavePrefixSum(matrix<T,N,M> expr)
}
}
+/// @category wave
__generic<T : __BuiltinType>
__glsl_extension(GL_KHR_shader_subgroup_ballot)
__spirv_version(1.3)
@@ -15507,6 +15830,7 @@ matrix<T,N,M> WaveReadLaneFirst(matrix<T,N,M> expr)
// https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_shader_subgroup.txt
// Versions SPIR-V greater than 1.4 loosen this restriction, and allow 'dynamic uniform' index
// If that's the behavior required then client code should use WaveReadLaneAt which works this way.
+/// @category wave
__generic<T : __BuiltinType>
__glsl_extension(GL_KHR_shader_subgroup_ballot)
__spirv_version(1.3)
@@ -15527,6 +15851,7 @@ T WaveBroadcastLaneAt(T value, constexpr int lane)
}
}
+/// @category wave
__generic<T : __BuiltinType, let N : int>
__glsl_extension(GL_KHR_shader_subgroup_ballot)
__spirv_version(1.3)
@@ -15568,6 +15893,7 @@ matrix<T, N, M> WaveBroadcastLaneAt(matrix<T, N, M> value, constexpr int lane)
// TODO(JS): If it can be determines that the `laneId` is constExpr, then subgroupBroadcast
// could be used on GLSL. For now we just use subgroupShuffle
+/// @category wave
__generic<T : __BuiltinType>
__glsl_extension(GL_KHR_shader_subgroup_shuffle)
__spirv_version(1.3)
@@ -15630,6 +15956,7 @@ matrix<T, N, M> WaveReadLaneAt(matrix<T, N, M> value, int lane)
// NOTE! WaveShuffle is a NON STANDARD HLSL intrinsic! It will map to WaveReadLaneAt on HLSL
// which means it will only work on hardware which allows arbitrary laneIds which is not true
// in general because it breaks the HLSL standard, which requires it's 'dynamically uniform' across the Wave.
+/// @category wave
__generic<T : __BuiltinType>
__glsl_extension(GL_KHR_shader_subgroup_shuffle)
__spirv_version(1.3)
@@ -15650,6 +15977,7 @@ T WaveShuffle(T value, int lane)
}
}
+/// @category wave
__generic<T : __BuiltinType, let N : int>
__glsl_extension(GL_KHR_shader_subgroup_shuffle)
__spirv_version(1.3)
@@ -15682,6 +16010,7 @@ matrix<T, N, M> WaveShuffle(matrix<T, N, M> value, int lane)
}
}
+/// @category wave
__glsl_extension(GL_KHR_shader_subgroup_ballot)
__spirv_version(1.3)
[require(cuda_glsl_hlsl_spirv, subgroup_ballot)]
@@ -15704,6 +16033,7 @@ uint WavePrefixCountBits(bool value)
}
}
+/// @category wave
__glsl_extension(GL_KHR_shader_subgroup_ballot)
__spirv_version(1.3)
[require(cuda_glsl_hlsl_spirv, subgroup_ballot)]
@@ -15725,6 +16055,7 @@ uint4 WaveGetConvergedMulti()
}
}
+/// @category wave
[ForceInline]
uint4 WaveGetActiveMulti()
{
@@ -15734,6 +16065,7 @@ uint4 WaveGetActiveMulti()
// Shader model 6.5 stuff
// https://github.com/microsoft/DirectX-Specs/blob/master/d3d/HLSL_ShaderModel6_5.md
+/// @category wave
__generic<T : __BuiltinType>
[require(cuda_glsl_hlsl_spirv, subgroup_partitioned)]
uint4 WaveMatch(T value)
@@ -15794,6 +16126,7 @@ uint4 WaveMatch(matrix<T,N,M> value)
}
}
+/// @category wave
[require(cuda_hlsl, waveprefix)]
uint WaveMultiPrefixCountBits(bool value, uint4 mask)
{
@@ -15804,6 +16137,7 @@ uint WaveMultiPrefixCountBits(bool value, uint4 mask)
}
}
+/// @category wave
__generic<T : __BuiltinArithmeticType>
__glsl_extension(GL_KHR_shader_subgroup_arithmetic)
__spirv_version(1.3)
@@ -15843,6 +16177,7 @@ matrix<T,N,M> WaveMultiPrefixBitAnd(matrix<T,N,M> expr, uint4 mask)
}
}
+/// @category wave
__generic<T : __BuiltinArithmeticType>
__glsl_extension(GL_KHR_shader_subgroup_arithmetic)
__spirv_version(1.3)
@@ -15882,6 +16217,7 @@ matrix<T,N,M> WaveMultiPrefixBitOr(matrix<T,N,M> expr, uint4 mask)
}
}
+/// @category wave
__generic<T : __BuiltinArithmeticType>
__glsl_extension(GL_KHR_shader_subgroup_arithmetic)
__spirv_version(1.3)
@@ -15921,6 +16257,7 @@ matrix<T,N,M> WaveMultiPrefixBitXor(matrix<T,N,M> expr, uint4 mask)
}
}
+/// @category wave
__generic<T : __BuiltinArithmeticType>
[require(cuda_hlsl, waveprefix)]
T WaveMultiPrefixProduct(T value, uint4 mask)
@@ -15954,6 +16291,7 @@ matrix<T,N,M> WaveMultiPrefixProduct(matrix<T,N,M> value, uint4 mask)
}
}
+/// @category wave
__generic<T : __BuiltinArithmeticType>
[require(cuda_hlsl, waveprefix)]
T WaveMultiPrefixSum(T value, uint4 mask)
@@ -16006,7 +16344,9 @@ bool IsHelperLane()
}
// `typedef`s to help with the fact that HLSL has been sorta-kinda case insensitive at various points
+//@hidden:
typedef Texture2D texture2D;
+//@public:
${{{{
@@ -16025,10 +16365,11 @@ static const int kBaseBufferAccessLevelCount = sizeof(kBaseBufferAccessLevels) /
for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
{
auto access = kBaseBufferAccessLevels[aa].access;
+ sb << "/// @category texture_types\n";
sb << "__generic<T,let format:int=0>\n";
sb << "typealias ";
sb << kBaseBufferAccessLevels[aa].name;
- sb << "Buffer = __TextureImpl<T, __ShapeBuffer, 0, 0, 0, " << aa << ", 0, 0, format>;\n";
+ sb << "Buffer = _Texture<T, __ShapeBuffer, 0, 0, 0, " << aa << ", 0, 0, format>;\n";
bool isReadOnly = aa == 0;
@@ -16041,7 +16382,7 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
}}}}
__generic<T, let format:int>
-extension __TextureImpl<T, __ShapeBuffer, 0, 0, 0, $(aa), 0, 0, format>
+extension _Texture<T, __ShapeBuffer, 0, 0, 0, $(aa), 0, 0, format>
{
[__readNone]
$(requireToSetQuery)
@@ -16138,22 +16479,34 @@ ${{{{
// 10.1.1 - Ray Flags
+/// @category raytracing Ray-tracing
typedef uint RAY_FLAG;
-static const RAY_FLAG RAY_FLAG_NONE = 0x00;
-static const RAY_FLAG RAY_FLAG_FORCE_OPAQUE = 0x01;
-static const RAY_FLAG RAY_FLAG_FORCE_NON_OPAQUE = 0x02;
-static const RAY_FLAG RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH = 0x04;
-static const RAY_FLAG RAY_FLAG_SKIP_CLOSEST_HIT_SHADER = 0x08;
-static const RAY_FLAG RAY_FLAG_CULL_BACK_FACING_TRIANGLES = 0x10;
-static const RAY_FLAG RAY_FLAG_CULL_FRONT_FACING_TRIANGLES = 0x20;
-static const RAY_FLAG RAY_FLAG_CULL_OPAQUE = 0x40;
-static const RAY_FLAG RAY_FLAG_CULL_NON_OPAQUE = 0x80;
-static const RAY_FLAG RAY_FLAG_SKIP_TRIANGLES = 0x100;
-static const RAY_FLAG RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES = 0x200;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_NONE = 0x00;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_FORCE_OPAQUE = 0x01;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_FORCE_NON_OPAQUE = 0x02;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH = 0x04;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_SKIP_CLOSEST_HIT_SHADER = 0x08;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_CULL_BACK_FACING_TRIANGLES = 0x10;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_CULL_FRONT_FACING_TRIANGLES = 0x20;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_CULL_OPAQUE = 0x40;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_CULL_NON_OPAQUE = 0x80;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_SKIP_TRIANGLES = 0x100;
+/// @category raytracing
+static const RAY_FLAG RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES = 0x200;
// 10.1.2 - Ray Description Structure
-
+/// @category raytracing
__target_intrinsic(hlsl, RayDesc)
__target_intrinsic(cuda, RayDesc)
struct RayDesc
@@ -16176,7 +16529,7 @@ struct RayDesc
};
// 10.1.3 - Ray Acceleration Structure
-
+/// @category raytracing
__builtin
__magic_type(RaytracingAccelerationStructureType)
__intrinsic_type($(kIROp_RaytracingAccelerationStructureType))
@@ -16190,7 +16543,7 @@ struct RaytracingAccelerationStructure {};
// for this stuff comes across as a kludge rather than the best possible design.
// 10.1.5 - Intersection Attributes Structure
-
+/// @category raytracing
__target_intrinsic(hlsl, BuiltInTriangleIntersectionAttributes)
[require(cpp_cuda_glsl_hlsl_spirv, raytracing)]
struct BuiltInTriangleIntersectionAttributes
@@ -16232,6 +16585,7 @@ int __callablePayloadLocation(__ref Payload payload);
// targets, which maps the generic HLSL operation into the non-generic
// GLSL equivalent.
//
+/// @category raytracing
__generic<Payload>
[require(glsl_hlsl_spirv, raytracing_raygen_closesthit_miss_callable)]
void CallShader(uint shaderIndex, inout Payload payload)
@@ -16322,6 +16676,7 @@ __generic<Payload>
__intrinsic_op($(kIROp_GetVulkanRayTracingPayloadLocation))
int __rayPayloadLocation(__ref Payload payload);
+/// @category raytracing
[ForceInline]
__generic<payload_t>
[require(cuda_glsl_hlsl_spirv, raytracing_raygen_closesthit_miss)]
@@ -16446,6 +16801,7 @@ void __traceMotionRay(
}
}
+/// @category raytracing
[ForceInline]
[require(glsl_hlsl_spirv, raytracing_motionblur_raygen_closesthit_miss)]
__generic<payload_t>
@@ -16546,6 +16902,7 @@ bool __reportIntersection(float tHit, uint hitKind)
}
}
+/// @category raytracing
__generic<A>
[ForceInline]
[require(glsl_hlsl_spirv, raytracing_intersection)]
@@ -16564,6 +16921,7 @@ bool ReportHit(float tHit, uint hitKind, A attributes)
}
}
+/// @category raytracing
__generic<each T : __BuiltinIntegerType>
[ForceInline]
[require(cuda_glsl_hlsl_spirv, raytracing_intersection)]
@@ -16579,6 +16937,7 @@ bool ReportHitOptix(float tHit, uint hitKind, expand each T attribs)
}
// 10.3.4
+/// @category raytracing
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit)]
void IgnoreHit()
{
@@ -16596,6 +16955,7 @@ void IgnoreHit()
}
// 10.3.5
+/// @category raytracing
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit)]
void AcceptHitAndEndSearch()
{
@@ -16619,6 +16979,7 @@ void AcceptHitAndEndSearch()
// 10.4.1 - Ray Dispatch System Values
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_allstages)]
uint3 DispatchRaysIndex()
@@ -16636,6 +16997,7 @@ uint3 DispatchRaysIndex()
}
}
+/// @category raytracing
[require(cuda_glsl_hlsl_spirv, raytracing_allstages)]
uint3 DispatchRaysDimensions()
{
@@ -16654,6 +17016,7 @@ uint3 DispatchRaysDimensions()
// 10.4.2 - Ray System Values
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection_miss)]
float3 WorldRayOrigin()
@@ -16671,6 +17034,7 @@ float3 WorldRayOrigin()
}
}
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection_miss)]
float3 WorldRayDirection()
@@ -16688,6 +17052,7 @@ float3 WorldRayDirection()
}
}
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection_miss)]
float RayTMin()
@@ -16715,6 +17080,7 @@ float RayTMin()
// we should simply provide two overloads here, specialized
// to the appropriate Vulkan stages.
//
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection_miss)]
float RayTCurrent()
@@ -16732,6 +17098,7 @@ float RayTCurrent()
}
}
+/// @category raytracing
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection_miss)]
uint RayFlags()
{
@@ -16750,6 +17117,7 @@ uint RayFlags()
// 10.4.3 - Primitive/Object Space System Values
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
uint InstanceIndex()
@@ -16767,6 +17135,7 @@ uint InstanceIndex()
}
}
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
uint InstanceID()
@@ -16784,6 +17153,7 @@ uint InstanceID()
}
}
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
uint PrimitiveIndex()
@@ -16801,6 +17171,7 @@ uint PrimitiveIndex()
}
}
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
float3 ObjectRayOrigin()
@@ -16818,6 +17189,7 @@ float3 ObjectRayOrigin()
}
}
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
float3 ObjectRayDirection()
@@ -16837,6 +17209,7 @@ float3 ObjectRayDirection()
// TODO: optix has an optixGetObjectToWorldTransformMatrix function that returns 12
// floats by reference.
+/// @category raytracing
[NonUniformReturn]
[require(glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
float3x4 ObjectToWorld3x4()
@@ -16854,6 +17227,7 @@ float3x4 ObjectToWorld3x4()
}
}
+/// @category raytracing
[NonUniformReturn]
[require(glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
float3x4 WorldToObject3x4()
@@ -16871,6 +17245,7 @@ float3x4 WorldToObject3x4()
}
}
+/// @category raytracing
[NonUniformReturn]
[require(glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
float4x3 ObjectToWorld4x3()
@@ -16887,6 +17262,7 @@ float4x3 ObjectToWorld4x3()
}
}
+/// @category raytracing
[NonUniformReturn]
[require(glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
float4x3 WorldToObject4x3()
@@ -16907,6 +17283,7 @@ float4x3 WorldToObject4x3()
// The name of the following functions may change when DXR supports
// a feature similar to the `GL_NV_ray_tracing_motion_blur` extension
+/// @category raytracing
__glsl_extension(GL_NV_ray_tracing_motion_blur)
__glsl_extension(GL_EXT_ray_tracing)
[NonUniformReturn]
@@ -16934,10 +17311,13 @@ float RayCurrentTime()
// declarations, so that users can know they aren't coding
// against the final spec?
//
+/// @category raytracing
[NonUniformReturn] float3x4 ObjectToWorld() { return ObjectToWorld3x4(); }
+/// @category raytracing
[NonUniformReturn] float3x4 WorldToObject() { return WorldToObject3x4(); }
// 10.4.4 - Hit Specific System values
+/// @category raytracing
[NonUniformReturn]
[require(cuda_glsl_hlsl_spirv, raytracing_anyhit_closesthit)]
uint HitKind()
@@ -16956,22 +17336,26 @@ uint HitKind()
}
// Pre-defined hit kinds (not documented explicitly)
-static const uint HIT_KIND_TRIANGLE_FRONT_FACE = 254;
+/// @category raytracing
+static const uint HIT_KIND_TRIANGLE_FRONT_FACE = 254;
+/// @category raytracing
static const uint HIT_KIND_TRIANGLE_BACK_FACE = 255;
//
// Shader Model 6.4
//
-// Treats `left` and `right` as 4-component vectors of `UInt8` and computes `dot(left, right) + acc`
+/// Treats `left` and `right` as 4-component vectors of `UInt8` and computes `dot(left, right) + acc`
+/// @category math
uint dot4add_u8packed(uint left, uint right, uint acc);
-// Treats `left` and `right` as 4-component vectors of `Int8` and computes `dot(left, right) + acc`
+/// Treats `left` and `right` as 4-component vectors of `Int8` and computes `dot(left, right) + acc`
+/// @category math
int dot4add_i8packed(uint left, uint right, int acc);
-// Computes `dot(left, right) + acc`.
-//
-// May not produce infinities or NaNs for intermediate results that overflow the range of `half`
+/// Computes `dot(left, right) + acc`.
+/// May not produce infinities or NaNs for intermediate results that overflow the range of `half`
+/// @category math
float dot2add(float2 left, float2 right, float acc);
//
@@ -16982,7 +17366,8 @@ float dot2add(float2 left, float2 right, float acc);
// Mesh Shaders
//
-// Set the number of output vertices and primitives for a mesh shader invocation.
+/// Set the number of output vertices and primitives for a mesh shader invocation.
+/// @category meshshading Mesh shading
__glsl_extension(GL_EXT_mesh_shader)
__glsl_version(450)
[require(glsl_hlsl_metal_spirv, meshshading)]
@@ -17007,18 +17392,17 @@ void SetMeshOutputCounts(uint vertexCount, uint primitiveCount)
}
}
-// Specify the number of downstream mesh shader thread groups to invoke from an amplification shader,
-// and provide the values for per-mesh payload parameters.
-//
-// This function doesn't return.
-//
-// This function cannot be inlined due to a legalization pass happening mid-way through processing
-// and later more processing happening to the function which requires eventual inlining.
+/// Specify the number of downstream mesh shader thread groups to invoke from an amplification shader,
+/// and provide the values for per-mesh payload parameters.
+/// @return This function doesn't return.
+/// @category meshshading
[KnownBuiltin("DispatchMesh")]
[require(glsl_hlsl_metal_spirv, meshshading)]
[noRefInline]
void DispatchMesh<P>(uint threadGroupCountX, uint threadGroupCountY, uint threadGroupCountZ, __ref P meshPayload)
{
+ // This function cannot be inlined due to a legalization pass happening mid-way through processing
+ // and later more processing happening to the function which requires eventual inlining.
__target_switch
{
case hlsl:
@@ -17055,19 +17439,22 @@ void DispatchMesh<P>(uint threadGroupCountX, uint threadGroupCountY, uint thread
[builtin]
interface __BuiltinSamplerFeedbackType {};
+/// @category texture_types
[sealed]
__magic_type(FeedbackType, $(int(FeedbackType::Kind::MinMip)))
__target_intrinsic(hlsl, SAMPLER_FEEDBACK_MIN_MIP)
struct SAMPLER_FEEDBACK_MIN_MIP : __BuiltinSamplerFeedbackType {};
+/// @category texture_types
[sealed]
__magic_type(FeedbackType, $(int(FeedbackType::Kind::MipRegionUsed)))
__target_intrinsic(hlsl, SAMPLER_FEEDBACK_MIP_REGION_USED)
struct SAMPLER_FEEDBACK_MIP_REGION_USED : __BuiltinSamplerFeedbackType {};
// All of these objects are write-only resources that point to a special kind of unordered access view meant for sampler feedback.
+
__generic<T:__BuiltinSamplerFeedbackType>
-extension __TextureImpl<T,__Shape2D, 0, 0, 0, $(kStdlibResourceAccessFeedback), 0, 0, 0>
+extension _Texture<T,__Shape2D, 0, 0, 0, $(kStdlibResourceAccessFeedback), 0, 0, 0>
{
// With Clamp
@@ -17147,7 +17534,7 @@ extension __TextureImpl<T,__Shape2D, 0, 0, 0, $(kStdlibResourceAccessFeedback),
};
__generic<T:__BuiltinSamplerFeedbackType>
-extension __TextureImpl<T,__Shape2D, 1, 0, 0, $(kStdlibResourceAccessFeedback), 0, 0, 0>
+extension _Texture<T,__Shape2D, 1, 0, 0, $(kStdlibResourceAccessFeedback), 0, 0, 0>
{
// With Clamp
@@ -17231,6 +17618,7 @@ extension __TextureImpl<T,__Shape2D, 1, 0, 0, $(kStdlibResourceAccessFeedback),
//
// Get the index of the geometry that was hit in an intersection, any-hit, or closest-hit shader
+/// @category raytracing
__glsl_extension(GL_EXT_ray_tracing)
[NonUniformReturn]
[require(glsl_hlsl_spirv, raytracing_anyhit_closesthit_intersection)]
@@ -17246,8 +17634,9 @@ uint GeometryIndex()
}
}
-// Get the vertex positions of the currently hit triangle in any-hit or closest-hit shader.
-// https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GLSL_EXT_ray_tracing_position_fetch.txt
+/// Get the vertex positions of the currently hit triangle in any-hit or closest-hit shader.
+/// https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GLSL_EXT_ray_tracing_position_fetch.txt
+/// @category raytracing
__glsl_extension(GL_EXT_ray_tracing)
__glsl_extension(GL_EXT_ray_tracing_position_fetch)
[ForceInline]
@@ -17271,71 +17660,73 @@ float3 HitTriangleVertexPosition(uint index)
}
}
-// Status of whether a (closest) hit has been committed in a `RayQuery`.
+/// Status of whether a (closest) hit has been committed in a `RayQuery`.
+/// @category raytracing
typedef uint COMMITTED_STATUS;
-// No hit committed.
+/// No hit committed.
+/// @category raytracing
static const COMMITTED_STATUS COMMITTED_NOTHING = 0;
-// Closest hit is a triangle.
-//
-// This could be an opaque triangle hit found by the fixed-function
-// traversal and intersection implementation, or a non-opaque
-// triangle hit committed by user code with `RayQuery.CommitNonOpaqueTriangleHit`
-//
+/// Closest hit is a triangle.
+/// This could be an opaque triangle hit found by the fixed-function
+/// traversal and intersection implementation, or a non-opaque
+/// triangle hit committed by user code with `RayQuery.CommitNonOpaqueTriangleHit`
+/// @category raytracing
static const COMMITTED_STATUS COMMITTED_TRIANGLE_HIT = 1;
-// Closest hit is a procedural primitive.
-//
-// A procedural hit primitive is committed using `RayQuery.CommitProceduralPrimitiveHit`.
+/// Closest hit is a procedural primitive.
+/// A procedural hit primitive is committed using `RayQuery.CommitProceduralPrimitiveHit`.
+/// @category raytracing
static const COMMITTED_STATUS COMMITTED_PROCEDURAL_PRIMITIVE_HIT = 2;
-// Type of candidate hit that a `RayQuery` is pausing at.
-//
-// A `RayQuery` can automatically commit hits with opaque triangles,
-// but yields to user code for other hits to allow them to be
-// dismissed or committed.
-//
+/// Type of candidate hit that a `RayQuery` is pausing at.
+/// A `RayQuery` can automatically commit hits with opaque triangles,
+/// but yields to user code for other hits to allow them to be
+/// dismissed or committed.
+/// @category raytracing
typedef uint CANDIDATE_TYPE;
-// Candidate hit is a non-opaque triangle.
+/// Candidate hit is a non-opaque triangle.
+/// @category raytracing
static const CANDIDATE_TYPE CANDIDATE_NON_OPAQUE_TRIANGLE = 0;
-// Candidate hit is a procedural primitive.
+/// Candidate hit is a procedural primitive.
+/// @category raytracing
static const CANDIDATE_TYPE CANDIDATE_PROCEDURAL_PRIMITIVE = 1;
-// Handle to state of an in-progress ray-tracing query.
+/// Handle to state of an in-progress ray-tracing query.
+/// The ray query is effectively a coroutine that user shader
+/// code can resume to continue tracing the ray, and which yields
+/// back to the user code at interesting events along the ray.
//
-// The ray query is effectively a coroutine that user shader
-// code can resume to continue tracing the ray, and which yields
-// back to the user code at interesting events along the ray.
-//
-// Note: The treatment of the `RayQuery` type in Slang does not
-// perfectly match its semantics in vanilla HLSL in some corner
-// cases. Specifically, a `RayQuery` in vanilla HLSL is an
-// opaque handle to mutable storage, and assigning a `RayQuery`
-// or passing one as a parameter will only copy the *handle*,
-// potentially resulting in aliasing of the underlying mutable
-// storage.
-//
-// In contrast, Slang considers a `RayQuery` to own its mutable
-// state, and (because the API does not support cloning of queries),
-// `RayQuery` values are non-copyable (aka "move-only").
-//
-// The main place where this arises as a consideration is when
-// passing a `RayQuery` down into a function that will perform
-// mutating operations on it (e.g., `TraceRay` or `Proceed`):
-//
-// void myFunc( inout RayQuery<FLAGS> q )
-// {
-// q.Proceed();
-// }
-//
-// In Slang, a parameter like `q` above should be declared `inout`.
-// HLSL does not care about whether `q` is declared `inout` or not.
-//
-//cannot use a cap for struct with unequal target support
-//since it will propegate rules to children
+/// Note: The treatment of the `RayQuery` type in Slang does not
+/// perfectly match its semantics in vanilla HLSL in some corner
+/// cases. Specifically, a `RayQuery` in vanilla HLSL is an
+/// opaque handle to mutable storage, and assigning a `RayQuery`
+/// or passing one as a parameter will only copy the *handle*,
+/// potentially resulting in aliasing of the underlying mutable
+/// storage.
+///
+/// In contrast, Slang considers a `RayQuery` to own its mutable
+/// state, and (because the API does not support cloning of queries),
+/// `RayQuery` values are non-copyable (aka "move-only").
+///
+/// The main place where this arises as a consideration is when
+/// passing a `RayQuery` down into a function that will perform
+/// mutating operations on it (e.g., `TraceRay` or `Proceed`):
+/// ```
+/// void myFunc( inout RayQuery<FLAGS> q )
+/// {
+/// q.Proceed();
+/// }
+/// ```
+/// In Slang, a parameter like `q` above should be declared `inout`.
+/// HLSL does not care about whether `q` is declared `inout` or not.
+///
+///cannot use a cap for struct with unequal target support
+///since it will propegate rules to children
+/// @category raytracing Ray-tracing
__glsl_extension(GL_EXT_ray_query)
[__NonCopyableType]
__intrinsic_type($(kIROp_RayQueryType))
@@ -18182,6 +18573,7 @@ ${{{{
// SubpassInput
//
+/// @category stage_io
__magic_type(SubpassInputType)
__intrinsic_type($(kIROp_SubpassInputType))
[require(glsl_hlsl_spirv, subpass)]
@@ -18189,6 +18581,7 @@ struct __SubpassImpl<T, let isMS:int>
{
}
+/// @category stage_io
__generic<T = float4, let isMS:int=0>
typealias SubpassInput = __SubpassImpl<T, isMS>;
@@ -18216,6 +18609,7 @@ extension __SubpassImpl<T, 0>
}
}
+/// @category stage_io
__generic<T = float4, let isMS:int=1>
typealias SubpassInputMS = __SubpassImpl<T, isMS>;
@@ -18293,9 +18687,10 @@ __generic<Attributes>
__intrinsic_op($(kIROp_GetVulkanRayTracingPayloadLocation))
int __hitObjectAttributesLocation(__ref Attributes attributes);
- /// Immutable data type representing a ray hit or a miss. Can be used to invoke hit or miss shading,
- /// or as a key in ReorderThread. Created by one of several methods described below. HitObject
- /// and its related functions are available in raytracing shader types only.
+/// Immutable data type representing a ray hit or a miss. Can be used to invoke hit or miss shading,
+/// or as a key in ReorderThread. Created by one of several methods described below. HitObject
+/// and its related functions are available in raytracing shader types only.
+/// @category raytracing Ray-tracing
__glsl_extension(GL_NV_shader_invocation_reorder)
__glsl_extension(GL_EXT_ray_tracing)
[__NonCopyableType]
@@ -19959,6 +20354,7 @@ uint3 cudaBlockDim()
// (This fusion takes place in the fuse-satcoop pass, and as such any changes to
// the signature or behavior of this function should be adjusted for there).
//
+//@hidden:
[KnownBuiltin("saturated_cooperation")]
func saturated_cooperation<A : __BuiltinType, B, C>(
cooperate : functype (A, B) -> C,
@@ -20054,12 +20450,13 @@ ${
// for any resource type.
}
-__intrinsic_op($(kIROp_GetRegisterSpace)) uint __getRegisterSpace<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>(__TextureImpl<T,Shape,isArray,isMS,sampleCount,access,isShadow,isCombined,format> texture);
+__intrinsic_op($(kIROp_GetRegisterSpace)) uint __getRegisterSpace<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>(_Texture<T,Shape,isArray,isMS,sampleCount,access,isShadow,isCombined,format> texture);
__intrinsic_op($(kIROp_GetRegisterSpace)) uint __getRegisterSpace(SamplerState sampler);
-__intrinsic_op($(kIROp_GetRegisterIndex)) uint __getRegisterIndex<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>(__TextureImpl<T,Shape,isArray,isMS,sampleCount,access,isShadow,isCombined,format> texture);
+__intrinsic_op($(kIROp_GetRegisterIndex)) uint __getRegisterIndex<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>(_Texture<T,Shape,isArray,isMS,sampleCount,access,isShadow,isCombined,format> texture);
__intrinsic_op($(kIROp_GetRegisterIndex)) uint __getRegisterIndex(SamplerState sampler);
+//@public:
${{{{
//
@@ -20131,6 +20528,7 @@ vector<uint, ND> __textureFootprintGetOffset<let ND:int>(__TextureFootprintData<
}
}
+//@public:
__intrinsic_type($(kIROp_TextureFootprintType))
[require(glsl_hlsl_spirv, texturefootprint)]
struct __TextureFootprintData<let ND:int>
@@ -20218,6 +20616,7 @@ struct __TextureFootprintData<let ND:int>
}
}
+///@category stage_io
struct TextureFootprint<let ND:int> : __TextureFootprintData<ND>
{
bool _isSingleLevel;
@@ -20232,7 +20631,10 @@ struct TextureFootprint<let ND:int> : __TextureFootprintData<ND>
}
}
+///@category stage_io
typealias TextureFootprint2D = TextureFootprint<2>;
+
+///@category stage_io
typealias TextureFootprint3D = TextureFootprint<3>;
${
@@ -20242,7 +20644,7 @@ ${
}
__generic<T, Shape: __ITextureShape, let sampleCount:int, let isShadow:int, let format:int>
-extension __TextureImpl<T,Shape,0,0,sampleCount,0,isShadow,0,format>
+extension _Texture<T,Shape,0,0,sampleCount,0,isShadow,0,format>
{
${
// We introduce a few convenience type aliases here,
@@ -20842,10 +21244,9 @@ ${{{{
} // extension
-
//<T, Shape: __ITextureShape, let isArray:int, let isMS:int, let sampleCount:int, let access:int, let isShadow:int, let isCombined:int, let format:int>
__generic<Shape:__ITextureShape1D2D3D, let format : int>
-extension __TextureImpl<float, Shape, 0, 0, 0, $(kStdlibResourceAccessReadWrite), 0, 0, format>
+extension _Texture<float, Shape, 0, 0, 0, $(kStdlibResourceAccessReadWrite), 0, 0, format>
{
[__requiresNVAPI]
[ForceInline]
@@ -20876,6 +21277,8 @@ extension __TextureImpl<float, Shape, 0, 0, 0, $(kStdlibResourceAccessReadWrite)
// Buffer Pointer
+//@hidden:
+
namespace vk
{
// Partial implementation of the vk::buffer_ref proposal:
@@ -21025,7 +21428,7 @@ enum __DynamicResourceKind
}
__generic<T, Shape : __ITextureShape, let isArray : int, let isMS : int, let sampleCount : int, let access : int, let isShadow : int, let isCombined : int, let format : int>
-extension __TextureImpl<T, Shape, isArray, isMS, sampleCount, access, isShadow, isCombined, format> : __IDynamicResourceCastable<__DynamicResourceKind.General>
+extension _Texture<T, Shape, isArray, isMS, sampleCount, access, isShadow, isCombined, format> : __IDynamicResourceCastable<__DynamicResourceKind.General>
{
__intrinsic_op($(kIROp_CastDynamicResource))
__implicit_conversion($(kConversionCost_GenericParamUpcast))
diff --git a/source/slang/slang-ast-print.cpp b/source/slang/slang-ast-print.cpp
index f5f99f01d..f3ed4ee0b 100644
--- a/source/slang/slang-ast-print.cpp
+++ b/source/slang/slang-ast-print.cpp
@@ -1,6 +1,8 @@
// slang-ast-print.cpp
#include "slang-ast-print.h"
+#include "core/slang-char-util.h"
+
#include "slang-check-impl.h"
namespace Slang {
@@ -81,7 +83,11 @@ void ASTPrinter::addVal(Val* val)
}
else
{
- out << getText(decl->getName());
+ auto text = getText(decl->getName());
+ if (text.getLength() && !(CharUtil::isAlphaOrDigit(text[0]) || text[0] == '_'))
+ out << "operator" << text;
+ else
+ out << text;
}
}
@@ -140,6 +146,13 @@ void ASTPrinter::_addDeclPathRec(const DeclRef<Decl>& declRef, Index depth)
{
ExtensionDecl* extensionDecl = as<ExtensionDecl>(parentDeclRef.getDecl());
Type* type = extensionDecl->targetType.type;
+ if (m_optionFlags & OptionFlag::NoSpecializedExtensionTypeName)
+ {
+ if (auto unspecializedDeclRef = isDeclRefTypeOf<Decl>(type))
+ {
+ type = DeclRefType::create(m_astBuilder, unspecializedDeclRef.getDecl()->getDefaultDeclRef());
+ }
+ }
addType(type);
sb << toSlice(".");
}
diff --git a/source/slang/slang-ast-print.h b/source/slang/slang-ast-print.h
index 1b61a8904..0befc89d6 100644
--- a/source/slang/slang-ast-print.h
+++ b/source/slang/slang-ast-print.h
@@ -20,6 +20,11 @@ public:
ModuleName = 0x02, ///< Writes out module names
NoInternalKeywords = 0x04, ///< Omits internal decoration keywords (e.g. __target_intrinsic).
SimplifiedBuiltinType = 0x08, ///< Prints simplified builtin generic types (e.g. float3) instead of its generic form.
+
+ /// Use the original generic type name instead of the specialized
+ /// type name defined on an extension when
+ /// printing the target type of an extension decl.
+ NoSpecializedExtensionTypeName = 0x10,
};
};
diff --git a/source/slang/slang-capability.cpp b/source/slang/slang-capability.cpp
index 00a3b6001..bae5a1c72 100644
--- a/source/slang/slang-capability.cpp
+++ b/source/slang/slang-capability.cpp
@@ -568,6 +568,25 @@ void CapabilitySet::nonDestructiveJoin(const CapabilitySet& other)
}
}
+bool CapabilitySet::operator==(CapabilitySet const& that) const
+{
+ for (auto set : this->m_targetSets)
+ {
+ auto thatSet = that.m_targetSets.tryGetValue(set.first);
+ if (!thatSet)
+ return false;
+ for (auto stageSet : set.second.shaderStageSets)
+ {
+ auto thatStageSet = thatSet->shaderStageSets.tryGetValue(stageSet.first);
+ if (!thatStageSet)
+ return false;
+ if (stageSet.second.atomSet != thatStageSet->atomSet)
+ return false;
+ }
+ }
+ return true;
+}
+
CapabilitySet CapabilitySet::getTargetsThisHasButOtherDoesNot(const CapabilitySet& other)
{
CapabilitySet newSet{};
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 39d0df86b..980490df5 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -3272,6 +3272,7 @@ namespace Slang
SLANG_NO_THROW SlangResult SLANG_MCALL checkCompileTargetSupport(SlangCompileTarget target) override;
SLANG_NO_THROW SlangResult SLANG_MCALL checkPassThroughSupport(SlangPassThrough passThrough) override;
+ void writeStdlibDoc(String config);
SLANG_NO_THROW SlangResult SLANG_MCALL compileStdLib(slang::CompileStdLibFlags flags) override;
SLANG_NO_THROW SlangResult SLANG_MCALL loadStdLib(const void* stdLib, size_t stdLibSizeInBytes) override;
SLANG_NO_THROW SlangResult SLANG_MCALL saveStdLib(SlangArchiveType archiveType, ISlangBlob** outBlob) override;
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 23eba5f03..3f4376eb3 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -904,6 +904,9 @@ DIAGNOSTIC(-1, Note, reportCheckpointVariable, "$0 bytes ($1) used to checkpoint
DIAGNOSTIC(-1, Note, reportCheckpointCounter, "$0 bytes ($1) used for a loop counter here:")
DIAGNOSTIC(-1, Note, reportCheckpointNone, "no checkpoint contexts to report")
+// 9xxxx - Documentation generation
+DIAGNOSTIC(90001, Warning, ignoredDocumentationOnOverloadCandidate, "documentation comment on overload candidate '$0' is ignored")
+
//
// 8xxxx - Issues specific to a particular library/technology/platform/etc.
//
diff --git a/source/slang/slang-doc-ast.h b/source/slang/slang-doc-ast.h
index a0d5367af..fb5a08986 100644
--- a/source/slang/slang-doc-ast.h
+++ b/source/slang/slang-doc-ast.h
@@ -25,7 +25,7 @@ public:
Entry* getEntry(NodeBase* base);
/// Get list of all of the entries in source order
- const List<Entry>& getEntries() const { return m_entries; }
+ List<Entry>& getEntries() { return m_entries; }
/// Attaches the markup to the AST nodes.
void attachToAST();
diff --git a/source/slang/slang-doc-markdown-writer.cpp b/source/slang/slang-doc-markdown-writer.cpp
index e32a738c7..86cdb6d29 100644
--- a/source/slang/slang-doc-markdown-writer.cpp
+++ b/source/slang/slang-doc-markdown-writer.cpp
@@ -3,6 +3,8 @@
#include "../core/slang-string-util.h"
#include "../core/slang-type-text-util.h"
+#include "../core/slang-char-util.h"
+#include "../core/slang-token-reader.h"
#include "slang-ast-builder.h"
#include "slang-lookup.h"
@@ -25,15 +27,50 @@ static void _getDecls(ContainerDecl* containerDecl, List<T*>& out)
}
template <typename T>
-static void _getDeclsOfType(ContainerDecl* containerDecl, List<Decl*>& out)
+static void _getDeclsOfType(DocMarkdownWriter* writer, ContainerDecl* containerDecl, List<Decl*>& out)
{
for (Decl* decl : containerDecl->members)
{
if (as<T>(decl))
{
+ if (!writer->isVisible(decl))
+ continue;
out.add(decl);
}
+ else if (auto genericDecl = as<GenericDecl>(decl))
+ {
+ if (as<T>(genericDecl->inner))
+ {
+ if (!writer->isVisible(decl))
+ continue;
+ out.add(genericDecl);
+ }
+ }
+ }
+}
+
+template <typename T>
+static void _getDeclsOfType(DocMarkdownWriter* writer, DocumentPage* page, List<Decl*>& out)
+{
+ // Collect all decls of type T from all entries for the page.
+ List<Decl*> declList;
+ for (auto entry : page->entries)
+ {
+ _getDeclsOfType<T>(writer, as<ContainerDecl>(entry->m_node), declList);
+ }
+ // Deduplicate based on name.
+ Dictionary<Name*, Decl*> nameDict;
+ for (auto decl : declList)
+ {
+ nameDict[decl->getName()] = decl;
+ }
+ // Sort by name.
+ for (auto pair : nameDict)
+ {
+ if (pair.first)
+ out.add(pair.second);
}
+ out.sort([](Decl* a, Decl* b) -> bool { return getText(a->getName()) < getText(b->getName()); });
}
template <typename T>
@@ -54,61 +91,118 @@ static void _appendAsSingleLine(const UnownedStringSlice& in, StringBuilder& out
StringUtil::join(lines.getBuffer(), lines.getCount(), ' ', out);
}
-void DocMarkdownWriter::_appendAsBullets(const List<NameAndText>& values, char wrapChar)
+String getDocPath(const DocumentationConfig& config, String path)
+{
+ return config.rootDir + Path::getPathWithoutExt(path);
+}
+
+void DocMarkdownWriter::_appendAsBullets(const List<NameAndText>& values, bool insertLinkForName, char wrapChar)
{
- auto& out = m_builder;
+ auto& out = *m_builder;
for (const auto& value : values)
{
- out << "* ";
-
+ out << "#### ";
const String& name = value.name;
+ auto path = findLinkForToken(m_currentPage, name);
if (name.getLength())
{
if (wrapChar)
{
+ if (path.getLength())
+ {
+ out << "[";
+ }
out.appendChar(wrapChar);
out << name;
out.appendChar(wrapChar);
+ if (path.getLength())
+ {
+ out << "](" << getDocPath(m_config, path) << ")";
+ }
}
else
{
- out << name;
+ if (insertLinkForName)
+ out << translateToMarkdownWithLinks(name);
+ else
+ {
+ auto spaceLoc = name.indexOf(' ');
+ if (spaceLoc == -1)
+ out << escapeMarkdownText(name);
+ else
+ {
+ auto first = name.getUnownedSlice().head(spaceLoc);
+ auto rest = name.getUnownedSlice().tail(spaceLoc + 1);
+ out << escapeMarkdownText(first) << " ";
+ out << translateToMarkdownWithLinks(rest);
+ }
+ }
+ }
+ }
+ if (value.decl)
+ {
+ // Add anchor ID for the decl.
+ if (as<GenericTypeParamDeclBase>(value.decl))
+ {
+ out << " {#typeparam-" << getText(value.decl->getName()) << "}";
+ }
+ else
+ {
+ out << " {#decl-" << getText(value.decl->getName()) << "}";
}
}
-
if (value.text.getLength())
{
- out.appendChar(' ');
+ out.appendChar('\n');
- // Hmm, we'll want to make something multiline into a single line
- _appendAsSingleLine(value.text.getUnownedSlice(), out);
+ ParsedDescription desc;
+ desc.parse(value.text.getUnownedSlice());
+ desc.write(this, value.decl, out);
+ }
+ else
+ {
+ out << "\n";
}
-
- out << "\n";
}
}
void DocMarkdownWriter::_appendAsBullets(const List<String>& values, char wrapChar)
{
- auto& out = m_builder;
+ auto& out = *m_builder;
for (const auto& value : values)
{
out << "* ";
+ const String& name = value;
- if (value.getLength())
+ String path;
+ path = findLinkForToken(m_currentPage, name);
+ if (path.getLength() == 0)
+ {
+ Slang::Misc::TokenReader tokenReader(name);
+ if (!tokenReader.IsEnd())
+ path = findLinkForToken(m_currentPage, tokenReader.ReadToken().Content);
+ }
+ if (path.getLength())
+ {
+ out << "[";
+ }
+ if (name.getLength())
{
if (wrapChar)
{
out.appendChar(wrapChar);
- out << value;
+ out << escapeMarkdownText(name);
out.appendChar(wrapChar);
-
}
else
{
- out << value;
+ out << escapeMarkdownText(name);
}
}
+ if (path.getLength())
+ {
+ out << "](" << getDocPath(m_config, path) << ")";
+ }
out << "\n";
}
}
@@ -120,6 +214,93 @@ String DocMarkdownWriter::_getName(Decl* decl)
return buf.produceString();
}
+String DocMarkdownWriter::_getFullName(Decl* decl)
+{
+ ASTPrinter printer(m_astBuilder);
+ printer.addDeclPath(decl);
+ return printer.getStringBuilder().produceString();
+}
+
+String _translateNameToPath(const UnownedStringSlice& name)
+{
+ StringBuilder buf;
+ for (const char c : name)
+ {
+ // Removing leading underscores to prevent url issues.
+ if (c == '_' && buf.getLength() == 0)
+ continue;
+
+ if (c == ' ')
+ {
+ buf.appendChar('-');
+ }
+ else if (CharUtil::isAlphaOrDigit(c) || c == '_')
+ {
+ buf.appendChar(c);
+ }
+ else
+ {
+ buf.appendChar('x');
+ buf << String((int)c, 16);
+ }
+ }
+ return buf;
+}
+
+String DocMarkdownWriter::_getDocFilePath(Decl* decl)
+{
+ if (!decl)
+ return "";
+
+ StringBuilder sb;
+ if (as<NamespaceDeclBase>(getParentDecl(decl)))
+ {
+ if (as<InterfaceDecl>(decl))
+ {
+ sb << "interfaces/";
+ }
+ else if (as<AggTypeDeclBase>(decl) || as<TypeDefDecl>(decl))
+ {
+ sb << "types/";
+ }
+ else
+ {
+ sb << "global-decls/";
+ }
+ }
+
+ if (auto extDecl = as<ExtensionDecl>(decl))
+ {
+ if (auto declRef = isDeclRefTypeOf<Decl>(extDecl->targetType))
+ {
+ auto name = _translateNameToPath(_getName(declRef.getDecl()).getUnownedSlice());
+ sb << name;
+ sb << "/index.md";
+ return sb.produceString();
+ }
+ }
+ if (as<AggTypeDeclBase>(decl))
+ {
+ auto name = _translateNameToPath(_getName(decl).getUnownedSlice());
+ sb << name;
+ sb << "/index.md";
+ return sb.produceString();
+ }
+ auto parentPath = _getDocFilePath(getParentDecl(decl));
+ if (parentPath.endsWith(".md"))
+ {
+ parentPath = Path::getParentDirectory(parentPath);
+ }
+ if (parentPath.getLength() > 0)
+ {
+ sb << parentPath;
+ sb << "/";
+ }
+ sb << _translateNameToPath(_getName(decl).getUnownedSlice());
+ sb << ".md";
+ return sb.produceString();
+}
+
String DocMarkdownWriter::_getName(InheritanceDecl* decl)
{
StringBuilder buf;
@@ -132,12 +313,64 @@ DocMarkdownWriter::NameAndText DocMarkdownWriter::_getNameAndText(ASTMarkup::Ent
{
NameAndText nameAndText;
+ nameAndText.decl = decl;
nameAndText.name = _getName(decl);
-
- // We could extract different text here, but for now just do all markup
- if (entry)
+
+ StringBuilder sb;
+ if (auto varDeclBase = as<VarDeclBase>(decl))
+ {
+ sb << " : " << varDeclBase->type->toString();
+
+ if (varDeclBase->initExpr)
+ {
+ sb << " = ";
+ _appendExpr(sb, varDeclBase->initExpr);
+ }
+ }
+ else if (auto typeParam = as<GenericTypeParamDeclBase>(decl))
+ {
+ bool isFirst = true;
+ for (auto member : decl->parentDecl->members)
+ {
+ if (auto constraint = as<TypeConstraintDecl>(member))
+ {
+ if (isDeclRefTypeOf<Decl>(getSub(m_astBuilder, constraint)).getDecl() == typeParam)
+ {
+ if (isFirst)
+ {
+ sb << ": ";
+ isFirst = false;
+ }
+ else
+ {
+ sb << ", ";
+ }
+ sb << constraint->getSup().type->toString();
+ break;
+ }
+ }
+ }
+ if (auto genericTypeParam = as<GenericTypeParamDecl>(decl))
+ {
+ if (genericTypeParam->initType.type)
+ {
+ sb << " = ";
+ sb << genericTypeParam->initType.type->toString();
+ }
+ }
+ }
+ else if (auto enumCase = as<EnumCaseDecl>(decl))
+ {
+ if (enumCase->tagExpr)
+ {
+ sb << " = ";
+ _appendExpr(sb, enumCase->tagExpr);
+ }
+ }
+ nameAndText.name.append(sb.produceString());
+
+ if (entry && entry->m_markup.getLength())
{
- // For now we'll just use all markup, but really we need something more sophisticated here
nameAndText.text = entry->m_markup;
}
@@ -172,21 +405,22 @@ List<String> DocMarkdownWriter::_getAsStringList(const List<Decl*>& in)
void DocMarkdownWriter::_appendCommaList(const List<String>& strings, char wrapChar)
{
+ auto& out = *m_builder;
for (Index i = 0; i < strings.getCount(); ++i)
{
if (i > 0)
{
- m_builder << toSlice(", ");
+ out << toSlice(", ");
}
if (wrapChar)
{
- m_builder.appendChar(wrapChar);
- m_builder << strings[i];
- m_builder.appendChar(wrapChar);
+ out.appendChar(wrapChar);
+ out << strings[i];
+ out.appendChar(wrapChar);
}
else
{
- m_builder << strings[i];
+ out << translateToMarkdownWithLinks(strings[i]);
}
}
}
@@ -242,35 +476,276 @@ void DocMarkdownWriter::_appendCommaList(const List<String>& strings, char wrapC
}
}
+void escapeHTMLContent(StringBuilder& sb, UnownedStringSlice str)
+{
+ for (auto ch : str)
+ {
+ switch (ch)
+ {
+ case '<': sb << "&lt;"; break;
+ case '>': sb << "&gt;"; break;
+ case '&': sb << "&amp;"; break;
+ case '"': sb << "&quot;"; break;
+ default: sb.appendChar(ch); break;
+ }
+ }
+}
+
void DocMarkdownWriter::writeVar(const ASTMarkup::Entry& entry, VarDecl* varDecl)
{
- writePreamble(entry);
- auto& out = m_builder;
+ auto& out = *m_builder;
+
+ ASTPrinter printer(m_astBuilder);
+ printer.addDeclPath(DeclRef<Decl>(varDecl));
+
+ out << toSlice("# ") << printer.getSlice() << toSlice("\n\n");
+
+ DeclDocumentation declDoc;
+ declDoc.parse(entry.m_markup.getUnownedSlice());
+ declDoc.writeDescription(out, this, varDecl);
+ registerCategory(m_currentPage, declDoc);
+
+ out << toSlice("## Signature\n");
+ out << toSlice("<pre>\n");
+ if (varDecl->hasModifier<HLSLStaticModifier>())
+ {
+ out << toSlice("<span class='code_keyword'>static</span> ");
+ }
+ if (varDecl->hasModifier<ConstModifier>())
+ {
+ out << toSlice("<span class='code_keyword'>const</span> ");
+ }
+ if (varDecl->hasModifier<ConstExprModifier>())
+ {
+ out << toSlice("<span class='code_keyword'>constexpr</span> ");
+ }
+ if (varDecl->hasModifier<InModifier>())
+ {
+ out << toSlice("<span class='code_keyword'>in</span> ");
+ }
+ if (varDecl->hasModifier<OutModifier>())
+ {
+ out << toSlice("<span class='code_keyword'>out</span> ");
+ }
+ StringBuilder typeSB;
+ varDecl->type->toText(typeSB);
+ out << translateToHTMLWithLinks(varDecl, typeSB.produceString()) << toSlice(" ");
+ out << translateToHTMLWithLinks(varDecl, printer.getSlice());
+
+ if (varDecl->initExpr)
+ {
+ out << toSlice(" = ");
+ _appendExpr(out, varDecl->initExpr);
+ }
+
+ out << toSlice(";\n</pre>\n\n");
+
+ declDoc.writeSection(out, this, varDecl, DocPageSection::Remarks);
+ declDoc.writeSection(out, this, varDecl, DocPageSection::Example);
+ declDoc.writeSection(out, this, varDecl, DocPageSection::SeeAlso);
+}
+
+void DocMarkdownWriter::writeProperty(const ASTMarkup::Entry& entry, PropertyDecl* propertyDecl)
+{
+ auto& out = *m_builder;
+ out << toSlice("# property ");
+
+ ASTPrinter printer(m_astBuilder);
+ printer.addDeclPath(DeclRef<Decl>(propertyDecl));
+ out << escapeMarkdownText(printer.getSlice()) << toSlice("\n\n");
+
+ DeclDocumentation declDoc;
+ declDoc.parse(entry.m_markup.getUnownedSlice());
+ declDoc.writeDescription(out, this, propertyDecl);
+ registerCategory(m_currentPage, declDoc);
+
+ out << toSlice("## Signature\n\n");
+
+ out << toSlice("<pre>\n<span class='code_keyword'>property</span> ");
+ out << translateToHTMLWithLinks(propertyDecl, printer.getSlice());
+ out << toSlice(" : ");
+ StringBuilder typeSB;
+ propertyDecl->type->toText(typeSB);
+ out << translateToHTMLWithLinks(propertyDecl, typeSB.produceString());
+ out << "\n{\n";
+ for (auto member : propertyDecl->members)
+ {
+ if (as<GetterDecl>(member))
+ {
+ out << " get;\n";
+ }
+ else if (as<SetterDecl>(member))
+ {
+ out << " set;\n";
+ }
+ else if (as<RefAccessorDecl>(member))
+ {
+ out << " ref;\n";
+ }
+ }
+ out << "}\n</pre>\n\n";
+
+ declDoc.writeSection(out, this, propertyDecl, DocPageSection::ReturnInfo);
+ declDoc.writeSection(out, this, propertyDecl, DocPageSection::Remarks);
+ declDoc.writeSection(out, this, propertyDecl, DocPageSection::Example);
+ declDoc.writeSection(out, this, propertyDecl, DocPageSection::SeeAlso);
+}
+
+void DocMarkdownWriter::writeTypeDef(const ASTMarkup::Entry& entry, TypeDefDecl* typeDefDecl)
+{
+ auto& out = *m_builder;
+
+ out << toSlice("# ");
+ ASTMarkup::Entry newEntry = entry;
+ _appendAggTypeName(newEntry, typeDefDecl);
+ out << toSlice("\n\n");
+
+ DeclDocumentation declDoc;
+ declDoc.parse(entry.m_markup.getUnownedSlice());
+ registerCategory(m_currentPage, declDoc);
+
+ declDoc.writeDescription(out, this, typeDefDecl);
+
+ out << toSlice("## Signature\n\n");
+
+ out << toSlice("<pre>\n<span class='code_keyword'>typealias</span> ");
+ ASTPrinter printer(m_astBuilder);
+ printer.addDeclPath(typeDefDecl);
+ out << translateToHTMLWithLinks(typeDefDecl, printer.getSlice());
+ out << toSlice(" = ");
+
+ // Insert a line break if the type name is already long.
+ if (printer.getSlice().getLength() > 25)
+ {
+ out << "\n ";
+ }
+ out << translateToHTMLWithLinks(typeDefDecl, typeDefDecl->type->toString());
+ out << ";\n</pre>\n\n";
+
+ declDoc.writeGenericParameters(out, this, typeDefDecl);
+
+ declDoc.writeSection(out, this, typeDefDecl, DocPageSection::Remarks);
+ declDoc.writeSection(out, this, typeDefDecl, DocPageSection::Example);
+ declDoc.writeSection(out, this, typeDefDecl, DocPageSection::SeeAlso);
+}
+
+void DocMarkdownWriter::writeExtensionConditions(StringBuilder& out, ExtensionDecl* extensionDecl, const char* prefix, bool isHtml)
+{
+ // Synthesize `where` clause for things defined in an extension.
+ auto targetTypeDeclRef = isDeclRefTypeOf<ContainerDecl>(extensionDecl->targetType);
+ if (!targetTypeDeclRef)
+ return;
- out << toSlice("# ") << varDecl->getName()->text << toSlice("\n\n");
+ if (auto genAppDeclRef = as<GenericAppDeclRef>(targetTypeDeclRef.declRefBase))
+ {
+ for (Index i = 0; i < genAppDeclRef->getArgCount(); i++)
+ {
+ auto arg = genAppDeclRef->getArg(i);
+ Decl* genericParamDecl = nullptr;
+ Index parameterIndex = i;
+ if (auto extTypeParamDecl = isDeclRefTypeOf<GenericTypeParamDeclBase>(arg))
+ {
+ genericParamDecl = extTypeParamDecl.getDecl();
+ }
+ else if (auto extValueParamVal = as<GenericParamIntVal>(arg))
+ {
+ genericParamDecl = extValueParamVal->getDeclRef().getDecl();
+ }
- // TODO(JS): The outputting of types this way isn't right - it doesn't handle int a[10] for example.
- //ASTPrinter printer(m_astBuilder, ASTPrinter::OptionFlag::ParamNames);
+ // Locate the original generic parameter defined on the type being extended.
+ Decl* originalParamDecl = nullptr;
+ if (auto targetTypeParentGenericDecl = as<GenericDecl>(targetTypeDeclRef.getDecl()->parentDecl))
+ {
+ for (auto member : targetTypeParentGenericDecl->members)
+ {
+ if (auto typeParamDecl = as<GenericTypeParamDeclBase>(member))
+ {
+ if (typeParamDecl->parameterIndex == parameterIndex)
+ {
+ originalParamDecl = typeParamDecl;
+ break;
+ }
+ }
+ else if (auto valParamDecl = as<GenericValueParamDecl>(member))
+ {
+ if (valParamDecl->parameterIndex == parameterIndex)
+ {
+ originalParamDecl = valParamDecl;
+ break;
+ }
+ }
+ }
+ }
- out << toSlice("```\n");
- out << varDecl->type << toSlice(" ") << varDecl << toSlice("\n");
- out << toSlice("```\n\n");
+ // If we can't find such parameter, bail.
+ if (!originalParamDecl)
+ continue;
+
+ bool isEqualityConstraint = false;
+ Val* constraintVal = nullptr;
+ if (genericParamDecl)
+ {
+ // If we have `TargetType<T>` the member belongs to `extension<X : C> TargetType<X>`,
+ // We want to print a synthesized `where T : C` clause.
+ // Here `extTypeParamDecl` is a reference to `X`, so we need to find the corresponding `T`.
- writeDescription(entry);
+ // Find constraints on the originalParamDecl.
+ for (auto member : genericParamDecl->parentDecl->members)
+ {
+ if (auto typeConstraint = as<GenericTypeConstraintDecl>(member))
+ {
+ if (isDeclRefTypeOf<Decl>(typeConstraint->sub.type).getDecl() == genericParamDecl)
+ {
+ if (typeConstraint->isEqualityConstraint)
+ {
+ isEqualityConstraint = true;
+ }
+ constraintVal = typeConstraint->getSup().type;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // If we have `extension TargetType<Y>` where `Y` does not name a generic parameter defined
+ // on the extension itself, we want to print a synthesized `where T == Y` clause, where
+ // `T` is the original generic parameter on the target type.
+ isEqualityConstraint = true;
+ constraintVal = arg;
+ }
+ if (constraintVal)
+ {
+ out << prefix;
+ if (isHtml)
+ out << translateToHTMLWithLinks(originalParamDecl, originalParamDecl->getName()->text);
+ else
+ out << translateToMarkdownWithLinks(originalParamDecl->getName()->text);
+ if (isEqualityConstraint)
+ out << " == ";
+ else
+ out << " : ";
+ if (isHtml)
+ out << translateToHTMLWithLinks(originalParamDecl, constraintVal->toString());
+ else
+ out << translateToMarkdownWithLinks(constraintVal->toString());
+ }
+ }
+ }
}
void DocMarkdownWriter::writeSignature(CallableDecl* callableDecl)
{
- auto& out = m_builder;
+ StringBuilder& out = *getBuilder(callableDecl);
if (callableDecl->hasModifier<HLSLStaticModifier>())
{
- out << "static ";
+ out << "<span class='code_keyword'>static</span> ";
}
List<ASTPrinter::Part> parts;
- ASTPrinter printer(m_astBuilder, ASTPrinter::OptionFlag::ParamNames, &parts);
+ ASTPrinter printer(m_astBuilder, ASTPrinter::OptionFlag::ParamNames | ASTPrinter::OptionFlag::NoSpecializedExtensionTypeName, &parts);
printer.addDeclSignature(makeDeclRef(callableDecl));
Signature signature;
@@ -283,52 +758,34 @@ void DocMarkdownWriter::writeSignature(CallableDecl* callableDecl)
const UnownedStringSlice returnType = printer.getPartSlice(signature.returnType);
if (returnType.getLength() > 0)
{
- out << returnType << toSlice(" ");
+ out << translateToHTMLWithLinks(callableDecl, returnType) << toSlice(" ");
}
}
- out << printer.getPartSlice(signature.name);
-
-#if 0
- if (signature.genericParams.getCount())
- {
- out << toSlice("<");
- const Index count = signature.genericParams.getCount();
- for (Index i = 0; i < count; ++i)
- {
- const auto& genericParam = signature.genericParams[i];
- if (i > 0)
- {
- out << toSlice(", ");
- }
- out << printer.getPartSlice(genericParam.name);
-
- if (genericParam.type.type != Part::Type::None)
- {
- out << toSlice(" : ");
- out << printer.getPartSlice(genericParam.type);
- }
- }
- out << toSlice(">");
- }
-#endif
+ out << translateToHTMLWithLinks(callableDecl, printer.getPartSlice(signature.name));
switch (paramCount)
{
case 0:
{
// Has no parameters
- out << toSlice("();\n");
+ out << toSlice("()");
break;
}
case 1:
{
- // Place all on single line
- out.appendChar('(');
- const auto& param = signature.params[0];
- out << printer.getPartSlice(param.first) << toSlice(" ") << printer.getPartSlice(param.second);
- out << ");\n";
- break;
+ if (signature.name.end - signature.name.start < 40)
+ {
+ // Place all on single line
+ out.appendChar('(');
+ const auto& param = signature.params[0];
+ out << translateToHTMLWithLinks(callableDecl, printer.getPartSlice(param.first)) << toSlice(" ");
+ out << translateToHTMLWithLinks(callableDecl, printer.getPartSlice(param.second));
+ out << ")";
+ break;
+ }
+ // If the name is already long, fall through to default.
+ [[fallthrough]];
}
default:
{
@@ -339,20 +796,11 @@ void DocMarkdownWriter::writeSignature(CallableDecl* callableDecl)
{
const auto& param = signature.params[i];
line.clear();
- // If we want to tab these over... we'll need to know how must space I have
- line << " " << printer.getPartSlice(param.first);
- Index indent = 25;
- if (line.getLength() < indent)
- {
- line.appendRepeatedChar(' ', indent - line.getLength());
- }
- else
- {
- line.appendChar(' ');
- }
+ line << " " << translateToHTMLWithLinks(callableDecl, printer.getPartSlice(param.first));
- line << printer.getPartSlice(param.second);
+ line.appendChar(' ');
+ line << translateToHTMLWithLinks(callableDecl, printer.getPartSlice(param.second));
if (i < paramCount - 1)
{
line << ",\n";
@@ -361,17 +809,53 @@ void DocMarkdownWriter::writeSignature(CallableDecl* callableDecl)
out << line;
}
- out << ");\n";
+ out << ")";
break;
}
}
+
+ // Print `where` clause.
+ Decl* parentDecl = callableDecl;
+ while (parentDecl)
+ {
+ if (auto extensionDecl = as<ExtensionDecl>(parentDecl))
+ {
+ // Synthesize `where` clause for things defined in an extension.
+ if (auto targetTypeDeclRef = isDeclRefTypeOf<ContainerDecl>(extensionDecl->targetType))
+ {
+ writeExtensionConditions(out, extensionDecl, "\n <span class='code_keyword'>where</span> ", true);
+ // We need to follow the parent of the target type instead of the parent of the extension decl.
+ parentDecl = getParentDecl(targetTypeDeclRef.getDecl());
+ continue;
+ }
+ }
+
+ if (auto genericParent = as<GenericDecl>(parentDecl->parentDecl))
+ {
+ for (auto member : genericParent->members)
+ {
+ if (auto typeConstraint = as<GenericTypeConstraintDecl>(member))
+ {
+ out << toSlice("\n <span class='code_keyword'>where</span> ");
+ out << translateToHTMLWithLinks(parentDecl, getSub(m_astBuilder, typeConstraint)->toString());
+ if (typeConstraint->isEqualityConstraint)
+ out << " == ";
+ else
+ out << toSlice(" : ");
+ out << translateToHTMLWithLinks(parentDecl, getSup(m_astBuilder, typeConstraint)->toString());
+ }
+ }
+ }
+ parentDecl = getParentDecl(parentDecl);
+ }
+ out << ";\n";
}
-List<DocMarkdownWriter::NameAndText> DocMarkdownWriter::_getUniqueParams(const List<Decl*>& decls)
+List<DocMarkdownWriter::NameAndText> DocMarkdownWriter::_getUniqueParams(const List<Decl*>& decls, DeclDocumentation* funcDoc)
{
List<NameAndText> out;
- Dictionary<Name*, Index> nameDict;
+ Dictionary<String, Index> nameDict;
for (auto decl : decls)
{
@@ -380,231 +864,187 @@ List<DocMarkdownWriter::NameAndText> DocMarkdownWriter::_getUniqueParams(const L
{
continue;
}
-
- Index index = nameDict.getOrAddValue(name, out.getCount());
+ auto nameText = _getNameAndText(decl);
+ Index index = nameDict.getOrAddValue(nameText.name, out.getCount());
if (index >= out.getCount())
{
- out.add(NameAndText{ getText(name), String() });
+ out.add(nameText);
}
+ // Extract text.
NameAndText& nameAndMarkup = out[index];
if (nameAndMarkup.text.getLength() > 0)
{
continue;
}
- auto entry = m_markup->getEntry(decl);
- if (entry && entry->m_markup.getLength())
+ ParamDocumentation paramDoc;
+ if (funcDoc->parameters.tryGetValue(getText(name), paramDoc))
{
- nameAndMarkup.text = entry->m_markup;
+ StringBuilder sb;
+ if (paramDoc.direction.getLength())
+ sb << "\\[" << paramDoc.direction << "\\] ";
+ sb << paramDoc.description.ownedText;
+ nameAndMarkup.text = sb.produceString();
+ }
+ else
+ {
+ auto entry = m_markup->getEntry(decl);
+ if (entry && entry->m_markup.getLength())
+ {
+ nameAndMarkup.text = entry->m_markup;
+ }
}
}
return out;
}
-static void _addRequirement(const DocMarkdownWriter::Requirement& req, List<DocMarkdownWriter::Requirement>& ioReqs)
+static Index _addRequirement(const DocMarkdownWriter::Requirement& req, List<DocMarkdownWriter::Requirement>& ioReqs)
{
- if (ioReqs.indexOf(req) < 0)
+ auto index = ioReqs.indexOf(req);
+ if (index < 0)
{
ioReqs.add(req);
+ return ioReqs.getCount() - 1;
}
+ return index;
}
-static void _addRequirement(CodeGenTarget target, const String& value, List<DocMarkdownWriter::Requirement>& ioReqs)
+static Index _addRequirement(CapabilitySet set, List<DocMarkdownWriter::Requirement>& ioReqs)
{
- _addRequirement(DocMarkdownWriter::Requirement{ target, value }, ioReqs);
+ return _addRequirement(DocMarkdownWriter::Requirement{ set }, ioReqs);
}
-static DocMarkdownWriter::Requirement _getRequirementFromTargetToken(const Token& tok)
+static Index _addRequirements(Decl* decl, List<DocMarkdownWriter::Requirement>& ioReqs)
{
- typedef DocMarkdownWriter::Requirement Requirement;
-
- if (tok.type == TokenType::Unknown)
- {
- return Requirement{ CodeGenTarget::None, String() };
- }
-
- auto targetName = tok.getContent();
- if (targetName == "spirv")
- {
- return Requirement{CodeGenTarget::SPIRV, UnownedStringSlice("")};
- }
-
- const CapabilityAtom targetCap = asAtom(findCapabilityName(targetName));
-
- if (targetCap == CapabilityAtom::Invalid)
- {
- return Requirement{ CodeGenTarget::None, String() };
- }
- SLANG_ASSERT(targetCap < CapabilityAtom::Count);
-
- static const CapabilityAtom rootAtoms[] =
- {
- CapabilityAtom::glsl,
- CapabilityAtom::hlsl,
- CapabilityAtom::cuda,
- CapabilityAtom::cpp,
- CapabilityAtom::c,
- };
-
- for (auto rootAtom : rootAtoms)
- {
- if (rootAtom == targetCap)
- {
- // If its one of the roots we don't need to store the name
- targetName = UnownedStringSlice();
- break;
- }
- }
+ StringBuilder buf;
- if (isCapabilityDerivedFrom(targetCap, CapabilityAtom::glsl))
- {
- return Requirement{CodeGenTarget::GLSL, targetName};
- }
- else if (isCapabilityDerivedFrom(targetCap, CapabilityAtom::hlsl))
- {
- return Requirement{ CodeGenTarget::HLSL, targetName };
- }
- else if (isCapabilityDerivedFrom(targetCap, CapabilityAtom::cuda))
- {
- return Requirement{ CodeGenTarget::CUDASource, targetName };
- }
- else if (isCapabilityDerivedFrom(targetCap, CapabilityAtom::cpp))
- {
- return Requirement{ CodeGenTarget::CPPSource, targetName };
- }
- else if (isCapabilityDerivedFrom(targetCap, CapabilityAtom::c))
- {
- return Requirement{ CodeGenTarget::CSource, targetName };
- }
- else if (isCapabilityDerivedFrom(targetCap, CapabilityAtom::metal))
- {
- return Requirement{ CodeGenTarget::Metal, targetName };
- }
- else if (isCapabilityDerivedFrom(targetCap, CapabilityAtom::wgsl))
+ if (auto capAttr = decl->findModifier<RequireCapabilityAttribute>())
{
- return Requirement{ CodeGenTarget::WGSL, targetName };
+ return _addRequirement(capAttr->capabilitySet, ioReqs);
}
- return Requirement{ CodeGenTarget::Unknown, String() };
+ return -1;
}
-static void _addRequirementFromTargetToken(const Token& tok, List<DocMarkdownWriter::Requirement>& ioReqs)
+static String getCapabilityName(CapabilityName name)
{
- auto req = _getRequirementFromTargetToken(tok);
- if (req.target != CodeGenTarget::None)
+ auto text = capabilityNameToString(name);
+ if (text.startsWith("_"))
{
- _addRequirement(req, ioReqs);
+ return text.tail(1);
}
+ return text;
}
-static void _addRequirements(Decl* decl, List<DocMarkdownWriter::Requirement>& ioReqs)
+static String getCapabilityName(CapabilityAtom atom)
{
- StringBuilder buf;
-
- if (auto spirvRequiredModifier = decl->findModifier<RequiredSPIRVVersionModifier>())
- {
- buf.clear();
- buf << "SPIR-V ";
- spirvRequiredModifier->version.append(buf);
- _addRequirement(CodeGenTarget::GLSL, buf, ioReqs);
- }
-
- if (auto glslRequiredModifier = decl->findModifier<RequiredGLSLVersionModifier>())
- {
- buf.clear();
- buf << "GLSL" << glslRequiredModifier->versionNumberToken.getContent();
- _addRequirement(CodeGenTarget::GLSL, buf, ioReqs);
- }
-
- if (auto cudaSMVersionModifier = decl->findModifier<RequiredCUDASMVersionModifier>())
- {
- buf.clear();
- buf << "SM ";
- cudaSMVersionModifier->version.append(buf);
- _addRequirement(CodeGenTarget::CUDASource, buf, ioReqs);
- }
-
- if (auto extensionModifier = decl->findModifier<RequiredGLSLExtensionModifier>())
- {
- buf.clear();
- buf << extensionModifier->extensionNameToken.getContent();
- _addRequirement(CodeGenTarget::GLSL, buf, ioReqs);
- }
+ return getCapabilityName((CapabilityName)atom);
+}
- if (const auto requiresNVAPIAttribute = decl->findModifier<RequiresNVAPIAttribute>())
+void DocMarkdownWriter::_appendExpr(StringBuilder& sb, Expr* expr)
+{
+ if (auto typeCast = as<TypeCastExpr>(expr))
+ _appendExpr(sb, typeCast->arguments[0]);
+ else if (auto declRefExpr = as<DeclRefExpr>(expr))
{
- _addRequirement(CodeGenTarget::HLSL, "NVAPI", ioReqs);
+ ASTPrinter printer(m_astBuilder);
+ printer.addDeclPath(declRefExpr->declRef);
+ sb << escapeMarkdownText(printer.getSlice());
}
-
- for (auto targetIntrinsic : decl->getModifiersOfType<TargetIntrinsicModifier>())
+ else if (auto litExpr = as<LiteralExpr>(expr))
{
- _addRequirementFromTargetToken(targetIntrinsic->targetToken, ioReqs);
+ sb << litExpr->token.getContent();
}
- for (auto specializedForTarget : decl->getModifiersOfType<SpecializedForTargetModifier>())
+ else
{
- _addRequirementFromTargetToken(specializedForTarget->targetToken, ioReqs);
+ sb << "...";
}
}
-void DocMarkdownWriter::_writeTargetRequirements(const Requirement* reqs, Index reqsCount)
+void DocMarkdownWriter::_appendRequirements(const Requirement& requirement)
{
- if (reqsCount == 0)
+ auto capabilitySet = requirement.capabilitySet;
+ m_builder->append("Defined for the following targets:\n\n");
+ for (auto targetSet : capabilitySet.getCapabilityTargetSets())
{
- return;
- }
-
- auto& out = m_builder;
-
- // Okay we need the name of the CodeGen target
- UnownedStringSlice name = TypeTextUtil::getCompileTargetName(SlangCompileTarget(reqs->target));
+ m_builder->append("#### ");
+ m_builder->append(getCapabilityName(targetSet.first));
+ m_builder->append("\n");
- out << toSlice("**") << String(name).toUpper() << toSlice("**");
-
- if (!(reqsCount == 1 && reqs[0].value.getLength() == 0))
- {
- // Put in a list so we can use convenience funcs
- List<String> values;
- for (Index i = 0; i < reqsCount; i++)
+ if (targetSet.second.shaderStageSets.getCount() == kCapabilityStageCount)
{
- if (reqs[i].value.getLength() > 0)
+ m_builder->append("Available in all stages.\n");
+ }
+ else if (targetSet.second.shaderStageSets.getCount() > 1)
+ {
+ m_builder->append("Available in stages: ");
+ bool isFirst = true;
+ for (auto& stage : targetSet.second.shaderStageSets)
{
- values.add(reqs[i].value);
+ if (!isFirst)
+ {
+ m_builder->append(", ");
+ }
+ isFirst = false;
+ m_builder->append("`");
+ m_builder->append(getCapabilityName(stage.first));
+ m_builder->append("`");
}
+ m_builder->append(".\n");
+ }
+ else if (targetSet.second.shaderStageSets.getCount() == 1)
+ {
+ m_builder->append("Available in `");
+ m_builder->append(getCapabilityName(targetSet.second.shaderStageSets.begin()->first));
+ m_builder->append("` stage only.\n");
}
- out << toSlice(" ");
- _appendCommaList(values, '`');
- }
-
- out << toSlice(" ");
-}
-
-void DocMarkdownWriter::_appendRequirements(const List<Requirement>& requirements)
-{
- Index startIndex = 0;
- CodeGenTarget curTarget = CodeGenTarget::None;
-
- for (Index i = 0; i < requirements.getCount(); ++i)
- {
- const auto& req = requirements[i];
+ m_builder->append("\n");
- if (req.target != curTarget)
+ // TODO: We should probably print the capabilities for each stage set if the requirements differ between
+ // different stages, but for now we'll just print the first one, assuming the rest are the same.
+ // This is currently true for most if not all of our stdlib decls.
+ //
+ if (targetSet.second.shaderStageSets.getCount() > 0 &&
+ targetSet.second.shaderStageSets.begin()->second.atomSet.has_value())
{
- _writeTargetRequirements(requirements.getBuffer() + startIndex, i - startIndex);
-
- startIndex = i;
- curTarget = req.target;
+ List<String> capabilities;
+ auto atomSet = targetSet.second.shaderStageSets.begin()->second.atomSet.value().newSetWithoutImpliedAtoms();
+ for (auto atom : atomSet)
+ {
+ // If the requirement atom is the target or stage atom, don't repeat ourselves.
+ if ((CapabilityAtom)atom == targetSet.first)
+ continue;
+ if ((CapabilityAtom)atom == targetSet.second.shaderStageSets.begin()->first)
+ continue;
+ String capabilityName = capabilityNameToString((CapabilityName)atom);
+ if (!capabilityName.startsWith("_"))
+ {
+ capabilities.add(capabilityName);
+ }
+ }
+ if (capabilities.getCount() > 1)
+ {
+ m_builder->append("Requires capabilities: ");
+ _appendCommaList(capabilities, '`');
+ m_builder->append(".\n");
+ }
+ else if (capabilities.getCount() == 1)
+ {
+ m_builder->append("Requires capability: `");
+ m_builder->append(capabilities[0]);
+ m_builder->append("`");
+ m_builder->append(".\n");
+ }
}
}
-
- _writeTargetRequirements(requirements.getBuffer() + startIndex, requirements.getCount() - startIndex);
}
-void DocMarkdownWriter::_maybeAppendRequirements(const UnownedStringSlice& title, const List<List<DocMarkdownWriter::Requirement>>& uniqueRequirements)
+void DocMarkdownWriter::_maybeAppendRequirements(const UnownedStringSlice& title, const List<DocMarkdownWriter::Requirement>& uniqueRequirements)
{
- auto& out = m_builder;
+ auto& out = *m_builder;
const Index uniqueCount = uniqueRequirements.getCount();
if (uniqueCount <= 0)
@@ -616,12 +1056,6 @@ void DocMarkdownWriter::_maybeAppendRequirements(const UnownedStringSlice& title
{
const auto& reqs = uniqueRequirements[0];
- // If just HLSL on own, then ignore
- if (reqs.getCount() == 0 || (reqs.getCount() == 1 && reqs[0] == Requirement{ CodeGenTarget::HLSL, String() }))
- {
- return;
- }
-
out << title;
_appendRequirements(reqs);
@@ -633,7 +1067,7 @@ void DocMarkdownWriter::_maybeAppendRequirements(const UnownedStringSlice& title
for (Index i = 0; i < uniqueCount; ++i)
{
- out << (i + 1) << (". ");
+ out << "### Capability Set " << (i + 1) << ("\n\n");
_appendRequirements(uniqueRequirements[i]);
out << toSlice("\n");
}
@@ -642,39 +1076,16 @@ void DocMarkdownWriter::_maybeAppendRequirements(const UnownedStringSlice& title
out << toSlice("\n");
}
-static Decl* _getSameNameDecl(Decl* decl)
+static Decl* _getSameNameDecl(ContainerDecl* parentDecl, Decl* decl)
{
- auto parentDecl = decl->parentDecl;
-
- // Sanity check: there should always be a parent declaration.
- //
- SLANG_ASSERT(parentDecl);
- if (!parentDecl) return nullptr;
-
- // If the declaration is the "inner" declaration of a generic,
- // then we actually want to look one level up, because the
- // peers/siblings of the declaration will belong to the same
- // parent as the generic, not to the generic.
- //
- if (auto genericParentDecl = as<GenericDecl>(parentDecl))
- {
- // Note: we need to check here to be sure `newDecl`
- // is the "inner" declaration and not one of the
- // generic parameters, or else we will end up
- // checking them at the wrong scope.
- //
- if (decl == genericParentDecl->inner)
- {
- decl = parentDecl;
- }
- }
-
- return decl;
+ Decl* result = nullptr;
+ parentDecl->getMemberDictionary().tryGetValue(decl->getName(), result);
+ return result;
}
static bool _isFirstOverridden(Decl* decl)
{
- decl = _getSameNameDecl(decl);
+ decl = _getSameNameDecl(as<ContainerDecl>(getParentDecl(decl)), decl);
ContainerDecl* parentDecl = decl->parentDecl;
@@ -688,47 +1099,291 @@ static bool _isFirstOverridden(Decl* decl)
return false;
}
-void DocMarkdownWriter::writeCallableOverridable(const ASTMarkup::Entry& entry, CallableDecl* callableDecl)
+void ParsedDescription::write(DocMarkdownWriter* writer, Decl* decl, StringBuilder& out)
{
- auto& out = m_builder;
-
- writePreamble(entry);
-
+ for (auto span : spans)
{
- // Output the overridable path (ie without terminal generic parameters)
- ASTPrinter printer(m_astBuilder);
- printer.addOverridableDeclPath(DeclRef<Decl>(callableDecl));
- // Extract the name
- out << toSlice("# `") << printer.getStringBuilder() << toSlice("`\n\n");
+ switch (span.kind)
+ {
+ case DocumentationSpanKind::OrdinaryText:
+ {
+ out << span.text;
+ break;
+ }
+ case DocumentationSpanKind::InlineCode:
+ {
+ out << "<span class='code'>" << writer->translateToHTMLWithLinks(decl, span.text) << "</span>";
+ break;
+ }
+ }
}
+}
- writeDescription(entry);
-
- List<CallableDecl*> sigs;
+void ParsedDescription::parse(UnownedStringSlice text)
+{
+ text = text.trim();
+ ownedText = text;
+ List<UnownedStringSlice> lines;
+ StringUtil::calcLines(text, lines);
+ bool isInCodeBlock = false;
+ for (auto line : lines)
{
- Decl* sameNameDecl = _getSameNameDecl(callableDecl);
+ line = line.trim();
+ if (line.startsWith("```"))
+ {
+ isInCodeBlock = !isInCodeBlock;
+ spans.add({ line, DocumentationSpanKind::OrdinaryText});
+ spans.add({ toSlice("\n"), DocumentationSpanKind::OrdinaryText });
+ continue;
+ }
+
+ if (!isInCodeBlock)
+ {
+ bool isInCode = false;
+ const char* currentSpanStart = line.begin();
+ const char* currentSpanEnd = currentSpanStart;
+ for (Index i = 0; i < line.getLength(); i++)
+ {
+ if (line[i] == '`')
+ {
+ if (currentSpanEnd > currentSpanStart)
+ {
+ spans.add({
+ UnownedStringSlice(currentSpanStart, line.begin() + i),
+ isInCode ? DocumentationSpanKind::InlineCode : DocumentationSpanKind::OrdinaryText });
+ currentSpanEnd = currentSpanStart = line.begin() + i + 1;
+ }
+ isInCode = !isInCode;
+ }
+ else
+ {
+ currentSpanEnd = line.begin() + i + 1;
+ }
+ }
+ if (currentSpanEnd > currentSpanStart)
+ {
+ spans.add({ UnownedStringSlice(currentSpanStart, currentSpanEnd),
+ DocumentationSpanKind::OrdinaryText });
+ }
+ spans.add({ toSlice("\n"), DocumentationSpanKind::OrdinaryText });
+ }
+ else
+ {
+ spans.add({ line, DocumentationSpanKind::OrdinaryText });
+ spans.add({ toSlice("\n"), DocumentationSpanKind::OrdinaryText });
+ }
+ }
+}
- for (Decl* curDecl = sameNameDecl; curDecl; curDecl = curDecl->nextInContainerWithSameName)
+void DeclDocumentation::parse(const UnownedStringSlice& text)
+{
+ List<UnownedStringSlice> lines;
+ StringUtil::calcLines(text, lines);
+ DocPageSection currentSection = DocPageSection::Description;
+ Dictionary<DocPageSection, StringBuilder> sectionBuilders;
+ for (Index ptr = 0; ptr < lines.getCount(); ptr++)
+ {
+ auto line = lines[ptr].trim();
+ if (line.startsWith("@param"))
{
- CallableDecl* sig = nullptr;
- if (GenericDecl* genericDecl = as<GenericDecl>(curDecl))
+ currentSection = DocPageSection::Parameter;
+ line = line.tail(6).trimStart();
+ UnownedStringSlice paramDirection;
+ UnownedStringSlice paramName;
+ if (line.startsWith("["))
+ {
+ auto closingIndex = line.indexOf(']');
+ if (closingIndex != -1)
+ {
+ paramDirection = line.subString(1, closingIndex - 1);
+ line = line.tail(closingIndex + 1).trimStart();
+ }
+ }
+ auto spaceIndex = line.indexOf(' ');
+ if (spaceIndex != -1)
+ {
+ paramName = line.subString(0, spaceIndex);
+ line = line.tail(spaceIndex + 1).trimStart();
+ }
+ StringBuilder paramSB;
+ paramSB << line << "\n";
+ ptr++;
+ for (; ptr < lines.getCount(); ptr++)
{
- sig = as<CallableDecl>(genericDecl->inner);
+ auto nextLine = lines[ptr].trim();
+ if (nextLine.getLength() == 0 || nextLine.startsWith("@"))
+ {
+ ptr--;
+ break;
+ }
+ paramSB << nextLine << "\n";
+ }
+ ParamDocumentation paramDesc;
+ paramDesc.description.parse(paramSB.getUnownedSlice());
+ paramDesc.name = paramName;
+ paramDesc.direction = paramDirection;
+ parameters[paramDesc.name] = paramDesc;
+ continue;
+ }
+ else if (line.startsWith("@return"))
+ {
+ currentSection = DocPageSection::ReturnInfo;
+ line = line.tail(7).trim();
+ }
+ else if (line.startsWith("@returns"))
+ {
+ currentSection = DocPageSection::ReturnInfo;
+ line = line.tail(8).trim();
+ }
+ else if (line.startsWith("@remarks"))
+ {
+ currentSection = DocPageSection::Remarks;
+ line = line.tail(8).trim();
+ }
+ else if (line.startsWith("@example"))
+ {
+ currentSection = DocPageSection::Example;
+ line = line.tail(8).trim();
+ }
+ else if (line.startsWith("@see"))
+ {
+ currentSection = DocPageSection::SeeAlso;
+ line = line.tail(4).trim();
+ }
+ else if (line.startsWith("@experimental"))
+ {
+ currentSection = DocPageSection::ExperimentalCallout;
+ line = line.tail(13).trim();
+ }
+ else if (line.startsWith("@internal"))
+ {
+ currentSection = DocPageSection::InternalCallout;
+ line = line.tail(9).trim();
+ }
+ else if (line.startsWith("@deprecated"))
+ {
+ currentSection = DocPageSection::DeprecatedCallout;
+ line = line.tail(11).trim();
+ }
+ else if (line.startsWith("@category"))
+ {
+ line = line.tail(9).trimStart();
+ auto spaceIndex = line.indexOf(' ');
+ if (spaceIndex != -1)
+ {
+ categoryName = line.subString(0, spaceIndex);
+ categoryText = line.tail(spaceIndex + 1).trim();
}
else
{
- sig = as<CallableDecl>(curDecl);
+ categoryName = line.trim();
}
-
- if (!sig)
+ continue;
+ }
+ sectionBuilders[currentSection] << line << "\n";
+
+ // If the current directive is a callout, set currentSection back
+ // to Description after processing the directive line.
+ switch (currentSection)
+ {
+ case DocPageSection::ExperimentalCallout:
+ case DocPageSection::InternalCallout:
+ case DocPageSection::DeprecatedCallout:
+ currentSection = DocPageSection::Description;
+ break;
+ }
+ }
+ for (auto& kv : sectionBuilders)
+ {
+ sections[kv.first].parse(kv.second.getUnownedSlice());
+ }
+}
+
+void DocMarkdownWriter::writeCallableOverridable(DocumentPage* page, const ASTMarkup::Entry& primaryEntry, CallableDecl* callableDecl)
+{
+ SLANG_UNUSED(primaryEntry);
+
+ auto& out = *m_builder;
+ {
+ // Output the overridable path (ie without terminal generic parameters)
+ ASTPrinter printer(m_astBuilder, ASTPrinter::OptionFlag::NoSpecializedExtensionTypeName);
+ printer.addOverridableDeclPath(DeclRef<Decl>(callableDecl));
+ // Extract the name
+ out << toSlice("# ") << escapeMarkdownText(printer.getStringBuilder()) << toSlice("\n\n");
+ }
+
+ // Collect descriptions from all overloads.
+ StringBuilder descriptionSB, additionalDescriptionSB;
+ for (auto entry : page->entries)
+ {
+ auto markup = entry->m_markup.trim();
+ if (markup.getLength() == 0)
+ continue;
+ if (entry->m_markup.startsWith("@"))
+ {
+ additionalDescriptionSB << markup << "\n";
+ }
+ else if (descriptionSB.getLength() != 0)
+ {
+ // We already have a main description, so this is potentially a duplicate.
+ // If the content is not the same, we will report a warning.
+ if (!descriptionSB.toString().startsWith(markup))
{
- continue;
+ auto decl = as<Decl>(entry->m_node);
+ m_sink->diagnose(decl->loc, Diagnostics::ignoredDocumentationOnOverloadCandidate, decl);
}
+ }
+ else
+ {
+ descriptionSB << markup << "\n";
+ }
+ }
+
+ DeclDocumentation funcDoc;
+ funcDoc.parse(descriptionSB.getUnownedSlice());
+ funcDoc.parse(additionalDescriptionSB.getUnownedSlice());
+
+ registerCategory(page, funcDoc);
- // Want to add only the primary sig
- if (sig->primaryDecl == nullptr || sig->primaryDecl == sig)
+ auto& descSection = funcDoc.sections[DocPageSection::Description];
+ if (descSection.ownedText.getLength() > 0)
+ {
+ out << toSlice("## Description\n\n");
+ descSection.write(this, callableDecl, out);
+ }
+
+ // Collect all overloads from all entries on the page.
+ List<CallableDecl*> sigs;
+ List<Requirement> requirements;
+ HashSet<Decl*> sigSet;
+ {
+ for (auto& entry : page->entries)
+ {
+ Decl* sameNameDecl = _getSameNameDecl(as<ContainerDecl>(getParentDecl((Decl*)entry->m_node)), callableDecl);
+
+ for (Decl* curDecl = sameNameDecl; curDecl; curDecl = curDecl->nextInContainerWithSameName)
{
- sigs.add(sig);
+ CallableDecl* sig = nullptr;
+ if (GenericDecl* genericDecl = as<GenericDecl>(curDecl))
+ {
+ sig = as<CallableDecl>(genericDecl->inner);
+ }
+ else
+ {
+ sig = as<CallableDecl>(curDecl);
+ }
+
+ if (!sig)
+ {
+ continue;
+ }
+
+ // Want to add only the primary sig
+ if (sig->primaryDecl == nullptr || sig->primaryDecl == sig)
+ {
+ if (sigSet.add(sig))
+ sigs.add(sig);
+ }
}
}
@@ -736,8 +1391,6 @@ void DocMarkdownWriter::writeCallableOverridable(const ASTMarkup::Entry& entry,
sigs.sort([](CallableDecl* a, CallableDecl* b) -> bool { return a->loc.getRaw() < b->loc.getRaw(); });
}
- // The unique requirements found
- List<List<Requirement>> uniqueRequirements;
// Maps a sig index to a unique requirements set
List<Index> requirementsMap;
@@ -746,40 +1399,17 @@ void DocMarkdownWriter::writeCallableOverridable(const ASTMarkup::Entry& entry,
CallableDecl* sig = sigs[i];
// Add the requirements for all the different versions
- List<Requirement> requirements;
for (CallableDecl* curSig = sig; curSig; curSig = curSig->nextDecl)
{
- _addRequirements(sig, requirements);
- }
-
- // TODO(JS): HACK - almost everything is available for HLSL, and is generally not marked up in stdlib
- // So assume here it's available
- _addRequirement(Requirement{ CodeGenTarget::HLSL, String() }, requirements);
-
- // We want to make the requirements set unique, so we can look it up easily in the uniqueRequirements, so we sort it
- // This also has the benefit of keeping the ordering consistent
- requirements.sort();
-
- // See if we already have this combination of requirements
- Index uniqueRequirementIndex = uniqueRequirements.indexOf(requirements);
- if (uniqueRequirementIndex < 0)
- {
- // If not add it
- uniqueRequirementIndex = uniqueRequirements.getCount();
- uniqueRequirements.add(requirements);
+ requirementsMap.add(_addRequirements(sig, requirements));
}
-
- // Add the uniqueRequirement index for this sig index
- requirementsMap.add(uniqueRequirementIndex);
}
// Output the signature
{
out << toSlice("## Signature \n\n");
- out << toSlice("```\n");
+ out << toSlice("<pre>\n");
- Index prevRequirementsIndex = -1;
-
const Int sigCount = sigs.getCount();
for (Index i = 0; i < sigCount; ++i)
{
@@ -788,22 +1418,18 @@ void DocMarkdownWriter::writeCallableOverridable(const ASTMarkup::Entry& entry,
const Index requirementsIndex = requirementsMap[i];
// Output if needs unique requirements
- if (uniqueRequirements.getCount() > 1 )
+ if (requirements.getCount() > 1 && requirementsIndex != -1)
{
- if (requirementsIndex != prevRequirementsIndex)
- {
- out << toSlice("/// See Availability ") << (requirementsIndex + 1) << toSlice("\n");
- prevRequirementsIndex = requirementsIndex;
- }
+ out << toSlice("/// Requires Capability Set ") << (requirementsIndex + 1) << toSlice(":\n");
}
writeSignature(sig);
+
+ out << "\n";
}
- out << "```\n\n";
+ out << "</pre>\n\n";
}
- _maybeAppendRequirements(toSlice("## Availability\n\n"), uniqueRequirements);
-
{
// We will use the first documentation found for each parameter type
{
@@ -822,7 +1448,7 @@ void DocMarkdownWriter::writeCallableOverridable(const ASTMarkup::Entry& entry,
{
for (Decl* decl : genericDecl->members)
{
- if (as<GenericTypeParamDecl>(decl) ||
+ if (as<GenericTypeParamDeclBase>(decl) ||
as<GenericValueParamDecl>(decl))
{
genericDecls.add(decl);
@@ -836,26 +1462,62 @@ void DocMarkdownWriter::writeCallableOverridable(const ASTMarkup::Entry& entry,
}
}
- if (paramDecls.getCount() > 0 || paramDecls.getCount() > 0)
+ if (genericDecls.getCount() > 0)
+ {
+ out << "## Generic Parameters\n\n";
+
+ // Document generic parameters
+ _appendAsBullets(_getUniqueParams(genericDecls, &funcDoc), false, 0);
+
+ out << toSlice("\n");
+ }
+
+ if (paramDecls.getCount() > 0)
{
out << "## Parameters\n\n";
- // Get the unique generics
- _appendAsBullets(_getUniqueParams(genericDecls), '`');
- // And parameters
- _appendAsBullets(_getUniqueParams(paramDecls), '`');
+ // Document ordinary parameters
+ _appendAsBullets(_getUniqueParams(paramDecls, &funcDoc), false, 0);
out << toSlice("\n");
}
}
}
+
+ auto& returnsSection = funcDoc.sections[DocPageSection::ReturnInfo];
+ if (returnsSection.ownedText.getLength() > 0)
+ {
+ out << toSlice("## Return value\n");
+ returnsSection.write(this, callableDecl, out);
+ }
+
+ auto& remarksSection = funcDoc.sections[DocPageSection::Remarks];
+ if (remarksSection.ownedText.getLength() > 0)
+ {
+ out << toSlice("## Remarks\n");
+ remarksSection.write(this, callableDecl, out);
+ }
+
+ auto& exampleSection = funcDoc.sections[DocPageSection::Example];
+ if (exampleSection.ownedText.getLength() > 0)
+ {
+ out << toSlice("## Example\n");
+ exampleSection.write(this, callableDecl, out);
+ }
+
+ _maybeAppendRequirements(toSlice("## Availability and Requirements\n\n"), requirements);
+
+ auto& seeAlsoSection = funcDoc.sections[DocPageSection::SeeAlso];
+ if (seeAlsoSection.ownedText.getLength() > 0)
+ {
+ out << toSlice("## See Also\n");
+ seeAlsoSection.write(this, callableDecl, out);
+ }
}
void DocMarkdownWriter::writeEnum(const ASTMarkup::Entry& entry, EnumDecl* enumDecl)
{
- writePreamble(entry);
-
- auto& out = m_builder;
+ auto& out = *m_builder;
out << toSlice("# enum ");
Name* name = enumDecl->getName();
@@ -865,16 +1527,23 @@ void DocMarkdownWriter::writeEnum(const ASTMarkup::Entry& entry, EnumDecl* enumD
}
out << toSlice("\n\n");
+ DeclDocumentation declDoc;
+ declDoc.parse(entry.m_markup.getUnownedSlice());
+ declDoc.writeDescription(out, this, enumDecl);
+ registerCategory(m_currentPage, declDoc);
+
out << toSlice("## Values \n\n");
- _appendAsBullets(_getAsNameAndTextList(enumDecl->getMembersOfType<EnumCaseDecl>()), '_');
+ _appendAsBullets(_getAsNameAndTextList(enumDecl->getMembersOfType<EnumCaseDecl>()), false, '_');
- writeDescription(entry);
+ declDoc.writeSection(out, this, enumDecl, DocPageSection::Remarks);
+ declDoc.writeSection(out, this, enumDecl, DocPageSection::Example);
+ declDoc.writeSection(out, this, enumDecl, DocPageSection::SeeAlso);
}
void DocMarkdownWriter::_appendEscaped(const UnownedStringSlice& text)
{
- auto& out = m_builder;
+ auto& out = *m_builder;
const char* start = text.begin();
const char* cur = start;
@@ -918,7 +1587,7 @@ void DocMarkdownWriter::_appendEscaped(const UnownedStringSlice& text)
void DocMarkdownWriter::_appendDerivedFrom(const UnownedStringSlice& prefix, AggTypeDeclBase* aggTypeDecl)
{
- auto& out = m_builder;
+ auto& out = *m_builder;
List<InheritanceDecl*> inheritanceDecls;
_getDecls(aggTypeDecl, inheritanceDecls);
@@ -934,14 +1603,42 @@ void DocMarkdownWriter::_appendDerivedFrom(const UnownedStringSlice& prefix, Agg
{
out << toSlice(", ");
}
- out << inheritanceDecl->base;
+ out << escapeMarkdownText(inheritanceDecl->base->toString());
}
}
}
-void DocMarkdownWriter::_appendAggTypeName(AggTypeDeclBase* aggTypeDecl)
+void DocMarkdownWriter::_appendAggTypeName(const ASTMarkup::Entry& entry, Decl* aggTypeDecl)
{
- auto& out = m_builder;
+ SLANG_UNUSED(entry);
+
+ auto& out = *m_builder;
+
+#if 0
+ // For extensions, try to see if the documentation defines a more readable title.
+ if (as<ExtensionDecl>(aggTypeDecl))
+ {
+ auto trimStart = String(entry.m_markup.trimStart());
+ if (trimStart.startsWith("@title"))
+ {
+ List<UnownedStringSlice> lines;
+ StringUtil::calcLines(trimStart.getUnownedSlice(), lines);
+ if (lines.getCount() > 0)
+ {
+ out << escapeMarkdownText(lines[0].tail(6).trim());
+
+ // Remove @title directive from the description markup.
+ StringBuilder restSB;
+ for (Index i = 1; i < lines.getCount(); ++i)
+ {
+ restSB << lines[i] << "\n";
+ }
+ entry.m_markup = restSB.produceString();
+ return;
+ }
+ }
+ }
+#endif
// This could be lots of different things - struct/class/extension/interface/..
@@ -950,55 +1647,86 @@ void DocMarkdownWriter::_appendAggTypeName(AggTypeDeclBase* aggTypeDecl)
if (as<StructDecl>(aggTypeDecl))
{
- out << toSlice("struct ") << printer.getStringBuilder();
+ out << toSlice("struct ") << escapeMarkdownText(printer.getStringBuilder().produceString());
}
else if (as<ClassDecl>(aggTypeDecl))
{
- out << toSlice("class ") << printer.getStringBuilder();
+ out << toSlice("class ") << escapeMarkdownText(printer.getStringBuilder().produceString());
}
else if (as<InterfaceDecl>(aggTypeDecl))
{
- out << toSlice("interface ") << printer.getStringBuilder();
+ out << toSlice("interface ") << escapeMarkdownText(printer.getStringBuilder().produceString());
}
else if (ExtensionDecl* extensionDecl = as<ExtensionDecl>(aggTypeDecl))
{
- out << toSlice("extension ") << extensionDecl->targetType;
+ out << toSlice("extension ") << escapeMarkdownText(extensionDecl->targetType->toString());
_appendDerivedFrom(toSlice(" : "), extensionDecl);
}
+ else if (as<TypeDefDecl>(aggTypeDecl))
+ {
+ out << toSlice("typealias ") << escapeMarkdownText(printer.getStringBuilder().produceString());
+ }
else
{
out << toSlice("?");
}
}
-void DocMarkdownWriter::writeAggType(const ASTMarkup::Entry& entry, AggTypeDeclBase* aggTypeDecl)
+void DocMarkdownWriter::writeAggType(DocumentPage* page, const ASTMarkup::Entry& primaryEntry, AggTypeDeclBase* aggTypeDecl)
{
- writePreamble(entry);
-
- auto& out = m_builder;
+ auto& out = *m_builder;
// We can write out he name using the printer
-
- ASTPrinter printer(m_astBuilder);
- printer.addDeclPath(DeclRef<Decl>(aggTypeDecl));
-
- out << toSlice("# `");
- _appendAggTypeName(aggTypeDecl);
- out << toSlice("`\n\n");
-
+ out << toSlice("# ");
+ _appendAggTypeName(primaryEntry, aggTypeDecl);
+ out << toSlice("\n\n");
+ List<ExtensionDecl*> conditionalConformanceExts;
{
List<InheritanceDecl*> inheritanceDecls;
_getDecls<InheritanceDecl>(aggTypeDecl, inheritanceDecls);
-
- if (inheritanceDecls.getCount())
+ List<String> baseTypes;
+ HashSet<String> conditionalBaseTypes;
+ baseTypes = _getAsStringList(inheritanceDecls);
+ for (auto entry : page->entries)
+ {
+ for (auto member : as<ContainerDecl>(entry->m_node)->members)
+ {
+ if (auto inheritanceDecl = as<InheritanceDecl>(member))
+ {
+ if (auto extDecl = as<ExtensionDecl>(entry->m_node))
+ {
+ conditionalConformanceExts.add(extDecl);
+ conditionalBaseTypes.add(inheritanceDecl->base->toString());
+ }
+ }
+ }
+ }
+ if (baseTypes.getCount())
{
- out << "*Implements:* ";
- _appendCommaList(_getAsStringList(inheritanceDecls), '`');
+ if (as<InterfaceDecl>(aggTypeDecl))
+ out << "*Inherits from:* ";
+ else
+ out << "*Conforms to:* ";
+ _appendCommaList(baseTypes, 0);
+ out << toSlice("\n\n");
+ }
+ if (conditionalBaseTypes.getCount())
+ {
+ out << "*Conditionally conforms to:* ";
+ List<String> list;
+ for (auto t : conditionalBaseTypes)
+ list.add(t);
+ _appendCommaList(list, 0);
out << toSlice("\n\n");
}
}
- writeDescription(entry);
+ DeclDocumentation declDoc;
+ declDoc.parse(primaryEntry.m_markup.getUnownedSlice());
+ declDoc.writeDescription(out, this, aggTypeDecl);
+ registerCategory(page, declDoc);
+
+ declDoc.writeGenericParameters(out, this, aggTypeDecl);
{
List<AssocTypeDecl*> assocTypeDecls;
@@ -1009,7 +1737,7 @@ void DocMarkdownWriter::writeAggType(const ASTMarkup::Entry& entry, AggTypeDeclB
out << toSlice("# Associated types\n\n");
for (AssocTypeDecl* assocTypeDecl : assocTypeDecls)
- {
+ {
out << "* _" << assocTypeDecl->getName()->text << "_ ";
// Look up markup
@@ -1020,8 +1748,8 @@ void DocMarkdownWriter::writeAggType(const ASTMarkup::Entry& entry, AggTypeDeclB
}
out << toSlice("\n");
- List<InheritanceDecl*> inheritanceDecls;
- _getDecls<InheritanceDecl>(assocTypeDecl, inheritanceDecls);
+ List<TypeConstraintDecl*> inheritanceDecls;
+ _getDecls<TypeConstraintDecl>(assocTypeDecl, inheritanceDecls);
if (inheritanceDecls.getCount())
{
@@ -1035,101 +1763,449 @@ void DocMarkdownWriter::writeAggType(const ASTMarkup::Entry& entry, AggTypeDeclB
}
}
- if (GenericDecl* genericDecl = as<GenericDecl>(aggTypeDecl->parentDecl))
{
- // The parameters, in order
- List<Decl*> params;
- for (Decl* decl : genericDecl->members)
+ List<Decl*> fields;
+ _getDeclsOfType<VarDecl>(this, page, fields);
+ if (fields.getCount())
{
- if (as<GenericTypeParamDecl>(decl) ||
- as<GenericValueParamDecl>(decl))
- {
- params.add(decl);
- }
+ out << toSlice("## Fields\n\n");
+ _appendAsBullets(_getAsNameAndTextList(fields), true, 0);
+ out << toSlice("\n");
}
-
- if (params.getCount())
+ }
+
+ {
+ List<Decl*> properties;
+ _getDeclsOfType<PropertyDecl>(this, page, properties);
+ if (properties.getCount())
{
- out << toSlice("## Generic Parameters\n\n");
- _appendAsBullets(_getAsNameAndTextList(params), '`');
+ out << toSlice("## Properties\n\n");
+ _appendAsBullets(_getAsNameAndTextList(properties), true, 0);
out << toSlice("\n");
}
}
{
- List<Decl*> fields;
- _getDeclsOfType<VarDecl>(aggTypeDecl, fields);
- if (fields.getCount())
+ List<Decl*> uniqueMethods;
+ _getDeclsOfType<CallableDecl>(this, page, uniqueMethods);
+
+ if (uniqueMethods.getCount())
{
- out << toSlice("## Fields\n\n");
- _appendAsBullets(_getAsNameAndTextList(fields), '`');
+ // Put in source definition order
+ uniqueMethods.sort([](Decl* a, Decl* b) -> bool { return a->loc.getRaw() < b->loc.getRaw(); });
+
+ out << "## Methods\n\n";
+ _appendAsBullets(_getAsStringList(uniqueMethods), 0);
out << toSlice("\n");
}
}
+ if (conditionalConformanceExts.getCount())
{
- // Make sure we've got a query-able member dictionary
- auto& memberDict = aggTypeDecl->getMemberDictionary();
+ out << "## Conditional Conformances\n\n";
+ for (auto ext : conditionalConformanceExts)
+ {
+ for (auto member : ext->members)
+ {
+ auto inheritanceDecl = as<InheritanceDecl>(member);
+ if (!inheritanceDecl)
+ continue;
+ out << "### Conformance to ";
+ out << escapeMarkdownText(inheritanceDecl->base.type->toString());
+ out << "\n";
+ StringBuilder sb;
+ writeExtensionConditions(sb, ext, "\n", false);
+ List<UnownedStringSlice> lines, nonEmptyLines;
+ StringUtil::calcLines(sb.getUnownedSlice(), lines);
+ for (auto line : lines)
+ {
+ if (line.trim().getLength())
+ nonEmptyLines.add(line);
+ }
+ ASTPrinter printer(m_astBuilder);
+ printer.addDeclPath(aggTypeDecl->getDefaultDeclRef());
+ out << "`" << printer.getString() << "` additionally conforms to `";
+ out << escapeMarkdownText(inheritanceDecl->base.type->toString());
+ if (nonEmptyLines.getCount() != 0)
+ {
+ out << "` when the following conditions are met:\n\n";
+ for (auto condition : nonEmptyLines)
+ {
+ out << " * " << condition << "\n";
+ }
+ }
+ else
+ {
+ out << "`.\n";
+ }
+ }
+ }
+ }
+ declDoc.writeSection(out, this, aggTypeDecl, DocPageSection::Remarks);
+ declDoc.writeSection(out, this, aggTypeDecl, DocPageSection::Example);
+ declDoc.writeSection(out, this, aggTypeDecl, DocPageSection::SeeAlso);
+}
- List<Decl*> uniqueMethods;
- for (const auto& [_, decl] : memberDict)
+String DocMarkdownWriter::escapeMarkdownText(String text)
+{
+ StringBuilder sb;
+ for (auto c : text)
+ {
+ switch (c)
{
- if (!shouldDocumentDecl(decl))
+ case '_':
+ case '*':
+ case '[':
+ case ']':
+ case '<':
+ case '>':
+ case '|':
+ case '.':
+ case '!':
+ case '(':
+ case ')':
+ sb << '\\';
+ sb.appendChar(c);
+ break;
+ default:
+ sb.appendChar(c);
+ break;
+ }
+ }
+ return sb.produceString();
+}
+
+void DocMarkdownWriter::ensureDeclPageCreated(ASTMarkup::Entry& entry)
+{
+ auto page = getPage(as<Decl>(entry.m_node));
+ page->entries.add(&entry);
+}
+
+Slang::Misc::Token treatLiteralsAsIdentifier(Slang::Misc::Token token)
+{
+ // If the token is a literal, we want to treat it as an identifier.
+ if (token.Type == Slang::Misc::TokenType::StringLiteral)
+ {
+ token.Type = Slang::Misc::TokenType::Identifier;
+ StringBuilder stringSB;
+ StringEscapeUtil::appendQuoted(StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp), token.Content.getUnownedSlice(), stringSB);
+ token.Content = stringSB.produceString();
+ }
+ else if (token.Type == Slang::Misc::TokenType::IntLiteral ||
+ token.Type == Slang::Misc::TokenType::DoubleLiteral)
+ {
+ token.Type = Slang::Misc::TokenType::Identifier;
+ }
+ return token;
+}
+
+String DocMarkdownWriter::translateToMarkdownWithLinks(String text, bool strictChildLookup)
+{
+ StringBuilder sb;
+ List<DocumentPage*> currentPage;
+ currentPage.add(m_currentPage);
+ Slang::Misc::TokenReader reader(text);
+ bool requireSpaceBeforeNextToken = false;
+ bool isFirstToken = true;
+ for (; !reader.IsEnd(); )
+ {
+ auto token = treatLiteralsAsIdentifier(reader.ReadToken());
+
+
+ if (token.Type == Slang::Misc::TokenType::Identifier)
+ {
+ if (requireSpaceBeforeNextToken)
+ sb.append(' ');
+ auto tokenContent = token.Content;
+ if (tokenContent == "operator")
+ {
+ for (;;)
+ {
+ auto operatorToken = reader.ReadToken();
+ tokenContent.append(operatorToken.Content);
+ if (operatorToken.Type != Slang::Misc::TokenType::LParent &&
+ operatorToken.Type != Slang::Misc::TokenType::LBracket)
+ {
+ break;
+ }
+ }
+ }
+ String sectionName;
+ Decl* referencedDecl = nullptr;
+ auto page = findPageForToken(currentPage.getLast(), tokenContent, sectionName, referencedDecl);
+
+ if (isFirstToken && strictChildLookup && page && page->parentPage != m_currentPage)
+ {
+ // If we are performing a strict child lookup (for displaying the member list of an agg type),
+ // then we want to ignore any lookup results that refer to a different parent page.
+ page = nullptr;
+ }
+
+ if (page)
+ {
+ sb.append("[");
+ sb << escapeMarkdownText(tokenContent.getUnownedSlice());
+ sb.append("](");
+ sb.append(getDocPath(m_config, page->path));
+ if (sectionName.getLength())
+ sb << "#" << sectionName;
+ sb.append(")");
+ currentPage.getLast() = page;
continue;
- CallableDecl* callableDecl = as<CallableDecl>(decl);
- if (callableDecl && isVisible(callableDecl))
+ }
+ requireSpaceBeforeNextToken = true;
+ isFirstToken = false;
+ }
+ else
+ {
+ switch (token.Type)
{
- uniqueMethods.add(callableDecl);
+ case Slang::Misc::TokenType::OpLess:
+ case Slang::Misc::TokenType::OpGreater:
+ case Slang::Misc::TokenType::Comma:
+ case Slang::Misc::TokenType::Dot:
+ case Slang::Misc::TokenType::IntLiteral:
+ case Slang::Misc::TokenType::Semicolon:
+ requireSpaceBeforeNextToken = false;
+ break;
+ default:
+ requireSpaceBeforeNextToken = true;
+ sb.appendChar(' ');
+ break;
}
}
-
- if (uniqueMethods.getCount())
+ // Maintain the `currentPage` stack so we can use the correct starting page
+ // to lookup things like `Foo<int>.Bar`. When we look up `Bar`, we want to start
+ // from the same page after looking up `Foo`, so we need to push the stack when we
+ // see `<` and pop the stack when we see `>`.
+ if (token.Type == Slang::Misc::TokenType::OpLess)
{
- // Put in source definition order
- uniqueMethods.sort([](Decl* a, Decl* b) -> bool { return a->loc.getRaw() < b->loc.getRaw(); });
+ currentPage.add(currentPage.getLast());
+ }
+ else if (token.Type == Slang::Misc::TokenType::OpGreater)
+ {
+ if (currentPage.getCount() > 1)
+ currentPage.removeLast();
+ }
+ sb << escapeMarkdownText(token.Content.getUnownedSlice());
+ if (token.Type == Slang::Misc::TokenType::Comma)
+ sb.appendChar(' ');
+ }
+ return sb.produceString();
+}
- out << "## Methods\n\n";
- _appendAsBullets(_getAsStringList(uniqueMethods), '`');
- out << toSlice("\n");
+// Implemented in slang-language-server-completion.cpp
+bool isDeclKeyword(const UnownedStringSlice& slice);
+
+bool isKeyword(const UnownedStringSlice& slice)
+{
+ if (isDeclKeyword(slice))
+ return true;
+ static const char* knownTypeNames[] = { "int", "float", "half", "double", "bool", "void", "uint" };
+ for (auto typeName : knownTypeNames)
+ {
+ if (slice == typeName)
+ return true;
+ }
+ return false;
+}
+
+String DocMarkdownWriter::translateToHTMLWithLinks(Decl* decl, String text)
+{
+ SLANG_UNUSED(decl);
+ StringBuilder sb;
+ List<DocumentPage*> currentPage;
+ currentPage.add(m_currentPage);
+ Slang::Misc::TokenReader reader(text);
+ bool prevIsIdentifier = false;
+ for (; !reader.IsEnd(); )
+ {
+ auto token = treatLiteralsAsIdentifier(reader.ReadToken());
+
+ if (token.Type == Slang::Misc::TokenType::Identifier)
+ {
+ if (prevIsIdentifier)
+ sb.append(' ');
+ String sectionName;
+ Decl* referencedDecl = nullptr;
+ auto page = findPageForToken(currentPage.getLast(), token.Content, sectionName, referencedDecl);
+ if (page)
+ {
+ sb.append("<a href=\"");
+ sb.append(getDocPath(m_config, page->path));
+ if (sectionName.getLength())
+ sb << "#" << sectionName;
+ sb.append("\"");
+ if (isKeyword(token.Content.getUnownedSlice()))
+ sb.append(" class=\"code_keyword\"");
+ else if (as<AggTypeDeclBase>(referencedDecl) ||
+ as<SimpleTypeDecl>(referencedDecl))
+ sb.append(" class=\"code_type\"");
+ else if (as<ParamDecl>(referencedDecl))
+ sb.append(" class=\"code_param\"");
+ else if (as<VarDeclBase>(referencedDecl) || as<EnumCaseDecl>(referencedDecl))
+ sb.append(" class=\"code_var\"");
+ sb.append(">");
+ escapeHTMLContent(sb, token.Content.getUnownedSlice());
+ sb.append("</a>");
+ currentPage.getLast() = page;
+ continue;
+ }
+ prevIsIdentifier = true;
+ }
+ else
+ {
+ prevIsIdentifier = false;
}
+ // Maintain the `currentPage` stack so we can use the correct starting page
+ // to lookup things like `Foo<int>.Bar`. When we look up `Bar`, we want to start
+ // from the same page after looking up `Foo`, so we need to push the stack when we
+ // see `<` and pop the stack when we see `>`.
+ if (token.Type == Slang::Misc::TokenType::OpLess)
+ {
+ currentPage.add(m_currentPage);
+ }
+ else if (token.Type == Slang::Misc::TokenType::OpGreater)
+ {
+ if (currentPage.getCount() > 1)
+ currentPage.removeLast();
+ }
+ bool shouldCloseSpan = false;
+ if (isKeyword(token.Content.getUnownedSlice()))
+ {
+ sb.append("<span class=\"code_keyword\">");
+ shouldCloseSpan = true;
+ }
+ escapeHTMLContent(sb, token.Content.getUnownedSlice());
+ if (shouldCloseSpan)
+ sb.append("</span>");
+ if (token.Type == Slang::Misc::TokenType::Comma)
+ sb.appendChar(' ');
}
+ return sb.produceString();
}
-void DocMarkdownWriter::writePreamble(const ASTMarkup::Entry& entry)
+void DocMarkdownWriter::writePreamble()
{
- SLANG_UNUSED(entry);
- auto& out = m_builder;
+ auto& out = *m_builder;
+ if (out.getLength() == 0)
+ {
+ out << m_config.preamble;
+ out << toSlice("\n");
+ }
+}
+
+const char* getSectionTitle(DocPageSection section)
+{
+ switch (section)
+ {
+ case DocPageSection::Description: return "Description";
+ case DocPageSection::Parameter: return "Parameters";
+ case DocPageSection::ReturnInfo: return "Return value";
+ case DocPageSection::Remarks: return "Remarks";
+ case DocPageSection::Example: return "Example";
+ case DocPageSection::SeeAlso: return "See also";
+ default: return "";
+ }
+}
- //out << toSlice("\n");
+void DeclDocumentation::writeDescription(StringBuilder& out, DocMarkdownWriter* writer, Decl* decl)
+{
+ // Write all callout sections first.
+ writeSection(out, writer, decl, DocPageSection::DeprecatedCallout);
+ writeSection(out, writer, decl, DocPageSection::ExperimentalCallout);
+ writeSection(out, writer, decl, DocPageSection::InternalCallout);
- out.appendRepeatedChar('-', 80);
- out << toSlice("\n");
+ // Write description section.
+ writeSection(out, writer, decl, DocPageSection::Description);
}
-void DocMarkdownWriter::writeDescription(const ASTMarkup::Entry& entry)
+void DeclDocumentation::writeGenericParameters(StringBuilder& out, DocMarkdownWriter* writer, Decl* decl)
{
- auto& out = m_builder;
+ GenericDecl* genericDecl = as<GenericDecl>(decl->parentDecl);
+ if (!genericDecl)
+ return;
- if (entry.m_markup.getLength() > 0)
+ // The parameters, in order
+ List<Decl*> params;
+ for (Decl* member : genericDecl->members)
{
- out << toSlice("## Description\n\n");
+ if (as<GenericTypeParamDeclBase>(member) ||
+ as<GenericValueParamDecl>(member))
+ {
+ params.add(member);
+ }
+ }
- out << entry.m_markup.getUnownedSlice();
-#if 0
- UnownedStringSlice text(entry.m_markup.getUnownedSlice()), line;
- while (StringUtil::extractLine(text, line))
+ if (params.getCount())
+ {
+ out << toSlice("## Generic Parameters\n\n");
+ auto paramList = writer->_getAsNameAndTextList(params);
+
+ // Append names with constraints if any.
+ for (Index i = 0; i < paramList.getCount(); i++)
{
- out << line << toSlice("\n");
+ auto param = params[i];
+ if (paramList[i].text.getLength() == 0)
+ {
+ ParamDocumentation paramDoc;
+ if (parameters.tryGetValue(getText(param->getName()), paramDoc))
+ {
+ StringBuilder sb;
+ sb << paramDoc.description.ownedText;
+ paramList[i].text = sb.produceString();
+ }
+ }
}
-#endif
+ writer->_appendAsBullets(paramList, false, 0);
out << toSlice("\n");
}
}
-void DocMarkdownWriter::writeDecl(const ASTMarkup::Entry& entry, Decl* decl)
+void DeclDocumentation::writeSection(StringBuilder& out, DocMarkdownWriter* writer, Decl* decl, DocPageSection section)
+{
+ SLANG_UNUSED(decl);
+ ParsedDescription* sectionDoc = sections.tryGetValue(section);
+ if (!sectionDoc)
+ return;
+
+ switch (section)
+ {
+ case DocPageSection::DeprecatedCallout:
+ out << "> #### Deprecated Feature\n";
+ out << "> The feature described in this page is marked as deprecated, and may be removed in a future release.\n";
+ out << "> Users are advised to avoid using this feature, and to migrate to a newer alternative.\n";
+ out << "\n";
+ return;
+ case DocPageSection::ExperimentalCallout:
+ out << "> #### Experimental Feature\n";
+ out << "> The feature described in this page is marked as experimental, and may be subject to change in future releases.\n";
+ out << "> Users are advised that any code that depend on this feature may not be compilable by future versions of the compiler.\n";
+ out << "\n";
+ return;
+ case DocPageSection::InternalCallout:
+ out << "> #### Internal Feature\n";
+ out << "> The feature described in this page is marked as an internal implementation detail, and is not intended for use by end-users.\n";
+ out << "> Users are advised to avoid using this declaration directly, as it may be removed or changed in future releases.\n";
+ out << "\n";
+ return;
+ }
+ if (sectionDoc && sectionDoc->ownedText.getLength() > 0)
+ {
+ out << "## " << getSectionTitle(section) << "\n\n";
+ sectionDoc->write(writer, decl, out);
+ }
+}
+
+void DocMarkdownWriter::createPage(DocMarkdownWriter::WriteDeclMode mode, ASTMarkup::Entry& entry, Decl* decl)
{
// Skip these they will be output as part of their respective 'containers'
- if (as<ParamDecl>(decl) || as<EnumCaseDecl>(decl) || as<AssocTypeDecl>(decl) || as<InheritanceDecl>(decl) || as<ThisTypeDecl>(decl))
+ if (as<ParamDecl>(decl) ||
+ as<EnumCaseDecl>(decl) ||
+ as<AssocTypeDecl>(decl) ||
+ as<TypeConstraintDecl>(decl) ||
+ as<ThisTypeDecl>(decl) ||
+ as<AccessorDecl>(decl))
{
return;
}
@@ -1138,26 +2214,35 @@ void DocMarkdownWriter::writeDecl(const ASTMarkup::Entry& entry, Decl* decl)
{
if (_isFirstOverridden(callableDecl))
{
- writeCallableOverridable(entry, callableDecl);
+ if (mode == WriteDeclMode::Header)
+ ensureDeclPageCreated(entry);
}
}
- else if (EnumDecl* enumDecl = as<EnumDecl>(decl))
+ else if (as<EnumDecl>(decl))
{
- writeEnum(entry, enumDecl);
+ if (mode == WriteDeclMode::Header)
+ ensureDeclPageCreated(entry);
}
- else if (AggTypeDeclBase* aggType = as<AggTypeDeclBase>(decl))
+ else if (as<AggTypeDeclBase>(decl))
{
- writeAggType(entry, aggType);
+ if (mode == WriteDeclMode::Header)
+ ensureDeclPageCreated(entry);
}
- else if (VarDecl* varDecl = as<VarDecl>(decl))
+ else if (as<VarDecl>(decl))
{
// If part of aggregate type will be output there.
- if (as<AggTypeDecl>(varDecl->parentDecl))
- {
- return;
- }
-
- writeVar(entry, varDecl);
+ if (mode == WriteDeclMode::Header)
+ ensureDeclPageCreated(entry);
+ }
+ else if (as<TypeDefDecl>(decl))
+ {
+ if (mode == WriteDeclMode::Header)
+ ensureDeclPageCreated(entry);
+ }
+ else if (as<PropertyDecl>(decl))
+ {
+ if (mode == WriteDeclMode::Header)
+ ensureDeclPageCreated(entry);
}
else if (as<GenericDecl>(decl))
{
@@ -1165,9 +2250,113 @@ void DocMarkdownWriter::writeDecl(const ASTMarkup::Entry& entry, Decl* decl)
}
}
+void DocMarkdownWriter::registerCategory(DocumentPage* page, DeclDocumentation& doc)
+{
+ if (doc.categoryText.getLength() != 0)
+ {
+ m_categories[doc.categoryName] = doc.categoryText;
+ }
+ else if (!m_categories.containsKey(doc.categoryName))
+ {
+ m_categories[doc.categoryName] = doc.categoryName;
+ }
+ page->category = doc.categoryName;
+}
+
+
bool DocMarkdownWriter::isVisible(const Name* name)
{
- return name == nullptr || !name->text.startsWith(toSlice("__"));
+ return name == nullptr || !name->text.startsWith(toSlice("__"))
+ || m_config.visibleDeclNames.contains(getText((Name*)name));
+}
+
+DocumentPage* DocMarkdownWriter::findPageForToken(DocumentPage* currentPage, String token, String& outSectionName, Decl*& outDecl)
+{
+ while (currentPage)
+ {
+ // Are there any children pages whose short title matches `token`?
+ // If so, return the path of that page.
+ if (currentPage->shortName == token)
+ {
+ outDecl = currentPage->decl;
+ return currentPage;
+ }
+ if (auto rs = currentPage->findChildByShortName(token.getUnownedSlice()))
+ {
+ outDecl = rs->decl;
+ return rs;
+ }
+ // Is `token` documented as a section on current page?
+ // This will be the case for parameters and generic parameters.
+ if (currentPage->decl)
+ {
+ for (auto entry : currentPage->entries)
+ {
+ auto containerDecl = as<ContainerDecl>(entry->m_node);
+ if (!containerDecl)
+ continue;
+ if (auto genericParent = as<GenericDecl>(containerDecl->parentDecl))
+ {
+ for (auto member : genericParent->members)
+ {
+ if (getText(member->getName()) == token)
+ {
+ outDecl = member;
+ if (as<GenericTypeParamDeclBase>(member))
+ outSectionName = String("typeparam-") + token;
+ else if (as<GenericValueParamDecl>(member))
+ outSectionName = String("decl-") + token;
+ return currentPage;
+ }
+ }
+ }
+ for (auto member : containerDecl->members)
+ {
+ if (as<ParamDecl>(member) || as<EnumCaseDecl>(member))
+ {
+ if (getText(member->getName()) == token)
+ {
+ outDecl = member;
+ outSectionName = String("decl-") + token;
+ return currentPage;
+ }
+ }
+ }
+ }
+ }
+
+ currentPage = currentPage->parentPage;
+ }
+ // Otherwise, try find in global decls.
+ if (auto rs = m_typesPage->findChildByShortName(token.getUnownedSlice()))
+ {
+ outDecl = rs->decl;
+ return rs;
+ }
+ if (auto rs = m_interfacesPage->findChildByShortName(token.getUnownedSlice()))
+ {
+ outDecl = rs->decl;
+ return rs;
+ }
+ if (auto rs = m_globalDeclsPage->findChildByShortName(token.getUnownedSlice()))
+ {
+ outDecl = rs->decl;
+ return rs;
+ }
+ return nullptr;
+}
+
+String DocMarkdownWriter::findLinkForToken(DocumentPage* currentPage, String token)
+{
+ String sectionName;
+ Decl* decl = nullptr;
+ if (auto page = findPageForToken(currentPage, token, sectionName, decl))
+ {
+ if (sectionName.getLength() == 0)
+ return page->path;
+ return page->path + "#" + sectionName;
+ }
+ return String();
}
bool DocMarkdownWriter::isVisible(const ASTMarkup::Entry& entry)
@@ -1179,7 +2368,7 @@ bool DocMarkdownWriter::isVisible(const ASTMarkup::Entry& entry)
}
Decl* decl = as<Decl>(entry.m_node);
- return decl == nullptr || isVisible(decl->getName());
+ return decl == nullptr || isVisible(decl);
}
bool DocMarkdownWriter::isVisible(Decl* decl)
@@ -1188,22 +2377,362 @@ bool DocMarkdownWriter::isVisible(Decl* decl)
{
return false;
}
-
+ bool parentIsVisible = true;
+ auto parent = decl;
+ while (parent)
+ {
+ if (auto extDecl = as<ExtensionDecl>(parent))
+ {
+ if (auto targetDecl = isDeclRefTypeOf<Decl>(extDecl->targetType))
+ {
+ parentIsVisible = parentIsVisible && isVisible(targetDecl.getDecl());
+ parent = targetDecl.getDecl();
+ }
+ else
+ {
+ parent = getParentDecl(parent);
+ }
+ }
+ else
+ {
+ parent = getParentDecl(parent);
+ }
+ if (as<AggTypeDeclBase>(parent))
+ {
+ parentIsVisible = parentIsVisible && isVisible(parent);
+ }
+ }
auto entry = m_markup->getEntry(decl);
- return entry == nullptr || entry->m_visibility == MarkupVisibility::Public;
+ return parentIsVisible && (entry == nullptr || entry->m_visibility == MarkupVisibility::Public);
}
-void DocMarkdownWriter::writeAll()
+void DocumentationConfig::parse(UnownedStringSlice config)
{
- for (const auto& entry : m_markup->getEntries())
+ List<UnownedStringSlice> lines;
+ StringUtil::calcLines(config, lines);
+ Index ptr = 0;
+ for (;ptr < lines.getCount(); ptr++)
+ {
+ auto line = lines[ptr];
+ if (line.startsWith(toSlice("@preamble:")))
+ {
+ ptr++;
+ StringBuilder preambleSB;
+ for (; ptr < lines.getCount(); ptr++)
+ {
+ if (lines[ptr].startsWith("@end"))
+ break;
+ preambleSB << lines[ptr] << "\n";
+ }
+ ptr++;
+ preamble = preambleSB.produceString();
+ }
+ else if (line.startsWith(toSlice("@title:")))
+ {
+ title = line.tail(7).trim();
+ }
+ else if (line.startsWith(toSlice("@libname:")))
+ {
+ libName = line.tail(9).trim();
+ }
+ else if (line.startsWith(toSlice("@rootdir:")))
+ {
+ rootDir = line.tail(9).trim();
+ }
+ else if (line.startsWith("@includedecl:"))
+ {
+ ptr++;
+ for (; ptr < lines.getCount(); ptr++)
+ {
+ if (lines[ptr].startsWith("@end"))
+ break;
+ auto name = lines[ptr].trim();
+ if (name.getLength())
+ visibleDeclNames.add(name);
+ }
+ ptr++;
+ }
+ }
+}
+
+void sortPages(DocumentPage* page)
+{
+ page->children.sort([](DocumentPage* a, DocumentPage* b) -> bool { return a->shortName < b->shortName; });
+}
+
+void DocMarkdownWriter::generateSectionIndexPage(DocumentPage* page)
+{
+ // Generate the content for meta section index page.
+ StringBuilder& sb = page->get();
+ sb << m_config.preamble;
+ sb << "# " << page->title;
+ sb << "\n\n";
+ sb << m_config.libName;
+ sb << " defines the following " << String(page->title).toLower() << ":\n\n";
+ sortPages(page);
+
+ for (auto child : page->children)
+ {
+ sb << "- [" << escapeMarkdownText(child->shortName) << "](" << getDocPath(m_config, child->path) << ")\n";
+ }
+}
+
+DocumentPage* DocMarkdownWriter::writeAll(UnownedStringSlice configStr)
+{
+ m_config.parse(configStr);
+
+ auto addBuiltinPage = [&](DocumentPage* parent, UnownedStringSlice path, UnownedStringSlice title, UnownedStringSlice shortTitle)
+ {
+ RefPtr<DocumentPage> page = new DocumentPage();
+ page->title = title;
+ page->path = path;
+ page->shortName = shortTitle;
+ page->decl = nullptr;
+ if (parent)
+ {
+ parent->children.add(page);
+ }
+ m_output[page->path] = page;
+ return page.get();
+ };
+ m_rootPage = addBuiltinPage(nullptr, toSlice("index.md"), m_config.title.getUnownedSlice(), toSlice("Standard Library Reference"));
+ m_rootPage->skipWrite = true;
+
+ m_interfacesPage = addBuiltinPage(m_rootPage.get(), toSlice("interfaces/index.md"), toSlice("Interfaces"), toSlice("Interfaces"));
+ m_typesPage = addBuiltinPage(m_rootPage.get(), toSlice("types/index.md"), toSlice("Types"), toSlice("Types"));
+ m_globalDeclsPage = addBuiltinPage(m_rootPage.get(), toSlice("global-decls/index.md"), toSlice("Global Declarations"), toSlice("Global Declarations"));
+
+ // In the first pass, we create all the pages so we can reference them
+ // when writing the content.
+ for (auto& entry : m_markup->getEntries())
{
Decl* decl = as<Decl>(entry.m_node);
if (decl && isVisible(entry))
{
- writeDecl(entry, decl);
+ createPage(WriteDeclMode::Header, entry, decl);
+ }
+ }
+ // In the second pass, actually writes the content to each page.
+ writePageRecursive(m_rootPage.get());
+
+ generateSectionIndexPage(m_interfacesPage);
+ generateSectionIndexPage(m_typesPage);
+ generateSectionIndexPage(m_globalDeclsPage);
+
+ return m_rootPage.get();
+}
+
+void DocMarkdownWriter::writePage(DocumentPage* page)
+{
+ if (page->skipWrite)
+ return;
+ if (page->entries.getCount() == 0)
+ return;
+
+ m_currentPage = page;
+ m_builder = &(page->get());
+
+ writePreamble();
+
+ Decl* decl = (Decl*)page->getFirstEntry()->m_node;
+ if (CallableDecl* callableDecl = as<CallableDecl>(decl))
+ {
+ writeCallableOverridable(page, *page->getFirstEntry(), callableDecl);
+ }
+ else if (EnumDecl* enumDecl = as<EnumDecl>(decl))
+ {
+ writeEnum(*page->getFirstEntry(), enumDecl);
+ }
+ else if (AggTypeDeclBase* aggTypeDeclBase = as<AggTypeDeclBase>(decl))
+ {
+ // Find the primary decl.
+ ASTMarkup::Entry* primaryEntry = page->getFirstEntry();
+ AggTypeDeclBase* primaryDecl = aggTypeDeclBase;
+ for (auto entry : page->entries)
+ {
+ if (auto aggTypeDecl = as<AggTypeDecl>(entry->m_node))
+ {
+ primaryEntry = entry;
+ primaryDecl = aggTypeDecl;
+ break;
+ }
+ }
+ writeAggType(page, *primaryEntry, primaryDecl);
+ }
+ else if (PropertyDecl* propertyDecl = as<PropertyDecl>(decl))
+ {
+ writeProperty(*page->getFirstEntry(), propertyDecl);
+ }
+ else if (VarDecl* varDecl = as<VarDecl>(decl))
+ {
+ writeVar(*page->getFirstEntry(), varDecl);
+ }
+ else if (TypeDefDecl* typeDefDecl = as<TypeDefDecl>(decl))
+ {
+ writeTypeDef(*page->getFirstEntry(), typeDefDecl);
+ }
+}
+
+void DocMarkdownWriter::writePageRecursive(DocumentPage* page)
+{
+ writePage(page);
+ for (auto child : page->children)
+ {
+ writePageRecursive(child);
+ }
+}
+
+void writeTOCImpl(StringBuilder& sb, DocMarkdownWriter* writer, DocumentationConfig& config, DocumentPage* page);
+
+void writeTOCChildren(StringBuilder& sb, DocMarkdownWriter* writer, DocumentationConfig& config, DocumentPage* page)
+{
+ if (page->children.getCount() == 0)
+ return;
+
+ sb << R"(<ul class="toc_list">)" << "\n";
+
+ // Don't sort the root page.
+ if (page->path != "index.md")
+ sortPages(page);
+
+ Dictionary<String, List<DocumentPage*>> categories;
+ for (auto child : page->children)
+ {
+ categories[child->category].add(child);
+ }
+ List<String> categoryNames;
+ for (auto& kv : categories)
+ {
+ categoryNames.add(kv.first);
+ }
+ categoryNames.sort();
+ auto parentPath = Path::getParentDirectory(page->path);
+ parentPath.append("/");
+ for (auto& cat : categoryNames)
+ {
+ // Skip non-categorized pages first.
+ if (cat.getLength() == 0)
+ continue;
+ sb << "<li data-link=\"" << config.rootDir << parentPath << cat << "\"><span>";
+ escapeHTMLContent(sb, writer->m_categories[cat].getUnownedSlice());
+ sb << "</span>\n";
+ sb << "<ul class=\"toc_list\">\n";
+ for (auto child : categories[cat])
+ {
+ writeTOCImpl(sb, writer, config, child);
+ }
+ sb << "</ul>\n";
+ sb << "</li>\n";
+
+ // Create a landing page for the category.
+ RefPtr<DocumentPage> landingPage = new DocumentPage();
+ landingPage->title = writer->m_categories[cat];
+ landingPage->path = parentPath + cat + ".md";
+ landingPage->shortName = writer->m_categories[cat];
+ landingPage->decl = nullptr;
+ landingPage->parentPage = page;
+ landingPage->contentSB << config.preamble;
+ landingPage->contentSB << "# " << landingPage->title << "\n\nThis category contains the following declarations:\n\n";
+ for (auto child : categories[cat])
+ {
+ landingPage->contentSB << "#### [" << writer->escapeMarkdownText(child->title) << "](" <<
+ child->path << ")\n\n";
}
+ page->children.add(landingPage);
}
+
+ for (auto child : categories[""])
+ {
+ writeTOCImpl(sb, writer, config, child);
+ }
+ sb << "</ul>\n";
}
+void writeTOCImpl(StringBuilder& sb, DocMarkdownWriter* writer, DocumentationConfig& config, DocumentPage* page)
+{
+ sb << R"(<li data-link=")" << getDocPath(config, page->path) << R"("><span>)";
+ escapeHTMLContent(sb, page->shortName.getUnownedSlice());
+ sb << "</span>\n";
+ writeTOCChildren(sb, writer, config, page);
+ sb << "</li>";
+}
+
+String DocMarkdownWriter::writeTOC()
+{
+ StringBuilder sb;
+ sb << R"(<ul class="toc_root_list"><li data-link=")"
+ << m_config.rootDir << R"(index"><span>)"
+ << m_config.title << "</span>\n";
+ writeTOCChildren(sb, this, m_config, m_rootPage);
+ sb << "</li></ul>\n";
+ return sb.produceString();
+}
+
+DocumentPage* DocMarkdownWriter::getPage(Decl* decl)
+{
+ auto path = _getDocFilePath(decl);
+ RefPtr<DocumentPage> page;
+ if (m_output.tryGetValue(path, page))
+ {
+ return page.get();
+ }
+ page = new DocumentPage();
+ page->title = _getFullName(decl);
+ page->path = path;
+ page->shortName = _getName(decl);
+ page->decl = decl;
+ m_output[path] = page;
+
+ // If parent page exists, add this page to it's children
+ if (path.endsWith("index.md"))
+ path = Path::getParentDirectory(path);
+ auto parentPath = Path::getParentDirectory(path);
+ parentPath = parentPath + "/index.md";
+ RefPtr<DocumentPage> parentPage;
+ if (m_output.tryGetValue(parentPath, parentPage))
+ {
+ parentPage->children.add(page);
+ page->parentPage = parentPage.get();
+ }
+ return page.get();
+}
+
+StringBuilder* DocMarkdownWriter::getBuilder(Decl* decl)
+{
+ m_currentPage = getPage(decl);
+ return &(m_currentPage->get());
+}
+
+void writePageToDisk(DocumentPage* page)
+{
+ if (!page->skipWrite)
+ {
+ auto dir = Path::getParentDirectory(page->path);
+ if (dir.getLength())
+ Path::createDirectoryRecursive(dir);
+ File::writeAllText(page->path, page->contentSB.toString());
+ }
+ for (auto child : page->children)
+ {
+ writePageToDisk(child);
+ }
+}
+
+void DocumentPage::writeToDisk()
+{
+ writePageToDisk(this);
+}
+
+DocumentPage* DocumentPage::findChildByShortName(const UnownedStringSlice& name)
+{
+ for (auto child : children)
+ {
+ if (child->shortName == name)
+ return child;
+ }
+ return nullptr;
+}
+
+
} // namespace Slang
diff --git a/source/slang/slang-doc-markdown-writer.h b/source/slang/slang-doc-markdown-writer.h
index ff4c50759..813e674ae 100644
--- a/source/slang/slang-doc-markdown-writer.h
+++ b/source/slang/slang-doc-markdown-writer.h
@@ -11,11 +11,99 @@ namespace Slang {
class ASTBuilder;
+struct DocumentPage : public RefObject
+{
+ String title;
+ String shortName;
+ String path;
+ String category;
+ StringBuilder contentSB;
+ Decl* decl = nullptr;
+ bool skipWrite = false;
+ DocumentPage* parentPage = nullptr;
+ DocumentPage* findChildByShortName(const UnownedStringSlice& shortName);
+ StringBuilder& get() { return contentSB; }
+ List<RefPtr<DocumentPage>> children;
+
+ // List of entries to document on this page.
+ OrderedHashSet<ASTMarkup::Entry*> entries;
+ ASTMarkup::Entry* getFirstEntry() { return *entries.begin(); }
+ void writeToDisk();
+};
+
+struct DocumentationConfig
+{
+ String preamble;
+ String title;
+ String libName;
+ String rootDir;
+ HashSet<String> visibleDeclNames;
+ void parse(UnownedStringSlice configStr);
+};
+
+enum DocumentationSpanKind
+{
+ OrdinaryText,
+ InlineCode,
+};
+struct ParsedDocumentationSpan
+{
+ String text;
+ DocumentationSpanKind kind;
+};
+struct DocMarkdownWriter;
+
+struct ParsedDescription
+{
+ String ownedText;
+ List<ParsedDocumentationSpan> spans;
+ void parse(UnownedStringSlice text);
+ void write(DocMarkdownWriter* writer, Decl* decl, StringBuilder& out);
+};
+
+struct ParamDocumentation
+{
+ String name;
+ String direction;
+ ParsedDescription description;
+};
+
+enum class DocPageSection
+{
+ Description,
+ Parameter,
+ ReturnInfo,
+ Remarks,
+ Example,
+ SeeAlso,
+ InternalCallout,
+ ExperimentalCallout,
+ DeprecatedCallout,
+};
+
+struct DeclDocumentation
+{
+ Dictionary<String, ParamDocumentation> parameters;
+ Dictionary<DocPageSection, ParsedDescription> sections;
+ String categoryName;
+ String categoryText;
+
+ void parse(const UnownedStringSlice& text);
+ void writeDescription(StringBuilder& out, DocMarkdownWriter* writer, Decl* decl);
+ void writeGenericParameters(StringBuilder& out, DocMarkdownWriter* writer, Decl* decl);
+ void writeSection(StringBuilder& sb, DocMarkdownWriter* writer, Decl* decl, DocPageSection section);
+};
+
struct DocMarkdownWriter
{
typedef ASTPrinter::Part Part;
typedef ASTPrinter::PartPair PartPair;
+ enum WriteDeclMode
+ {
+ Header, Content
+ };
+
struct Signature
{
struct GenericParam
@@ -34,46 +122,59 @@ struct DocMarkdownWriter
{
typedef Requirement ThisType;
- bool operator<(const ThisType& rhs) const { return Index(target) < Index(rhs.target) || (target == rhs.target && value < rhs.value); }
+ bool operator==(const ThisType& rhs) const { return capabilitySet == rhs.capabilitySet; }
+ SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(capabilitySet == rhs.capabilitySet); }
- bool operator==(const ThisType& rhs) const { return target == rhs.target && value == rhs.value; }
- SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
-
- /// Using CodeGenTarget may not be most appropriate, perhaps it should use a CapabilityAtom
- /// For now use target, and since we always go through Source -> byte code it is fairly straight forward to understand the
- /// meaning.
- CodeGenTarget target;
- /// The 'value' requirement associated with a target. If it's empty it's just the target that is a requirement.
- String value;
+ CapabilitySet capabilitySet;
};
/// Write out all documentation to the output buffer
- void writeAll();
+ DocumentPage* writeAll(UnownedStringSlice configStr);
+ String writeTOC();
+
+ void ensureDeclPageCreated(ASTMarkup::Entry& entry);
+ String translateToHTMLWithLinks(Decl* decl, String text);
+ String translateToMarkdownWithLinks(String text, bool strictChildLookup = false);
+ String escapeMarkdownText(String text);
+ void generateSectionIndexPage(DocumentPage* page);
+ void writePageRecursive(DocumentPage* page);
+ void writePage(DocumentPage* page);
/// This will write information about *all* of the overridden versions of a function/method
- void writeCallableOverridable(const ASTMarkup::Entry& entry, CallableDecl* callable);
+ void writeCallableOverridable(DocumentPage* page, const ASTMarkup::Entry& entry, CallableDecl* callable);
void writeEnum(const ASTMarkup::Entry& entry, EnumDecl* enumDecl);
- void writeAggType(const ASTMarkup::Entry& entry, AggTypeDeclBase* aggTypeDecl);
- void writeDecl(const ASTMarkup::Entry& entry, Decl* decl);
+ void writeAggType(DocumentPage* page, const ASTMarkup::Entry& entry, AggTypeDeclBase* aggTypeDecl);
void writeVar(const ASTMarkup::Entry& entry, VarDecl* varDecl);
+ void writeProperty(const ASTMarkup::Entry& entry, PropertyDecl* propertyDecl);
+ void writeTypeDef(const ASTMarkup::Entry& entry, TypeDefDecl* typeDefDecl);
- void writePreamble(const ASTMarkup::Entry& entry);
- void writeDescription(const ASTMarkup::Entry& entry);
+ void createPage(WriteDeclMode mode, ASTMarkup::Entry& entry, Decl* decl);
+ void registerCategory(DocumentPage* page, DeclDocumentation& doc);
+
+ void writePreamble();
void writeSignature(CallableDecl* callableDecl);
+ void writeExtensionConditions(StringBuilder& sb, ExtensionDecl* decl, const char* prefix, bool isHtml);
bool isVisible(const ASTMarkup::Entry& entry);
bool isVisible(Decl* decl);
bool isVisible(const Name* name);
+ DocumentPage* findPageForToken(DocumentPage* currentPage, String token, String& outSectionName, Decl*& outDecl);
+ String findLinkForToken(DocumentPage* currentPage, String token);
+
/// Get the output string
- const StringBuilder& getOutput() const { return m_builder; }
+ Dictionary<String, RefPtr<DocumentPage>>& getOutput() { return m_output; }
+
+ DocumentPage* getPage(Decl* decl);
+ StringBuilder* getBuilder(Decl* decl);
/// Ctor.
- DocMarkdownWriter(ASTMarkup* markup, ASTBuilder* astBuilder) :
+ DocMarkdownWriter(ASTMarkup* markup, ASTBuilder* astBuilder, DiagnosticSink* sink) :
m_markup(markup),
- m_astBuilder(astBuilder)
+ m_astBuilder(astBuilder),
+ m_sink(sink)
{
}
@@ -84,13 +185,16 @@ struct DocMarkdownWriter
struct NameAndText
{
+ Decl* decl = nullptr;
String name;
String text;
};
- List<NameAndText> _getUniqueParams(const List<Decl*>& decls);
+ List<NameAndText> _getUniqueParams(const List<Decl*>& decls, DeclDocumentation* funcDoc);
String _getName(Decl* decl);
+ String _getFullName(Decl* decl);
+ String _getDocFilePath(Decl* decl);
String _getName(InheritanceDecl* decl);
NameAndText _getNameAndText(ASTMarkup::Entry* entry, Decl* decl);
@@ -120,24 +224,35 @@ struct DocMarkdownWriter
List<NameAndText> _getAsNameAndTextList(const List<Decl*>& in);
List<String> _getAsStringList(const List<Decl*>& in);
- void _appendAsBullets(const List<NameAndText>& values, char wrapChar);
+ void _appendAsBullets(const List<NameAndText>& values, bool insertLinkForName, char wrapChar);
void _appendAsBullets(const List<String>& values, char wrapChar);
void _appendCommaList(const List<String>& strings, char wrapChar);
- void _appendRequirements(const List<DocMarkdownWriter::Requirement>& requirements);
- void _maybeAppendRequirements(const UnownedStringSlice& title, const List<List<DocMarkdownWriter::Requirement>>& uniqueRequirements);
- void _writeTargetRequirements(const Requirement* reqs, Index reqsCount);
+ void _appendRequirements(const DocMarkdownWriter::Requirement& requirements);
+ void _maybeAppendRequirements(const UnownedStringSlice& title, const List<DocMarkdownWriter::Requirement>& uniqueRequirements);
+
+ void _appendExpr(StringBuilder& sb, Expr* expr);
/// Appends prefix and the list of types derived from
void _appendDerivedFrom(const UnownedStringSlice& prefix, AggTypeDeclBase* aggTypeDecl);
void _appendEscaped(const UnownedStringSlice& text);
- void _appendAggTypeName(AggTypeDeclBase* aggTypeDecl);
+ void _appendAggTypeName(const ASTMarkup::Entry& entry, Decl* aggTypeDecl);
ASTMarkup* m_markup;
ASTBuilder* m_astBuilder;
- StringBuilder m_builder;
+ DiagnosticSink* m_sink;
+ StringBuilder* m_builder = nullptr;
+ DocumentPage* m_currentPage = nullptr;
+ Dictionary<String, RefPtr<DocumentPage>> m_output;
+ RefPtr<DocumentPage> m_rootPage;
+ RefPtr<DocumentPage> m_typesPage;
+ RefPtr<DocumentPage> m_interfacesPage;
+ RefPtr<DocumentPage> m_globalDeclsPage;
+
+ DocumentationConfig m_config;
+ Dictionary<String, String> m_categories;
};
} // namespace Slang
diff --git a/source/slang/slang-language-server-completion.cpp b/source/slang/slang-language-server-completion.cpp
index 0c7f10ad7..14613d08b 100644
--- a/source/slang/slang-language-server-completion.cpp
+++ b/source/slang/slang-language-server-completion.cpp
@@ -23,7 +23,7 @@ static const char* kDeclKeywords[] = {
"protected", "typedef", "typealias", "uniform", "export", "groupshared",
"extension", "associatedtype", "namespace", "This", "using",
"__generic", "__exported", "import", "enum", "cbuffer", "tbuffer", "func",
- "functype", "typename", "each", "expand" };
+ "functype", "typename", "each", "expand", "where" };
static const char* kStmtKeywords[] = {
"if", "else", "switch", "case", "default", "return",
"try", "throw", "throws", "catch", "while", "for",
@@ -74,6 +74,16 @@ static const char* hlslSemanticNames[] = {
"SV_ShadingRate",
};
+bool isDeclKeyword(const UnownedStringSlice& slice)
+{
+ for (auto keyword : kDeclKeywords)
+ {
+ if (slice == keyword)
+ return true;
+ }
+ return false;
+}
+
SlangResult CompletionContext::tryCompleteHLSLSemantic()
{
if (version->linkage->contentAssistInfo.completionSuggestions.scopeKind !=
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 5fcf20e0a..4bdbbd0aa 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -312,8 +312,39 @@ SlangResult Session::checkPassThroughSupport(SlangPassThrough inPassThrough)
return checkExternalCompilerSupport(this, PassThroughMode(inPassThrough));
}
+void Session::writeStdlibDoc(String config)
+{
+ ASTBuilder* astBuilder = getBuiltinLinkage()->getASTBuilder();
+ SourceManager* sourceManager = getBuiltinSourceManager();
+
+ DiagnosticSink sink(sourceManager, Lexer::sourceLocationLexer);
+
+ List<String> docStrings;
+
+ // For all the modules add their doc output to docStrings
+ for (Module* stdlibModule : stdlibModules)
+ {
+ RefPtr<ASTMarkup> markup(new ASTMarkup);
+ ASTMarkupUtil::extract(stdlibModule->getModuleDecl(), sourceManager, &sink, markup);
+
+ DocMarkdownWriter writer(markup, astBuilder, &sink);
+ auto rootPage = writer.writeAll(config.getUnownedSlice());
+ File::writeAllText("toc.html", writer.writeTOC());
+ rootPage->writeToDisk();
+ }
+ ComPtr<ISlangBlob> diagnosticBlob;
+ sink.getBlobIfNeeded(diagnosticBlob.writeRef());
+ if (diagnosticBlob && diagnosticBlob->getBufferSize() != 0)
+ {
+ // Write the diagnostic blob to stdout.
+ fprintf(stderr, "%s", (const char*)diagnosticBlob->getBufferPointer());
+ }
+}
+
SlangResult Session::compileStdLib(slang::CompileStdLibFlags compileFlags)
{
+ SLANG_AST_BUILDER_RAII(m_builtinLinkage->getASTBuilder());
+
if (m_builtinLinkage->mapNameToLoadedModules.getCount())
{
// Already have a StdLib loaded
@@ -339,40 +370,15 @@ SlangResult Session::compileStdLib(slang::CompileStdLibFlags compileFlags)
if (compileFlags & slang::CompileStdLibFlag::WriteDocumentation)
{
- // Not 100% clear where best to get the ASTBuilder from, but from the linkage shouldn't
- // cause any problems with scoping
-
- ASTBuilder* astBuilder = getBuiltinLinkage()->getASTBuilder();
- SourceManager* sourceManager = getBuiltinSourceManager();
-
- DiagnosticSink sink(sourceManager, Lexer::sourceLocationLexer);
-
- List<String> docStrings;
-
- // For all the modules add their doc output to docStrings
- for (Module* stdlibModule : stdlibModules)
+ // Load config file first.
+ String configText;
+ if (SLANG_FAILED(File::readAllText("config.txt", configText)))
{
- RefPtr<ASTMarkup> markup(new ASTMarkup);
- ASTMarkupUtil::extract(stdlibModule->getModuleDecl(), sourceManager, &sink, markup);
-
- DocMarkdownWriter writer(markup, astBuilder);
- writer.writeAll();
- docStrings.add(writer.getOutput());
+ fprintf(stderr, "Error writing documentation: config file not found on current working directory.\n");
}
-
- // Combine all together in stdlib-doc.md output fiel
+ else
{
- String fileName("stdlib-doc.md");
-
- RefPtr<FileStream> stream = new FileStream;
- SLANG_RETURN_ON_FAIL(stream->init(fileName, FileMode::Create));
- StreamWriter writer;
- SLANG_RETURN_ON_FAIL(writer.init(stream));
-
- for (auto& docString : docStrings)
- {
- SLANG_RETURN_ON_FAIL(writer.write(docString));
- }
+ writeStdlibDoc(configText);
}
}
@@ -3161,28 +3167,7 @@ SlangResult FrontEndCompileRequest::executeActionsInner()
// After semantic checking is performed we can try and output doc information for this
if (optionSet.getBoolOption(CompilerOptionName::Doc))
{
- // Not 100% clear where best to get the ASTBuilder from, but from the linkage shouldn't
- // cause any problems with scoping
- ASTBuilder* astBuilder = getLinkage()->getASTBuilder();
-
- ISlangWriter* writer = getSink()->writer;
-
- // Write output to the diagnostic writer
- if (writer)
- {
- for (TranslationUnitRequest* translationUnit : translationUnits)
- {
- RefPtr<ASTMarkup> markup(new ASTMarkup);
- ASTMarkupUtil::extract(translationUnit->getModuleDecl(), getSourceManager(), getSink(), markup);
-
- // Convert to markdown
- DocMarkdownWriter markdownWriter(markup, astBuilder);
- markdownWriter.writeAll();
-
- UnownedStringSlice docText = markdownWriter.getOutput().getUnownedSlice();
- writer->write(docText.begin(), docText.getLength());
- }
- }
+ // TODO: implement the logic to output generated documents to target directory/zip file.
}
// Look up all the entry points that are expected,