diff --git a/qrenderdoc/Windows/ShaderViewer.cpp b/qrenderdoc/Windows/ShaderViewer.cpp index f573276e1..38e497465 100644 --- a/qrenderdoc/Windows/ShaderViewer.cpp +++ b/qrenderdoc/Windows/ShaderViewer.cpp @@ -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); } } diff --git a/qrenderdoc/Windows/ShaderViewer.h b/qrenderdoc/Windows/ShaderViewer.h index c8527783f..ac0f07329 100644 --- a/qrenderdoc/Windows/ShaderViewer.h +++ b/qrenderdoc/Windows/ShaderViewer.h @@ -209,6 +209,9 @@ private: // a map per file, from line number to instruction indices QVector>> m_Line2Insts; + // a vector for the disassembly + QVector m_AsmLine2Inst; + ScintillaEdit *m_CurInstructionScintilla = NULL; QList m_FileScintillas; @@ -262,7 +265,7 @@ private: int snippetPos(); QString vulkanUBO(); - int instructionForLine(sptr_t line); + int instructionForDisassemblyLine(sptr_t line); void updateDebugging(); diff --git a/renderdoc/api/replay/shader_types.h b/renderdoc/api/replay/shader_types.h index cbdb44682..e3278ce91 100644 --- a/renderdoc/api/replay/shader_types.h +++ b/renderdoc/api/replay/shader_types.h @@ -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 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 callstack; }; DECLARE_REFLECTION_STRUCT(ShaderDebugState); diff --git a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp index 64bbf27e0..5f0524868 100644 --- a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp +++ b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp @@ -2072,9 +2072,7 @@ ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uin rdcarray 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 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 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++) { diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index 8bfd1ebb2..b7b0ee5cc 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -1662,9 +1662,7 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim rdcarray 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 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++) { diff --git a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp index 57816e02e..287bc4781 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp @@ -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 diff --git a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.h b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.h index c5723eaae..d9e45ac76 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.h @@ -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; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp index 5723379fc..e2e50da1e 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp @@ -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)) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.h b/renderdoc/driver/shaders/dxbc/dxbc_container.h index 5fbf04e18..6bae2d5cf 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.h @@ -124,6 +124,8 @@ public: rdcarray> Files; // virtual void GetLineInfo(size_t instruction, uintptr_t offset, LineColumnInfo &lineInfo) const = 0; + virtual void GetCallstack(size_t instruction, uintptr_t offset, + rdcarray &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; } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp index 890385de3..22f9718c5 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp @@ -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 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 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 + "\""; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_sdbg.cpp b/renderdoc/driver/shaders/dxbc/dxbc_sdbg.cpp index 25371867d..4626deb94 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_sdbg.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_sdbg.cpp @@ -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 &callstack) const +{ + if(instruction < m_Instructions.size()) + { + callstack = {m_Entry}; + } +} + bool SDBGChunk::HasLocals() const { return false; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_sdbg.h b/renderdoc/driver/shaders/dxbc/dxbc_sdbg.h index 8305af6e5..54ee57d1c 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_sdbg.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_sdbg.h @@ -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 &callstack) const; bool HasLocals() const; void GetLocals(size_t instruction, uintptr_t offset, rdcarray &locals) const; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_spdb.cpp b/renderdoc/driver/shaders/dxbc/dxbc_spdb.cpp index aa4cd8e3c..ca398d906 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_spdb.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_spdb.cpp @@ -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 &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 diff --git a/renderdoc/driver/shaders/dxbc/dxbc_spdb.h b/renderdoc/driver/shaders/dxbc/dxbc_spdb.h index b16634c5c..d4d68cc93 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_spdb.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_spdb.h @@ -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 &callstack) const; bool HasLocals() const; void GetLocals(size_t instruction, uintptr_t offset, rdcarray &locals) const; @@ -283,7 +284,13 @@ private: rdcarray m_Locals; + struct InstInfo + { + LineColumnInfo lineInfo; + rdcarray callstack; + }; + std::map m_Functions; - std::map m_Lines; + std::map m_InstructionInfo; }; }; diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp index a4b94cc2d..d867f7b3e 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp @@ -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()"); diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index e8697c9d7..60af52d4e 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -50,6 +50,7 @@ public: MakeDisassemblyString(); return m_Disassembly; } + uint32_t GetDisassemblyLine(uint32_t instruction) const; private: void MakeDisassemblyString(); diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index 61c09b905..746fcf3c3 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -367,14 +367,14 @@ void DoSerialise(SerialiserType &ser, LocalVariableMapping &el) template 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 @@ -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