From 9b1332077ad89d49b5c95e46008c90ec654d6f4b Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Fri, 20 Sep 2024 10:04:36 +0100 Subject: [PATCH] DXIL Disassembly: Include GlobalVar in SSA Id generation During SettleIDs() check that all instruction arguments that require an SSA Id have one set Moved DXILDebug::Id, INVALID_ID, DXIL::GetSSAId() out of DXIL Debugger --- renderdoc/driver/shaders/dxil/dxil_bytecode.h | 5 +++- renderdoc/driver/shaders/dxil/dxil_debug.cpp | 29 ++++++++---------- renderdoc/driver/shaders/dxil/dxil_debug.h | 1 - .../driver/shaders/dxil/dxil_disassemble.cpp | 30 +++++++++++++++++-- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index 50b22229a..9f8e0d827 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -45,6 +45,8 @@ namespace DXILDebug { class Debugger; struct ThreadState; +const uint32_t INVALID_ID = ~0U; +typedef uint32_t Id; }; namespace DXIL @@ -1283,7 +1285,7 @@ struct Instruction : public ForwardReferencableValue // For DXC Compatibility mode: slot contains a number assigned to instructions that don't have // names and return a value, used for disassembly - // Otherwise a unique global ID used by the debugger and disassemvbly + // Otherwise a unique global ID used by the debugger and disassembly uint32_t slot = ~0U; InstructionFlags &opFlags() { return (InstructionFlags &)flags; } InstructionFlags opFlags() const { return (InstructionFlags)flags; } @@ -1724,6 +1726,7 @@ bool getival(const Value *v, T &out) } bool IsSSA(const Value *dxilValue); +DXILDebug::Id GetSSAId(const DXIL::Value *value); bool IsDXCNop(const Instruction &inst); bool IsLLVMDebugCall(const Instruction &inst); diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.cpp b/renderdoc/driver/shaders/dxil/dxil_debug.cpp index face4ae2b..0065c80ed 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_debug.cpp @@ -31,17 +31,6 @@ using namespace DXIL; using namespace DXDebug; -const uint32_t DXIL_INVALID_ID = ~0U; - -DXILDebug::Id GetSSAId(DXIL::Value *value) -{ - if(const Instruction *inst = cast(value)) - return inst->slot; - - RDCERR("Unhandled DXIL::Value type"); - return DXIL_INVALID_ID; -} - static bool OperationFlushing(const Operation op, DXOp dxOpCode) { if(dxOpCode != DXOp::NumOpCodes) @@ -1283,7 +1272,7 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, } else { - resultId = DXIL_INVALID_ID; + resultId = DXILDebug::INVALID_ID; result.name.clear(); } break; @@ -2379,14 +2368,14 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, const StackAllocPointer &ptr = itPtr->second; Id baseMemoryId = ptr.baseMemoryId; RDCASSERT(ptr.backingMemory); - RDCASSERTNOTEQUAL(baseMemoryId, DXIL_INVALID_ID); + RDCASSERTNOTEQUAL(baseMemoryId, DXILDebug::INVALID_ID); auto itAlloc = m_StackAllocs.find(baseMemoryId); RDCASSERT(itAlloc != m_StackAllocs.end()); StackAlloc &alloc = itAlloc->second; ShaderVariable arg; RDCASSERT(GetShaderVariable(inst.args[1], opCode, dxOpCode, arg)); - RDCASSERTEQUAL(resultId, DXIL_INVALID_ID); + RDCASSERTEQUAL(resultId, DXILDebug::INVALID_ID); // Memory copy from value to backing memory VarType type = ConvertDXILTypeToVarType(inst.args[1]->type); @@ -2895,8 +2884,8 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, } // Update the result variable after the dormant variables have been brought back - RDCASSERT(!(result.name.empty() ^ (resultId == DXIL_INVALID_ID))); - if(!result.name.empty() && resultId != DXIL_INVALID_ID) + RDCASSERT(!(result.name.empty() ^ (resultId == DXILDebug::INVALID_ID))); + if(!result.name.empty() && resultId != DXILDebug::INVALID_ID) { if(recordChange) SetResult(resultId, result, opCode, dxOpCode, eventFlags); @@ -4639,7 +4628,7 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain const uint32_t maxInst = i + 1; { Id resultId = inst.slot; - if(resultId != DXIL_INVALID_ID) + if(resultId != DXILDebug::INVALID_ID) { // The result SSA should not have been referenced before RDCASSERTEQUAL(ssaRefs.count(resultId), 0); @@ -4670,6 +4659,12 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain if(DXIL::IsSSA(arg)) { Id argId = GetSSAId(arg); + // Add GlobalVar args to the SSA refs (they won't be the result of an instruction) + if(cast(arg)) + { + if(ssaRefs.count(argId) == 0) + ssaRefs.insert(argId); + } if(!isPhiNode) { // For non phi-nodes the argument SSA should already exist as the result of a previous operation diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.h b/renderdoc/driver/shaders/dxil/dxil_debug.h index 3117e19b1..071ede224 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.h +++ b/renderdoc/driver/shaders/dxil/dxil_debug.h @@ -43,7 +43,6 @@ typedef DXDebug::GatherChannel GatherChannel; typedef DXBCBytecode::SamplerMode SamplerMode; typedef DXBC::InterpolationMode InterpolationMode; -typedef uint32_t Id; class Debugger; struct GlobalState; diff --git a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp index 736b8f2c7..14b75efa2 100644 --- a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp @@ -110,14 +110,14 @@ bool DXIL::IsSSA(const Value *dxilValue) { if(const Instruction *inst = cast(dxilValue)) return true; + if(const GlobalVar *gv = cast(dxilValue)) + return true; if(const Constant *c = cast(dxilValue)) return false; if(const Literal *lit = cast(dxilValue)) return false; if(const Block *block = cast(dxilValue)) return false; - if(const GlobalVar *gv = cast(dxilValue)) - return false; if(const Function *func = cast(dxilValue)) return false; if(const Metadata *meta = cast(dxilValue)) @@ -127,6 +127,17 @@ bool DXIL::IsSSA(const Value *dxilValue) return false; } +DXILDebug::Id DXIL::GetSSAId(const DXIL::Value *value) +{ + if(const Instruction *inst = cast(value)) + return inst->slot; + if(const GlobalVar *gv = cast(value)) + return gv->ssaId; + + RDCERR("Unhandled DXIL::Value type"); + return DXILDebug::INVALID_ID; +} + static const char *shaderNames[] = { "Pixel", "Vertex", "Geometry", "Hull", "Domain", "Compute", "Library", "RayGeneration", "Intersection", "AnyHit", @@ -1060,6 +1071,13 @@ void Program::SettleIDs() AssignMetaSlot(m_MetaSlots, m_NextMetaSlot, m.children[c]); } } + // assign SSA ID for global variables + for(GlobalVar *g : m_GlobalVars) + { + if(g->ssaId == ~0U) + g->ssaId = m_NextSSAId++; + } + rdcarray &metaSlots = m_MetaSlots; uint32_t &nextMetaSlot = m_NextMetaSlot; for(size_t i = 0; i < m_Functions.size(); i++) @@ -1093,6 +1111,14 @@ void Program::SettleIDs() inst->slot = slot++; #endif } +#if DISABLED(DXC_COMPATIBLE_DISASM) + // Check all arguments have valid SSA IDs + for(const Value *arg : inst->args) + { + if(IsSSA(arg)) + RDCASSERTNOTEQUAL(GetSSAId(arg), ~0U); + } +#endif if(inst->op == Operation::Call) { Function *callFunc = (Function *)inst->getFuncCall();