mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-06 14:51:04 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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 + "\"";
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user