Skip to content

Commit 0773a49

Browse files
committed
Improve DXIL callstack generation
Resolve debug scopes in a separate pass before callstacks Walk callstacks using DILocation (DebugLocation) data (dwarf scopes and inlinedAt data) For each DILocation Walk scope upwards to fill in the callstack (always a dwarf scope) Make new DILocation from inlinedAt and walk that DILocation
1 parent 63e07b3 commit 0773a49

File tree

1 file changed

+72
-46
lines changed

1 file changed

+72
-46
lines changed

renderdoc/driver/shaders/dxil/dxil_debug.cpp

+72-46
Original file line numberDiff line numberDiff line change
@@ -7922,84 +7922,110 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
79227922
}
79237923
}
79247924

7925-
// Generate scopes and callstacks
7925+
// Generate scopes
79267926
for(const Function *f : m_Program->m_Functions)
79277927
{
79287928
if(!f->external)
79297929
{
79307930
FunctionInfo &info = m_FunctionInfos[f];
79317931
uint32_t countInstructions = (uint32_t)f->instructions.size();
79327932

7933-
rdcarray<ScopedDebugData *> scopeHierarchy;
79347933
ScopedDebugData *currentScope = NULL;
79357934
for(uint32_t i = 0; i < countInstructions; ++i)
79367935
{
79377936
uint32_t instructionIndex = i + info.globalInstructionOffset;
79387937
const Instruction &inst = *f->instructions[i];
79397938
ScopedDebugData *thisScope = NULL;
7940-
if(!DXIL::IsLLVMDebugCall(inst))
7939+
// Use DebugLoc data for building up the list of scopes
7940+
uint32_t dbgLoc = ShouldIgnoreSourceMapping(inst) ? ~0U : inst.debugLoc;
7941+
if(dbgLoc != ~0U)
79417942
{
7942-
// Use DebugLoc data for building up the list of scopes
7943-
uint32_t dbgLoc = ShouldIgnoreSourceMapping(inst) ? ~0U : inst.debugLoc;
7944-
if(dbgLoc != ~0U)
7945-
{
7946-
const DebugLocation &debugLoc = m_Program->m_DebugLocations[dbgLoc];
7947-
thisScope = AddScopedDebugData(debugLoc.scope);
7948-
}
7943+
const DebugLocation &debugLoc = m_Program->m_DebugLocations[dbgLoc];
7944+
thisScope = AddScopedDebugData(debugLoc.scope);
79497945
}
7946+
if(!thisScope)
7947+
continue;
7948+
79507949
if(currentScope)
79517950
currentScope->maxInstruction = instructionIndex - 1;
79527951

7953-
if(thisScope == currentScope)
7954-
continue;
7952+
currentScope = thisScope;
7953+
thisScope->maxInstruction = instructionIndex;
7954+
}
7955+
}
7956+
}
79557957

7956-
if(!thisScope)
7958+
// Sort the scopes by instruction index
7959+
std::sort(m_DebugInfo.scopedDebugDatas.begin(), m_DebugInfo.scopedDebugDatas.end(),
7960+
[](const ScopedDebugData *a, const ScopedDebugData *b) { return *a < *b; });
7961+
7962+
// Generate callstacks
7963+
for(const Function *f : m_Program->m_Functions)
7964+
{
7965+
if(!f->external)
7966+
{
7967+
FunctionInfo &info = m_FunctionInfos[f];
7968+
uint32_t countInstructions = (uint32_t)f->instructions.size();
7969+
7970+
rdcarray<ScopedDebugData *> scopeHierarchy;
7971+
for(uint32_t i = 0; i < countInstructions; ++i)
7972+
{
7973+
uint32_t instructionIndex = i + info.globalInstructionOffset;
7974+
const Instruction &inst = *f->instructions[i];
7975+
// Use DebugLoc data for building up the list of scopes
7976+
uint32_t dbgLoc = ShouldIgnoreSourceMapping(inst) ? ~0U : inst.debugLoc;
7977+
if(dbgLoc == ~0U)
79577978
continue;
79587979

7959-
currentScope = thisScope;
7960-
thisScope->maxInstruction = instructionIndex;
7961-
// Walk upwards from this scope to find where to append to the scope hierarchy
7980+
FunctionInfo::Callstack callstack;
7981+
7982+
const DebugLocation *debugLoc = &m_Program->m_DebugLocations[dbgLoc];
7983+
// For each DILocation
7984+
while(debugLoc)
79627985
{
7963-
ScopedDebugData *scope = thisScope;
7964-
while(scope)
7986+
// Walk scope upwards to make callstack : always a DebugScope
7987+
const DXIL::Metadata *scopeMD = debugLoc->scope;
7988+
while(scopeMD)
79657989
{
7966-
int32_t index = scopeHierarchy.indexOf(thisScope);
7967-
if(index >= 0)
7990+
DXIL::DIBase *dwarf = scopeMD->dwarf;
7991+
if(dwarf)
79687992
{
7969-
scopeHierarchy.erase(index, scopeHierarchy.count() - index);
7970-
break;
7993+
// Walk upwards through all the functions
7994+
if(dwarf->type == DIBase::Subprogram)
7995+
{
7996+
rdcstr funcName = m_Program->GetFunctionScopeName(dwarf);
7997+
if(!funcName.empty())
7998+
callstack.insert(0, funcName);
7999+
scopeMD = dwarf->As<DISubprogram>()->scope;
8000+
}
8001+
else if(dwarf->type == DIBase::LexicalBlock)
8002+
{
8003+
scopeMD = dwarf->As<DILexicalBlock>()->scope;
8004+
}
8005+
else if(dwarf->type == DIBase::File)
8006+
{
8007+
scopeMD = NULL;
8008+
break;
8009+
}
8010+
else
8011+
{
8012+
RDCERR("Unhandled scope type %s", ToStr(dwarf->type).c_str());
8013+
scopeMD = NULL;
8014+
break;
8015+
}
79718016
}
7972-
scope = scope->parent;
79738017
}
8018+
// Make new DILocation from inlinedAt and walk that DILocation
8019+
if(debugLoc->inlinedAt)
8020+
debugLoc = debugLoc->inlinedAt->debugLoc;
8021+
else
8022+
debugLoc = NULL;
79748023
}
7975-
// Add the new scope to the hierarchy and generate the callstack
7976-
scopeHierarchy.push_back(thisScope);
7977-
7978-
FunctionInfo::Callstack callstack;
7979-
for(ScopedDebugData *scope : scopeHierarchy)
7980-
{
7981-
if(!scope->functionName.empty())
7982-
callstack.push_back(scope->functionName);
7983-
}
7984-
// If there is no callstack then use the function name
7985-
if(callstack.empty())
7986-
callstack.push_back(f->name);
79878024
info.callstacks[instructionIndex] = callstack;
79888025
}
7989-
// If there is no callstack for the function then use the function name
7990-
if(info.callstacks.empty())
7991-
{
7992-
FunctionInfo::Callstack callstack;
7993-
callstack.push_back(f->name);
7994-
info.callstacks[0] = callstack;
7995-
}
79968026
}
79978027
}
79988028

7999-
// Sort the scopes by instruction index
8000-
std::sort(m_DebugInfo.scopedDebugDatas.begin(), m_DebugInfo.scopedDebugDatas.end(),
8001-
[](const ScopedDebugData *a, const ScopedDebugData *b) { return *a < *b; });
8002-
80038029
ParseDebugData();
80048030

80058031
// Extend the life time of any SSA ID which is mapped to a source variable

0 commit comments

Comments
 (0)