From 59e6b4efbb967c12390f285cf8d1806698ca5199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D0=B8=D1=80=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D1=9F=D0=B8=D1=9B?= Date: Sat, 13 Dec 2025 11:47:58 -0800 Subject: [PATCH] Updated glslang. --- 3rdparty/glslang/SPIRV/GlslangToSpv.cpp | 13 +- 3rdparty/glslang/SPIRV/SpvBuilder.cpp | 217 +++++++++--------- 3rdparty/glslang/SPIRV/SpvBuilder.h | 77 ++++++- 3rdparty/glslang/build_info.h | 2 +- .../MachineIndependent/ParseHelper.cpp | 10 +- .../glslang/MachineIndependent/SymbolTable.h | 18 +- .../glslang/MachineIndependent/Versions.cpp | 4 +- .../MachineIndependent/localintermediate.h | 11 + 8 files changed, 236 insertions(+), 116 deletions(-) diff --git a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp b/3rdparty/glslang/SPIRV/GlslangToSpv.cpp index c42c1395e..1a5c40c53 100644 --- a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp +++ b/3rdparty/glslang/SPIRV/GlslangToSpv.cpp @@ -5167,6 +5167,16 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* } spv::Id var = builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer, false); + + if (options.emitNonSemanticShaderDebugInfo && storageClass != spv::StorageClass::Function) { + // Create variable alias for retargeted symbols if any. + // Notably, this is only applicable to built-in variables so that it is okay to only use name as the key. + auto [itBegin, itEnd] = glslangIntermediate->getBuiltinAliasLookup().equal_range(name); + for (auto it = itBegin; it != itEnd; ++it) { + builder.createDebugGlobalVariable(builder.getDebugType(spvType), it->second.c_str(), var); + } + } + std::vector topLevelDecorations; glslang::TQualifier typeQualifier = node->getType().getQualifier(); TranslateMemoryDecoration(typeQualifier, topLevelDecorations, glslangIntermediate->usingVulkanMemoryModel()); @@ -5675,7 +5685,8 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty if (type.isSizedArray()) spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride); else { - if (!lastBufferBlockMember) { + // If we see an runtime array in a buffer_reference, it is not a descriptor + if (!lastBufferBlockMember && type.getBasicType() != glslang::EbtReference) { builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); builder.addCapability(spv::Capability::RuntimeDescriptorArrayEXT); } diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.cpp b/3rdparty/glslang/SPIRV/SpvBuilder.cpp index 6e7f3cc17..0e4237fb8 100644 --- a/3rdparty/glslang/SPIRV/SpvBuilder.cpp +++ b/3rdparty/glslang/SPIRV/SpvBuilder.cpp @@ -97,7 +97,7 @@ Id Builder::makeVoidType() module.mapInstruction(type); // Core OpTypeVoid used for debug void type if (emitNonSemanticShaderDebugInfo) - debugId[typeId] = typeId; + debugTypeIdLookup[typeId] = typeId; } else type = groupedTypes[enumCast(Op::OpTypeVoid)].back(); @@ -115,7 +115,7 @@ Id Builder::makeBoolType() if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeBoolDebugType(32); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } } else @@ -139,7 +139,7 @@ Id Builder::makeSamplerType(const char* debugName) if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeOpaqueDebugType(debugName); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -167,7 +167,7 @@ Id Builder::makePointer(StorageClass storageClass, Id pointee) if (emitNonSemanticShaderDebugInfo) { const Id debugResultId = makePointerDebugType(storageClass, pointee); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -185,7 +185,7 @@ Id Builder::makeForwardPointer(StorageClass storageClass) if (emitNonSemanticShaderDebugInfo) { const Id debugResultId = makeForwardPointerDebugType(storageClass); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); } @@ -213,9 +213,9 @@ Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardP // that was emitted alongside the forward pointer, now that we have a pointee debug // type for it to point to. if (emitNonSemanticShaderDebugInfo) { - Instruction *debugForwardPointer = module.getInstruction(debugId[forwardPointerType]); - assert(debugId[pointee]); - debugForwardPointer->setIdOperand(2, debugId[pointee]); + Instruction *debugForwardPointer = module.getInstruction(getDebugType(forwardPointerType)); + assert(getDebugType(pointee)); + debugForwardPointer->setIdOperand(2, getDebugType(pointee)); } return type->getResultId(); @@ -257,7 +257,7 @@ Id Builder::makeIntegerType(int width, bool hasSign) if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeIntegerDebugType(width, hasSign); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -298,7 +298,7 @@ Id Builder::makeFloatType(int width) if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeFloatDebugType(width); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -334,7 +334,7 @@ Id Builder::makeBFloat16Type() if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeFloatDebugType(width); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } #endif @@ -371,7 +371,7 @@ Id Builder::makeFloatE5M2Type() if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeFloatDebugType(width); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } #endif @@ -408,7 +408,7 @@ Id Builder::makeFloatE4M3Type() if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeFloatDebugType(width); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } #endif @@ -439,7 +439,7 @@ Id Builder::makeStructType(const std::vector& members, const std::vectorgetResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -492,7 +492,7 @@ Id Builder::makeVectorType(Id component, int size) if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeVectorDebugType(component, size); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -525,7 +525,7 @@ Id Builder::makeMatrixType(Id component, int cols, int rows) if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeMatrixDebugType(column, cols); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -562,7 +562,7 @@ Id Builder::makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id col // Find a name for one of the parameters. It can either come from debuginfo for another // type, or an OpName from a constant. auto const findName = [&](Id id) { - Id id2 = debugId[id]; + Id id2 = getDebugType(id); for (auto &t : groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic]) { if (t->getResultId() == id2) { for (auto &s : strings) { @@ -591,7 +591,7 @@ Id Builder::makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id col // There's no nonsemantic debug info instruction for cooperative matrix types, // use opaque composite instead. auto const debugResultId = makeOpaqueDebugType(debugName.c_str()); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -742,7 +742,7 @@ Id Builder::makeArrayType(Id element, Id sizeId, int stride) if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeArrayDebugType(element, sizeId); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -758,7 +758,7 @@ Id Builder::makeRuntimeArray(Id element) if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeArrayDebugType(element, makeUintConstant(0)); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -785,12 +785,12 @@ Id Builder::makeFunctionType(Id returnType, const std::vector& paramTypes) // function type is created for the wrapper function. However, nonsemantic shader debug information is disabled // while creating the HLSL wrapper. Consequently, if we encounter another void(void) function, we need to create // the associated debug function type if it hasn't been created yet. - if(emitNonSemanticShaderDebugInfo && debugId[type->getResultId()] == 0) { + if(emitNonSemanticShaderDebugInfo && getDebugType(type->getResultId()) == NoType) { assert(sourceLang == spv::SourceLanguage::HLSL); assert(getTypeClass(returnType) == Op::OpTypeVoid && paramTypes.size() == 0); - Id debugTypeId = makeDebugFunctionType(returnType, {}); - debugId[type->getResultId()] = debugTypeId; + Id id = makeDebugFunctionType(returnType, {}); + debugTypeIdLookup[type->getResultId()] = id; } return type->getResultId(); } @@ -810,7 +810,7 @@ Id Builder::makeFunctionType(Id returnType, const std::vector& paramTypes) // make debug type and map it if (emitNonSemanticShaderDebugInfo) { Id debugTypeId = makeDebugFunctionType(returnType, paramTypes); - debugId[typeId] = debugTypeId; + debugTypeIdLookup[typeId] = debugTypeId; } return type->getResultId(); @@ -818,7 +818,7 @@ Id Builder::makeFunctionType(Id returnType, const std::vector& paramTypes) Id Builder::makeDebugFunctionType(Id returnType, const std::vector& paramTypes) { - assert(debugId[returnType] != 0); + assert(getDebugType(returnType) != NoType); Id typeId = getUniqueId(); auto type = new Instruction(typeId, makeVoidType(), Op::OpExtInst); @@ -826,13 +826,13 @@ Id Builder::makeDebugFunctionType(Id returnType, const std::vector& paramTyp type->addIdOperand(nonSemanticShaderDebugInfo); type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeFunction); type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); - type->addIdOperand(debugId[returnType]); + type->addIdOperand(getDebugType(returnType)); for (auto const paramType : paramTypes) { if (isPointerType(paramType) || isArrayType(paramType)) { - type->addIdOperand(debugId[getContainedTypeId(paramType)]); + type->addIdOperand(getDebugType(getContainedTypeId(paramType))); } else { - type->addIdOperand(debugId[paramType]); + type->addIdOperand(getDebugType(paramType)); } } constantsTypesGlobals.push_back(std::unique_ptr(type)); @@ -923,7 +923,7 @@ Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, boo if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeOpaqueDebugType(debugName); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -950,7 +950,7 @@ Id Builder::makeSampledImageType(Id imageType, const char* debugName) if (emitNonSemanticShaderDebugInfo) { auto const debugResultId = makeOpaqueDebugType(debugName); - debugId[type->getResultId()] = debugResultId; + debugTypeIdLookup[type->getResultId()] = debugResultId; } return type->getResultId(); @@ -1099,7 +1099,7 @@ Id Builder::makeSequentialDebugType(Id const baseType, Id const componentCount, type->reserveOperands(4); type->addIdOperand(nonSemanticShaderDebugInfo); type->addImmediateOperand(sequenceType); - type->addIdOperand(debugId[baseType]); // base type + type->addIdOperand(getDebugType(baseType)); // base type type->addIdOperand(componentCount); // component count groupedDebugTypes[sequenceType].push_back(type); @@ -1135,7 +1135,7 @@ Id Builder::makeMatrixDebugType(Id const vectorType, int const vectorCount, bool type->reserveOperands(5); type->addIdOperand(nonSemanticShaderDebugInfo); type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMatrix); - type->addIdOperand(debugId[vectorType]); // vector type id + type->addIdOperand(getDebugType(vectorType)); // vector type id type->addIdOperand(makeUintConstant(vectorCount)); // component count id type->addIdOperand(makeBoolConstant(columnMajor)); // column-major id @@ -1148,7 +1148,7 @@ Id Builder::makeMatrixDebugType(Id const vectorType, int const vectorCount, bool Id Builder::makeMemberDebugType(Id const memberType, StructMemberDebugInfo const& debugTypeLoc) { - assert(debugId[memberType] != 0); + assert(getDebugType(memberType) != NoType); Instruction* type = new Instruction(getUniqueId(), makeVoidType(), Op::OpExtInst); type->reserveOperands(10); @@ -1156,7 +1156,7 @@ Id Builder::makeMemberDebugType(Id const memberType, StructMemberDebugInfo const type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember); type->addIdOperand(getStringId(debugTypeLoc.name)); // name id type->addIdOperand(debugTypeLoc.debugTypeOverride != 0 ? debugTypeLoc.debugTypeOverride - : debugId[memberType]); // type id + : getDebugType(memberType)); // type id type->addIdOperand(makeDebugSource(currentFileId)); // source id type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id @@ -1178,7 +1178,7 @@ Id Builder::makeCompositeDebugType(std::vector const& memberTypes, std::vect std::vector memberDebugTypes; assert(memberTypes.size() == memberDebugInfo.size()); for (size_t i = 0; i < memberTypes.size(); i++) { - if (debugId[memberTypes[i]]) { + if (getDebugType(memberTypes[i]) != NoType) { memberDebugTypes.emplace_back(makeMemberDebugType(memberTypes[i], memberDebugInfo[i])); } } @@ -1238,7 +1238,7 @@ Id Builder::makeOpaqueDebugType(char const* const name) Id Builder::makePointerDebugType(StorageClass storageClass, Id const baseType) { - const Id debugBaseType = debugId[baseType]; + const Id debugBaseType = getDebugType(baseType); if (!debugBaseType) { return makeDebugInfoNone(); } @@ -1474,7 +1474,7 @@ Id Builder::makeAccelerationStructureType() module.mapInstruction(type); if (emitNonSemanticShaderDebugInfo) { spv::Id debugType = makeOpaqueDebugType("accelerationStructure"); - debugId[type->getResultId()] = debugType; + debugTypeIdLookup[type->getResultId()] = debugType; } } else { type = groupedTypes[enumCast(Op::OpTypeAccelerationStructureKHR)].back(); @@ -1493,7 +1493,7 @@ Id Builder::makeRayQueryType() module.mapInstruction(type); if (emitNonSemanticShaderDebugInfo) { spv::Id debugType = makeOpaqueDebugType("rayQuery"); - debugId[type->getResultId()] = debugType; + debugTypeIdLookup[type->getResultId()] = debugType; } } else { type = groupedTypes[enumCast(Op::OpTypeRayQueryKHR)].back(); @@ -1526,7 +1526,7 @@ Id Builder::makeHitObjectNVType() module.mapInstruction(type); if (emitNonSemanticShaderDebugInfo) { spv::Id debugType = makeOpaqueDebugType("hitObjectNV"); - debugId[type->getResultId()] = debugType; + debugTypeIdLookup[type->getResultId()] = debugType; } } else { type = groupedTypes[enumCast(Op::OpTypeHitObjectNV)].back(); @@ -1734,32 +1734,17 @@ bool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const // can be reused rather than duplicated. (Required by the specification). Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) { - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[enumCast(typeClass)].size(); ++i) { - constant = groupedConstants[enumCast(typeClass)][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == value) - return constant->getResultId(); - } - - return 0; + ScalarConstantKey key{ enumCast(typeClass), enumCast(opcode), typeId, value, 0 }; + auto it = groupedScalarConstantResultIDs.find(key); + return (it != groupedScalarConstantResultIDs.end()) ? it->second : 0; } // Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64'). Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) { - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[enumCast(typeClass)].size(); ++i) { - constant = groupedConstants[enumCast(typeClass)][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == v1 && - constant->getImmediateOperand(1) == v2) - return constant->getResultId(); - } - - return 0; + ScalarConstantKey key{ enumCast(typeClass), enumCast(opcode), typeId, v1, v2 }; + auto it = groupedScalarConstantResultIDs.find(key); + return (it != groupedScalarConstantResultIDs.end()) ? it->second : 0; } // Return true if consuming 'opcode' means consuming a constant. @@ -1831,19 +1816,12 @@ Id Builder::makeNullConstant(Id typeId) Id Builder::makeBoolConstant(bool b, bool specConstant) { Id typeId = makeBoolType(); - Instruction* constant; Op opcode = specConstant ? (b ? Op::OpSpecConstantTrue : Op::OpSpecConstantFalse) : (b ? Op::OpConstantTrue : Op::OpConstantFalse); // See if we already made it. Applies only to regular constants, because specialization constants // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = 0; - for (int i = 0; i < (int)groupedConstants[enumCast(Op::OpTypeBool)].size(); ++i) { - constant = groupedConstants[enumCast(Op::OpTypeBool)][i]; - if (constant->getTypeId() == typeId && constant->getOpCode() == opcode) - existing = constant->getResultId(); - } - + if (!specConstant) { + Id existing = findScalarConstant(Op::OpTypeBool, opcode, typeId, 0); if (existing) return existing; } @@ -1851,10 +1829,14 @@ Id Builder::makeBoolConstant(bool b, bool specConstant) // Make it Instruction* c = new Instruction(getUniqueId(), typeId, opcode); constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[enumCast(Op::OpTypeBool)].push_back(c); module.mapInstruction(c); - return c->getResultId(); + Id resultId = c->getResultId(); + if (!specConstant) { + ScalarConstantKey key{enumCast(Op::OpTypeBool), enumCast(opcode), typeId, 0, 0}; + groupedScalarConstantResultIDs[key] = resultId; + } + return resultId; } Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant) @@ -1872,10 +1854,14 @@ Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant) Instruction* c = new Instruction(getUniqueId(), typeId, opcode); c->addImmediateOperand(value); constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[enumCast(Op::OpTypeInt)].push_back(c); module.mapInstruction(c); - return c->getResultId(); + Id resultId = c->getResultId(); + if (!specConstant) { + ScalarConstantKey key{ enumCast(Op::OpTypeInt), enumCast(opcode), typeId, value, 0 }; + groupedScalarConstantResultIDs[key] = resultId; + } + return resultId; } Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant) @@ -1898,10 +1884,14 @@ Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specCons c->addImmediateOperand(op1); c->addImmediateOperand(op2); constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[enumCast(Op::OpTypeInt)].push_back(c); module.mapInstruction(c); - return c->getResultId(); + Id resultId = c->getResultId(); + if (!specConstant) { + ScalarConstantKey key{ enumCast(Op::OpTypeInt), enumCast(opcode), typeId, op1, op2 }; + groupedScalarConstantResultIDs[key] = resultId; + } + return resultId; } Id Builder::makeFloatConstant(float f, bool specConstant) @@ -1923,10 +1913,14 @@ Id Builder::makeFloatConstant(float f, bool specConstant) Instruction* c = new Instruction(getUniqueId(), typeId, opcode); c->addImmediateOperand(value); constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[enumCast(Op::OpTypeFloat)].push_back(c); module.mapInstruction(c); - return c->getResultId(); + Id resultId = c->getResultId(); + if (!specConstant) { + ScalarConstantKey key{ enumCast(Op::OpTypeFloat), enumCast(opcode), typeId, value, 0 }; + groupedScalarConstantResultIDs[key] = resultId; + } + return resultId; } Id Builder::makeDoubleConstant(double d, bool specConstant) @@ -1952,10 +1946,14 @@ Id Builder::makeDoubleConstant(double d, bool specConstant) c->addImmediateOperand(op1); c->addImmediateOperand(op2); constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[enumCast(Op::OpTypeFloat)].push_back(c); module.mapInstruction(c); - return c->getResultId(); + Id resultId = c->getResultId(); + if (!specConstant) { + ScalarConstantKey key{ enumCast(Op::OpTypeFloat), enumCast(opcode), typeId, op1, op2 }; + groupedScalarConstantResultIDs[key] = resultId; + } + return resultId; } Id Builder::makeFloat16Constant(float f16, bool specConstant) @@ -1980,10 +1978,14 @@ Id Builder::makeFloat16Constant(float f16, bool specConstant) Instruction* c = new Instruction(getUniqueId(), typeId, opcode); c->addImmediateOperand(value); constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[enumCast(Op::OpTypeFloat)].push_back(c); module.mapInstruction(c); - return c->getResultId(); + Id resultId = c->getResultId(); + if (!specConstant) { + ScalarConstantKey key{ enumCast(Op::OpTypeFloat), enumCast(opcode), typeId, value, 0 }; + groupedScalarConstantResultIDs[key] = resultId; + } + return resultId; } Id Builder::makeBFloat16Constant(float bf16, bool specConstant) @@ -2011,10 +2013,14 @@ Id Builder::makeBFloat16Constant(float bf16, bool specConstant) Instruction* c = new Instruction(getUniqueId(), typeId, opcode); c->addImmediateOperand(value); constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[enumCast(Op::OpTypeFloat)].push_back(c); module.mapInstruction(c); - return c->getResultId(); + Id resultId = c->getResultId(); + if (!specConstant) { + ScalarConstantKey key{ enumCast(Op::OpTypeFloat), enumCast(opcode), typeId, value, 0 }; + groupedScalarConstantResultIDs[key] = resultId; + } + return resultId; } Id Builder::makeFloatE5M2Constant(float fe5m2, bool specConstant) @@ -2039,10 +2045,14 @@ Id Builder::makeFloatE5M2Constant(float fe5m2, bool specConstant) Instruction* c = new Instruction(getUniqueId(), typeId, opcode); c->addImmediateOperand(value); constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[enumCast(Op::OpTypeFloat)].push_back(c); module.mapInstruction(c); - return c->getResultId(); + Id resultId = c->getResultId(); + if (!specConstant) { + ScalarConstantKey key{enumCast(Op::OpTypeFloat), enumCast(opcode), typeId, value, 0}; + groupedScalarConstantResultIDs[key] = resultId; + } + return resultId; } Id Builder::makeFloatE4M3Constant(float fe4m3, bool specConstant) @@ -2067,10 +2077,14 @@ Id Builder::makeFloatE4M3Constant(float fe4m3, bool specConstant) Instruction* c = new Instruction(getUniqueId(), typeId, opcode); c->addImmediateOperand(value); constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[enumCast(Op::OpTypeFloat)].push_back(c); module.mapInstruction(c); - return c->getResultId(); + Id resultId = c->getResultId(); + if (!specConstant) { + ScalarConstantKey key{enumCast(Op::OpTypeFloat), enumCast(opcode), typeId, value, 0}; + groupedScalarConstantResultIDs[key] = resultId; + } + return resultId; } Id Builder::makeFpConstant(Id type, double d, bool specConstant) @@ -2111,8 +2125,8 @@ Id Builder::findCompositeConstant(Op typeClass, Op opcode, Id typeId, const std: { Instruction* constant = nullptr; bool found = false; - for (int i = 0; i < (int)groupedConstants[enumCast(typeClass)].size(); ++i) { - constant = groupedConstants[enumCast(typeClass)][i]; + for (int i = 0; i < (int)groupedCompositeConstants[enumCast(typeClass)].size(); ++i) { + constant = groupedCompositeConstants[enumCast(typeClass)][i]; if (constant->getTypeId() != typeId) continue; @@ -2222,7 +2236,7 @@ Id Builder::makeCompositeConstant(Id typeId, const std::vector& members, boo if (typeClass == Op::OpTypeStruct) groupedStructConstants[typeId].push_back(c); else - groupedConstants[enumCast(typeClass)].push_back(c); + groupedCompositeConstants[enumCast(typeClass)].push_back(c); module.mapInstruction(c); return c->getResultId(); @@ -2603,14 +2617,14 @@ void Builder::setupFunctionDebugInfo(Function* function, const char* name, const Id nameId = getStringId(unmangleFunctionName(name)); Id funcTypeId = function->getFuncTypeId(); - assert(debugId[funcTypeId] != 0); + assert(getDebugType(funcTypeId) != NoType); Id funcId = function->getId(); assert(funcId != 0); // Make the debug function instruction Id debugFuncId = makeDebugFunction(function, nameId, funcTypeId); - debugId[funcId] = debugFuncId; + debugFuncIdLookup[funcId] = debugFuncId; currentDebugScopeId.push(debugFuncId); // DebugScope and DebugLine for parameter DebugDeclares @@ -2629,9 +2643,8 @@ void Builder::setupFunctionDebugInfo(Function* function, const char* name, const } auto const& paramName = paramNames[p]; - auto const debugLocalVariableId = createDebugLocalVariable(debugId[paramTypeId], paramName, p + 1); + auto const debugLocalVariableId = createDebugLocalVariable(getDebugType(paramTypeId), paramName, p + 1); auto const paramId = static_cast(firstParamId + p); - debugId[paramId] = debugLocalVariableId; if (passByRef) { makeDebugDeclare(debugLocalVariableId, paramId); @@ -2651,7 +2664,7 @@ Id Builder::makeDebugFunction([[maybe_unused]] Function* function, Id nameId, Id assert(function != nullptr); assert(nameId != 0); assert(funcTypeId != 0); - assert(debugId[funcTypeId] != 0); + assert(getDebugType(funcTypeId) != NoType); Id funcId = getUniqueId(); auto type = new Instruction(funcId, makeVoidType(), Op::OpExtInst); @@ -2659,7 +2672,7 @@ Id Builder::makeDebugFunction([[maybe_unused]] Function* function, Id nameId, Id type->addIdOperand(nonSemanticShaderDebugInfo); type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunction); type->addIdOperand(nameId); - type->addIdOperand(debugId[funcTypeId]); + type->addIdOperand(getDebugType(funcTypeId)); type->addIdOperand(makeDebugSource(currentFileId)); // TODO: This points to file of definition instead of declaration type->addIdOperand(makeUintConstant(currentLine)); // TODO: This points to line of definition instead of declaration type->addIdOperand(makeUintConstant(0)); // column @@ -2754,14 +2767,15 @@ void Builder::enterFunction(Function const* function) if (emitNonSemanticShaderDebugInfo) { // Initialize scope state Id funcId = function->getFuncId(); - currentDebugScopeId.push(debugId[funcId]); + Id debugFuncId = getDebugFunction(funcId); + currentDebugScopeId.push(debugFuncId); // Create DebugFunctionDefinition spv::Id resultId = getUniqueId(); Instruction* defInst = new Instruction(resultId, makeVoidType(), Op::OpExtInst); defInst->reserveOperands(4); defInst->addIdOperand(nonSemanticShaderDebugInfo); defInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunctionDefinition); - defInst->addIdOperand(debugId[funcId]); + defInst->addIdOperand(debugFuncId); defInst->addIdOperand(funcId); addInstruction(std::unique_ptr(defInst)); } @@ -2855,14 +2869,11 @@ Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id t // We may emulate some local variables as global variable with private storage in SPIR-V, but we still want to // treat them as local variables in debug info. if (storageClass == StorageClass::Function || (currentFunction && storageClass == StorageClass::Private)) { - auto const debugLocalVariableId = createDebugLocalVariable(debugId[type], name); - debugId[inst->getResultId()] = debugLocalVariableId; - + auto const debugLocalVariableId = createDebugLocalVariable(getDebugType(type), name); makeDebugDeclare(debugLocalVariableId, inst->getResultId()); } else { - auto const debugResultId = createDebugGlobalVariable(debugId[type], name, inst->getResultId()); - debugId[inst->getResultId()] = debugResultId; + createDebugGlobalVariable(getDebugType(type), name, inst->getResultId()); } } diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.h b/3rdparty/glslang/SPIRV/SpvBuilder.h index 68b4764c4..70c1defb7 100644 --- a/3rdparty/glslang/SPIRV/SpvBuilder.h +++ b/3rdparty/glslang/SPIRV/SpvBuilder.h @@ -208,10 +208,20 @@ public: // Maps the given OpType Id to a Non-Semantic DebugType Id. Id getDebugType(Id type) { - if (emitNonSemanticShaderDebugInfo) { - return debugId[type]; + if (auto it = debugTypeIdLookup.find(type); it != debugTypeIdLookup.end()) { + return it->second; } - return 0; + + return NoType; + } + + // Maps the given OpFunction Id to a Non-Semantic DebugFunction Id. + Id getDebugFunction(Id func) { + if (auto it = debugFuncIdLookup.find(func); it != debugFuncIdLookup.end()) { + return it->second; + } + + return NoResult; } // For creating new types (will return old type if the requested one was already made). @@ -1031,8 +1041,58 @@ protected: // not output, internally used for quick & dirty canonical (unique) creation + // Key for scalar constants (handles both 32-bit and 64-bit) + struct ScalarConstantKey { + unsigned int typeClass; // OpTypeInt, OpTypeFloat, OpTypeBool + unsigned int opcode; // OpConstant, OpSpecConstant, OpConstantTrue, etc. + Id typeId; // The specific type + unsigned value1; // First operand (or only operand) + unsigned value2; // Second operand (0 for single-operand constants) + + bool operator==(const ScalarConstantKey& other) const { + return typeClass == other.typeClass && + opcode == other.opcode && + typeId == other.typeId && + value1 == other.value1 && + value2 == other.value2; + } + }; + + struct ScalarConstantKeyHash { + // 64/32 bit mix function from MurmurHash3 + inline std::size_t hash_mix(std::size_t h) const { + if constexpr (sizeof(std::size_t) == 8) { + h ^= h >> 33; + h *= UINT64_C(0xff51afd7ed558ccd); + h ^= h >> 33; + h *= UINT64_C(0xc4ceb9fe1a85ec53); + h ^= h >> 33; + return h; + } else { + h ^= h >> 16; + h *= UINT32_C(0x85ebca6b); + h ^= h >> 13; + h *= UINT32_C(0xc2b2ae35); + h ^= h >> 16; + return h; + } + } + + // Hash combine from boost + inline std::size_t hash_combine(std::size_t seed, std::size_t v) const { + return hash_mix(seed + 0x9e3779b9 + v); + } + + std::size_t operator()(const ScalarConstantKey& k) const { + size_t hash1 = hash_combine(std::hash{}(k.typeClass), std::hash{}(k.opcode)); + size_t hash2 = hash_combine(std::hash{}(k.value1), std::hash{}(k.value2)); + size_t hash3 = hash_combine(hash1, hash2); + return hash_combine(hash3, std::hash{}(k.typeId)); + } + }; + // map type opcodes to constant inst. - std::unordered_map> groupedConstants; + std::unordered_map> groupedCompositeConstants; // map struct-id to constant instructions std::unordered_map> groupedStructConstants; // map type opcodes to type instructions @@ -1041,6 +1101,8 @@ protected: std::unordered_map> groupedDebugTypes; // list of OpConstantNull instructions std::vector nullConstants; + // map scalar constants to result IDs + std::unordered_map groupedScalarConstantResultIDs; // Track which types have explicit layouts, to avoid reusing in storage classes without layout. // Currently only tracks array types. @@ -1058,8 +1120,11 @@ protected: // map from include file name ids to their contents std::map includeFiles; - // map from core id to debug id - std::map debugId; + // maps from OpTypeXXX id to DebugTypeXXX id + std::unordered_map debugTypeIdLookup; + + // maps from OpFunction id to DebugFunction id + std::unordered_map debugFuncIdLookup; // map from file name string id to DebugSource id std::unordered_map debugSourceId; diff --git a/3rdparty/glslang/build_info.h b/3rdparty/glslang/build_info.h index d8f2a74ce..7816b66d2 100644 --- a/3rdparty/glslang/build_info.h +++ b/3rdparty/glslang/build_info.h @@ -35,7 +35,7 @@ #define GLSLANG_BUILD_INFO #define GLSLANG_VERSION_MAJOR 16 -#define GLSLANG_VERSION_MINOR 0 +#define GLSLANG_VERSION_MINOR 1 #define GLSLANG_VERSION_PATCH 0 #define GLSLANG_VERSION_FLAVOR "" diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp index 667ed6780..38ce7bd69 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp @@ -4188,6 +4188,10 @@ void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& ide // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be // declared in a shader; this results in a compile-time error." if (! symbolTable.atBuiltInLevel()) { + // The extension GL_EXT_conservative_depth allows us to declare "gl_FragDepth". + if (identifier == "gl_FragDepth" && extensionTurnedOn(E_GL_EXT_conservative_depth)) + return; + if (builtInName(identifier) && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) // The extension GL_EXT_spirv_intrinsics allows us to declare identifiers starting with "gl_". error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), ""); @@ -5830,7 +5834,8 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS bool nonEsRedecls = (!isEsProfile() && (version >= 130 || identifier == "gl_TexCoord")); bool esRedecls = (isEsProfile() && - (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks))); + (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks) || + (identifier == "gl_FragDepth" && extensionTurnedOn(E_GL_EXT_conservative_depth)))); if (! esRedecls && ! nonEsRedecls) return nullptr; @@ -6535,6 +6540,9 @@ void TParseContext::finish() if (parsingBuiltins) return; + // Forward builtin alias to AST for later use + intermediate.setBuiltinAliasLookup(symbolTable.collectBuiltinAlias()); + // Check on array indexes for ES 2.0 (version 100) limitations. for (size_t i = 0; i < needsIndexLimitationChecking.size(); ++i) constantIndexExpressionCheck(needsIndexLimitationChecking[i]); diff --git a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h b/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h index edeb8d540..916192749 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h +++ b/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h @@ -70,6 +70,7 @@ #include "../Include/InfoSink.h" #include +#include namespace glslang { @@ -505,6 +506,11 @@ public: retargetedSymbols.push_back({from, to}); } + void collectRetargetedSymbols(std::unordered_multimap &out) const { + for (const auto &[fromName, toName] : retargetedSymbols) + out.insert({std::string{toName}, std::string{fromName}}); + } + TSymbol* find(const TString& name) const { tLevel::const_iterator it = level.find(name); @@ -662,9 +668,10 @@ public: // protected: static const uint32_t LevelFlagBitOffset = 56; - static const int globalLevel = 3; + static constexpr int builtinLevel = 2; + static constexpr int globalLevel = 3; static bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels - static bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals + static bool isBuiltInLevel(int level) { return level <= builtinLevel; } // exclude user globals static bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals public: bool isEmpty() { return table.size() == 0; } @@ -829,6 +836,13 @@ public: table[level]->retargetSymbol(from, to); } + std::unordered_multimap collectBuiltinAlias() { + std::unordered_multimap allRetargets; + for (int level = 0; level <= std::min(currentLevel(), builtinLevel); ++level) + table[level]->collectRetargetedSymbols(allRetargets); + + return allRetargets; + } // Find of a symbol that returns how many layers deep of nested // structures-with-member-functions ('this' scopes) deep the symbol was diff --git a/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp b/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp index e8ce15097..e01f96be4 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp @@ -728,8 +728,8 @@ void TParseVersions::getPreamble(std::string& preamble) case EShLangClosestHit: preamble += "#define GL_CLOSEST_HIT_SHADER_EXT 1 \n"; break; case EShLangMiss: preamble += "#define GL_MISS_SHADER_EXT 1 \n"; break; case EShLangCallable: preamble += "#define GL_CALLABLE_SHADER_EXT 1 \n"; break; - case EShLangTask: preamble += "#define GL_TASK_SHADER_NV 1 \n"; break; - case EShLangMesh: preamble += "#define GL_MESH_SHADER_NV 1 \n"; break; + case EShLangTask: preamble += "#define GL_TASK_SHADER_EXT 1 \n"; break; + case EShLangMesh: preamble += "#define GL_MESH_SHADER_EXT 1 \n"; break; default: break; } } diff --git a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h index 2e1074456..ce57ce4ca 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h +++ b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h @@ -48,6 +48,7 @@ #include #include #include +#include #include class TInfoSink; @@ -1161,6 +1162,13 @@ public: void updateNumericFeature(TNumericFeatures::feature f, bool on) { on ? numericFeatures.insert(f) : numericFeatures.erase(f); } + void setBuiltinAliasLookup(std::unordered_multimap symbolMap) { + builtinAliasLookup = std::move(symbolMap); + } + const std::unordered_multimap& getBuiltinAliasLookup() const { + return builtinAliasLookup; + } + protected: TIntermSymbol* addSymbol(long long Id, const TString&, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); void error(TInfoSink& infoSink, const TSourceLoc* loc, EShMessages messages, const char*, EShLanguage unitStage = EShLangCount); @@ -1335,6 +1343,9 @@ protected: // Included text. First string is a name, second is the included text std::map includeText; + // Maps from canonical symbol name to alias symbol names + std::unordered_multimap builtinAliasLookup; + // for OpModuleProcessed, or equivalent TProcesses processes;