瀏覽代碼

[spirv] Associated counter assign across different nested struct level (#1837)

Lei Zhang 6 年之前
父節點
當前提交
1ddb0ba5d2

+ 8 - 6
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -3455,12 +3455,14 @@ bool SPIRVEmitter::tryToAssignCounterVar(const DeclaratorDecl *dstDecl,
   const auto *srcFields = getIntermediateACSBufferCounter(srcExpr, &srcIndices);
 
   if (dstFields && srcFields) {
-    if (!dstFields->assign(*srcFields, theBuilder, typeTranslator)) {
-      emitFatalError("cannot handle associated counter variable assignment",
-                     srcExpr->getExprLoc());
-      return false;
-    }
-    return true;
+    // The destination is a struct whose fields are directly alias resources.
+    // But that's not necessarily true for the source, which can be deep
+    // nested structs. That means they will have different index "prefixes"
+    // for all their fields; while the "prefix" for destination is effectively
+    // an empty list (since it is not nested in other structs). We need to
+    // strip the index prefix from the source.
+    return dstFields->assign(*srcFields, /*dstIndices=*/{}, srcIndices,
+                             theBuilder, typeTranslator);
   }
 
   // AssocCounter#2 and AssocCounter#4 for the lhs cannot happen since the lhs

+ 32 - 0
tools/clang/test/CodeGenSPIRV/spirv.legal.counter.nested-struct.hlsl

@@ -0,0 +1,32 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// CHECK: %counter_var_rw = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform
+// CHECK: %counter_var_t_1_0 = OpVariable %_ptr_Private__ptr_Uniform_type_ACSBuffer_counter Private
+// CHECK: %counter_var_s_0 = OpVariable %_ptr_Private__ptr_Uniform_type_ACSBuffer_counter Private
+  
+RWStructuredBuffer<uint> rw : register(u0); 
+
+struct S {
+  RWStructuredBuffer<uint> rw; 
+  uint u; 
+}; 
+
+struct T { 
+  float a; 
+  S s; 
+};
+
+void foo(S s) { s.rw[0] = 0; }
+
+float4 main() : SV_POSITION { 
+  T t;
+// CHECK: OpStore %counter_var_t_1_0 %counter_var_rw
+  t.s.rw = rw; 
+
+// CHECK: [[var:%\d+]] = OpLoad %_ptr_Uniform_type_ACSBuffer_counter %counter_var_t_1_0
+// CHECK: OpStore %counter_var_s_0 [[var]]
+// CHECK: OpFunctionCall
+  foo(t.s);
+
+  return float4(1, 1, 1, 1);
+} 

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

@@ -1336,6 +1336,11 @@ TEST_F(FileTest, SpirvLegalizationStructuredBufferCounterInMethod) {
   setRelaxLogicalPointer();
   runFileTest("spirv.legal.sbuffer.counter.method.hlsl");
 }
+TEST_F(FileTest,
+       SpirvLegalizationCounterVarAssignAcrossDifferentNestedStructLevel) {
+  setRelaxLogicalPointer();
+  runFileTest("spirv.legal.counter.nested-struct.hlsl");
+}
 TEST_F(FileTest, SpirvLegalizationStructuredBufferInStruct) {
   setRelaxLogicalPointer();
   runFileTest("spirv.legal.sbuffer.struct.hlsl");