From eddb1318ae125d5d963bec1c00d762fa62a9529a Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 13 Mar 2018 10:57:59 +0100 Subject: [PATCH] Use the correct type for the constant for matrix/scalar division 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 | 3 ++- SPIRV/SpvBuilder.cpp | 17 +++++++++++++++++ SPIRV/SpvBuilder.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 1527fec..11257f0 100644 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -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; diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 10d0d50..b509edd 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -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& comps) { Instruction* constant = 0; diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index d4d2719..25495fb 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -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& comps, bool specConst = false); -- 2.7.4