Browse Source

Allow arrays of RW, consume, and append structured buffers. (#5405)

This is the first commit in a series that will enable array of
RW, consume, and append Structured buffers. This commit removes the
error when one is used on its own.

There will be a failure if a counter variable is needed.

This is the first PR is a series that will slowly enable different
features for arrays of RWStructuredBuffers. To see the general direction
the changes will go see
https://github.com/microsoft/DirectXShaderCompiler/pull/5407.
Steven Perron 2 years ago
parent
commit
34b47c2c8b

+ 2 - 0
include/dxc/Support/HLSLOptions.td

@@ -396,6 +396,8 @@ def fspv_preserve_bindings : Flag<["-"], "fspv-preserve-bindings">, Group<spirv_
   HelpText<"Preserves all bindings declared within the module, even when those bindings are unused">;
 def fspv_preserve_interface : Flag<["-"], "fspv-preserve-interface">, Group<spirv_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<spirv_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
 
 //////////////////////////////////////////////////////////////////////////////

+ 1 - 0
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

+ 6 - 1
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() ||

+ 2 - 1
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();

+ 0 - 12
tools/clang/test/CodeGenSPIRV/type.append-structured-buffer.array.error.hlsl

@@ -1,12 +0,0 @@
-// RUN: %dxc -T ps_6_0 -E main
-
-struct T {
-  float  a;
-  float3 b;
-};
-
-AppendStructuredBuffer<T> myAppendStructuredBuffer[];
-
-void main() {}
-
-// CHECK: :8:27: error: arrays of RW/append/consume structured buffers unsupported

+ 12 - 0
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<T> myAppendStructuredBuffer[];
+
+void main() {}
+

+ 0 - 12
tools/clang/test/CodeGenSPIRV/type.consume-structured-buffer.array.error.hlsl

@@ -1,12 +0,0 @@
-// RUN: %dxc -T ps_6_0 -E main
-
-struct T {
-  float  a;
-  float3 b;
-};
-
-ConsumeStructuredBuffer<T> myConsumeStructuredBuffer[2];
-
-void main() {}
-
-// CHECK: :8:28: error: arrays of RW/append/consume structured buffers unsupported

+ 13 - 0
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<T> myConsumeStructuredBuffer[2];
+
+void main() {}
+

+ 19 - 0
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<uint> 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];
+}

+ 5 - 4
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");