Przeglądaj źródła

[spirv] Add support for arrays of resources (#1184)

An array of resources will be translated into an SPIR-V array
behind one single descriptor.
Lei Zhang 7 lat temu
rodzic
commit
725ecab3b9

+ 8 - 2
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

@@ -387,8 +387,14 @@ SpirvEvalInfo DeclResultIdMapper::createExternVar(const VarDecl *var) {
     // For CS groupshared variables
     // For CS groupshared variables
     storageClass = spv::StorageClass::Workgroup;
     storageClass = spv::StorageClass::Workgroup;
   } else if (TypeTranslator::isResourceType(var)) {
   } else if (TypeTranslator::isResourceType(var)) {
-    const auto *t = var->getType()->getAs<RecordType>();
-    const llvm::StringRef typeName = t->getDecl()->getName();
+    // See through the possible outer arrays
+    QualType resourceType = var->getType();
+    while (resourceType->isArrayType()) {
+      resourceType = resourceType->getAsArrayTypeUnsafe()->getElementType();
+    }
+
+    const llvm::StringRef typeName =
+        resourceType->getAs<RecordType>()->getDecl()->getName();
 
 
     // These types are all translated into OpTypeStruct with BufferBlock
     // These types are all translated into OpTypeStruct with BufferBlock
     // decoration. They should follow standard storage buffer layout,
     // decoration. They should follow standard storage buffer layout,

+ 6 - 1
tools/clang/lib/SPIRV/TypeTranslator.cpp

@@ -985,7 +985,12 @@ bool TypeTranslator::isResourceType(const ValueDecl *decl) {
   if (isConstantTextureBuffer(decl))
   if (isConstantTextureBuffer(decl))
     return true;
     return true;
 
 
-  const QualType declType = decl->getType();
+  QualType declType = decl->getType();
+
+  // Deprive the arrayness to see the element type
+  while (declType->isArrayType()) {
+    declType = declType->getAsArrayTypeUnsafe()->getElementType();
+  }
 
 
   if (isSubpassInput(declType) || isSubpassInputMS(declType))
   if (isSubpassInput(declType) || isSubpassInputMS(declType))
     return true;
     return true;

+ 5 - 1
tools/clang/test/CodeGenSPIRV/var.globals.hlsl

@@ -39,6 +39,8 @@
 // CHECK: OpDecorate %gTBuffer Binding 6
 // CHECK: OpDecorate %gTBuffer Binding 6
 // CHECK: OpDecorate %MyTBuffer Binding 7
 // CHECK: OpDecorate %MyTBuffer Binding 7
 // CHECK: OpDecorate %gSPInput Binding 8
 // CHECK: OpDecorate %gSPInput Binding 8
+// CHECK: OpDecorate %gRWBuffer DescriptorSet 0
+// CHECK: OpDecorate %gRWBuffer Binding 9
 
 
           int           gScalar;   // 0
           int           gScalar;   // 0
           SamplerState  gSampler;  // Not included - 1
           SamplerState  gSampler;  // Not included - 1
@@ -64,7 +66,7 @@ cbuffer MyCBuffer {                // Not included - 4
 ConstantBuffer<S>       gCBuffer;  // Not included - 5
 ConstantBuffer<S>       gCBuffer;  // Not included - 5
 TextureBuffer<S>        gTBuffer;  // Not included - 6
 TextureBuffer<S>        gTBuffer;  // Not included - 6
 
 
-typedef SamplerState SamplerStateType;
+typedef SamplerState SamplerStateType; // Not included - type definition
 
 
 // CHECK: [[v2f_struct:%\w+]] = OpTypeStruct %v2float
 // CHECK: [[v2f_struct:%\w+]] = OpTypeStruct %v2float
 struct {
 struct {
@@ -78,6 +80,8 @@ tbuffer MyTBuffer {                // Not included - 7
 [[vk::input_attachment_index(0)]]
 [[vk::input_attachment_index(0)]]
 SubpassInput            gSPInput;  // Not included - 8
 SubpassInput            gSPInput;  // Not included - 8
 
 
+RWBuffer<float4>        gRWBuffer[4]; // Not included - 9 (array)
+
 // CHECK: %type__Globals = OpTypeStruct %int %v2float %mat2v3float %mat2v3float %_arr_mat2v3float_uint_2 %S [[v2f_struct]]
 // CHECK: %type__Globals = OpTypeStruct %int %v2float %mat2v3float %mat2v3float %_arr_mat2v3float_uint_2 %S [[v2f_struct]]
 // CHECK: %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
 // CHECK: %_ptr_Uniform_type__Globals = OpTypePointer Uniform %type__Globals
 
 

+ 59 - 0
tools/clang/test/CodeGenSPIRV/var.resource.array.hlsl

@@ -0,0 +1,59 @@
+// Run: %dxc -T ps_6_0 -E main
+
+// CHECK: OpDecorate %MyBuffer DescriptorSet 0
+// CHECK: OpDecorate %MyBuffer Binding 0
+// CHECK: OpDecorate %MyRWBuffer DescriptorSet 0
+// CHECK: OpDecorate %MyRWBuffer Binding 1
+// CHECK: OpDecorate %MyTexture DescriptorSet 0
+// CHECK: OpDecorate %MyTexture Binding 2
+// CHECK: OpDecorate %MyRWTexture DescriptorSet 0
+// CHECK: OpDecorate %MyRWTexture Binding 3
+// CHECK: OpDecorate %MySamplers DescriptorSet 0
+// CHECK: OpDecorate %MySamplers Binding 4
+// CHECK: OpDecorate %MyCompSamplers DescriptorSet 0
+// CHECK: OpDecorate %MyCompSamplers Binding 5
+
+// CHECK: %type_buffer_image = OpTypeImage %float Buffer 0 0 0 1 Rgba32f
+// CHECK: %_arr_type_buffer_image_uint_1 = OpTypeArray %type_buffer_image %uint_1
+
+// CHECK: %type_buffer_image_0 = OpTypeImage %float Buffer 0 0 0 2 Rgba32f
+// CHECK: %_arr_type_buffer_image_0_uint_2 = OpTypeArray %type_buffer_image_0 %uint_2
+
+// CHECK: %type_2d_image = OpTypeImage %float 2D 0 0 0 1 Unknown
+// CHECK: %_arr_type_2d_image_uint_3 = OpTypeArray %type_2d_image %uint_3
+
+// CHECK: %type_2d_image_0 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
+// CHECK: %_arr_type_2d_image_0_uint_4 = OpTypeArray %type_2d_image_0 %uint_4
+
+// CHECK: %type_sampler = OpTypeSampler
+// CHECK: %_arr_type_sampler_uint_5 = OpTypeArray %type_sampler %uint_5
+// CHECK: %_arr_type_sampler_uint_6 = OpTypeArray %type_sampler %uint_6
+
+// CHECK:       %MyBuffer = OpVariable %_ptr_UniformConstant__arr_type_buffer_image_uint_1 UniformConstant
+Buffer<float4>         MyBuffer[1];
+// CHECK:     %MyRWBuffer = OpVariable %_ptr_UniformConstant__arr_type_buffer_image_0_uint_2 UniformConstant
+RWBuffer<float4>       MyRWBuffer[2];
+// CHECK:      %MyTexture = OpVariable %_ptr_UniformConstant__arr_type_2d_image_uint_3 UniformConstant
+Texture2D<float4>      MyTexture[3];
+// CHECK:    %MyRWTexture = OpVariable %_ptr_UniformConstant__arr_type_2d_image_0_uint_4 UniformConstant
+RWTexture2D<float4>    MyRWTexture[4];
+// CHECK:     %MySamplers = OpVariable %_ptr_UniformConstant__arr_type_sampler_uint_5 UniformConstant
+SamplerState           MySamplers[5];
+// CHECK: %MyCompSamplers = OpVariable %_ptr_UniformConstant__arr_type_sampler_uint_6 UniformConstant
+SamplerComparisonState MyCompSamplers[6];
+
+// TODO: unsized arrays of resources
+
+float4 main() : SV_Target {
+// CHECK:   [[MyBuffer:%\d+]] = OpAccessChain %_ptr_UniformConstant_type_buffer_image %MyBuffer %int_0
+// CHECK:            {{%\d+}} = OpLoad %type_buffer_image [[MyBuffer]]
+    return MyBuffer[0].Load(1) +
+// CHECK: [[MyRWBuffer:%\d+]] = OpAccessChain %_ptr_UniformConstant_type_buffer_image_0 %MyRWBuffer %int_1
+// CHECK:            {{%\d+}} = OpLoad %type_buffer_image_0 [[MyRWBuffer]]
+           MyRWBuffer[1][2] +
+// CHECK:  [[MyTexture:%\d+]] = OpAccessChain %_ptr_UniformConstant_type_2d_image %MyTexture %int_2
+// CHECK:            {{%\d+}} = OpLoad %type_2d_image [[MyTexture]]
+// CHECK:  [[MySampler:%\d+]] = OpAccessChain %_ptr_UniformConstant_type_sampler %MySamplers %int_3
+// CHECK:            {{%\d+}} = OpLoad %type_sampler [[MySampler]]
+           MyTexture[2].Sample(MySamplers[3], float2(0.1, 0.2));
+}

+ 1 - 0
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -126,6 +126,7 @@ TEST_F(FileTest, StaticVar) { runFileTest("var.static.hlsl"); }
 TEST_F(FileTest, UninitStaticResourceVar) {
 TEST_F(FileTest, UninitStaticResourceVar) {
   runFileTest("var.static.resource.hlsl");
   runFileTest("var.static.resource.hlsl");
 }
 }
+TEST_F(FileTest, ResourceArrayVar) { runFileTest("var.resource.array.hlsl"); }
 TEST_F(FileTest, GlobalsCBuffer) { runFileTest("var.globals.hlsl"); }
 TEST_F(FileTest, GlobalsCBuffer) { runFileTest("var.globals.hlsl"); }
 TEST_F(FileTest, GlobalsCBufferError) {
 TEST_F(FileTest, GlobalsCBufferError) {
   runFileTest("var.globals.error.hlsl", Expect::Failure);
   runFileTest("var.globals.error.hlsl", Expect::Failure);