2
0
Эх сурвалжийг харах

[spirv] Handle inout structs. Fixed issue #806. (#810)

Ehsan 7 жил өмнө
parent
commit
511ef092a9

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

@@ -1357,9 +1357,16 @@ uint32_t SPIRVEmitter::processCall(const CallExpr *callExpr) {
 
     // Evaluate parameters
     for (uint32_t i = 0; i < numParams; ++i) {
-      const auto *arg = callExpr->getArg(i);
+      auto *arg = callExpr->getArg(i);
       const auto *param = callee->getParamDecl(i);
 
+      // In some cases where pass-by-reference should be done (such as an
+      // 'inout' struct), the AST does not use a reference type in the function
+      // signature. The LValueToRValue implicit cast should therefore be ignored
+      // in these cases.
+      if (canActAsOutParmVar(param) && !param->getType()->isReferenceType())
+        arg = cast<ImplicitCastExpr>(arg)->getSubExpr();
+
       // We need to create variables for holding the values to be used as
       // arguments. The variables themselves are of pointer types.
       const uint32_t varType = typeTranslator.translateType(arg->getType());

+ 13 - 2
tools/clang/test/CodeGenSPIRV/fn.param.inout.hlsl

@@ -1,6 +1,10 @@
 // Run: %dxc -T vs_6_0 -E main
 
-float fnInOut(uniform float a, in float b, out float c, inout float d) {
+struct Pixel {
+  float4 color;
+};
+
+float fnInOut(uniform float a, in float b, out float c, inout float d, inout Pixel e) {
     float v = a + b + c + d;
     d = c = a;
     return v;
@@ -9,10 +13,13 @@ float fnInOut(uniform float a, in float b, out float c, inout float d) {
 float main(float val: A) : B {
 // CHECK-LABEL: %src_main = OpFunction
     float m, n;
+    Pixel p;
+
 // CHECK:      %param_var_a = OpVariable %_ptr_Function_float Function
 // CHECK-NEXT: %param_var_b = OpVariable %_ptr_Function_float Function
 // CHECK-NEXT: %param_var_c = OpVariable %_ptr_Function_float Function
 // CHECK-NEXT: %param_var_d = OpVariable %_ptr_Function_float Function
+// CHECK-NEXT: %param_var_e = OpVariable %_ptr_Function_Pixel Function
 
 // CHECK-NEXT:                OpStore %param_var_a %float_5
 // CHECK-NEXT: [[val:%\d+]] = OpLoad %float %val
@@ -21,6 +28,8 @@ float main(float val: A) : B {
 // CHECK-NEXT:                OpStore %param_var_c [[m]]
 // CHECK-NEXT:   [[n:%\d+]] = OpLoad %float %n
 // CHECK-NEXT:                OpStore %param_var_d [[n]]
+// CHECK-NEXT:   [[p:%\d+]] = OpLoad %Pixel %p
+// CHECK-NEXT:                OpStore %param_var_e [[p]]
 
 // CHECK-NEXT: [[ret:%\d+]] = OpFunctionCall %float %fnInOut %param_var_a %param_var_b %param_var_c %param_var_d
 
@@ -28,8 +37,10 @@ float main(float val: A) : B {
 // CHECK-NEXT:                OpStore %m [[c]]
 // CHECK-NEXT:   [[d:%\d+]] = OpLoad %float %param_var_d
 // CHECK-NEXT:                OpStore %n [[d]]
+// CHECK-NEXT:   [[e:%\d+]] = OpLoad %Pixel %param_var_e
+// CHECK-NEXT:                OpStore %p [[e]]
 
 // CHECK-NEXT:                OpReturnValue [[ret]]
-    return fnInOut(5., val, m, n);
+    return fnInOut(5., val, m, n, p);
 // CHECK-NEXT: OpFunctionEnd
 }