Implement NonSemantic.Shader.DebugInfo.100
See https://github.com/KhronosGroup/SPIRV-Registry.
This commit is contained in:
@@ -1557,6 +1557,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;
|
||||
@@ -2498,6 +2502,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;
|
||||
@@ -2758,32 +2770,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;
|
||||
@@ -2812,6 +2830,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);
|
||||
@@ -3796,8 +3815,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();
|
||||
@@ -4016,7 +4035,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.
|
||||
@@ -4104,7 +4123,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);
|
||||
@@ -4422,14 +4441,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;
|
||||
@@ -4437,7 +4456,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
|
||||
@@ -4448,25 +4467,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;
|
||||
|
||||
@@ -5060,6 +5092,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();
|
||||
|
||||
@@ -5084,10 +5117,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();
|
||||
@@ -5177,6 +5214,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,
|
||||
|
||||
Reference in New Issue
Block a user