diff options
| -rw-r--r-- | source/slang/core.meta.slang | 146 | ||||
| -rw-r--r-- | source/slang/slang-intrinsic-expand.cpp | 87 | ||||
| -rw-r--r-- | source/slang/slang-intrinsic-expand.h | 20 | ||||
| -rw-r--r-- | source/slang/slang-reflection-api.cpp | 7 | ||||
| -rw-r--r-- | tests/type/texture-sampler/texture-sampler-2d.slang | 20 | ||||
| -rw-r--r-- | tests/type/texture-sampler/texture-sampler-2d.slang.expected.txt | 4 | ||||
| -rw-r--r-- | tools/render-test/shader-input-layout.cpp | 51 |
7 files changed, 205 insertions, 130 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 761316d86..d1dc25cc7 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -574,14 +574,14 @@ struct SamplerComparisonState ${{{{ static const struct { - char const* name; + char const* shapeName; TextureFlavor::Shape baseShape; int coordCount; } kBaseTextureTypes[] = { - { "Texture1D", TextureFlavor::Shape::Shape1D, 1 }, - { "Texture2D", TextureFlavor::Shape::Shape2D, 2 }, - { "Texture3D", TextureFlavor::Shape::Shape3D, 3 }, - { "TextureCube", TextureFlavor::Shape::ShapeCube, 3 }, + { "1D", TextureFlavor::Shape::Shape1D, 1 }, + { "2D", TextureFlavor::Shape::Shape2D, 2 }, + { "3D", TextureFlavor::Shape::Shape3D, 3 }, + { "Cube", TextureFlavor::Shape::ShapeCube,3 }, }; static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]); @@ -596,79 +596,21 @@ static const struct { }; static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]); -// Declare the GLSL types here for compatibility... -// -// TODO: The stdlib should include a module that declares the GLSL types, to keep -// them separate... -for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) +static const struct TextureTypePrefixInfo { - char const* name = kBaseTextureTypes[tt].name; - TextureFlavor::Shape baseShape = kBaseTextureTypes[tt].baseShape; - - for (int isArray = 0; isArray < 2; ++isArray) - { - // Arrays of 3D textures aren't allowed - if (isArray && baseShape == TextureFlavor::Shape::Shape3D) continue; - - for (int isMultisample = 0; isMultisample < 2; ++isMultisample) - { - for (int accessLevel = 0; accessLevel < kBaseTextureAccessLevelCount; ++accessLevel) - { - auto access = kBaseTextureAccessLevels[accessLevel].access; - - // No such thing as RWTextureCube - if (access == SLANG_RESOURCE_ACCESS_READ_WRITE && baseShape == TextureFlavor::Shape::ShapeCube) - { - continue; - } - - // TODO: any constraints to enforce on what gets to be multisampled? - - unsigned flavor = baseShape; - if (isArray) flavor |= TextureFlavor::ArrayFlag; - if (isMultisample) flavor |= TextureFlavor::MultisampleFlag; - // if (isShadow) flavor |= TextureFlavor::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(TextureSampler," << int(flavor) << ")\n"; - sb << "__intrinsic_type(" << (kIROp_TextureSamplerType + (int(flavor) << kIROpMeta_OtherShift)) << ")\n"; - sb << "struct Sampler"; - sb << kBaseTextureAccessLevels[accessLevel].name; - sb << name; - if (isMultisample) sb << "MS"; - if (isArray) sb << "Array"; - // if (isShadow) sb << "Shadow"; - sb << "\n{\n"; - sb << "__specialized_for_target(glsl)\n"; - sb << "__init("; - sb << kBaseTextureAccessLevels[accessLevel].name; - sb << name; - if (isMultisample) sb << "MS"; - if (isArray) sb << "Array"; - sb << "<T> t, "; - sb << "SamplerState s);\n"; - sb << "};\n"; - - sb << "__specialized_for_target(glsl)\n"; - sb << "T texture<T>(Sampler"; - sb << kBaseTextureAccessLevels[accessLevel].name; - sb << name; - if (isMultisample) sb << "MS"; - if (isArray) sb << "Array"; - sb << "<T> t, float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n"; - } - } - } -} + char const* name; + bool combined; +} kTexturePrefixes[] = +{ + { "Texture", false }, + { "Sampler", true }, +}; +for(auto& prefixInfo : kTexturePrefixes) for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) { - char const* name = kBaseTextureTypes[tt].name; + char const* baseName = prefixInfo.name; + char const* baseShapeName = kBaseTextureTypes[tt].shapeName; TextureFlavor::Shape baseShape = kBaseTextureTypes[tt].baseShape; for (int isArray = 0; isArray < 2; ++isArray) @@ -701,22 +643,33 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) // 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 + (int(flavor) << kIROpMeta_OtherShift)) << ")\n"; + if(prefixInfo.combined) + { + sb << "__magic_type(TextureSampler," << int(flavor) << ")\n"; + sb << "__intrinsic_type(" << (kIROp_TextureSamplerType + (int(flavor) << kIROpMeta_OtherShift)) << ")\n"; + } + else + { + sb << "__magic_type(Texture," << int(flavor) << ")\n"; + sb << "__intrinsic_type(" << (kIROp_TextureType + (int(flavor) << kIROpMeta_OtherShift)) << ")\n"; + } sb << "struct "; sb << kBaseTextureAccessLevels[accessLevel].name; - sb << name; + sb << baseName; + sb << baseShapeName; if (isMultisample) sb << "MS"; if (isArray) sb << "Array"; // if (isShadow) sb << "Shadow"; sb << "\n{"; + char const* samplerStateParam = prefixInfo.combined ? "" : "SamplerState s, "; + if( !isMultisample ) { - sb << "float CalculateLevelOfDetail(SamplerState s, "; + sb << "float CalculateLevelOfDetail(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n"; - sb << "float CalculateLevelOfDetailUnclamped(SamplerState s, "; + sb << "float CalculateLevelOfDetailUnclamped(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n"; } @@ -1235,18 +1188,18 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) } } - sb << "T Sample(SamplerState s, "; + sb << "T Sample(" << samplerStateParam;; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n"; if( baseShape != TextureFlavor::Shape::ShapeCube ) { sb << "__target_intrinsic(glsl, \"$ctextureOffset($p, $2, $3)$z\")\n"; - sb << "T Sample(SamplerState s, "; + sb << "T Sample(" << samplerStateParam;; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; } - sb << "T Sample(SamplerState s, "; + sb << "T Sample(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; if( baseShape != TextureFlavor::Shape::ShapeCube ) { @@ -1254,7 +1207,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) } sb << "float clamp);\n"; - sb << "T Sample(SamplerState s, "; + sb << "T Sample(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; if( baseShape != TextureFlavor::Shape::ShapeCube ) { @@ -1264,13 +1217,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) // `SampleBias()` sb << "__target_intrinsic(glsl, \"$ctexture($p, $2, $3)$z\")\n"; - sb << "T SampleBias(SamplerState s, "; + sb << "T SampleBias(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n"; if( baseShape != TextureFlavor::Shape::ShapeCube ) { sb << "__target_intrinsic(glsl, \"$ctextureOffset($p, $2, $3, $4)$z\")\n"; - sb << "T SampleBias(SamplerState s, "; + sb << "T SampleBias(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, "; sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; } @@ -1355,7 +1308,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) // the dimension. On CUDA there is texNDGrad, but it always just takes ddx, ddy. // I could just assume 0 for elements not supplied, and ignore z. For now will just leave sb << "__target_intrinsic(glsl, \"$ctextureGrad($p, $2, $3, $4)$z\")\n"; - sb << "T SampleGrad(SamplerState s, "; + sb << "T SampleGrad(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, "; sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY"; @@ -1364,7 +1317,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) if( baseShape != TextureFlavor::Shape::ShapeCube ) { sb << "__target_intrinsic(glsl, \"$ctextureGradOffset($p, $2, $3, $4, $5)$z\")\n"; - sb << "T SampleGrad(SamplerState s, "; + sb << "T SampleGrad(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, "; sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, "; @@ -1372,7 +1325,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) sb << "__glsl_extension(GL_ARB_sparse_texture_clamp)"; sb << "__target_intrinsic(glsl, \"$ctextureGradOffsetClampARB($p, $2, $3, $4, $5, $6)$z\")\n"; - sb << "T SampleGrad(SamplerState s, "; + sb << "T SampleGrad(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, "; sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, "; @@ -1428,14 +1381,14 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) } } - sb << "T SampleLevel(SamplerState s, "; + sb << "T SampleLevel(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "float level);\n"; if( baseShape != TextureFlavor::Shape::ShapeCube ) { sb << "__target_intrinsic(glsl, \"$ctextureLodOffset($p, $2, $3, $4)$z\")\n"; - sb << "T SampleLevel(SamplerState s, "; + sb << "T SampleLevel(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "float level, "; sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; @@ -1474,7 +1427,8 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) EMIT_LINE_DIRECTIVE(); sb << cc.genericPrefix << " __extension "; sb << kBaseTextureAccessLevels[accessLevel].name; - sb << name; + sb << baseName; + sb << baseShapeName; if (isArray) sb << "Array"; sb << "<" << cc.elementType << " >"; sb << "\n{\n"; @@ -1513,24 +1467,24 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) // "It is based on the base type of DataType except when readMode is equal to cudaReadModeNormalizedFloat (see Texture Reference API), in which case it is always float4." sb << "__target_intrinsic(cuda, \"tex2Dgather<$T0>($0, ($2).x, ($2).y, " << componentIndex << ")\")\n"; } - sb << outputType << " Gather" << componentName << "(SamplerState s, "; + sb << outputType << " Gather" << componentName << "(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n"; EMIT_LINE_DIRECTIVE(); sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $2, $3, " << componentIndex << ")\")\n"; - sb << outputType << " Gather" << componentName << "(SamplerState s, "; + sb << outputType << " Gather" << componentName << "(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; EMIT_LINE_DIRECTIVE(); - sb << outputType << " Gather" << componentName << "(SamplerState s, "; + sb << outputType << " Gather" << componentName << "(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset, "; sb << "out uint status);\n"; EMIT_LINE_DIRECTIVE(); sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $2, int" << kBaseTextureTypes[tt].coordCount << "[]($3, $4, $5, $6), " << componentIndex << ")\")\n"; - sb << outputType << " Gather" << componentName << "(SamplerState s, "; + sb << outputType << " Gather" << componentName << "(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, "; sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, "; @@ -1538,7 +1492,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4);\n"; EMIT_LINE_DIRECTIVE(); - sb << outputType << " Gather" << componentName << "(SamplerState s, "; + sb << outputType << " Gather" << componentName << "(" << samplerStateParam; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, "; sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, "; diff --git a/source/slang/slang-intrinsic-expand.cpp b/source/slang/slang-intrinsic-expand.cpp index 045b7e6c5..b494e71e1 100644 --- a/source/slang/slang-intrinsic-expand.cpp +++ b/source/slang/slang-intrinsic-expand.cpp @@ -228,7 +228,7 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) case '5': case '6': case '7': case '8': case '9': { // Simple case: emit one of the direct arguments to the call - Index argIndex = d - '0'; + Index argIndex = d - '0' + m_argIndexOffset; SLANG_RELEASE_ASSERT((0 <= argIndex) && (argIndex < m_argCount)); m_writer->emit("("); m_emitter->emitOperand(m_args[argIndex].get(), getInfo(EmitOp::General)); @@ -241,7 +241,7 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) // Get the type/value at the index of the specialization of this generic SLANG_RELEASE_ASSERT(*cursor >= '0' && *cursor <= '9'); - Index argIndex = (*cursor++) - '0'; + Index argIndex = (*cursor++) - '0' + m_argIndexOffset; IRSpecialize* specialize = as<IRSpecialize>(m_callInst->getCallee()); SLANG_ASSERT(specialize); @@ -269,7 +269,7 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) // Get the the 'element' type for the type of the param at the index { SLANG_RELEASE_ASSERT(*cursor >= '0' && *cursor <= '9'); - Index argIndex = (*cursor++) - '0'; + Index argIndex = (*cursor++) - '0' + m_argIndexOffset; SLANG_RELEASE_ASSERT(m_argCount > argIndex); IRType* type = m_args[argIndex].get()->getDataType(); @@ -285,7 +285,7 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) // Get the scalar type of a generic at specified index { SLANG_RELEASE_ASSERT(*cursor >= '0' && *cursor <= '9'); - Index argIndex = (*cursor++) - '0'; + Index argIndex = (*cursor++) - '0' + m_argIndexOffset; SLANG_RELEASE_ASSERT(m_argCount > argIndex); IRType* type = m_args[argIndex].get()->getDataType(); @@ -318,15 +318,37 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) // If we are calling a D3D texturing operation in the form t.Foo(s, ...), // then this form will pair up the t and s arguments as needed for a GLSL // texturing operation. - SLANG_RELEASE_ASSERT(m_argCount >= 2); + SLANG_RELEASE_ASSERT(m_argCount >= 1); auto textureArg = m_args[0].get(); - auto samplerArg = m_args[1].get(); - if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType())) + if (auto baseTextureSamplerType = as<IRTextureSamplerType>(textureArg->getDataType())) { - m_emitter->emitTextureOrTextureSamplerType(baseTextureType, "sampler"); + // If the base object (first argument) has a combined texture-sampler type, + // then we can simply use that argument as-is. + // + m_emitter->emitOperand(textureArg, getInfo(EmitOp::General)); + + // HACK: Because the target intrinsic strings are using indices based on the + // parameter list with the `SamplerState` parameter in place, seeing this opcode + // and this type tells us that we are about to have an off-by-one sort of + // situation. We quietly patch it up by offseting the index-based access for + // all the other operands. + // + m_argIndexOffset -= 1; + } + else if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType())) + { + // If the base object (first argument) has a texture type, then we expect + // the next argument to be a sampler to pair with it. + // + SLANG_RELEASE_ASSERT(m_argCount >= 2); + auto samplerArg = m_args[1].get(); + // We will emit GLSL code to construct the corresponding combined texture/sampler + // type from the separate pieces. + // + m_emitter->emitTextureOrTextureSamplerType(baseTextureType, "sampler"); if (auto samplerType = as<IRSamplerStateTypeBase>(samplerArg->getDataType())) { if (as<IRSamplerComparisonStateType>(samplerType)) @@ -462,32 +484,41 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) SLANG_RELEASE_ASSERT(m_argCount >= 1); auto textureArg = m_args[0].get(); + IRType* elementType = nullptr; + if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType())) { - auto elementType = baseTextureType->getElementType(); - if (auto basicType = as<IRBasicType>(elementType)) - { - // A scalar result is expected - m_writer->emit(".x"); - } - else if (auto vectorType = as<IRVectorType>(elementType)) - { - // A vector result is expected - auto elementCount = getIntVal(vectorType->getElementCount()); + elementType = baseTextureType->getElementType(); + } + else if(auto baseTextureSamplerType = as<IRTextureSamplerType>(textureArg->getDataType())) + { + elementType = baseTextureSamplerType->getElementType(); + } + else + { + SLANG_UNEXPECTED("bad format in intrinsic definition"); + } - if (elementCount < 4) - { - char const* swiz[] = { "", ".x", ".xy", ".xyz", "" }; - m_writer->emit(swiz[elementCount]); - } - } - else + SLANG_ASSERT(elementType); + if (auto basicType = as<IRBasicType>(elementType)) + { + // A scalar result is expected + m_writer->emit(".x"); + } + else if (auto vectorType = as<IRVectorType>(elementType)) + { + // A vector result is expected + auto elementCount = getIntVal(vectorType->getElementCount()); + + if (elementCount < 4) { - // What other cases are possible? + char const* swiz[] = { "", ".x", ".xy", ".xyz", "" }; + m_writer->emit(swiz[elementCount]); } } else { + // What other cases are possible? SLANG_UNEXPECTED("bad format in intrinsic definition"); } } @@ -499,7 +530,7 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) // we can use it in the constructed expression. SLANG_RELEASE_ASSERT(*cursor >= '0' && *cursor <= '9'); - Index argIndex = (*cursor++) - '0'; + Index argIndex = (*cursor++) - '0' + m_argIndexOffset; SLANG_RELEASE_ASSERT(m_argCount > argIndex); auto vectorArg = m_args[argIndex].get(); @@ -522,7 +553,7 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) // (this is the inverse of `$z`). // SLANG_RELEASE_ASSERT(*cursor >= '0' && *cursor <= '9'); - Index argIndex = (*cursor++) - '0'; + Index argIndex = (*cursor++) - '0' + m_argIndexOffset; SLANG_RELEASE_ASSERT(m_argCount > argIndex); auto arg = m_args[argIndex].get(); diff --git a/source/slang/slang-intrinsic-expand.h b/source/slang/slang-intrinsic-expand.h index b52e3e8f5..cf072e3f4 100644 --- a/source/slang/slang-intrinsic-expand.h +++ b/source/slang/slang-intrinsic-expand.h @@ -29,6 +29,26 @@ protected: Int m_argCount = 0; Index m_openParenCount = 0; CLikeSourceEmitter* m_emitter; + + // An arbitrary offset to apply to argument indices. + // + // Note: This is a bit of a gross hack to allow the definitions + // of the texture-sampling operations to be easier to share + // between combined and non-combined cases. + // + // TODO: It would be great to slowly migrate away from needing + // so much complicated logic here, but if we decide to keep this + // general approach it would be great to move some of the processing + // to the front-end and allow things like: + // + // __target_intrinsic(hlsl, "specialOp($a - $b)") + // int SomeCoolFunction(int a, int b); + // + // That is, we could try to allow direct by-name references to parameters + // in the intrinsic strings as they appear in the front-end, and then remap + // those to be index-based as part of translation to the IR. + // + Index m_argIndexOffset = 0; }; } diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp index 00ecfdbc1..17ceb6842 100644 --- a/source/slang/slang-reflection-api.cpp +++ b/source/slang/slang-reflection-api.cpp @@ -1231,7 +1231,11 @@ namespace Slang SlangBindingType _calcResourceBindingType( Type* type) { - if( auto resourceType = as<ResourceType>(type) ) + if(auto combinedTextureSamplerType = as<TextureSamplerType>(type)) + { + return SLANG_BINDING_TYPE_COMBINED_TEXTURE_SAMPLER; + } + else if( auto resourceType = as<ResourceType>(type) ) { auto shape = resourceType->getBaseShape(); @@ -1246,7 +1250,6 @@ namespace Slang case SLANG_TEXTURE_BUFFER: return SLANG_BINDING_TYPE_TYPED_BUFFER | mutableFlag; } - } else if( auto structuredBufferType = as<HLSLStructuredBufferTypeBase>(type) ) { diff --git a/tests/type/texture-sampler/texture-sampler-2d.slang b/tests/type/texture-sampler/texture-sampler-2d.slang new file mode 100644 index 000000000..974231b9b --- /dev/null +++ b/tests/type/texture-sampler/texture-sampler-2d.slang @@ -0,0 +1,20 @@ +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj + +//TEST_INPUT: TextureSampler2D(size=4, content=one):name t2D +Sampler2D<float> t2D; + +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer<float> outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int idx = dispatchThreadID.x; + float u = idx * (1.0f / 4); + + float val = 0.0f; + + val += t2D.SampleLevel(float2(u, u), 0); + + outputBuffer[idx] = val; +} diff --git a/tests/type/texture-sampler/texture-sampler-2d.slang.expected.txt b/tests/type/texture-sampler/texture-sampler-2d.slang.expected.txt new file mode 100644 index 000000000..cc5e55ab6 --- /dev/null +++ b/tests/type/texture-sampler/texture-sampler-2d.slang.expected.txt @@ -0,0 +1,4 @@ +3F800000 +3F800000 +3F800000 +3F800000 diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp index 11356a29a..c55c10d3e 100644 --- a/tools/render-test/shader-input-layout.cpp +++ b/tools/render-test/shader-input-layout.cpp @@ -146,6 +146,16 @@ namespace renderer_test return SLANG_OK; } + + SlangResult parseOption(Misc::TokenReader& parser, String const& word, ShaderInputLayout::CombinedTextureSamplerVal* val) + { + auto result = parseOption(parser, word, val->textureVal); + if(SLANG_SUCCEEDED(result)) return result; + + result = parseOption(parser, word, val->samplerVal); + return result; + } + SlangResult parseOption(Misc::TokenReader& parser, String const& word, ShaderInputLayout::DataValBase* val) { if (word == "data") @@ -673,10 +683,43 @@ namespace renderer_test maybeParseOptions(parser, val.Ptr()); return val; } - // TODO: We can include combined texture/sampler cases - // here, but we don't really have tests for them and - // it might be better to save it for a point where - // we support hierarchical binding values more directly. + else if (parser.AdvanceIf("TextureSampler1D")) + { + RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = new ShaderInputLayout::CombinedTextureSamplerVal; + val->textureVal = new ShaderInputLayout::TextureVal; + val->samplerVal = new ShaderInputLayout::SamplerVal; + val->textureVal->textureDesc.dimension = 1; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("TextureSampler2D")) + { + RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = new ShaderInputLayout::CombinedTextureSamplerVal; + val->textureVal = new ShaderInputLayout::TextureVal; + val->samplerVal = new ShaderInputLayout::SamplerVal; + val->textureVal->textureDesc.dimension = 2; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("TextureSampler3D")) + { + RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = new ShaderInputLayout::CombinedTextureSamplerVal; + val->textureVal = new ShaderInputLayout::TextureVal; + val->samplerVal = new ShaderInputLayout::SamplerVal; + val->textureVal->textureDesc.dimension = 3; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("TextureSamplerCube")) + { + RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = new ShaderInputLayout::CombinedTextureSamplerVal; + val->textureVal = new ShaderInputLayout::TextureVal; + val->samplerVal = new ShaderInputLayout::SamplerVal; + val->textureVal->textureDesc.dimension = 2; + val->textureVal->textureDesc.isCube = true; + maybeParseOptions(parser, val.Ptr()); + return val; + } else { throw ShaderInputLayoutFormatException(String("Unknown shader input type '") + word + String("' at line") + String(parser.NextToken().Position.Line)); |
