diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index 1e0b3ea29e..5b448983e0 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -396,6 +396,8 @@ def fspv_preserve_bindings : Flag<["-"], "fspv-preserve-bindings">, Group; def fspv_preserve_interface : Flag<["-"], "fspv-preserve-interface">, Group, Flags<[CoreOption, DriverOption]>, HelpText<"Preserves all interface variables in the entry point, even when those variables are unused">; +def fvk_allow_rwstructuredbuffer_arrays: Flag<["-"], "fvk-allow-rwstructuredbuffer-arrays">, Group, Flags<[CoreOption, DriverOption, HelpHidden]>, + HelpText<"Allow arrays of RWStructuredBuffers, AppendStructuredBuffers, and ConsumeStructuredBuffers. This is in development, and the option will be removed when the feature is complete.">; // SPIRV Change Ends ////////////////////////////////////////////////////////////////////////////// diff --git a/include/dxc/Support/SPIRVOptions.h b/include/dxc/Support/SPIRVOptions.h index 55a342b268..ee62bc5d7a 100644 --- a/include/dxc/Support/SPIRVOptions.h +++ b/include/dxc/Support/SPIRVOptions.h @@ -66,6 +66,7 @@ struct SpirvCodeGenOptions { bool autoShiftBindings; bool supportNonzeroBaseInstance; bool fixFuncCallArguments; + bool allowRWStructuredBufferArrays; /// Maximum length in words for the OpString literal containing the shader /// source for DebugSource and DebugSourceContinued. If the source code length /// is larger than this number, we will use DebugSourceContinued instructions diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 1a01d5f2f2..d7dff11bdf 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -988,6 +988,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, Args.hasFlag(OPT_fspv_preserve_bindings, OPT_INVALID, false); opts.SpirvOptions.preserveInterface = Args.hasFlag(OPT_fspv_preserve_interface, OPT_INVALID, false); + opts.SpirvOptions.allowRWStructuredBufferArrays = + Args.hasFlag(OPT_fvk_allow_rwstructuredbuffer_arrays, OPT_INVALID, false); if (!handleVkShiftArgs(Args, OPT_fvk_b_shift, "b", &opts.SpirvOptions.bShift, errors) || !handleVkShiftArgs(Args, OPT_fvk_t_shift, "t", &opts.SpirvOptions.tShift, errors) || @@ -1107,7 +1109,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false) || Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false) || Args.hasFlag(OPT_fvk_use_scalar_layout, OPT_INVALID, false) || - Args.hasFlag(OPT_fspv_use_legacy_buffer_matrix_order, OPT_INVALID, false) || + Args.hasFlag(OPT_fspv_use_legacy_buffer_matrix_order, OPT_INVALID, + false) || Args.hasFlag(OPT_fspv_flatten_resource_arrays, OPT_INVALID, false) || Args.hasFlag(OPT_fspv_reduce_load_size, OPT_INVALID, false) || Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false) || @@ -1116,6 +1119,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, Args.hasFlag(OPT_Wno_vk_ignored_features, OPT_INVALID, false) || Args.hasFlag(OPT_Wno_vk_emulated_features, OPT_INVALID, false) || Args.hasFlag(OPT_fvk_auto_shift_bindings, OPT_INVALID, false) || + Args.hasFlag(OPT_fvk_allow_rwstructuredbuffer_arrays, OPT_INVALID, + true) || !Args.getLastArgValue(OPT_fvk_stage_io_order_EQ).empty() || !Args.getLastArgValue(OPT_fspv_debug_EQ).empty() || !Args.getLastArgValue(OPT_fspv_extension_EQ).empty() || diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index 1b6592cd6b..6ab265b749 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -1733,7 +1733,8 @@ void SpirvEmitter::doVarDecl(const VarDecl *decl) { // Reject arrays of RW/append/consume structured buffers. They have assoicated // counters, which are quite nasty to handle. - if (decl->getType()->isArrayType()) { + if (!spirvOptions.allowRWStructuredBufferArrays && + decl->getType()->isArrayType()) { auto type = decl->getType(); do { type = type->getAsArrayTypeUnsafe()->getElementType(); diff --git a/tools/clang/test/CodeGenSPIRV/type.append-structured-buffer.array.error.hlsl b/tools/clang/test/CodeGenSPIRV/type.append-structured-buffer.array.error.hlsl deleted file mode 100644 index 03c729b74f..0000000000 --- a/tools/clang/test/CodeGenSPIRV/type.append-structured-buffer.array.error.hlsl +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %dxc -T ps_6_0 -E main - -struct T { - float a; - float3 b; -}; - -AppendStructuredBuffer myAppendStructuredBuffer[]; - -void main() {} - -// CHECK: :8:27: error: arrays of RW/append/consume structured buffers unsupported diff --git a/tools/clang/test/CodeGenSPIRV/type.append-structured-buffer.array.hlsl b/tools/clang/test/CodeGenSPIRV/type.append-structured-buffer.array.hlsl new file mode 100644 index 0000000000..b26f549a2d --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/type.append-structured-buffer.array.hlsl @@ -0,0 +1,12 @@ +// RUN: %dxc -T ps_6_0 -E main -fvk-allow-rwstructuredbuffer-arrays + +struct T { + float a; + float3 b; +}; + +// CHECK: %myAppendStructuredBuffer = OpVariable %_ptr_Uniform__runtimearr_type_AppendStructuredBuffer_T Uniform +AppendStructuredBuffer myAppendStructuredBuffer[]; + +void main() {} + diff --git a/tools/clang/test/CodeGenSPIRV/type.consume-structured-buffer.array.error.hlsl b/tools/clang/test/CodeGenSPIRV/type.consume-structured-buffer.array.error.hlsl deleted file mode 100644 index 752a7fb408..0000000000 --- a/tools/clang/test/CodeGenSPIRV/type.consume-structured-buffer.array.error.hlsl +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %dxc -T ps_6_0 -E main - -struct T { - float a; - float3 b; -}; - -ConsumeStructuredBuffer myConsumeStructuredBuffer[2]; - -void main() {} - -// CHECK: :8:28: error: arrays of RW/append/consume structured buffers unsupported diff --git a/tools/clang/test/CodeGenSPIRV/type.consume-structured-buffer.array.hlsl b/tools/clang/test/CodeGenSPIRV/type.consume-structured-buffer.array.hlsl new file mode 100644 index 0000000000..90d3c6a967 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/type.consume-structured-buffer.array.hlsl @@ -0,0 +1,13 @@ +// RUN: %dxc -T ps_6_0 -E main -fvk-allow-rwstructuredbuffer-arrays + +struct T { + float a; + float3 b; +}; + + +// CHECK: %myConsumeStructuredBuffer = OpVariable %_ptr_Uniform__arr_type_ConsumeStructuredBuffer_T_uint_2 Uniform +ConsumeStructuredBuffer myConsumeStructuredBuffer[2]; + +void main() {} + diff --git a/tools/clang/test/CodeGenSPIRV/type.rwstructured-buffer.array.nocounter.hlsl b/tools/clang/test/CodeGenSPIRV/type.rwstructured-buffer.array.nocounter.hlsl new file mode 100644 index 0000000000..b2a1d8bbe7 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/type.rwstructured-buffer.array.nocounter.hlsl @@ -0,0 +1,19 @@ +// RUN: %dxc -T ps_6_6 -E main -fvk-allow-rwstructuredbuffer-arrays + +struct PSInput +{ + uint idx : COLOR; +}; + +// CHECK: OpDecorate %g_rwbuffer DescriptorSet 2 +// CHECK: OpDecorate %g_rwbuffer Binding 0 +// CHECK: %g_rwbuffer = OpVariable %_ptr_Uniform__arr_type_RWStructuredBuffer_uint_uint_5 Uniform +RWStructuredBuffer g_rwbuffer[5] : register(u0, space2); + +float4 main(PSInput input) : SV_TARGET +{ +// CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_type_RWStructuredBuffer_uint %g_rwbuffer %35 +// CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_uint [[ac1]] %int_0 %uint_0 +// CHECK: OpLoad %uint [[ac2]] + return g_rwbuffer[input.idx][0]; +} diff --git a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp index 3943129732..b70a6c7977 100644 --- a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp +++ b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp @@ -143,13 +143,14 @@ TEST_F(FileTest, StructuredByteBufferArray) { TEST_F(FileTest, StructuredBufferArrayError) { runFileTest("type.structured-buffer.array.error.hlsl", Expect::Failure); } +TEST_F(FileTest, RWStructuredBufferArrayNoCounter) { + runFileTest("type.rwstructured-buffer.array.nocounter.hlsl"); +} TEST_F(FileTest, AppendStructuredBufferArrayError) { - runFileTest("type.append-structured-buffer.array.error.hlsl", - Expect::Failure); + runFileTest("type.append-structured-buffer.array.hlsl"); } TEST_F(FileTest, ConsumeStructuredBufferArrayError) { - runFileTest("type.consume-structured-buffer.array.error.hlsl", - Expect::Failure); + runFileTest("type.consume-structured-buffer.array.hlsl"); } TEST_F(FileTest, AppendConsumeStructuredBufferTypeCast) { runFileTest("type.append.consume-structured-buffer.cast.hlsl");