Avoid duplicate BuiltIn variables for ray tracing matrices (fix #2921)

Fixes an issue where invalid SPIR-V was generated when
gl_ObjectToWorldEXT and gl_ObjectToWorld3x4EXT, or
gl_WorldToObjectEXT and gl_WorldToObject3x4EXT, were used in the same
shader. The SPIR-V specification requires that there be at most one
OpVariable decorated with a given BuiltIn value.
This commit is contained in:
Andrea Faulds 2022-06-01 10:43:13 +02:00
parent 316f12ac1d
commit 6cdae46314
4 changed files with 142 additions and 134 deletions

View file

@ -260,6 +260,7 @@ protected:
std::unordered_map<std::string, spv::Id> extBuiltinMap;
std::unordered_map<long long, spv::Id> symbolValues;
std::unordered_map<uint32_t, spv::Id> builtInVariableIds;
std::unordered_set<long long> rValueParameters; // set of formal function parameters passed as rValues,
// rather than a pointer
std::unordered_map<std::string, spv::Function*> functionMap;
@ -8750,7 +8751,32 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
// it was not found, create it
spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType());
// There are pairs of symbols that map to the same SPIR-V built-in:
// gl_ObjectToWorldEXT and gl_ObjectToWorld3x4EXT, and gl_WorldToObjectEXT
// and gl_WorldToObject3x4EXT. SPIR-V forbids having two OpVariables
// with the same BuiltIn in the same storage class, so we must re-use one.
const bool mayNeedToReuseBuiltIn =
builtIn == spv::BuiltInObjectToWorldKHR ||
builtIn == spv::BuiltInWorldToObjectKHR;
if (mayNeedToReuseBuiltIn) {
auto iter = builtInVariableIds.find(uint32_t(builtIn));
if (builtInVariableIds.end() != iter) {
id = iter->second;
symbolValues[symbol->getId()] = id;
if (forcedType.second != spv::NoType)
forceType[id] = forcedType.second;
return id;
}
}
id = createSpvVariable(symbol, forcedType.first);
if (mayNeedToReuseBuiltIn) {
builtInVariableIds.insert({uint32_t(builtIn), id});
}
symbolValues[symbol->getId()] = id;
if (forcedType.second != spv::NoType)
forceType[id] = forcedType.second;