summaryrefslogtreecommitdiff
path: root/source/slang/core.meta.slang.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-09-27 11:17:39 -0700
committerGitHub <noreply@github.com>2017-09-27 11:17:39 -0700
commit74f2f47cb63b02638270beecd20acea1a0f5665e (patch)
treeaf50d0355c7fccb4fb93fc1a0d45c66b5d07f1c9 /source/slang/core.meta.slang.cpp
parentb6cf0f4ae0f3f9d1f377d3f134dcf994676e68b4 (diff)
First attempt at a Linux build (#193)
* First attempt at a Linux build - Fix up places where C++ idioms were written assuming lenient behavior of Microsoft's compiler - Add a few more alternatives for platform-specific behavior where Windows was the only platform accounted for. - Add a basic Makefile that can at least invoke our build, even if it isn't going good dependency tracking, etc. - Build `libslang.so` and `slangc` that depends on it, using a relative `RPATH` to make the binary portable (I hope) - Add an initial `.travis.yml` to see if we can trigger their build process. * Fixup: const bug in `List::Sort` I'm not clear why this gets picked up by the gcc *and* clang that Travis uses, but not the (newer) gcc I'm using on Ubuntu here, but I'm hoping it is just some missing `const` qualifiers. * Fixup: reorder specialization of "class info" Clang complains about things being specialized after being instantiated (implicilty), and I hope it is just the fact that I generate the class info for the roots of the hierarchy after the other cases. We'll see. * Fixup: add `platform.cpp` to unified/lumped build * Fixup: Windows uses `FreeLibrary` and not `UnloadLibrary` * Fixup: fix Windows project file to include new source file This obviously points to the fact that we are going to need to be generating these files sooner or later.
Diffstat (limited to 'source/slang/core.meta.slang.cpp')
-rw-r--r--source/slang/core.meta.slang.cpp916
1 files changed, 0 insertions, 916 deletions
diff --git a/source/slang/core.meta.slang.cpp b/source/slang/core.meta.slang.cpp
deleted file mode 100644
index cf2052d3c..000000000
--- a/source/slang/core.meta.slang.cpp
+++ /dev/null
@@ -1,916 +0,0 @@
-sb << "// Slang `core` library\n";
-sb << "\n";
-sb << "// A type that can be used as an operand for builtins\n";
-sb << "interface __BuiltinType {}\n";
-sb << "\n";
-sb << "// A type that can be used for arithmetic operations\n";
-sb << "interface __BuiltinArithmeticType : __BuiltinType {}\n";
-sb << "\n";
-sb << "// A type that logically has a sign (positive/negative/zero)\n";
-sb << "interface __BuiltinSignedArithmeticType : __BuiltinArithmeticType {}\n";
-sb << "\n";
-sb << "// A type that can represent integers\n";
-sb << "interface __BuiltinIntegerType : __BuiltinArithmeticType {}\n";
-sb << "\n";
-sb << "// A type that can represent non-integers\n";
-sb << "interface __BuiltinRealType : __BuiltinArithmeticType {}\n";
-sb << "\n";
-sb << "// A type that uses a floating-point representation\n";
-sb << "interface __BuiltinFloatingPointType : __BuiltinRealType, __BuiltinSignedArithmeticType {}\n";
-sb << "\n";
-sb << "__generic<T,U> __intrinsic_op(Sequence) U operator,(T left, U right);\n";
-sb << "\n";
-sb << "__generic<T> __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse);\n";
-sb << "__generic<T, let N : int> __intrinsic_op(select) vector<T,N> operator?:(vector<bool,N> condition, vector<T,N> ifTrue, vector<T,N> ifFalse);\n";
-sb << "\n";
-sb << "";
-
-// We are going to use code generation to produce the
-// declarations for all of our base types.
-
-static const int kBaseTypeCount = sizeof(kBaseTypes) / sizeof(kBaseTypes[0]);
-for (int tt = 0; tt < kBaseTypeCount; ++tt)
-{
- EMIT_LINE_DIRECTIVE();
- sb << "__builtin_type(" << int(kBaseTypes[tt].tag) << ") struct " << kBaseTypes[tt].name;
-
- // Declare interface conformances for this type
-
- sb << "\n : __BuiltinType\n";
-
- switch (kBaseTypes[tt].tag)
- {
- case BaseType::Float:
- sb << "\n , __BuiltinFloatingPointType\n";
- sb << "\n , __BuiltinRealType\n";
- // fall through to:
- case BaseType::Int:
- sb << "\n , __BuiltinSignedArithmeticType\n";
- // fall through to:
- case BaseType::UInt:
- case BaseType::UInt64:
- sb << "\n , __BuiltinArithmeticType\n";
- // fall through to:
- case BaseType::Bool:
- sb << "\n , __BuiltinType\n";
- break;
-
- default:
- break;
- }
-
- sb << "\n{\n";
-
-
- // Declare initializers to convert from various other types
- for (int ss = 0; ss < kBaseTypeCount; ++ss)
- {
- // Don't allow conversion from `void`
- if (kBaseTypes[ss].tag == BaseType::Void)
- continue;
-
- // We need to emit a modifier so that the semantic-checking
- // layer will know it can use these operations for implicit
- // conversion.
- ConversionCost conversionCost = getBaseTypeConversionCost(
- kBaseTypes[tt],
- kBaseTypes[ss]);
-
- EMIT_LINE_DIRECTIVE();
- sb << "__implicit_conversion(" << conversionCost << ")\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "__init(" << kBaseTypes[ss].name << " value);\n";
- }
-
- sb << "};\n";
-}
-
-
-
-// Declare vector and matrix types
-
-sb << "__generic<T = float, let N : int = 4> __magic_type(Vector) struct vector\n{\n";
-sb << " typedef T Element;\n";
-
-// Declare initializer taking a single scalar of the elemnt type
-sb << " __implicit_conversion(" << kConversionCost_ScalarToVector << ")\n";
-sb << " __intrinsic_op(" << kIROp_constructVectorFromScalar << ")\n";
-sb << " __init(T value);\n";
-
-sb << "};\n";
-
-// TODO: Probably need to do similar
-sb << "\n";
-sb << "\n";
-sb << "__generic<T = float, let R : int = 4, let C : int = 4>\n";
-sb << "__magic_type(Matrix)\n";
-sb << "struct matrix {};\n";
-sb << "\n";
-sb << "";
-
-
-
-
-static const struct {
- char const* name;
- char const* glslPrefix;
-} kTypes[] =
-{
- {"float", ""},
- {"int", "i"},
- {"uint", "u"},
- {"bool", "b"},
-};
-static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]);
-
-for (int tt = 0; tt < kTypeCount; ++tt)
-{
- // Declare HLSL vector types
- for (int ii = 1; ii <= 4; ++ii)
- {
- sb << "typedef vector<" << kTypes[tt].name << "," << ii << "> " << kTypes[tt].name << ii << ";\n";
- }
-
- // Declare HLSL matrix types
- for (int rr = 2; rr <= 4; ++rr)
- for (int cc = 2; cc <= 4; ++cc)
- {
- sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].name << rr << "x" << cc << ";\n";
- }
-}
-
-// Declare additional built-in generic types
-// EMIT_LINE_DIRECTIVE();
-
-
-sb << "__generic<T>\n";
-sb << "__intrinsic_type(" << kIROp_ConstantBufferType << ")\n";
-sb << "__magic_type(ConstantBuffer) struct ConstantBuffer {};\n";
-
-sb << "__generic<T>\n";
-sb << "__intrinsic_type(" << kIROp_TextureBufferType << ")\n";
-sb << "__magic_type(TextureBuffer) struct TextureBuffer {};\n";
-
-
-static const char* kComponentNames[]{ "x", "y", "z", "w" };
-static const char* kVectorNames[]{ "", "x", "xy", "xyz", "xyzw" };
-
-// Need to add constructors to the types above
-for (int N = 2; N <= 4; ++N)
-{
- sb << "__generic<T> __extension vector<T, " << N << ">\n{\n";
-
- // initialize from N scalars
- sb << "__init(";
- for (int ii = 0; ii < N; ++ii)
- {
- if (ii != 0) sb << ", ";
- sb << "T " << kComponentNames[ii];
- }
- sb << ");\n";
-
- // Initialize from an M-vector and then scalars
- for (int M = 2; M < N; ++M)
- {
- sb << "__init(vector<T," << M << "> " << kVectorNames[M];
- for (int ii = M; ii < N; ++ii)
- {
- sb << ", T " << kComponentNames[ii];
- }
- sb << ");\n";
- }
-
- // initialize from another vector of the same size
- //
- // TODO(tfoley): this overlaps with implicit conversions.
- // We should look for a way that we can define implicit
- // conversions directly in the stdlib instead...
- sb << "__generic<U> __init(vector<U," << N << ">);\n";
-
- // Initialize from two vectors, of size M and N-M
- for(int M = 2; M <= (N-2); ++M)
- {
- int K = N - M;
- SLANG_ASSERT(K >= 2);
-
- sb << "__init(vector<T," << M << "> " << kVectorNames[M];
- sb << ", vector<T," << K << "> ";
- for (int ii = 0; ii < K; ++ii)
- {
- sb << kComponentNames[ii];
- }
- sb << ");\n";
- }
-
- sb << "}\n";
-}
-
-// The above extension was generic in the *type* of the vector,
-// but explicit in the *size*. We will now declare an extension
-// for each builtin type that is generic in the size.
-//
-for (int tt = 0; tt < kBaseTypeCount; ++tt)
-{
- if(kBaseTypes[tt].tag == BaseType::Void) continue;
-
- sb << "__generic<let N : int> __extension vector<"
- << kBaseTypes[tt].name << ",N>\n{\n";
-
- for (int ff = 0; ff < kBaseTypeCount; ++ff)
- {
- if(kBaseTypes[ff].tag == BaseType::Void) continue;
-
- // We need a constructor to make a vector from a scalar
- // of another type.
-
- if( tt != ff )
- {
- auto cost = getBaseTypeConversionCost(
- kBaseTypes[tt],
- kBaseTypes[ff]);
- cost += kConversionCost_ScalarToVector;
-
- sb << " __implicit_conversion(" << cost << ")\n";
- sb << " __init(" << kBaseTypes[ff].name << " value);\n";
- }
- }
-
- sb << "}\n";
-}
-
-for( int R = 2; R <= 4; ++R )
-for( int C = 2; C <= 4; ++C )
-{
- sb << "__generic<T> __extension matrix<T, " << R << "," << C << ">\n{\n";
-
- // initialize from R*C scalars
- sb << "__init(";
- for( int ii = 0; ii < R; ++ii )
- for( int jj = 0; jj < C; ++jj )
- {
- if ((ii+jj) != 0) sb << ", ";
- sb << "T m" << ii << jj;
- }
- sb << ");\n";
-
- // Initialize from R C-vectors
- sb << "__init(";
- for (int ii = 0; ii < R; ++ii)
- {
- if(ii != 0) sb << ", ";
- sb << "vector<T," << C << "> row" << ii;
- }
- sb << ");\n";
-
-
- // initialize from another matrix of the same size
- //
- // TODO(tfoley): See comment about how this overlaps
- // with implicit conversion, in the `vector` case above
- sb << "__generic<U> __init(matrix<U," << R << ", " << C << ">);\n";
-
- // initialize from a matrix of larger size
- for(int rr = R; rr <= 4; ++rr)
- for( int cc = C; cc <= 4; ++cc )
- {
- if(rr == R && cc == C) continue;
- sb << "__init(matrix<T," << rr << "," << cc << "> value);\n";
- }
-
- sb << "}\n";
-}
-
-// Declare built-in texture and sampler types
-
-
-
-sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ")\n";
-sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerState) << ")\n";
-sb << "struct SamplerState {};";
-
-sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n";
-sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n";
-sb << "struct SamplerComparisonState {};";
-
-// TODO(tfoley): Need to handle `RW*` variants of texture types as well...
-static const struct {
- char const* name;
- TextureType::Shape baseShape;
- int coordCount;
-} kBaseTextureTypes[] = {
- { "Texture1D", TextureType::Shape1D, 1 },
- { "Texture2D", TextureType::Shape2D, 2 },
- { "Texture3D", TextureType::Shape3D, 3 },
- { "TextureCube", TextureType::ShapeCube, 3 },
-};
-static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]);
-
-
-static const struct {
- char const* name;
- SlangResourceAccess access;
-} kBaseTextureAccessLevels[] = {
- { "", SLANG_RESOURCE_ACCESS_READ },
- { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE },
- { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED },
-};
-static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]);
-
-for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
-{
- char const* name = kBaseTextureTypes[tt].name;
- TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape;
-
- for (int isArray = 0; isArray < 2; ++isArray)
- {
- // Arrays of 3D textures aren't allowed
- if (isArray && baseShape == TextureType::Shape3D) continue;
-
- for (int isMultisample = 0; isMultisample < 2; ++isMultisample)
- for (int accessLevel = 0; accessLevel < kBaseTextureAccessLevelCount; ++accessLevel)
- {
- auto access = kBaseTextureAccessLevels[accessLevel].access;
-
- // TODO: any constraints to enforce on what gets to be multisampled?
-
- unsigned flavor = baseShape;
- if (isArray) flavor |= TextureType::ArrayFlag;
- if (isMultisample) flavor |= TextureType::MultisampleFlag;
-// if (isShadow) flavor |= TextureType::ShadowFlag;
-
- flavor |= (access << 8);
-
- // emit a generic signature
- // TODO: allow for multisample count to come in as well...
- sb << "__generic<T = float4> ";
-
- sb << "__magic_type(Texture," << int(flavor) << ")\n";
- sb << "__intrinsic_type(" << kIROp_TextureType << ", " << flavor << ")\n";
- sb << "struct ";
- sb << kBaseTextureAccessLevels[accessLevel].name;
- sb << name;
- if (isMultisample) sb << "MS";
- if (isArray) sb << "Array";
-// if (isShadow) sb << "Shadow";
- sb << "\n{";
-
- if( !isMultisample )
- {
- sb << "float CalculateLevelOfDetail(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
-
- sb << "float CalculateLevelOfDetailUnclamped(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
- }
-
- // `GetDimensions`
-
- for(int isFloat = 0; isFloat < 2; ++isFloat)
- for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo)
- {
- {
- sb << "__glsl_version(450)\n";
- sb << "__target_intrinsic(glsl, \"(";
-
- int aa = 0;
- String lodStr = "0";
- if (includeMipInfo)
- {
- int mipLevelArg = aa++;
- lodStr = "int($";
- lodStr.append(mipLevelArg);
- lodStr.append(")");
- }
-
- int cc = 0;
- switch(baseShape)
- {
- case TextureType::Shape1D:
- sb << "($" << aa++ << " = textureSize($P, " << lodStr << "))";
- cc = 1;
- break;
-
- case TextureType::Shape2D:
- case TextureType::ShapeCube:
- sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)";
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)";
- cc = 2;
- break;
-
- case TextureType::Shape3D:
- sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)";
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)";
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").z)";
- cc = 3;
- break;
-
- default:
- SLANG_UNEXPECTED("unhandled resource shape");
- break;
- }
-
- if(isArray)
- {
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ")." << kComponentNames[cc] << ")";
- }
-
- if(isMultisample)
- {
- sb << ", ($" << aa++ << " = textureSamples($P))";
- }
-
- if (includeMipInfo)
- {
- sb << ", ($" << aa++ << " = textureQueryLevels($P))";
- }
-
-
- sb << ")\")\n";
-
-
- // TIM: Making `GetDimensions` *not* be marked as
- // an intrinsic, just so we can see how defining
- // things as `extern` functions would work.
-// sb << "__intrinsic_op\n";
-
- }
-
- char const* t = isFloat ? "out float " : "out uint ";
-
- sb << "void GetDimensions(";
- if(includeMipInfo)
- sb << "uint mipLevel, ";
-
- switch(baseShape)
- {
- case TextureType::Shape1D:
- sb << t << "width";
- break;
-
- case TextureType::Shape2D:
- case TextureType::ShapeCube:
- sb << t << "width,";
- sb << t << "height";
- break;
-
- case TextureType::Shape3D:
- sb << t << "width,";
- sb << t << "height,";
- sb << t << "depth";
- break;
-
- default:
- assert(!"unexpected");
- break;
- }
-
- if(isArray)
- {
- sb << ", " << t << "elements";
- }
-
- if(isMultisample)
- {
- sb << ", " << t << "sampleCount";
- }
-
- if(includeMipInfo)
- sb << ", " << t << "numberOfLevels";
-
- sb << ");\n";
- }
-
- // `GetSamplePosition()`
- if( isMultisample )
- {
- sb << "float2 GetSamplePosition(int s);\n";
- }
-
- // `Load()`
-
- if( kBaseTextureTypes[tt].coordCount + isArray < 4 )
- {
- int loadCoordCount = kBaseTextureTypes[tt].coordCount + isArray + (isMultisample?0:1);
-
- // When translating to GLSL, we need to break apart the `location` argument.
- //
- // TODO: this should realy be handled by having this member actually get lowered!
- static const char* kGLSLLoadCoordsSwizzle[] = { "", "", "x", "xy", "xyz", "xyzw" };
- static const char* kGLSLLoadLODSwizzle[] = { "", "", "y", "z", "w", "error" };
-
- if (isMultisample)
- {
- sb << "__target_intrinsic(glsl, \"texelFetch($P, $0, $1)\")\n";
- }
- else
- {
- sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
- }
- sb << "__intrinsic_op\n";
- sb << "T Load(";
- sb << "int" << loadCoordCount << " location";
- if(isMultisample)
- {
- sb << ", int sampleIndex";
- }
- sb << ");\n";
-
- if (isMultisample)
- {
- sb << "__target_intrinsic(glsl, \"texelFetchOffset($P, $0, $1, $2)\")\n";
- }
- else
- {
- sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $1)\")\n";
- }
- sb << "__intrinsic_op\n";
- sb << "T Load(";
- sb << "int" << loadCoordCount << " location";
- if(isMultisample)
- {
- sb << ", int sampleIndex";
- }
- sb << ", int" << loadCoordCount << " offset";
- sb << ");\n";
-
-
- sb << "T Load(";
- sb << "int" << loadCoordCount << " location";
- if(isMultisample)
- {
- sb << ", int sampleIndex";
- }
- sb << ", int" << kBaseTextureTypes[tt].coordCount << " offset";
- sb << ", out uint status";
- sb << ");\n";
- }
-
- if(baseShape != TextureType::ShapeCube)
- {
- // subscript operator
- sb << "__intrinsic_op __subscript(uint" << kBaseTextureTypes[tt].coordCount + isArray << " location) -> T;\n";
- }
-
- if( !isMultisample )
- {
- // `Sample()`
-
- sb << "__target_intrinsic(glsl, \"texture($p, $1)\")\n";
-
- // TODO: only enable if IR is being used?
- sb << "__intrinsic_op(sample)\n";
-
- sb << "__intrinsic_op\n";
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
-
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
- }
- sb << "float clamp);\n";
-
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
- }
- sb << "float clamp, out uint status);\n";
-
-
- // `SampleBias()`
- sb << "__target_intrinsic(glsl, \"texture($p, $1, $2)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T SampleBias(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2, $3)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T SampleBias(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
-
- // `SampleCmp()` and `SampleCmpLevelZero`
- sb << "T SampleCmp(SamplerComparisonState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float compareValue";
- sb << ");\n";
-
- int baseCoordCount = kBaseTextureTypes[tt].coordCount;
- int arrCoordCount = baseCoordCount + isArray;
- if (arrCoordCount < 3)
- {
- int extCoordCount = arrCoordCount + 1;
-
- if (extCoordCount < 3)
- extCoordCount = 3;
-
- sb << "__target_intrinsic(glsl, \"textureLod($p, ";
-
- sb << "vec" << extCoordCount << "($1,";
- for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
- {
- sb << " 0.0,";
- }
- sb << "$2)";
-
- sb << ", 0.0)\")\n";
- }
- else if(arrCoordCount <= 3)
- {
- int extCoordCount = arrCoordCount + 1;
-
- if (extCoordCount < 3)
- extCoordCount = 3;
-
- sb << "__target_intrinsic(glsl, \"textureGrad($p, ";
-
- sb << "vec" << extCoordCount << "($1,";
- for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
- {
- sb << " 0.0,";
- }
- sb << "$2)";
-
- // Construct gradients
- sb << ", vec" << baseCoordCount << "(0.0)";
- sb << ", vec" << baseCoordCount << "(0.0)";
- sb << ")\")\n";
- }
- sb << "__intrinsic_op\n";
- sb << "T SampleCmpLevelZero(SamplerComparisonState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float compareValue";
- sb << ");\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- // Note(tfoley): MSDN seems confused, and claims that the `offset`
- // parameter for `SampleCmp` is available for everything but 3D
- // textures, while `Sample` and `SampleBias` are consistent in
- // saying they only exclude `offset` for cube maps (which makes
- // sense). I'm going to assume the documentation for `SampleCmp`
- // is just wrong.
-
- sb << "T SampleCmp(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float compareValue, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
-
- sb << "T SampleCmpLevelZero(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float compareValue, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
-
-
- sb << "__target_intrinsic(glsl, \"textureGrad($p, $1, $2, $3)\")\n";
- sb << "__intrinsic_op(sampleGrad)\n";
- sb << "T SampleGrad(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY";
- sb << ");\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "__target_intrinsic(glsl, \"textureGradOffset($p, $1, $2, $3, $4)\")\n";
- sb << "__intrinsic_op(sampleGrad)\n";
- sb << "T SampleGrad(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
-
- // `SampleLevel`
-
- sb << "__target_intrinsic(glsl, \"textureLod($p, $1, $2)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T SampleLevel(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float level);\n";
-
- if( baseShape != TextureType::ShapeCube )
- {
- sb << "__target_intrinsic(glsl, \"textureLodOffset($p, $1, $2, $3)\")\n";
- sb << "__intrinsic_op\n";
- sb << "T SampleLevel(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
- sb << "float level, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
- }
- }
-
- sb << "\n};\n";
-
- // `Gather*()` operations are handled via an `extension` declaration,
- // because this lets us capture the element type of the texture.
- //
- // TODO: longer-term there should be something like a `TextureElementType`
- // interface, that both scalars and vectors implement, that then exposes
- // a `Scalar` associated type, and `Gather` can return `vector<T.Scalar, 4>`.
- //
- static const struct {
- char const* genericPrefix;
- char const* elementType;
- } kGatherExtensionCases[] = {
- { "__generic<T, let N : int>", "vector<T,N>" },
-
- // TODO: need a case here for scalars `T`, but also
- // need to ensure that case doesn't accidentally match
- // for `T = vector<...>`, which requires actual checking
- // of constraints on generic parameters.
- };
- for(auto cc : kGatherExtensionCases)
- {
- // TODO: this should really be an `if` around the entire `Gather` logic
- if (isMultisample) break;
-
- EMIT_LINE_DIRECTIVE();
- sb << cc.genericPrefix << " __extension ";
- sb << kBaseTextureAccessLevels[accessLevel].name;
- sb << name;
- if (isArray) sb << "Array";
- sb << "<" << cc.elementType << " >";
- sb << "\n{\n";
-
-
- // `Gather`
- // (tricky because it returns a 4-vector of the element type
- // of the texture components...)
- //
- // TODO: is it actually correct to restrict these so that, e.g.,
- // `GatherAlpha()` isn't allowed on `Texture2D<float3>` because
- // it nominally doesn't have an alpha component?
- static const struct {
- int componentIndex;
- char const* componentName;
- } kGatherComponets[] = {
- { 0, "" },
- { 0, "Red" },
- { 1, "Green" },
- { 2, "Blue" },
- { 3, "Alpha" },
- };
-
- for(auto kk : kGatherComponets)
- {
- auto componentIndex = kk.componentIndex;
- auto componentName = kk.componentName;
-
- EMIT_LINE_DIRECTIVE();
-
- sb << "__target_intrinsic(glsl, \"textureGather($p, $1, " << componentIndex << ")\")\n";
- sb << "__intrinsic_op\n";
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $1, $2, " << componentIndex << ")\")\n";
- sb << "__intrinsic_op\n";
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, ";
- sb << "out uint status);\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $1, int" << kBaseTextureTypes[tt].coordCount << "[]($2, $3, $4, $5), " << componentIndex << ")\")\n";
- sb << "__intrinsic_op\n";
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4);\n";
-
- EMIT_LINE_DIRECTIVE();
- sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, ";
- sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4, ";
- sb << "out uint status);\n";
- }
-
- EMIT_LINE_DIRECTIVE();
- sb << "\n}\n";
- }
- }
- }
-}
-
-
-for (auto op : unaryOps)
-{
- for (auto type : kBaseTypes)
- {
- if ((type.flags & op.flags) == 0)
- continue;
-
- char const* fixity = (op.flags & POSTFIX) != 0 ? "__postfix " : "__prefix ";
- char const* qual = (op.flags & ASSIGNMENT) != 0 ? "in out " : "";
-
- // scalar version
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") " << type.name << " operator" << op.opName << "(" << qual << type.name << " value);\n";
-
- // vector version
- sb << "__generic<let N : int> ";
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << type.name << ",N> operator" << op.opName << "(" << qual << "vector<" << type.name << ",N> value);\n";
-
- // matrix version
- sb << "__generic<let N : int, let M : int> ";
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << type.name << ",N,M> operator" << op.opName << "(" << qual << "matrix<" << type.name << ",N,M> value);\n";
- }
-}
-
-for (auto op : binaryOps)
-{
- for (auto type : kBaseTypes)
- {
- if ((type.flags & op.flags) == 0)
- continue;
-
- char const* leftType = type.name;
- char const* rightType = leftType;
- char const* resultType = leftType;
-
- if (op.flags & COMPARISON) resultType = "bool";
-
- char const* leftQual = "";
- if(op.flags & ASSIGNMENT) leftQual = "in out ";
-
- // TODO: handle `SHIFT`
-
- // scalar version
- sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftQual << leftType << " left, " << rightType << " right);\n";
-
- // vector version
- sb << "__generic<let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n";
-
- // matrix version
-
- // skip matrix-matrix multiply operations here, so that GLSL doesn't see them
- switch (op.opCode)
- {
- case kIROp_Mul:
- case kIRPseudoOp_MulAssign:
- break;
-
- default:
- sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
- break;
- }
-
- // We are going to go ahead and explicitly define combined
- // operations for the scalar-op-vector, etc. cases, rather
- // than rely on promotion rules.
-
- // scalar-vector and scalar-matrix
- if (!(op.flags & ASSIGNMENT))
- {
- sb << "__generic<let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n";
-
- sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << leftType << " left, matrix<" << rightType << ",N,M> right);\n";
- }
-
- // vector-scalar and matrix-scalar
- sb << "__generic<let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n";
-
- sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, " << rightType << " right);\n";
- }
-}
-
-sb << "\n";
-sb << "";