SPV: Partially address #2293: correct "const in" precision matching.
authorJohn Kessenich <cepheus@frii.com>
Fri, 26 Jun 2020 14:37:06 +0000 (08:37 -0600)
committerJohn Kessenich <cepheus@frii.com>
Fri, 26 Jun 2020 14:37:06 +0000 (08:37 -0600)
Track whether formal parameters declare reduced precision and match
that with arguments, and if they differ, make a copy to promote the
precision.

SPIRV/GlslangToSpv.cpp
SPIRV/SpvBuilder.cpp
SPIRV/spvIR.h
Test/baseResults/spv.precisionArgs.frag.out [new file with mode: 0755]
Test/spv.precisionArgs.frag [new file with mode: 0644]
gtests/Spv.FromFile.cpp

index b63d901..fb36212 100644 (file)
@@ -5346,13 +5346,21 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
             }
             ++lValueCount;
         } else {
+            const bool argIsRelaxedPrecision = TranslatePrecisionDecoration(*argTypes[a]) ==
+                spv::DecorationRelaxedPrecision;
             // process r-value, which involves a copy for a type mismatch
-            if (function->getParamType(a) != convertGlslangToSpvType(*argTypes[a])) {
+            if (function->getParamType(a) != convertGlslangToSpvType(*argTypes[a]) ||
+                argIsRelaxedPrecision != function->isReducedPrecisionParam(a))
+            {
                 spv::Id argCopy = builder.createVariable(spv::StorageClassFunction, function->getParamType(a), "arg");
+                if (function->isReducedPrecisionParam(a))
+                    builder.setPrecision(argCopy, spv::DecorationRelaxedPrecision);
                 builder.clearAccessChain();
                 builder.setAccessChainLValue(argCopy);
                 multiTypeStore(*argTypes[a], rValues[rValueCount]);
                 arg = builder.createLoad(argCopy);
+                if (function->isReducedPrecisionParam(a))
+                    builder.setPrecision(arg, spv::DecorationRelaxedPrecision);
             } else
                 arg = rValues[rValueCount];
             ++rValueCount;
index 62b7d0e..f884224 100644 (file)
@@ -1298,8 +1298,11 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
     // Set up the precisions
     setPrecision(function->getId(), precision);
     for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
-        for (int d = 0; d < (int)decorations[p].size(); ++d)
+        for (int d = 0; d < (int)decorations[p].size(); ++d) {
             addDecoration(firstParamId + p, decorations[p][d]);
+            if (decorations[p][d] == DecorationRelaxedPrecision)
+                function->addReducedPrecisionParam(p);
+        }
     }
 
     // CFG
index 6523035..6146518 100755 (executable)
@@ -55,6 +55,7 @@
 #include <iostream>
 #include <memory>
 #include <vector>
+#include <set>
 
 namespace spv {
 
@@ -355,6 +356,10 @@ public:
     void setImplicitThis() { implicitThis = true; }
     bool hasImplicitThis() const { return implicitThis; }
 
+    void addReducedPrecisionParam(int p) { reducedPrecisionParams.insert(p); }
+    bool isReducedPrecisionParam(int p) const
+        { return reducedPrecisionParams.find(p) != reducedPrecisionParams.end(); }
+
     void dump(std::vector<unsigned int>& out) const
     {
         // OpFunction
@@ -379,6 +384,7 @@ protected:
     std::vector<Instruction*> parameterInstructions;
     std::vector<Block*> blocks;
     bool implicitThis;  // true if this is a member function expecting to be passed a 'this' as the first argument
+    std::set<int> reducedPrecisionParams;  // list of parameter indexes that need a relaxed precision arg
 };
 
 //
diff --git a/Test/baseResults/spv.precisionArgs.frag.out b/Test/baseResults/spv.precisionArgs.frag.out
new file mode 100755 (executable)
index 0000000..3e9eb66
--- /dev/null
@@ -0,0 +1,59 @@
+spv.precisionArgs.frag
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 27
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source ESSL 310
+                              Name 4  "main"
+                              Name 10  "fooConst(f1;f1;"
+                              Name 8  "f"
+                              Name 9  "g"
+                              Name 13  "aM"
+                              Name 15  "bM"
+                              Name 17  "arg"
+                              Name 20  "aH"
+                              Name 22  "bH"
+                              Name 24  "arg"
+                              Decorate 8(f) RelaxedPrecision
+                              Decorate 13(aM) RelaxedPrecision
+                              Decorate 14 RelaxedPrecision
+                              Decorate 15(bM) RelaxedPrecision
+                              Decorate 16 RelaxedPrecision
+                              Decorate 24(arg) RelaxedPrecision
+                              Decorate 25 RelaxedPrecision
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeFunction 2 6(float) 6(float)
+              12:             TypePointer Function 6(float)
+         4(main):           2 Function None 3
+               5:             Label
+          13(aM):     12(ptr) Variable Function
+          15(bM):     12(ptr) Variable Function
+         17(arg):     12(ptr) Variable Function
+          20(aH):     12(ptr) Variable Function
+          22(bH):     12(ptr) Variable Function
+         24(arg):     12(ptr) Variable Function
+              14:    6(float) Load 13(aM)
+              16:    6(float) Load 15(bM)
+                              Store 17(arg) 16
+              18:    6(float) Load 17(arg)
+              19:           2 FunctionCall 10(fooConst(f1;f1;) 14 18
+              21:    6(float) Load 20(aH)
+              23:    6(float) Load 22(bH)
+                              Store 24(arg) 21
+              25:    6(float) Load 24(arg)
+              26:           2 FunctionCall 10(fooConst(f1;f1;) 25 23
+                              Return
+                              FunctionEnd
+10(fooConst(f1;f1;):           2 Function None 7
+            8(f):    6(float) FunctionParameter
+            9(g):    6(float) FunctionParameter
+              11:             Label
+                              Return
+                              FunctionEnd
diff --git a/Test/spv.precisionArgs.frag b/Test/spv.precisionArgs.frag
new file mode 100644 (file)
index 0000000..4bf49b3
--- /dev/null
@@ -0,0 +1,15 @@
+#version 310 es
+
+precision mediump float;
+
+void fooConst(const in float f, const in highp float g)
+{
+}
+
+void main()
+{
+    float aM, bM;
+    highp float aH, bH;
+    fooConst(aM, bM);   // must copy bM
+    fooConst(aH, bH);   // must copy aH
+}
index e1d9735..80a75aa 100644 (file)
@@ -375,6 +375,7 @@ INSTANTIATE_TEST_CASE_P(
         "spv.Operations.frag",
         "spv.paramMemory.frag",
         "spv.precision.frag",
+        "spv.precisionArgs.frag",
         "spv.precisionNonESSamp.frag",
         "spv.prepost.frag",
         "spv.privateVariableTypes.frag",