瀏覽代碼

[spirv] Handle rvalue passed to Interlocked methods (#1220)

Ehsan 7 年之前
父節點
當前提交
b241b8bd98

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

@@ -6554,7 +6554,14 @@ SPIRVEmitter::processIntrinsicInterlockedMethod(const CallExpr *expr,
     if (isBufferTextureIndexing(callExpr, &base, &index)) {
       const auto ptrType =
           theBuilder.getPointerType(baseTypeId, spv::StorageClass::Image);
-      const auto baseId = doExpr(base);
+      auto baseId = doExpr(base);
+      if (baseId.isRValue()) {
+        // OpImageTexelPointer's Image argument must have a type of
+        // OpTypePointer with Type OpTypeImage. Need to create a temporary
+        // variable if the baseId is an rvalue.
+        baseId = createTemporaryVar(
+            base->getType(), TypeTranslator::getName(base->getType()), baseId);
+      }
       const auto coordId = doExpr(index);
       ptr = theBuilder.createImageTexelPointer(ptrType, baseId, coordId, zero);
     }

+ 10 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.interlocked-methods.cs.hlsl

@@ -3,6 +3,11 @@
 groupshared int dest_i;
 groupshared uint dest_u;
 
+RWBuffer<uint> buff;
+RWBuffer<uint> getDest() {
+  return buff;
+}
+
 void main()
 {
   uint original_u_val;
@@ -21,6 +26,11 @@ void main()
 // CHECK-NEXT:                   OpStore %original_i_val [[iadd27]]
   InterlockedAdd(dest_i, val1, original_i_val);
 
+// CHECK:      [[buff:%\d+]] = OpFunctionCall %type_buffer_image %getDest
+// CHECK-NEXT: OpStore %temp_var_RWBuffer [[buff]]
+// CHECK-NEXT: OpImageTexelPointer %_ptr_Image_uint %temp_var_RWBuffer %uint_0 %uint_0
+  InterlockedAdd(getDest()[0], val1, original_i_val);
+
 // CHECK:      [[and28:%\d+]] = OpAtomicAnd %uint %dest_u %uint_1 %uint_0 %uint_10
 // CHECK-NEXT:                  OpStore %original_u_val [[and28]]
   InterlockedAnd(dest_u, 10,  original_u_val);