ソースを参照

[spirv] Fix accessing (RW)Buffer sub-element using [][] (#1354)

Accessing sub-elements in (RW)Buffer with adjacent array subscript
operators was falsely translated into an OpAccessChain with two
indices. Instead, we need to perform OpImage* on the (RW)Buffer
object and then do single-index OpAccessChain.
Lei Zhang 7 年 前
コミット
c7fe4cb0af

+ 10 - 2
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -3475,7 +3475,7 @@ SPIRVEmitter::processACSBufferAppendConsume(const CXXMemberCallExpr *expr) {
   if (isAppend) {
     // Write out the value
     auto arg0 = doExpr(expr->getArg(0));
-    if(!arg0.isRValue()) {
+    if (!arg0.isRValue()) {
       arg0.setResultId(theBuilder.createLoad(
           typeTranslator.translateType(bufferElemTy), arg0));
     }
@@ -5966,8 +5966,15 @@ const Expr *SPIRVEmitter::collectArrayStructIndices(
       if (rawIndex)
         return nullptr; // TODO: handle constant array index
 
+      // If this is indexing into resources, we need specific OpImage*
+      // instructions for accessing. Return directly to avoid further building
+      // up the access chain.
+      if (isBufferTextureIndexing(indexing))
+        return indexing;
+
       const Expr *thisBase =
           indexing->getArg(0)->IgnoreParenNoopCasts(astContext);
+
       const auto thisBaseType = thisBase->getType();
       const Expr *base = collectArrayStructIndices(thisBase, indices, rawIndex);
 
@@ -8448,7 +8455,8 @@ uint32_t SPIRVEmitter::processIntrinsicUsingSpirvInst(
       needsLegalization = true;
       break;
     default:
-      // Only the given opcodes need legalization. Anything else should preserve previous.
+      // Only the given opcodes need legalization. Anything else should preserve
+      // previous.
       break;
     }
 

+ 16 - 0
tools/clang/test/CodeGenSPIRV/op.buffer.access.hlsl

@@ -86,4 +86,20 @@ void main() {
 // CHECK:      [[r12:%\d+]] = OpImageRead %v4float [[img12]] {{%\d+}} None
 // CHECK-NEXT: OpStore %float4 [[r12]]
   float4 float4 = float4buf[address];
+
+// CHECK:      [[img13:%\d+]] = OpLoad %type_buffer_image_5 %int3buf
+// CHECK-NEXT:   [[f13:%\d+]] = OpImageFetch %v4int [[img13]] %uint_0 None
+// CHECK-NEXT:   [[r13:%\d+]] = OpVectorShuffle %v3int [[f13]] [[f13]] 0 1 2
+// CHECK-NEXT:                  OpStore %temp_var_vector [[r13]]
+// CHECK-NEXT:  [[ac13:%\d+]] = OpAccessChain %_ptr_Function_int %temp_var_vector %uint_1
+// CHECK-NEXT:     [[a:%\d+]] = OpLoad %int [[ac13]]
+// CHECK-NEXT:                  OpStore %a [[a]]
+  int   a = int3buf[0][1];
+// CHECK:      [[img14:%\d+]] = OpLoad %type_buffer_image_10 %float4buf
+// CHECK-NEXT:   [[f14:%\d+]] = OpImageRead %v4float [[img14]] {{%\d+}} None
+// CHECK-NEXT:                  OpStore %temp_var_vector_0 [[f14]]
+// CHECK-NEXT:  [[ac14:%\d+]] = OpAccessChain %_ptr_Function_float %temp_var_vector_0 %uint_2
+// CHECK-NEXT:     [[b:%\d+]] = OpLoad %float [[ac14]]
+// CHECK-NEXT:                  OpStore %b [[b]]
+  float b = float4buf[address][2];
 }