Переглянути джерело

[spirv] Generate RelaxedPrecision decorations also for arrays of minimum precision variables (#3546)

Currently, arrays of min16float etc. types don't get a RelaxedPrecision decoration for the OpVariable. This has some real performance implications since at least some hardware can fit more RelaxedPrecision variables into registers, and maybe also groupshared memory.

This pull request add the missing RelaxedPrecision decoration for OpVariables of array types in a similar way vector and matrix minimum precision types are already handled.
Atte Seppälä 4 роки тому
батько
коміт
13b12d6b51

+ 7 - 0
tools/clang/include/clang/SPIRV/AstTypeProbe.h

@@ -86,6 +86,13 @@ bool isMx1Matrix(QualType type, QualType *elemType = nullptr,
 bool isMxNMatrix(QualType type, QualType *elemType = nullptr,
                  uint32_t *rowCount = nullptr, uint32_t *colCount = nullptr);
 
+/// Returns true if the given type will be translated into a SPIR-V array type.
+///
+/// Writes the element type and count into *elementType and *count respectively
+/// if they are not nullptr.
+bool isArrayType(QualType type, QualType *elemType = nullptr,
+                 uint32_t *elemCount = nullptr);
+
 /// \brief Returns true if the given type is a ConstantBuffer or an array of
 /// ConstantBuffers.
 bool isConstantBuffer(QualType);

+ 16 - 3
tools/clang/lib/SPIRV/AstTypeProbe.cpp

@@ -265,6 +265,17 @@ bool isSubpassInputMS(QualType type) {
   return false;
 }
 
+bool isArrayType(QualType type, QualType *elemType, uint32_t *elemCount) {
+  if (const auto *arrayType = type->getAsArrayTypeUnsafe()) {
+    if (elemType)
+      *elemType = arrayType->getElementType();
+    if (elemCount)
+      *elemCount = hlsl::GetArraySize(type);
+    return true;
+  }
+  return false;
+}
+
 bool isConstantBuffer(clang::QualType type) {
   // Strip outer arrayness first
   while (type->isArrayType())
@@ -1051,12 +1062,14 @@ bool isRelaxedPrecisionType(QualType type, const SpirvCodeGenOptions &opts) {
         }
   }
 
-  // Vector & Matrix types could use relaxed precision based on their element
-  // type.
+  // Vector, Matrix and Array types could use relaxed precision based on their
+  // element type.
   {
     QualType elemType = {};
-    if (isVectorType(type, &elemType) || isMxNMatrix(type, &elemType))
+    if (isVectorType(type, &elemType) || isMxNMatrix(type, &elemType) ||
+        isArrayType(type, &elemType)) {
       return isRelaxedPrecisionType(elemType, opts);
+    }
   }
 
   // Images with RelaxedPrecision sampled type.

+ 46 - 0
tools/clang/test/CodeGenSPIRV/decoration.relaxed-precision.array.hlsl

@@ -0,0 +1,46 @@
+// Run: %dxc -T cs_6_0 -E main
+
+// CHECK:                      OpDecorate %testShared RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate %test RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate %testTypedef RelaxedPrecision
+// CHECK-NOT:                  OpDecorate %notMin16 RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate %a RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[compositeConstr1:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[compositeConstr2:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[loadFromTest1:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[loadFromTest2:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[loadFromTestTypedef:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[multiply1:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[loadVariable1:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[multiply2:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[loadFromShared:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[loadVariable2:%\d+]] RelaxedPrecision
+// CHECK-NEXT:                 OpDecorate [[multiply3:%\d+]] RelaxedPrecision
+
+typedef min16float ArrayOfMin16Float0[2];
+typedef ArrayOfMin16Float0 ArrayOfMin16Float;
+
+groupshared min16float testShared[2];
+
+[numthreads(1, 1, 1)] void main()
+{
+// CHECK: [[compositeConstr2:%\d+]] = OpCompositeConstruct %_arr_v2float_uint_2 {{%\d+}} {{%\d+}}
+    min16float2 test[2] = { float2(1.0, 1.0), float2(1.0, 1.0) };
+// CHECK: [[compositeConstr1:%\d+]] = OpCompositeConstruct %_arr_float_uint_2 %float_1 %float_1
+    ArrayOfMin16Float testTypedef = { 1.0, 1.0 };
+    float notMin16[2] = { 1.0, 1.0 };
+// CHECK: [[loadFromTest1:%\d+]] = OpLoad %float {{%\d+}}
+    testShared[0] = test[0].x;
+
+    min16float a = 1.0;
+// CHECK: [[loadFromTest2:%\d+]] = OpLoad %float {{%\d+}}
+// CHECK: [[loadFromTestTypedef:%\d+]] = OpLoad %float {{%\d+}}
+// CHECK: [[multiply1:%\d+]] = OpFMul %float {{%\d+}} {{%\d+}}
+// CHECK: [[loadVariable1:%\d+]] = OpLoad %float %a
+// CHECK: [[multiply2:%\d+]] = OpFMul %float {{%\d+}} {{%\d+}}
+    a *= (test[0].x * testTypedef[0]);
+// CHECK: [[loadFromShared:%\d+]] = OpLoad %float {{%\d+}}
+// CHECK: [[loadVariable2:%\d+]] = OpLoad %float %a
+// CHECK: [[multiply3:%\d+]] = OpFMul %float {{%\d+}} {{%\d+}}
+    a *= testShared[0];
+}

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

@@ -2315,6 +2315,9 @@ TEST_F(FileTest, DecorationRelaxedPrecisionImage) {
 TEST_F(FileTest, DecorationRelaxedPrecisionBool) {
   runFileTest("decoration.relaxed-precision.bool.hlsl");
 }
+TEST_F(FileTest, DecorationRelaxedPrecisionArray) {
+  runFileTest("decoration.relaxed-precision.array.hlsl");
+}
 
 // For NoContraction decorations
 TEST_F(FileTest, DecorationNoContraction) {