diff options
21 files changed, 571 insertions, 11 deletions
diff --git a/docs/command-line-slangc-reference.md b/docs/command-line-slangc-reference.md Binary files differindex 3e25cdce6..b7cef7a53 100644 --- a/docs/command-line-slangc-reference.md +++ b/docs/command-line-slangc-reference.md diff --git a/include/slang.h b/include/slang.h index ea62a829f..8f4d53a0d 100644 --- a/include/slang.h +++ b/include/slang.h @@ -958,6 +958,7 @@ extern "C" // precompiled modules if it is up-to-date with its source. EmbedDXIL, // bool + ForceDXLayout, // bool CountOf, }; @@ -4837,6 +4838,8 @@ namespace slang virtual SLANG_NO_THROW void SLANG_MCALL setTargetEmbedDXIL( int targetIndex, bool value) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceDXLayout(int targetIndex, bool value) = 0; }; #define SLANG_UUID_ICompileRequest ICompileRequest::getTypeGuid() diff --git a/source/slang-record-replay/util/emum-to-string.h b/source/slang-record-replay/util/emum-to-string.h index f06631719..3c7568818 100644 --- a/source/slang-record-replay/util/emum-to-string.h +++ b/source/slang-record-replay/util/emum-to-string.h @@ -175,6 +175,7 @@ namespace SlangRecord CASE(VulkanUseGLLayout); CASE(VulkanEmitReflection); CASE(GLSLForceScalarLayout); + CASE(ForceDXLayout); CASE(EnableEffectAnnotations); CASE(EmitSpirvViaGLSL); CASE(EmitSpirvDirectly); diff --git a/source/slang/slang-compiler-options.cpp b/source/slang/slang-compiler-options.cpp index ea2593713..3325a313a 100644 --- a/source/slang/slang-compiler-options.cpp +++ b/source/slang/slang-compiler-options.cpp @@ -110,6 +110,7 @@ namespace Slang break; case CompilerOptionName::EmitSpirvDirectly: case CompilerOptionName::GLSLForceScalarLayout: + case CompilerOptionName::ForceDXLayout: case CompilerOptionName::MatrixLayoutRow: case CompilerOptionName::MatrixLayoutColumn: case CompilerOptionName::VulkanInvertY: diff --git a/source/slang/slang-compiler-options.h b/source/slang/slang-compiler-options.h index dae6d49e5..f2bf467e2 100644 --- a/source/slang/slang-compiler-options.h +++ b/source/slang/slang-compiler-options.h @@ -346,6 +346,11 @@ namespace Slang return getBoolOption(CompilerOptionName::GLSLForceScalarLayout); } + bool shouldUseDXLayout() + { + return getBoolOption(CompilerOptionName::ForceDXLayout); + } + bool shouldDumpIntermediates() { return getBoolOption(CompilerOptionName::DumpIntermediates); diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index ac85f175e..5ebefb888 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -2807,6 +2807,7 @@ namespace Slang virtual SLANG_NO_THROW void SLANG_MCALL setTargetFloatingPointMode(int targetIndex, SlangFloatingPointMode mode) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setTargetMatrixLayoutMode(int targetIndex, SlangMatrixLayoutMode mode) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceGLSLScalarBufferLayout(int targetIndex, bool value) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceDXLayout(int targetIndex, bool value) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setTargetGenerateWholeProgram(int targetIndex, bool value) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setTargetEmbedDXIL(int targetIndex, bool value) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setMatrixLayoutMode(SlangMatrixLayoutMode mode) SLANG_OVERRIDE; diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 20cbbac02..8f4501c2b 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -3993,7 +3993,7 @@ struct SPIRVEmitContext auto rule = IRTypeLayoutRules::get(layoutRuleName); IRSizeAndAlignment elementSizeAlignment; getSizeAndAlignment(m_targetProgram->getOptionSet(), rule, matrixType->getElementType(), &elementSizeAlignment); - + IRIntegerValue matrixMinorVectorCount = 0; // Reminder: the meaning of row/column major layout // in our semantics is the *opposite* of what GLSL/SPIRV // calls them, because what they call "columns" @@ -4007,10 +4007,7 @@ struct SPIRVEmitContext spvStructID, SpvLiteralInteger::from32(id), SpvDecorationRowMajor); - - auto vectorSize = rule->getVectorSizeAndAlignment(elementSizeAlignment, getIntVal(matrixType->getRowCount())); - vectorSize = rule->alignCompositeElement(vectorSize); - matrixStride = vectorSize.getStride(); + matrixMinorVectorCount = getIntVal(matrixType->getRowCount()); } else { @@ -4020,12 +4017,15 @@ struct SPIRVEmitContext spvStructID, SpvLiteralInteger::from32(id), SpvDecorationColMajor); - - auto vectorSize = rule->getVectorSizeAndAlignment(elementSizeAlignment, getIntVal(matrixType->getColumnCount())); - vectorSize = rule->alignCompositeElement(vectorSize); - matrixStride = vectorSize.getStride(); + matrixMinorVectorCount = getIntVal(matrixType->getColumnCount()); } + // We need the size of our vector. To get the stride we need to know how 'big' + // each vector element is inside an array, due to this we align our vector + // as if a composite. + auto vectorSize = rule->getVectorSizeAndAlignment(elementSizeAlignment, matrixMinorVectorCount); + vectorSize = rule->alignCompositeElement(vectorSize); + matrixStride = vectorSize.getStride(); emitOpMemberDecorateMatrixStride( getSection(SpvLogicalSectionID::Annotations), nullptr, diff --git a/source/slang/slang-ir-layout.cpp b/source/slang/slang-ir-layout.cpp index 6a4e9360a..3a2471930 100644 --- a/source/slang/slang-ir-layout.cpp +++ b/source/slang/slang-ir-layout.cpp @@ -443,6 +443,33 @@ struct NaturalLayoutRules : IRTypeLayoutRules } }; +struct ConstantBufferLayoutRules : IRTypeLayoutRules +{ + ConstantBufferLayoutRules() + { + ruleName = IRTypeLayoutRuleName::D3DConstantBuffer; + } + + /// Next member only aligns to 16 if the next member is an array/matrix/struct + virtual IRSizeAndAlignment alignCompositeElement(IRSizeAndAlignment currentSize) + { + // Matrix/Array/Struct should be aligned on a new register + return IRSizeAndAlignment(currentSize.size, 16); + } + + virtual IRIntegerValue adjustOffsetForNextAggregateMember(IRIntegerValue currentSize, IRIntegerValue lastElementAlignment) + { + SLANG_UNUSED(lastElementAlignment); + return currentSize; + } + + virtual IRSizeAndAlignment getVectorSizeAndAlignment(IRSizeAndAlignment element, IRIntegerValue count) + { + IRIntegerValue countForAlignment = count; + return IRSizeAndAlignment((int)(element.size * count), (int)(element.size * countForAlignment)); + } +}; + struct Std430LayoutRules : IRTypeLayoutRules { Std430LayoutRules() @@ -534,6 +561,13 @@ IRTypeLayoutRules* IRTypeLayoutRules::getNatural() static NaturalLayoutRules rules; return &rules; } + +IRTypeLayoutRules* IRTypeLayoutRules::getConstantBuffer() +{ + static ConstantBufferLayoutRules rules; + return &rules; +} + IRTypeLayoutRules* IRTypeLayoutRules::get(IRTypeLayoutRuleName name) { switch (name) @@ -541,6 +575,7 @@ IRTypeLayoutRules* IRTypeLayoutRules::get(IRTypeLayoutRuleName name) case IRTypeLayoutRuleName::Std430: return getStd430(); case IRTypeLayoutRuleName::Std140: return getStd140(); case IRTypeLayoutRuleName::Natural: return getNatural(); + case IRTypeLayoutRuleName::D3DConstantBuffer: return getConstantBuffer(); default: return nullptr; } } diff --git a/source/slang/slang-ir-layout.h b/source/slang/slang-ir-layout.h index 09da2a8f9..c7e5d2b31 100644 --- a/source/slang/slang-ir-layout.h +++ b/source/slang/slang-ir-layout.h @@ -58,12 +58,19 @@ struct IRTypeLayoutRules { public: IRTypeLayoutRuleName ruleName; + + /// Align composite based on rule. Type is aligned assuming + /// it is apart of a composite (array, struct, matrix, etc...) virtual IRSizeAndAlignment alignCompositeElement(IRSizeAndAlignment elementSize) = 0; + + /// Get alignment and size of a vector given components of vector. + /// This alignment is not assuming this vector is a member of a struct. virtual IRSizeAndAlignment getVectorSizeAndAlignment(IRSizeAndAlignment element, IRIntegerValue count) = 0; virtual IRIntegerValue adjustOffsetForNextAggregateMember(IRIntegerValue currentSize, IRIntegerValue lastElementAlignment) = 0; static IRTypeLayoutRules* getStd430(); static IRTypeLayoutRules* getStd140(); static IRTypeLayoutRules* getNatural(); + static IRTypeLayoutRules* getConstantBuffer(); static IRTypeLayoutRules* get(IRTypeLayoutRuleName name); }; diff --git a/source/slang/slang-ir-lower-buffer-element-type.cpp b/source/slang/slang-ir-lower-buffer-element-type.cpp index cc24a0e81..a480ae673 100644 --- a/source/slang/slang-ir-lower-buffer-element-type.cpp +++ b/source/slang/slang-ir-lower-buffer-element-type.cpp @@ -899,6 +899,16 @@ namespace Slang if (target->getOptionSet().shouldUseScalarLayout()) return IRTypeLayoutRules::getNatural(); + if (target->getOptionSet().shouldUseDXLayout()) + { + if (as<IRUniformParameterGroupType>(bufferType)) + { + return IRTypeLayoutRules::getConstantBuffer(); + } + else + return IRTypeLayoutRules::getNatural(); + } + // The default behavior is to use std140 for constant buffers and std430 for other buffers. switch (bufferType->getOp()) { diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h index 4a3a04404..036c7f3a7 100644 --- a/source/slang/slang-ir.h +++ b/source/slang/slang-ir.h @@ -564,6 +564,7 @@ enum class IRTypeLayoutRuleName Scalar = Natural, Std430, Std140, + D3DConstantBuffer, _Count, }; diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 33103442d..12b32998f 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -400,6 +400,7 @@ void initCommandOptions(CommandOptions& options) { OptionKind::GLSLForceScalarLayout, "-force-glsl-scalar-layout,-fvk-use-scalar-layout", nullptr, "Make data accessed through ConstantBuffer, ParameterBlock, StructuredBuffer, ByteAddressBuffer and general pointers follow the 'scalar' layout when targeting GLSL or SPIRV."}, + { OptionKind::ForceDXLayout, "-fvk-use-dx-layout", nullptr, "Pack members using FXCs member packing rules when targeting GLSL or SPIRV." }, { OptionKind::VulkanBindShift, vkShiftNames.getBuffer(), "-fvk-<vulkan-shift>-shift <N> <space>", "For example '-fvk-b-shift <N> <space>' shifts by N the inferred binding numbers for all resources in 'b' registers of space <space>. " "For a resource attached with :register(bX, <space>) but not [vk::binding(...)], " @@ -2054,6 +2055,11 @@ SlangResult OptionsParser::_parse( getCurrentTarget()->optionSet.add(CompilerOptionName::GLSLForceScalarLayout, true); break; } + case OptionKind::ForceDXLayout: + { + getCurrentTarget()->optionSet.add(CompilerOptionName::ForceDXLayout, true); + break; + } case OptionKind::EnableEffectAnnotations: { m_compileRequest->setEnableEffectAnnotations(true); @@ -2780,6 +2786,11 @@ SlangResult OptionsParser::_parse( m_compileRequest->setTargetForceGLSLScalarBufferLayout(targetID, true); } + if (rawTarget.optionSet.shouldUseDXLayout()) + { + m_compileRequest->setTargetForceDXLayout(targetID, true); + } + if (rawTarget.optionSet.getBoolOption(CompilerOptionName::GenerateWholeProgram)) { m_compileRequest->setTargetGenerateWholeProgram(targetID, true); diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index f5fbfafdf..7d6d047d3 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -400,6 +400,12 @@ struct HLSLConstantBufferLayoutRulesImpl : DefaultLayoutRulesImpl } }; +/// GLSL fvk-use-dx-layout for `ShaderResource` +struct FXCShaderResourceLayoutRulesImpl : DefaultLayoutRulesImpl +{ + // Currently this FXC layout is equal to how we compute 'DefaultLayoutRulesImpl' +}; + /* CPU layout requires that all sizes are a multiple of alignment. */ struct CPULayoutRulesImpl : DefaultLayoutRulesImpl @@ -894,6 +900,7 @@ struct CUDARayTracingLayoutRulesImpl : DefaultVaryingLayoutRulesImpl DefaultLayoutRulesImpl kDefaultLayoutRulesImpl; Std140LayoutRulesImpl kStd140LayoutRulesImpl; Std430LayoutRulesImpl kStd430LayoutRulesImpl; +FXCShaderResourceLayoutRulesImpl kFXCShaderResourceLayoutRulesImpl; HLSLConstantBufferLayoutRulesImpl kHLSLConstantBufferLayoutRulesImpl; HLSLStructuredBufferLayoutRulesImpl kHLSLStructuredBufferLayoutRulesImpl; @@ -1206,6 +1213,18 @@ LayoutRulesImpl kScalarLayoutRulesImpl_ = { &kGLSLObjectLayoutRulesImpl, }; +LayoutRulesImpl kFXCShaderResourceLayoutRulesFamilyImpl = { + &kGLSLLayoutRulesFamilyImpl, + &kFXCShaderResourceLayoutRulesImpl, + &kGLSLObjectLayoutRulesImpl, +}; + +LayoutRulesImpl kFXCConstantBufferLayoutRulesFamilyImpl = { + &kGLSLLayoutRulesFamilyImpl, + &kHLSLConstantBufferLayoutRulesImpl, + &kGLSLObjectLayoutRulesImpl, +}; + LayoutRulesImpl kGLSLAnyValueLayoutRulesImpl_ = { &kGLSLLayoutRulesFamilyImpl, &kDefaultLayoutRulesImpl, @@ -1300,6 +1319,9 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptio { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseDXLayout()) + return &kFXCConstantBufferLayoutRulesFamilyImpl; + return &kStd140LayoutRulesImpl_; } @@ -1307,6 +1329,9 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getParameterBlockRules(CompilerOptio { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseDXLayout()) + return &kFXCConstantBufferLayoutRulesFamilyImpl; + return &kStd140LayoutRulesImpl_; } @@ -1324,6 +1349,9 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getTextureBufferRules(CompilerOption { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseDXLayout()) + return &kFXCConstantBufferLayoutRulesFamilyImpl; + return &kStd430LayoutRulesImpl_; } @@ -1347,6 +1375,9 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getShaderStorageBufferRules(Compiler { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseDXLayout()) + return &kFXCShaderResourceLayoutRulesFamilyImpl; + return &kStd430LayoutRulesImpl_; } @@ -1365,10 +1396,13 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getHitAttributesParameterRules() return &kGLSLHitAttributesParameterLayoutRulesImpl_; } -LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getStructuredBufferRules(CompilerOptionSet& options) +LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getStructuredBufferRules(CompilerOptionSet& compilerOptions) { - if (options.shouldUseScalarLayout()) + if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; + else if (compilerOptions.shouldUseDXLayout()) + return &kFXCShaderResourceLayoutRulesFamilyImpl; + return &kGLSLStructuredBufferLayoutRulesImpl_; } diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index f08a6fc44..3072ef0a7 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -5854,6 +5854,11 @@ void EndToEndCompileRequest::setTargetForceGLSLScalarBufferLayout(int targetInde getTargetOptionSet(targetIndex).set(CompilerOptionName::GLSLForceScalarLayout, value); } +void EndToEndCompileRequest::setTargetForceDXLayout(int targetIndex, bool value) +{ + getTargetOptionSet(targetIndex).set(CompilerOptionName::ForceDXLayout, value); +} + void EndToEndCompileRequest::setTargetFloatingPointMode(int targetIndex, SlangFloatingPointMode mode) { getTargetOptionSet(targetIndex).set(CompilerOptionName::FloatingPointMode, FloatingPointMode(mode)); diff --git a/tests/spirv/cbuffer-dx-layout-1.slang b/tests/spirv/cbuffer-dx-layout-1.slang new file mode 100644 index 000000000..35d528bda --- /dev/null +++ b/tests/spirv/cbuffer-dx-layout-1.slang @@ -0,0 +1,76 @@ +//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -xslang -fvk-use-dx-layout -emit-spirv-directly +//TEST:SIMPLE(filecheck=SPIRV): -target spirv -entry computeMain -stage compute -fvk-use-dx-layout +//TEST_INPUT:cbuffer(data=[1 2.0 3.0 4.0 5 6 7 0 8 9 10 11 12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0 16 17 18 0 19 20 21 22 23 24 0 0 25 0 0 0 26 0 0 0]):name=Test + +//SPIRV: ArrayStride 16 + +cbuffer Test +{ +//SPIRV: Offset 0 + uint v0; +//SPIRV: Offset 4 + float3 v1; + +//SPIRV: Offset 16 + uint3 v2; + +//SPIRV: Offset 32 + uint2 v3; +//SPIRV: Offset 40 + uint2 v4; + +//SPIRV: Offset 48 + uint v5[4]; + +// array always starts on a new register. +//SPIRV: Offset 112 + uint3 v6[2]; +//SPIRV: Offset 140 +// non-array can pack with a partially filled register + uint v7; + +//SPIRV: Offset 144 + uint2 v8; + +// SPIRV: Offset 160 +// array always starts on a new register. + uint v9[2]; +}; + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +__generic<T : IArithmetic, let N : int> +bool comp(vector<T,N> v1, vector<T,N> v2) +{ + for (uint i = 0; i < N; i++) + if (v1[i] != v2[i]) + return false; + + return true; +} + +[shader("compute")] +[numthreads(2, 2, 1)] +void computeMain() +{ + // CHECK: 64 + + outputBuffer[0] = (true + && v0 == 1 + && comp(v1, float3(2, 3, 4)) + && comp(v2, uint3(5, 6, 7)) + && comp(v3, uint2(8, 9)) + && comp(v4, uint2(10, 11)) + && v5[0] == 12 + && v5[1] == 13 + && v5[2] == 14 + && v5[3] == 15 + && comp(v6[0], uint3(16, 17, 18)) + && comp(v6[1], uint3(19, 20, 21)) + && v7 == 22 + && comp(v8, uint2(23, 24)) + && v9[0] == 25 + && v9[1] == 26 + ) ? 100 : 0; +}
\ No newline at end of file diff --git a/tests/spirv/cbuffer-dx-layout-2.slang b/tests/spirv/cbuffer-dx-layout-2.slang new file mode 100644 index 000000000..19bc6ea9e --- /dev/null +++ b/tests/spirv/cbuffer-dx-layout-2.slang @@ -0,0 +1,86 @@ +//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -xslang -fvk-use-dx-layout -emit-spirv-directly +//TEST:SIMPLE(filecheck=SPIRV): -target spirv -entry computeMain -stage compute -fvk-use-dx-layout +//TEST_INPUT: set Test.v0 = 1; +//TEST_INPUT: set Test.v1 = {2.0,3.0,4.0}; +//TEST_INPUT: set Test.v2 = {5,6,7}; +//TEST_INPUT: set Test.v3 = {8,9}; +//TEST_INPUT: set Test.v4 = {10,11}; +//TEST_INPUT: set Test.v5 = {12,13,14,15}; +//TEST_INPUT: set Test.v6 = {{16,17,18}, {19,20,21}}; +//TEST_INPUT: set Test.v6 = {{16,17,18}, {19,20,21}}; +//TEST_INPUT: set Test.v7 = 22; +//TEST_INPUT: set Test.v8 = {23,24}; +//TEST_INPUT: set Test.v9 = {25,26}; + +//SPIRV_DX: ArrayStride 16 + +cbuffer Test +{ +//SPIRV: Offset 0 + uint v0; +//SPIRV: Offset 4 + float3 v1; + +//SPIRV: Offset 16 + uint3 v2; + +//SPIRV: Offset 32 + uint2 v3; +//SPIRV: Offset 40 + uint2 v4; + +//SPIRV: Offset 48 + uint v5[4]; + +//SPIRV: Offset 112 +// Array always starts on a new register. + uint3 v6[2]; +//SPIRV: Offset 140 +// Non-array can pack with a partially filled register + uint v7; + +//SPIRV: Offset 144 + uint2 v8; + +// SPIRV: Offset 160 +// Array always starts on a new register. + uint v9[2]; +}; + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +__generic<T : IArithmetic, let N : int> +bool comp(vector<T,N> v1, vector<T,N> v2) +{ + for (uint i = 0; i < N; i++) + if (v1[i] != v2[i]) + return false; + + return true; +} + +[shader("compute")] +[numthreads(2, 2, 1)] +void computeMain() +{ + // CHECK: 64 + + outputBuffer[0] = (true + && v0 == 1 + && comp(v1, float3(2, 3, 4)) + && comp(v2, uint3(5, 6, 7)) + && comp(v3, uint2(8, 9)) + && comp(v4, uint2(10, 11)) + && v5[0] == 12 + && v5[1] == 13 + && v5[2] == 14 + && v5[3] == 15 + && comp(v6[0], uint3(16, 17, 18)) + && comp(v6[1], uint3(19, 20, 21)) + && v7 == 22 + && comp(v8, uint2(23, 24)) + && v9[0] == 25 + && v9[1] == 26 + ) ? 100 : 0; +}
\ No newline at end of file diff --git a/tests/spirv/cbuffer-dx-layout-3.slang b/tests/spirv/cbuffer-dx-layout-3.slang new file mode 100644 index 000000000..e05cd25f1 --- /dev/null +++ b/tests/spirv/cbuffer-dx-layout-3.slang @@ -0,0 +1,46 @@ +//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -xslang -fvk-use-dx-layout -emit-spirv-directly +//TEST:SIMPLE(filecheck=SPIRV): -target spirv -entry computeMain -stage compute -fvk-use-dx-layout +//TEST_INPUT:cbuffer(data=[1 0 0 0 2.0 3.0 4.0 0 5.0 6.0 7.0 0 8.0 9.0 10.0 11]):name=Test + +//SPIRV: ArrayStride 16 + +cbuffer Test +{ +//SPIRV: Offset 0 + uint v0; + +//SPIRV: Offset 16 +// matrix always start on a new register + float3x3 v1; +//SPIRV: Offset 60 +// Non-matrix can pack with a partially filled register + uint v2; +}; + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +__generic<T : IArithmetic, let N : int> +bool comp(vector<T,N> v1, vector<T,N> v2) +{ + for (uint i = 0; i < N; i++) + if (v1[i] != v2[i]) + return false; + + return true; +} + +[shader("compute")] +[numthreads(2, 2, 1)] +void computeMain() +{ + // CHECK: 64 + + outputBuffer[0] = (true + && v0 == 1 + && comp(v1[0], float3(2, 3, 4)) + && comp(v1[1], float3(5, 6, 7)) + && comp(v1[2], float3(8, 9, 10)) + && v2 == 11 + ) ? 100 : 0; +}
\ No newline at end of file diff --git a/tests/spirv/cbuffer-dx-layout-4.slang b/tests/spirv/cbuffer-dx-layout-4.slang new file mode 100644 index 000000000..c7df18e28 --- /dev/null +++ b/tests/spirv/cbuffer-dx-layout-4.slang @@ -0,0 +1,52 @@ +// For some reason CI fails this compute test by not loading data correctly +//IGNORE_TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -xslang -fvk-use-dx-layout +//TEST:SIMPLE(filecheck=SPIRV): -target spirv -entry computeMain -stage compute -fvk-use-dx-layout + +//TEST_INPUT: set Test.v0 = 1; +//TEST_INPUT: set Test.v1 = {2,3}; +//TEST_INPUT: set Test.v2 = 4; + +struct Int_wrapper +{ +//SPIRV: Offset 0 + uint v0; +//SPIRV: Offset 4 + uint v1; +}; + +cbuffer Test +{ +//SPIRV: Offset 0 + uint v0; + +//SPIRV: Offset 16 +// struct's always start on a new register + Int_wrapper v1; +//SPIRV: Offset 24 +// Non-struct can pack with a partially filled register + uint v2; +}; + +//TEST_INPUT:ubuffer(data=[0 0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +[shader("compute")] +[numthreads(2, 2, 1)] +void computeMain() +{ + // CHECK: 64 + + outputBuffer[1] = v0; + outputBuffer[2] = v1.v0; + outputBuffer[3] = v1.v1; + outputBuffer[4] = v2; + + + + outputBuffer[0] = (true + && v0 == 1 + && v1.v0 == 2 + && v1.v1 == 3 + && v2 == 4 + ) ? 100 : 0; +}
\ No newline at end of file diff --git a/tests/spirv/cbuffer-not-dx-layout.slang b/tests/spirv/cbuffer-not-dx-layout.slang new file mode 100644 index 000000000..27063188d --- /dev/null +++ b/tests/spirv/cbuffer-not-dx-layout.slang @@ -0,0 +1,56 @@ +//TEST:SIMPLE(filecheck=SPIRV): -target spirv -entry computeMain -stage compute + +cbuffer Test +{ +//SPIRV: Offset 0 + uint v0; + +//SPIRV: Offset 16 + float3 v1; + +//SPIRV: Offset 32 + uint3 v2; + +//SPIRV: Offset 48 + uint2 v3; + +//SPIRV: Offset 56 + uint2 v4; + +//SPIRV: Offset 64 + uint v5[4]; + +//SPIRV: Offset 128 + uint3 v6[2]; +}; + +RWStructuredBuffer<int> outputBuffer; + +__generic<T : IArithmetic, let N : int> +bool comp(vector<T,N> v1, vector<T,N> v2) +{ + for (uint i = 0; i < N; i++) + if (v1[i] != v2[i]) + return false; + + return true; +} + +[shader("compute")] +[numthreads(16, 16, 1)] +void computeMain() +{ + outputBuffer[0] = (true + && v0 == 1 + && comp(v1, float3( 2, 3, 4)) + && comp(v2, uint3( 5, 6, 7)) + && comp(v3, uint2( 8, 9 )) + && comp(v4, uint2( 10, 11 )) + && v5[0] == 12 + && v5[1] == 13 + && v5[2] == 14 + && v5[3] == 15 + && comp(v6[0], uint3( 16, 17, 18 )) + && comp(v6[1], uint3( 19, 20, 21 )) + ) ? 100 : 0; +}
\ No newline at end of file diff --git a/tests/spirv/structured-buffer-dx-layout.slang b/tests/spirv/structured-buffer-dx-layout.slang new file mode 100644 index 000000000..678ad758d --- /dev/null +++ b/tests/spirv/structured-buffer-dx-layout.slang @@ -0,0 +1,57 @@ +//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -xslang -fvk-use-dx-layout -emit-spirv-directly +//TEST:SIMPLE(filecheck=SPIRV): -target spirv -entry computeMain -stage compute -fvk-use-dx-layout + +struct Test_t +{ +//SPIRV: Offset 0 + uint v0; +//SPIRV: Offset 4 + float3 v1; +//SPIRV: Offset 16 + uint3 v2; +//SPIRV: Offset 28 + uint2 v3; +//SPIRV: Offset 36 + uint2 v4; +//SPIRV: Offset 44 + uint v5[4]; +//SPIRV: Offset 60 + uint3 v6[2]; +}; + +//TEST_INPUT:ubuffer(data=[1 2.0 3.0 4.0 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21], stride=4):out,name testBuffer +RWStructuredBuffer<Test_t> testBuffer; + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +__generic<T : IArithmetic, let N : int> +bool comp(vector<T,N> v1, vector<T,N> v2) +{ + for (uint i = 0; i < N; i++) + if (v1[i] != v2[i]) + return false; + + return true; +} + +[shader("compute")] +[numthreads(16, 16, 1)] +void computeMain() +{ + // CHECK: 64 + Test_t test = testBuffer[0]; + outputBuffer[0] = (true + && test.v0 == 1 + && comp(test.v1, float3( 2, 3, 4)) + && comp(test.v2, uint3( 5, 6, 7)) + && comp(test.v3, uint2( 8, 9 )) + && comp(test.v4, uint2( 10, 11 )) + && test.v5[0] == 12 + && test.v5[1] == 13 + && test.v5[2] == 14 + && test.v5[3] == 15 + && comp(test.v6[0], uint3( 16, 17, 18 )) + && comp(test.v6[1], uint3( 19, 20, 21 )) + ) ? 100 : 0; +}
\ No newline at end of file diff --git a/tests/spirv/tbuffer-dx-layout-1.slang b/tests/spirv/tbuffer-dx-layout-1.slang new file mode 100644 index 000000000..c1f494497 --- /dev/null +++ b/tests/spirv/tbuffer-dx-layout-1.slang @@ -0,0 +1,73 @@ +//IGNORE_TEST:SIMPLE(filecheck=SPIRV): -target spirv -entry computeMain -stage compute -fvk-use-dx-layout + +// 'tbuffer' is not implemented for SPIRV targets currently. + +tbuffer Test +{ +//SPIRV: Offset 0 + uint v0; +//SPIRV: Offset 4 + float3 v1; + +//SPIRV: Offset 16 + uint3 v2; + +//SPIRV: Offset 32 + uint2 v3; +//SPIRV: Offset 40 + uint2 v4; + +//SPIRV: Offset 48 + uint v5[4]; + +// array always starts on a new register. +//SPIRV: Offset 112 + uint3 v6[2]; +//SPIRV: Offset 140 +// non-array can pack with a partially filled register + uint v7; + +//SPIRV: Offset 144 + uint2 v8; + +// SPIRV: Offset 160 +// array always starts on a new register. + uint v9[2]; +}; + +RWStructuredBuffer<int> outputBuffer; + +__generic<T : IArithmetic, let N : int> +bool comp(vector<T,N> v1, vector<T,N> v2) +{ + for (uint i = 0; i < N; i++) + if (v1[i] != v2[i]) + return false; + + return true; +} + +[shader("compute")] +[numthreads(2, 2, 1)] +void computeMain() +{ + // CHECK: 64 + + outputBuffer[0] = (true + && v0 == 1 + && comp(v1, float3(2, 3, 4)) + && comp(v2, uint3(5, 6, 7)) + && comp(v3, uint2(8, 9)) + && comp(v4, uint2(10, 11)) + && v5[0] == 12 + && v5[1] == 13 + && v5[2] == 14 + && v5[3] == 15 + && comp(v6[0], uint3(16, 17, 18)) + && comp(v6[1], uint3(19, 20, 21)) + && v7 == 22 + && comp(v8, uint2(23, 24)) + && v9[0] == 25 + && v9[1] == 26 + ) ? 100 : 0; +}
\ No newline at end of file |
