Use the correct type for the constant for matrix/scalar division
authorNeil Roberts <nroberts@igalia.com>
Tue, 13 Mar 2018 09:57:59 +0000 (10:57 +0100)
committerNeil Roberts <nroberts@igalia.com>
Tue, 13 Mar 2018 12:50:56 +0000 (13:50 +0100)
When a matrix is divided by a scalar it tries to take the reciprocal
of the scalar to convert the operation into a multiply. However it was
always doing this by making a 32-bit constant. If the scalar is a
double then this would end up making an FDiv instruction with
different types in the operands.

This patch adds a helper method called makeFpConstant which makes a
floating-point constant of the given type. The code to take the
reciprocal now uses it to make the same type as the result.

Fixes https://github.com/KhronosGroup/glslang/issues/1278

SPIRV/GlslangToSpv.cpp
SPIRV/SpvBuilder.cpp
SPIRV/SpvBuilder.h

index 1527fec..11257f0 100644 (file)
@@ -4137,7 +4137,8 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
     case spv::OpFDiv:
         if (builder.isMatrix(left) && builder.isScalar(right)) {
             // turn matrix / scalar into a multiply...
-            right = builder.createBinOp(spv::OpFDiv, builder.getTypeId(right), builder.makeFloatConstant(1.0F), right);
+            spv::Id resultType = builder.getTypeId(right);
+            right = builder.createBinOp(spv::OpFDiv, resultType, builder.makeFpConstant(resultType, 1.0), right);
             op = spv::OpMatrixTimesScalar;
         } else
             firstClass = false;
index 10d0d50..b509edd 100644 (file)
@@ -848,6 +848,23 @@ Id Builder::makeFloat16Constant(float f16, bool specConstant)
     return c->getResultId();
 }
 
+Id Builder::makeFpConstant(Id type, double d, bool specConstant)
+{
+        assert(isFloatType(type));
+
+        switch (getScalarTypeWidth(type)) {
+        case 16:
+                return makeFloat16Constant(d, specConstant);
+        case 32:
+                return makeFloatConstant(d, specConstant);
+        case 64:
+                return makeDoubleConstant(d, specConstant);
+        }
+
+        assert(false);
+}
+
+
 Id Builder::findCompositeConstant(Op typeClass, const std::vector<Id>& comps)
 {
     Instruction* constant = 0;
index d4d2719..25495fb 100755 (executable)
@@ -226,6 +226,7 @@ public:
     Id makeFloatConstant(float f, bool specConstant = false);
     Id makeDoubleConstant(double d, bool specConstant = false);
     Id makeFloat16Constant(float f16, bool specConstant = false);
+    Id makeFpConstant(Id type, double d, bool specConstant = false);
 
     // Turn the array of constants into a proper spv constant of the requested type.
     Id makeCompositeConstant(Id type, const std::vector<Id>& comps, bool specConst = false);