Fix loading bool arrays from interface blocks

SPIR-V disallows bool in interface blocks, which is emulated with uint.
When loading a bool variable (through accessChainLoad()), it's converted
from uint to bool if it came from an interface block.

This was handled for bool and bvecN, but not for bool arrays.  This
change implements the conversion for bool arrays.

Closes #2694
This commit is contained in:
Shahbaz Youssefi
2021-07-15 22:00:51 -04:00
parent 4b7b86d568
commit 097215f618
6 changed files with 304 additions and 13 deletions

View File

@@ -179,6 +179,7 @@ protected:
spv::Id accessChainLoad(const glslang::TType& type);
void accessChainStore(const glslang::TType& type, spv::Id rvalue);
void multiTypeStore(const glslang::TType&, spv::Id rValue);
spv::Id convertLoadedBoolInUniformToUint(const glslang::TType& type, spv::Id nominalTypeId, spv::Id loadedId);
glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
@@ -2231,6 +2232,49 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
}
}
spv::Id TGlslangToSpvTraverser::convertLoadedBoolInUniformToUint(const glslang::TType& type,
spv::Id nominalTypeId,
spv::Id loadedId)
{
if (builder.isScalarType(nominalTypeId)) {
// Conversion for bool
spv::Id boolType = builder.makeBoolType();
if (nominalTypeId != boolType)
return builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0));
} else if (builder.isVectorType(nominalTypeId)) {
// Conversion for bvec
int vecSize = builder.getNumTypeComponents(nominalTypeId);
spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
if (nominalTypeId != bvecType)
loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId,
makeSmearedConstant(builder.makeUintConstant(0), vecSize));
} else if (builder.isArrayType(nominalTypeId)) {
// Conversion for bool array
spv::Id boolArrayTypeId = convertGlslangToSpvType(type);
if (nominalTypeId != boolArrayTypeId)
{
// Use OpCopyLogical from SPIR-V 1.4 if available.
if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4)
return builder.createUnaryOp(spv::OpCopyLogical, boolArrayTypeId, loadedId);
glslang::TType glslangElementType(type, 0);
spv::Id elementNominalTypeId = builder.getContainedTypeId(nominalTypeId);
std::vector<spv::Id> constituents;
for (int index = 0; index < type.getOuterArraySize(); ++index) {
// get the element
spv::Id elementValue = builder.createCompositeExtract(loadedId, elementNominalTypeId, index);
// recursively convert it
spv::Id elementConvertedValue = convertLoadedBoolInUniformToUint(glslangElementType, elementNominalTypeId, elementValue);
constituents.push_back(elementConvertedValue);
}
return builder.createCompositeConstruct(boolArrayTypeId, constituents);
}
}
return loadedId;
}
// Figure out what, if any, type changes are needed when accessing a specific built-in.
// Returns <the type SPIR-V requires for declarion, the type to translate to on use>.
// Also see comment for 'forceType', regarding tracking SPIR-V-required types.
@@ -4560,19 +4604,7 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
// Need to convert to abstract types when necessary
if (type.getBasicType() == glslang::EbtBool) {
if (builder.isScalarType(nominalTypeId)) {
// Conversion for bool
spv::Id boolType = builder.makeBoolType();
if (nominalTypeId != boolType)
loadedId = builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0));
} else if (builder.isVectorType(nominalTypeId)) {
// Conversion for bvec
int vecSize = builder.getNumTypeComponents(nominalTypeId);
spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
if (nominalTypeId != bvecType)
loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId,
makeSmearedConstant(builder.makeUintConstant(0), vecSize));
}
loadedId = convertLoadedBoolInUniformToUint(type, nominalTypeId, loadedId);
}
return loadedId;