From 74f2f47cb63b02638270beecd20acea1a0f5665e Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Wed, 27 Sep 2017 11:17:39 -0700 Subject: 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. --- source/slang/core.meta.slang.cpp | 916 --------------------------------------- 1 file changed, 916 deletions(-) delete mode 100644 source/slang/core.meta.slang.cpp (limited to 'source/slang/core.meta.slang.cpp') 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 __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 << " __intrinsic_op(" << kIROp_constructVectorFromScalar << ")\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"; - - - // 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`. - // - 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 << ""; -- cgit v1.2.3