Updated glslang.

This commit is contained in:
Бранимир Караџић
2025-12-13 11:47:58 -08:00
committed by Branimir Karadžić
parent f78f1aee10
commit 59e6b4efbb
8 changed files with 236 additions and 116 deletions

View File

@@ -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<spv::Decoration> 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);
}

View File

@@ -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<Id>& members, const std::vector<spv
assert(members.size() == memberDebugInfo.size());
auto const debugResultId =
makeCompositeDebugType(members, memberDebugInfo, name, NonSemanticShaderDebugInfo100Structure);
debugId[type->getResultId()] = 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<Id>& 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<Id>& 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<Id>& paramTypes)
Id Builder::makeDebugFunctionType(Id returnType, const std::vector<Id>& 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<Id>& 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<Instruction>(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<Id> const& memberTypes, std::vect
std::vector<Id> 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<Instruction>(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<Instruction>(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<Instruction>(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<Instruction>(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<Instruction>(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<Instruction>(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<Instruction>(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<Instruction>(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<Instruction>(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<Id>& 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<Id>(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<Instruction>(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());
}
}

View File

@@ -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<unsigned>{}(k.typeClass), std::hash<unsigned>{}(k.opcode));
size_t hash2 = hash_combine(std::hash<Id>{}(k.value1), std::hash<unsigned>{}(k.value2));
size_t hash3 = hash_combine(hash1, hash2);
return hash_combine(hash3, std::hash<unsigned>{}(k.typeId));
}
};
// map type opcodes to constant inst.
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedCompositeConstants;
// map struct-id to constant instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
// map type opcodes to type instructions
@@ -1041,6 +1101,8 @@ protected:
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedDebugTypes;
// list of OpConstantNull instructions
std::vector<Instruction*> nullConstants;
// map scalar constants to result IDs
std::unordered_map<ScalarConstantKey, Id, ScalarConstantKeyHash> 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<spv::Id, const std::string*> includeFiles;
// map from core id to debug id
std::map <spv::Id, spv::Id> debugId;
// maps from OpTypeXXX id to DebugTypeXXX id
std::unordered_map<spv::Id, spv::Id> debugTypeIdLookup;
// maps from OpFunction id to DebugFunction id
std::unordered_map<spv::Id, spv::Id> debugFuncIdLookup;
// map from file name string id to DebugSource id
std::unordered_map<spv::Id, spv::Id> debugSourceId;

View File

@@ -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 ""

View File

@@ -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]);

View File

@@ -70,6 +70,7 @@
#include "../Include/InfoSink.h"
#include <functional>
#include <unordered_map>
namespace glslang {
@@ -505,6 +506,11 @@ public:
retargetedSymbols.push_back({from, to});
}
void collectRetargetedSymbols(std::unordered_multimap<std::string, std::string> &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<std::string, std::string> collectBuiltinAlias() {
std::unordered_multimap<std::string, std::string> 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

View File

@@ -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;
}
}

View File

@@ -48,6 +48,7 @@
#include <functional>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
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<std::string, std::string> symbolMap) {
builtinAliasLookup = std::move(symbolMap);
}
const std::unordered_multimap<std::string, std::string>& 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<std::string, std::string> includeText;
// Maps from canonical symbol name to alias symbol names
std::unordered_multimap<std::string, std::string> builtinAliasLookup;
// for OpModuleProcessed, or equivalent
TProcesses processes;