HLSL: Fix an issue of frexp().
The "exp" parameter is floating-point type in HLSL intrinsic while it is
integer type in GLSL built-in function.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index d30432e..a14b2bb 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -4609,6 +4609,9 @@
spv::Id typeId0 = 0;
if (consumedOperands > 0)
typeId0 = builder.getTypeId(operands[0]);
+ spv::Id typeId1 = 0;
+ if (consumedOperands > 1)
+ typeId1 = builder.getTypeId(operands[1]);
spv::Id frexpIntType = 0;
switch (op) {
@@ -4730,13 +4733,22 @@
libCall = spv::GLSLstd450Fma;
break;
case glslang::EOpFrexp:
- libCall = spv::GLSLstd450FrexpStruct;
- if (builder.getNumComponents(operands[0]) == 1)
- frexpIntType = builder.makeIntegerType(32, true);
- else
- frexpIntType = builder.makeVectorType(builder.makeIntegerType(32, true), builder.getNumComponents(operands[0]));
- typeId = builder.makeStructResultType(typeId0, frexpIntType);
- consumedOperands = 1;
+ {
+ libCall = spv::GLSLstd450FrexpStruct;
+ assert(builder.isPointerType(typeId1));
+ typeId1 = builder.getContainedTypeId(typeId1);
+#ifdef AMD_EXTENSIONS
+ int width = builder.getScalarTypeWidth(typeId1);
+#else
+ int width = 32;
+#endif
+ if (builder.getNumComponents(operands[0]) == 1)
+ frexpIntType = builder.makeIntegerType(width, true);
+ else
+ frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0]));
+ typeId = builder.makeStructResultType(typeId0, frexpIntType);
+ consumedOperands = 1;
+ }
break;
case glslang::EOpLdexp:
libCall = spv::GLSLstd450Ldexp;
@@ -4844,9 +4856,18 @@
builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
break;
case glslang::EOpFrexp:
- assert(operands.size() == 2);
- builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]);
- id = builder.createCompositeExtract(id, typeId0, 0);
+ {
+ assert(operands.size() == 2);
+ if (builder.isFloatType(builder.getScalarTypeId(typeId1))) {
+ // "exp" is floating-point type (from HLSL intrinsic)
+ spv::Id member1 = builder.createCompositeExtract(id, frexpIntType, 1);
+ member1 = builder.createUnaryOp(spv::OpConvertSToF, typeId1, member1);
+ builder.createStore(member1, operands[1]);
+ } else
+ // "exp" is integer type (from GLSL built-in function)
+ builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]);
+ id = builder.createCompositeExtract(id, typeId0, 0);
+ }
break;
default:
break;
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 204d3e7..d93174e 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -134,6 +134,9 @@
bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
bool isBoolType(Id typeId) const { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
+ bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
+ bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
+ bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; }
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
@@ -153,6 +156,13 @@
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
+ int getScalarTypeWidth(Id typeId) const
+ {
+ Id scalarTypeId = getScalarTypeId(typeId);
+ assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat);
+ return module.getInstruction(scalarTypeId)->getImmediateOperand(0);
+ }
+
int getTypeNumColumns(Id typeId) const
{
assert(isMatrixType(typeId));