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

[spirv] convert return type if memory layout is different (#3262)

For a function `ReturnType foo( .. ) { .. return value; }`, if the type
of value has a memory layout, `value` cannot be used for the operand of
OpReturnValue because of the type mis-match. Note that the `ReturnType`
for the return value must have a void memory layout (i.e., unknown).

This CL converts the type of the return value if it has an explicit
physical memory layout.
Jaebaek Seo 4 жил өмнө
parent
commit
09a4d3c1ef

+ 1 - 1
tools/clang/lib/SPIRV/SpirvEmitter.cpp

@@ -1929,7 +1929,7 @@ void SpirvEmitter::doReturnStmt(const ReturnStmt *stmt) {
       return;
       return;
 
 
     auto retType = retVal->getType();
     auto retType = retVal->getType();
-    if (retInfo->getStorageClass() != spv::StorageClass::Function &&
+    if (retInfo->getLayoutRule() != SpirvLayoutRule::Void &&
         retType->isStructureType()) {
         retType->isStructureType()) {
       // We are returning some value from a non-Function storage class. Need to
       // We are returning some value from a non-Function storage class. Need to
       // create a temporary variable to "convert" the value to Function storage
       // create a temporary variable to "convert" the value to Function storage

+ 39 - 0
tools/clang/test/CodeGenSPIRV/cf.return.memory-layout.hlsl

@@ -0,0 +1,39 @@
+// Run: %dxc -T cs_6_5 -E main -fvk-use-gl-layout -Zpr -WX -enable-16bit-types -Zi
+
+struct Data
+{
+    uint a;
+    uint b;
+    uint c;
+    uint d;
+};
+
+RWByteAddressBuffer buffer;
+
+// CHECK:     OpName [[Data:%\w+]] "Data"
+// CHECK-NOT: OpMemberDecorate [[Data]] 0 Offset 0
+// CHECK:     OpName [[Data_0:%\w+]] "Data"
+// CHECK-NOT: OpMemberDecorate [[Data]] 0 Offset 0
+// CHECK:     OpMemberDecorate [[Data_0]] 0 Offset 0
+// CHECK:     OpMemberDecorate [[Data_0]] 1 Offset 4
+// CHECK:     OpMemberDecorate [[Data_0]] 2 Offset 8
+// CHECK:     OpMemberDecorate [[Data_0]] 3 Offset 12
+// CHECK:     [[Data]] = OpTypeStruct %uint %uint %uint %uint
+// CHECK:     [[Data_0]] = OpTypeStruct %uint %uint %uint %uint
+
+Data returnDataWithoutPhysicalMemoryLayout(uint idx)
+{
+// CHECK: [[comp:%\d+]] = OpCompositeConstruct [[Data_0]]
+// CHECK: [[a:%\d+]] = OpCompositeExtract %uint [[comp]] 0
+// CHECK: [[b:%\d+]] = OpCompositeExtract %uint [[comp]] 1
+// CHECK: [[c:%\d+]] = OpCompositeExtract %uint [[comp]] 2
+// CHECK: [[d:%\d+]] = OpCompositeExtract %uint [[comp]] 3
+// CHECK: OpCompositeConstruct [[Data]] [[a]] [[b]] [[c]] [[d]]
+    return buffer.Load<Data>(idx);
+}
+
+[numthreads(1, 1, 1)]
+void main(uint3 groupThreadID : SV_GroupThreadID)
+{
+    Data foo = returnDataWithoutPhysicalMemoryLayout(groupThreadID.x);
+}

+ 3 - 0
tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp

@@ -534,6 +534,9 @@ TEST_F(FileTest, ReturnStruct) { runFileTest("cf.return.struct.hlsl"); }
 TEST_F(FileTest, ReturnFromDifferentStorageClass) {
 TEST_F(FileTest, ReturnFromDifferentStorageClass) {
   runFileTest("cf.return.storage-class.hlsl");
   runFileTest("cf.return.storage-class.hlsl");
 }
 }
+TEST_F(FileTest, ReturnFromDifferentMemoryLayout) {
+  runFileTest("cf.return.memory-layout.hlsl");
+}
 
 
 // For control flows
 // For control flows
 TEST_F(FileTest, ControlFlowNestedIfForStmt) { runFileTest("cf.if.for.hlsl"); }
 TEST_F(FileTest, ControlFlowNestedIfForStmt) { runFileTest("cf.if.for.hlsl"); }