summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-09-11 10:27:41 -0700
committerGitHub <noreply@github.com>2017-09-11 10:27:41 -0700
commit80fb7b05b851e645d821331fdbbcea1add686c9a (patch)
tree5f9b010837de0c78f2f96e59388bf76e4cbd8575 /source
parent0e566a63f0bafb7def65521315e9f19a2bc79e34 (diff)
parent14137cbd2ddd7deebcdf8cc85c30d534bec8e40b (diff)
Merge pull request #178 from tfoleyNV/boilerplate-generator
Initial work on boilerplate code generator
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang907
-rw-r--r--source/slang/core.meta.slang.cpp910
-rw-r--r--source/slang/glsl.meta.slang205
-rw-r--r--source/slang/glsl.meta.slang.cpp206
-rw-r--r--source/slang/hlsl.meta.slang1065
-rw-r--r--source/slang/hlsl.meta.slang.cpp1066
-rw-r--r--source/slang/slang-stdlib.cpp2197
-rw-r--r--source/slang/slang.vcxproj59
-rw-r--r--source/slang/slang.vcxproj.filters5
9 files changed, 4426 insertions, 2194 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
new file mode 100644
index 000000000..fc2d27b08
--- /dev/null
+++ b/source/slang/core.meta.slang
@@ -0,0 +1,907 @@
+// Slang `core` library
+
+// A type that can be used as an operand for builtins
+interface __BuiltinType {}
+
+// A type that can be used for arithmetic operations
+interface __BuiltinArithmeticType : __BuiltinType {}
+
+// A type that logically has a sign (positive/negative/zero)
+interface __BuiltinSignedArithmeticType : __BuiltinArithmeticType {}
+
+// A type that can represent integers
+interface __BuiltinIntegerType : __BuiltinArithmeticType {}
+
+// A type that can represent non-integers
+interface __BuiltinRealType : __BuiltinArithmeticType {}
+
+// A type that uses a floating-point representation
+interface __BuiltinFloatingPointType : __BuiltinRealType, __BuiltinSignedArithmeticType {}
+
+__generic<T,U> __intrinsic_op(Sequence) U operator,(T left, U right);
+
+__generic<T> __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse);
+__generic<T, let N : int> __intrinsic_op(select) vector<T,N> operator?:(vector<bool,N> condition, vector<T,N> ifTrue, vector<T,N> ifFalse);
+
+${{{{
+// We are going to use code generation to produce the
+// declarations for all of our base types.
+
+static const int kBaseTypeCount = sizeof(kBaseTypes) / sizeof(kBaseTypes[0]);
+for (int tt = 0; tt < kBaseTypeCount; ++tt)
+{
+ EMIT_LINE_DIRECTIVE();
+ sb << "__builtin_type(" << int(kBaseTypes[tt].tag) << ") struct " << kBaseTypes[tt].name;
+
+ // Declare interface conformances for this type
+
+ sb << "\n : __BuiltinType\n";
+
+ switch (kBaseTypes[tt].tag)
+ {
+ case BaseType::Float:
+ sb << "\n , __BuiltinFloatingPointType\n";
+ sb << "\n , __BuiltinRealType\n";
+ // fall through to:
+ case BaseType::Int:
+ sb << "\n , __BuiltinSignedArithmeticType\n";
+ // fall through to:
+ case BaseType::UInt:
+ case BaseType::UInt64:
+ sb << "\n , __BuiltinArithmeticType\n";
+ // fall through to:
+ case BaseType::Bool:
+ sb << "\n , __BuiltinType\n";
+ break;
+
+ default:
+ break;
+ }
+
+ sb << "\n{\n";
+
+
+ // Declare initializers to convert from various other types
+ for (int ss = 0; ss < kBaseTypeCount; ++ss)
+ {
+ // Don't allow conversion from `void`
+ if (kBaseTypes[ss].tag == BaseType::Void)
+ continue;
+
+ // We need to emit a modifier so that the semantic-checking
+ // layer will know it can use these operations for implicit
+ // conversion.
+ ConversionCost conversionCost = getBaseTypeConversionCost(
+ kBaseTypes[tt],
+ kBaseTypes[ss]);
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "__implicit_conversion(" << conversionCost << ")\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "__init(" << kBaseTypes[ss].name << " value);\n";
+ }
+
+ sb << "};\n";
+}
+
+
+
+// Declare vector and matrix types
+
+sb << "__generic<T = float, let N : int = 4> __magic_type(Vector) struct vector\n{\n";
+sb << " typedef T Element;\n";
+
+// Declare initializer taking a single scalar of the elemnt type
+sb << " __implicit_conversion(" << kConversionCost_ScalarToVector << ")\n";
+sb << " __init(T value);\n";
+
+sb << "};\n";
+
+// TODO: Probably need to do similar
+}}}}
+
+__generic<T = float, let R : int = 4, let C : int = 4>
+__magic_type(Matrix)
+struct matrix {};
+
+${{{{
+
+
+
+static const struct {
+ char const* name;
+ char const* glslPrefix;
+} kTypes[] =
+{
+ {"float", ""},
+ {"int", "i"},
+ {"uint", "u"},
+ {"bool", "b"},
+};
+static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]);
+
+for (int tt = 0; tt < kTypeCount; ++tt)
+{
+ // Declare HLSL vector types
+ for (int ii = 1; ii <= 4; ++ii)
+ {
+ sb << "typedef vector<" << kTypes[tt].name << "," << ii << "> " << kTypes[tt].name << ii << ";\n";
+ }
+
+ // Declare HLSL matrix types
+ for (int rr = 2; rr <= 4; ++rr)
+ for (int cc = 2; cc <= 4; ++cc)
+ {
+ sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].name << rr << "x" << cc << ";\n";
+ }
+}
+
+// Declare additional built-in generic types
+// EMIT_LINE_DIRECTIVE();
+
+
+sb << "__generic<T>\n";
+sb << "__intrinsic_type(" << kIROp_ConstantBufferType << ")\n";
+sb << "__magic_type(ConstantBuffer) struct ConstantBuffer {};\n";
+
+sb << "__generic<T>\n";
+sb << "__intrinsic_type(" << kIROp_TextureBufferType << ")\n";
+sb << "__magic_type(TextureBuffer) struct TextureBuffer {};\n";
+
+
+static const char* kComponentNames[]{ "x", "y", "z", "w" };
+static const char* kVectorNames[]{ "", "x", "xy", "xyz", "xyzw" };
+
+// Need to add constructors to the types above
+for (int N = 2; N <= 4; ++N)
+{
+ sb << "__generic<T> __extension vector<T, " << N << ">\n{\n";
+
+ // initialize from N scalars
+ sb << "__init(";
+ for (int ii = 0; ii < N; ++ii)
+ {
+ if (ii != 0) sb << ", ";
+ sb << "T " << kComponentNames[ii];
+ }
+ sb << ");\n";
+
+ // Initialize from an M-vector and then scalars
+ for (int M = 2; M < N; ++M)
+ {
+ sb << "__init(vector<T," << M << "> " << kVectorNames[M];
+ for (int ii = M; ii < N; ++ii)
+ {
+ sb << ", T " << kComponentNames[ii];
+ }
+ sb << ");\n";
+ }
+
+ // initialize from another vector of the same size
+ //
+ // TODO(tfoley): this overlaps with implicit conversions.
+ // We should look for a way that we can define implicit
+ // conversions directly in the stdlib instead...
+ sb << "__generic<U> __init(vector<U," << N << ">);\n";
+
+ // Initialize from two vectors, of size M and N-M
+ for(int M = 2; M <= (N-2); ++M)
+ {
+ int K = N - M;
+ SLANG_ASSERT(K >= 2);
+
+ sb << "__init(vector<T," << M << "> " << kVectorNames[M];
+ sb << ", vector<T," << K << "> ";
+ for (int ii = 0; ii < K; ++ii)
+ {
+ sb << kComponentNames[ii];
+ }
+ sb << ");\n";
+ }
+
+ sb << "}\n";
+}
+
+// The above extension was generic in the *type* of the vector,
+// but explicit in the *size*. We will now declare an extension
+// for each builtin type that is generic in the size.
+//
+for (int tt = 0; tt < kBaseTypeCount; ++tt)
+{
+ if(kBaseTypes[tt].tag == BaseType::Void) continue;
+
+ sb << "__generic<let N : int> __extension vector<"
+ << kBaseTypes[tt].name << ",N>\n{\n";
+
+ for (int ff = 0; ff < kBaseTypeCount; ++ff)
+ {
+ if(kBaseTypes[ff].tag == BaseType::Void) continue;
+
+ // We need a constructor to make a vector from a scalar
+ // of another type.
+
+ if( tt != ff )
+ {
+ auto cost = getBaseTypeConversionCost(
+ kBaseTypes[tt],
+ kBaseTypes[ff]);
+ cost += kConversionCost_ScalarToVector;
+
+ sb << " __implicit_conversion(" << cost << ")\n";
+ sb << " __init(" << kBaseTypes[ff].name << " value);\n";
+ }
+ }
+
+ sb << "}\n";
+}
+
+for( int R = 2; R <= 4; ++R )
+for( int C = 2; C <= 4; ++C )
+{
+ sb << "__generic<T> __extension matrix<T, " << R << "," << C << ">\n{\n";
+
+ // initialize from R*C scalars
+ sb << "__init(";
+ for( int ii = 0; ii < R; ++ii )
+ for( int jj = 0; jj < C; ++jj )
+ {
+ if ((ii+jj) != 0) sb << ", ";
+ sb << "T m" << ii << jj;
+ }
+ sb << ");\n";
+
+ // Initialize from R C-vectors
+ sb << "__init(";
+ for (int ii = 0; ii < R; ++ii)
+ {
+ if(ii != 0) sb << ", ";
+ sb << "vector<T," << C << "> row" << ii;
+ }
+ sb << ");\n";
+
+
+ // initialize from another matrix of the same size
+ //
+ // TODO(tfoley): See comment about how this overlaps
+ // with implicit conversion, in the `vector` case above
+ sb << "__generic<U> __init(matrix<U," << R << ", " << C << ">);\n";
+
+ // initialize from a matrix of larger size
+ for(int rr = R; rr <= 4; ++rr)
+ for( int cc = C; cc <= 4; ++cc )
+ {
+ if(rr == R && cc == C) continue;
+ sb << "__init(matrix<T," << rr << "," << cc << "> value);\n";
+ }
+
+ sb << "}\n";
+}
+
+// Declare built-in texture and sampler types
+
+
+
+sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ")\n";
+sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerState) << ")\n";
+sb << "struct SamplerState {};";
+
+sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n";
+sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n";
+sb << "struct SamplerComparisonState {};";
+
+// TODO(tfoley): Need to handle `RW*` variants of texture types as well...
+static const struct {
+ char const* name;
+ TextureType::Shape baseShape;
+ int coordCount;
+} kBaseTextureTypes[] = {
+ { "Texture1D", TextureType::Shape1D, 1 },
+ { "Texture2D", TextureType::Shape2D, 2 },
+ { "Texture3D", TextureType::Shape3D, 3 },
+ { "TextureCube", TextureType::ShapeCube, 3 },
+};
+static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]);
+
+
+static const struct {
+ char const* name;
+ SlangResourceAccess access;
+} kBaseTextureAccessLevels[] = {
+ { "", SLANG_RESOURCE_ACCESS_READ },
+ { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
+ { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
+};
+static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]);
+
+for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
+{
+ char const* name = kBaseTextureTypes[tt].name;
+ TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape;
+
+ for (int isArray = 0; isArray < 2; ++isArray)
+ {
+ // Arrays of 3D textures aren't allowed
+ if (isArray && baseShape == TextureType::Shape3D) continue;
+
+ for (int isMultisample = 0; isMultisample < 2; ++isMultisample)
+ for (int accessLevel = 0; accessLevel < kBaseTextureAccessLevelCount; ++accessLevel)
+ {
+ auto access = kBaseTextureAccessLevels[accessLevel].access;
+
+ // TODO: any constraints to enforce on what gets to be multisampled?
+
+ unsigned flavor = baseShape;
+ if (isArray) flavor |= TextureType::ArrayFlag;
+ if (isMultisample) flavor |= TextureType::MultisampleFlag;
+// if (isShadow) flavor |= TextureType::ShadowFlag;
+
+ flavor |= (access << 8);
+
+ // emit a generic signature
+ // TODO: allow for multisample count to come in as well...
+ sb << "__generic<T = float4> ";
+
+ sb << "__magic_type(Texture," << int(flavor) << ")\n";
+ sb << "__intrinsic_type(" << kIROp_TextureType << ", " << flavor << ")\n";
+ sb << "struct ";
+ sb << kBaseTextureAccessLevels[accessLevel].name;
+ sb << name;
+ if (isMultisample) sb << "MS";
+ if (isArray) sb << "Array";
+// if (isShadow) sb << "Shadow";
+ sb << "\n{";
+
+ if( !isMultisample )
+ {
+ sb << "float CalculateLevelOfDetail(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
+
+ sb << "float CalculateLevelOfDetailUnclamped(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
+ }
+
+ // `GetDimensions`
+
+ for(int isFloat = 0; isFloat < 2; ++isFloat)
+ for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo)
+ {
+ {
+ sb << "__glsl_version(450)\n";
+ sb << "__target_intrinsic(glsl, \"(";
+
+ int aa = 0;
+ String lodStr = "0";
+ if (includeMipInfo)
+ {
+ int mipLevelArg = aa++;
+ lodStr = "int($";
+ lodStr.append(mipLevelArg);
+ lodStr.append(")");
+ }
+
+ int cc = 0;
+ switch(baseShape)
+ {
+ case TextureType::Shape1D:
+ sb << "($" << aa++ << " = textureSize($$P, " << lodStr << "))";
+ cc = 1;
+ break;
+
+ case TextureType::Shape2D:
+ case TextureType::ShapeCube:
+ sb << "($" << aa++ << " = textureSize($$P, " << lodStr << ").x)";
+ sb << ", ($" << aa++ << " = textureSize($$P, " << lodStr << ").y)";
+ cc = 2;
+ break;
+
+ case TextureType::Shape3D:
+ sb << "($" << aa++ << " = textureSize($$P, " << lodStr << ").x)";
+ sb << ", ($" << aa++ << " = textureSize($$P, " << lodStr << ").y)";
+ sb << ", ($" << aa++ << " = textureSize($$P, " << lodStr << ").z)";
+ cc = 3;
+ break;
+
+ default:
+ SLANG_UNEXPECTED("unhandled resource shape");
+ break;
+ }
+
+ if(isArray)
+ {
+ sb << ", ($" << aa++ << " = textureSize($$P, " << lodStr << ")." << kComponentNames[cc] << ")";
+ }
+
+ if(isMultisample)
+ {
+ sb << ", ($" << aa++ << " = textureSamples($$P))";
+ }
+
+ if (includeMipInfo)
+ {
+ sb << ", ($" << aa++ << " = textureQueryLevels($$P))";
+ }
+
+
+ sb << ")\")\n";
+ sb << "__intrinsic_op\n";
+
+ }
+
+ char const* t = isFloat ? "out float " : "out uint ";
+
+ sb << "void GetDimensions(";
+ if(includeMipInfo)
+ sb << "uint mipLevel, ";
+
+ switch(baseShape)
+ {
+ case TextureType::Shape1D:
+ sb << t << "width";
+ break;
+
+ case TextureType::Shape2D:
+ case TextureType::ShapeCube:
+ sb << t << "width,";
+ sb << t << "height";
+ break;
+
+ case TextureType::Shape3D:
+ sb << t << "width,";
+ sb << t << "height,";
+ sb << t << "depth";
+ break;
+
+ default:
+ assert(!"unexpected");
+ break;
+ }
+
+ if(isArray)
+ {
+ sb << ", " << t << "elements";
+ }
+
+ if(isMultisample)
+ {
+ sb << ", " << t << "sampleCount";
+ }
+
+ if(includeMipInfo)
+ sb << ", " << t << "numberOfLevels";
+
+ sb << ");\n";
+ }
+
+ // `GetSamplePosition()`
+ if( isMultisample )
+ {
+ sb << "float2 GetSamplePosition(int s);\n";
+ }
+
+ // `Load()`
+
+ if( kBaseTextureTypes[tt].coordCount + isArray < 4 )
+ {
+ int loadCoordCount = kBaseTextureTypes[tt].coordCount + isArray + (isMultisample?0:1);
+
+ // When translating to GLSL, we need to break apart the `location` argument.
+ //
+ // TODO: this should realy be handled by having this member actually get lowered!
+ static const char* kGLSLLoadCoordsSwizzle[] = { "", "", "x", "xy", "xyz", "xyzw" };
+ static const char* kGLSLLoadLODSwizzle[] = { "", "", "y", "z", "w", "error" };
+
+ if (isMultisample)
+ {
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, $0, $1)\")\n";
+ }
+ else
+ {
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
+ }
+ sb << "__intrinsic_op\n";
+ sb << "T Load(";
+ sb << "int" << loadCoordCount << " location";
+ if(isMultisample)
+ {
+ sb << ", int sampleIndex";
+ }
+ sb << ");\n";
+
+ if (isMultisample)
+ {
+ sb << "__target_intrinsic(glsl, \"texelFetchOffset($$P, $0, $1, $2)\")\n";
+ }
+ else
+ {
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $1)\")\n";
+ }
+ sb << "__intrinsic_op\n";
+ sb << "T Load(";
+ sb << "int" << loadCoordCount << " location";
+ if(isMultisample)
+ {
+ sb << ", int sampleIndex";
+ }
+ sb << ", int" << loadCoordCount << " offset";
+ sb << ");\n";
+
+
+ sb << "T Load(";
+ sb << "int" << loadCoordCount << " location";
+ if(isMultisample)
+ {
+ sb << ", int sampleIndex";
+ }
+ sb << ", int" << kBaseTextureTypes[tt].coordCount << " offset";
+ sb << ", out uint status";
+ sb << ");\n";
+ }
+
+ if(baseShape != TextureType::ShapeCube)
+ {
+ // subscript operator
+ sb << "__intrinsic_op __subscript(uint" << kBaseTextureTypes[tt].coordCount + isArray << " location) -> T;\n";
+ }
+
+ if( !isMultisample )
+ {
+ // `Sample()`
+
+ sb << "__target_intrinsic(glsl, \"texture($$p, $1)\")\n";
+
+ // TODO: only enable if IR is being used?
+ sb << "__intrinsic_op(sample)\n";
+
+ sb << "__intrinsic_op\n";
+ sb << "T Sample(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "__target_intrinsic(glsl, \"textureOffset($$p, $1, $2)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T Sample(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+
+ sb << "T Sample(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
+ }
+ sb << "float clamp);\n";
+
+ sb << "T Sample(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
+ }
+ sb << "float clamp, out uint status);\n";
+
+
+ // `SampleBias()`
+ sb << "__target_intrinsic(glsl, \"texture($$p, $1, $2)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T SampleBias(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "__target_intrinsic(glsl, \"textureOffset($$p, $1, $2, $3)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T SampleBias(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+
+ // `SampleCmp()` and `SampleCmpLevelZero`
+ sb << "T SampleCmp(SamplerComparisonState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float compareValue";
+ sb << ");\n";
+
+ int baseCoordCount = kBaseTextureTypes[tt].coordCount;
+ int arrCoordCount = baseCoordCount + isArray;
+ if (arrCoordCount < 3)
+ {
+ int extCoordCount = arrCoordCount + 1;
+
+ if (extCoordCount < 3)
+ extCoordCount = 3;
+
+ sb << "__target_intrinsic(glsl, \"textureLod($$p, ";
+
+ sb << "vec" << extCoordCount << "($1,";
+ for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
+ {
+ sb << " 0.0,";
+ }
+ sb << "$2)";
+
+ sb << ", 0.0)\")\n";
+ }
+ else if(arrCoordCount <= 3)
+ {
+ int extCoordCount = arrCoordCount + 1;
+
+ if (extCoordCount < 3)
+ extCoordCount = 3;
+
+ sb << "__target_intrinsic(glsl, \"textureGrad($$p, ";
+
+ sb << "vec" << extCoordCount << "($1,";
+ for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
+ {
+ sb << " 0.0,";
+ }
+ sb << "$2)";
+
+ // Construct gradients
+ sb << ", vec" << baseCoordCount << "(0.0)";
+ sb << ", vec" << baseCoordCount << "(0.0)";
+ sb << ")\")\n";
+ }
+ sb << "__intrinsic_op\n";
+ sb << "T SampleCmpLevelZero(SamplerComparisonState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float compareValue";
+ sb << ");\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ // Note(tfoley): MSDN seems confused, and claims that the `offset`
+ // parameter for `SampleCmp` is available for everything but 3D
+ // textures, while `Sample` and `SampleBias` are consistent in
+ // saying they only exclude `offset` for cube maps (which makes
+ // sense). I'm going to assume the documentation for `SampleCmp`
+ // is just wrong.
+
+ sb << "T SampleCmp(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float compareValue, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+
+ sb << "T SampleCmpLevelZero(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float compareValue, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+
+
+ sb << "__target_intrinsic(glsl, \"textureGrad($$p, $1, $2, $3)\")\n";
+ sb << "__intrinsic_op(sampleGrad)\n";
+ sb << "T SampleGrad(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY";
+ sb << ");\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "__target_intrinsic(glsl, \"textureGradOffset($$p, $1, $2, $3, $4)\")\n";
+ sb << "__intrinsic_op(sampleGrad)\n";
+ sb << "T SampleGrad(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+
+ // `SampleLevel`
+
+ sb << "__target_intrinsic(glsl, \"textureLod($$p, $1, $2)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T SampleLevel(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float level);\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "__target_intrinsic(glsl, \"textureLodOffset($$p, $1, $2, $3)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T SampleLevel(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float level, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+ }
+
+ sb << "\n};\n";
+
+ // `Gather*()` operations are handled via an `extension` declaration,
+ // because this lets us capture the element type of the texture.
+ //
+ // TODO: longer-term there should be something like a `TextureElementType`
+ // interface, that both scalars and vectors implement, that then exposes
+ // a `Scalar` associated type, and `Gather` can return `vector<T.Scalar, 4>`.
+ //
+ static const struct {
+ char const* genericPrefix;
+ char const* elementType;
+ } kGatherExtensionCases[] = {
+ { "__generic<T, let N : int>", "vector<T,N>" },
+
+ // TODO: need a case here for scalars `T`, but also
+ // need to ensure that case doesn't accidentally match
+ // for `T = vector<...>`, which requires actual checking
+ // of constraints on generic parameters.
+ };
+ for(auto cc : kGatherExtensionCases)
+ {
+ // TODO: this should really be an `if` around the entire `Gather` logic
+ if (isMultisample) break;
+
+ EMIT_LINE_DIRECTIVE();
+ sb << cc.genericPrefix << " __extension ";
+ sb << kBaseTextureAccessLevels[accessLevel].name;
+ sb << name;
+ if (isArray) sb << "Array";
+ sb << "<" << cc.elementType << " >";
+ sb << "\n{\n";
+
+
+ // `Gather`
+ // (tricky because it returns a 4-vector of the element type
+ // of the texture components...)
+ //
+ // TODO: is it actually correct to restrict these so that, e.g.,
+ // `GatherAlpha()` isn't allowed on `Texture2D<float3>` because
+ // it nominally doesn't have an alpha component?
+ static const struct {
+ int componentIndex;
+ char const* componentName;
+ } kGatherComponets[] = {
+ { 0, "" },
+ { 0, "Red" },
+ { 1, "Green" },
+ { 2, "Blue" },
+ { 3, "Alpha" },
+ };
+
+ for(auto kk : kGatherComponets)
+ {
+ auto componentIndex = kk.componentIndex;
+ auto componentName = kk.componentName;
+
+ EMIT_LINE_DIRECTIVE();
+
+ sb << "__target_intrinsic(glsl, \"textureGather($$p, $1, " << componentIndex << ")\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "__target_intrinsic(glsl, \"textureGatherOffset($$p, $1, $2, " << componentIndex << ")\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
+ sb << "out uint status);\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "__target_intrinsic(glsl, \"textureGatherOffsets($$p, $1, int" << kBaseTextureTypes[tt].coordCount << "[]($2, $3, $4, $5), " << componentIndex << ")\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4);\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4, ";
+ sb << "out uint status);\n";
+ }
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "\n}\n";
+ }
+ }
+ }
+}
+
+
+for (auto op : unaryOps)
+{
+ for (auto type : kBaseTypes)
+ {
+ if ((type.flags & op.flags) == 0)
+ continue;
+
+ char const* fixity = (op.flags & POSTFIX) != 0 ? "__postfix " : "__prefix ";
+ char const* qual = (op.flags & ASSIGNMENT) != 0 ? "in out " : "";
+
+ // scalar version
+ sb << fixity;
+ sb << "__intrinsic_op(" << int(op.opCode) << ") " << type.name << " operator" << op.opName << "(" << qual << type.name << " value);\n";
+
+ // vector version
+ sb << "__generic<let N : int> ";
+ sb << fixity;
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << type.name << ",N> operator" << op.opName << "(" << qual << "vector<" << type.name << ",N> value);\n";
+
+ // matrix version
+ sb << "__generic<let N : int, let M : int> ";
+ sb << fixity;
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << type.name << ",N,M> operator" << op.opName << "(" << qual << "matrix<" << type.name << ",N,M> value);\n";
+ }
+}
+
+for (auto op : binaryOps)
+{
+ for (auto type : kBaseTypes)
+ {
+ if ((type.flags & op.flags) == 0)
+ continue;
+
+ char const* leftType = type.name;
+ char const* rightType = leftType;
+ char const* resultType = leftType;
+
+ if (op.flags & COMPARISON) resultType = "bool";
+
+ char const* leftQual = "";
+ if(op.flags & ASSIGNMENT) leftQual = "in out ";
+
+ // TODO: handle `SHIFT`
+
+ // scalar version
+ sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftQual << leftType << " left, " << rightType << " right);\n";
+
+ // vector version
+ sb << "__generic<let N : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n";
+
+ // matrix version
+
+ // skip matrix-matrix multiply operations here, so that GLSL doesn't see them
+ switch (op.opCode)
+ {
+ case kIROp_Mul:
+ case kIRPseudoOp_MulAssign:
+ break;
+
+ default:
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
+ break;
+ }
+
+ // We are going to go ahead and explicitly define combined
+ // operations for the scalar-op-vector, etc. cases, rather
+ // than rely on promotion rules.
+
+ // scalar-vector and scalar-matrix
+ if (!(op.flags & ASSIGNMENT))
+ {
+ sb << "__generic<let N : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n";
+
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << leftType << " left, matrix<" << rightType << ",N,M> right);\n";
+ }
+
+ // vector-scalar and matrix-scalar
+ sb << "__generic<let N : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n";
+
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, " << rightType << " right);\n";
+ }
+}
+
+}}}}
diff --git a/source/slang/core.meta.slang.cpp b/source/slang/core.meta.slang.cpp
new file mode 100644
index 000000000..8395f11f5
--- /dev/null
+++ b/source/slang/core.meta.slang.cpp
@@ -0,0 +1,910 @@
+sb << "// Slang `core` library\n";
+sb << "\n";
+sb << "// A type that can be used as an operand for builtins\n";
+sb << "interface __BuiltinType {}\n";
+sb << "\n";
+sb << "// A type that can be used for arithmetic operations\n";
+sb << "interface __BuiltinArithmeticType : __BuiltinType {}\n";
+sb << "\n";
+sb << "// A type that logically has a sign (positive/negative/zero)\n";
+sb << "interface __BuiltinSignedArithmeticType : __BuiltinArithmeticType {}\n";
+sb << "\n";
+sb << "// A type that can represent integers\n";
+sb << "interface __BuiltinIntegerType : __BuiltinArithmeticType {}\n";
+sb << "\n";
+sb << "// A type that can represent non-integers\n";
+sb << "interface __BuiltinRealType : __BuiltinArithmeticType {}\n";
+sb << "\n";
+sb << "// A type that uses a floating-point representation\n";
+sb << "interface __BuiltinFloatingPointType : __BuiltinRealType, __BuiltinSignedArithmeticType {}\n";
+sb << "\n";
+sb << "__generic<T,U> __intrinsic_op(Sequence) U operator,(T left, U right);\n";
+sb << "\n";
+sb << "__generic<T> __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse);\n";
+sb << "__generic<T, let N : int> __intrinsic_op(select) vector<T,N> operator?:(vector<bool,N> condition, vector<T,N> ifTrue, vector<T,N> ifFalse);\n";
+sb << "\n";
+sb << "";
+
+// We are going to use code generation to produce the
+// declarations for all of our base types.
+
+static const int kBaseTypeCount = sizeof(kBaseTypes) / sizeof(kBaseTypes[0]);
+for (int tt = 0; tt < kBaseTypeCount; ++tt)
+{
+ EMIT_LINE_DIRECTIVE();
+ sb << "__builtin_type(" << int(kBaseTypes[tt].tag) << ") struct " << kBaseTypes[tt].name;
+
+ // Declare interface conformances for this type
+
+ sb << "\n : __BuiltinType\n";
+
+ switch (kBaseTypes[tt].tag)
+ {
+ case BaseType::Float:
+ sb << "\n , __BuiltinFloatingPointType\n";
+ sb << "\n , __BuiltinRealType\n";
+ // fall through to:
+ case BaseType::Int:
+ sb << "\n , __BuiltinSignedArithmeticType\n";
+ // fall through to:
+ case BaseType::UInt:
+ case BaseType::UInt64:
+ sb << "\n , __BuiltinArithmeticType\n";
+ // fall through to:
+ case BaseType::Bool:
+ sb << "\n , __BuiltinType\n";
+ break;
+
+ default:
+ break;
+ }
+
+ sb << "\n{\n";
+
+
+ // Declare initializers to convert from various other types
+ for (int ss = 0; ss < kBaseTypeCount; ++ss)
+ {
+ // Don't allow conversion from `void`
+ if (kBaseTypes[ss].tag == BaseType::Void)
+ continue;
+
+ // We need to emit a modifier so that the semantic-checking
+ // layer will know it can use these operations for implicit
+ // conversion.
+ ConversionCost conversionCost = getBaseTypeConversionCost(
+ kBaseTypes[tt],
+ kBaseTypes[ss]);
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "__implicit_conversion(" << conversionCost << ")\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "__init(" << kBaseTypes[ss].name << " value);\n";
+ }
+
+ sb << "};\n";
+}
+
+
+
+// Declare vector and matrix types
+
+sb << "__generic<T = float, let N : int = 4> __magic_type(Vector) struct vector\n{\n";
+sb << " typedef T Element;\n";
+
+// Declare initializer taking a single scalar of the elemnt type
+sb << " __implicit_conversion(" << kConversionCost_ScalarToVector << ")\n";
+sb << " __init(T value);\n";
+
+sb << "};\n";
+
+// TODO: Probably need to do similar
+sb << "\n";
+sb << "\n";
+sb << "__generic<T = float, let R : int = 4, let C : int = 4>\n";
+sb << "__magic_type(Matrix)\n";
+sb << "struct matrix {};\n";
+sb << "\n";
+sb << "";
+
+
+
+
+static const struct {
+ char const* name;
+ char const* glslPrefix;
+} kTypes[] =
+{
+ {"float", ""},
+ {"int", "i"},
+ {"uint", "u"},
+ {"bool", "b"},
+};
+static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]);
+
+for (int tt = 0; tt < kTypeCount; ++tt)
+{
+ // Declare HLSL vector types
+ for (int ii = 1; ii <= 4; ++ii)
+ {
+ sb << "typedef vector<" << kTypes[tt].name << "," << ii << "> " << kTypes[tt].name << ii << ";\n";
+ }
+
+ // Declare HLSL matrix types
+ for (int rr = 2; rr <= 4; ++rr)
+ for (int cc = 2; cc <= 4; ++cc)
+ {
+ sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].name << rr << "x" << cc << ";\n";
+ }
+}
+
+// Declare additional built-in generic types
+// EMIT_LINE_DIRECTIVE();
+
+
+sb << "__generic<T>\n";
+sb << "__intrinsic_type(" << kIROp_ConstantBufferType << ")\n";
+sb << "__magic_type(ConstantBuffer) struct ConstantBuffer {};\n";
+
+sb << "__generic<T>\n";
+sb << "__intrinsic_type(" << kIROp_TextureBufferType << ")\n";
+sb << "__magic_type(TextureBuffer) struct TextureBuffer {};\n";
+
+
+static const char* kComponentNames[]{ "x", "y", "z", "w" };
+static const char* kVectorNames[]{ "", "x", "xy", "xyz", "xyzw" };
+
+// Need to add constructors to the types above
+for (int N = 2; N <= 4; ++N)
+{
+ sb << "__generic<T> __extension vector<T, " << N << ">\n{\n";
+
+ // initialize from N scalars
+ sb << "__init(";
+ for (int ii = 0; ii < N; ++ii)
+ {
+ if (ii != 0) sb << ", ";
+ sb << "T " << kComponentNames[ii];
+ }
+ sb << ");\n";
+
+ // Initialize from an M-vector and then scalars
+ for (int M = 2; M < N; ++M)
+ {
+ sb << "__init(vector<T," << M << "> " << kVectorNames[M];
+ for (int ii = M; ii < N; ++ii)
+ {
+ sb << ", T " << kComponentNames[ii];
+ }
+ sb << ");\n";
+ }
+
+ // initialize from another vector of the same size
+ //
+ // TODO(tfoley): this overlaps with implicit conversions.
+ // We should look for a way that we can define implicit
+ // conversions directly in the stdlib instead...
+ sb << "__generic<U> __init(vector<U," << N << ">);\n";
+
+ // Initialize from two vectors, of size M and N-M
+ for(int M = 2; M <= (N-2); ++M)
+ {
+ int K = N - M;
+ SLANG_ASSERT(K >= 2);
+
+ sb << "__init(vector<T," << M << "> " << kVectorNames[M];
+ sb << ", vector<T," << K << "> ";
+ for (int ii = 0; ii < K; ++ii)
+ {
+ sb << kComponentNames[ii];
+ }
+ sb << ");\n";
+ }
+
+ sb << "}\n";
+}
+
+// The above extension was generic in the *type* of the vector,
+// but explicit in the *size*. We will now declare an extension
+// for each builtin type that is generic in the size.
+//
+for (int tt = 0; tt < kBaseTypeCount; ++tt)
+{
+ if(kBaseTypes[tt].tag == BaseType::Void) continue;
+
+ sb << "__generic<let N : int> __extension vector<"
+ << kBaseTypes[tt].name << ",N>\n{\n";
+
+ for (int ff = 0; ff < kBaseTypeCount; ++ff)
+ {
+ if(kBaseTypes[ff].tag == BaseType::Void) continue;
+
+ // We need a constructor to make a vector from a scalar
+ // of another type.
+
+ if( tt != ff )
+ {
+ auto cost = getBaseTypeConversionCost(
+ kBaseTypes[tt],
+ kBaseTypes[ff]);
+ cost += kConversionCost_ScalarToVector;
+
+ sb << " __implicit_conversion(" << cost << ")\n";
+ sb << " __init(" << kBaseTypes[ff].name << " value);\n";
+ }
+ }
+
+ sb << "}\n";
+}
+
+for( int R = 2; R <= 4; ++R )
+for( int C = 2; C <= 4; ++C )
+{
+ sb << "__generic<T> __extension matrix<T, " << R << "," << C << ">\n{\n";
+
+ // initialize from R*C scalars
+ sb << "__init(";
+ for( int ii = 0; ii < R; ++ii )
+ for( int jj = 0; jj < C; ++jj )
+ {
+ if ((ii+jj) != 0) sb << ", ";
+ sb << "T m" << ii << jj;
+ }
+ sb << ");\n";
+
+ // Initialize from R C-vectors
+ sb << "__init(";
+ for (int ii = 0; ii < R; ++ii)
+ {
+ if(ii != 0) sb << ", ";
+ sb << "vector<T," << C << "> row" << ii;
+ }
+ sb << ");\n";
+
+
+ // initialize from another matrix of the same size
+ //
+ // TODO(tfoley): See comment about how this overlaps
+ // with implicit conversion, in the `vector` case above
+ sb << "__generic<U> __init(matrix<U," << R << ", " << C << ">);\n";
+
+ // initialize from a matrix of larger size
+ for(int rr = R; rr <= 4; ++rr)
+ for( int cc = C; cc <= 4; ++cc )
+ {
+ if(rr == R && cc == C) continue;
+ sb << "__init(matrix<T," << rr << "," << cc << "> value);\n";
+ }
+
+ sb << "}\n";
+}
+
+// Declare built-in texture and sampler types
+
+
+
+sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ")\n";
+sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerState) << ")\n";
+sb << "struct SamplerState {};";
+
+sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n";
+sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n";
+sb << "struct SamplerComparisonState {};";
+
+// TODO(tfoley): Need to handle `RW*` variants of texture types as well...
+static const struct {
+ char const* name;
+ TextureType::Shape baseShape;
+ int coordCount;
+} kBaseTextureTypes[] = {
+ { "Texture1D", TextureType::Shape1D, 1 },
+ { "Texture2D", TextureType::Shape2D, 2 },
+ { "Texture3D", TextureType::Shape3D, 3 },
+ { "TextureCube", TextureType::ShapeCube, 3 },
+};
+static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]);
+
+
+static const struct {
+ char const* name;
+ SlangResourceAccess access;
+} kBaseTextureAccessLevels[] = {
+ { "", SLANG_RESOURCE_ACCESS_READ },
+ { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
+ { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
+};
+static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]);
+
+for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
+{
+ char const* name = kBaseTextureTypes[tt].name;
+ TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape;
+
+ for (int isArray = 0; isArray < 2; ++isArray)
+ {
+ // Arrays of 3D textures aren't allowed
+ if (isArray && baseShape == TextureType::Shape3D) continue;
+
+ for (int isMultisample = 0; isMultisample < 2; ++isMultisample)
+ for (int accessLevel = 0; accessLevel < kBaseTextureAccessLevelCount; ++accessLevel)
+ {
+ auto access = kBaseTextureAccessLevels[accessLevel].access;
+
+ // TODO: any constraints to enforce on what gets to be multisampled?
+
+ unsigned flavor = baseShape;
+ if (isArray) flavor |= TextureType::ArrayFlag;
+ if (isMultisample) flavor |= TextureType::MultisampleFlag;
+// if (isShadow) flavor |= TextureType::ShadowFlag;
+
+ flavor |= (access << 8);
+
+ // emit a generic signature
+ // TODO: allow for multisample count to come in as well...
+ sb << "__generic<T = float4> ";
+
+ sb << "__magic_type(Texture," << int(flavor) << ")\n";
+ sb << "__intrinsic_type(" << kIROp_TextureType << ", " << flavor << ")\n";
+ sb << "struct ";
+ sb << kBaseTextureAccessLevels[accessLevel].name;
+ sb << name;
+ if (isMultisample) sb << "MS";
+ if (isArray) sb << "Array";
+// if (isShadow) sb << "Shadow";
+ sb << "\n{";
+
+ if( !isMultisample )
+ {
+ sb << "float CalculateLevelOfDetail(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
+
+ sb << "float CalculateLevelOfDetailUnclamped(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
+ }
+
+ // `GetDimensions`
+
+ for(int isFloat = 0; isFloat < 2; ++isFloat)
+ for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo)
+ {
+ {
+ sb << "__glsl_version(450)\n";
+ sb << "__target_intrinsic(glsl, \"(";
+
+ int aa = 0;
+ String lodStr = "0";
+ if (includeMipInfo)
+ {
+ int mipLevelArg = aa++;
+ lodStr = "int($";
+ lodStr.append(mipLevelArg);
+ lodStr.append(")");
+ }
+
+ int cc = 0;
+ switch(baseShape)
+ {
+ case TextureType::Shape1D:
+ sb << "($" << aa++ << " = textureSize($P, " << lodStr << "))";
+ cc = 1;
+ break;
+
+ case TextureType::Shape2D:
+ case TextureType::ShapeCube:
+ sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)";
+ sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)";
+ cc = 2;
+ break;
+
+ case TextureType::Shape3D:
+ sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)";
+ sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)";
+ sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").z)";
+ cc = 3;
+ break;
+
+ default:
+ SLANG_UNEXPECTED("unhandled resource shape");
+ break;
+ }
+
+ if(isArray)
+ {
+ sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ")." << kComponentNames[cc] << ")";
+ }
+
+ if(isMultisample)
+ {
+ sb << ", ($" << aa++ << " = textureSamples($P))";
+ }
+
+ if (includeMipInfo)
+ {
+ sb << ", ($" << aa++ << " = textureQueryLevels($P))";
+ }
+
+
+ sb << ")\")\n";
+ sb << "__intrinsic_op\n";
+
+ }
+
+ char const* t = isFloat ? "out float " : "out uint ";
+
+ sb << "void GetDimensions(";
+ if(includeMipInfo)
+ sb << "uint mipLevel, ";
+
+ switch(baseShape)
+ {
+ case TextureType::Shape1D:
+ sb << t << "width";
+ break;
+
+ case TextureType::Shape2D:
+ case TextureType::ShapeCube:
+ sb << t << "width,";
+ sb << t << "height";
+ break;
+
+ case TextureType::Shape3D:
+ sb << t << "width,";
+ sb << t << "height,";
+ sb << t << "depth";
+ break;
+
+ default:
+ assert(!"unexpected");
+ break;
+ }
+
+ if(isArray)
+ {
+ sb << ", " << t << "elements";
+ }
+
+ if(isMultisample)
+ {
+ sb << ", " << t << "sampleCount";
+ }
+
+ if(includeMipInfo)
+ sb << ", " << t << "numberOfLevels";
+
+ sb << ");\n";
+ }
+
+ // `GetSamplePosition()`
+ if( isMultisample )
+ {
+ sb << "float2 GetSamplePosition(int s);\n";
+ }
+
+ // `Load()`
+
+ if( kBaseTextureTypes[tt].coordCount + isArray < 4 )
+ {
+ int loadCoordCount = kBaseTextureTypes[tt].coordCount + isArray + (isMultisample?0:1);
+
+ // When translating to GLSL, we need to break apart the `location` argument.
+ //
+ // TODO: this should realy be handled by having this member actually get lowered!
+ static const char* kGLSLLoadCoordsSwizzle[] = { "", "", "x", "xy", "xyz", "xyzw" };
+ static const char* kGLSLLoadLODSwizzle[] = { "", "", "y", "z", "w", "error" };
+
+ if (isMultisample)
+ {
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, $0, $1)\")\n";
+ }
+ else
+ {
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
+ }
+ sb << "__intrinsic_op\n";
+ sb << "T Load(";
+ sb << "int" << loadCoordCount << " location";
+ if(isMultisample)
+ {
+ sb << ", int sampleIndex";
+ }
+ sb << ");\n";
+
+ if (isMultisample)
+ {
+ sb << "__target_intrinsic(glsl, \"texelFetchOffset($P, $0, $1, $2)\")\n";
+ }
+ else
+ {
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $1)\")\n";
+ }
+ sb << "__intrinsic_op\n";
+ sb << "T Load(";
+ sb << "int" << loadCoordCount << " location";
+ if(isMultisample)
+ {
+ sb << ", int sampleIndex";
+ }
+ sb << ", int" << loadCoordCount << " offset";
+ sb << ");\n";
+
+
+ sb << "T Load(";
+ sb << "int" << loadCoordCount << " location";
+ if(isMultisample)
+ {
+ sb << ", int sampleIndex";
+ }
+ sb << ", int" << kBaseTextureTypes[tt].coordCount << " offset";
+ sb << ", out uint status";
+ sb << ");\n";
+ }
+
+ if(baseShape != TextureType::ShapeCube)
+ {
+ // subscript operator
+ sb << "__intrinsic_op __subscript(uint" << kBaseTextureTypes[tt].coordCount + isArray << " location) -> T;\n";
+ }
+
+ if( !isMultisample )
+ {
+ // `Sample()`
+
+ sb << "__target_intrinsic(glsl, \"texture($p, $1)\")\n";
+
+ // TODO: only enable if IR is being used?
+ sb << "__intrinsic_op(sample)\n";
+
+ sb << "__intrinsic_op\n";
+ sb << "T Sample(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T Sample(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+
+ sb << "T Sample(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
+ }
+ sb << "float clamp);\n";
+
+ sb << "T Sample(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
+ }
+ sb << "float clamp, out uint status);\n";
+
+
+ // `SampleBias()`
+ sb << "__target_intrinsic(glsl, \"texture($p, $1, $2)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T SampleBias(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2, $3)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T SampleBias(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+
+ // `SampleCmp()` and `SampleCmpLevelZero`
+ sb << "T SampleCmp(SamplerComparisonState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float compareValue";
+ sb << ");\n";
+
+ int baseCoordCount = kBaseTextureTypes[tt].coordCount;
+ int arrCoordCount = baseCoordCount + isArray;
+ if (arrCoordCount < 3)
+ {
+ int extCoordCount = arrCoordCount + 1;
+
+ if (extCoordCount < 3)
+ extCoordCount = 3;
+
+ sb << "__target_intrinsic(glsl, \"textureLod($p, ";
+
+ sb << "vec" << extCoordCount << "($1,";
+ for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
+ {
+ sb << " 0.0,";
+ }
+ sb << "$2)";
+
+ sb << ", 0.0)\")\n";
+ }
+ else if(arrCoordCount <= 3)
+ {
+ int extCoordCount = arrCoordCount + 1;
+
+ if (extCoordCount < 3)
+ extCoordCount = 3;
+
+ sb << "__target_intrinsic(glsl, \"textureGrad($p, ";
+
+ sb << "vec" << extCoordCount << "($1,";
+ for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
+ {
+ sb << " 0.0,";
+ }
+ sb << "$2)";
+
+ // Construct gradients
+ sb << ", vec" << baseCoordCount << "(0.0)";
+ sb << ", vec" << baseCoordCount << "(0.0)";
+ sb << ")\")\n";
+ }
+ sb << "__intrinsic_op\n";
+ sb << "T SampleCmpLevelZero(SamplerComparisonState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float compareValue";
+ sb << ");\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ // Note(tfoley): MSDN seems confused, and claims that the `offset`
+ // parameter for `SampleCmp` is available for everything but 3D
+ // textures, while `Sample` and `SampleBias` are consistent in
+ // saying they only exclude `offset` for cube maps (which makes
+ // sense). I'm going to assume the documentation for `SampleCmp`
+ // is just wrong.
+
+ sb << "T SampleCmp(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float compareValue, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+
+ sb << "T SampleCmpLevelZero(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float compareValue, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+
+
+ sb << "__target_intrinsic(glsl, \"textureGrad($p, $1, $2, $3)\")\n";
+ sb << "__intrinsic_op(sampleGrad)\n";
+ sb << "T SampleGrad(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY";
+ sb << ");\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "__target_intrinsic(glsl, \"textureGradOffset($p, $1, $2, $3, $4)\")\n";
+ sb << "__intrinsic_op(sampleGrad)\n";
+ sb << "T SampleGrad(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+
+ // `SampleLevel`
+
+ sb << "__target_intrinsic(glsl, \"textureLod($p, $1, $2)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T SampleLevel(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float level);\n";
+
+ if( baseShape != TextureType::ShapeCube )
+ {
+ sb << "__target_intrinsic(glsl, \"textureLodOffset($p, $1, $2, $3)\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "T SampleLevel(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
+ sb << "float level, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+ }
+ }
+
+ sb << "\n};\n";
+
+ // `Gather*()` operations are handled via an `extension` declaration,
+ // because this lets us capture the element type of the texture.
+ //
+ // TODO: longer-term there should be something like a `TextureElementType`
+ // interface, that both scalars and vectors implement, that then exposes
+ // a `Scalar` associated type, and `Gather` can return `vector<T.Scalar, 4>`.
+ //
+ static const struct {
+ char const* genericPrefix;
+ char const* elementType;
+ } kGatherExtensionCases[] = {
+ { "__generic<T, let N : int>", "vector<T,N>" },
+
+ // TODO: need a case here for scalars `T`, but also
+ // need to ensure that case doesn't accidentally match
+ // for `T = vector<...>`, which requires actual checking
+ // of constraints on generic parameters.
+ };
+ for(auto cc : kGatherExtensionCases)
+ {
+ // TODO: this should really be an `if` around the entire `Gather` logic
+ if (isMultisample) break;
+
+ EMIT_LINE_DIRECTIVE();
+ sb << cc.genericPrefix << " __extension ";
+ sb << kBaseTextureAccessLevels[accessLevel].name;
+ sb << name;
+ if (isArray) sb << "Array";
+ sb << "<" << cc.elementType << " >";
+ sb << "\n{\n";
+
+
+ // `Gather`
+ // (tricky because it returns a 4-vector of the element type
+ // of the texture components...)
+ //
+ // TODO: is it actually correct to restrict these so that, e.g.,
+ // `GatherAlpha()` isn't allowed on `Texture2D<float3>` because
+ // it nominally doesn't have an alpha component?
+ static const struct {
+ int componentIndex;
+ char const* componentName;
+ } kGatherComponets[] = {
+ { 0, "" },
+ { 0, "Red" },
+ { 1, "Green" },
+ { 2, "Blue" },
+ { 3, "Alpha" },
+ };
+
+ for(auto kk : kGatherComponets)
+ {
+ auto componentIndex = kk.componentIndex;
+ auto componentName = kk.componentName;
+
+ EMIT_LINE_DIRECTIVE();
+
+ sb << "__target_intrinsic(glsl, \"textureGather($p, $1, " << componentIndex << ")\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $1, $2, " << componentIndex << ")\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
+ sb << "out uint status);\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $1, int" << kBaseTextureTypes[tt].coordCount << "[]($2, $3, $4, $5), " << componentIndex << ")\")\n";
+ sb << "__intrinsic_op\n";
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4);\n";
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
+ sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, ";
+ sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4, ";
+ sb << "out uint status);\n";
+ }
+
+ EMIT_LINE_DIRECTIVE();
+ sb << "\n}\n";
+ }
+ }
+ }
+}
+
+
+for (auto op : unaryOps)
+{
+ for (auto type : kBaseTypes)
+ {
+ if ((type.flags & op.flags) == 0)
+ continue;
+
+ char const* fixity = (op.flags & POSTFIX) != 0 ? "__postfix " : "__prefix ";
+ char const* qual = (op.flags & ASSIGNMENT) != 0 ? "in out " : "";
+
+ // scalar version
+ sb << fixity;
+ sb << "__intrinsic_op(" << int(op.opCode) << ") " << type.name << " operator" << op.opName << "(" << qual << type.name << " value);\n";
+
+ // vector version
+ sb << "__generic<let N : int> ";
+ sb << fixity;
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << type.name << ",N> operator" << op.opName << "(" << qual << "vector<" << type.name << ",N> value);\n";
+
+ // matrix version
+ sb << "__generic<let N : int, let M : int> ";
+ sb << fixity;
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << type.name << ",N,M> operator" << op.opName << "(" << qual << "matrix<" << type.name << ",N,M> value);\n";
+ }
+}
+
+for (auto op : binaryOps)
+{
+ for (auto type : kBaseTypes)
+ {
+ if ((type.flags & op.flags) == 0)
+ continue;
+
+ char const* leftType = type.name;
+ char const* rightType = leftType;
+ char const* resultType = leftType;
+
+ if (op.flags & COMPARISON) resultType = "bool";
+
+ char const* leftQual = "";
+ if(op.flags & ASSIGNMENT) leftQual = "in out ";
+
+ // TODO: handle `SHIFT`
+
+ // scalar version
+ sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftQual << leftType << " left, " << rightType << " right);\n";
+
+ // vector version
+ sb << "__generic<let N : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n";
+
+ // matrix version
+
+ // skip matrix-matrix multiply operations here, so that GLSL doesn't see them
+ switch (op.opCode)
+ {
+ case kIROp_Mul:
+ case kIRPseudoOp_MulAssign:
+ break;
+
+ default:
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
+ break;
+ }
+
+ // We are going to go ahead and explicitly define combined
+ // operations for the scalar-op-vector, etc. cases, rather
+ // than rely on promotion rules.
+
+ // scalar-vector and scalar-matrix
+ if (!(op.flags & ASSIGNMENT))
+ {
+ sb << "__generic<let N : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n";
+
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << leftType << " left, matrix<" << rightType << ",N,M> right);\n";
+ }
+
+ // vector-scalar and matrix-scalar
+ sb << "__generic<let N : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n";
+
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, " << rightType << " right);\n";
+ }
+}
+
+sb << "\n";
+sb << "";
diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang
new file mode 100644
index 000000000..878cea188
--- /dev/null
+++ b/source/slang/glsl.meta.slang
@@ -0,0 +1,205 @@
+// Slang GLSL compatibility library
+
+${{{{
+
+static const struct {
+ char const* name;
+ char const* glslPrefix;
+} kTypes[] =
+{
+ {"float", ""},
+ {"int", "i"},
+ {"uint", "u"},
+ {"bool", "b"},
+};
+static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]);
+
+for( int tt = 0; tt < kTypeCount; ++tt )
+{
+ // Declare GLSL aliases for HLSL types
+ for (int vv = 2; vv <= 4; ++vv)
+ {
+ sb << "typedef vector<" << kTypes[tt].name << "," << vv << "> " << kTypes[tt].glslPrefix << "vec" << vv << ";\n";
+ sb << "typedef matrix<" << kTypes[tt].name << "," << vv << "," << vv << "> " << kTypes[tt].glslPrefix << "mat" << vv << ";\n";
+ }
+ for (int rr = 2; rr <= 4; ++rr)
+ for (int cc = 2; cc <= 4; ++cc)
+ {
+ sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].glslPrefix << "mat" << rr << "x" << cc << ";\n";
+ }
+}
+
+// Multiplication operations for vectors + matrices
+
+// scalar-vector and vector-scalar
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(mul) vector<T,N> operator*(vector<T,N> x, T y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(mul) vector<T,N> operator*(T x, vector<T,N> y);\n";
+
+// scalar-matrix and matrix-scalar
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(mul) matrix<T,N,M> operator*(matrix<T,N,M> x, T y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(mul) matrix<T,N,M> operator*(T x, matrix<T,N,M> y);\n";
+
+// vector-vector (dot product)
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(dot) T operator*(vector<T,N> x, vector<T,N> y);\n";
+
+// vector-matrix
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulVectorMatrix) vector<T,M> operator*(vector<T,N> x, matrix<T,N,M> y);\n";
+
+// matrix-vector
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulMatrixVector) vector<T,N> operator*(matrix<T,N,M> x, vector<T,M> y);\n";
+
+// matrix-matrix
+sb << "__generic<T : __BuiltinArithmeticType, let R : int, let N : int, let C : int> __intrinsic_op(mulMatrixMatrix) matrix<T,R,C> operator*(matrix<T,R,N> x, matrix<T,N,C> y);\n";
+
+
+
+//
+
+// TODO(tfoley): Need to handle `RW*` variants of texture types as well...
+static const struct {
+ char const* name;
+ TextureType::Shape baseShape;
+ int coordCount;
+} kBaseTextureTypes[] = {
+ { "1D", TextureType::Shape1D, 1 },
+ { "2D", TextureType::Shape2D, 2 },
+ { "3D", TextureType::Shape3D, 3 },
+ { "Cube", TextureType::ShapeCube, 3 },
+ { "Buffer", TextureType::ShapeBuffer, 1 },
+};
+static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]);
+
+
+static const struct {
+ char const* name;
+ SlangResourceAccess access;
+} kBaseTextureAccessLevels[] = {
+ { "", SLANG_RESOURCE_ACCESS_READ },
+ { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
+ { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
+};
+static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]);
+
+for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
+{
+ char const* shapeName = kBaseTextureTypes[tt].name;
+ TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape;
+
+ for (int isArray = 0; isArray < 2; ++isArray)
+ {
+ // Arrays of 3D textures aren't allowed
+ if (isArray && baseShape == TextureType::Shape3D) continue;
+
+ for (int isMultisample = 0; isMultisample < 2; ++isMultisample)
+ {
+ auto readAccess = SLANG_RESOURCE_ACCESS_READ;
+ auto readWriteAccess = SLANG_RESOURCE_ACCESS_READ_WRITE;
+
+ // TODO: any constraints to enforce on what gets to be multisampled?
+
+
+ unsigned flavor = baseShape;
+ if (isArray) flavor |= TextureType::ArrayFlag;
+ if (isMultisample) flavor |= TextureType::MultisampleFlag;
+// if (isShadow) flavor |= TextureType::ShadowFlag;
+
+
+
+ unsigned readFlavor = flavor | (readAccess << 8);
+ unsigned readWriteFlavor = flavor | (readWriteAccess << 8);
+
+ StringBuilder nameBuilder;
+ nameBuilder << shapeName;
+ if (isMultisample) nameBuilder << "MS";
+ if (isArray) nameBuilder << "Array";
+ auto name = nameBuilder.ProduceString();
+
+ sb << "__generic<T> ";
+ sb << "__magic_type(TextureSampler," << int(readFlavor) << ") struct ";
+ sb << "__sampler" << name;
+ sb << " {};\n";
+
+ sb << "__generic<T> ";
+ sb << "__magic_type(Texture," << int(readFlavor) << ") struct ";
+ sb << "__texture" << name;
+ sb << " {};\n";
+
+ sb << "__generic<T> ";
+ sb << "__magic_type(GLSLImageType," << int(readWriteFlavor) << ") struct ";
+ sb << "__image" << name;
+ sb << " {};\n";
+
+ // TODO(tfoley): flesh this out for all the available prefixes
+ static const struct
+ {
+ char const* prefix;
+ char const* elementType;
+ } kTextureElementTypes[] = {
+ { "", "vec4" },
+ { "i", "ivec4" },
+ { "u", "uvec4" },
+ { nullptr, nullptr },
+ };
+ for( auto ee = kTextureElementTypes; ee->prefix; ++ee )
+ {
+ sb << "typedef __sampler" << name << "<" << ee->elementType << "> " << ee->prefix << "sampler" << name << ";\n";
+ sb << "typedef __texture" << name << "<" << ee->elementType << "> " << ee->prefix << "texture" << name << ";\n";
+ sb << "typedef __image" << name << "<" << ee->elementType << "> " << ee->prefix << "image" << name << ";\n";
+ }
+ }
+ }
+}
+
+sb << "__generic<T> __magic_type(GLSLInputParameterBlockType) struct __GLSLInputParameterBlock {};\n";
+sb << "__generic<T> __magic_type(GLSLOutputParameterBlockType) struct __GLSLOutputParameterBlock {};\n";
+sb << "__generic<T> __magic_type(GLSLShaderStorageBufferType) struct __GLSLShaderStorageBuffer {};\n";
+
+sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ") struct sampler {};";
+
+sb << "__magic_type(GLSLInputAttachmentType) struct subpassInput {};";
+
+// Define additional keywords
+
+sb << "syntax buffer : GLSLBufferModifier;\n";
+
+// [GLSL 4.3] Storage Qualifiers
+
+// TODO: need to support `shared` here with its GLSL meaning
+
+sb << "syntax patch : GLSLPatchModifier;\n";
+// `centroid` and `sample` handled centrally
+
+// [GLSL 4.5] Interpolation Qualifiers
+sb << "syntax smooth : SimpleModifier;\n";
+sb << "syntax flat : SimpleModifier;\n";
+sb << "syntax noperspectie : SimpleModifier;\n";
+
+
+// [GLSL 4.3.2] Constant Qualifier
+
+// We need to handle GLSL `const` separately from HLSL `const`,
+// since they mean such different things.
+
+// [GLSL 4.7.2] Precision Qualifiers
+sb << "syntax highp : SimpleModifier;\n";
+sb << "syntax mediump : SimpleModifier;\n";
+sb << "syntax lowp : SimpleModifier;\n";
+
+// [GLSL 4.8.1] The Invariant Qualifier
+
+sb << "syntax invariant : SimpleModifier;\n";
+
+// [GLSL 4.10] Memory Qualifiers
+
+sb << "syntax coherent : SimpleModifier;\n";
+sb << "syntax volatile : SimpleModifier;\n";
+sb << "syntax restrict : SimpleModifier;\n";
+sb << "syntax readonly : GLSLReadOnlyModifier;\n";
+sb << "syntax writeonly : GLSLWriteOnlyModifier;\n";
+
+// We will treat `subroutine` as a qualifier for now
+sb << "syntax subroutine : SimpleModifier;\n";
+
+
+
+}}}} \ No newline at end of file
diff --git a/source/slang/glsl.meta.slang.cpp b/source/slang/glsl.meta.slang.cpp
new file mode 100644
index 000000000..e43a51ea9
--- /dev/null
+++ b/source/slang/glsl.meta.slang.cpp
@@ -0,0 +1,206 @@
+sb << "// Slang GLSL compatibility library\n";
+sb << "\n";
+sb << "";
+
+
+static const struct {
+ char const* name;
+ char const* glslPrefix;
+} kTypes[] =
+{
+ {"float", ""},
+ {"int", "i"},
+ {"uint", "u"},
+ {"bool", "b"},
+};
+static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]);
+
+for( int tt = 0; tt < kTypeCount; ++tt )
+{
+ // Declare GLSL aliases for HLSL types
+ for (int vv = 2; vv <= 4; ++vv)
+ {
+ sb << "typedef vector<" << kTypes[tt].name << "," << vv << "> " << kTypes[tt].glslPrefix << "vec" << vv << ";\n";
+ sb << "typedef matrix<" << kTypes[tt].name << "," << vv << "," << vv << "> " << kTypes[tt].glslPrefix << "mat" << vv << ";\n";
+ }
+ for (int rr = 2; rr <= 4; ++rr)
+ for (int cc = 2; cc <= 4; ++cc)
+ {
+ sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].glslPrefix << "mat" << rr << "x" << cc << ";\n";
+ }
+}
+
+// Multiplication operations for vectors + matrices
+
+// scalar-vector and vector-scalar
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(mul) vector<T,N> operator*(vector<T,N> x, T y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(mul) vector<T,N> operator*(T x, vector<T,N> y);\n";
+
+// scalar-matrix and matrix-scalar
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(mul) matrix<T,N,M> operator*(matrix<T,N,M> x, T y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(mul) matrix<T,N,M> operator*(T x, matrix<T,N,M> y);\n";
+
+// vector-vector (dot product)
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(dot) T operator*(vector<T,N> x, vector<T,N> y);\n";
+
+// vector-matrix
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulVectorMatrix) vector<T,M> operator*(vector<T,N> x, matrix<T,N,M> y);\n";
+
+// matrix-vector
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulMatrixVector) vector<T,N> operator*(matrix<T,N,M> x, vector<T,M> y);\n";
+
+// matrix-matrix
+sb << "__generic<T : __BuiltinArithmeticType, let R : int, let N : int, let C : int> __intrinsic_op(mulMatrixMatrix) matrix<T,R,C> operator*(matrix<T,R,N> x, matrix<T,N,C> y);\n";
+
+
+
+//
+
+// TODO(tfoley): Need to handle `RW*` variants of texture types as well...
+static const struct {
+ char const* name;
+ TextureType::Shape baseShape;
+ int coordCount;
+} kBaseTextureTypes[] = {
+ { "1D", TextureType::Shape1D, 1 },
+ { "2D", TextureType::Shape2D, 2 },
+ { "3D", TextureType::Shape3D, 3 },
+ { "Cube", TextureType::ShapeCube, 3 },
+ { "Buffer", TextureType::ShapeBuffer, 1 },
+};
+static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]);
+
+
+static const struct {
+ char const* name;
+ SlangResourceAccess access;
+} kBaseTextureAccessLevels[] = {
+ { "", SLANG_RESOURCE_ACCESS_READ },
+ { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
+ { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
+};
+static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]);
+
+for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
+{
+ char const* shapeName = kBaseTextureTypes[tt].name;
+ TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape;
+
+ for (int isArray = 0; isArray < 2; ++isArray)
+ {
+ // Arrays of 3D textures aren't allowed
+ if (isArray && baseShape == TextureType::Shape3D) continue;
+
+ for (int isMultisample = 0; isMultisample < 2; ++isMultisample)
+ {
+ auto readAccess = SLANG_RESOURCE_ACCESS_READ;
+ auto readWriteAccess = SLANG_RESOURCE_ACCESS_READ_WRITE;
+
+ // TODO: any constraints to enforce on what gets to be multisampled?
+
+
+ unsigned flavor = baseShape;
+ if (isArray) flavor |= TextureType::ArrayFlag;
+ if (isMultisample) flavor |= TextureType::MultisampleFlag;
+// if (isShadow) flavor |= TextureType::ShadowFlag;
+
+
+
+ unsigned readFlavor = flavor | (readAccess << 8);
+ unsigned readWriteFlavor = flavor | (readWriteAccess << 8);
+
+ StringBuilder nameBuilder;
+ nameBuilder << shapeName;
+ if (isMultisample) nameBuilder << "MS";
+ if (isArray) nameBuilder << "Array";
+ auto name = nameBuilder.ProduceString();
+
+ sb << "__generic<T> ";
+ sb << "__magic_type(TextureSampler," << int(readFlavor) << ") struct ";
+ sb << "__sampler" << name;
+ sb << " {};\n";
+
+ sb << "__generic<T> ";
+ sb << "__magic_type(Texture," << int(readFlavor) << ") struct ";
+ sb << "__texture" << name;
+ sb << " {};\n";
+
+ sb << "__generic<T> ";
+ sb << "__magic_type(GLSLImageType," << int(readWriteFlavor) << ") struct ";
+ sb << "__image" << name;
+ sb << " {};\n";
+
+ // TODO(tfoley): flesh this out for all the available prefixes
+ static const struct
+ {
+ char const* prefix;
+ char const* elementType;
+ } kTextureElementTypes[] = {
+ { "", "vec4" },
+ { "i", "ivec4" },
+ { "u", "uvec4" },
+ { nullptr, nullptr },
+ };
+ for( auto ee = kTextureElementTypes; ee->prefix; ++ee )
+ {
+ sb << "typedef __sampler" << name << "<" << ee->elementType << "> " << ee->prefix << "sampler" << name << ";\n";
+ sb << "typedef __texture" << name << "<" << ee->elementType << "> " << ee->prefix << "texture" << name << ";\n";
+ sb << "typedef __image" << name << "<" << ee->elementType << "> " << ee->prefix << "image" << name << ";\n";
+ }
+ }
+ }
+}
+
+sb << "__generic<T> __magic_type(GLSLInputParameterBlockType) struct __GLSLInputParameterBlock {};\n";
+sb << "__generic<T> __magic_type(GLSLOutputParameterBlockType) struct __GLSLOutputParameterBlock {};\n";
+sb << "__generic<T> __magic_type(GLSLShaderStorageBufferType) struct __GLSLShaderStorageBuffer {};\n";
+
+sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ") struct sampler {};";
+
+sb << "__magic_type(GLSLInputAttachmentType) struct subpassInput {};";
+
+// Define additional keywords
+
+sb << "syntax buffer : GLSLBufferModifier;\n";
+
+// [GLSL 4.3] Storage Qualifiers
+
+// TODO: need to support `shared` here with its GLSL meaning
+
+sb << "syntax patch : GLSLPatchModifier;\n";
+// `centroid` and `sample` handled centrally
+
+// [GLSL 4.5] Interpolation Qualifiers
+sb << "syntax smooth : SimpleModifier;\n";
+sb << "syntax flat : SimpleModifier;\n";
+sb << "syntax noperspectie : SimpleModifier;\n";
+
+
+// [GLSL 4.3.2] Constant Qualifier
+
+// We need to handle GLSL `const` separately from HLSL `const`,
+// since they mean such different things.
+
+// [GLSL 4.7.2] Precision Qualifiers
+sb << "syntax highp : SimpleModifier;\n";
+sb << "syntax mediump : SimpleModifier;\n";
+sb << "syntax lowp : SimpleModifier;\n";
+
+// [GLSL 4.8.1] The Invariant Qualifier
+
+sb << "syntax invariant : SimpleModifier;\n";
+
+// [GLSL 4.10] Memory Qualifiers
+
+sb << "syntax coherent : SimpleModifier;\n";
+sb << "syntax volatile : SimpleModifier;\n";
+sb << "syntax restrict : SimpleModifier;\n";
+sb << "syntax readonly : GLSLReadOnlyModifier;\n";
+sb << "syntax writeonly : GLSLWriteOnlyModifier;\n";
+
+// We will treat `subroutine` as a qualifier for now
+sb << "syntax subroutine : SimpleModifier;\n";
+
+
+
+sb << "";
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
new file mode 100644
index 000000000..3b4b85b91
--- /dev/null
+++ b/source/slang/hlsl.meta.slang
@@ -0,0 +1,1065 @@
+// Slang HLSL compatibility library
+
+typedef uint UINT;
+
+__generic<T> __magic_type(HLSLAppendStructuredBufferType) struct AppendStructuredBuffer
+{
+ __intrinsic_op void Append(T value);
+
+ __intrinsic_op void GetDimensions(
+ out uint numStructs,
+ out uint stride);
+};
+
+__magic_type(HLSLByteAddressBufferType) struct ByteAddressBuffer
+{
+ __intrinsic_op void GetDimensions(
+ out uint dim);
+
+ __intrinsic_op uint Load(int location);
+ __intrinsic_op uint Load(int location, out uint status);
+
+ __intrinsic_op uint2 Load2(int location);
+ __intrinsic_op uint2 Load2(int location, out uint status);
+
+ __intrinsic_op uint3 Load3(int location);
+ __intrinsic_op uint3 Load3(int location, out uint status);
+
+ __intrinsic_op uint4 Load4(int location);
+ __intrinsic_op uint4 Load4(int location, out uint status);
+};
+
+__generic<T> __magic_type(HLSLStructuredBufferType) struct StructuredBuffer
+{
+ __intrinsic_op void GetDimensions(
+ out uint numStructs,
+ out uint stride);
+
+ __intrinsic_op T Load(int location);
+ __intrinsic_op T Load(int location, out uint status);
+
+ __intrinsic_op __subscript(uint index) -> T;
+};
+
+__generic<T> __magic_type(HLSLConsumeStructuredBufferType) struct ConsumeStructuredBuffer
+{
+ __intrinsic_op T Consume();
+
+ __intrinsic_op void GetDimensions(
+ out uint numStructs,
+ out uint stride);
+};
+
+__generic<T, let N : int> __magic_type(HLSLInputPatchType) struct InputPatch
+{
+ __intrinsic_op __subscript(uint index) -> T;
+};
+
+__generic<T, let N : int> __magic_type(HLSLOutputPatchType) struct OutputPatch
+{
+ __intrinsic_op __subscript(uint index) -> T { set; }
+};
+
+__magic_type(HLSLRWByteAddressBufferType) struct RWByteAddressBuffer
+{
+ // Note(tfoley): supports alll operations from `ByteAddressBuffer`
+ // TODO(tfoley): can this be made a sub-type?
+
+ __intrinsic_op void GetDimensions(
+ out uint dim);
+
+ __intrinsic_op uint Load(int location);
+ __intrinsic_op uint Load(int location, out uint status);
+
+ __intrinsic_op uint2 Load2(int location);
+ __intrinsic_op uint2 Load2(int location, out uint status);
+
+ __intrinsic_op uint3 Load3(int location);
+ __intrinsic_op uint3 Load3(int location, out uint status);
+
+ __intrinsic_op uint4 Load4(int location);
+ __intrinsic_op uint4 Load4(int location, out uint status);
+
+ // Added operations:
+
+ __intrinsic_op void InterlockedAdd(
+ UINT dest,
+ UINT value,
+ out UINT original_value);
+ __intrinsic_op void InterlockedAdd(
+ UINT dest,
+ UINT value);
+
+ __intrinsic_op void InterlockedAnd(
+ UINT dest,
+ UINT value,
+ out UINT original_value);
+ __intrinsic_op void InterlockedAnd(
+ UINT dest,
+ UINT value);
+
+ __intrinsic_op void InterlockedCompareExchange(
+ UINT dest,
+ UINT compare_value,
+ UINT value,
+ out UINT original_value);
+ __intrinsic_op void InterlockedCompareExchange(
+ UINT dest,
+ UINT compare_value,
+ UINT value);
+
+ __intrinsic_op void InterlockedCompareStore(
+ UINT dest,
+ UINT compare_value,
+ UINT value);
+ __intrinsic_op void InterlockedCompareStore(
+ UINT dest,
+ UINT compare_value);
+
+ __intrinsic_op void InterlockedExchange(
+ UINT dest,
+ UINT value,
+ out UINT original_value);
+ __intrinsic_op void InterlockedExchange(
+ UINT dest,
+ UINT value);
+
+ __intrinsic_op void InterlockedMax(
+ UINT dest,
+ UINT value,
+ out UINT original_value);
+ __intrinsic_op void InterlockedMax(
+ UINT dest,
+ UINT value);
+
+ __intrinsic_op void InterlockedMin(
+ UINT dest,
+ UINT value,
+ out UINT original_value);
+ __intrinsic_op void InterlockedMin(
+ UINT dest,
+ UINT value);
+
+ __intrinsic_op void InterlockedOr(
+ UINT dest,
+ UINT value,
+ out UINT original_value);
+ __intrinsic_op void InterlockedOr(
+ UINT dest,
+ UINT value);
+
+ __intrinsic_op void InterlockedXor(
+ UINT dest,
+ UINT value,
+ out UINT original_value);
+ __intrinsic_op void InterlockedXor(
+ UINT dest,
+ UINT value);
+
+ __intrinsic_op void Store(
+ uint address,
+ uint value);
+
+ __intrinsic_op void Store2(
+ uint address,
+ uint2 value);
+
+ __intrinsic_op void Store3(
+ uint address,
+ uint3 value);
+
+ __intrinsic_op void Store4(
+ uint address,
+ uint4 value);
+};
+
+__generic<T> __magic_type(HLSLRWStructuredBufferType) struct RWStructuredBuffer
+{
+ __intrinsic_op uint DecrementCounter();
+
+ __intrinsic_op void GetDimensions(
+ out uint numStructs,
+ out uint stride);
+
+ __intrinsic_op void IncrementCounter();
+
+ __intrinsic_op T Load(int location);
+ __intrinsic_op T Load(int location, out uint status);
+
+ __intrinsic_op __subscript(uint index) -> T { get; set; }
+};
+
+__generic<T> __magic_type(HLSLPointStreamType) struct PointStream
+{
+ void Append(T value);
+ void RestartStrip();
+};
+
+__generic<T> __magic_type(HLSLLineStreamType) struct LineStream
+{
+ void Append(T value);
+ void RestartStrip();
+};
+
+__generic<T> __magic_type(HLSLTriangleStreamType) struct TriangleStream
+{
+ void Append(T value);
+ void RestartStrip();
+};
+
+// Note(tfoley): Trying to systematically add all the HLSL builtins
+
+// Try to terminate the current draw or dispatch call (HLSL SM 4.0)
+__intrinsic_op void abort();
+
+// Absolute value (HLSL SM 1.0)
+__generic<T : __BuiltinSignedArithmeticType> __intrinsic_op T abs(T x);
+__generic<T : __BuiltinSignedArithmeticType, let N : int> __intrinsic_op vector<T,N> abs(vector<T,N> x);
+__generic<T : __BuiltinSignedArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> abs(matrix<T,N,M> x);
+
+// Inverse cosine (HLSL SM 1.0)
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T acos(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> acos(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> acos(matrix<T,N,M> x);
+
+// Test if all components are non-zero (HLSL SM 1.0)
+__generic<T : __BuiltinType> __intrinsic_op T all(T x);
+__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> all(vector<T,N> x);
+__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> all(matrix<T,N,M> x);
+
+// Barrier for writes to all memory spaces (HLSL SM 5.0)
+__intrinsic_op void AllMemoryBarrier();
+
+// Thread-group sync and barrier for writes to all memory spaces (HLSL SM 5.0)
+__intrinsic_op void AllMemoryBarrierWithGroupSync();
+
+// Test if any components is non-zero (HLSL SM 1.0)
+__generic<T : __BuiltinType> __intrinsic_op T any(T x);
+__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> any(vector<T,N> x);
+__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> any(matrix<T,N,M> x);
+
+
+// Reinterpret bits as a double (HLSL SM 5.0)
+__intrinsic_op double asdouble(uint lowbits, uint highbits);
+
+// Reinterpret bits as a float (HLSL SM 4.0)
+__intrinsic_op float asfloat( int x);
+__intrinsic_op float asfloat(uint x);
+__generic<let N : int> __intrinsic_op vector<float,N> asfloat(vector< int,N> x);
+__generic<let N : int> __intrinsic_op vector<float,N> asfloat(vector<uint,N> x);
+__generic<let N : int, let M : int> __intrinsic_op matrix<float,N,M> asfloat(matrix< int,N,M> x);
+__generic<let N : int, let M : int> __intrinsic_op matrix<float,N,M> asfloat(matrix<uint,N,M> x);
+
+
+// Inverse sine (HLSL SM 1.0)
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T asin(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> asin(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> asin(matrix<T,N,M> x);
+
+// Reinterpret bits as an int (HLSL SM 4.0)
+__intrinsic_op int asint(float x);
+__intrinsic_op int asint(uint x);
+__generic<let N : int> __intrinsic_op vector<int,N> asint(vector<float,N> x);
+__generic<let N : int> __intrinsic_op vector<int,N> asint(vector<uint,N> x);
+__generic<let N : int, let M : int> __intrinsic_op matrix<int,N,M> asint(matrix<float,N,M> x);
+__generic<let N : int, let M : int> __intrinsic_op matrix<int,N,M> asint(matrix<uint,N,M> x);
+
+// Reinterpret bits of double as a uint (HLSL SM 5.0)
+__intrinsic_op void asuint(double value, out uint lowbits, out uint highbits);
+
+// Reinterpret bits as a uint (HLSL SM 4.0)
+__intrinsic_op uint asuint(float x);
+__intrinsic_op uint asuint(int x);
+__generic<let N : int> __intrinsic_op vector<uint,N> asuint(vector<float,N> x);
+__generic<let N : int> __intrinsic_op vector<uint,N> asuint(vector<int,N> x);
+__generic<let N : int, let M : int> __intrinsic_op matrix<uint,N,M> asuint(matrix<float,N,M> x);
+__generic<let N : int, let M : int> __intrinsic_op matrix<uint,N,M> asuint(matrix<int,N,M> x);
+
+// Inverse tangent (HLSL SM 1.0)
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T atan(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> atan(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> atan(matrix<T,N,M> x);
+
+__generic<T : __BuiltinFloatingPointType>
+__target_intrinsic(glsl,"atan($0,$1)")
+__intrinsic_op
+T atan2(T y, T x);
+
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__target_intrinsic(glsl,"atan($0,$1)")
+__intrinsic_op
+vector<T,N> atan2(vector<T,N> y, vector<T,N> x);
+
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__target_intrinsic(glsl,"atan($0,$1)")
+__intrinsic_op
+matrix<T,N,M> atan2(matrix<T,N,M> y, matrix<T,N,M> x);
+
+// Ceiling (HLSL SM 1.0)
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T ceil(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> ceil(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> ceil(matrix<T,N,M> x);
+
+
+// Check access status to tiled resource
+__intrinsic_op bool CheckAccessFullyMapped(uint status);
+
+// Clamp (HLSL SM 1.0)
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T clamp(T x, T min, T max);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> clamp(vector<T,N> x, vector<T,N> min, vector<T,N> max);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> clamp(matrix<T,N,M> x, matrix<T,N,M> min, matrix<T,N,M> max);
+
+// Clip (discard) fragment conditionally
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op void clip(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op void clip(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op void clip(matrix<T,N,M> x);
+
+// Cosine
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T cos(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> cos(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> cos(matrix<T,N,M> x);
+
+// Hyperbolic cosine
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T cosh(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> cosh(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> cosh(matrix<T,N,M> x);
+
+// Population count
+__intrinsic_op uint countbits(uint value);
+
+// Cross product
+__generic<T : __BuiltinArithmeticType> __intrinsic_op vector<T,3> cross(vector<T,3> x, vector<T,3> y);
+
+// Convert encoded color
+__intrinsic_op int4 D3DCOLORtoUBYTE4(float4 x);
+
+// Partial-difference derivatives
+__generic<T : __BuiltinFloatingPointType>
+__target_intrinsic(glsl, dFdx)
+__intrinsic_op
+T ddx(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__target_intrinsic(glsl, dFdx)
+__intrinsic_op
+vector<T,N> ddx(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__target_intrinsic(glsl, dFdx)
+__intrinsic_op
+matrix<T,N,M> ddx(matrix<T,N,M> x);
+
+__generic<T : __BuiltinFloatingPointType>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdxCoarse)
+__intrinsic_op
+T ddx_coarse(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdxCoarse)
+__intrinsic_op
+vector<T,N> ddx_coarse(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdxCoarse)
+__intrinsic_op
+matrix<T,N,M> ddx_coarse(matrix<T,N,M> x);
+
+__generic<T : __BuiltinFloatingPointType>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdxFine)
+__intrinsic_op
+T ddx_fine(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdxFine)
+__intrinsic_op
+vector<T,N> ddx_fine(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdxFine)
+__intrinsic_op
+matrix<T,N,M> ddx_fine(matrix<T,N,M> x);
+
+__generic<T : __BuiltinFloatingPointType>
+__target_intrinsic(glsl, dFdy)
+__intrinsic_op
+T ddy(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__target_intrinsic(glsl, dFdy)
+__intrinsic_op
+vector<T,N> ddy(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__target_intrinsic(glsl, dFdy)
+__intrinsic_op
+ matrix<T,N,M> ddy(matrix<T,N,M> x);
+
+__generic<T : __BuiltinFloatingPointType>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdyCoarse)
+__intrinsic_op
+T ddy_coarse(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdyCoarse)
+__intrinsic_op
+vector<T,N> ddy_coarse(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdyCoarse)
+__intrinsic_op
+matrix<T,N,M> ddy_coarse(matrix<T,N,M> x);
+
+__generic<T : __BuiltinFloatingPointType>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdyFine)
+__intrinsic_op
+T ddy_fine(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdyFine)
+__intrinsic_op
+vector<T,N> ddy_fine(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__glsl_extension(GL_ARB_derivative_control)
+__target_intrinsic(glsl, dFdyFine)
+__intrinsic_op
+matrix<T,N,M> ddy_fine(matrix<T,N,M> x);
+
+
+// Radians to degrees
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T degrees(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> degrees(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> degrees(matrix<T,N,M> x);
+
+// Matrix determinant
+
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op T determinant(matrix<T,N,N> m);
+
+// Barrier for device memory
+__intrinsic_op void DeviceMemoryBarrier();
+__intrinsic_op void DeviceMemoryBarrierWithGroupSync();
+
+// Vector distance
+
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op T distance(vector<T,N> x, vector<T,N> y);
+
+// Vector dot product
+
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op T dot(vector<T,N> x, vector<T,N> y);
+
+// Helper for computing distance terms for lighting (obsolete)
+
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op vector<T,4> dst(vector<T,4> x, vector<T,4> y);
+
+// Error message
+
+// __intrinsic_op void errorf( string format, ... );
+
+// Attribute evaluation
+
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T EvaluateAttributeAtCentroid(T x);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> EvaluateAttributeAtCentroid(vector<T,N> x);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> EvaluateAttributeAtCentroid(matrix<T,N,M> x);
+
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T EvaluateAttributeAtSample(T x, uint sampleindex);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> EvaluateAttributeAtSample(vector<T,N> x, uint sampleindex);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> EvaluateAttributeAtSample(matrix<T,N,M> x, uint sampleindex);
+
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T EvaluateAttributeSnapped(T x, int2 offset);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> EvaluateAttributeSnapped(vector<T,N> x, int2 offset);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> EvaluateAttributeSnapped(matrix<T,N,M> x, int2 offset);
+
+// Base-e exponent
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T exp(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> exp(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> exp(matrix<T,N,M> x);
+
+// Base-2 exponent
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T exp2(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> exp2(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> exp2(matrix<T,N,M> x);
+
+// Convert 16-bit float stored in low bits of integer
+__intrinsic_op float f16tof32(uint value);
+__generic<let N : int> __intrinsic_op vector<float,N> f16tof32(vector<uint,N> value);
+
+// Convert to 16-bit float stored in low bits of integer
+__intrinsic_op uint f32tof16(float value);
+__generic<let N : int> __intrinsic_op vector<uint,N> f32tof16(vector<float,N> value);
+
+// Flip surface normal to face forward, if needed
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op 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
+__intrinsic_op int firstbithigh(int value);
+__generic<let N : int> __intrinsic_op vector<int,N> firstbithigh(vector<int,N> value);
+
+__intrinsic_op uint firstbithigh(uint value);
+__generic<let N : int> __intrinsic_op vector<uint,N> firstbithigh(vector<uint,N> value);
+
+// Find first set bit starting at low bit and working up
+__intrinsic_op int firstbitlow(int value);
+__generic<let N : int> __intrinsic_op vector<int,N> firstbitlow(vector<int,N> value);
+
+__intrinsic_op uint firstbitlow(uint value);
+__generic<let N : int> __intrinsic_op vector<uint,N> firstbitlow(vector<uint,N> value);
+
+// Floor (HLSL SM 1.0)
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T floor(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> floor(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> floor(matrix<T,N,M> x);
+
+// Fused multiply-add for doubles
+__intrinsic_op double fma(double a, double b, double c);
+__generic<let N : int> __intrinsic_op vector<double, N> fma(vector<double, N> a, vector<double, N> b, vector<double, N> c);
+__generic<let N : int, let M : int> __intrinsic_op matrix<double,N,M> fma(matrix<double,N,M> a, matrix<double,N,M> b, matrix<double,N,M> c);
+
+// Floating point remainder of x/y
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T fmod(T x, T y);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> fmod(vector<T,N> x, vector<T,N> y);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> fmod(matrix<T,N,M> x, matrix<T,N,M> y);
+
+// Fractional part
+__generic<T : __BuiltinFloatingPointType>
+__target_intrinsic(glsl, fract)
+__intrinsic_op
+T frac(T x);
+
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__target_intrinsic(glsl, fract)
+__intrinsic_op
+vector<T,N> frac(vector<T,N> x);
+
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__target_intrinsic(glsl, fract)
+__intrinsic_op
+matrix<T,N,M> frac(matrix<T,N,M> x);
+
+// Split float into mantissa and exponent
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T frexp(T x, out T exp);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> frexp(vector<T,N> x, out vector<T,N> exp);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> frexp(matrix<T,N,M> x, out matrix<T,N,M> exp);
+
+// Texture filter width
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T fwidth(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> fwidth(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> fwidth(matrix<T,N,M> x);
+
+// Get number of samples in render target
+__intrinsic_op uint GetRenderTargetSampleCount();
+
+// Get position of given sample
+__intrinsic_op float2 GetRenderTargetSamplePosition(int Index);
+
+// Group memory barrier
+__intrinsic_op void GroupMemoryBarrier();
+__intrinsic_op void GroupMemoryBarrierWithGroupSync();
+
+// Atomics
+__intrinsic_op void InterlockedAdd(in out int dest, int value, out int original_value);
+__intrinsic_op void InterlockedAdd(in out uint dest, uint value, out uint original_value);
+
+__intrinsic_op void InterlockedAnd(in out int dest, int value, out int original_value);
+__intrinsic_op void InterlockedAnd(in out uint dest, uint value, out uint original_value);
+
+__intrinsic_op void InterlockedCompareExchange(in out int dest, int compare_value, int value, out int original_value);
+__intrinsic_op void InterlockedCompareExchange(in out uint dest, uint compare_value, uint value, out uint original_value);
+
+__intrinsic_op void InterlockedCompareStore(in out int dest, int compare_value, int value);
+__intrinsic_op void InterlockedCompareStore(in out uint dest, uint compare_value, uint value);
+
+__intrinsic_op void InterlockedExchange(in out int dest, int value, out int original_value);
+__intrinsic_op void InterlockedExchange(in out uint dest, uint value, out uint original_value);
+
+__intrinsic_op void InterlockedMax(in out int dest, int value, out int original_value);
+__intrinsic_op void InterlockedMax(in out uint dest, uint value, out uint original_value);
+
+__intrinsic_op void InterlockedMin(in out int dest, int value, out int original_value);
+__intrinsic_op void InterlockedMin(in out uint dest, uint value, out uint original_value);
+
+__intrinsic_op void InterlockedOr(in out int dest, int value, out int original_value);
+__intrinsic_op void InterlockedOr(in out uint dest, uint value, out uint original_value);
+
+__intrinsic_op void InterlockedXor(in out int dest, int value, out int original_value);
+__intrinsic_op void InterlockedXor(in out uint dest, uint value, out uint original_value);
+
+// Is floating-point value finite?
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op bool isfinite(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<bool,N> isfinite(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<bool,N,M> isfinite(matrix<T,N,M> x);
+
+// Is floating-point value infinite?
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op bool isinf(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<bool,N> isinf(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<bool,N,M> isinf(matrix<T,N,M> x);
+
+// Is floating-point value not-a-number?
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op bool isnan(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<bool,N> isnan(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<bool,N,M> isnan(matrix<T,N,M> x);
+
+// Construct float from mantissa and exponent
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T ldexp(T x, T exp);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> ldexp(vector<T,N> x, vector<T,N> exp);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> ldexp(matrix<T,N,M> x, matrix<T,N,M> exp);
+
+// Vector length
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op T length(vector<T,N> x);
+
+// Linear interpolation
+__generic<T : __BuiltinFloatingPointType>
+__target_intrinsic(glsl, mix)
+__intrinsic_op
+T lerp(T x, T y, T s);
+
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__target_intrinsic(glsl, mix)
+__intrinsic_op
+vector<T,N> lerp(vector<T,N> x, vector<T,N> y, vector<T,N> s);
+
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__target_intrinsic(glsl, mix)
+__intrinsic_op
+matrix<T,N,M> lerp(matrix<T,N,M> x, matrix<T,N,M> y, matrix<T,N,M> s);
+
+// Legacy lighting function (obsolete)
+__intrinsic_op float4 lit(float n_dot_l, float n_dot_h, float m);
+
+// Base-e logarithm
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T log(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> log(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> log(matrix<T,N,M> x);
+
+// Base-10 logarithm
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T log10(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> log10(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> log10(matrix<T,N,M> x);
+
+// Base-2 logarithm
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T log2(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> log2(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> log2(matrix<T,N,M> x);
+
+// multiply-add
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T mad(T mvalue, T avalue, T bvalue);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> mad(vector<T,N> mvalue, vector<T,N> avalue, vector<T,N> bvalue);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> mad(matrix<T,N,M> mvalue, matrix<T,N,M> avalue, matrix<T,N,M> bvalue);
+
+// maximum
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T max(T x, T y);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> max(vector<T,N> x, vector<T,N> y);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> max(matrix<T,N,M> x, matrix<T,N,M> y);
+
+// minimum
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T min(T x, T y);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> min(vector<T,N> x, vector<T,N> y);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> min(matrix<T,N,M> x, matrix<T,N,M> y);
+
+// split into integer and fractional parts (both with same sign)
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T modf(T x, out T ip);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> modf(vector<T,N> x, out vector<T,N> ip);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> modf(matrix<T,N,M> x, out matrix<T,N,M> ip);
+
+// msad4 (whatever that is)
+__intrinsic_op uint4 msad4(uint reference, uint2 source, uint4 accum);
+
+// General inner products
+
+// scalar-scalar
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T mul(T x, T y);
+
+// scalar-vector and vector-scalar
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> mul(vector<T,N> x, T y);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> mul(T x, vector<T,N> y);
+
+// scalar-matrix and matrix-scalar
+__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op matrix<T,N,M> mul(matrix<T,N,M> x, T y);
+__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op matrix<T,N,M> mul(T x, matrix<T,N,M> y);
+
+// vector-vector (dot product)
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(dot) T mul(vector<T,N> x, vector<T,N> y);
+
+// vector-matrix
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulVectorMatrix) vector<T,M> mul(vector<T,N> x, matrix<T,N,M> y);
+
+// matrix-vector
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulMatrixVector) vector<T,N> mul(matrix<T,N,M> x, vector<T,M> y);
+
+// matrix-matrix
+__generic<T : __BuiltinArithmeticType, let R : int, let N : int, let C : int> __intrinsic_op(mulMatrixMatrix) matrix<T,R,C> mul(matrix<T,R,N> x, matrix<T,N,C> y);
+
+// noise (deprecated)
+__intrinsic_op float noise(float x);
+__generic<let N : int> __intrinsic_op float noise(vector<float, N> x);
+
+// Normalize a vector
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> normalize(vector<T,N> x);
+
+// Raise to a power
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T pow(T x, T y);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> pow(vector<T,N> x, vector<T,N> y);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> pow(matrix<T,N,M> x, matrix<T,N,M> y);
+
+// Output message
+
+// __intrinsic_op void printf( string format, ... );
+
+// Tessellation factor fixup routines
+
+__intrinsic_op void Process2DQuadTessFactorsAvg(
+ in float4 RawEdgeFactors,
+ in float2 InsideScale,
+ out float4 RoundedEdgeTessFactors,
+ out float2 RoundedInsideTessFactors,
+ out float2 UnroundedInsideTessFactors);
+
+__intrinsic_op void Process2DQuadTessFactorsMax(
+ in float4 RawEdgeFactors,
+ in float2 InsideScale,
+ out float4 RoundedEdgeTessFactors,
+ out float2 RoundedInsideTessFactors,
+ out float2 UnroundedInsideTessFactors);
+
+__intrinsic_op void Process2DQuadTessFactorsMin(
+ in float4 RawEdgeFactors,
+ in float2 InsideScale,
+ out float4 RoundedEdgeTessFactors,
+ out float2 RoundedInsideTessFactors,
+ out float2 UnroundedInsideTessFactors);
+
+__intrinsic_op void ProcessIsolineTessFactors(
+ in float RawDetailFactor,
+ in float RawDensityFactor,
+ out float RoundedDetailFactor,
+ out float RoundedDensityFactor);
+
+__intrinsic_op void ProcessQuadTessFactorsAvg(
+ in float4 RawEdgeFactors,
+ in float InsideScale,
+ out float4 RoundedEdgeTessFactors,
+ out float2 RoundedInsideTessFactors,
+ out float2 UnroundedInsideTessFactors);
+
+__intrinsic_op void ProcessQuadTessFactorsMax(
+ in float4 RawEdgeFactors,
+ in float InsideScale,
+ out float4 RoundedEdgeTessFactors,
+ out float2 RoundedInsideTessFactors,
+ out float2 UnroundedInsideTessFactors);
+
+__intrinsic_op void ProcessQuadTessFactorsMin(
+ in float4 RawEdgeFactors,
+ in float InsideScale,
+ out float4 RoundedEdgeTessFactors,
+ out float2 RoundedInsideTessFactors,
+ out float2 UnroundedInsideTessFactors);
+
+__intrinsic_op void ProcessTriTessFactorsAvg(
+ in float3 RawEdgeFactors,
+ in float InsideScale,
+ out float3 RoundedEdgeTessFactors,
+ out float RoundedInsideTessFactor,
+ out float UnroundedInsideTessFactor);
+
+__intrinsic_op void ProcessTriTessFactorsMax(
+ in float3 RawEdgeFactors,
+ in float InsideScale,
+ out float3 RoundedEdgeTessFactors,
+ out float RoundedInsideTessFactor,
+ out float UnroundedInsideTessFactor);
+
+__intrinsic_op void ProcessTriTessFactorsMin(
+ in float3 RawEdgeFactors,
+ in float InsideScale,
+ out float3 RoundedEdgeTessFactors,
+ out float RoundedInsideTessFactors,
+ out float UnroundedInsideTessFactors);
+
+// Degrees to radians
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T radians(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> radians(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> radians(matrix<T,N,M> x);
+
+// Approximate reciprocal
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T rcp(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> rcp(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> rcp(matrix<T,N,M> x);
+
+// Reflect incident vector across plane with given normal
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__intrinsic_op
+vector<T,N> reflect(vector<T,N> i, vector<T,N> n);
+
+// Refract incident vector given surface normal and index of refraction
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__intrinsic_op
+vector<T,N> refract(vector<T,N> i, vector<T,N> n, float eta);
+
+// Reverse order of bits
+__intrinsic_op uint reversebits(uint value);
+__generic<let N : int> vector<uint,N> reversebits(vector<uint,N> value);
+
+// Round-to-nearest
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T round(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> round(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> round(matrix<T,N,M> x);
+
+// Reciprocal of square root
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T rsqrt(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> rsqrt(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> rsqrt(matrix<T,N,M> x);
+
+// Clamp value to [0,1] range
+__generic<T : __BuiltinFloatingPointType>
+__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op
+T saturate(T x);
+
+__generic<T : __BuiltinFloatingPointType, let N : int>
+__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op
+vector<T,N> saturate(vector<T,N> x);
+
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
+__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op
+matrix<T,N,M> saturate(matrix<T,N,M> x);
+
+
+// Extract sign of value
+__generic<T : __BuiltinSignedArithmeticType> __intrinsic_op int sign(T x);
+__generic<T : __BuiltinSignedArithmeticType, let N : int> __intrinsic_op vector<int,N> sign(vector<T,N> x);
+__generic<T : __BuiltinSignedArithmeticType, let N : int, let M : int> __intrinsic_op matrix<int,N,M> sign(matrix<T,N,M> x);
+
+
+// Sine
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T sin(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> sin(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> sin(matrix<T,N,M> x);
+
+// Sine and cosine
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op void sincos(T x, out T s, out T c);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op void sincos(vector<T,N> x, out vector<T,N> s, out vector<T,N> c);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op void sincos(matrix<T,N,M> x, out matrix<T,N,M> s, out matrix<T,N,M> c);
+
+// Hyperbolic Sine
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T sinh(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> sinh(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> sinh(matrix<T,N,M> x);
+
+// Smooth step (Hermite interpolation)
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T smoothstep(T min, T max, T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> smoothstep(vector<T,N> min, vector<T,N> max, vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> smoothstep(matrix<T,N,M> min, matrix<T,N,M> max, matrix<T,N,M> x);
+
+// Square root
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T sqrt(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> sqrt(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> sqrt(matrix<T,N,M> x);
+
+// Step function
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T step(T y, T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> step(vector<T,N> y, vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> step(matrix<T,N,M> y, matrix<T,N,M> x);
+
+// Tangent
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T tan(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> tan(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> tan(matrix<T,N,M> x);
+
+// Hyperbolic tangent
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T tanh(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> tanh(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> tanh(matrix<T,N,M> x);
+
+// Legacy texture-fetch operations
+
+/*
+__intrinsic_op float4 tex1D(sampler1D s, float t);
+__intrinsic_op float4 tex1D(sampler1D s, float t, float ddx, float ddy);
+__intrinsic_op float4 tex1Dbias(sampler1D s, float4 t);
+__intrinsic_op float4 tex1Dgrad(sampler1D s, float t, float ddx, float ddy);
+__intrinsic_op float4 tex1Dlod(sampler1D s, float4 t);
+__intrinsic_op float4 tex1Dproj(sampler1D s, float4 t);
+
+__intrinsic_op float4 tex2D(sampler2D s, float2 t);
+__intrinsic_op float4 tex2D(sampler2D s, float2 t, float2 ddx, float2 ddy);
+__intrinsic_op float4 tex2Dbias(sampler2D s, float4 t);
+__intrinsic_op float4 tex2Dgrad(sampler2D s, float2 t, float2 ddx, float2 ddy);
+__intrinsic_op float4 tex2Dlod(sampler2D s, float4 t);
+__intrinsic_op float4 tex2Dproj(sampler2D s, float4 t);
+
+__intrinsic_op float4 tex3D(sampler3D s, float3 t);
+__intrinsic_op float4 tex3D(sampler3D s, float3 t, float3 ddx, float3 ddy);
+__intrinsic_op float4 tex3Dbias(sampler3D s, float4 t);
+__intrinsic_op float4 tex3Dgrad(sampler3D s, float3 t, float3 ddx, float3 ddy);
+__intrinsic_op float4 tex3Dlod(sampler3D s, float4 t);
+__intrinsic_op float4 tex3Dproj(sampler3D s, float4 t);
+
+__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t);
+__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t, float3 ddx, float3 ddy);
+__intrinsic_op float4 texCUBEbias(samplerCUBE s, float4 t);
+__intrinsic_op float4 texCUBEgrad(samplerCUBE s, float3 t, float3 ddx, float3 ddy);
+__intrinsic_op float4 texCUBElod(samplerCUBE s, float4 t);
+__intrinsic_op float4 texCUBEproj(samplerCUBE s, float4 t);
+*/
+
+// Matrix transpose
+__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,M,N> transpose(matrix<T,N,M> x);
+
+// Truncate to integer
+__generic<T : __BuiltinFloatingPointType> __intrinsic_op T trunc(T x);
+__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> trunc(vector<T,N> x);
+__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> trunc(matrix<T,N,M> x);
+
+// Shader model 6.0 stuff
+
+__intrinsic_op uint GlobalOrderedCountIncrement(uint countToAppendForThisLane);
+
+__generic<T : __BuiltinType> __intrinsic_op T QuadReadLaneAt(T sourceValue, int quadLaneID);
+__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> QuadReadLaneAt(vector<T,N> sourceValue, int quadLaneID);
+__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> QuadReadLaneAt(matrix<T,N,M> sourceValue, int quadLaneID);
+
+__generic<T : __BuiltinType> __intrinsic_op T QuadSwapX(T localValue);
+__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> QuadSwapX(vector<T,N> localValue);
+__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> QuadSwapX(matrix<T,N,M> localValue);
+
+__generic<T : __BuiltinType> __intrinsic_op T QuadSwapY(T localValue);
+__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> QuadSwapY(vector<T,N> localValue);
+__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> QuadSwapY(matrix<T,N,M> localValue);
+
+__generic<T : __BuiltinIntegerType> __intrinsic_op T WaveAllBitAnd(T expr);
+__generic<T : __BuiltinIntegerType, let N : int> __intrinsic_op vector<T,N> WaveAllBitAnd(vector<T,N> expr);
+__generic<T : __BuiltinIntegerType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllBitAnd(matrix<T,N,M> expr);
+
+__generic<T : __BuiltinIntegerType> __intrinsic_op T WaveAllBitOr(T expr);
+__generic<T : __BuiltinIntegerType, let N : int> __intrinsic_op vector<T,N> WaveAllBitOr(vector<T,N> expr);
+__generic<T : __BuiltinIntegerType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllBitOr(matrix<T,N,M> expr);
+
+__generic<T : __BuiltinIntegerType> __intrinsic_op T WaveAllBitXor(T expr);
+__generic<T : __BuiltinIntegerType, let N : int> __intrinsic_op vector<T,N> WaveAllBitXor(vector<T,N> expr);
+__generic<T : __BuiltinIntegerType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllBitXor(matrix<T,N,M> expr);
+
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllMax(T expr);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllMax(vector<T,N> expr);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllMax(matrix<T,N,M> expr);
+
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllMin(T expr);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllMin(vector<T,N> expr);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllMin(matrix<T,N,M> expr);
+
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllProduct(T expr);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllProduct(vector<T,N> expr);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllProduct(matrix<T,N,M> expr);
+
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllSum(T expr);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllSum(vector<T,N> expr);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllSum(matrix<T,N,M> expr);
+
+__intrinsic_op bool WaveAllEqual(bool expr);
+__intrinsic_op bool WaveAllTrue(bool expr);
+__intrinsic_op bool WaveAnyTrue(bool expr);
+
+uint64_t WaveBallot(bool expr);
+
+uint WaveGetLaneCount();
+uint WaveGetLaneIndex();
+uint WaveGetOrderedIndex();
+
+bool WaveIsHelperLane();
+
+bool WaveOnce();
+
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T WavePrefixProduct(T expr);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WavePrefixProduct(vector<T,N> expr);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WavePrefixProduct(matrix<T,N,M> expr);
+
+__generic<T : __BuiltinArithmeticType> __intrinsic_op T WavePrefixSum(T expr);
+__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WavePrefixSum(vector<T,N> expr);
+__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WavePrefixSum(matrix<T,N,M> expr);
+
+__generic<T : __BuiltinType> __intrinsic_op T WaveReadFirstLane(T expr);
+__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> WaveReadFirstLane(vector<T,N> expr);
+__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveReadFirstLane(matrix<T,N,M> expr);
+
+__generic<T : __BuiltinType> __intrinsic_op T WaveReadLaneAt(T expr, int laneIndex);
+__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> WaveReadLaneAt(vector<T,N> expr, int laneIndex);
+__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveReadLaneAt(matrix<T,N,M> expr, int laneIndex);
+
+// `typedef`s to help with the fact that HLSL has been sorta-kinda case insensitive at various points
+typedef Texture2D texture2D;
+
+${{{{
+
+// Component-wise multiplication ops
+for(auto op : binaryOps)
+{
+ switch (op.opCode)
+ {
+ default:
+ continue;
+
+ case kIROp_Mul:
+ case kIRPseudoOp_MulAssign:
+ break;
+ }
+
+ for (auto type : kBaseTypes)
+ {
+ if ((type.flags & op.flags) == 0)
+ continue;
+
+ char const* leftType = type.name;
+ char const* rightType = leftType;
+ char const* resultType = leftType;
+
+ char const* leftQual = "";
+ if(op.flags & ASSIGNMENT) leftQual = "in out ";
+
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
+ }
+}
+
+//
+
+// Buffer types
+
+static const struct {
+ char const* name;
+ SlangResourceAccess access;
+} kBaseBufferAccessLevels[] = {
+ { "", SLANG_RESOURCE_ACCESS_READ },
+ { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
+ { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
+};
+static const int kBaseBufferAccessLevelCount = sizeof(kBaseBufferAccessLevels) / sizeof(kBaseBufferAccessLevels[0]);
+
+for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
+{
+
+ sb << "__generic<T> __magic_type(Texture, ";
+ sb << ResourceType::makeFlavor(ResourceType::Shape::ShapeBuffer, kBaseBufferAccessLevels[aa].access);
+ sb << ") struct ";
+ sb << kBaseBufferAccessLevels[aa].name;
+ sb << "Buffer {\n";
+
+ sb << "__intrinsic_op void GetDimensions(out uint dim);\n";
+
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, $0)$$z\")\n";
+ sb << "__intrinsic_op T Load(int location);\n";
+
+ sb << "__intrinsic_op T Load(int location, out uint status);\n";
+
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, int($0))$$z\")\n";
+ sb << "__intrinsic_op __subscript(uint index) -> T";
+
+ if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ)
+ {
+ sb << " { get; set; }\n";
+ }
+ else
+ {
+ sb << ";\n";
+ }
+
+ sb << "};\n";
+}
+
+}}}} \ No newline at end of file
diff --git a/source/slang/hlsl.meta.slang.cpp b/source/slang/hlsl.meta.slang.cpp
new file mode 100644
index 000000000..e9e2277e6
--- /dev/null
+++ b/source/slang/hlsl.meta.slang.cpp
@@ -0,0 +1,1066 @@
+sb << "// Slang HLSL compatibility library\n";
+sb << "\n";
+sb << "typedef uint UINT;\n";
+sb << "\n";
+sb << "__generic<T> __magic_type(HLSLAppendStructuredBufferType) struct AppendStructuredBuffer\n";
+sb << "{\n";
+sb << " __intrinsic_op void Append(T value);\n";
+sb << "\n";
+sb << " __intrinsic_op void GetDimensions(\n";
+sb << " out uint numStructs,\n";
+sb << " out uint stride);\n";
+sb << "};\n";
+sb << "\n";
+sb << "__magic_type(HLSLByteAddressBufferType) struct ByteAddressBuffer\n";
+sb << "{\n";
+sb << " __intrinsic_op void GetDimensions(\n";
+sb << " out uint dim);\n";
+sb << "\n";
+sb << " __intrinsic_op uint Load(int location);\n";
+sb << " __intrinsic_op uint Load(int location, out uint status);\n";
+sb << "\n";
+sb << " __intrinsic_op uint2 Load2(int location);\n";
+sb << " __intrinsic_op uint2 Load2(int location, out uint status);\n";
+sb << "\n";
+sb << " __intrinsic_op uint3 Load3(int location);\n";
+sb << " __intrinsic_op uint3 Load3(int location, out uint status);\n";
+sb << "\n";
+sb << " __intrinsic_op uint4 Load4(int location);\n";
+sb << " __intrinsic_op uint4 Load4(int location, out uint status);\n";
+sb << "};\n";
+sb << "\n";
+sb << "__generic<T> __magic_type(HLSLStructuredBufferType) struct StructuredBuffer\n";
+sb << "{\n";
+sb << " __intrinsic_op void GetDimensions(\n";
+sb << " out uint numStructs,\n";
+sb << " out uint stride);\n";
+sb << "\n";
+sb << " __intrinsic_op T Load(int location);\n";
+sb << " __intrinsic_op T Load(int location, out uint status);\n";
+sb << "\n";
+sb << " __intrinsic_op __subscript(uint index) -> T;\n";
+sb << "};\n";
+sb << "\n";
+sb << "__generic<T> __magic_type(HLSLConsumeStructuredBufferType) struct ConsumeStructuredBuffer\n";
+sb << "{\n";
+sb << " __intrinsic_op T Consume();\n";
+sb << "\n";
+sb << " __intrinsic_op void GetDimensions(\n";
+sb << " out uint numStructs,\n";
+sb << " out uint stride);\n";
+sb << "};\n";
+sb << "\n";
+sb << "__generic<T, let N : int> __magic_type(HLSLInputPatchType) struct InputPatch\n";
+sb << "{\n";
+sb << " __intrinsic_op __subscript(uint index) -> T;\n";
+sb << "};\n";
+sb << "\n";
+sb << "__generic<T, let N : int> __magic_type(HLSLOutputPatchType) struct OutputPatch\n";
+sb << "{\n";
+sb << " __intrinsic_op __subscript(uint index) -> T { set; }\n";
+sb << "};\n";
+sb << "\n";
+sb << "__magic_type(HLSLRWByteAddressBufferType) struct RWByteAddressBuffer\n";
+sb << "{\n";
+sb << " // Note(tfoley): supports alll operations from `ByteAddressBuffer`\n";
+sb << " // TODO(tfoley): can this be made a sub-type?\n";
+sb << "\n";
+sb << " __intrinsic_op void GetDimensions(\n";
+sb << " out uint dim);\n";
+sb << "\n";
+sb << " __intrinsic_op uint Load(int location);\n";
+sb << " __intrinsic_op uint Load(int location, out uint status);\n";
+sb << "\n";
+sb << " __intrinsic_op uint2 Load2(int location);\n";
+sb << " __intrinsic_op uint2 Load2(int location, out uint status);\n";
+sb << "\n";
+sb << " __intrinsic_op uint3 Load3(int location);\n";
+sb << " __intrinsic_op uint3 Load3(int location, out uint status);\n";
+sb << "\n";
+sb << " __intrinsic_op uint4 Load4(int location);\n";
+sb << " __intrinsic_op uint4 Load4(int location, out uint status);\n";
+sb << "\n";
+sb << " // Added operations:\n";
+sb << "\n";
+sb << " __intrinsic_op void InterlockedAdd(\n";
+sb << " UINT dest,\n";
+sb << " UINT value,\n";
+sb << " out UINT original_value);\n";
+sb << " __intrinsic_op void InterlockedAdd(\n";
+sb << " UINT dest,\n";
+sb << " UINT value);\n";
+sb << "\n";
+sb << " __intrinsic_op void InterlockedAnd(\n";
+sb << " UINT dest,\n";
+sb << " UINT value,\n";
+sb << " out UINT original_value);\n";
+sb << " __intrinsic_op void InterlockedAnd(\n";
+sb << " UINT dest,\n";
+sb << " UINT value);\n";
+sb << "\n";
+sb << " __intrinsic_op void InterlockedCompareExchange(\n";
+sb << " UINT dest,\n";
+sb << " UINT compare_value,\n";
+sb << " UINT value,\n";
+sb << " out UINT original_value);\n";
+sb << " __intrinsic_op void InterlockedCompareExchange(\n";
+sb << " UINT dest,\n";
+sb << " UINT compare_value,\n";
+sb << " UINT value);\n";
+sb << "\n";
+sb << " __intrinsic_op void InterlockedCompareStore(\n";
+sb << " UINT dest,\n";
+sb << " UINT compare_value,\n";
+sb << " UINT value);\n";
+sb << " __intrinsic_op void InterlockedCompareStore(\n";
+sb << " UINT dest,\n";
+sb << " UINT compare_value);\n";
+sb << "\n";
+sb << " __intrinsic_op void InterlockedExchange(\n";
+sb << " UINT dest,\n";
+sb << " UINT value,\n";
+sb << " out UINT original_value);\n";
+sb << " __intrinsic_op void InterlockedExchange(\n";
+sb << " UINT dest,\n";
+sb << " UINT value);\n";
+sb << "\n";
+sb << " __intrinsic_op void InterlockedMax(\n";
+sb << " UINT dest,\n";
+sb << " UINT value,\n";
+sb << " out UINT original_value);\n";
+sb << " __intrinsic_op void InterlockedMax(\n";
+sb << " UINT dest,\n";
+sb << " UINT value);\n";
+sb << "\n";
+sb << " __intrinsic_op void InterlockedMin(\n";
+sb << " UINT dest,\n";
+sb << " UINT value,\n";
+sb << " out UINT original_value);\n";
+sb << " __intrinsic_op void InterlockedMin(\n";
+sb << " UINT dest,\n";
+sb << " UINT value);\n";
+sb << "\n";
+sb << " __intrinsic_op void InterlockedOr(\n";
+sb << " UINT dest,\n";
+sb << " UINT value,\n";
+sb << " out UINT original_value);\n";
+sb << " __intrinsic_op void InterlockedOr(\n";
+sb << " UINT dest,\n";
+sb << " UINT value);\n";
+sb << "\n";
+sb << " __intrinsic_op void InterlockedXor(\n";
+sb << " UINT dest,\n";
+sb << " UINT value,\n";
+sb << " out UINT original_value);\n";
+sb << " __intrinsic_op void InterlockedXor(\n";
+sb << " UINT dest,\n";
+sb << " UINT value);\n";
+sb << "\n";
+sb << " __intrinsic_op void Store(\n";
+sb << " uint address,\n";
+sb << " uint value);\n";
+sb << "\n";
+sb << " __intrinsic_op void Store2(\n";
+sb << " uint address,\n";
+sb << " uint2 value);\n";
+sb << "\n";
+sb << " __intrinsic_op void Store3(\n";
+sb << " uint address,\n";
+sb << " uint3 value);\n";
+sb << "\n";
+sb << " __intrinsic_op void Store4(\n";
+sb << " uint address,\n";
+sb << " uint4 value);\n";
+sb << "};\n";
+sb << "\n";
+sb << "__generic<T> __magic_type(HLSLRWStructuredBufferType) struct RWStructuredBuffer\n";
+sb << "{\n";
+sb << " __intrinsic_op uint DecrementCounter();\n";
+sb << "\n";
+sb << " __intrinsic_op void GetDimensions(\n";
+sb << " out uint numStructs,\n";
+sb << " out uint stride);\n";
+sb << "\n";
+sb << " __intrinsic_op void IncrementCounter();\n";
+sb << "\n";
+sb << " __intrinsic_op T Load(int location);\n";
+sb << " __intrinsic_op T Load(int location, out uint status);\n";
+sb << "\n";
+sb << " __intrinsic_op __subscript(uint index) -> T { get; set; }\n";
+sb << "};\n";
+sb << "\n";
+sb << "__generic<T> __magic_type(HLSLPointStreamType) struct PointStream\n";
+sb << "{\n";
+sb << " void Append(T value);\n";
+sb << " void RestartStrip();\n";
+sb << "};\n";
+sb << "\n";
+sb << "__generic<T> __magic_type(HLSLLineStreamType) struct LineStream\n";
+sb << "{\n";
+sb << " void Append(T value);\n";
+sb << " void RestartStrip();\n";
+sb << "};\n";
+sb << "\n";
+sb << "__generic<T> __magic_type(HLSLTriangleStreamType) struct TriangleStream\n";
+sb << "{\n";
+sb << " void Append(T value);\n";
+sb << " void RestartStrip();\n";
+sb << "};\n";
+sb << "\n";
+sb << "// Note(tfoley): Trying to systematically add all the HLSL builtins\n";
+sb << "\n";
+sb << "// Try to terminate the current draw or dispatch call (HLSL SM 4.0)\n";
+sb << "__intrinsic_op void abort();\n";
+sb << "\n";
+sb << "// Absolute value (HLSL SM 1.0)\n";
+sb << "__generic<T : __BuiltinSignedArithmeticType> __intrinsic_op T abs(T x);\n";
+sb << "__generic<T : __BuiltinSignedArithmeticType, let N : int> __intrinsic_op vector<T,N> abs(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinSignedArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> abs(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Inverse cosine (HLSL SM 1.0)\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T acos(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> acos(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> acos(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Test if all components are non-zero (HLSL SM 1.0)\n";
+sb << "__generic<T : __BuiltinType> __intrinsic_op T all(T x);\n";
+sb << "__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> all(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> all(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Barrier for writes to all memory spaces (HLSL SM 5.0)\n";
+sb << "__intrinsic_op void AllMemoryBarrier();\n";
+sb << "\n";
+sb << "// Thread-group sync and barrier for writes to all memory spaces (HLSL SM 5.0)\n";
+sb << "__intrinsic_op void AllMemoryBarrierWithGroupSync();\n";
+sb << "\n";
+sb << "// Test if any components is non-zero (HLSL SM 1.0)\n";
+sb << "__generic<T : __BuiltinType> __intrinsic_op T any(T x);\n";
+sb << "__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> any(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> any(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "\n";
+sb << "// Reinterpret bits as a double (HLSL SM 5.0)\n";
+sb << "__intrinsic_op double asdouble(uint lowbits, uint highbits);\n";
+sb << "\n";
+sb << "// Reinterpret bits as a float (HLSL SM 4.0)\n";
+sb << "__intrinsic_op float asfloat( int x);\n";
+sb << "__intrinsic_op float asfloat(uint x);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<float,N> asfloat(vector< int,N> x);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<float,N> asfloat(vector<uint,N> x);\n";
+sb << "__generic<let N : int, let M : int> __intrinsic_op matrix<float,N,M> asfloat(matrix< int,N,M> x);\n";
+sb << "__generic<let N : int, let M : int> __intrinsic_op matrix<float,N,M> asfloat(matrix<uint,N,M> x);\n";
+sb << "\n";
+sb << "\n";
+sb << "// Inverse sine (HLSL SM 1.0)\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T asin(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> asin(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> asin(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Reinterpret bits as an int (HLSL SM 4.0)\n";
+sb << "__intrinsic_op int asint(float x);\n";
+sb << "__intrinsic_op int asint(uint x);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<int,N> asint(vector<float,N> x);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<int,N> asint(vector<uint,N> x);\n";
+sb << "__generic<let N : int, let M : int> __intrinsic_op matrix<int,N,M> asint(matrix<float,N,M> x);\n";
+sb << "__generic<let N : int, let M : int> __intrinsic_op matrix<int,N,M> asint(matrix<uint,N,M> x);\n";
+sb << "\n";
+sb << "// Reinterpret bits of double as a uint (HLSL SM 5.0)\n";
+sb << "__intrinsic_op void asuint(double value, out uint lowbits, out uint highbits);\n";
+sb << "\n";
+sb << "// Reinterpret bits as a uint (HLSL SM 4.0)\n";
+sb << "__intrinsic_op uint asuint(float x);\n";
+sb << "__intrinsic_op uint asuint(int x);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<uint,N> asuint(vector<float,N> x);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<uint,N> asuint(vector<int,N> x);\n";
+sb << "__generic<let N : int, let M : int> __intrinsic_op matrix<uint,N,M> asuint(matrix<float,N,M> x);\n";
+sb << "__generic<let N : int, let M : int> __intrinsic_op matrix<uint,N,M> asuint(matrix<int,N,M> x);\n";
+sb << "\n";
+sb << "// Inverse tangent (HLSL SM 1.0)\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T atan(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> atan(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> atan(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n";
+sb << "__intrinsic_op\n";
+sb << "T atan2(T y, T x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> atan2(vector<T,N> y, vector<T,N> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n";
+sb << "__intrinsic_op\n";
+sb << "matrix<T,N,M> atan2(matrix<T,N,M> y, matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Ceiling (HLSL SM 1.0)\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T ceil(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> ceil(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> ceil(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "\n";
+sb << "// Check access status to tiled resource\n";
+sb << "__intrinsic_op bool CheckAccessFullyMapped(uint status);\n";
+sb << "\n";
+sb << "// Clamp (HLSL SM 1.0)\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T clamp(T x, T min, T max);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> clamp(vector<T,N> x, vector<T,N> min, vector<T,N> max);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> clamp(matrix<T,N,M> x, matrix<T,N,M> min, matrix<T,N,M> max);\n";
+sb << "\n";
+sb << "// Clip (discard) fragment conditionally\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op void clip(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op void clip(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op void clip(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Cosine\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T cos(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> cos(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> cos(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Hyperbolic cosine\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T cosh(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> cosh(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> cosh(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Population count\n";
+sb << "__intrinsic_op uint countbits(uint value);\n";
+sb << "\n";
+sb << "// Cross product\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op vector<T,3> cross(vector<T,3> x, vector<T,3> y);\n";
+sb << "\n";
+sb << "// Convert encoded color\n";
+sb << "__intrinsic_op int4 D3DCOLORtoUBYTE4(float4 x);\n";
+sb << "\n";
+sb << "// Partial-difference derivatives\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__target_intrinsic(glsl, dFdx)\n";
+sb << "__intrinsic_op\n";
+sb << "T ddx(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__target_intrinsic(glsl, dFdx)\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> ddx(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__target_intrinsic(glsl, dFdx)\n";
+sb << "__intrinsic_op\n";
+sb << "matrix<T,N,M> ddx(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdxCoarse)\n";
+sb << "__intrinsic_op\n";
+sb << "T ddx_coarse(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdxCoarse)\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> ddx_coarse(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdxCoarse)\n";
+sb << "__intrinsic_op\n";
+sb << "matrix<T,N,M> ddx_coarse(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdxFine)\n";
+sb << "__intrinsic_op\n";
+sb << "T ddx_fine(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdxFine)\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> ddx_fine(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdxFine)\n";
+sb << "__intrinsic_op\n";
+sb << "matrix<T,N,M> ddx_fine(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__target_intrinsic(glsl, dFdy)\n";
+sb << "__intrinsic_op\n";
+sb << "T ddy(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__target_intrinsic(glsl, dFdy)\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> ddy(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__target_intrinsic(glsl, dFdy)\n";
+sb << "__intrinsic_op\n";
+sb << " matrix<T,N,M> ddy(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdyCoarse)\n";
+sb << "__intrinsic_op\n";
+sb << "T ddy_coarse(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdyCoarse)\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> ddy_coarse(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdyCoarse)\n";
+sb << "__intrinsic_op\n";
+sb << "matrix<T,N,M> ddy_coarse(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdyFine)\n";
+sb << "__intrinsic_op\n";
+sb << "T ddy_fine(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdyFine)\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> ddy_fine(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__glsl_extension(GL_ARB_derivative_control)\n";
+sb << "__target_intrinsic(glsl, dFdyFine)\n";
+sb << "__intrinsic_op\n";
+sb << "matrix<T,N,M> ddy_fine(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "\n";
+sb << "// Radians to degrees\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T degrees(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> degrees(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> degrees(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Matrix determinant\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op T determinant(matrix<T,N,N> m);\n";
+sb << "\n";
+sb << "// Barrier for device memory\n";
+sb << "__intrinsic_op void DeviceMemoryBarrier();\n";
+sb << "__intrinsic_op void DeviceMemoryBarrierWithGroupSync();\n";
+sb << "\n";
+sb << "// Vector distance\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op T distance(vector<T,N> x, vector<T,N> y);\n";
+sb << "\n";
+sb << "// Vector dot product\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op T dot(vector<T,N> x, vector<T,N> y);\n";
+sb << "\n";
+sb << "// Helper for computing distance terms for lighting (obsolete)\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op vector<T,4> dst(vector<T,4> x, vector<T,4> y);\n";
+sb << "\n";
+sb << "// Error message\n";
+sb << "\n";
+sb << "// __intrinsic_op void errorf( string format, ... );\n";
+sb << "\n";
+sb << "// Attribute evaluation\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T EvaluateAttributeAtCentroid(T x);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> EvaluateAttributeAtCentroid(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> EvaluateAttributeAtCentroid(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T EvaluateAttributeAtSample(T x, uint sampleindex);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> EvaluateAttributeAtSample(vector<T,N> x, uint sampleindex);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> EvaluateAttributeAtSample(matrix<T,N,M> x, uint sampleindex);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T EvaluateAttributeSnapped(T x, int2 offset);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> EvaluateAttributeSnapped(vector<T,N> x, int2 offset);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> EvaluateAttributeSnapped(matrix<T,N,M> x, int2 offset);\n";
+sb << "\n";
+sb << "// Base-e exponent\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T exp(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> exp(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> exp(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Base-2 exponent\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T exp2(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> exp2(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> exp2(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Convert 16-bit float stored in low bits of integer\n";
+sb << "__intrinsic_op float f16tof32(uint value);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<float,N> f16tof32(vector<uint,N> value);\n";
+sb << "\n";
+sb << "// Convert to 16-bit float stored in low bits of integer\n";
+sb << "__intrinsic_op uint f32tof16(float value);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<uint,N> f32tof16(vector<float,N> value);\n";
+sb << "\n";
+sb << "// Flip surface normal to face forward, if needed\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> faceforward(vector<T,N> n, vector<T,N> i, vector<T,N> ng);\n";
+sb << "\n";
+sb << "// Find first set bit starting at high bit and working down\n";
+sb << "__intrinsic_op int firstbithigh(int value);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<int,N> firstbithigh(vector<int,N> value);\n";
+sb << "\n";
+sb << "__intrinsic_op uint firstbithigh(uint value);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<uint,N> firstbithigh(vector<uint,N> value);\n";
+sb << "\n";
+sb << "// Find first set bit starting at low bit and working up\n";
+sb << "__intrinsic_op int firstbitlow(int value);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<int,N> firstbitlow(vector<int,N> value);\n";
+sb << "\n";
+sb << "__intrinsic_op uint firstbitlow(uint value);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<uint,N> firstbitlow(vector<uint,N> value);\n";
+sb << "\n";
+sb << "// Floor (HLSL SM 1.0)\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T floor(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> floor(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> floor(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Fused multiply-add for doubles\n";
+sb << "__intrinsic_op double fma(double a, double b, double c);\n";
+sb << "__generic<let N : int> __intrinsic_op vector<double, N> fma(vector<double, N> a, vector<double, N> b, vector<double, N> c);\n";
+sb << "__generic<let N : int, let M : int> __intrinsic_op matrix<double,N,M> fma(matrix<double,N,M> a, matrix<double,N,M> b, matrix<double,N,M> c);\n";
+sb << "\n";
+sb << "// Floating point remainder of x/y\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T fmod(T x, T y);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> fmod(vector<T,N> x, vector<T,N> y);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> fmod(matrix<T,N,M> x, matrix<T,N,M> y);\n";
+sb << "\n";
+sb << "// Fractional part\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__target_intrinsic(glsl, fract)\n";
+sb << "__intrinsic_op\n";
+sb << "T frac(T x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__target_intrinsic(glsl, fract)\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> frac(vector<T,N> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__target_intrinsic(glsl, fract)\n";
+sb << "__intrinsic_op\n";
+sb << "matrix<T,N,M> frac(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Split float into mantissa and exponent\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T frexp(T x, out T exp);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> frexp(vector<T,N> x, out vector<T,N> exp);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> frexp(matrix<T,N,M> x, out matrix<T,N,M> exp);\n";
+sb << "\n";
+sb << "// Texture filter width\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T fwidth(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> fwidth(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> fwidth(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Get number of samples in render target\n";
+sb << "__intrinsic_op uint GetRenderTargetSampleCount();\n";
+sb << "\n";
+sb << "// Get position of given sample\n";
+sb << "__intrinsic_op float2 GetRenderTargetSamplePosition(int Index);\n";
+sb << "\n";
+sb << "// Group memory barrier\n";
+sb << "__intrinsic_op void GroupMemoryBarrier();\n";
+sb << "__intrinsic_op void GroupMemoryBarrierWithGroupSync();\n";
+sb << "\n";
+sb << "// Atomics\n";
+sb << "__intrinsic_op void InterlockedAdd(in out int dest, int value, out int original_value);\n";
+sb << "__intrinsic_op void InterlockedAdd(in out uint dest, uint value, out uint original_value);\n";
+sb << "\n";
+sb << "__intrinsic_op void InterlockedAnd(in out int dest, int value, out int original_value);\n";
+sb << "__intrinsic_op void InterlockedAnd(in out uint dest, uint value, out uint original_value);\n";
+sb << "\n";
+sb << "__intrinsic_op void InterlockedCompareExchange(in out int dest, int compare_value, int value, out int original_value);\n";
+sb << "__intrinsic_op void InterlockedCompareExchange(in out uint dest, uint compare_value, uint value, out uint original_value);\n";
+sb << "\n";
+sb << "__intrinsic_op void InterlockedCompareStore(in out int dest, int compare_value, int value);\n";
+sb << "__intrinsic_op void InterlockedCompareStore(in out uint dest, uint compare_value, uint value);\n";
+sb << "\n";
+sb << "__intrinsic_op void InterlockedExchange(in out int dest, int value, out int original_value);\n";
+sb << "__intrinsic_op void InterlockedExchange(in out uint dest, uint value, out uint original_value);\n";
+sb << "\n";
+sb << "__intrinsic_op void InterlockedMax(in out int dest, int value, out int original_value);\n";
+sb << "__intrinsic_op void InterlockedMax(in out uint dest, uint value, out uint original_value);\n";
+sb << "\n";
+sb << "__intrinsic_op void InterlockedMin(in out int dest, int value, out int original_value);\n";
+sb << "__intrinsic_op void InterlockedMin(in out uint dest, uint value, out uint original_value);\n";
+sb << "\n";
+sb << "__intrinsic_op void InterlockedOr(in out int dest, int value, out int original_value);\n";
+sb << "__intrinsic_op void InterlockedOr(in out uint dest, uint value, out uint original_value);\n";
+sb << "\n";
+sb << "__intrinsic_op void InterlockedXor(in out int dest, int value, out int original_value);\n";
+sb << "__intrinsic_op void InterlockedXor(in out uint dest, uint value, out uint original_value);\n";
+sb << "\n";
+sb << "// Is floating-point value finite?\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op bool isfinite(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<bool,N> isfinite(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<bool,N,M> isfinite(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Is floating-point value infinite?\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op bool isinf(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<bool,N> isinf(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<bool,N,M> isinf(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Is floating-point value not-a-number?\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op bool isnan(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<bool,N> isnan(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<bool,N,M> isnan(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Construct float from mantissa and exponent\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T ldexp(T x, T exp);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> ldexp(vector<T,N> x, vector<T,N> exp);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> ldexp(matrix<T,N,M> x, matrix<T,N,M> exp);\n";
+sb << "\n";
+sb << "// Vector length\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op T length(vector<T,N> x);\n";
+sb << "\n";
+sb << "// Linear interpolation\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__target_intrinsic(glsl, mix)\n";
+sb << "__intrinsic_op\n";
+sb << "T lerp(T x, T y, T s);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__target_intrinsic(glsl, mix)\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> lerp(vector<T,N> x, vector<T,N> y, vector<T,N> s);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__target_intrinsic(glsl, mix)\n";
+sb << "__intrinsic_op\n";
+sb << "matrix<T,N,M> lerp(matrix<T,N,M> x, matrix<T,N,M> y, matrix<T,N,M> s);\n";
+sb << "\n";
+sb << "// Legacy lighting function (obsolete)\n";
+sb << "__intrinsic_op float4 lit(float n_dot_l, float n_dot_h, float m);\n";
+sb << "\n";
+sb << "// Base-e logarithm\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T log(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> log(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> log(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Base-10 logarithm\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T log10(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> log10(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> log10(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Base-2 logarithm\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T log2(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> log2(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> log2(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// multiply-add\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T mad(T mvalue, T avalue, T bvalue);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> mad(vector<T,N> mvalue, vector<T,N> avalue, vector<T,N> bvalue);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> mad(matrix<T,N,M> mvalue, matrix<T,N,M> avalue, matrix<T,N,M> bvalue);\n";
+sb << "\n";
+sb << "// maximum\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T max(T x, T y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> max(vector<T,N> x, vector<T,N> y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> max(matrix<T,N,M> x, matrix<T,N,M> y);\n";
+sb << "\n";
+sb << "// minimum\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T min(T x, T y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> min(vector<T,N> x, vector<T,N> y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> min(matrix<T,N,M> x, matrix<T,N,M> y);\n";
+sb << "\n";
+sb << "// split into integer and fractional parts (both with same sign)\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T modf(T x, out T ip);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> modf(vector<T,N> x, out vector<T,N> ip);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> modf(matrix<T,N,M> x, out matrix<T,N,M> ip);\n";
+sb << "\n";
+sb << "// msad4 (whatever that is)\n";
+sb << "__intrinsic_op uint4 msad4(uint reference, uint2 source, uint4 accum);\n";
+sb << "\n";
+sb << "// General inner products\n";
+sb << "\n";
+sb << "// scalar-scalar\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T mul(T x, T y);\n";
+sb << "\n";
+sb << "// scalar-vector and vector-scalar\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> mul(vector<T,N> x, T y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> mul(T x, vector<T,N> y);\n";
+sb << "\n";
+sb << "// scalar-matrix and matrix-scalar\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op matrix<T,N,M> mul(matrix<T,N,M> x, T y);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op matrix<T,N,M> mul(T x, matrix<T,N,M> y);\n";
+sb << "\n";
+sb << "// vector-vector (dot product)\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(dot) T mul(vector<T,N> x, vector<T,N> y);\n";
+sb << "\n";
+sb << "// vector-matrix\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulVectorMatrix) vector<T,M> mul(vector<T,N> x, matrix<T,N,M> y);\n";
+sb << "\n";
+sb << "// matrix-vector\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulMatrixVector) vector<T,N> mul(matrix<T,N,M> x, vector<T,M> y);\n";
+sb << "\n";
+sb << "// matrix-matrix\n";
+sb << "__generic<T : __BuiltinArithmeticType, let R : int, let N : int, let C : int> __intrinsic_op(mulMatrixMatrix) matrix<T,R,C> mul(matrix<T,R,N> x, matrix<T,N,C> y);\n";
+sb << "\n";
+sb << "// noise (deprecated)\n";
+sb << "__intrinsic_op float noise(float x);\n";
+sb << "__generic<let N : int> __intrinsic_op float noise(vector<float, N> x);\n";
+sb << "\n";
+sb << "// Normalize a vector\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> normalize(vector<T,N> x);\n";
+sb << "\n";
+sb << "// Raise to a power\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T pow(T x, T y);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> pow(vector<T,N> x, vector<T,N> y);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> pow(matrix<T,N,M> x, matrix<T,N,M> y);\n";
+sb << "\n";
+sb << "// Output message\n";
+sb << "\n";
+sb << "// __intrinsic_op void printf( string format, ... );\n";
+sb << "\n";
+sb << "// Tessellation factor fixup routines\n";
+sb << "\n";
+sb << "__intrinsic_op void Process2DQuadTessFactorsAvg(\n";
+sb << " in float4 RawEdgeFactors,\n";
+sb << " in float2 InsideScale,\n";
+sb << " out float4 RoundedEdgeTessFactors,\n";
+sb << " out float2 RoundedInsideTessFactors,\n";
+sb << " out float2 UnroundedInsideTessFactors);\n";
+sb << "\n";
+sb << "__intrinsic_op void Process2DQuadTessFactorsMax(\n";
+sb << " in float4 RawEdgeFactors,\n";
+sb << " in float2 InsideScale,\n";
+sb << " out float4 RoundedEdgeTessFactors,\n";
+sb << " out float2 RoundedInsideTessFactors,\n";
+sb << " out float2 UnroundedInsideTessFactors);\n";
+sb << "\n";
+sb << "__intrinsic_op void Process2DQuadTessFactorsMin(\n";
+sb << " in float4 RawEdgeFactors,\n";
+sb << " in float2 InsideScale,\n";
+sb << " out float4 RoundedEdgeTessFactors,\n";
+sb << " out float2 RoundedInsideTessFactors,\n";
+sb << " out float2 UnroundedInsideTessFactors);\n";
+sb << "\n";
+sb << "__intrinsic_op void ProcessIsolineTessFactors(\n";
+sb << " in float RawDetailFactor,\n";
+sb << " in float RawDensityFactor,\n";
+sb << " out float RoundedDetailFactor,\n";
+sb << " out float RoundedDensityFactor);\n";
+sb << "\n";
+sb << "__intrinsic_op void ProcessQuadTessFactorsAvg(\n";
+sb << " in float4 RawEdgeFactors,\n";
+sb << " in float InsideScale,\n";
+sb << " out float4 RoundedEdgeTessFactors,\n";
+sb << " out float2 RoundedInsideTessFactors,\n";
+sb << " out float2 UnroundedInsideTessFactors);\n";
+sb << "\n";
+sb << "__intrinsic_op void ProcessQuadTessFactorsMax(\n";
+sb << " in float4 RawEdgeFactors,\n";
+sb << " in float InsideScale,\n";
+sb << " out float4 RoundedEdgeTessFactors,\n";
+sb << " out float2 RoundedInsideTessFactors,\n";
+sb << " out float2 UnroundedInsideTessFactors);\n";
+sb << "\n";
+sb << "__intrinsic_op void ProcessQuadTessFactorsMin(\n";
+sb << " in float4 RawEdgeFactors,\n";
+sb << " in float InsideScale,\n";
+sb << " out float4 RoundedEdgeTessFactors,\n";
+sb << " out float2 RoundedInsideTessFactors,\n";
+sb << " out float2 UnroundedInsideTessFactors);\n";
+sb << "\n";
+sb << "__intrinsic_op void ProcessTriTessFactorsAvg(\n";
+sb << " in float3 RawEdgeFactors,\n";
+sb << " in float InsideScale,\n";
+sb << " out float3 RoundedEdgeTessFactors,\n";
+sb << " out float RoundedInsideTessFactor,\n";
+sb << " out float UnroundedInsideTessFactor);\n";
+sb << "\n";
+sb << "__intrinsic_op void ProcessTriTessFactorsMax(\n";
+sb << " in float3 RawEdgeFactors,\n";
+sb << " in float InsideScale,\n";
+sb << " out float3 RoundedEdgeTessFactors,\n";
+sb << " out float RoundedInsideTessFactor,\n";
+sb << " out float UnroundedInsideTessFactor);\n";
+sb << "\n";
+sb << "__intrinsic_op void ProcessTriTessFactorsMin(\n";
+sb << " in float3 RawEdgeFactors,\n";
+sb << " in float InsideScale,\n";
+sb << " out float3 RoundedEdgeTessFactors,\n";
+sb << " out float RoundedInsideTessFactors,\n";
+sb << " out float UnroundedInsideTessFactors);\n";
+sb << "\n";
+sb << "// Degrees to radians\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T radians(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> radians(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> radians(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Approximate reciprocal\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T rcp(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> rcp(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> rcp(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Reflect incident vector across plane with given normal\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> reflect(vector<T,N> i, vector<T,N> n);\n";
+sb << "\n";
+sb << "// Refract incident vector given surface normal and index of refraction\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__intrinsic_op\n";
+sb << "vector<T,N> refract(vector<T,N> i, vector<T,N> n, float eta);\n";
+sb << "\n";
+sb << "// Reverse order of bits\n";
+sb << "__intrinsic_op uint reversebits(uint value);\n";
+sb << "__generic<let N : int> vector<uint,N> reversebits(vector<uint,N> value);\n";
+sb << "\n";
+sb << "// Round-to-nearest\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T round(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> round(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> round(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Reciprocal of square root\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T rsqrt(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> rsqrt(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> rsqrt(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Clamp value to [0,1] range\n";
+sb << "__generic<T : __BuiltinFloatingPointType>\n";
+sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n";
+sb << "T saturate(T x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int>\n";
+sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n";
+sb << "vector<T,N> saturate(vector<T,N> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n";
+sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n";
+sb << "matrix<T,N,M> saturate(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "\n";
+sb << "// Extract sign of value\n";
+sb << "__generic<T : __BuiltinSignedArithmeticType> __intrinsic_op int sign(T x);\n";
+sb << "__generic<T : __BuiltinSignedArithmeticType, let N : int> __intrinsic_op vector<int,N> sign(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinSignedArithmeticType, let N : int, let M : int> __intrinsic_op matrix<int,N,M> sign(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "\n";
+sb << "// Sine\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T sin(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> sin(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> sin(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Sine and cosine\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op void sincos(T x, out T s, out T c);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op void sincos(vector<T,N> x, out vector<T,N> s, out vector<T,N> c);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op void sincos(matrix<T,N,M> x, out matrix<T,N,M> s, out matrix<T,N,M> c);\n";
+sb << "\n";
+sb << "// Hyperbolic Sine\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T sinh(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> sinh(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> sinh(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Smooth step (Hermite interpolation)\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T smoothstep(T min, T max, T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> smoothstep(vector<T,N> min, vector<T,N> max, vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> smoothstep(matrix<T,N,M> min, matrix<T,N,M> max, matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Square root\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T sqrt(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> sqrt(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> sqrt(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Step function\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T step(T y, T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> step(vector<T,N> y, vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> step(matrix<T,N,M> y, matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Tangent\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T tan(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> tan(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> tan(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Hyperbolic tangent\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T tanh(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> tanh(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> tanh(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Legacy texture-fetch operations\n";
+sb << "\n";
+sb << "/*\n";
+sb << "__intrinsic_op float4 tex1D(sampler1D s, float t);\n";
+sb << "__intrinsic_op float4 tex1D(sampler1D s, float t, float ddx, float ddy);\n";
+sb << "__intrinsic_op float4 tex1Dbias(sampler1D s, float4 t);\n";
+sb << "__intrinsic_op float4 tex1Dgrad(sampler1D s, float t, float ddx, float ddy);\n";
+sb << "__intrinsic_op float4 tex1Dlod(sampler1D s, float4 t);\n";
+sb << "__intrinsic_op float4 tex1Dproj(sampler1D s, float4 t);\n";
+sb << "\n";
+sb << "__intrinsic_op float4 tex2D(sampler2D s, float2 t);\n";
+sb << "__intrinsic_op float4 tex2D(sampler2D s, float2 t, float2 ddx, float2 ddy);\n";
+sb << "__intrinsic_op float4 tex2Dbias(sampler2D s, float4 t);\n";
+sb << "__intrinsic_op float4 tex2Dgrad(sampler2D s, float2 t, float2 ddx, float2 ddy);\n";
+sb << "__intrinsic_op float4 tex2Dlod(sampler2D s, float4 t);\n";
+sb << "__intrinsic_op float4 tex2Dproj(sampler2D s, float4 t);\n";
+sb << "\n";
+sb << "__intrinsic_op float4 tex3D(sampler3D s, float3 t);\n";
+sb << "__intrinsic_op float4 tex3D(sampler3D s, float3 t, float3 ddx, float3 ddy);\n";
+sb << "__intrinsic_op float4 tex3Dbias(sampler3D s, float4 t);\n";
+sb << "__intrinsic_op float4 tex3Dgrad(sampler3D s, float3 t, float3 ddx, float3 ddy);\n";
+sb << "__intrinsic_op float4 tex3Dlod(sampler3D s, float4 t);\n";
+sb << "__intrinsic_op float4 tex3Dproj(sampler3D s, float4 t);\n";
+sb << "\n";
+sb << "__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t);\n";
+sb << "__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t, float3 ddx, float3 ddy);\n";
+sb << "__intrinsic_op float4 texCUBEbias(samplerCUBE s, float4 t);\n";
+sb << "__intrinsic_op float4 texCUBEgrad(samplerCUBE s, float3 t, float3 ddx, float3 ddy);\n";
+sb << "__intrinsic_op float4 texCUBElod(samplerCUBE s, float4 t);\n";
+sb << "__intrinsic_op float4 texCUBEproj(samplerCUBE s, float4 t);\n";
+sb << "*/\n";
+sb << "\n";
+sb << "// Matrix transpose\n";
+sb << "__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,M,N> transpose(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Truncate to integer\n";
+sb << "__generic<T : __BuiltinFloatingPointType> __intrinsic_op T trunc(T x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> trunc(vector<T,N> x);\n";
+sb << "__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> trunc(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "// Shader model 6.0 stuff\n";
+sb << "\n";
+sb << "__intrinsic_op uint GlobalOrderedCountIncrement(uint countToAppendForThisLane);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinType> __intrinsic_op T QuadReadLaneAt(T sourceValue, int quadLaneID);\n";
+sb << "__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> QuadReadLaneAt(vector<T,N> sourceValue, int quadLaneID);\n";
+sb << "__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> QuadReadLaneAt(matrix<T,N,M> sourceValue, int quadLaneID);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinType> __intrinsic_op T QuadSwapX(T localValue);\n";
+sb << "__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> QuadSwapX(vector<T,N> localValue);\n";
+sb << "__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> QuadSwapX(matrix<T,N,M> localValue);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinType> __intrinsic_op T QuadSwapY(T localValue);\n";
+sb << "__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> QuadSwapY(vector<T,N> localValue);\n";
+sb << "__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> QuadSwapY(matrix<T,N,M> localValue);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinIntegerType> __intrinsic_op T WaveAllBitAnd(T expr);\n";
+sb << "__generic<T : __BuiltinIntegerType, let N : int> __intrinsic_op vector<T,N> WaveAllBitAnd(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinIntegerType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllBitAnd(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinIntegerType> __intrinsic_op T WaveAllBitOr(T expr);\n";
+sb << "__generic<T : __BuiltinIntegerType, let N : int> __intrinsic_op vector<T,N> WaveAllBitOr(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinIntegerType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllBitOr(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinIntegerType> __intrinsic_op T WaveAllBitXor(T expr);\n";
+sb << "__generic<T : __BuiltinIntegerType, let N : int> __intrinsic_op vector<T,N> WaveAllBitXor(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinIntegerType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllBitXor(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllMax(T expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllMax(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllMax(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllMin(T expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllMin(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllMin(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllProduct(T expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllProduct(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllProduct(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllSum(T expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllSum(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllSum(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__intrinsic_op bool WaveAllEqual(bool expr);\n";
+sb << "__intrinsic_op bool WaveAllTrue(bool expr);\n";
+sb << "__intrinsic_op bool WaveAnyTrue(bool expr);\n";
+sb << "\n";
+sb << "uint64_t WaveBallot(bool expr);\n";
+sb << "\n";
+sb << "uint WaveGetLaneCount();\n";
+sb << "uint WaveGetLaneIndex();\n";
+sb << "uint WaveGetOrderedIndex();\n";
+sb << "\n";
+sb << "bool WaveIsHelperLane();\n";
+sb << "\n";
+sb << "bool WaveOnce();\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T WavePrefixProduct(T expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WavePrefixProduct(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WavePrefixProduct(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinArithmeticType> __intrinsic_op T WavePrefixSum(T expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WavePrefixSum(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WavePrefixSum(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinType> __intrinsic_op T WaveReadFirstLane(T expr);\n";
+sb << "__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> WaveReadFirstLane(vector<T,N> expr);\n";
+sb << "__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveReadFirstLane(matrix<T,N,M> expr);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinType> __intrinsic_op T WaveReadLaneAt(T expr, int laneIndex);\n";
+sb << "__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> WaveReadLaneAt(vector<T,N> expr, int laneIndex);\n";
+sb << "__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveReadLaneAt(matrix<T,N,M> expr, int laneIndex);\n";
+sb << "\n";
+sb << "// `typedef`s to help with the fact that HLSL has been sorta-kinda case insensitive at various points\n";
+sb << "typedef Texture2D texture2D;\n";
+sb << "\n";
+sb << "";
+
+
+// Component-wise multiplication ops
+for(auto op : binaryOps)
+{
+ switch (op.opCode)
+ {
+ default:
+ continue;
+
+ case kIROp_Mul:
+ case kIRPseudoOp_MulAssign:
+ break;
+ }
+
+ for (auto type : kBaseTypes)
+ {
+ if ((type.flags & op.flags) == 0)
+ continue;
+
+ char const* leftType = type.name;
+ char const* rightType = leftType;
+ char const* resultType = leftType;
+
+ char const* leftQual = "";
+ if(op.flags & ASSIGNMENT) leftQual = "in out ";
+
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
+ }
+}
+
+//
+
+// Buffer types
+
+static const struct {
+ char const* name;
+ SlangResourceAccess access;
+} kBaseBufferAccessLevels[] = {
+ { "", SLANG_RESOURCE_ACCESS_READ },
+ { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
+ { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
+};
+static const int kBaseBufferAccessLevelCount = sizeof(kBaseBufferAccessLevels) / sizeof(kBaseBufferAccessLevels[0]);
+
+for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
+{
+
+ sb << "__generic<T> __magic_type(Texture, ";
+ sb << ResourceType::makeFlavor(ResourceType::Shape::ShapeBuffer, kBaseBufferAccessLevels[aa].access);
+ sb << ") struct ";
+ sb << kBaseBufferAccessLevels[aa].name;
+ sb << "Buffer {\n";
+
+ sb << "__intrinsic_op void GetDimensions(out uint dim);\n";
+
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, $0)$z\")\n";
+ sb << "__intrinsic_op T Load(int location);\n";
+
+ sb << "__intrinsic_op T Load(int location, out uint status);\n";
+
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, int($0))$z\")\n";
+ sb << "__intrinsic_op __subscript(uint index) -> T";
+
+ if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ)
+ {
+ sb << " { get; set; }\n";
+ }
+ else
+ {
+ sb << ";\n";
+ }
+
+ sb << "};\n";
+}
+
+sb << "";
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index 4d5fd6f87..cf45cbca8 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -8,1039 +8,6 @@
#define STRINGIZE2(x) #x
#define LINE_STRING STRINGIZE(__LINE__)
-enum { kCoreLibIncludeStringLine = __LINE__ + 1 };
-const char* kCoreLibIncludeStringChunks[] = { R"=(
-
-// A type that can be used as an operand for builtins
-interface __BuiltinType {}
-
-// A type that can be used for arithmetic operations
-interface __BuiltinArithmeticType : __BuiltinType {}
-
-// A type that logically has a sign (positive/negative/zero)
-interface __BuiltinSignedArithmeticType : __BuiltinArithmeticType {}
-
-// A type that can represent integers
-interface __BuiltinIntegerType : __BuiltinArithmeticType {}
-
-// A type that can represent non-integers
-interface __BuiltinRealType : __BuiltinArithmeticType {}
-
-// A type that uses a floating-point representation
-interface __BuiltinFloatingPointType : __BuiltinRealType, __BuiltinSignedArithmeticType {}
-
-__generic<T,U> __intrinsic_op(Sequence) U operator,(T left, U right);
-
-__generic<T> __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse);
-__generic<T, let N : int> __intrinsic_op(select) vector<T,N> operator?:(vector<bool,N> condition, vector<T,N> ifTrue, vector<T,N> ifFalse);
-
-)=" };
-
-
-enum { kHLSLLibIncludeStringLine = __LINE__+1 };
-const char * kHLSLLibIncludeStringChunks[] = { R"=(
-
-typedef uint UINT;
-
-__generic<T> __magic_type(HLSLAppendStructuredBufferType) struct AppendStructuredBuffer
-{
- __intrinsic_op void Append(T value);
-
- __intrinsic_op void GetDimensions(
- out uint numStructs,
- out uint stride);
-};
-
-__magic_type(HLSLByteAddressBufferType) struct ByteAddressBuffer
-{
- __intrinsic_op void GetDimensions(
- out uint dim);
-
- __intrinsic_op uint Load(int location);
- __intrinsic_op uint Load(int location, out uint status);
-
- __intrinsic_op uint2 Load2(int location);
- __intrinsic_op uint2 Load2(int location, out uint status);
-
- __intrinsic_op uint3 Load3(int location);
- __intrinsic_op uint3 Load3(int location, out uint status);
-
- __intrinsic_op uint4 Load4(int location);
- __intrinsic_op uint4 Load4(int location, out uint status);
-};
-
-__generic<T> __magic_type(HLSLStructuredBufferType) struct StructuredBuffer
-{
- __intrinsic_op void GetDimensions(
- out uint numStructs,
- out uint stride);
-
- __intrinsic_op T Load(int location);
- __intrinsic_op T Load(int location, out uint status);
-
- __intrinsic_op __subscript(uint index) -> T;
-};
-
-__generic<T> __magic_type(HLSLConsumeStructuredBufferType) struct ConsumeStructuredBuffer
-{
- __intrinsic_op T Consume();
-
- __intrinsic_op void GetDimensions(
- out uint numStructs,
- out uint stride);
-};
-
-__generic<T, let N : int> __magic_type(HLSLInputPatchType) struct InputPatch
-{
- __intrinsic_op __subscript(uint index) -> T;
-};
-
-__generic<T, let N : int> __magic_type(HLSLOutputPatchType) struct OutputPatch
-{
- __intrinsic_op __subscript(uint index) -> T { set; }
-};
-
-__magic_type(HLSLRWByteAddressBufferType) struct RWByteAddressBuffer
-{
- // Note(tfoley): supports alll operations from `ByteAddressBuffer`
- // TODO(tfoley): can this be made a sub-type?
-
- __intrinsic_op void GetDimensions(
- out uint dim);
-
- __intrinsic_op uint Load(int location);
- __intrinsic_op uint Load(int location, out uint status);
-
- __intrinsic_op uint2 Load2(int location);
- __intrinsic_op uint2 Load2(int location, out uint status);
-
- __intrinsic_op uint3 Load3(int location);
- __intrinsic_op uint3 Load3(int location, out uint status);
-
- __intrinsic_op uint4 Load4(int location);
- __intrinsic_op uint4 Load4(int location, out uint status);
-
- // Added operations:
-
- __intrinsic_op void InterlockedAdd(
- UINT dest,
- UINT value,
- out UINT original_value);
- __intrinsic_op void InterlockedAdd(
- UINT dest,
- UINT value);
-
- __intrinsic_op void InterlockedAnd(
- UINT dest,
- UINT value,
- out UINT original_value);
- __intrinsic_op void InterlockedAnd(
- UINT dest,
- UINT value);
-
- __intrinsic_op void InterlockedCompareExchange(
- UINT dest,
- UINT compare_value,
- UINT value,
- out UINT original_value);
- __intrinsic_op void InterlockedCompareExchange(
- UINT dest,
- UINT compare_value,
- UINT value);
-
- __intrinsic_op void InterlockedCompareStore(
- UINT dest,
- UINT compare_value,
- UINT value);
- __intrinsic_op void InterlockedCompareStore(
- UINT dest,
- UINT compare_value);
-
- __intrinsic_op void InterlockedExchange(
- UINT dest,
- UINT value,
- out UINT original_value);
- __intrinsic_op void InterlockedExchange(
- UINT dest,
- UINT value);
-
- __intrinsic_op void InterlockedMax(
- UINT dest,
- UINT value,
- out UINT original_value);
- __intrinsic_op void InterlockedMax(
- UINT dest,
- UINT value);
-
- __intrinsic_op void InterlockedMin(
- UINT dest,
- UINT value,
- out UINT original_value);
- __intrinsic_op void InterlockedMin(
- UINT dest,
- UINT value);
-
- __intrinsic_op void InterlockedOr(
- UINT dest,
- UINT value,
- out UINT original_value);
- __intrinsic_op void InterlockedOr(
- UINT dest,
- UINT value);
-
- __intrinsic_op void InterlockedXor(
- UINT dest,
- UINT value,
- out UINT original_value);
- __intrinsic_op void InterlockedXor(
- UINT dest,
- UINT value);
-
- __intrinsic_op void Store(
- uint address,
- uint value);
-
- __intrinsic_op void Store2(
- uint address,
- uint2 value);
-
- __intrinsic_op void Store3(
- uint address,
- uint3 value);
-
- __intrinsic_op void Store4(
- uint address,
- uint4 value);
-};
-
-__generic<T> __magic_type(HLSLRWStructuredBufferType) struct RWStructuredBuffer
-{
- __intrinsic_op uint DecrementCounter();
-
- __intrinsic_op void GetDimensions(
- out uint numStructs,
- out uint stride);
-
- __intrinsic_op void IncrementCounter();
-
- __intrinsic_op T Load(int location);
- __intrinsic_op T Load(int location, out uint status);
-
- __intrinsic_op __subscript(uint index) -> T { get; set; }
-};
-
-__generic<T> __magic_type(HLSLPointStreamType) struct PointStream
-{
- void Append(T value);
- void RestartStrip();
-};
-
-__generic<T> __magic_type(HLSLLineStreamType) struct LineStream
-{
- void Append(T value);
- void RestartStrip();
-};
-
-__generic<T> __magic_type(HLSLTriangleStreamType) struct TriangleStream
-{
- void Append(T value);
- void RestartStrip();
-};
-
-)=", R"=(
-
-// Note(tfoley): Trying to systematically add all the HLSL builtins
-
-// Try to terminate the current draw or dispatch call (HLSL SM 4.0)
-__intrinsic_op void abort();
-
-// Absolute value (HLSL SM 1.0)
-__generic<T : __BuiltinSignedArithmeticType> __intrinsic_op T abs(T x);
-__generic<T : __BuiltinSignedArithmeticType, let N : int> __intrinsic_op vector<T,N> abs(vector<T,N> x);
-__generic<T : __BuiltinSignedArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> abs(matrix<T,N,M> x);
-
-// Inverse cosine (HLSL SM 1.0)
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T acos(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> acos(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> acos(matrix<T,N,M> x);
-
-// Test if all components are non-zero (HLSL SM 1.0)
-__generic<T : __BuiltinType> __intrinsic_op T all(T x);
-__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> all(vector<T,N> x);
-__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> all(matrix<T,N,M> x);
-
-// Barrier for writes to all memory spaces (HLSL SM 5.0)
-__intrinsic_op void AllMemoryBarrier();
-
-// Thread-group sync and barrier for writes to all memory spaces (HLSL SM 5.0)
-__intrinsic_op void AllMemoryBarrierWithGroupSync();
-
-// Test if any components is non-zero (HLSL SM 1.0)
-__generic<T : __BuiltinType> __intrinsic_op T any(T x);
-__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> any(vector<T,N> x);
-__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> any(matrix<T,N,M> x);
-
-
-// Reinterpret bits as a double (HLSL SM 5.0)
-__intrinsic_op double asdouble(uint lowbits, uint highbits);
-
-// Reinterpret bits as a float (HLSL SM 4.0)
-__intrinsic_op float asfloat( int x);
-__intrinsic_op float asfloat(uint x);
-__generic<let N : int> __intrinsic_op vector<float,N> asfloat(vector< int,N> x);
-__generic<let N : int> __intrinsic_op vector<float,N> asfloat(vector<uint,N> x);
-__generic<let N : int, let M : int> __intrinsic_op matrix<float,N,M> asfloat(matrix< int,N,M> x);
-__generic<let N : int, let M : int> __intrinsic_op matrix<float,N,M> asfloat(matrix<uint,N,M> x);
-
-
-// Inverse sine (HLSL SM 1.0)
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T asin(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> asin(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> asin(matrix<T,N,M> x);
-
-// Reinterpret bits as an int (HLSL SM 4.0)
-__intrinsic_op int asint(float x);
-__intrinsic_op int asint(uint x);
-__generic<let N : int> __intrinsic_op vector<int,N> asint(vector<float,N> x);
-__generic<let N : int> __intrinsic_op vector<int,N> asint(vector<uint,N> x);
-__generic<let N : int, let M : int> __intrinsic_op matrix<int,N,M> asint(matrix<float,N,M> x);
-__generic<let N : int, let M : int> __intrinsic_op matrix<int,N,M> asint(matrix<uint,N,M> x);
-
-// Reinterpret bits of double as a uint (HLSL SM 5.0)
-__intrinsic_op void asuint(double value, out uint lowbits, out uint highbits);
-
-// Reinterpret bits as a uint (HLSL SM 4.0)
-__intrinsic_op uint asuint(float x);
-__intrinsic_op uint asuint(int x);
-__generic<let N : int> __intrinsic_op vector<uint,N> asuint(vector<float,N> x);
-__generic<let N : int> __intrinsic_op vector<uint,N> asuint(vector<int,N> x);
-__generic<let N : int, let M : int> __intrinsic_op matrix<uint,N,M> asuint(matrix<float,N,M> x);
-__generic<let N : int, let M : int> __intrinsic_op matrix<uint,N,M> asuint(matrix<int,N,M> x);
-
-// Inverse tangent (HLSL SM 1.0)
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T atan(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> atan(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> atan(matrix<T,N,M> x);
-
-__generic<T : __BuiltinFloatingPointType>
-__target_intrinsic(glsl,"atan($0,$1)")
-__intrinsic_op
-T atan2(T y, T x);
-
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__target_intrinsic(glsl,"atan($0,$1)")
-__intrinsic_op
-vector<T,N> atan2(vector<T,N> y, vector<T,N> x);
-
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__target_intrinsic(glsl,"atan($0,$1)")
-__intrinsic_op
-matrix<T,N,M> atan2(matrix<T,N,M> y, matrix<T,N,M> x);
-
-// Ceiling (HLSL SM 1.0)
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T ceil(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> ceil(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> ceil(matrix<T,N,M> x);
-
-
-// Check access status to tiled resource
-__intrinsic_op bool CheckAccessFullyMapped(uint status);
-
-// Clamp (HLSL SM 1.0)
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T clamp(T x, T min, T max);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> clamp(vector<T,N> x, vector<T,N> min, vector<T,N> max);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> clamp(matrix<T,N,M> x, matrix<T,N,M> min, matrix<T,N,M> max);
-
-// Clip (discard) fragment conditionally
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op void clip(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op void clip(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op void clip(matrix<T,N,M> x);
-
-// Cosine
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T cos(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> cos(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> cos(matrix<T,N,M> x);
-
-// Hyperbolic cosine
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T cosh(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> cosh(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> cosh(matrix<T,N,M> x);
-
-// Population count
-__intrinsic_op uint countbits(uint value);
-
-// Cross product
-__generic<T : __BuiltinArithmeticType> __intrinsic_op vector<T,3> cross(vector<T,3> x, vector<T,3> y);
-
-// Convert encoded color
-__intrinsic_op int4 D3DCOLORtoUBYTE4(float4 x);
-
-// Partial-difference derivatives
-__generic<T : __BuiltinFloatingPointType>
-__target_intrinsic(glsl, dFdx)
-__intrinsic_op
-T ddx(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__target_intrinsic(glsl, dFdx)
-__intrinsic_op
-vector<T,N> ddx(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__target_intrinsic(glsl, dFdx)
-__intrinsic_op
-matrix<T,N,M> ddx(matrix<T,N,M> x);
-
-__generic<T : __BuiltinFloatingPointType>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdxCoarse)
-__intrinsic_op
-T ddx_coarse(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdxCoarse)
-__intrinsic_op
-vector<T,N> ddx_coarse(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdxCoarse)
-__intrinsic_op
-matrix<T,N,M> ddx_coarse(matrix<T,N,M> x);
-
-__generic<T : __BuiltinFloatingPointType>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdxFine)
-__intrinsic_op
-T ddx_fine(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdxFine)
-__intrinsic_op
-vector<T,N> ddx_fine(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdxFine)
-__intrinsic_op
-matrix<T,N,M> ddx_fine(matrix<T,N,M> x);
-
-__generic<T : __BuiltinFloatingPointType>
-__target_intrinsic(glsl, dFdy)
-__intrinsic_op
-T ddy(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__target_intrinsic(glsl, dFdy)
-__intrinsic_op
-vector<T,N> ddy(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__target_intrinsic(glsl, dFdy)
-__intrinsic_op
- matrix<T,N,M> ddy(matrix<T,N,M> x);
-
-__generic<T : __BuiltinFloatingPointType>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdyCoarse)
-__intrinsic_op
-T ddy_coarse(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdyCoarse)
-__intrinsic_op
-vector<T,N> ddy_coarse(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdyCoarse)
-__intrinsic_op
-matrix<T,N,M> ddy_coarse(matrix<T,N,M> x);
-
-__generic<T : __BuiltinFloatingPointType>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdyFine)
-__intrinsic_op
-T ddy_fine(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdyFine)
-__intrinsic_op
-vector<T,N> ddy_fine(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__glsl_extension(GL_ARB_derivative_control)
-__target_intrinsic(glsl, dFdyFine)
-__intrinsic_op
-matrix<T,N,M> ddy_fine(matrix<T,N,M> x);
-
-
-// Radians to degrees
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T degrees(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> degrees(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> degrees(matrix<T,N,M> x);
-
-// Matrix determinant
-
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op T determinant(matrix<T,N,N> m);
-
-// Barrier for device memory
-__intrinsic_op void DeviceMemoryBarrier();
-__intrinsic_op void DeviceMemoryBarrierWithGroupSync();
-
-// Vector distance
-
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op T distance(vector<T,N> x, vector<T,N> y);
-
-// Vector dot product
-
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op T dot(vector<T,N> x, vector<T,N> y);
-
-// Helper for computing distance terms for lighting (obsolete)
-
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op vector<T,4> dst(vector<T,4> x, vector<T,4> y);
-
-// Error message
-
-// __intrinsic_op void errorf( string format, ... );
-
-// Attribute evaluation
-
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T EvaluateAttributeAtCentroid(T x);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> EvaluateAttributeAtCentroid(vector<T,N> x);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> EvaluateAttributeAtCentroid(matrix<T,N,M> x);
-
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T EvaluateAttributeAtSample(T x, uint sampleindex);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> EvaluateAttributeAtSample(vector<T,N> x, uint sampleindex);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> EvaluateAttributeAtSample(matrix<T,N,M> x, uint sampleindex);
-
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T EvaluateAttributeSnapped(T x, int2 offset);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> EvaluateAttributeSnapped(vector<T,N> x, int2 offset);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> EvaluateAttributeSnapped(matrix<T,N,M> x, int2 offset);
-
-// Base-e exponent
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T exp(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> exp(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> exp(matrix<T,N,M> x);
-
-// Base-2 exponent
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T exp2(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> exp2(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> exp2(matrix<T,N,M> x);
-
-// Convert 16-bit float stored in low bits of integer
-__intrinsic_op float f16tof32(uint value);
-__generic<let N : int> __intrinsic_op vector<float,N> f16tof32(vector<uint,N> value);
-
-// Convert to 16-bit float stored in low bits of integer
-__intrinsic_op uint f32tof16(float value);
-__generic<let N : int> __intrinsic_op vector<uint,N> f32tof16(vector<float,N> value);
-
-// Flip surface normal to face forward, if needed
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op 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
-__intrinsic_op int firstbithigh(int value);
-__generic<let N : int> __intrinsic_op vector<int,N> firstbithigh(vector<int,N> value);
-
-__intrinsic_op uint firstbithigh(uint value);
-__generic<let N : int> __intrinsic_op vector<uint,N> firstbithigh(vector<uint,N> value);
-
-// Find first set bit starting at low bit and working up
-__intrinsic_op int firstbitlow(int value);
-__generic<let N : int> __intrinsic_op vector<int,N> firstbitlow(vector<int,N> value);
-
-__intrinsic_op uint firstbitlow(uint value);
-__generic<let N : int> __intrinsic_op vector<uint,N> firstbitlow(vector<uint,N> value);
-
-// Floor (HLSL SM 1.0)
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T floor(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> floor(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> floor(matrix<T,N,M> x);
-
-// Fused multiply-add for doubles
-__intrinsic_op double fma(double a, double b, double c);
-__generic<let N : int> __intrinsic_op vector<double, N> fma(vector<double, N> a, vector<double, N> b, vector<double, N> c);
-__generic<let N : int, let M : int> __intrinsic_op matrix<double,N,M> fma(matrix<double,N,M> a, matrix<double,N,M> b, matrix<double,N,M> c);
-
-// Floating point remainder of x/y
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T fmod(T x, T y);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> fmod(vector<T,N> x, vector<T,N> y);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> fmod(matrix<T,N,M> x, matrix<T,N,M> y);
-
-// Fractional part
-__generic<T : __BuiltinFloatingPointType>
-__target_intrinsic(glsl, fract)
-__intrinsic_op
-T frac(T x);
-
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__target_intrinsic(glsl, fract)
-__intrinsic_op
-vector<T,N> frac(vector<T,N> x);
-
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__target_intrinsic(glsl, fract)
-__intrinsic_op
-matrix<T,N,M> frac(matrix<T,N,M> x);
-
-// Split float into mantissa and exponent
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T frexp(T x, out T exp);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> frexp(vector<T,N> x, out vector<T,N> exp);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> frexp(matrix<T,N,M> x, out matrix<T,N,M> exp);
-
-// Texture filter width
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T fwidth(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> fwidth(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> fwidth(matrix<T,N,M> x);
-
-)=", R"=(
-
-// Get number of samples in render target
-__intrinsic_op uint GetRenderTargetSampleCount();
-
-// Get position of given sample
-__intrinsic_op float2 GetRenderTargetSamplePosition(int Index);
-
-// Group memory barrier
-__intrinsic_op void GroupMemoryBarrier();
-__intrinsic_op void GroupMemoryBarrierWithGroupSync();
-
-// Atomics
-__intrinsic_op void InterlockedAdd(in out int dest, int value, out int original_value);
-__intrinsic_op void InterlockedAdd(in out uint dest, uint value, out uint original_value);
-
-__intrinsic_op void InterlockedAnd(in out int dest, int value, out int original_value);
-__intrinsic_op void InterlockedAnd(in out uint dest, uint value, out uint original_value);
-
-__intrinsic_op void InterlockedCompareExchange(in out int dest, int compare_value, int value, out int original_value);
-__intrinsic_op void InterlockedCompareExchange(in out uint dest, uint compare_value, uint value, out uint original_value);
-
-__intrinsic_op void InterlockedCompareStore(in out int dest, int compare_value, int value);
-__intrinsic_op void InterlockedCompareStore(in out uint dest, uint compare_value, uint value);
-
-__intrinsic_op void InterlockedExchange(in out int dest, int value, out int original_value);
-__intrinsic_op void InterlockedExchange(in out uint dest, uint value, out uint original_value);
-
-__intrinsic_op void InterlockedMax(in out int dest, int value, out int original_value);
-__intrinsic_op void InterlockedMax(in out uint dest, uint value, out uint original_value);
-
-__intrinsic_op void InterlockedMin(in out int dest, int value, out int original_value);
-__intrinsic_op void InterlockedMin(in out uint dest, uint value, out uint original_value);
-
-__intrinsic_op void InterlockedOr(in out int dest, int value, out int original_value);
-__intrinsic_op void InterlockedOr(in out uint dest, uint value, out uint original_value);
-
-__intrinsic_op void InterlockedXor(in out int dest, int value, out int original_value);
-__intrinsic_op void InterlockedXor(in out uint dest, uint value, out uint original_value);
-
-// Is floating-point value finite?
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op bool isfinite(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<bool,N> isfinite(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<bool,N,M> isfinite(matrix<T,N,M> x);
-
-// Is floating-point value infinite?
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op bool isinf(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<bool,N> isinf(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<bool,N,M> isinf(matrix<T,N,M> x);
-
-// Is floating-point value not-a-number?
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op bool isnan(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<bool,N> isnan(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<bool,N,M> isnan(matrix<T,N,M> x);
-
-// Construct float from mantissa and exponent
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T ldexp(T x, T exp);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> ldexp(vector<T,N> x, vector<T,N> exp);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> ldexp(matrix<T,N,M> x, matrix<T,N,M> exp);
-
-// Vector length
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op T length(vector<T,N> x);
-
-// Linear interpolation
-__generic<T : __BuiltinFloatingPointType>
-__target_intrinsic(glsl, mix)
-__intrinsic_op
-T lerp(T x, T y, T s);
-
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__target_intrinsic(glsl, mix)
-__intrinsic_op
-vector<T,N> lerp(vector<T,N> x, vector<T,N> y, vector<T,N> s);
-
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__target_intrinsic(glsl, mix)
-__intrinsic_op
-matrix<T,N,M> lerp(matrix<T,N,M> x, matrix<T,N,M> y, matrix<T,N,M> s);
-
-// Legacy lighting function (obsolete)
-__intrinsic_op float4 lit(float n_dot_l, float n_dot_h, float m);
-
-// Base-e logarithm
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T log(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> log(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> log(matrix<T,N,M> x);
-
-// Base-10 logarithm
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T log10(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> log10(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> log10(matrix<T,N,M> x);
-
-// Base-2 logarithm
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T log2(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> log2(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> log2(matrix<T,N,M> x);
-
-// multiply-add
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T mad(T mvalue, T avalue, T bvalue);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> mad(vector<T,N> mvalue, vector<T,N> avalue, vector<T,N> bvalue);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> mad(matrix<T,N,M> mvalue, matrix<T,N,M> avalue, matrix<T,N,M> bvalue);
-
-// maximum
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T max(T x, T y);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> max(vector<T,N> x, vector<T,N> y);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> max(matrix<T,N,M> x, matrix<T,N,M> y);
-
-// minimum
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T min(T x, T y);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> min(vector<T,N> x, vector<T,N> y);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> min(matrix<T,N,M> x, matrix<T,N,M> y);
-
-// split into integer and fractional parts (both with same sign)
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T modf(T x, out T ip);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> modf(vector<T,N> x, out vector<T,N> ip);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> modf(matrix<T,N,M> x, out matrix<T,N,M> ip);
-
-// msad4 (whatever that is)
-__intrinsic_op uint4 msad4(uint reference, uint2 source, uint4 accum);
-
-// General inner products
-
-// scalar-scalar
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T mul(T x, T y);
-
-// scalar-vector and vector-scalar
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> mul(vector<T,N> x, T y);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> mul(T x, vector<T,N> y);
-
-// scalar-matrix and matrix-scalar
-__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op matrix<T,N,M> mul(matrix<T,N,M> x, T y);
-__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op matrix<T,N,M> mul(T x, matrix<T,N,M> y);
-
-// vector-vector (dot product)
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(dot) T mul(vector<T,N> x, vector<T,N> y);
-
-// vector-matrix
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulVectorMatrix) vector<T,M> mul(vector<T,N> x, matrix<T,N,M> y);
-
-// matrix-vector
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulMatrixVector) vector<T,N> mul(matrix<T,N,M> x, vector<T,M> y);
-
-// matrix-matrix
-__generic<T : __BuiltinArithmeticType, let R : int, let N : int, let C : int> __intrinsic_op(mulMatrixMatrix) matrix<T,R,C> mul(matrix<T,R,N> x, matrix<T,N,C> y);
-
-// noise (deprecated)
-__intrinsic_op float noise(float x);
-__generic<let N : int> __intrinsic_op float noise(vector<float, N> x);
-
-// Normalize a vector
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> normalize(vector<T,N> x);
-
-// Raise to a power
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T pow(T x, T y);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> pow(vector<T,N> x, vector<T,N> y);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> pow(matrix<T,N,M> x, matrix<T,N,M> y);
-
-// Output message
-
-// __intrinsic_op void printf( string format, ... );
-
-// Tessellation factor fixup routines
-
-__intrinsic_op void Process2DQuadTessFactorsAvg(
- in float4 RawEdgeFactors,
- in float2 InsideScale,
- out float4 RoundedEdgeTessFactors,
- out float2 RoundedInsideTessFactors,
- out float2 UnroundedInsideTessFactors);
-
-__intrinsic_op void Process2DQuadTessFactorsMax(
- in float4 RawEdgeFactors,
- in float2 InsideScale,
- out float4 RoundedEdgeTessFactors,
- out float2 RoundedInsideTessFactors,
- out float2 UnroundedInsideTessFactors);
-
-__intrinsic_op void Process2DQuadTessFactorsMin(
- in float4 RawEdgeFactors,
- in float2 InsideScale,
- out float4 RoundedEdgeTessFactors,
- out float2 RoundedInsideTessFactors,
- out float2 UnroundedInsideTessFactors);
-
-__intrinsic_op void ProcessIsolineTessFactors(
- in float RawDetailFactor,
- in float RawDensityFactor,
- out float RoundedDetailFactor,
- out float RoundedDensityFactor);
-
-__intrinsic_op void ProcessQuadTessFactorsAvg(
- in float4 RawEdgeFactors,
- in float InsideScale,
- out float4 RoundedEdgeTessFactors,
- out float2 RoundedInsideTessFactors,
- out float2 UnroundedInsideTessFactors);
-
-__intrinsic_op void ProcessQuadTessFactorsMax(
- in float4 RawEdgeFactors,
- in float InsideScale,
- out float4 RoundedEdgeTessFactors,
- out float2 RoundedInsideTessFactors,
- out float2 UnroundedInsideTessFactors);
-
-__intrinsic_op void ProcessQuadTessFactorsMin(
- in float4 RawEdgeFactors,
- in float InsideScale,
- out float4 RoundedEdgeTessFactors,
- out float2 RoundedInsideTessFactors,
- out float2 UnroundedInsideTessFactors);
-
-__intrinsic_op void ProcessTriTessFactorsAvg(
- in float3 RawEdgeFactors,
- in float InsideScale,
- out float3 RoundedEdgeTessFactors,
- out float RoundedInsideTessFactor,
- out float UnroundedInsideTessFactor);
-
-__intrinsic_op void ProcessTriTessFactorsMax(
- in float3 RawEdgeFactors,
- in float InsideScale,
- out float3 RoundedEdgeTessFactors,
- out float RoundedInsideTessFactor,
- out float UnroundedInsideTessFactor);
-
-__intrinsic_op void ProcessTriTessFactorsMin(
- in float3 RawEdgeFactors,
- in float InsideScale,
- out float3 RoundedEdgeTessFactors,
- out float RoundedInsideTessFactors,
- out float UnroundedInsideTessFactors);
-
-// Degrees to radians
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T radians(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> radians(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> radians(matrix<T,N,M> x);
-
-// Approximate reciprocal
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T rcp(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> rcp(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> rcp(matrix<T,N,M> x);
-
-// Reflect incident vector across plane with given normal
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__intrinsic_op
-vector<T,N> reflect(vector<T,N> i, vector<T,N> n);
-
-// Refract incident vector given surface normal and index of refraction
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__intrinsic_op
-vector<T,N> refract(vector<T,N> i, vector<T,N> n, float eta);
-
-// Reverse order of bits
-__intrinsic_op uint reversebits(uint value);
-__generic<let N : int> vector<uint,N> reversebits(vector<uint,N> value);
-
-// Round-to-nearest
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T round(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> round(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> round(matrix<T,N,M> x);
-
-// Reciprocal of square root
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T rsqrt(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> rsqrt(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> rsqrt(matrix<T,N,M> x);
-
-// Clamp value to [0,1] range
-__generic<T : __BuiltinFloatingPointType>
-__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op
-T saturate(T x);
-
-__generic<T : __BuiltinFloatingPointType, let N : int>
-__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op
-vector<T,N> saturate(vector<T,N> x);
-
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>
-__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op
-matrix<T,N,M> saturate(matrix<T,N,M> x);
-
-
-// Extract sign of value
-__generic<T : __BuiltinSignedArithmeticType> __intrinsic_op int sign(T x);
-__generic<T : __BuiltinSignedArithmeticType, let N : int> __intrinsic_op vector<int,N> sign(vector<T,N> x);
-__generic<T : __BuiltinSignedArithmeticType, let N : int, let M : int> __intrinsic_op matrix<int,N,M> sign(matrix<T,N,M> x);
-
-)=", R"=(
-
-
-// Sine
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T sin(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> sin(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> sin(matrix<T,N,M> x);
-
-// Sine and cosine
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op void sincos(T x, out T s, out T c);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op void sincos(vector<T,N> x, out vector<T,N> s, out vector<T,N> c);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op void sincos(matrix<T,N,M> x, out matrix<T,N,M> s, out matrix<T,N,M> c);
-
-// Hyperbolic Sine
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T sinh(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> sinh(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> sinh(matrix<T,N,M> x);
-
-// Smooth step (Hermite interpolation)
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T smoothstep(T min, T max, T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> smoothstep(vector<T,N> min, vector<T,N> max, vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> smoothstep(matrix<T,N,M> min, matrix<T,N,M> max, matrix<T,N,M> x);
-
-// Square root
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T sqrt(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> sqrt(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> sqrt(matrix<T,N,M> x);
-
-// Step function
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T step(T y, T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> step(vector<T,N> y, vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> step(matrix<T,N,M> y, matrix<T,N,M> x);
-
-// Tangent
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T tan(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> tan(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> tan(matrix<T,N,M> x);
-
-// Hyperbolic tangent
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T tanh(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> tanh(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> tanh(matrix<T,N,M> x);
-
-// Legacy texture-fetch operations
-
-/*
-__intrinsic_op float4 tex1D(sampler1D s, float t);
-__intrinsic_op float4 tex1D(sampler1D s, float t, float ddx, float ddy);
-__intrinsic_op float4 tex1Dbias(sampler1D s, float4 t);
-__intrinsic_op float4 tex1Dgrad(sampler1D s, float t, float ddx, float ddy);
-__intrinsic_op float4 tex1Dlod(sampler1D s, float4 t);
-__intrinsic_op float4 tex1Dproj(sampler1D s, float4 t);
-
-__intrinsic_op float4 tex2D(sampler2D s, float2 t);
-__intrinsic_op float4 tex2D(sampler2D s, float2 t, float2 ddx, float2 ddy);
-__intrinsic_op float4 tex2Dbias(sampler2D s, float4 t);
-__intrinsic_op float4 tex2Dgrad(sampler2D s, float2 t, float2 ddx, float2 ddy);
-__intrinsic_op float4 tex2Dlod(sampler2D s, float4 t);
-__intrinsic_op float4 tex2Dproj(sampler2D s, float4 t);
-
-__intrinsic_op float4 tex3D(sampler3D s, float3 t);
-__intrinsic_op float4 tex3D(sampler3D s, float3 t, float3 ddx, float3 ddy);
-__intrinsic_op float4 tex3Dbias(sampler3D s, float4 t);
-__intrinsic_op float4 tex3Dgrad(sampler3D s, float3 t, float3 ddx, float3 ddy);
-__intrinsic_op float4 tex3Dlod(sampler3D s, float4 t);
-__intrinsic_op float4 tex3Dproj(sampler3D s, float4 t);
-
-__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t);
-__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t, float3 ddx, float3 ddy);
-__intrinsic_op float4 texCUBEbias(samplerCUBE s, float4 t);
-__intrinsic_op float4 texCUBEgrad(samplerCUBE s, float3 t, float3 ddx, float3 ddy);
-__intrinsic_op float4 texCUBElod(samplerCUBE s, float4 t);
-__intrinsic_op float4 texCUBEproj(samplerCUBE s, float4 t);
-*/
-
-// Matrix transpose
-__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,M,N> transpose(matrix<T,N,M> x);
-
-// Truncate to integer
-__generic<T : __BuiltinFloatingPointType> __intrinsic_op T trunc(T x);
-__generic<T : __BuiltinFloatingPointType, let N : int> __intrinsic_op vector<T,N> trunc(vector<T,N> x);
-__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> trunc(matrix<T,N,M> x);
-
-
-)=", R"=(
-
-// Shader model 6.0 stuff
-
-__intrinsic_op uint GlobalOrderedCountIncrement(uint countToAppendForThisLane);
-
-__generic<T : __BuiltinType> __intrinsic_op T QuadReadLaneAt(T sourceValue, int quadLaneID);
-__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> QuadReadLaneAt(vector<T,N> sourceValue, int quadLaneID);
-__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> QuadReadLaneAt(matrix<T,N,M> sourceValue, int quadLaneID);
-
-__generic<T : __BuiltinType> __intrinsic_op T QuadSwapX(T localValue);
-__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> QuadSwapX(vector<T,N> localValue);
-__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> QuadSwapX(matrix<T,N,M> localValue);
-
-__generic<T : __BuiltinType> __intrinsic_op T QuadSwapY(T localValue);
-__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> QuadSwapY(vector<T,N> localValue);
-__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> QuadSwapY(matrix<T,N,M> localValue);
-
-__generic<T : __BuiltinIntegerType> __intrinsic_op T WaveAllBitAnd(T expr);
-__generic<T : __BuiltinIntegerType, let N : int> __intrinsic_op vector<T,N> WaveAllBitAnd(vector<T,N> expr);
-__generic<T : __BuiltinIntegerType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllBitAnd(matrix<T,N,M> expr);
-
-__generic<T : __BuiltinIntegerType> __intrinsic_op T WaveAllBitOr(T expr);
-__generic<T : __BuiltinIntegerType, let N : int> __intrinsic_op vector<T,N> WaveAllBitOr(vector<T,N> expr);
-__generic<T : __BuiltinIntegerType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllBitOr(matrix<T,N,M> expr);
-
-__generic<T : __BuiltinIntegerType> __intrinsic_op T WaveAllBitXor(T expr);
-__generic<T : __BuiltinIntegerType, let N : int> __intrinsic_op vector<T,N> WaveAllBitXor(vector<T,N> expr);
-__generic<T : __BuiltinIntegerType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllBitXor(matrix<T,N,M> expr);
-
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllMax(T expr);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllMax(vector<T,N> expr);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllMax(matrix<T,N,M> expr);
-
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllMin(T expr);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllMin(vector<T,N> expr);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllMin(matrix<T,N,M> expr);
-
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllProduct(T expr);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllProduct(vector<T,N> expr);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllProduct(matrix<T,N,M> expr);
-
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T WaveAllSum(T expr);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WaveAllSum(vector<T,N> expr);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveAllSum(matrix<T,N,M> expr);
-
-__intrinsic_op bool WaveAllEqual(bool expr);
-__intrinsic_op bool WaveAllTrue(bool expr);
-__intrinsic_op bool WaveAnyTrue(bool expr);
-
-uint64_t WaveBallot(bool expr);
-
-uint WaveGetLaneCount();
-uint WaveGetLaneIndex();
-uint WaveGetOrderedIndex();
-
-bool WaveIsHelperLane();
-
-bool WaveOnce();
-
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T WavePrefixProduct(T expr);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WavePrefixProduct(vector<T,N> expr);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WavePrefixProduct(matrix<T,N,M> expr);
-
-__generic<T : __BuiltinArithmeticType> __intrinsic_op T WavePrefixSum(T expr);
-__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op vector<T,N> WavePrefixSum(vector<T,N> expr);
-__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WavePrefixSum(matrix<T,N,M> expr);
-
-__generic<T : __BuiltinType> __intrinsic_op T WaveReadFirstLane(T expr);
-__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> WaveReadFirstLane(vector<T,N> expr);
-__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveReadFirstLane(matrix<T,N,M> expr);
-
-__generic<T : __BuiltinType> __intrinsic_op T WaveReadLaneAt(T expr, int laneIndex);
-__generic<T : __BuiltinType, let N : int> __intrinsic_op vector<T,N> WaveReadLaneAt(vector<T,N> expr, int laneIndex);
-__generic<T : __BuiltinType, let N : int, let M : int> __intrinsic_op matrix<T,N,M> WaveReadLaneAt(matrix<T,N,M> expr, int laneIndex);
-
-
-)=", R"=(
-
-// `typedef`s to help with the fact that HLSL has been sorta-kinda case insensitive at various points
-typedef Texture2D texture2D;
-
-#line default
-)=" };
-
-
namespace Slang
{
String Session::getStdlibPath()
@@ -1277,890 +244,11 @@ namespace Slang
StringBuilder sb;
- // generate operator overloads
-
-
String path = getStdlibPath();
#define EMIT_LINE_DIRECTIVE() sb << "#line " << (__LINE__+1) << " \"" << path << "\"\n"
- // Generate declarations for all the base types
-
- static const int kBaseTypeCount = sizeof(kBaseTypes) / sizeof(kBaseTypes[0]);
- for (int tt = 0; tt < kBaseTypeCount; ++tt)
- {
- EMIT_LINE_DIRECTIVE();
- sb << "__builtin_type(" << int(kBaseTypes[tt].tag) << ") struct " << kBaseTypes[tt].name;
-
- // Declare interface conformances for this type
-
- sb << "\n : __BuiltinType\n";
-
- switch (kBaseTypes[tt].tag)
- {
- case BaseType::Float:
- sb << "\n , __BuiltinFloatingPointType\n";
- sb << "\n , __BuiltinRealType\n";
- // fall through to:
- case BaseType::Int:
- sb << "\n , __BuiltinSignedArithmeticType\n";
- // fall through to:
- case BaseType::UInt:
- case BaseType::UInt64:
- sb << "\n , __BuiltinArithmeticType\n";
- // fall through to:
- case BaseType::Bool:
- sb << "\n , __BuiltinType\n";
- break;
-
- default:
- break;
- }
-
- sb << "\n{\n";
-
-
- // Declare initializers to convert from various other types
- for (int ss = 0; ss < kBaseTypeCount; ++ss)
- {
- // Don't allow conversion from `void`
- if (kBaseTypes[ss].tag == BaseType::Void)
- continue;
-
- // We need to emit a modifier so that the semantic-checking
- // layer will know it can use these operations for implicit
- // conversion.
- ConversionCost conversionCost = getBaseTypeConversionCost(
- kBaseTypes[tt],
- kBaseTypes[ss]);
-
- EMIT_LINE_DIRECTIVE();
- sb << "__implicit_conversion(" << conversionCost << ")\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "__init(" << kBaseTypes[ss].name << " value);\n";
- }
-
- sb << "};\n";
- }
-
- // Declare vector and matrix types
-
- sb << "__generic<T = float, let N : int = 4> __magic_type(Vector) struct vector\n{\n";
- sb << " typedef T Element;\n";
-
- // Declare initializer taking a single scalar of the elemnt type
- sb << " __implicit_conversion(" << kConversionCost_ScalarToVector << ")\n";
- sb << " __init(T value);\n";
-
- sb << "};\n";
-
- // TODO: Probably need to do similar
- sb << "__generic<T = float, let R : int = 4, let C : int = 4> __magic_type(Matrix) struct matrix {};\n";
-
- static const struct {
- char const* name;
- char const* glslPrefix;
- } kTypes[] =
- {
- {"float", ""},
- {"int", "i"},
- {"uint", "u"},
- {"bool", "b"},
- };
- static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]);
-
- for (int tt = 0; tt < kTypeCount; ++tt)
- {
- // Declare HLSL vector types
- for (int ii = 1; ii <= 4; ++ii)
- {
- sb << "typedef vector<" << kTypes[tt].name << "," << ii << "> " << kTypes[tt].name << ii << ";\n";
- }
-
- // Declare HLSL matrix types
- for (int rr = 2; rr <= 4; ++rr)
- for (int cc = 2; cc <= 4; ++cc)
- {
- sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].name << rr << "x" << cc << ";\n";
- }
- }
-
- // Declare additional built-in generic types
-// EMIT_LINE_DIRECTIVE();
-
-
- sb << "__generic<T>\n";
- sb << "__intrinsic_type(" << kIROp_ConstantBufferType << ")\n";
- sb << "__magic_type(ConstantBuffer) struct ConstantBuffer {};\n";
-
- sb << "__generic<T>\n";
- sb << "__intrinsic_type(" << kIROp_TextureBufferType << ")\n";
- sb << "__magic_type(TextureBuffer) struct TextureBuffer {};\n";
-
-
- static const char* kComponentNames[]{ "x", "y", "z", "w" };
- static const char* kVectorNames[]{ "", "x", "xy", "xyz", "xyzw" };
-
- // Need to add constructors to the types above
- for (int N = 2; N <= 4; ++N)
- {
- sb << "__generic<T> __extension vector<T, " << N << ">\n{\n";
-
- // initialize from N scalars
- sb << "__init(";
- for (int ii = 0; ii < N; ++ii)
- {
- if (ii != 0) sb << ", ";
- sb << "T " << kComponentNames[ii];
- }
- sb << ");\n";
-
- // Initialize from an M-vector and then scalars
- for (int M = 2; M < N; ++M)
- {
- sb << "__init(vector<T," << M << "> " << kVectorNames[M];
- for (int ii = M; ii < N; ++ii)
- {
- sb << ", T " << kComponentNames[ii];
- }
- sb << ");\n";
- }
-
- // initialize from another vector of the same size
- //
- // TODO(tfoley): this overlaps with implicit conversions.
- // We should look for a way that we can define implicit
- // conversions directly in the stdlib instead...
- sb << "__generic<U> __init(vector<U," << N << ">);\n";
-
- // Initialize from two vectors, of size M and N-M
- for(int M = 2; M <= (N-2); ++M)
- {
- int K = N - M;
- SLANG_ASSERT(K >= 2);
-
- sb << "__init(vector<T," << M << "> " << kVectorNames[M];
- sb << ", vector<T," << K << "> ";
- for (int ii = 0; ii < K; ++ii)
- {
- sb << kComponentNames[ii];
- }
- sb << ");\n";
- }
-
- sb << "}\n";
- }
-
- // The above extension was generic in the *type* of the vector,
- // but explicit in the *size*. We will now declare an extension
- // for each builtin type that is generic in the size.
- //
- for (int tt = 0; tt < kBaseTypeCount; ++tt)
- {
- if(kBaseTypes[tt].tag == BaseType::Void) continue;
-
- sb << "__generic<let N : int> __extension vector<"
- << kBaseTypes[tt].name << ",N>\n{\n";
-
- for (int ff = 0; ff < kBaseTypeCount; ++ff)
- {
- if(kBaseTypes[ff].tag == BaseType::Void) continue;
-
- // We need a constructor to make a vector from a scalar
- // of another type.
-
- if( tt != ff )
- {
- auto cost = getBaseTypeConversionCost(
- kBaseTypes[tt],
- kBaseTypes[ff]);
- cost += kConversionCost_ScalarToVector;
-
- sb << " __implicit_conversion(" << cost << ")\n";
- sb << " __init(" << kBaseTypes[ff].name << " value);\n";
- }
- }
-
- sb << "}\n";
- }
-
- for( int R = 2; R <= 4; ++R )
- for( int C = 2; C <= 4; ++C )
- {
- sb << "__generic<T> __extension matrix<T, " << R << "," << C << ">\n{\n";
-
- // initialize from R*C scalars
- sb << "__init(";
- for( int ii = 0; ii < R; ++ii )
- for( int jj = 0; jj < C; ++jj )
- {
- if ((ii+jj) != 0) sb << ", ";
- sb << "T m" << ii << jj;
- }
- sb << ");\n";
-
- // Initialize from R C-vectors
- sb << "__init(";
- for (int ii = 0; ii < R; ++ii)
- {
- if(ii != 0) sb << ", ";
- sb << "vector<T," << C << "> row" << ii;
- }
- sb << ");\n";
-
-
- // initialize from another matrix of the same size
- //
- // TODO(tfoley): See comment about how this overlaps
- // with implicit conversion, in the `vector` case above
- sb << "__generic<U> __init(matrix<U," << R << ", " << C << ">);\n";
-
- // initialize from a matrix of larger size
- for(int rr = R; rr <= 4; ++rr)
- for( int cc = C; cc <= 4; ++cc )
- {
- if(rr == R && cc == C) continue;
- sb << "__init(matrix<T," << rr << "," << cc << "> value);\n";
- }
-
- sb << "}\n";
- }
-
- // Declare built-in texture and sampler types
-
-
-
- sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ")\n";
- sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerState) << ")\n";
- sb << "struct SamplerState {};";
-
- sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n";
- sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n";
- sb << "struct SamplerComparisonState {};";
-
- // TODO(tfoley): Need to handle `RW*` variants of texture types as well...
- static const struct {
- char const* name;
- TextureType::Shape baseShape;
- int coordCount;
- } kBaseTextureTypes[] = {
- { "Texture1D", TextureType::Shape1D, 1 },
- { "Texture2D", TextureType::Shape2D, 2 },
- { "Texture3D", TextureType::Shape3D, 3 },
- { "TextureCube", TextureType::ShapeCube, 3 },
- };
- static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]);
-
-
- static const struct {
- char const* name;
- SlangResourceAccess access;
- } kBaseTextureAccessLevels[] = {
- { "", SLANG_RESOURCE_ACCESS_READ },
- { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
- { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
- };
- static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]);
-
- for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
- {
- char const* name = kBaseTextureTypes[tt].name;
- TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape;
-
- for (int isArray = 0; isArray < 2; ++isArray)
- {
- // Arrays of 3D textures aren't allowed
- if (isArray && baseShape == TextureType::Shape3D) continue;
-
- for (int isMultisample = 0; isMultisample < 2; ++isMultisample)
- for (int accessLevel = 0; accessLevel < kBaseTextureAccessLevelCount; ++accessLevel)
- {
- auto access = kBaseTextureAccessLevels[accessLevel].access;
-
- // TODO: any constraints to enforce on what gets to be multisampled?
-
- unsigned flavor = baseShape;
- if (isArray) flavor |= TextureType::ArrayFlag;
- if (isMultisample) flavor |= TextureType::MultisampleFlag;
-// if (isShadow) flavor |= TextureType::ShadowFlag;
-
- flavor |= (access << 8);
-
- // emit a generic signature
- // TODO: allow for multisample count to come in as well...
- sb << "__generic<T = float4> ";
-
- sb << "__magic_type(Texture," << int(flavor) << ")\n";
- sb << "__intrinsic_type(" << kIROp_TextureType << ", " << flavor << ")\n";
- sb << "struct ";
- sb << kBaseTextureAccessLevels[accessLevel].name;
- sb << name;
- if (isMultisample) sb << "MS";
- if (isArray) sb << "Array";
-// if (isShadow) sb << "Shadow";
- sb << "\n{";
-
- if( !isMultisample )
- {
- sb << "float CalculateLevelOfDetail(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
-
- sb << "float CalculateLevelOfDetailUnclamped(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
- }
-
- // `GetDimensions`
-
- for(int isFloat = 0; isFloat < 2; ++isFloat)
- for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo)
- {
- {
- sb << "__glsl_version(450)\n";
- sb << "__target_intrinsic(glsl, \"(";
-
- int aa = 0;
- String lodStr = "0";
- if (includeMipInfo)
- {
- int mipLevelArg = aa++;
- lodStr = "int($";
- lodStr.append(mipLevelArg);
- lodStr.append(")");
- }
-
- int cc = 0;
- switch(baseShape)
- {
- case TextureType::Shape1D:
- sb << "($" << aa++ << " = textureSize($P, " << lodStr << "))";
- cc = 1;
- break;
-
- case TextureType::Shape2D:
- case TextureType::ShapeCube:
- sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)";
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)";
- cc = 2;
- break;
-
- case TextureType::Shape3D:
- sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)";
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)";
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").z)";
- cc = 3;
- break;
-
- default:
- SLANG_UNEXPECTED("unhandled resource shape");
- break;
- }
-
- if(isArray)
- {
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ")." << kComponentNames[cc] << ")";
- }
-
- if(isMultisample)
- {
- sb << ", ($" << aa++ << " = textureSamples($P))";
- }
-
- if (includeMipInfo)
- {
- sb << ", ($" << aa++ << " = textureQueryLevels($P))";
- }
-
-
- sb << ")\")\n";
- sb << "__intrinsic_op\n";
-
- }
-
- char const* t = isFloat ? "out float " : "out uint ";
-
- sb << "void GetDimensions(";
- if(includeMipInfo)
- sb << "uint mipLevel, ";
-
- switch(baseShape)
- {
- case TextureType::Shape1D:
- sb << t << "width";
- break;
-
- case TextureType::Shape2D:
- case TextureType::ShapeCube:
- sb << t << "width,";
- sb << t << "height";
- break;
-
- case TextureType::Shape3D:
- sb << t << "width,";
- sb << t << "height,";
- sb << t << "depth";
- break;
-
- default:
- assert(!"unexpected");
- break;
- }
-
- if(isArray)
- {
- sb << ", " << t << "elements";
- }
-
- if(isMultisample)
- {
- sb << ", " << t << "sampleCount";
- }
-
- if(includeMipInfo)
- sb << ", " << t << "numberOfLevels";
-
- sb << ");\n";
- }
-
- // `GetSamplePosition()`
- if( isMultisample )
- {
- sb << "float2 GetSamplePosition(int s);\n";
- }
-
- // `Load()`
-
- if( kBaseTextureTypes[tt].coordCount + isArray < 4 )
- {
- int loadCoordCount = kBaseTextureTypes[tt].coordCount + isArray + (isMultisample?0:1);
-
- // When translating to GLSL, we need to break apart the `location` argument.
- //
- // TODO: this should realy be handled by having this member actually get lowered!
- static const char* kGLSLLoadCoordsSwizzle[] = { "", "", "x", "xy", "xyz", "xyzw" };
- static const char* kGLSLLoadLODSwizzle[] = { "", "", "y", "z", "w", "error" };
-
- if (isMultisample)
- {
- sb << "__target_intrinsic(glsl, \"texelFetch($P, $0, $1)\")\n";
- }
- else
- {
- sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
- }
- sb << "__intrinsic_op\n";
- sb << "T Load(";
- sb << "int" << loadCoordCount << " location";
- if(isMultisample)
- {
- sb << ", int sampleIndex";
- }
- sb << ");\n";
-
- if (isMultisample)
- {
- sb << "__target_intrinsic(glsl, \"texelFetchOffset($P, $0, $1, $2)\")\n";
- }
- else
- {
- sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $1)\")\n";
- }
- sb << "__intrinsic_op\n";
- sb << "T Load(";
- sb << "int" << loadCoordCount << " location";
- if(isMultisample)
- {
- sb << ", int sampleIndex";
- }
- sb << ", int" << loadCoordCount << " offset";
- sb << ");\n";
-
-
- sb << "T Load(";
- sb << "int" << loadCoordCount << " location";
- if(isMultisample)
- {
- sb << ", int sampleIndex";
- }
- sb << ", int" << kBaseTextureTypes[tt].coordCount << " offset";
- sb << ", out uint status";
- sb << ");\n";
- }
-
- if(baseShape != TextureType::ShapeCube)
- {
- // subscript operator
- sb << "__intrinsic_op __subscript(uint" << kBaseTextureTypes[tt].coordCount + isArray << " location) -> T;\n";
- }
-
- if( !isMultisample )
- {
- // `Sample()`
-
- sb << "__target_intrinsic(glsl, \"texture($p, $1)\")\n";
-
- // TODO: only enable if IR is being used?
- sb << "__intrinsic_op(sample)\n";
-
- sb << "__intrinsic_op\n";
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
-
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
- }
- sb << "float clamp);\n";
-
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
- }
- sb << "float clamp, out uint status);\n";
-
-
- // `SampleBias()`
- sb << "__target_intrinsic(glsl, \"texture($p, $1, $2)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T SampleBias(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2, $3)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T SampleBias(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
-
- // `SampleCmp()` and `SampleCmpLevelZero`
- sb << "T SampleCmp(SamplerComparisonState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float compareValue";
- sb << ");\n";
-
- int baseCoordCount = kBaseTextureTypes[tt].coordCount;
- int arrCoordCount = baseCoordCount + isArray;
- if (arrCoordCount < 3)
- {
- int extCoordCount = arrCoordCount + 1;
-
- if (extCoordCount < 3)
- extCoordCount = 3;
-
- sb << "__target_intrinsic(glsl, \"textureLod($p, ";
-
- sb << "vec" << extCoordCount << "($1,";
- for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
- {
- sb << " 0.0,";
- }
- sb << "$2)";
-
- sb << ", 0.0)\")\n";
- }
- else if(arrCoordCount <= 3)
- {
- int extCoordCount = arrCoordCount + 1;
-
- if (extCoordCount < 3)
- extCoordCount = 3;
-
- sb << "__target_intrinsic(glsl, \"textureGrad($p, ";
-
- sb << "vec" << extCoordCount << "($1,";
- for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
- {
- sb << " 0.0,";
- }
- sb << "$2)";
-
- // Construct gradients
- sb << ", vec" << baseCoordCount << "(0.0)";
- sb << ", vec" << baseCoordCount << "(0.0)";
- sb << ")\")\n";
- }
- sb << "__intrinsic_op\n";
- sb << "T SampleCmpLevelZero(SamplerComparisonState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float compareValue";
- sb << ");\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- // Note(tfoley): MSDN seems confused, and claims that the `offset`
- // parameter for `SampleCmp` is available for everything but 3D
- // textures, while `Sample` and `SampleBias` are consistent in
- // saying they only exclude `offset` for cube maps (which makes
- // sense). I'm going to assume the documentation for `SampleCmp`
- // is just wrong.
-
- sb << "T SampleCmp(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float compareValue, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
-
- sb << "T SampleCmpLevelZero(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float compareValue, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
-
-
- sb << "__target_intrinsic(glsl, \"textureGrad($p, $1, $2, $3)\")\n";
- sb << "__intrinsic_op(sampleGrad)\n";
- sb << "T SampleGrad(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY";
- sb << ");\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "__target_intrinsic(glsl, \"textureGradOffset($p, $1, $2, $3, $4)\")\n";
- sb << "__intrinsic_op(sampleGrad)\n";
- sb << "T SampleGrad(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
-
- // `SampleLevel`
-
- sb << "__target_intrinsic(glsl, \"textureLod($p, $1, $2)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T SampleLevel(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float level);\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "__target_intrinsic(glsl, \"textureLodOffset($p, $1, $2, $3)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T SampleLevel(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float level, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
- }
-
- sb << "\n};\n";
-
- // `Gather*()` operations are handled via an `extension` declaration,
- // because this lets us capture the element type of the texture.
- //
- // TODO: longer-term there should be something like a `TextureElementType`
- // interface, that both scalars and vectors implement, that then exposes
- // a `Scalar` associated type, and `Gather` can return `vector<T.Scalar, 4>`.
- //
- static const struct {
- char const* genericPrefix;
- char const* elementType;
- } kGatherExtensionCases[] = {
- { "__generic<T, let N : int>", "vector<T,N>" },
-
- // TODO: need a case here for scalars `T`, but also
- // need to ensure that case doesn't accidentally match
- // for `T = vector<...>`, which requires actual checking
- // of constraints on generic parameters.
- };
- for(auto cc : kGatherExtensionCases)
- {
- // TODO: this should really be an `if` around the entire `Gather` logic
- if (isMultisample) break;
-
- EMIT_LINE_DIRECTIVE();
- sb << cc.genericPrefix << " __extension ";
- sb << kBaseTextureAccessLevels[accessLevel].name;
- sb << name;
- if (isArray) sb << "Array";
- sb << "<" << cc.elementType << " >";
- sb << "\n{\n";
-
-
- // `Gather`
- // (tricky because it returns a 4-vector of the element type
- // of the texture components...)
- //
- // TODO: is it actually correct to restrict these so that, e.g.,
- // `GatherAlpha()` isn't allowed on `Texture2D<float3>` because
- // it nominally doesn't have an alpha component?
- static const struct {
- int componentIndex;
- char const* componentName;
- } kGatherComponets[] = {
- { 0, "" },
- { 0, "Red" },
- { 1, "Green" },
- { 2, "Blue" },
- { 3, "Alpha" },
- };
-
- for(auto kk : kGatherComponets)
- {
- auto componentIndex = kk.componentIndex;
- auto componentName = kk.componentName;
-
- EMIT_LINE_DIRECTIVE();
-
- sb << "__target_intrinsic(glsl, \"textureGather($p, $1, " << componentIndex << ")\")\n";
- sb << "__intrinsic_op\n";
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $1, $2, " << componentIndex << ")\")\n";
- sb << "__intrinsic_op\n";
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
- sb << "out uint status);\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $1, int" << kBaseTextureTypes[tt].coordCount << "[]($2, $3, $4, $5), " << componentIndex << ")\")\n";
- sb << "__intrinsic_op\n";
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4);\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4, ";
- sb << "out uint status);\n";
- }
-
- EMIT_LINE_DIRECTIVE();
- sb << "\n}\n";
- }
- }
- }
- }
-
-
- for (auto op : unaryOps)
- {
- for (auto type : kBaseTypes)
- {
- if ((type.flags & op.flags) == 0)
- continue;
-
- char const* fixity = (op.flags & POSTFIX) != 0 ? "__postfix " : "__prefix ";
- char const* qual = (op.flags & ASSIGNMENT) != 0 ? "in out " : "";
-
- // scalar version
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") " << type.name << " operator" << op.opName << "(" << qual << type.name << " value);\n";
-
- // vector version
- sb << "__generic<let N : int> ";
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << type.name << ",N> operator" << op.opName << "(" << qual << "vector<" << type.name << ",N> value);\n";
-
- // matrix version
- sb << "__generic<let N : int, let M : int> ";
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << type.name << ",N,M> operator" << op.opName << "(" << qual << "matrix<" << type.name << ",N,M> value);\n";
- }
- }
-
- for (auto op : binaryOps)
- {
- for (auto type : kBaseTypes)
- {
- if ((type.flags & op.flags) == 0)
- continue;
-
- char const* leftType = type.name;
- char const* rightType = leftType;
- char const* resultType = leftType;
-
- if (op.flags & COMPARISON) resultType = "bool";
-
- char const* leftQual = "";
- if(op.flags & ASSIGNMENT) leftQual = "in out ";
-
- // TODO: handle `SHIFT`
-
- // scalar version
- sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftQual << leftType << " left, " << rightType << " right);\n";
-
- // vector version
- sb << "__generic<let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n";
-
- // matrix version
-
- // skip matrix-matrix multiply operations here, so that GLSL doesn't see them
- switch (op.opCode)
- {
- case kIROp_Mul:
- case kIRPseudoOp_MulAssign:
- break;
-
- default:
- sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
- break;
- }
-
- // We are going to go ahead and explicitly define combined
- // operations for the scalar-op-vector, etc. cases, rather
- // than rely on promotion rules.
-
- // scalar-vector and scalar-matrix
- if (!(op.flags & ASSIGNMENT))
- {
- sb << "__generic<let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n";
-
- sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << leftType << " left, matrix<" << rightType << ",N,M> right);\n";
- }
-
- // vector-scalar and matrix-scalar
- sb << "__generic<let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n";
-
- sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, " << rightType << " right);\n";
- }
- }
-
- // Output a suitable `#line` directive to point at our raw stdlib code above
- sb << "\n#line " << kCoreLibIncludeStringLine << " \"" << path << "\"\n";
-
- int chunkCount = sizeof(kCoreLibIncludeStringChunks) / sizeof(kCoreLibIncludeStringChunks[0]);
- for (int cc = 0; cc < chunkCount; ++cc)
- {
- sb << kCoreLibIncludeStringChunks[cc];
- }
+ #include "core.meta.slang.cpp"
coreLibraryCode = sb.ProduceString();
return coreLibraryCode;
@@ -2173,90 +261,7 @@ namespace Slang
StringBuilder sb;
-
- // Component-wise multiplication ops
- for(auto op : binaryOps)
- {
- switch (op.opCode)
- {
- default:
- continue;
-
- case kIROp_Mul:
- case kIRPseudoOp_MulAssign:
- break;
- }
-
- for (auto type : kBaseTypes)
- {
- if ((type.flags & op.flags) == 0)
- continue;
-
- char const* leftType = type.name;
- char const* rightType = leftType;
- char const* resultType = leftType;
-
- char const* leftQual = "";
- if(op.flags & ASSIGNMENT) leftQual = "in out ";
-
- sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
- }
- }
-
- //
-
- // Buffer types
-
- static const struct {
- char const* name;
- SlangResourceAccess access;
- } kBaseBufferAccessLevels[] = {
- { "", SLANG_RESOURCE_ACCESS_READ },
- { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
- { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
- };
- static const int kBaseBufferAccessLevelCount = sizeof(kBaseBufferAccessLevels) / sizeof(kBaseBufferAccessLevels[0]);
-
- for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
- {
-
- sb << "__generic<T> __magic_type(Texture, ";
- sb << ResourceType::makeFlavor(ResourceType::Shape::ShapeBuffer, kBaseBufferAccessLevels[aa].access);
- sb << ") struct ";
- sb << kBaseBufferAccessLevels[aa].name;
- sb << "Buffer {\n";
-
- sb << "__intrinsic_op void GetDimensions(out uint dim);\n";
-
- sb << "__target_intrinsic(glsl, \"texelFetch($P, $0)$z\")\n";
- sb << "__intrinsic_op T Load(int location);\n";
-
- sb << "__intrinsic_op T Load(int location, out uint status);\n";
-
- sb << "__target_intrinsic(glsl, \"texelFetch($P, int($0))$z\")\n";
- sb << "__intrinsic_op __subscript(uint index) -> T";
-
- if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ)
- {
- sb << " { get; set; }\n";
- }
- else
- {
- sb << ";\n";
- }
-
- sb << "};\n";
- }
-
- // Output a suitable `#line` directive to point at our raw stdlib code above
- sb << "\n#line " << kHLSLLibIncludeStringLine << " \"" << getStdlibPath() << "\"\n";
-
- int chunkCount = sizeof(kHLSLLibIncludeStringChunks) / sizeof(kHLSLLibIncludeStringChunks[0]);
- for (int cc = 0; cc < chunkCount; ++cc)
- {
- sb << kHLSLLibIncludeStringChunks[cc];
- }
+ #include "hlsl.meta.slang.cpp"
hlslLibraryCode = sb.ProduceString();
return hlslLibraryCode;
@@ -2274,203 +279,7 @@ namespace Slang
StringBuilder sb;
- static const struct {
- char const* name;
- char const* glslPrefix;
- } kTypes[] =
- {
- {"float", ""},
- {"int", "i"},
- {"uint", "u"},
- {"bool", "b"},
- };
- static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]);
-
- for( int tt = 0; tt < kTypeCount; ++tt )
- {
- // Declare GLSL aliases for HLSL types
- for (int vv = 2; vv <= 4; ++vv)
- {
- sb << "typedef vector<" << kTypes[tt].name << "," << vv << "> " << kTypes[tt].glslPrefix << "vec" << vv << ";\n";
- sb << "typedef matrix<" << kTypes[tt].name << "," << vv << "," << vv << "> " << kTypes[tt].glslPrefix << "mat" << vv << ";\n";
- }
- for (int rr = 2; rr <= 4; ++rr)
- for (int cc = 2; cc <= 4; ++cc)
- {
- sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].glslPrefix << "mat" << rr << "x" << cc << ";\n";
- }
- }
-
- // Multiplication operations for vectors + matrices
-
- // scalar-vector and vector-scalar
- sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(mul) vector<T,N> operator*(vector<T,N> x, T y);\n";
- sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(mul) vector<T,N> operator*(T x, vector<T,N> y);\n";
-
- // scalar-matrix and matrix-scalar
- sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(mul) matrix<T,N,M> operator*(matrix<T,N,M> x, T y);\n";
- sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(mul) matrix<T,N,M> operator*(T x, matrix<T,N,M> y);\n";
-
- // vector-vector (dot product)
- sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(dot) T operator*(vector<T,N> x, vector<T,N> y);\n";
-
- // vector-matrix
- sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulVectorMatrix) vector<T,M> operator*(vector<T,N> x, matrix<T,N,M> y);\n";
-
- // matrix-vector
- sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulMatrixVector) vector<T,N> operator*(matrix<T,N,M> x, vector<T,M> y);\n";
-
- // matrix-matrix
- sb << "__generic<T : __BuiltinArithmeticType, let R : int, let N : int, let C : int> __intrinsic_op(mulMatrixMatrix) matrix<T,R,C> operator*(matrix<T,R,N> x, matrix<T,N,C> y);\n";
-
-
-
- //
-
- // TODO(tfoley): Need to handle `RW*` variants of texture types as well...
- static const struct {
- char const* name;
- TextureType::Shape baseShape;
- int coordCount;
- } kBaseTextureTypes[] = {
- { "1D", TextureType::Shape1D, 1 },
- { "2D", TextureType::Shape2D, 2 },
- { "3D", TextureType::Shape3D, 3 },
- { "Cube", TextureType::ShapeCube, 3 },
- { "Buffer", TextureType::ShapeBuffer, 1 },
- };
- static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]);
-
-
- static const struct {
- char const* name;
- SlangResourceAccess access;
- } kBaseTextureAccessLevels[] = {
- { "", SLANG_RESOURCE_ACCESS_READ },
- { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
- { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
- };
- static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]);
-
- for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
- {
- char const* shapeName = kBaseTextureTypes[tt].name;
- TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape;
-
- for (int isArray = 0; isArray < 2; ++isArray)
- {
- // Arrays of 3D textures aren't allowed
- if (isArray && baseShape == TextureType::Shape3D) continue;
-
- for (int isMultisample = 0; isMultisample < 2; ++isMultisample)
- {
- auto readAccess = SLANG_RESOURCE_ACCESS_READ;
- auto readWriteAccess = SLANG_RESOURCE_ACCESS_READ_WRITE;
-
- // TODO: any constraints to enforce on what gets to be multisampled?
-
-
- unsigned flavor = baseShape;
- if (isArray) flavor |= TextureType::ArrayFlag;
- if (isMultisample) flavor |= TextureType::MultisampleFlag;
-// if (isShadow) flavor |= TextureType::ShadowFlag;
-
-
-
- unsigned readFlavor = flavor | (readAccess << 8);
- unsigned readWriteFlavor = flavor | (readWriteAccess << 8);
-
- StringBuilder nameBuilder;
- nameBuilder << shapeName;
- if (isMultisample) nameBuilder << "MS";
- if (isArray) nameBuilder << "Array";
- auto name = nameBuilder.ProduceString();
-
- sb << "__generic<T> ";
- sb << "__magic_type(TextureSampler," << int(readFlavor) << ") struct ";
- sb << "__sampler" << name;
- sb << " {};\n";
-
- sb << "__generic<T> ";
- sb << "__magic_type(Texture," << int(readFlavor) << ") struct ";
- sb << "__texture" << name;
- sb << " {};\n";
-
- sb << "__generic<T> ";
- sb << "__magic_type(GLSLImageType," << int(readWriteFlavor) << ") struct ";
- sb << "__image" << name;
- sb << " {};\n";
-
- // TODO(tfoley): flesh this out for all the available prefixes
- static const struct
- {
- char const* prefix;
- char const* elementType;
- } kTextureElementTypes[] = {
- { "", "vec4" },
- { "i", "ivec4" },
- { "u", "uvec4" },
- { nullptr, nullptr },
- };
- for( auto ee = kTextureElementTypes; ee->prefix; ++ee )
- {
- sb << "typedef __sampler" << name << "<" << ee->elementType << "> " << ee->prefix << "sampler" << name << ";\n";
- sb << "typedef __texture" << name << "<" << ee->elementType << "> " << ee->prefix << "texture" << name << ";\n";
- sb << "typedef __image" << name << "<" << ee->elementType << "> " << ee->prefix << "image" << name << ";\n";
- }
- }
- }
- }
-
- sb << "__generic<T> __magic_type(GLSLInputParameterBlockType) struct __GLSLInputParameterBlock {};\n";
- sb << "__generic<T> __magic_type(GLSLOutputParameterBlockType) struct __GLSLOutputParameterBlock {};\n";
- sb << "__generic<T> __magic_type(GLSLShaderStorageBufferType) struct __GLSLShaderStorageBuffer {};\n";
-
- sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ") struct sampler {};";
-
- sb << "__magic_type(GLSLInputAttachmentType) struct subpassInput {};";
-
- // Define additional keywords
-
- sb << "syntax buffer : GLSLBufferModifier;\n";
-
- // [GLSL 4.3] Storage Qualifiers
-
- // TODO: need to support `shared` here with its GLSL meaning
-
- sb << "syntax patch : GLSLPatchModifier;\n";
- // `centroid` and `sample` handled centrally
-
- // [GLSL 4.5] Interpolation Qualifiers
- sb << "syntax smooth : SimpleModifier;\n";
- sb << "syntax flat : SimpleModifier;\n";
- sb << "syntax noperspectie : SimpleModifier;\n";
-
-
- // [GLSL 4.3.2] Constant Qualifier
-
- // We need to handle GLSL `const` separately from HLSL `const`,
- // since they mean such different things.
-
- // [GLSL 4.7.2] Precision Qualifiers
- sb << "syntax highp : SimpleModifier;\n";
- sb << "syntax mediump : SimpleModifier;\n";
- sb << "syntax lowp : SimpleModifier;\n";
-
- // [GLSL 4.8.1] The Invariant Qualifier
-
- sb << "syntax invariant : SimpleModifier;\n";
-
- // [GLSL 4.10] Memory Qualifiers
-
- sb << "syntax coherent : SimpleModifier;\n";
- sb << "syntax volatile : SimpleModifier;\n";
- sb << "syntax restrict : SimpleModifier;\n";
- sb << "syntax readonly : GLSLReadOnlyModifier;\n";
- sb << "syntax writeonly : GLSLWriteOnlyModifier;\n";
-
- // We will treat `subroutine` as a qualifier for now
- sb << "syntax subroutine : SimpleModifier;\n";
+ #include "glsl.meta.slang.cpp"
glslLibraryCode = sb.ProduceString();
return glslLibraryCode;
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index bc41ddb71..1f55138e4 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -229,6 +229,65 @@
<Project>{f9be7957-8399-899e-0c49-e714fddd4b65}</Project>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="core.meta.slang">
+ <FileType>Document</FileType>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">slang-generate %(Identity)</Message>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Identity).cpp</Outputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">slang-generate %(Identity)</Message>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Identity).cpp</Outputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">slang-generate %(Identity)</Message>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Identity).cpp</Outputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">slang-generate %(Identity)</Message>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Identity).cpp</Outputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ </CustomBuild>
+ <CustomBuild Include="glsl.meta.slang">
+ <FileType>Document</FileType>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">slang-generate %(Identity)</Message>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">slang-generate %(Identity)</Message>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">slang-generate %(Identity)</Message>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">slang-generate %(Identity)</Message>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Identity).cpp</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Identity).cpp</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Identity).cpp</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Identity).cpp</Outputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ </CustomBuild>
+ <CustomBuild Include="hlsl.meta.slang">
+ <FileType>Document</FileType>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)slang-generate.exe %(Identity)</Command>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">slang-generate %(Identity)</Message>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">slang-generate %(Identity)</Message>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">slang-generate %(Identity)</Message>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">slang-generate %(Identity)</Message>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Identity).cpp</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Identity).cpp</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Identity).cpp</Outputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Identity).cpp</Outputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)slang-generate.exe</AdditionalInputs>
+ </CustomBuild>
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index 4bd7ff9a0..9a85ce966 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -64,4 +64,9 @@
<ClCompile Include="ir.cpp" />
<ClCompile Include="lower-to-ir.cpp" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="core.meta.slang" />
+ <None Include="glsl.meta.slang" />
+ <None Include="hlsl.meta.slang" />
+ </ItemGroup>
</Project> \ No newline at end of file