Store mapping from instruction to disassembly line in shader debug trace

* This avoids having the UI need to do a scan and expecting to find
  "instruction:" on the start of a line.
* We also move the callstack to be stored per-step, and not in the line info
  mapping.
This commit is contained in:
baldurk
2020-02-06 17:58:41 +00:00
parent 14c1af06a3
commit 01461db738
17 changed files with 248 additions and 184 deletions
+39 -48
View File
@@ -560,6 +560,18 @@ void ShaderViewer::debugShader(const ShaderBindpointMapping *bind, const ShaderR
{
const LineColumnInfo &line = m_Trace->lineInfo[inst];
int disasmLine = (int)line.disassemblyLine;
if(disasmLine > 0 && disasmLine >= m_AsmLine2Inst.size())
{
int oldSize = m_AsmLine2Inst.size();
m_AsmLine2Inst.resize(disasmLine + 1);
for(int i = oldSize; i < disasmLine; i++)
m_AsmLine2Inst[i] = -1;
}
if(disasmLine > 0)
m_AsmLine2Inst[disasmLine] = (int)inst;
if(line.fileIndex < 0 || line.fileIndex >= m_Line2Insts.count())
continue;
@@ -1329,7 +1341,7 @@ bool ShaderViewer::stepBack()
if(m_CurrentStep == 0)
break;
if(m_Trace->lineInfo[state.nextInstruction] == oldLine)
if(m_Trace->lineInfo[state.nextInstruction].sourceEqual(oldLine))
continue;
break;
@@ -1371,7 +1383,7 @@ bool ShaderViewer::stepNext()
if(m_CurrentStep + 1 >= m_Trace->states.count())
break;
if(m_Trace->lineInfo[state.nextInstruction] == oldLine)
if(m_Trace->lineInfo[state.nextInstruction].sourceEqual(oldLine))
continue;
break;
@@ -1424,7 +1436,7 @@ void ShaderViewer::runToCursor()
for(; i < m_DisassemblyView->lineCount(); i++)
{
int line = instructionForLine(i);
int line = instructionForDisassemblyLine(i);
if(line >= 0)
{
runTo({(size_t)line}, true);
@@ -1434,22 +1446,13 @@ void ShaderViewer::runToCursor()
}
}
int ShaderViewer::instructionForLine(sptr_t line)
int ShaderViewer::instructionForDisassemblyLine(sptr_t line)
{
QString trimmed = QString::fromUtf8(m_DisassemblyView->getLine(line).trimmed());
// go from scintilla's lines (0-based) to ours (1-based)
line++;
int colon = trimmed.indexOf(QLatin1Char(':'));
if(colon > 0)
{
trimmed.truncate(colon);
bool ok = false;
int instruction = trimmed.toInt(&ok);
if(ok && instruction >= 0)
return instruction;
}
if(line < m_AsmLine2Inst.size())
return m_AsmLine2Inst[line];
return -1;
}
@@ -1776,30 +1779,27 @@ void ShaderViewer::updateDebugging()
m_CurInstructionScintilla = NULL;
}
for(sptr_t i = 0; i < m_DisassemblyView->lineCount(); i++)
{
if(QString::fromUtf8(m_DisassemblyView->getLine(i).trimmed())
.startsWith(QFormatStr("%1:").arg(nextInst)))
{
m_DisassemblyView->markerAdd(i, done ? FINISHED_MARKER : CURRENT_MARKER);
m_DisassemblyView->markerAdd(i, done ? FINISHED_MARKER + 1 : CURRENT_MARKER + 1);
int pos = m_DisassemblyView->positionFromLine(i);
m_DisassemblyView->setSelection(pos, pos);
ensureLineScrolled(m_DisassemblyView, i);
break;
}
}
ui->callstack->clear();
for(const rdcstr &s : state.callstack)
ui->callstack->insertItem(0, s);
if(state.nextInstruction < m_Trace->lineInfo.size())
{
LineColumnInfo &lineInfo = m_Trace->lineInfo[state.nextInstruction];
for(const rdcstr &s : lineInfo.callstack)
ui->callstack->insertItem(0, s);
// highlight the current line
{
m_DisassemblyView->markerAdd(lineInfo.disassemblyLine - 1,
done ? FINISHED_MARKER : CURRENT_MARKER);
m_DisassemblyView->markerAdd(lineInfo.disassemblyLine - 1,
done ? FINISHED_MARKER + 1 : CURRENT_MARKER + 1);
int pos = m_DisassemblyView->positionFromLine(lineInfo.disassemblyLine - 1);
m_DisassemblyView->setSelection(pos, pos);
ensureLineScrolled(m_DisassemblyView, lineInfo.disassemblyLine - 1);
}
if(lineInfo.fileIndex >= 0 && lineInfo.fileIndex < m_FileScintillas.count())
{
@@ -2529,7 +2529,7 @@ void ShaderViewer::ToggleBreakpoint(int instruction)
for(; instLine < m_DisassemblyView->lineCount(); instLine++)
{
instruction = instructionForLine(instLine);
instruction = instructionForDisassemblyLine(instLine);
if(instruction >= 0)
break;
@@ -2542,17 +2542,8 @@ void ShaderViewer::ToggleBreakpoint(int instruction)
if(instLine == -1)
{
// find line for this instruction
for(instLine = 0; instLine < m_DisassemblyView->lineCount(); instLine++)
{
int inst = instructionForLine(instLine);
if(instruction == inst)
break;
}
if(instLine >= m_DisassemblyView->lineCount())
instLine = -1;
if(m_Trace && instruction >= 0 && instruction < m_Trace->lineInfo.count())
instLine = m_Trace->lineInfo[instruction].disassemblyLine - 1;
}
if(m_Breakpoints.contains(instruction))
@@ -2600,8 +2591,8 @@ void ShaderViewer::ToggleBreakpoint(int instruction)
}
}
}
m_Breakpoints.push_back(instruction);
}
m_Breakpoints.push_back(instruction);
}
}
+4 -1
View File
@@ -209,6 +209,9 @@ private:
// a map per file, from line number to instruction indices
QVector<QMap<int32_t, QVector<size_t>>> m_Line2Insts;
// a vector for the disassembly
QVector<int32_t> m_AsmLine2Inst;
ScintillaEdit *m_CurInstructionScintilla = NULL;
QList<ScintillaEdit *> m_FileScintillas;
@@ -262,7 +265,7 @@ private:
int snippetPos();
QString vulkanUBO();
int instructionForLine(sptr_t line);
int instructionForDisassemblyLine(sptr_t line);
void updateDebugging();
+27 -13
View File
@@ -439,11 +439,14 @@ struct LineColumnInfo
bool operator==(const LineColumnInfo &o) const
{
return fileIndex == o.fileIndex && lineStart == o.lineStart && lineEnd == o.lineEnd &&
colStart == o.colStart && colEnd == o.colEnd && callstack == o.callstack;
return disassemblyLine == o.disassemblyLine && fileIndex == o.fileIndex &&
lineStart == o.lineStart && lineEnd == o.lineEnd && colStart == o.colStart &&
colEnd == o.colEnd;
}
bool operator<(const LineColumnInfo &o) const
{
if(!(disassemblyLine == o.disassemblyLine))
return disassemblyLine < o.disassemblyLine;
if(!(fileIndex == o.fileIndex))
return fileIndex < o.fileIndex;
if(!(lineStart == o.lineStart))
@@ -454,18 +457,29 @@ struct LineColumnInfo
return colStart < o.colStart;
if(!(colEnd == o.colEnd))
return colEnd < o.colEnd;
if(!(callstack == o.callstack))
return callstack < o.callstack;
return false;
}
DOCUMENT("The current file, as an index into the list of files for this shader.");
bool sourceEqual(const LineColumnInfo &o) const
{
// comparison without considering the disassembly line
return fileIndex == o.fileIndex && lineStart == o.lineStart && lineEnd == o.lineEnd &&
colStart == o.colStart && colEnd == o.colEnd;
}
DOCUMENT("The line (starting from 1) in the disassembly where this instruction is located.");
uint32_t disassemblyLine;
DOCUMENT(R"(The current file, as an index into the list of files for this shader.
If this is negative, no source mapping is available and only :data:`disassemblyLine` is valid.
)");
int32_t fileIndex = -1;
DOCUMENT("The line-number (starting from 1) of the start of the current section of code.");
DOCUMENT("The starting line-number (starting from 1) of the source code.");
uint32_t lineStart = 0;
DOCUMENT("The line-number (starting from 1) of the end of the current section of code.");
DOCUMENT("The ending line-number (starting from 1) of the source code.");
uint32_t lineEnd = 0;
DOCUMENT(R"(The column number (starting from 1) of the start of the code on the line specified by
@@ -479,12 +493,6 @@ treated as covering the code.
treated as covering the code.
)");
uint32_t colEnd = 0;
DOCUMENT(R"(A ``list`` of ``str`` with each function call in the current callstack at this line.
The oldest/outer function is first in the list, the newest/inner function is last.
)");
rdcarray<rdcstr> callstack;
};
DECLARE_REFLECTION_STRUCT(LineColumnInfo);
@@ -542,6 +550,12 @@ shader execution happened will have ``nextInstruction == 0``.
DOCUMENT("A set of :class:`ShaderEvents` flags that indicate what events happened on this step.");
ShaderEvents flags;
DOCUMENT(R"(A ``list`` of ``str`` with each function call in the current callstack at this line.
The oldest/outer function is first in the list, the newest/inner function is last.
)");
rdcarray<rdcstr> callstack;
};
DECLARE_REFLECTION_STRUCT(ShaderDebugState);
+9 -46
View File
@@ -2072,9 +2072,7 @@ ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uin
rdcarray<ShaderDebugState> states;
if(dxbc->GetDebugInfo())
dxbc->GetDebugInfo()->GetLocals(0, dxbc->GetDXBCByteCode()->GetInstruction(0).offset,
initialState.locals);
dxbc->FillStateInstructionInfo(initialState);
states.push_back((State)initialState);
@@ -2089,12 +2087,7 @@ ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uin
initialState = initialState.GetNext(global, &apiWrapper, NULL);
if(dxbc->GetDebugInfo())
{
const DXBCBytecode::Operation &op =
dxbc->GetDXBCByteCode()->GetInstruction((size_t)initialState.nextInstruction);
dxbc->GetDebugInfo()->GetLocals(initialState.nextInstruction, op.offset, initialState.locals);
}
dxbc->FillStateInstructionInfo(initialState);
states.push_back((State)initialState);
@@ -2109,12 +2102,7 @@ ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uin
ret.hasLocals = dxbc->GetDebugInfo() && dxbc->GetDebugInfo()->HasLocals();
ret.lineInfo.resize(dxbc->GetDXBCByteCode()->GetNumInstructions());
for(size_t i = 0; dxbc->GetDebugInfo() && i < dxbc->GetDXBCByteCode()->GetNumInstructions(); i++)
{
const DXBCBytecode::Operation &op = dxbc->GetDXBCByteCode()->GetInstruction(i);
dxbc->GetDebugInfo()->GetLineInfo(i, op.offset, ret.lineInfo[i]);
}
dxbc->FillTraceLineInfo(ret);
return ret;
}
@@ -2836,9 +2824,7 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim
rdcarray<ShaderDebugState> states;
if(dxbc->GetDebugInfo())
dxbc->GetDebugInfo()->GetLocals(0, dxbc->GetDXBCByteCode()->GetInstruction(0).offset,
quad[destIdx].locals);
dxbc->FillStateInstructionInfo(quad[destIdx]);
states.push_back((State)quad[destIdx]);
@@ -2878,13 +2864,7 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim
{
State &s = curquad[destIdx];
if(dxbc->GetDebugInfo())
{
size_t inst =
RDCMIN((size_t)s.nextInstruction, dxbc->GetDXBCByteCode()->GetNumInstructions() - 1);
const DXBCBytecode::Operation &op = dxbc->GetDXBCByteCode()->GetInstruction(inst);
dxbc->GetDebugInfo()->GetLocals(s.nextInstruction, op.offset, s.locals);
}
dxbc->FillStateInstructionInfo(s);
states.push_back(s);
}
@@ -2981,12 +2961,7 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim
traces[destIdx].hasLocals = dxbc->GetDebugInfo() && dxbc->GetDebugInfo()->HasLocals();
traces[destIdx].lineInfo.resize(dxbc->GetDXBCByteCode()->GetNumInstructions());
for(size_t i = 0; dxbc->GetDebugInfo() && i < dxbc->GetDXBCByteCode()->GetNumInstructions(); i++)
{
const DXBCBytecode::Operation &op = dxbc->GetDXBCByteCode()->GetInstruction(i);
dxbc->GetDebugInfo()->GetLineInfo(i, op.offset, traces[destIdx].lineInfo[i]);
}
dxbc->FillTraceLineInfo(traces[destIdx]);
return traces[destIdx];
}
@@ -3043,9 +3018,7 @@ ShaderDebugTrace D3D11Replay::DebugThread(uint32_t eventId, const uint32_t group
rdcarray<ShaderDebugState> states;
if(dxbc->GetDebugInfo())
dxbc->GetDebugInfo()->GetLocals(0, dxbc->GetDXBCByteCode()->GetInstruction(0).offset,
initialState.locals);
dxbc->FillStateInstructionInfo(initialState);
states.push_back((State)initialState);
@@ -3058,12 +3031,7 @@ ShaderDebugTrace D3D11Replay::DebugThread(uint32_t eventId, const uint32_t group
initialState = initialState.GetNext(global, &apiWrapper, NULL);
if(dxbc->GetDebugInfo())
{
const DXBCBytecode::Operation &op =
dxbc->GetDXBCByteCode()->GetInstruction((size_t)initialState.nextInstruction);
dxbc->GetDebugInfo()->GetLocals(initialState.nextInstruction, op.offset, initialState.locals);
}
dxbc->FillStateInstructionInfo(initialState);
states.push_back((State)initialState);
@@ -3078,12 +3046,7 @@ ShaderDebugTrace D3D11Replay::DebugThread(uint32_t eventId, const uint32_t group
ret.hasLocals = dxbc->GetDebugInfo() && dxbc->GetDebugInfo()->HasLocals();
ret.lineInfo.resize(dxbc->GetDXBCByteCode()->GetNumInstructions());
for(size_t i = 0; dxbc->GetDebugInfo() && i < dxbc->GetDXBCByteCode()->GetNumInstructions(); i++)
{
const Operation &op = dxbc->GetDXBCByteCode()->GetInstruction(i);
dxbc->GetDebugInfo()->GetLineInfo(i, op.offset, ret.lineInfo[i]);
}
dxbc->FillTraceLineInfo(ret);
for(size_t i = 0; i < dxbc->GetDXBCByteCode()->GetNumDeclarations(); i++)
{
+6 -31
View File
@@ -1662,9 +1662,7 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim
rdcarray<ShaderDebugState> states;
if(dxbc->GetDebugInfo())
dxbc->GetDebugInfo()->GetLocals(0, dxbc->GetDXBCByteCode()->GetInstruction(0).offset,
quad[destIdx].locals);
dxbc->FillStateInstructionInfo(quad[destIdx]);
states.push_back(quad[destIdx]);
@@ -1704,13 +1702,7 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim
{
State &s = curquad[destIdx];
if(dxbc->GetDebugInfo())
{
size_t inst =
RDCMIN((size_t)s.nextInstruction, dxbc->GetDXBCByteCode()->GetNumInstructions() - 1);
const Operation &op = dxbc->GetDXBCByteCode()->GetInstruction(inst);
dxbc->GetDebugInfo()->GetLocals(s.nextInstruction, op.offset, s.locals);
}
dxbc->FillStateInstructionInfo(s);
states.push_back(s);
}
@@ -1807,12 +1799,7 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim
traces[destIdx].hasLocals = dxbc->GetDebugInfo() && dxbc->GetDebugInfo()->HasLocals();
traces[destIdx].lineInfo.resize(dxbc->GetDXBCByteCode()->GetNumInstructions());
for(size_t i = 0; dxbc->GetDebugInfo() && i < dxbc->GetDXBCByteCode()->GetNumInstructions(); i++)
{
const Operation &op = dxbc->GetDXBCByteCode()->GetInstruction(i);
dxbc->GetDebugInfo()->GetLineInfo(i, op.offset, traces[destIdx].lineInfo[i]);
}
dxbc->FillTraceLineInfo(traces[destIdx]);
return traces[destIdx];
}
@@ -1881,9 +1868,7 @@ ShaderDebugTrace D3D12Replay::DebugThread(uint32_t eventId, const uint32_t group
rdcarray<ShaderDebugState> states;
if(dxbc->GetDebugInfo())
dxbc->GetDebugInfo()->GetLocals(0, dxbc->GetDXBCByteCode()->GetInstruction(0).offset,
initialState.locals);
dxbc->FillStateInstructionInfo(initialState);
states.push_back((State)initialState);
@@ -1896,12 +1881,7 @@ ShaderDebugTrace D3D12Replay::DebugThread(uint32_t eventId, const uint32_t group
initialState = initialState.GetNext(global, &apiWrapper, NULL);
if(dxbc->GetDebugInfo())
{
const DXBCBytecode::Operation &op =
dxbc->GetDXBCByteCode()->GetInstruction((size_t)initialState.nextInstruction);
dxbc->GetDebugInfo()->GetLocals(initialState.nextInstruction, op.offset, initialState.locals);
}
dxbc->FillStateInstructionInfo(initialState);
states.push_back((State)initialState);
@@ -1916,12 +1896,7 @@ ShaderDebugTrace D3D12Replay::DebugThread(uint32_t eventId, const uint32_t group
ret.hasLocals = dxbc->GetDebugInfo() && dxbc->GetDebugInfo()->HasLocals();
ret.lineInfo.resize(dxbc->GetDXBCByteCode()->GetNumInstructions());
for(size_t i = 0; dxbc->GetDebugInfo() && i < dxbc->GetDXBCByteCode()->GetNumInstructions(); i++)
{
const Operation &op = dxbc->GetDXBCByteCode()->GetInstruction(i);
dxbc->GetDebugInfo()->GetLineInfo(i, op.offset, ret.lineInfo[i]);
}
dxbc->FillTraceLineInfo(ret);
for(size_t i = 0; i < dxbc->GetDXBCByteCode()->GetNumDeclarations(); i++)
{
@@ -442,4 +442,9 @@ D3D_PRIMITIVE_TOPOLOGY Program::GetOutputTopology()
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
uint32_t Program::GetDisassemblyLine(uint32_t instruction) const
{
return m_Instructions[RDCMIN(m_Instructions.size() - 1, (size_t)instruction)].line;
}
}; // namespace DXBCBytecode
@@ -780,7 +780,7 @@ struct Declaration
///////////////////////////////////////
uintptr_t offset;
uint64_t offset;
uint32_t length;
size_t instruction; // happens before this instruction. Usually 0 as all decls are up front,
@@ -893,6 +893,7 @@ struct Operation
Operation()
{
offset = 0;
line = 0;
length = 0;
stride = 0;
operation = NUM_OPCODES;
@@ -911,6 +912,7 @@ struct Operation
///////////////////////////////////////
uintptr_t offset;
uint32_t line;
uint32_t length;
OpcodeType operation;
@@ -949,6 +951,7 @@ public:
MakeDisassemblyString();
return m_Disassembly;
}
uint32_t GetDisassemblyLine(uint32_t instruction) const;
size_t GetNumDeclarations() const { return m_Declarations.size(); }
const Declaration &GetDeclaration(size_t i) const { return m_Declarations[i]; }
const Declaration *FindDeclaration(OperandType declType, uint32_t identifier) const;
@@ -509,6 +509,49 @@ const rdcstr &DXBCContainer::GetDisassembly()
return m_Disassembly;
}
void DXBCContainer::FillTraceLineInfo(ShaderDebugTrace &trace) const
{
if(m_DXBCByteCode)
{
trace.lineInfo.resize(m_DXBCByteCode->GetNumInstructions());
for(size_t i = 0; i < m_DXBCByteCode->GetNumInstructions(); i++)
{
const DXBCBytecode::Operation &op = m_DXBCByteCode->GetInstruction(i);
if(m_DebugInfo)
m_DebugInfo->GetLineInfo(i, op.offset, trace.lineInfo[i]);
// we add two lines for the shader hash on top of what the bytecode disassembler did
if(op.line > 0)
trace.lineInfo[i].disassemblyLine = 2 + op.line;
}
}
}
void DXBCContainer::FillStateInstructionInfo(ShaderDebugState &state) const
{
uint32_t instruction = state.nextInstruction;
uintptr_t offset = 0;
if(m_DXBCByteCode)
{
if(instruction < m_DXBCByteCode->GetNumInstructions())
offset = m_DXBCByteCode->GetInstruction(instruction).offset;
}
if(m_DebugInfo)
{
m_DebugInfo->GetLocals(instruction, offset, state.locals);
m_DebugInfo->GetCallstack(instruction, offset, state.callstack);
}
else
{
state.locals.clear();
state.callstack.clear();
}
}
void DXBCContainer::GetHash(uint32_t hash[4], const void *ByteCode, size_t BytecodeLength)
{
if(BytecodeLength < sizeof(FileHeader))
@@ -124,6 +124,8 @@ public:
rdcarray<rdcpair<rdcstr, rdcstr>> Files; // <filename, source>
virtual void GetLineInfo(size_t instruction, uintptr_t offset, LineColumnInfo &lineInfo) const = 0;
virtual void GetCallstack(size_t instruction, uintptr_t offset,
rdcarray<rdcstr> &callstack) const = 0;
virtual bool HasLocals() const = 0;
virtual void GetLocals(size_t instruction, uintptr_t offset,
@@ -154,6 +156,8 @@ public:
D3D_PRIMITIVE_TOPOLOGY GetOutputTopology();
const rdcstr &GetDisassembly();
void FillTraceLineInfo(ShaderDebugTrace &trace) const;
void FillStateInstructionInfo(ShaderDebugState &state) const;
const DXBCBytecode::Program *GetDXBCByteCode() { return m_DXBCByteCode; }
const DXIL::Program *GetDXILByteCode() { return m_DXILByteCode; }
@@ -482,24 +482,29 @@ void Program::MakeDisassemblyString()
return;
}
rdcstr shadermodel = "xs_";
switch(m_Type)
{
case DXBC::ShaderType::Pixel: m_Disassembly += "ps_"; break;
case DXBC::ShaderType::Vertex: m_Disassembly += "vs_"; break;
case DXBC::ShaderType::Geometry: m_Disassembly += "gs_"; break;
case DXBC::ShaderType::Hull: m_Disassembly += "hs_"; break;
case DXBC::ShaderType::Domain: m_Disassembly += "ds_"; break;
case DXBC::ShaderType::Compute: m_Disassembly += "cs_"; break;
case DXBC::ShaderType::Pixel: shadermodel = "ps_"; break;
case DXBC::ShaderType::Vertex: shadermodel = "vs_"; break;
case DXBC::ShaderType::Geometry: shadermodel = "gs_"; break;
case DXBC::ShaderType::Hull: shadermodel = "hs_"; break;
case DXBC::ShaderType::Domain: shadermodel = "ds_"; break;
case DXBC::ShaderType::Compute: shadermodel = "cs_"; break;
default: RDCERR("Unknown shader type: %u", m_Type); break;
}
m_Disassembly += StringFormat::Fmt("%d_%d\n", m_Major, m_Minor);
m_Disassembly = StringFormat::Fmt("%s%d_%d\n", shadermodel.c_str(), m_Major, m_Minor);
uint32_t linenum = 2;
int indent = 0;
size_t d = 0;
LineColumnInfo prevLineInfo;
rdcarray<rdcstr> prevCallstack;
size_t debugInst = 0;
@@ -521,13 +526,23 @@ void Program::MakeDisassemblyString()
if(m_Declarations[d].instruction > i)
{
if(i == 0)
{
m_Disassembly += "\n";
linenum++;
}
break;
}
m_Disassembly += " ";
m_Disassembly += m_Declarations[d].str;
m_Disassembly += "\n";
m_Disassembly += StringFormat::Fmt("% 4s %s\n", "", m_Declarations[d].str.c_str());
linenum++;
int32_t nl = m_Declarations[d].str.indexOf('\n');
while(nl >= 0)
{
linenum++;
nl = m_Declarations[d].str.indexOf('\n', nl + 1);
}
}
if(m_Instructions[i].operation == OPCODE_ENDIF || m_Instructions[i].operation == OPCODE_ENDLOOP)
@@ -537,9 +552,11 @@ void Program::MakeDisassemblyString()
if(m_DebugInfo)
{
LineColumnInfo lineInfo = prevLineInfo;
LineColumnInfo lineInfo;
rdcarray<rdcstr> callstack;
m_DebugInfo->GetLineInfo(debugInst, m_Instructions[i].offset, lineInfo);
m_DebugInfo->GetCallstack(debugInst, m_Instructions[i].offset, callstack);
if(lineInfo.fileIndex >= 0 && (lineInfo.fileIndex != prevLineInfo.fileIndex ||
lineInfo.lineStart != prevLineInfo.lineStart))
@@ -571,9 +588,9 @@ void Program::MakeDisassemblyString()
line = line.substr(startLine);
m_Disassembly += "\n";
linenum++;
if(((lineInfo.fileIndex != prevLineInfo.fileIndex ||
lineInfo.callstack.back() != prevLineInfo.callstack.back()) &&
if(((lineInfo.fileIndex != prevLineInfo.fileIndex || callstack.back() != prevCallstack.back()) &&
lineInfo.fileIndex < (int32_t)fileLines.size()) ||
line == "")
{
@@ -581,18 +598,20 @@ void Program::MakeDisassemblyString()
for(int in = 0; in < indent; in++)
m_Disassembly += " ";
rdcstr func = lineInfo.callstack.back();
rdcstr func = callstack.back();
if(!func.empty())
{
m_Disassembly += StringFormat::Fmt("%s:%d - %s()\n",
m_DebugInfo->Files[lineInfo.fileIndex].first.c_str(),
lineInfo.lineStart, func.c_str());
linenum++;
}
else
{
m_Disassembly += StringFormat::Fmt(
"%s:%d\n", m_DebugInfo->Files[lineInfo.fileIndex].first.c_str(), lineInfo.lineStart);
linenum++;
}
}
@@ -602,10 +621,12 @@ void Program::MakeDisassemblyString()
for(int in = 0; in < indent; in++)
m_Disassembly += " ";
m_Disassembly += line + "\n";
linenum++;
}
}
prevLineInfo = lineInfo;
prevCallstack = callstack;
}
int curIndent = indent;
@@ -615,8 +636,11 @@ void Program::MakeDisassemblyString()
rdcstr whitespace;
whitespace.fill(curIndent * 2, ' ');
m_Instructions[i].line = linenum;
m_Disassembly +=
StringFormat::Fmt("% 4u: %s%s\n", i, whitespace.c_str(), m_Instructions[i].str.c_str());
linenum++;
if(m_Instructions[i].operation == OPCODE_IF || m_Instructions[i].operation == OPCODE_LOOP)
{
@@ -2124,6 +2148,15 @@ bool Program::ExtractOperation(uint32_t *&tokenStream, Operation &retOp, bool fr
rdcstr formatString = (char *)&tokenStream[0];
// escape any newlines
int32_t nl = formatString.find("\n");
while(nl >= 0)
{
formatString[nl] = '\\';
formatString.insert(nl + 1, 'n');
nl = formatString.find("\n", nl);
}
retOp.str = (messageFormat ? "errorf" : "error");
retOp.str += " \"" + formatString + "\"";
+8 -1
View File
@@ -110,11 +110,18 @@ void SDBGChunk::GetLineInfo(size_t instruction, uintptr_t offset, LineColumnInfo
lineInfo.lineEnd = sym.lineNum;
lineInfo.colStart = 0;
lineInfo.colEnd = 0;
lineInfo.callstack = {m_Entry};
}
}
}
void SDBGChunk::GetCallstack(size_t instruction, uintptr_t offset, rdcarray<rdcstr> &callstack) const
{
if(instruction < m_Instructions.size())
{
callstack = {m_Entry};
}
}
bool SDBGChunk::HasLocals() const
{
return false;
@@ -249,6 +249,7 @@ public:
rdcstr GetShaderProfile() const { return m_Profile; }
uint32_t GetShaderCompileFlags() const { return m_ShaderFlags; }
void GetLineInfo(size_t instruction, uintptr_t offset, LineColumnInfo &lineInfo) const;
void GetCallstack(size_t instruction, uintptr_t offset, rdcarray<rdcstr> &callstack) const;
bool HasLocals() const;
void GetLocals(size_t instruction, uintptr_t offset, rdcarray<LocalVariableMapping> &locals) const;
+33 -25
View File
@@ -1562,19 +1562,17 @@ SPDBChunk::SPDBChunk(Reflection *reflection, void *chunk)
{
CV_Line_t &line = lines[l];
LineColumnInfo lineCol;
lineCol.fileIndex = fileIdx;
lineCol.lineStart = line.linenumStart;
lineCol.lineEnd = line.linenumStart + line.deltaLineEnd;
LineColumnInfo &lineInfo = m_InstructionInfo[line.offset].lineInfo;
lineInfo.fileIndex = fileIdx;
lineInfo.lineStart = line.linenumStart;
lineInfo.lineEnd = line.linenumStart + line.deltaLineEnd;
if(hasColumns)
{
CV_Column_t &col = columns[l];
lineCol.colStart = col.offColumnStart;
lineCol.colEnd = col.offColumnEnd;
lineInfo.colStart = col.offColumnStart;
lineInfo.colEnd = col.offColumnEnd;
}
m_Lines[line.offset] = lineCol;
}
}
RDCASSERT(iter == subend);
@@ -1628,7 +1626,7 @@ SPDBChunk::SPDBChunk(Reflection *reflection, void *chunk)
}
}
for(auto it = m_Lines.begin(); it != m_Lines.end(); ++it)
for(auto it = m_InstructionInfo.begin(); it != m_InstructionInfo.end(); ++it)
it->second.callstack.push_back(m_Functions[0].name);
SPDBLOG("Applying %zu inline sites", inlines.size());
@@ -1661,24 +1659,26 @@ SPDBChunk::SPDBChunk(Reflection *reflection, void *chunk)
int nPatched = 0;
auto it = m_Lines.lower_bound(loc.offsetStart);
auto it = m_InstructionInfo.lower_bound(loc.offsetStart);
for(; it != m_Lines.end() && it->first <= loc.offsetEnd; ++it)
for(; it != m_InstructionInfo.end() && it->first <= loc.offsetEnd; ++it)
{
if((it->first >= loc.offsetStart && it->first < loc.offsetEnd) ||
(it->first == loc.offsetStart && it->first == loc.offsetEnd))
{
LineColumnInfo &lineInfo = it->second.lineInfo;
SPDBLOG("Patching %x between [%x,%x] from (%d %u:%u -> %u:%u) into (%d %u:%u -> %u:%u)",
it->first, loc.offsetStart, loc.offsetEnd, it->second.fileIndex,
it->second.lineStart, it->second.colStart, it->second.lineEnd, it->second.colEnd,
fileIdx, loc.lineStart + inlines[i].baseLineNum, loc.colStart,
it->first, loc.offsetStart, loc.offsetEnd, lineInfo.fileIndex, lineInfo.lineStart,
lineInfo.colStart, lineInfo.lineEnd, lineInfo.colEnd, fileIdx,
loc.lineStart + inlines[i].baseLineNum, loc.colStart,
loc.lineEnd + inlines[i].baseLineNum, loc.colEnd);
it->second.fileIndex = fileIdx;
it->second.lineStart = loc.lineStart + inlines[i].baseLineNum;
it->second.lineEnd = loc.lineEnd + inlines[i].baseLineNum;
it->second.colStart = loc.colStart;
it->second.colEnd = loc.colEnd;
lineInfo.fileIndex = fileIdx;
lineInfo.lineStart = loc.lineStart + inlines[i].baseLineNum;
lineInfo.lineEnd = loc.lineEnd + inlines[i].baseLineNum;
lineInfo.colStart = loc.colStart;
lineInfo.colEnd = loc.colEnd;
if(loc.statement)
it->second.callstack.push_back(m_Functions[inlines[i].id].name);
nPatched++;
@@ -1732,11 +1732,11 @@ SPDBChunk::SPDBChunk(Reflection *reflection, void *chunk)
remapping[Files[i].first] = (int32_t)i;
// remap the line info by looking up the original intended filename, then looking up the new index
for(auto it = m_Lines.begin(); it != m_Lines.end(); ++it)
for(auto it = m_InstructionInfo.begin(); it != m_InstructionInfo.end(); ++it)
{
if(it->second.fileIndex == -1)
if(it->second.lineInfo.fileIndex == -1)
continue;
it->second.fileIndex = remapping[filenames[it->second.fileIndex]];
it->second.lineInfo.fileIndex = remapping[filenames[it->second.lineInfo.fileIndex]];
}
std::sort(m_Locals.begin(), m_Locals.end());
@@ -1746,10 +1746,18 @@ SPDBChunk::SPDBChunk(Reflection *reflection, void *chunk)
void SPDBChunk::GetLineInfo(size_t instruction, uintptr_t offset, LineColumnInfo &lineInfo) const
{
auto it = m_Lines.lower_bound((uint32_t)offset);
auto it = m_InstructionInfo.lower_bound((uint32_t)offset);
if(it != m_Lines.end() && (uintptr_t)it->first <= offset)
lineInfo = it->second;
if(it != m_InstructionInfo.end() && (uintptr_t)it->first <= offset)
lineInfo = it->second.lineInfo;
}
void SPDBChunk::GetCallstack(size_t instruction, uintptr_t offset, rdcarray<rdcstr> &callstack) const
{
auto it = m_InstructionInfo.lower_bound((uint32_t)offset);
if(it != m_InstructionInfo.end() && (uintptr_t)it->first <= offset)
callstack = it->second.callstack;
}
bool SPDBChunk::HasLocals() const
+8 -1
View File
@@ -267,6 +267,7 @@ public:
rdcstr GetShaderProfile() const { return m_Profile; }
uint32_t GetShaderCompileFlags() const { return m_ShaderFlags; }
void GetLineInfo(size_t instruction, uintptr_t offset, LineColumnInfo &lineInfo) const;
void GetCallstack(size_t instruction, uintptr_t offset, rdcarray<rdcstr> &callstack) const;
bool HasLocals() const;
void GetLocals(size_t instruction, uintptr_t offset, rdcarray<LocalVariableMapping> &locals) const;
@@ -283,7 +284,13 @@ private:
rdcarray<LocalMapping> m_Locals;
struct InstInfo
{
LineColumnInfo lineInfo;
rdcarray<rdcstr> callstack;
};
std::map<uint32_t, Function> m_Functions;
std::map<uint32_t, LineColumnInfo> m_Lines;
std::map<uint32_t, InstInfo> m_InstructionInfo;
};
};
@@ -785,6 +785,11 @@ D3D_PRIMITIVE_TOPOLOGY Program::GetOutputTopology()
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
uint32_t Program::GetDisassemblyLine(uint32_t instruction) const
{
return 0;
}
void Program::MakeDisassemblyString()
{
RDCERR("Unimplemented DXIL::Program::MakeDisassemblyString()");
@@ -50,6 +50,7 @@ public:
MakeDisassemblyString();
return m_Disassembly;
}
uint32_t GetDisassemblyLine(uint32_t instruction) const;
private:
void MakeDisassemblyString();
+4 -3
View File
@@ -367,14 +367,14 @@ void DoSerialise(SerialiserType &ser, LocalVariableMapping &el)
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, LineColumnInfo &el)
{
SERIALISE_MEMBER(disassemblyLine);
SERIALISE_MEMBER(fileIndex);
SERIALISE_MEMBER(lineStart);
SERIALISE_MEMBER(lineEnd);
SERIALISE_MEMBER(colStart);
SERIALISE_MEMBER(colEnd);
SERIALISE_MEMBER(callstack);
SIZE_CHECK(48);
SIZE_CHECK(24);
}
template <typename SerialiserType>
@@ -387,8 +387,9 @@ void DoSerialise(SerialiserType &ser, ShaderDebugState &el)
SERIALISE_MEMBER(modified);
SERIALISE_MEMBER(nextInstruction);
SERIALISE_MEMBER(flags);
SERIALISE_MEMBER(callstack);
SIZE_CHECK(128);
SIZE_CHECK(152);
}
template <typename SerialiserType>