SPV: Handle GLSL bool loads from a uniform buffer as a conversion from int -> bool.
SPIR-V bool is abstract; it has no bit pattern for storage with transparent memory. OpenGL's convention is a bool in a uniform buffer is 32-bit int with non-0 being 'true'.
This commit is contained in:
@@ -1570,7 +1570,12 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
spvType = builder.makeFloatType(64);
|
||||
break;
|
||||
case glslang::EbtBool:
|
||||
spvType = builder.makeBoolType();
|
||||
// "transparent" bool doesn't exist in SPIR-V. The GLSL convention is
|
||||
// a 32-bit int where non-0 means true.
|
||||
if (explicitLayout != glslang::ElpNone)
|
||||
spvType = builder.makeUintType(32);
|
||||
else
|
||||
spvType = builder.makeBoolType();
|
||||
break;
|
||||
case glslang::EbtInt:
|
||||
spvType = builder.makeIntType(32);
|
||||
@@ -1764,9 +1769,21 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
return spvType;
|
||||
}
|
||||
|
||||
// Wrap the builder's accessChainLoad to:
|
||||
// - localize handling of RelaxedPrecision
|
||||
// - use the SPIR-V inferred type instead of another conversion of the glslang type
|
||||
// (avoids unnecessary work and possible type punning for structures)
|
||||
// - do conversion of concrete to abstract type
|
||||
spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
|
||||
{
|
||||
return builder.accessChainLoad(TranslatePrecisionDecoration(type), convertGlslangToSpvType(type));
|
||||
spv::Id nominalTypeId = builder.accessChainGetInferredType();
|
||||
spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), nominalTypeId);
|
||||
|
||||
// Need to convert to abstract types when necessary
|
||||
if (builder.isScalarType(nominalTypeId) && type.getBasicType() == glslang::EbtBool && nominalTypeId != builder.makeBoolType())
|
||||
loadedId = builder.createBinOp(spv::OpINotEqual, builder.makeBoolType(), loadedId, builder.makeUintConstant(0));
|
||||
|
||||
return loadedId;
|
||||
}
|
||||
|
||||
// Decide whether or not this type should be
|
||||
|
||||
@@ -1990,6 +1990,39 @@ Id Builder::accessChainGetLValue()
|
||||
return lvalue;
|
||||
}
|
||||
|
||||
// comment in header
|
||||
Id Builder::accessChainGetInferredType()
|
||||
{
|
||||
// anything to operate on?
|
||||
if (accessChain.base == NoResult)
|
||||
return NoType;
|
||||
Id type = getTypeId(accessChain.base);
|
||||
|
||||
// do initial dereference
|
||||
if (! accessChain.isRValue)
|
||||
type = getContainedTypeId(type);
|
||||
|
||||
// dereference each index
|
||||
for (auto deref : accessChain.indexChain) {
|
||||
if (isStructType(type))
|
||||
type = getContainedTypeId(type, getConstantScalar(deref));
|
||||
else
|
||||
type = getContainedTypeId(type);
|
||||
}
|
||||
|
||||
// dereference swizzle
|
||||
if (accessChain.swizzle.size() == 1)
|
||||
type = getContainedTypeId(type);
|
||||
else if (accessChain.swizzle.size() > 1)
|
||||
type = makeVectorType(getContainedTypeId(type), accessChain.swizzle.size());
|
||||
|
||||
// dereference component selection
|
||||
if (accessChain.component)
|
||||
type = getContainedTypeId(type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
void Builder::dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
// Header, before first instructions:
|
||||
|
||||
@@ -506,6 +506,10 @@ public:
|
||||
// get the direct pointer for an l-value
|
||||
Id accessChainGetLValue();
|
||||
|
||||
// Get the inferred SPIR-V type of the result of the current access chain,
|
||||
// based on the type of the base and the chain of dereferences.
|
||||
Id accessChainGetInferredType();
|
||||
|
||||
void dump(std::vector<unsigned int>&) const;
|
||||
|
||||
void createBranch(Block* block);
|
||||
|
||||
Reference in New Issue
Block a user