From 14137cbd2ddd7deebcdf8cc85c30d534bec8e40b Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 7 Sep 2017 14:35:07 -0700 Subject: Initial work on boilerplate code generator The goal here is to get the Slang "standard library" code out of string literals and into something a bit more like an actual code file. This is handled by having a `slang-generate` tool that can translate a "template" file that mixes raw Slang code (or any language we want to generate...) with generation logic that is implemented in C++ (currently). This work isn't final by any stretch of the imagination, but it moves a lot of code and not merging it ASAP will complicate other changes. My expectation is that the generator tool will be beefed up on an as-needed basis, to get our stdlib code working. Similarly, the stdlib code does not really take advantage of the new approach as much as it could. That is something we can clean up along the way as we do modifications of the stdlib. --- source/slang/core.meta.slang | 907 +++++++++++++++ source/slang/core.meta.slang.cpp | 910 +++++++++++++++ source/slang/glsl.meta.slang | 205 ++++ source/slang/glsl.meta.slang.cpp | 206 ++++ source/slang/hlsl.meta.slang | 1065 +++++++++++++++++ source/slang/hlsl.meta.slang.cpp | 1066 +++++++++++++++++ source/slang/slang-stdlib.cpp | 2203 +----------------------------------- source/slang/slang.vcxproj | 59 + source/slang/slang.vcxproj.filters | 5 + 9 files changed, 4429 insertions(+), 2197 deletions(-) create mode 100644 source/slang/core.meta.slang create mode 100644 source/slang/core.meta.slang.cpp create mode 100644 source/slang/glsl.meta.slang create mode 100644 source/slang/glsl.meta.slang.cpp create mode 100644 source/slang/hlsl.meta.slang create mode 100644 source/slang/hlsl.meta.slang.cpp (limited to 'source') 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 __intrinsic_op(Sequence) U operator,(T left, U right); + +__generic __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse); +__generic __intrinsic_op(select) vector operator?:(vector condition, vector ifTrue, vector 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 __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 +__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\n"; +sb << "__intrinsic_type(" << kIROp_ConstantBufferType << ")\n"; +sb << "__magic_type(ConstantBuffer) struct ConstantBuffer {};\n"; + +sb << "__generic\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 __extension vector\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 " << 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 __init(vector);\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 " << kVectorNames[M]; + sb << ", vector "; + 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 __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 __extension matrix\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 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 __init(matrix);\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 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 "; + + 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`. + // + static const struct { + char const* genericPrefix; + char const* elementType; + } kGatherExtensionCases[] = { + { "__generic", "vector" }, + + // 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` 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 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 Gather" << componentName << "(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; + + EMIT_LINE_DIRECTIVE(); + sb << "vector 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 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 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 "; + 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 "; + 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 "; + 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 "; + 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 "; + sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n"; + + sb << "__generic "; + 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 "; + sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n"; + + sb << "__generic "; + 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 __intrinsic_op(Sequence) U operator,(T left, U right);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse);\n"; +sb << "__generic __intrinsic_op(select) vector operator?:(vector condition, vector ifTrue, vector 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 __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\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\n"; +sb << "__intrinsic_type(" << kIROp_ConstantBufferType << ")\n"; +sb << "__magic_type(ConstantBuffer) struct ConstantBuffer {};\n"; + +sb << "__generic\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 __extension vector\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 " << 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 __init(vector);\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 " << kVectorNames[M]; + sb << ", vector "; + 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 __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 __extension matrix\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 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 __init(matrix);\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 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 "; + + 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`. + // + static const struct { + char const* genericPrefix; + char const* elementType; + } kGatherExtensionCases[] = { + { "__generic", "vector" }, + + // 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` 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 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 Gather" << componentName << "(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; + + EMIT_LINE_DIRECTIVE(); + sb << "vector 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 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 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 "; + 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 "; + 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 "; + 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 "; + 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 "; + sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n"; + + sb << "__generic "; + 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 "; + sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n"; + + sb << "__generic "; + 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 __intrinsic_op(mul) vector operator*(vector x, T y);\n"; +sb << "__generic __intrinsic_op(mul) vector operator*(T x, vector y);\n"; + +// scalar-matrix and matrix-scalar +sb << "__generic __intrinsic_op(mul) matrix operator*(matrix x, T y);\n"; +sb << "__generic __intrinsic_op(mul) matrix operator*(T x, matrix y);\n"; + +// vector-vector (dot product) +sb << "__generic __intrinsic_op(dot) T operator*(vector x, vector y);\n"; + +// vector-matrix +sb << "__generic __intrinsic_op(mulVectorMatrix) vector operator*(vector x, matrix y);\n"; + +// matrix-vector +sb << "__generic __intrinsic_op(mulMatrixVector) vector operator*(matrix x, vector y);\n"; + +// matrix-matrix +sb << "__generic __intrinsic_op(mulMatrixMatrix) matrix operator*(matrix x, matrix 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 "; + sb << "__magic_type(TextureSampler," << int(readFlavor) << ") struct "; + sb << "__sampler" << name; + sb << " {};\n"; + + sb << "__generic "; + sb << "__magic_type(Texture," << int(readFlavor) << ") struct "; + sb << "__texture" << name; + sb << " {};\n"; + + sb << "__generic "; + 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 __magic_type(GLSLInputParameterBlockType) struct __GLSLInputParameterBlock {};\n"; +sb << "__generic __magic_type(GLSLOutputParameterBlockType) struct __GLSLOutputParameterBlock {};\n"; +sb << "__generic __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 __intrinsic_op(mul) vector operator*(vector x, T y);\n"; +sb << "__generic __intrinsic_op(mul) vector operator*(T x, vector y);\n"; + +// scalar-matrix and matrix-scalar +sb << "__generic __intrinsic_op(mul) matrix operator*(matrix x, T y);\n"; +sb << "__generic __intrinsic_op(mul) matrix operator*(T x, matrix y);\n"; + +// vector-vector (dot product) +sb << "__generic __intrinsic_op(dot) T operator*(vector x, vector y);\n"; + +// vector-matrix +sb << "__generic __intrinsic_op(mulVectorMatrix) vector operator*(vector x, matrix y);\n"; + +// matrix-vector +sb << "__generic __intrinsic_op(mulMatrixVector) vector operator*(matrix x, vector y);\n"; + +// matrix-matrix +sb << "__generic __intrinsic_op(mulMatrixMatrix) matrix operator*(matrix x, matrix 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 "; + sb << "__magic_type(TextureSampler," << int(readFlavor) << ") struct "; + sb << "__sampler" << name; + sb << " {};\n"; + + sb << "__generic "; + sb << "__magic_type(Texture," << int(readFlavor) << ") struct "; + sb << "__texture" << name; + sb << " {};\n"; + + sb << "__generic "; + 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 __magic_type(GLSLInputParameterBlockType) struct __GLSLInputParameterBlock {};\n"; +sb << "__generic __magic_type(GLSLOutputParameterBlockType) struct __GLSLOutputParameterBlock {};\n"; +sb << "__generic __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 __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 __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 __magic_type(HLSLConsumeStructuredBufferType) struct ConsumeStructuredBuffer +{ + __intrinsic_op T Consume(); + + __intrinsic_op void GetDimensions( + out uint numStructs, + out uint stride); +}; + +__generic __magic_type(HLSLInputPatchType) struct InputPatch +{ + __intrinsic_op __subscript(uint index) -> T; +}; + +__generic __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 __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 __magic_type(HLSLPointStreamType) struct PointStream +{ + void Append(T value); + void RestartStrip(); +}; + +__generic __magic_type(HLSLLineStreamType) struct LineStream +{ + void Append(T value); + void RestartStrip(); +}; + +__generic __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 __intrinsic_op T abs(T x); +__generic __intrinsic_op vector abs(vector x); +__generic __intrinsic_op matrix abs(matrix x); + +// Inverse cosine (HLSL SM 1.0) +__generic __intrinsic_op T acos(T x); +__generic __intrinsic_op vector acos(vector x); +__generic __intrinsic_op matrix acos(matrix x); + +// Test if all components are non-zero (HLSL SM 1.0) +__generic __intrinsic_op T all(T x); +__generic __intrinsic_op vector all(vector x); +__generic __intrinsic_op matrix all(matrix 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 __intrinsic_op T any(T x); +__generic __intrinsic_op vector any(vector x); +__generic __intrinsic_op matrix any(matrix 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 __intrinsic_op vector asfloat(vector< int,N> x); +__generic __intrinsic_op vector asfloat(vector x); +__generic __intrinsic_op matrix asfloat(matrix< int,N,M> x); +__generic __intrinsic_op matrix asfloat(matrix x); + + +// Inverse sine (HLSL SM 1.0) +__generic __intrinsic_op T asin(T x); +__generic __intrinsic_op vector asin(vector x); +__generic __intrinsic_op matrix asin(matrix x); + +// Reinterpret bits as an int (HLSL SM 4.0) +__intrinsic_op int asint(float x); +__intrinsic_op int asint(uint x); +__generic __intrinsic_op vector asint(vector x); +__generic __intrinsic_op vector asint(vector x); +__generic __intrinsic_op matrix asint(matrix x); +__generic __intrinsic_op matrix asint(matrix 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 __intrinsic_op vector asuint(vector x); +__generic __intrinsic_op vector asuint(vector x); +__generic __intrinsic_op matrix asuint(matrix x); +__generic __intrinsic_op matrix asuint(matrix x); + +// Inverse tangent (HLSL SM 1.0) +__generic __intrinsic_op T atan(T x); +__generic __intrinsic_op vector atan(vector x); +__generic __intrinsic_op matrix atan(matrix x); + +__generic +__target_intrinsic(glsl,"atan($0,$1)") +__intrinsic_op +T atan2(T y, T x); + +__generic +__target_intrinsic(glsl,"atan($0,$1)") +__intrinsic_op +vector atan2(vector y, vector x); + +__generic +__target_intrinsic(glsl,"atan($0,$1)") +__intrinsic_op +matrix atan2(matrix y, matrix x); + +// Ceiling (HLSL SM 1.0) +__generic __intrinsic_op T ceil(T x); +__generic __intrinsic_op vector ceil(vector x); +__generic __intrinsic_op matrix ceil(matrix x); + + +// Check access status to tiled resource +__intrinsic_op bool CheckAccessFullyMapped(uint status); + +// Clamp (HLSL SM 1.0) +__generic __intrinsic_op T clamp(T x, T min, T max); +__generic __intrinsic_op vector clamp(vector x, vector min, vector max); +__generic __intrinsic_op matrix clamp(matrix x, matrix min, matrix max); + +// Clip (discard) fragment conditionally +__generic __intrinsic_op void clip(T x); +__generic __intrinsic_op void clip(vector x); +__generic __intrinsic_op void clip(matrix x); + +// Cosine +__generic __intrinsic_op T cos(T x); +__generic __intrinsic_op vector cos(vector x); +__generic __intrinsic_op matrix cos(matrix x); + +// Hyperbolic cosine +__generic __intrinsic_op T cosh(T x); +__generic __intrinsic_op vector cosh(vector x); +__generic __intrinsic_op matrix cosh(matrix x); + +// Population count +__intrinsic_op uint countbits(uint value); + +// Cross product +__generic __intrinsic_op vector cross(vector x, vector y); + +// Convert encoded color +__intrinsic_op int4 D3DCOLORtoUBYTE4(float4 x); + +// Partial-difference derivatives +__generic +__target_intrinsic(glsl, dFdx) +__intrinsic_op +T ddx(T x); +__generic +__target_intrinsic(glsl, dFdx) +__intrinsic_op +vector ddx(vector x); +__generic +__target_intrinsic(glsl, dFdx) +__intrinsic_op +matrix ddx(matrix x); + +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdxCoarse) +__intrinsic_op +T ddx_coarse(T x); +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdxCoarse) +__intrinsic_op +vector ddx_coarse(vector x); +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdxCoarse) +__intrinsic_op +matrix ddx_coarse(matrix x); + +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdxFine) +__intrinsic_op +T ddx_fine(T x); +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdxFine) +__intrinsic_op +vector ddx_fine(vector x); +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdxFine) +__intrinsic_op +matrix ddx_fine(matrix x); + +__generic +__target_intrinsic(glsl, dFdy) +__intrinsic_op +T ddy(T x); +__generic +__target_intrinsic(glsl, dFdy) +__intrinsic_op +vector ddy(vector x); +__generic +__target_intrinsic(glsl, dFdy) +__intrinsic_op + matrix ddy(matrix x); + +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdyCoarse) +__intrinsic_op +T ddy_coarse(T x); +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdyCoarse) +__intrinsic_op +vector ddy_coarse(vector x); +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdyCoarse) +__intrinsic_op +matrix ddy_coarse(matrix x); + +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdyFine) +__intrinsic_op +T ddy_fine(T x); +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdyFine) +__intrinsic_op +vector ddy_fine(vector x); +__generic +__glsl_extension(GL_ARB_derivative_control) +__target_intrinsic(glsl, dFdyFine) +__intrinsic_op +matrix ddy_fine(matrix x); + + +// Radians to degrees +__generic __intrinsic_op T degrees(T x); +__generic __intrinsic_op vector degrees(vector x); +__generic __intrinsic_op matrix degrees(matrix x); + +// Matrix determinant + +__generic __intrinsic_op T determinant(matrix m); + +// Barrier for device memory +__intrinsic_op void DeviceMemoryBarrier(); +__intrinsic_op void DeviceMemoryBarrierWithGroupSync(); + +// Vector distance + +__generic __intrinsic_op T distance(vector x, vector y); + +// Vector dot product + +__generic __intrinsic_op T dot(vector x, vector y); + +// Helper for computing distance terms for lighting (obsolete) + +__generic __intrinsic_op vector dst(vector x, vector y); + +// Error message + +// __intrinsic_op void errorf( string format, ... ); + +// Attribute evaluation + +__generic __intrinsic_op T EvaluateAttributeAtCentroid(T x); +__generic __intrinsic_op vector EvaluateAttributeAtCentroid(vector x); +__generic __intrinsic_op matrix EvaluateAttributeAtCentroid(matrix x); + +__generic __intrinsic_op T EvaluateAttributeAtSample(T x, uint sampleindex); +__generic __intrinsic_op vector EvaluateAttributeAtSample(vector x, uint sampleindex); +__generic __intrinsic_op matrix EvaluateAttributeAtSample(matrix x, uint sampleindex); + +__generic __intrinsic_op T EvaluateAttributeSnapped(T x, int2 offset); +__generic __intrinsic_op vector EvaluateAttributeSnapped(vector x, int2 offset); +__generic __intrinsic_op matrix EvaluateAttributeSnapped(matrix x, int2 offset); + +// Base-e exponent +__generic __intrinsic_op T exp(T x); +__generic __intrinsic_op vector exp(vector x); +__generic __intrinsic_op matrix exp(matrix x); + +// Base-2 exponent +__generic __intrinsic_op T exp2(T x); +__generic __intrinsic_op vector exp2(vector x); +__generic __intrinsic_op matrix exp2(matrix x); + +// Convert 16-bit float stored in low bits of integer +__intrinsic_op float f16tof32(uint value); +__generic __intrinsic_op vector f16tof32(vector value); + +// Convert to 16-bit float stored in low bits of integer +__intrinsic_op uint f32tof16(float value); +__generic __intrinsic_op vector f32tof16(vector value); + +// Flip surface normal to face forward, if needed +__generic __intrinsic_op vector faceforward(vector n, vector i, vector ng); + +// Find first set bit starting at high bit and working down +__intrinsic_op int firstbithigh(int value); +__generic __intrinsic_op vector firstbithigh(vector value); + +__intrinsic_op uint firstbithigh(uint value); +__generic __intrinsic_op vector firstbithigh(vector value); + +// Find first set bit starting at low bit and working up +__intrinsic_op int firstbitlow(int value); +__generic __intrinsic_op vector firstbitlow(vector value); + +__intrinsic_op uint firstbitlow(uint value); +__generic __intrinsic_op vector firstbitlow(vector value); + +// Floor (HLSL SM 1.0) +__generic __intrinsic_op T floor(T x); +__generic __intrinsic_op vector floor(vector x); +__generic __intrinsic_op matrix floor(matrix x); + +// Fused multiply-add for doubles +__intrinsic_op double fma(double a, double b, double c); +__generic __intrinsic_op vector fma(vector a, vector b, vector c); +__generic __intrinsic_op matrix fma(matrix a, matrix b, matrix c); + +// Floating point remainder of x/y +__generic __intrinsic_op T fmod(T x, T y); +__generic __intrinsic_op vector fmod(vector x, vector y); +__generic __intrinsic_op matrix fmod(matrix x, matrix y); + +// Fractional part +__generic +__target_intrinsic(glsl, fract) +__intrinsic_op +T frac(T x); + +__generic +__target_intrinsic(glsl, fract) +__intrinsic_op +vector frac(vector x); + +__generic +__target_intrinsic(glsl, fract) +__intrinsic_op +matrix frac(matrix x); + +// Split float into mantissa and exponent +__generic __intrinsic_op T frexp(T x, out T exp); +__generic __intrinsic_op vector frexp(vector x, out vector exp); +__generic __intrinsic_op matrix frexp(matrix x, out matrix exp); + +// Texture filter width +__generic __intrinsic_op T fwidth(T x); +__generic __intrinsic_op vector fwidth(vector x); +__generic __intrinsic_op matrix fwidth(matrix 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 __intrinsic_op bool isfinite(T x); +__generic __intrinsic_op vector isfinite(vector x); +__generic __intrinsic_op matrix isfinite(matrix x); + +// Is floating-point value infinite? +__generic __intrinsic_op bool isinf(T x); +__generic __intrinsic_op vector isinf(vector x); +__generic __intrinsic_op matrix isinf(matrix x); + +// Is floating-point value not-a-number? +__generic __intrinsic_op bool isnan(T x); +__generic __intrinsic_op vector isnan(vector x); +__generic __intrinsic_op matrix isnan(matrix x); + +// Construct float from mantissa and exponent +__generic __intrinsic_op T ldexp(T x, T exp); +__generic __intrinsic_op vector ldexp(vector x, vector exp); +__generic __intrinsic_op matrix ldexp(matrix x, matrix exp); + +// Vector length +__generic __intrinsic_op T length(vector x); + +// Linear interpolation +__generic +__target_intrinsic(glsl, mix) +__intrinsic_op +T lerp(T x, T y, T s); + +__generic +__target_intrinsic(glsl, mix) +__intrinsic_op +vector lerp(vector x, vector y, vector s); + +__generic +__target_intrinsic(glsl, mix) +__intrinsic_op +matrix lerp(matrix x, matrix y, matrix s); + +// Legacy lighting function (obsolete) +__intrinsic_op float4 lit(float n_dot_l, float n_dot_h, float m); + +// Base-e logarithm +__generic __intrinsic_op T log(T x); +__generic __intrinsic_op vector log(vector x); +__generic __intrinsic_op matrix log(matrix x); + +// Base-10 logarithm +__generic __intrinsic_op T log10(T x); +__generic __intrinsic_op vector log10(vector x); +__generic __intrinsic_op matrix log10(matrix x); + +// Base-2 logarithm +__generic __intrinsic_op T log2(T x); +__generic __intrinsic_op vector log2(vector x); +__generic __intrinsic_op matrix log2(matrix x); + +// multiply-add +__generic __intrinsic_op T mad(T mvalue, T avalue, T bvalue); +__generic __intrinsic_op vector mad(vector mvalue, vector avalue, vector bvalue); +__generic __intrinsic_op matrix mad(matrix mvalue, matrix avalue, matrix bvalue); + +// maximum +__generic __intrinsic_op T max(T x, T y); +__generic __intrinsic_op vector max(vector x, vector y); +__generic __intrinsic_op matrix max(matrix x, matrix y); + +// minimum +__generic __intrinsic_op T min(T x, T y); +__generic __intrinsic_op vector min(vector x, vector y); +__generic __intrinsic_op matrix min(matrix x, matrix y); + +// split into integer and fractional parts (both with same sign) +__generic __intrinsic_op T modf(T x, out T ip); +__generic __intrinsic_op vector modf(vector x, out vector ip); +__generic __intrinsic_op matrix modf(matrix x, out matrix ip); + +// msad4 (whatever that is) +__intrinsic_op uint4 msad4(uint reference, uint2 source, uint4 accum); + +// General inner products + +// scalar-scalar +__generic __intrinsic_op T mul(T x, T y); + +// scalar-vector and vector-scalar +__generic __intrinsic_op vector mul(vector x, T y); +__generic __intrinsic_op vector mul(T x, vector y); + +// scalar-matrix and matrix-scalar +__generic __intrinsic_op matrix mul(matrix x, T y); +__generic __intrinsic_op matrix mul(T x, matrix y); + +// vector-vector (dot product) +__generic __intrinsic_op(dot) T mul(vector x, vector y); + +// vector-matrix +__generic __intrinsic_op(mulVectorMatrix) vector mul(vector x, matrix y); + +// matrix-vector +__generic __intrinsic_op(mulMatrixVector) vector mul(matrix x, vector y); + +// matrix-matrix +__generic __intrinsic_op(mulMatrixMatrix) matrix mul(matrix x, matrix y); + +// noise (deprecated) +__intrinsic_op float noise(float x); +__generic __intrinsic_op float noise(vector x); + +// Normalize a vector +__generic __intrinsic_op vector normalize(vector x); + +// Raise to a power +__generic __intrinsic_op T pow(T x, T y); +__generic __intrinsic_op vector pow(vector x, vector y); +__generic __intrinsic_op matrix pow(matrix x, matrix 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 __intrinsic_op T radians(T x); +__generic __intrinsic_op vector radians(vector x); +__generic __intrinsic_op matrix radians(matrix x); + +// Approximate reciprocal +__generic __intrinsic_op T rcp(T x); +__generic __intrinsic_op vector rcp(vector x); +__generic __intrinsic_op matrix rcp(matrix x); + +// Reflect incident vector across plane with given normal +__generic +__intrinsic_op +vector reflect(vector i, vector n); + +// Refract incident vector given surface normal and index of refraction +__generic +__intrinsic_op +vector refract(vector i, vector n, float eta); + +// Reverse order of bits +__intrinsic_op uint reversebits(uint value); +__generic vector reversebits(vector value); + +// Round-to-nearest +__generic __intrinsic_op T round(T x); +__generic __intrinsic_op vector round(vector x); +__generic __intrinsic_op matrix round(matrix x); + +// Reciprocal of square root +__generic __intrinsic_op T rsqrt(T x); +__generic __intrinsic_op vector rsqrt(vector x); +__generic __intrinsic_op matrix rsqrt(matrix x); + +// Clamp value to [0,1] range +__generic +__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op +T saturate(T x); + +__generic +__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op +vector saturate(vector x); + +__generic +__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op +matrix saturate(matrix x); + + +// Extract sign of value +__generic __intrinsic_op int sign(T x); +__generic __intrinsic_op vector sign(vector x); +__generic __intrinsic_op matrix sign(matrix x); + + +// Sine +__generic __intrinsic_op T sin(T x); +__generic __intrinsic_op vector sin(vector x); +__generic __intrinsic_op matrix sin(matrix x); + +// Sine and cosine +__generic __intrinsic_op void sincos(T x, out T s, out T c); +__generic __intrinsic_op void sincos(vector x, out vector s, out vector c); +__generic __intrinsic_op void sincos(matrix x, out matrix s, out matrix c); + +// Hyperbolic Sine +__generic __intrinsic_op T sinh(T x); +__generic __intrinsic_op vector sinh(vector x); +__generic __intrinsic_op matrix sinh(matrix x); + +// Smooth step (Hermite interpolation) +__generic __intrinsic_op T smoothstep(T min, T max, T x); +__generic __intrinsic_op vector smoothstep(vector min, vector max, vector x); +__generic __intrinsic_op matrix smoothstep(matrix min, matrix max, matrix x); + +// Square root +__generic __intrinsic_op T sqrt(T x); +__generic __intrinsic_op vector sqrt(vector x); +__generic __intrinsic_op matrix sqrt(matrix x); + +// Step function +__generic __intrinsic_op T step(T y, T x); +__generic __intrinsic_op vector step(vector y, vector x); +__generic __intrinsic_op matrix step(matrix y, matrix x); + +// Tangent +__generic __intrinsic_op T tan(T x); +__generic __intrinsic_op vector tan(vector x); +__generic __intrinsic_op matrix tan(matrix x); + +// Hyperbolic tangent +__generic __intrinsic_op T tanh(T x); +__generic __intrinsic_op vector tanh(vector x); +__generic __intrinsic_op matrix tanh(matrix 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 __intrinsic_op matrix transpose(matrix x); + +// Truncate to integer +__generic __intrinsic_op T trunc(T x); +__generic __intrinsic_op vector trunc(vector x); +__generic __intrinsic_op matrix trunc(matrix x); + +// Shader model 6.0 stuff + +__intrinsic_op uint GlobalOrderedCountIncrement(uint countToAppendForThisLane); + +__generic __intrinsic_op T QuadReadLaneAt(T sourceValue, int quadLaneID); +__generic __intrinsic_op vector QuadReadLaneAt(vector sourceValue, int quadLaneID); +__generic __intrinsic_op matrix QuadReadLaneAt(matrix sourceValue, int quadLaneID); + +__generic __intrinsic_op T QuadSwapX(T localValue); +__generic __intrinsic_op vector QuadSwapX(vector localValue); +__generic __intrinsic_op matrix QuadSwapX(matrix localValue); + +__generic __intrinsic_op T QuadSwapY(T localValue); +__generic __intrinsic_op vector QuadSwapY(vector localValue); +__generic __intrinsic_op matrix QuadSwapY(matrix localValue); + +__generic __intrinsic_op T WaveAllBitAnd(T expr); +__generic __intrinsic_op vector WaveAllBitAnd(vector expr); +__generic __intrinsic_op matrix WaveAllBitAnd(matrix expr); + +__generic __intrinsic_op T WaveAllBitOr(T expr); +__generic __intrinsic_op vector WaveAllBitOr(vector expr); +__generic __intrinsic_op matrix WaveAllBitOr(matrix expr); + +__generic __intrinsic_op T WaveAllBitXor(T expr); +__generic __intrinsic_op vector WaveAllBitXor(vector expr); +__generic __intrinsic_op matrix WaveAllBitXor(matrix expr); + +__generic __intrinsic_op T WaveAllMax(T expr); +__generic __intrinsic_op vector WaveAllMax(vector expr); +__generic __intrinsic_op matrix WaveAllMax(matrix expr); + +__generic __intrinsic_op T WaveAllMin(T expr); +__generic __intrinsic_op vector WaveAllMin(vector expr); +__generic __intrinsic_op matrix WaveAllMin(matrix expr); + +__generic __intrinsic_op T WaveAllProduct(T expr); +__generic __intrinsic_op vector WaveAllProduct(vector expr); +__generic __intrinsic_op matrix WaveAllProduct(matrix expr); + +__generic __intrinsic_op T WaveAllSum(T expr); +__generic __intrinsic_op vector WaveAllSum(vector expr); +__generic __intrinsic_op matrix WaveAllSum(matrix 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 __intrinsic_op T WavePrefixProduct(T expr); +__generic __intrinsic_op vector WavePrefixProduct(vector expr); +__generic __intrinsic_op matrix WavePrefixProduct(matrix expr); + +__generic __intrinsic_op T WavePrefixSum(T expr); +__generic __intrinsic_op vector WavePrefixSum(vector expr); +__generic __intrinsic_op matrix WavePrefixSum(matrix expr); + +__generic __intrinsic_op T WaveReadFirstLane(T expr); +__generic __intrinsic_op vector WaveReadFirstLane(vector expr); +__generic __intrinsic_op matrix WaveReadFirstLane(matrix expr); + +__generic __intrinsic_op T WaveReadLaneAt(T expr, int laneIndex); +__generic __intrinsic_op vector WaveReadLaneAt(vector expr, int laneIndex); +__generic __intrinsic_op matrix WaveReadLaneAt(matrix 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 "; + 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 __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 __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 __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 __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 __magic_type(HLSLInputPatchType) struct InputPatch\n"; +sb << "{\n"; +sb << " __intrinsic_op __subscript(uint index) -> T;\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic __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 __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 __magic_type(HLSLPointStreamType) struct PointStream\n"; +sb << "{\n"; +sb << " void Append(T value);\n"; +sb << " void RestartStrip();\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic __magic_type(HLSLLineStreamType) struct LineStream\n"; +sb << "{\n"; +sb << " void Append(T value);\n"; +sb << " void RestartStrip();\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic __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 __intrinsic_op T abs(T x);\n"; +sb << "__generic __intrinsic_op vector abs(vector x);\n"; +sb << "__generic __intrinsic_op matrix abs(matrix x);\n"; +sb << "\n"; +sb << "// Inverse cosine (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T acos(T x);\n"; +sb << "__generic __intrinsic_op vector acos(vector x);\n"; +sb << "__generic __intrinsic_op matrix acos(matrix x);\n"; +sb << "\n"; +sb << "// Test if all components are non-zero (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T all(T x);\n"; +sb << "__generic __intrinsic_op vector all(vector x);\n"; +sb << "__generic __intrinsic_op matrix all(matrix 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 __intrinsic_op T any(T x);\n"; +sb << "__generic __intrinsic_op vector any(vector x);\n"; +sb << "__generic __intrinsic_op matrix any(matrix 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 __intrinsic_op vector asfloat(vector< int,N> x);\n"; +sb << "__generic __intrinsic_op vector asfloat(vector x);\n"; +sb << "__generic __intrinsic_op matrix asfloat(matrix< int,N,M> x);\n"; +sb << "__generic __intrinsic_op matrix asfloat(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Inverse sine (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T asin(T x);\n"; +sb << "__generic __intrinsic_op vector asin(vector x);\n"; +sb << "__generic __intrinsic_op matrix asin(matrix 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 __intrinsic_op vector asint(vector x);\n"; +sb << "__generic __intrinsic_op vector asint(vector x);\n"; +sb << "__generic __intrinsic_op matrix asint(matrix x);\n"; +sb << "__generic __intrinsic_op matrix asint(matrix 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 __intrinsic_op vector asuint(vector x);\n"; +sb << "__generic __intrinsic_op vector asuint(vector x);\n"; +sb << "__generic __intrinsic_op matrix asuint(matrix x);\n"; +sb << "__generic __intrinsic_op matrix asuint(matrix x);\n"; +sb << "\n"; +sb << "// Inverse tangent (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T atan(T x);\n"; +sb << "__generic __intrinsic_op vector atan(vector x);\n"; +sb << "__generic __intrinsic_op matrix atan(matrix x);\n"; +sb << "\n"; +sb << "__generic\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\n"; +sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n"; +sb << "__intrinsic_op\n"; +sb << "vector atan2(vector y, vector x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n"; +sb << "__intrinsic_op\n"; +sb << "matrix atan2(matrix y, matrix x);\n"; +sb << "\n"; +sb << "// Ceiling (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T ceil(T x);\n"; +sb << "__generic __intrinsic_op vector ceil(vector x);\n"; +sb << "__generic __intrinsic_op matrix ceil(matrix 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 __intrinsic_op T clamp(T x, T min, T max);\n"; +sb << "__generic __intrinsic_op vector clamp(vector x, vector min, vector max);\n"; +sb << "__generic __intrinsic_op matrix clamp(matrix x, matrix min, matrix max);\n"; +sb << "\n"; +sb << "// Clip (discard) fragment conditionally\n"; +sb << "__generic __intrinsic_op void clip(T x);\n"; +sb << "__generic __intrinsic_op void clip(vector x);\n"; +sb << "__generic __intrinsic_op void clip(matrix x);\n"; +sb << "\n"; +sb << "// Cosine\n"; +sb << "__generic __intrinsic_op T cos(T x);\n"; +sb << "__generic __intrinsic_op vector cos(vector x);\n"; +sb << "__generic __intrinsic_op matrix cos(matrix x);\n"; +sb << "\n"; +sb << "// Hyperbolic cosine\n"; +sb << "__generic __intrinsic_op T cosh(T x);\n"; +sb << "__generic __intrinsic_op vector cosh(vector x);\n"; +sb << "__generic __intrinsic_op matrix cosh(matrix x);\n"; +sb << "\n"; +sb << "// Population count\n"; +sb << "__intrinsic_op uint countbits(uint value);\n"; +sb << "\n"; +sb << "// Cross product\n"; +sb << "__generic __intrinsic_op vector cross(vector x, vector 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\n"; +sb << "__target_intrinsic(glsl, dFdx)\n"; +sb << "__intrinsic_op\n"; +sb << "T ddx(T x);\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdx)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddx(vector x);\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdx)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddx(matrix x);\n"; +sb << "\n"; +sb << "__generic\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\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddx_coarse(vector x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddx_coarse(matrix x);\n"; +sb << "\n"; +sb << "__generic\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\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxFine)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddx_fine(vector x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxFine)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddx_fine(matrix x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdy)\n"; +sb << "__intrinsic_op\n"; +sb << "T ddy(T x);\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdy)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddy(vector x);\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdy)\n"; +sb << "__intrinsic_op\n"; +sb << " matrix ddy(matrix x);\n"; +sb << "\n"; +sb << "__generic\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\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddy_coarse(vector x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddy_coarse(matrix x);\n"; +sb << "\n"; +sb << "__generic\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\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyFine)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddy_fine(vector x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyFine)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddy_fine(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Radians to degrees\n"; +sb << "__generic __intrinsic_op T degrees(T x);\n"; +sb << "__generic __intrinsic_op vector degrees(vector x);\n"; +sb << "__generic __intrinsic_op matrix degrees(matrix x);\n"; +sb << "\n"; +sb << "// Matrix determinant\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T determinant(matrix 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 __intrinsic_op T distance(vector x, vector y);\n"; +sb << "\n"; +sb << "// Vector dot product\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T dot(vector x, vector y);\n"; +sb << "\n"; +sb << "// Helper for computing distance terms for lighting (obsolete)\n"; +sb << "\n"; +sb << "__generic __intrinsic_op vector dst(vector x, vector 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 __intrinsic_op T EvaluateAttributeAtCentroid(T x);\n"; +sb << "__generic __intrinsic_op vector EvaluateAttributeAtCentroid(vector x);\n"; +sb << "__generic __intrinsic_op matrix EvaluateAttributeAtCentroid(matrix x);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T EvaluateAttributeAtSample(T x, uint sampleindex);\n"; +sb << "__generic __intrinsic_op vector EvaluateAttributeAtSample(vector x, uint sampleindex);\n"; +sb << "__generic __intrinsic_op matrix EvaluateAttributeAtSample(matrix x, uint sampleindex);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T EvaluateAttributeSnapped(T x, int2 offset);\n"; +sb << "__generic __intrinsic_op vector EvaluateAttributeSnapped(vector x, int2 offset);\n"; +sb << "__generic __intrinsic_op matrix EvaluateAttributeSnapped(matrix x, int2 offset);\n"; +sb << "\n"; +sb << "// Base-e exponent\n"; +sb << "__generic __intrinsic_op T exp(T x);\n"; +sb << "__generic __intrinsic_op vector exp(vector x);\n"; +sb << "__generic __intrinsic_op matrix exp(matrix x);\n"; +sb << "\n"; +sb << "// Base-2 exponent\n"; +sb << "__generic __intrinsic_op T exp2(T x);\n"; +sb << "__generic __intrinsic_op vector exp2(vector x);\n"; +sb << "__generic __intrinsic_op matrix exp2(matrix 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 __intrinsic_op vector f16tof32(vector 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 __intrinsic_op vector f32tof16(vector value);\n"; +sb << "\n"; +sb << "// Flip surface normal to face forward, if needed\n"; +sb << "__generic __intrinsic_op vector faceforward(vector n, vector i, vector 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 __intrinsic_op vector firstbithigh(vector value);\n"; +sb << "\n"; +sb << "__intrinsic_op uint firstbithigh(uint value);\n"; +sb << "__generic __intrinsic_op vector firstbithigh(vector 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 __intrinsic_op vector firstbitlow(vector value);\n"; +sb << "\n"; +sb << "__intrinsic_op uint firstbitlow(uint value);\n"; +sb << "__generic __intrinsic_op vector firstbitlow(vector value);\n"; +sb << "\n"; +sb << "// Floor (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T floor(T x);\n"; +sb << "__generic __intrinsic_op vector floor(vector x);\n"; +sb << "__generic __intrinsic_op matrix floor(matrix 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 __intrinsic_op vector fma(vector a, vector b, vector c);\n"; +sb << "__generic __intrinsic_op matrix fma(matrix a, matrix b, matrix c);\n"; +sb << "\n"; +sb << "// Floating point remainder of x/y\n"; +sb << "__generic __intrinsic_op T fmod(T x, T y);\n"; +sb << "__generic __intrinsic_op vector fmod(vector x, vector y);\n"; +sb << "__generic __intrinsic_op matrix fmod(matrix x, matrix y);\n"; +sb << "\n"; +sb << "// Fractional part\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, fract)\n"; +sb << "__intrinsic_op\n"; +sb << "T frac(T x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, fract)\n"; +sb << "__intrinsic_op\n"; +sb << "vector frac(vector x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, fract)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix frac(matrix x);\n"; +sb << "\n"; +sb << "// Split float into mantissa and exponent\n"; +sb << "__generic __intrinsic_op T frexp(T x, out T exp);\n"; +sb << "__generic __intrinsic_op vector frexp(vector x, out vector exp);\n"; +sb << "__generic __intrinsic_op matrix frexp(matrix x, out matrix exp);\n"; +sb << "\n"; +sb << "// Texture filter width\n"; +sb << "__generic __intrinsic_op T fwidth(T x);\n"; +sb << "__generic __intrinsic_op vector fwidth(vector x);\n"; +sb << "__generic __intrinsic_op matrix fwidth(matrix 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 __intrinsic_op bool isfinite(T x);\n"; +sb << "__generic __intrinsic_op vector isfinite(vector x);\n"; +sb << "__generic __intrinsic_op matrix isfinite(matrix x);\n"; +sb << "\n"; +sb << "// Is floating-point value infinite?\n"; +sb << "__generic __intrinsic_op bool isinf(T x);\n"; +sb << "__generic __intrinsic_op vector isinf(vector x);\n"; +sb << "__generic __intrinsic_op matrix isinf(matrix x);\n"; +sb << "\n"; +sb << "// Is floating-point value not-a-number?\n"; +sb << "__generic __intrinsic_op bool isnan(T x);\n"; +sb << "__generic __intrinsic_op vector isnan(vector x);\n"; +sb << "__generic __intrinsic_op matrix isnan(matrix x);\n"; +sb << "\n"; +sb << "// Construct float from mantissa and exponent\n"; +sb << "__generic __intrinsic_op T ldexp(T x, T exp);\n"; +sb << "__generic __intrinsic_op vector ldexp(vector x, vector exp);\n"; +sb << "__generic __intrinsic_op matrix ldexp(matrix x, matrix exp);\n"; +sb << "\n"; +sb << "// Vector length\n"; +sb << "__generic __intrinsic_op T length(vector x);\n"; +sb << "\n"; +sb << "// Linear interpolation\n"; +sb << "__generic\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\n"; +sb << "__target_intrinsic(glsl, mix)\n"; +sb << "__intrinsic_op\n"; +sb << "vector lerp(vector x, vector y, vector s);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, mix)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix lerp(matrix x, matrix y, matrix 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 __intrinsic_op T log(T x);\n"; +sb << "__generic __intrinsic_op vector log(vector x);\n"; +sb << "__generic __intrinsic_op matrix log(matrix x);\n"; +sb << "\n"; +sb << "// Base-10 logarithm\n"; +sb << "__generic __intrinsic_op T log10(T x);\n"; +sb << "__generic __intrinsic_op vector log10(vector x);\n"; +sb << "__generic __intrinsic_op matrix log10(matrix x);\n"; +sb << "\n"; +sb << "// Base-2 logarithm\n"; +sb << "__generic __intrinsic_op T log2(T x);\n"; +sb << "__generic __intrinsic_op vector log2(vector x);\n"; +sb << "__generic __intrinsic_op matrix log2(matrix x);\n"; +sb << "\n"; +sb << "// multiply-add\n"; +sb << "__generic __intrinsic_op T mad(T mvalue, T avalue, T bvalue);\n"; +sb << "__generic __intrinsic_op vector mad(vector mvalue, vector avalue, vector bvalue);\n"; +sb << "__generic __intrinsic_op matrix mad(matrix mvalue, matrix avalue, matrix bvalue);\n"; +sb << "\n"; +sb << "// maximum\n"; +sb << "__generic __intrinsic_op T max(T x, T y);\n"; +sb << "__generic __intrinsic_op vector max(vector x, vector y);\n"; +sb << "__generic __intrinsic_op matrix max(matrix x, matrix y);\n"; +sb << "\n"; +sb << "// minimum\n"; +sb << "__generic __intrinsic_op T min(T x, T y);\n"; +sb << "__generic __intrinsic_op vector min(vector x, vector y);\n"; +sb << "__generic __intrinsic_op matrix min(matrix x, matrix y);\n"; +sb << "\n"; +sb << "// split into integer and fractional parts (both with same sign)\n"; +sb << "__generic __intrinsic_op T modf(T x, out T ip);\n"; +sb << "__generic __intrinsic_op vector modf(vector x, out vector ip);\n"; +sb << "__generic __intrinsic_op matrix modf(matrix x, out matrix 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 __intrinsic_op T mul(T x, T y);\n"; +sb << "\n"; +sb << "// scalar-vector and vector-scalar\n"; +sb << "__generic __intrinsic_op vector mul(vector x, T y);\n"; +sb << "__generic __intrinsic_op vector mul(T x, vector y);\n"; +sb << "\n"; +sb << "// scalar-matrix and matrix-scalar\n"; +sb << "__generic __intrinsic_op matrix mul(matrix x, T y);\n"; +sb << "__generic __intrinsic_op matrix mul(T x, matrix y);\n"; +sb << "\n"; +sb << "// vector-vector (dot product)\n"; +sb << "__generic __intrinsic_op(dot) T mul(vector x, vector y);\n"; +sb << "\n"; +sb << "// vector-matrix\n"; +sb << "__generic __intrinsic_op(mulVectorMatrix) vector mul(vector x, matrix y);\n"; +sb << "\n"; +sb << "// matrix-vector\n"; +sb << "__generic __intrinsic_op(mulMatrixVector) vector mul(matrix x, vector y);\n"; +sb << "\n"; +sb << "// matrix-matrix\n"; +sb << "__generic __intrinsic_op(mulMatrixMatrix) matrix mul(matrix x, matrix y);\n"; +sb << "\n"; +sb << "// noise (deprecated)\n"; +sb << "__intrinsic_op float noise(float x);\n"; +sb << "__generic __intrinsic_op float noise(vector x);\n"; +sb << "\n"; +sb << "// Normalize a vector\n"; +sb << "__generic __intrinsic_op vector normalize(vector x);\n"; +sb << "\n"; +sb << "// Raise to a power\n"; +sb << "__generic __intrinsic_op T pow(T x, T y);\n"; +sb << "__generic __intrinsic_op vector pow(vector x, vector y);\n"; +sb << "__generic __intrinsic_op matrix pow(matrix x, matrix 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 __intrinsic_op T radians(T x);\n"; +sb << "__generic __intrinsic_op vector radians(vector x);\n"; +sb << "__generic __intrinsic_op matrix radians(matrix x);\n"; +sb << "\n"; +sb << "// Approximate reciprocal\n"; +sb << "__generic __intrinsic_op T rcp(T x);\n"; +sb << "__generic __intrinsic_op vector rcp(vector x);\n"; +sb << "__generic __intrinsic_op matrix rcp(matrix x);\n"; +sb << "\n"; +sb << "// Reflect incident vector across plane with given normal\n"; +sb << "__generic\n"; +sb << "__intrinsic_op\n"; +sb << "vector reflect(vector i, vector n);\n"; +sb << "\n"; +sb << "// Refract incident vector given surface normal and index of refraction\n"; +sb << "__generic\n"; +sb << "__intrinsic_op\n"; +sb << "vector refract(vector i, vector n, float eta);\n"; +sb << "\n"; +sb << "// Reverse order of bits\n"; +sb << "__intrinsic_op uint reversebits(uint value);\n"; +sb << "__generic vector reversebits(vector value);\n"; +sb << "\n"; +sb << "// Round-to-nearest\n"; +sb << "__generic __intrinsic_op T round(T x);\n"; +sb << "__generic __intrinsic_op vector round(vector x);\n"; +sb << "__generic __intrinsic_op matrix round(matrix x);\n"; +sb << "\n"; +sb << "// Reciprocal of square root\n"; +sb << "__generic __intrinsic_op T rsqrt(T x);\n"; +sb << "__generic __intrinsic_op vector rsqrt(vector x);\n"; +sb << "__generic __intrinsic_op matrix rsqrt(matrix x);\n"; +sb << "\n"; +sb << "// Clamp value to [0,1] range\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n"; +sb << "T saturate(T x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n"; +sb << "vector saturate(vector x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n"; +sb << "matrix saturate(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Extract sign of value\n"; +sb << "__generic __intrinsic_op int sign(T x);\n"; +sb << "__generic __intrinsic_op vector sign(vector x);\n"; +sb << "__generic __intrinsic_op matrix sign(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Sine\n"; +sb << "__generic __intrinsic_op T sin(T x);\n"; +sb << "__generic __intrinsic_op vector sin(vector x);\n"; +sb << "__generic __intrinsic_op matrix sin(matrix x);\n"; +sb << "\n"; +sb << "// Sine and cosine\n"; +sb << "__generic __intrinsic_op void sincos(T x, out T s, out T c);\n"; +sb << "__generic __intrinsic_op void sincos(vector x, out vector s, out vector c);\n"; +sb << "__generic __intrinsic_op void sincos(matrix x, out matrix s, out matrix c);\n"; +sb << "\n"; +sb << "// Hyperbolic Sine\n"; +sb << "__generic __intrinsic_op T sinh(T x);\n"; +sb << "__generic __intrinsic_op vector sinh(vector x);\n"; +sb << "__generic __intrinsic_op matrix sinh(matrix x);\n"; +sb << "\n"; +sb << "// Smooth step (Hermite interpolation)\n"; +sb << "__generic __intrinsic_op T smoothstep(T min, T max, T x);\n"; +sb << "__generic __intrinsic_op vector smoothstep(vector min, vector max, vector x);\n"; +sb << "__generic __intrinsic_op matrix smoothstep(matrix min, matrix max, matrix x);\n"; +sb << "\n"; +sb << "// Square root\n"; +sb << "__generic __intrinsic_op T sqrt(T x);\n"; +sb << "__generic __intrinsic_op vector sqrt(vector x);\n"; +sb << "__generic __intrinsic_op matrix sqrt(matrix x);\n"; +sb << "\n"; +sb << "// Step function\n"; +sb << "__generic __intrinsic_op T step(T y, T x);\n"; +sb << "__generic __intrinsic_op vector step(vector y, vector x);\n"; +sb << "__generic __intrinsic_op matrix step(matrix y, matrix x);\n"; +sb << "\n"; +sb << "// Tangent\n"; +sb << "__generic __intrinsic_op T tan(T x);\n"; +sb << "__generic __intrinsic_op vector tan(vector x);\n"; +sb << "__generic __intrinsic_op matrix tan(matrix x);\n"; +sb << "\n"; +sb << "// Hyperbolic tangent\n"; +sb << "__generic __intrinsic_op T tanh(T x);\n"; +sb << "__generic __intrinsic_op vector tanh(vector x);\n"; +sb << "__generic __intrinsic_op matrix tanh(matrix 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 __intrinsic_op matrix transpose(matrix x);\n"; +sb << "\n"; +sb << "// Truncate to integer\n"; +sb << "__generic __intrinsic_op T trunc(T x);\n"; +sb << "__generic __intrinsic_op vector trunc(vector x);\n"; +sb << "__generic __intrinsic_op matrix trunc(matrix 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 __intrinsic_op T QuadReadLaneAt(T sourceValue, int quadLaneID);\n"; +sb << "__generic __intrinsic_op vector QuadReadLaneAt(vector sourceValue, int quadLaneID);\n"; +sb << "__generic __intrinsic_op matrix QuadReadLaneAt(matrix sourceValue, int quadLaneID);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T QuadSwapX(T localValue);\n"; +sb << "__generic __intrinsic_op vector QuadSwapX(vector localValue);\n"; +sb << "__generic __intrinsic_op matrix QuadSwapX(matrix localValue);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T QuadSwapY(T localValue);\n"; +sb << "__generic __intrinsic_op vector QuadSwapY(vector localValue);\n"; +sb << "__generic __intrinsic_op matrix QuadSwapY(matrix localValue);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllBitAnd(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllBitAnd(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllBitAnd(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllBitOr(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllBitOr(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllBitOr(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllBitXor(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllBitXor(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllBitXor(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllMax(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllMax(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllMax(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllMin(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllMin(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllMin(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllProduct(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllProduct(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllProduct(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllSum(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllSum(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllSum(matrix 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 __intrinsic_op T WavePrefixProduct(T expr);\n"; +sb << "__generic __intrinsic_op vector WavePrefixProduct(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WavePrefixProduct(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WavePrefixSum(T expr);\n"; +sb << "__generic __intrinsic_op vector WavePrefixSum(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WavePrefixSum(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveReadFirstLane(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveReadFirstLane(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveReadFirstLane(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveReadLaneAt(T expr, int laneIndex);\n"; +sb << "__generic __intrinsic_op vector WaveReadLaneAt(vector expr, int laneIndex);\n"; +sb << "__generic __intrinsic_op matrix WaveReadLaneAt(matrix 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 "; + 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 __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 __intrinsic_op(Sequence) U operator,(T left, U right); - -__generic __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse); -__generic __intrinsic_op(select) vector operator?:(vector condition, vector ifTrue, vector ifFalse); - -)=" }; - - -enum { kHLSLLibIncludeStringLine = __LINE__+1 }; -const char * kHLSLLibIncludeStringChunks[] = { R"=( - -typedef uint UINT; - -__generic __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 __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 __magic_type(HLSLConsumeStructuredBufferType) struct ConsumeStructuredBuffer -{ - __intrinsic_op T Consume(); - - __intrinsic_op void GetDimensions( - out uint numStructs, - out uint stride); -}; - -__generic __magic_type(HLSLInputPatchType) struct InputPatch -{ - __intrinsic_op __subscript(uint index) -> T; -}; - -__generic __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 __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 __magic_type(HLSLPointStreamType) struct PointStream -{ - void Append(T value); - void RestartStrip(); -}; - -__generic __magic_type(HLSLLineStreamType) struct LineStream -{ - void Append(T value); - void RestartStrip(); -}; - -__generic __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 __intrinsic_op T abs(T x); -__generic __intrinsic_op vector abs(vector x); -__generic __intrinsic_op matrix abs(matrix x); - -// Inverse cosine (HLSL SM 1.0) -__generic __intrinsic_op T acos(T x); -__generic __intrinsic_op vector acos(vector x); -__generic __intrinsic_op matrix acos(matrix x); - -// Test if all components are non-zero (HLSL SM 1.0) -__generic __intrinsic_op T all(T x); -__generic __intrinsic_op vector all(vector x); -__generic __intrinsic_op matrix all(matrix 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 __intrinsic_op T any(T x); -__generic __intrinsic_op vector any(vector x); -__generic __intrinsic_op matrix any(matrix 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 __intrinsic_op vector asfloat(vector< int,N> x); -__generic __intrinsic_op vector asfloat(vector x); -__generic __intrinsic_op matrix asfloat(matrix< int,N,M> x); -__generic __intrinsic_op matrix asfloat(matrix x); - - -// Inverse sine (HLSL SM 1.0) -__generic __intrinsic_op T asin(T x); -__generic __intrinsic_op vector asin(vector x); -__generic __intrinsic_op matrix asin(matrix x); - -// Reinterpret bits as an int (HLSL SM 4.0) -__intrinsic_op int asint(float x); -__intrinsic_op int asint(uint x); -__generic __intrinsic_op vector asint(vector x); -__generic __intrinsic_op vector asint(vector x); -__generic __intrinsic_op matrix asint(matrix x); -__generic __intrinsic_op matrix asint(matrix 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 __intrinsic_op vector asuint(vector x); -__generic __intrinsic_op vector asuint(vector x); -__generic __intrinsic_op matrix asuint(matrix x); -__generic __intrinsic_op matrix asuint(matrix x); - -// Inverse tangent (HLSL SM 1.0) -__generic __intrinsic_op T atan(T x); -__generic __intrinsic_op vector atan(vector x); -__generic __intrinsic_op matrix atan(matrix x); - -__generic -__target_intrinsic(glsl,"atan($0,$1)") -__intrinsic_op -T atan2(T y, T x); - -__generic -__target_intrinsic(glsl,"atan($0,$1)") -__intrinsic_op -vector atan2(vector y, vector x); - -__generic -__target_intrinsic(glsl,"atan($0,$1)") -__intrinsic_op -matrix atan2(matrix y, matrix x); - -// Ceiling (HLSL SM 1.0) -__generic __intrinsic_op T ceil(T x); -__generic __intrinsic_op vector ceil(vector x); -__generic __intrinsic_op matrix ceil(matrix x); - - -// Check access status to tiled resource -__intrinsic_op bool CheckAccessFullyMapped(uint status); - -// Clamp (HLSL SM 1.0) -__generic __intrinsic_op T clamp(T x, T min, T max); -__generic __intrinsic_op vector clamp(vector x, vector min, vector max); -__generic __intrinsic_op matrix clamp(matrix x, matrix min, matrix max); - -// Clip (discard) fragment conditionally -__generic __intrinsic_op void clip(T x); -__generic __intrinsic_op void clip(vector x); -__generic __intrinsic_op void clip(matrix x); - -// Cosine -__generic __intrinsic_op T cos(T x); -__generic __intrinsic_op vector cos(vector x); -__generic __intrinsic_op matrix cos(matrix x); - -// Hyperbolic cosine -__generic __intrinsic_op T cosh(T x); -__generic __intrinsic_op vector cosh(vector x); -__generic __intrinsic_op matrix cosh(matrix x); - -// Population count -__intrinsic_op uint countbits(uint value); - -// Cross product -__generic __intrinsic_op vector cross(vector x, vector y); - -// Convert encoded color -__intrinsic_op int4 D3DCOLORtoUBYTE4(float4 x); - -// Partial-difference derivatives -__generic -__target_intrinsic(glsl, dFdx) -__intrinsic_op -T ddx(T x); -__generic -__target_intrinsic(glsl, dFdx) -__intrinsic_op -vector ddx(vector x); -__generic -__target_intrinsic(glsl, dFdx) -__intrinsic_op -matrix ddx(matrix x); - -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdxCoarse) -__intrinsic_op -T ddx_coarse(T x); -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdxCoarse) -__intrinsic_op -vector ddx_coarse(vector x); -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdxCoarse) -__intrinsic_op -matrix ddx_coarse(matrix x); - -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdxFine) -__intrinsic_op -T ddx_fine(T x); -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdxFine) -__intrinsic_op -vector ddx_fine(vector x); -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdxFine) -__intrinsic_op -matrix ddx_fine(matrix x); - -__generic -__target_intrinsic(glsl, dFdy) -__intrinsic_op -T ddy(T x); -__generic -__target_intrinsic(glsl, dFdy) -__intrinsic_op -vector ddy(vector x); -__generic -__target_intrinsic(glsl, dFdy) -__intrinsic_op - matrix ddy(matrix x); - -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdyCoarse) -__intrinsic_op -T ddy_coarse(T x); -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdyCoarse) -__intrinsic_op -vector ddy_coarse(vector x); -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdyCoarse) -__intrinsic_op -matrix ddy_coarse(matrix x); - -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdyFine) -__intrinsic_op -T ddy_fine(T x); -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdyFine) -__intrinsic_op -vector ddy_fine(vector x); -__generic -__glsl_extension(GL_ARB_derivative_control) -__target_intrinsic(glsl, dFdyFine) -__intrinsic_op -matrix ddy_fine(matrix x); - - -// Radians to degrees -__generic __intrinsic_op T degrees(T x); -__generic __intrinsic_op vector degrees(vector x); -__generic __intrinsic_op matrix degrees(matrix x); - -// Matrix determinant - -__generic __intrinsic_op T determinant(matrix m); - -// Barrier for device memory -__intrinsic_op void DeviceMemoryBarrier(); -__intrinsic_op void DeviceMemoryBarrierWithGroupSync(); - -// Vector distance - -__generic __intrinsic_op T distance(vector x, vector y); - -// Vector dot product - -__generic __intrinsic_op T dot(vector x, vector y); - -// Helper for computing distance terms for lighting (obsolete) - -__generic __intrinsic_op vector dst(vector x, vector y); - -// Error message - -// __intrinsic_op void errorf( string format, ... ); - -// Attribute evaluation - -__generic __intrinsic_op T EvaluateAttributeAtCentroid(T x); -__generic __intrinsic_op vector EvaluateAttributeAtCentroid(vector x); -__generic __intrinsic_op matrix EvaluateAttributeAtCentroid(matrix x); - -__generic __intrinsic_op T EvaluateAttributeAtSample(T x, uint sampleindex); -__generic __intrinsic_op vector EvaluateAttributeAtSample(vector x, uint sampleindex); -__generic __intrinsic_op matrix EvaluateAttributeAtSample(matrix x, uint sampleindex); - -__generic __intrinsic_op T EvaluateAttributeSnapped(T x, int2 offset); -__generic __intrinsic_op vector EvaluateAttributeSnapped(vector x, int2 offset); -__generic __intrinsic_op matrix EvaluateAttributeSnapped(matrix x, int2 offset); - -// Base-e exponent -__generic __intrinsic_op T exp(T x); -__generic __intrinsic_op vector exp(vector x); -__generic __intrinsic_op matrix exp(matrix x); - -// Base-2 exponent -__generic __intrinsic_op T exp2(T x); -__generic __intrinsic_op vector exp2(vector x); -__generic __intrinsic_op matrix exp2(matrix x); - -// Convert 16-bit float stored in low bits of integer -__intrinsic_op float f16tof32(uint value); -__generic __intrinsic_op vector f16tof32(vector value); - -// Convert to 16-bit float stored in low bits of integer -__intrinsic_op uint f32tof16(float value); -__generic __intrinsic_op vector f32tof16(vector value); - -// Flip surface normal to face forward, if needed -__generic __intrinsic_op vector faceforward(vector n, vector i, vector ng); - -// Find first set bit starting at high bit and working down -__intrinsic_op int firstbithigh(int value); -__generic __intrinsic_op vector firstbithigh(vector value); - -__intrinsic_op uint firstbithigh(uint value); -__generic __intrinsic_op vector firstbithigh(vector value); - -// Find first set bit starting at low bit and working up -__intrinsic_op int firstbitlow(int value); -__generic __intrinsic_op vector firstbitlow(vector value); - -__intrinsic_op uint firstbitlow(uint value); -__generic __intrinsic_op vector firstbitlow(vector value); - -// Floor (HLSL SM 1.0) -__generic __intrinsic_op T floor(T x); -__generic __intrinsic_op vector floor(vector x); -__generic __intrinsic_op matrix floor(matrix x); - -// Fused multiply-add for doubles -__intrinsic_op double fma(double a, double b, double c); -__generic __intrinsic_op vector fma(vector a, vector b, vector c); -__generic __intrinsic_op matrix fma(matrix a, matrix b, matrix c); - -// Floating point remainder of x/y -__generic __intrinsic_op T fmod(T x, T y); -__generic __intrinsic_op vector fmod(vector x, vector y); -__generic __intrinsic_op matrix fmod(matrix x, matrix y); - -// Fractional part -__generic -__target_intrinsic(glsl, fract) -__intrinsic_op -T frac(T x); - -__generic -__target_intrinsic(glsl, fract) -__intrinsic_op -vector frac(vector x); - -__generic -__target_intrinsic(glsl, fract) -__intrinsic_op -matrix frac(matrix x); - -// Split float into mantissa and exponent -__generic __intrinsic_op T frexp(T x, out T exp); -__generic __intrinsic_op vector frexp(vector x, out vector exp); -__generic __intrinsic_op matrix frexp(matrix x, out matrix exp); - -// Texture filter width -__generic __intrinsic_op T fwidth(T x); -__generic __intrinsic_op vector fwidth(vector x); -__generic __intrinsic_op matrix fwidth(matrix 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 __intrinsic_op bool isfinite(T x); -__generic __intrinsic_op vector isfinite(vector x); -__generic __intrinsic_op matrix isfinite(matrix x); - -// Is floating-point value infinite? -__generic __intrinsic_op bool isinf(T x); -__generic __intrinsic_op vector isinf(vector x); -__generic __intrinsic_op matrix isinf(matrix x); - -// Is floating-point value not-a-number? -__generic __intrinsic_op bool isnan(T x); -__generic __intrinsic_op vector isnan(vector x); -__generic __intrinsic_op matrix isnan(matrix x); - -// Construct float from mantissa and exponent -__generic __intrinsic_op T ldexp(T x, T exp); -__generic __intrinsic_op vector ldexp(vector x, vector exp); -__generic __intrinsic_op matrix ldexp(matrix x, matrix exp); - -// Vector length -__generic __intrinsic_op T length(vector x); - -// Linear interpolation -__generic -__target_intrinsic(glsl, mix) -__intrinsic_op -T lerp(T x, T y, T s); - -__generic -__target_intrinsic(glsl, mix) -__intrinsic_op -vector lerp(vector x, vector y, vector s); - -__generic -__target_intrinsic(glsl, mix) -__intrinsic_op -matrix lerp(matrix x, matrix y, matrix s); - -// Legacy lighting function (obsolete) -__intrinsic_op float4 lit(float n_dot_l, float n_dot_h, float m); - -// Base-e logarithm -__generic __intrinsic_op T log(T x); -__generic __intrinsic_op vector log(vector x); -__generic __intrinsic_op matrix log(matrix x); - -// Base-10 logarithm -__generic __intrinsic_op T log10(T x); -__generic __intrinsic_op vector log10(vector x); -__generic __intrinsic_op matrix log10(matrix x); - -// Base-2 logarithm -__generic __intrinsic_op T log2(T x); -__generic __intrinsic_op vector log2(vector x); -__generic __intrinsic_op matrix log2(matrix x); - -// multiply-add -__generic __intrinsic_op T mad(T mvalue, T avalue, T bvalue); -__generic __intrinsic_op vector mad(vector mvalue, vector avalue, vector bvalue); -__generic __intrinsic_op matrix mad(matrix mvalue, matrix avalue, matrix bvalue); - -// maximum -__generic __intrinsic_op T max(T x, T y); -__generic __intrinsic_op vector max(vector x, vector y); -__generic __intrinsic_op matrix max(matrix x, matrix y); - -// minimum -__generic __intrinsic_op T min(T x, T y); -__generic __intrinsic_op vector min(vector x, vector y); -__generic __intrinsic_op matrix min(matrix x, matrix y); - -// split into integer and fractional parts (both with same sign) -__generic __intrinsic_op T modf(T x, out T ip); -__generic __intrinsic_op vector modf(vector x, out vector ip); -__generic __intrinsic_op matrix modf(matrix x, out matrix ip); - -// msad4 (whatever that is) -__intrinsic_op uint4 msad4(uint reference, uint2 source, uint4 accum); - -// General inner products - -// scalar-scalar -__generic __intrinsic_op T mul(T x, T y); - -// scalar-vector and vector-scalar -__generic __intrinsic_op vector mul(vector x, T y); -__generic __intrinsic_op vector mul(T x, vector y); - -// scalar-matrix and matrix-scalar -__generic __intrinsic_op matrix mul(matrix x, T y); -__generic __intrinsic_op matrix mul(T x, matrix y); - -// vector-vector (dot product) -__generic __intrinsic_op(dot) T mul(vector x, vector y); - -// vector-matrix -__generic __intrinsic_op(mulVectorMatrix) vector mul(vector x, matrix y); - -// matrix-vector -__generic __intrinsic_op(mulMatrixVector) vector mul(matrix x, vector y); - -// matrix-matrix -__generic __intrinsic_op(mulMatrixMatrix) matrix mul(matrix x, matrix y); - -// noise (deprecated) -__intrinsic_op float noise(float x); -__generic __intrinsic_op float noise(vector x); - -// Normalize a vector -__generic __intrinsic_op vector normalize(vector x); - -// Raise to a power -__generic __intrinsic_op T pow(T x, T y); -__generic __intrinsic_op vector pow(vector x, vector y); -__generic __intrinsic_op matrix pow(matrix x, matrix 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 __intrinsic_op T radians(T x); -__generic __intrinsic_op vector radians(vector x); -__generic __intrinsic_op matrix radians(matrix x); - -// Approximate reciprocal -__generic __intrinsic_op T rcp(T x); -__generic __intrinsic_op vector rcp(vector x); -__generic __intrinsic_op matrix rcp(matrix x); - -// Reflect incident vector across plane with given normal -__generic -__intrinsic_op -vector reflect(vector i, vector n); - -// Refract incident vector given surface normal and index of refraction -__generic -__intrinsic_op -vector refract(vector i, vector n, float eta); - -// Reverse order of bits -__intrinsic_op uint reversebits(uint value); -__generic vector reversebits(vector value); - -// Round-to-nearest -__generic __intrinsic_op T round(T x); -__generic __intrinsic_op vector round(vector x); -__generic __intrinsic_op matrix round(matrix x); - -// Reciprocal of square root -__generic __intrinsic_op T rsqrt(T x); -__generic __intrinsic_op vector rsqrt(vector x); -__generic __intrinsic_op matrix rsqrt(matrix x); - -// Clamp value to [0,1] range -__generic -__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op -T saturate(T x); - -__generic -__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op -vector saturate(vector x); - -__generic -__target_intrinsic(glsl, "clamp($0, 0, 1)") __intrinsic_op -matrix saturate(matrix x); - - -// Extract sign of value -__generic __intrinsic_op int sign(T x); -__generic __intrinsic_op vector sign(vector x); -__generic __intrinsic_op matrix sign(matrix x); - -)=", R"=( - - -// Sine -__generic __intrinsic_op T sin(T x); -__generic __intrinsic_op vector sin(vector x); -__generic __intrinsic_op matrix sin(matrix x); - -// Sine and cosine -__generic __intrinsic_op void sincos(T x, out T s, out T c); -__generic __intrinsic_op void sincos(vector x, out vector s, out vector c); -__generic __intrinsic_op void sincos(matrix x, out matrix s, out matrix c); - -// Hyperbolic Sine -__generic __intrinsic_op T sinh(T x); -__generic __intrinsic_op vector sinh(vector x); -__generic __intrinsic_op matrix sinh(matrix x); - -// Smooth step (Hermite interpolation) -__generic __intrinsic_op T smoothstep(T min, T max, T x); -__generic __intrinsic_op vector smoothstep(vector min, vector max, vector x); -__generic __intrinsic_op matrix smoothstep(matrix min, matrix max, matrix x); - -// Square root -__generic __intrinsic_op T sqrt(T x); -__generic __intrinsic_op vector sqrt(vector x); -__generic __intrinsic_op matrix sqrt(matrix x); - -// Step function -__generic __intrinsic_op T step(T y, T x); -__generic __intrinsic_op vector step(vector y, vector x); -__generic __intrinsic_op matrix step(matrix y, matrix x); - -// Tangent -__generic __intrinsic_op T tan(T x); -__generic __intrinsic_op vector tan(vector x); -__generic __intrinsic_op matrix tan(matrix x); - -// Hyperbolic tangent -__generic __intrinsic_op T tanh(T x); -__generic __intrinsic_op vector tanh(vector x); -__generic __intrinsic_op matrix tanh(matrix 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 __intrinsic_op matrix transpose(matrix x); - -// Truncate to integer -__generic __intrinsic_op T trunc(T x); -__generic __intrinsic_op vector trunc(vector x); -__generic __intrinsic_op matrix trunc(matrix x); - - -)=", R"=( - -// Shader model 6.0 stuff - -__intrinsic_op uint GlobalOrderedCountIncrement(uint countToAppendForThisLane); - -__generic __intrinsic_op T QuadReadLaneAt(T sourceValue, int quadLaneID); -__generic __intrinsic_op vector QuadReadLaneAt(vector sourceValue, int quadLaneID); -__generic __intrinsic_op matrix QuadReadLaneAt(matrix sourceValue, int quadLaneID); - -__generic __intrinsic_op T QuadSwapX(T localValue); -__generic __intrinsic_op vector QuadSwapX(vector localValue); -__generic __intrinsic_op matrix QuadSwapX(matrix localValue); - -__generic __intrinsic_op T QuadSwapY(T localValue); -__generic __intrinsic_op vector QuadSwapY(vector localValue); -__generic __intrinsic_op matrix QuadSwapY(matrix localValue); - -__generic __intrinsic_op T WaveAllBitAnd(T expr); -__generic __intrinsic_op vector WaveAllBitAnd(vector expr); -__generic __intrinsic_op matrix WaveAllBitAnd(matrix expr); - -__generic __intrinsic_op T WaveAllBitOr(T expr); -__generic __intrinsic_op vector WaveAllBitOr(vector expr); -__generic __intrinsic_op matrix WaveAllBitOr(matrix expr); - -__generic __intrinsic_op T WaveAllBitXor(T expr); -__generic __intrinsic_op vector WaveAllBitXor(vector expr); -__generic __intrinsic_op matrix WaveAllBitXor(matrix expr); - -__generic __intrinsic_op T WaveAllMax(T expr); -__generic __intrinsic_op vector WaveAllMax(vector expr); -__generic __intrinsic_op matrix WaveAllMax(matrix expr); - -__generic __intrinsic_op T WaveAllMin(T expr); -__generic __intrinsic_op vector WaveAllMin(vector expr); -__generic __intrinsic_op matrix WaveAllMin(matrix expr); - -__generic __intrinsic_op T WaveAllProduct(T expr); -__generic __intrinsic_op vector WaveAllProduct(vector expr); -__generic __intrinsic_op matrix WaveAllProduct(matrix expr); - -__generic __intrinsic_op T WaveAllSum(T expr); -__generic __intrinsic_op vector WaveAllSum(vector expr); -__generic __intrinsic_op matrix WaveAllSum(matrix 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 __intrinsic_op T WavePrefixProduct(T expr); -__generic __intrinsic_op vector WavePrefixProduct(vector expr); -__generic __intrinsic_op matrix WavePrefixProduct(matrix expr); - -__generic __intrinsic_op T WavePrefixSum(T expr); -__generic __intrinsic_op vector WavePrefixSum(vector expr); -__generic __intrinsic_op matrix WavePrefixSum(matrix expr); - -__generic __intrinsic_op T WaveReadFirstLane(T expr); -__generic __intrinsic_op vector WaveReadFirstLane(vector expr); -__generic __intrinsic_op matrix WaveReadFirstLane(matrix expr); - -__generic __intrinsic_op T WaveReadLaneAt(T expr, int laneIndex); -__generic __intrinsic_op vector WaveReadLaneAt(vector expr, int laneIndex); -__generic __intrinsic_op matrix WaveReadLaneAt(matrix 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,894 +244,15 @@ 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 + #include "core.meta.slang.cpp" - 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 __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 __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\n"; - sb << "__intrinsic_type(" << kIROp_ConstantBufferType << ")\n"; - sb << "__magic_type(ConstantBuffer) struct ConstantBuffer {};\n"; - - sb << "__generic\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 __extension vector\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 " << 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 __init(vector);\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 " << kVectorNames[M]; - sb << ", vector "; - 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 __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 __extension matrix\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 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 __init(matrix);\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 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 "; - - 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`. - // - static const struct { - char const* genericPrefix; - char const* elementType; - } kGatherExtensionCases[] = { - { "__generic", "vector" }, - - // 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` 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 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 Gather" << componentName << "(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; - - EMIT_LINE_DIRECTIVE(); - sb << "vector 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 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 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 "; - 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 "; - 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 "; - 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 "; - 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 "; - sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n"; - - sb << "__generic "; - 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 "; - sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n"; - - sb << "__generic "; - 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]; - } - - coreLibraryCode = sb.ProduceString(); - return coreLibraryCode; - } + coreLibraryCode = sb.ProduceString(); + return coreLibraryCode; + } String Session::getHLSLLibraryCode() { @@ -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 "; - 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 __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 __intrinsic_op(mul) vector operator*(vector x, T y);\n"; - sb << "__generic __intrinsic_op(mul) vector operator*(T x, vector y);\n"; - - // scalar-matrix and matrix-scalar - sb << "__generic __intrinsic_op(mul) matrix operator*(matrix x, T y);\n"; - sb << "__generic __intrinsic_op(mul) matrix operator*(T x, matrix y);\n"; - - // vector-vector (dot product) - sb << "__generic __intrinsic_op(dot) T operator*(vector x, vector y);\n"; - - // vector-matrix - sb << "__generic __intrinsic_op(mulVectorMatrix) vector operator*(vector x, matrix y);\n"; - - // matrix-vector - sb << "__generic __intrinsic_op(mulMatrixVector) vector operator*(matrix x, vector y);\n"; - - // matrix-matrix - sb << "__generic __intrinsic_op(mulMatrixMatrix) matrix operator*(matrix x, matrix 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 "; - sb << "__magic_type(TextureSampler," << int(readFlavor) << ") struct "; - sb << "__sampler" << name; - sb << " {};\n"; - - sb << "__generic "; - sb << "__magic_type(Texture," << int(readFlavor) << ") struct "; - sb << "__texture" << name; - sb << " {};\n"; - - sb << "__generic "; - 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 __magic_type(GLSLInputParameterBlockType) struct __GLSLInputParameterBlock {};\n"; - sb << "__generic __magic_type(GLSLOutputParameterBlockType) struct __GLSLOutputParameterBlock {};\n"; - sb << "__generic __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 @@ {f9be7957-8399-899e-0c49-e714fddd4b65} + + + Document + $(OutDir)slang-generate.exe %(Identity) + slang-generate %(Identity) + %(Identity).cpp + $(OutDir)slang-generate.exe + $(OutDir)slang-generate.exe %(Identity) + slang-generate %(Identity) + %(Identity).cpp + $(OutDir)slang-generate.exe + $(OutDir)slang-generate.exe %(Identity) + slang-generate %(Identity) + %(Identity).cpp + $(OutDir)slang-generate.exe + $(OutDir)slang-generate.exe %(Identity) + slang-generate %(Identity) + %(Identity).cpp + $(OutDir)slang-generate.exe + + + Document + $(OutDir)slang-generate.exe %(Identity) + $(OutDir)slang-generate.exe %(Identity) + $(OutDir)slang-generate.exe %(Identity) + $(OutDir)slang-generate.exe %(Identity) + slang-generate %(Identity) + slang-generate %(Identity) + slang-generate %(Identity) + slang-generate %(Identity) + %(Identity).cpp + %(Identity).cpp + %(Identity).cpp + %(Identity).cpp + $(OutDir)slang-generate.exe + $(OutDir)slang-generate.exe + $(OutDir)slang-generate.exe + $(OutDir)slang-generate.exe + + + Document + $(OutDir)slang-generate.exe %(Identity) + $(OutDir)slang-generate.exe %(Identity) + $(OutDir)slang-generate.exe %(Identity) + $(OutDir)slang-generate.exe %(Identity) + slang-generate %(Identity) + slang-generate %(Identity) + slang-generate %(Identity) + slang-generate %(Identity) + %(Identity).cpp + %(Identity).cpp + %(Identity).cpp + %(Identity).cpp + $(OutDir)slang-generate.exe + $(OutDir)slang-generate.exe + $(OutDir)slang-generate.exe + $(OutDir)slang-generate.exe + + 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 @@ + + + + + \ No newline at end of file -- cgit v1.2.3