Merge pull request #2985 from jeremy-lunarg/hayes-nonsemantic-shader-debuginfo-rebase

Implement NonSemantic.Shader.DebugInfo.100 debug instruction generation.

These instructions will be generated under the -gV and -gVS  command line options. These instructions enable source-level shader debugging with Renderdoc.

This is an alpha release of this capability. Additional improvements are forthcoming. Use and feedback are welcome.
This commit is contained in:
Greg Fischer
2022-09-09 10:13:02 -06:00
committed by GitHub
55 changed files with 11275 additions and 96 deletions

View File

@@ -1578,6 +1578,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
for (auto iItr = include_txt.begin(); iItr != include_txt.end(); ++iItr)
builder.addInclude(iItr->first, iItr->second);
}
builder.setEmitNonSemanticShaderDebugInfo(options.emitNonSemanticShaderDebugInfo);
builder.setEmitNonSemanticShaderDebugSource(options.emitNonSemanticShaderDebugSource);
stdBuiltins = builder.import("GLSL.std.450");
spv::AddressingModel addressingModel = spv::AddressingModelLogical;
@@ -2526,6 +2530,14 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
return false;
}
// Force variable declaration - Debug Mode Only
if (node->getOp() == glslang::EOpDeclare) {
builder.clearAccessChain();
node->getOperand()->traverse(this);
builder.clearAccessChain();
return false;
}
// Start by evaluating the operand
// Does it need a swizzle inversion? If so, evaluation is inverted;
@@ -2786,32 +2798,38 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
switch (node->getOp()) {
case glslang::EOpScope:
case glslang::EOpSequence:
{
if (preVisit)
if (visit == glslang::EvPreVisit) {
++sequenceDepth;
else
if (sequenceDepth == 1) {
// If this is the parent node of all the functions, we want to see them
// early, so all call points have actual SPIR-V functions to reference.
// In all cases, still let the traverser visit the children for us.
makeFunctions(node->getAsAggregate()->getSequence());
// Also, we want all globals initializers to go into the beginning of the entry point, before
// anything else gets there, so visit out of order, doing them all now.
makeGlobalInitializers(node->getAsAggregate()->getSequence());
//Pre process linker objects for ray tracing stages
if (glslangIntermediate->isRayTracingStage())
collectRayTracingLinkerObjects();
// Initializers are done, don't want to visit again, but functions and link objects need to be processed,
// so do them manually.
visitFunctions(node->getAsAggregate()->getSequence());
return false;
} else {
if (node->getOp() == glslang::EOpScope)
builder.enterScope(0);
}
} else {
if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope)
builder.leaveScope();
--sequenceDepth;
if (sequenceDepth == 1) {
// If this is the parent node of all the functions, we want to see them
// early, so all call points have actual SPIR-V functions to reference.
// In all cases, still let the traverser visit the children for us.
makeFunctions(node->getAsAggregate()->getSequence());
// Also, we want all globals initializers to go into the beginning of the entry point, before
// anything else gets there, so visit out of order, doing them all now.
makeGlobalInitializers(node->getAsAggregate()->getSequence());
//Pre process linker objects for ray tracing stages
if (glslangIntermediate->isRayTracingStage())
collectRayTracingLinkerObjects();
// Initializers are done, don't want to visit again, but functions and link objects need to be processed,
// so do them manually.
visitFunctions(node->getAsAggregate()->getSequence());
return false;
}
return true;
@@ -2840,6 +2858,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
if (isShaderEntryPoint(node)) {
inEntryPoint = true;
builder.setBuildPoint(shaderEntry->getLastBlock());
builder.enterFunction(shaderEntry);
currentFunction = shaderEntry;
} else {
handleFunctionEntry(node);
@@ -3826,8 +3845,8 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
// by a block-ending branch. But we don't want to put any other body/test
// instructions in it, since the body/test may have arbitrary instructions,
// including merges of its own.
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
builder.setBuildPoint(&blocks.head);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands);
if (node->testFirst() && node->getTest()) {
spv::Block& test = builder.makeNewBlock();
@@ -4046,7 +4065,7 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
initializer = builder.makeNullConstant(spvType);
}
return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer);
return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer, false);
}
// Return type Id of the sampled type.
@@ -4134,7 +4153,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
if (explicitLayout != glslang::ElpNone)
spvType = builder.makeUintType(32);
else
spvType = builder.makeBoolType();
spvType = builder.makeBoolType(false);
break;
case glslang::EbtInt:
spvType = builder.makeIntType(32);
@@ -4454,14 +4473,14 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
// except sometimes for blocks
std::vector<std::pair<glslang::TType*, glslang::TQualifier> > deferredForwardPointers;
for (int i = 0; i < (int)glslangMembers->size(); i++) {
glslang::TType& glslangMember = *(*glslangMembers)[i].type;
if (glslangMember.hiddenMember()) {
auto& glslangMember = (*glslangMembers)[i];
if (glslangMember.type->hiddenMember()) {
++memberDelta;
if (type.getBasicType() == glslang::EbtBlock)
memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
} else {
if (type.getBasicType() == glslang::EbtBlock) {
if (filterMember(glslangMember)) {
if (filterMember(*glslangMember.type)) {
memberDelta++;
memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
continue;
@@ -4469,7 +4488,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta;
}
// modify just this child's view of the qualifier
glslang::TQualifier memberQualifier = glslangMember.getQualifier();
glslang::TQualifier memberQualifier = glslangMember.type->getQualifier();
InheritQualifiers(memberQualifier, qualifier);
// manually inherit location
@@ -4480,25 +4499,38 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
bool lastBufferBlockMember = qualifier.storage == glslang::EvqBuffer &&
i == (int)glslangMembers->size() - 1;
// Make forward pointers for any pointer members, and create a list of members to
// convert to spirv types after creating the struct.
if (glslangMember.isReference()) {
if (forwardPointers.find(glslangMember.getReferentType()) == forwardPointers.end()) {
deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier));
}
spvMembers.push_back(
convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
true));
} else {
spvMembers.push_back(
convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
false));
// Make forward pointers for any pointer members.
if (glslangMember.type->isReference() &&
forwardPointers.find(glslangMember.type->getReferentType()) == forwardPointers.end()) {
deferredForwardPointers.push_back(std::make_pair(glslangMember.type, memberQualifier));
}
// Create the member type.
auto const spvMember = convertGlslangToSpvType(*glslangMember.type, explicitLayout, memberQualifier, lastBufferBlockMember,
glslangMember.type->isReference());
spvMembers.push_back(spvMember);
// Update the builder with the type's location so that we can create debug types for the structure members.
// There doesn't exist a "clean" entry point for this information to be passed along to the builder so, for now,
// it is stored in the builder and consumed during the construction of composite debug types.
// TODO: This probably warrants further investigation. This approach was decided to be the least ugly of the
// quick and dirty approaches that were tried.
// Advantages of this approach:
// + Relatively clean. No direct calls into debug type system.
// + Handles nested recursive structures.
// Disadvantages of this approach:
// + Not as clean as desired. Traverser queries/sets persistent state. This is fragile.
// + Table lookup during creation of composite debug types. This really shouldn't be necessary.
if(options.emitNonSemanticShaderDebugInfo) {
builder.debugTypeLocs[spvMember].name = glslangMember.type->getFieldName().c_str();
builder.debugTypeLocs[spvMember].line = glslangMember.loc.line;
builder.debugTypeLocs[spvMember].column = glslangMember.loc.column;
}
}
}
// Make the SPIR-V type
spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str());
spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str(), false);
if (! HasNonLayoutQualifiers(type, qualifier))
structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType;
@@ -5092,6 +5124,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
// GLSL has copy-in/copy-out semantics. They can be handled though with a pointer to a copy.
std::vector<spv::Id> paramTypes;
std::vector<char const*> paramNames;
std::vector<std::vector<spv::Decoration>> paramDecorations; // list of decorations per parameter
glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence();
@@ -5116,10 +5149,14 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
paramTypes.push_back(typeId);
}
for (auto const parameter:parameters) {
paramNames.push_back(parameter->getAsSymbolNode()->getName().c_str());
}
spv::Block* functionBlock;
spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()),
convertGlslangToSpvType(glslFunction->getType()),
glslFunction->getName().c_str(), paramTypes,
glslFunction->getName().c_str(), paramTypes, paramNames,
paramDecorations, &functionBlock);
if (implicitThis)
function->setImplicitThis();
@@ -5209,6 +5246,7 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate
currentFunction = functionMap[node->getName().c_str()];
spv::Block* functionBlock = currentFunction->getEntryBlock();
builder.setBuildPoint(functionBlock);
builder.enterFunction(currentFunction);
}
void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,