diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index affade05b..c35722f99 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -1667,6 +1667,7 @@ protected: static void MakeResultId(const Instruction &inst, rdcstr &resultId); rdcstr GetArgId(const Instruction &inst, uint32_t arg) const; rdcstr GetArgId(const Value *v) const; + rdcstr GetArgumentName(const Value *v) const; const Metadata *FindMetadata(uint32_t slot) const; rdcstr ArgToString(const Value *v, bool withTypes, const rdcstr &attrString = "") const; diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.cpp b/renderdoc/driver/shaders/dxil/dxil_debug.cpp index 1b89e035c..82ba4f247 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_debug.cpp @@ -848,6 +848,11 @@ static bool ConvertDXILConstantToShaderVariable(const Constant *constant, Shader const rdcarray &members = constant->getMembers(); value = members[0]; } + if(constant->op == Operation::GetElementPtr) + { + RDCLOG("Unsupported Constant Op %s", ToStr(constant->op).c_str()); + return true; + } RDCASSERT(ConvertDXILValueToShaderValue(value, var.type, 0, var.value)); return true; } @@ -1647,6 +1652,11 @@ void ThreadState::EnterEntryPoint(const Function *function, ShaderDebugState *st m_Variables[gv.id] = gv.var; m_Assigned[gv.id] = true; } + for(const GlobalConstant &c : m_GlobalState.constants) + { + m_Variables[c.id] = c.var; + m_Assigned[c.id] = true; + } // Start with the global memory allocations m_Memory = m_GlobalState.memory; @@ -5972,7 +5982,7 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, rdcstr ThreadState::GetArgumentName(uint32_t i) const { - return m_Program.GetArgId(*m_CurrentInstruction, i); + return m_Program.GetArgumentName(m_CurrentInstruction->args[i]); } DXILDebug::Id ThreadState::GetArgumentId(uint32_t i) const @@ -6597,7 +6607,7 @@ void Debugger::ParseDbgOpValue(const DXIL::Instruction &inst, uint32_t instructi // arg 0 is metadata containing the new value const Metadata *valueMD = cast(inst.args[0]); Id resultId = GetSSAId(valueMD->value); - rdcstr resultName = m_Program->GetArgId(valueMD->value); + rdcstr resultName = m_Program->GetArgumentName(valueMD->value); // arg 1 is i64 byte offset in the source variable where the new value is written int64_t value = 0; RDCASSERT(getival(inst.args[1], value)); @@ -7625,6 +7635,38 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain m_GlobalState.globals.push_back(globalVar); m_LiveGlobals[globalVar.id] = true; } + // Find all the constants and create them as shader variables and store them in the global state + for(const Function *f : m_Program->m_Functions) + { + if(!f->external) + { + for(Instruction *inst : f->instructions) + { + for(const Value *arg : inst->args) + { + if(arg && arg->kind() == ValueKind::Constant) + { + Constant *c = (Constant *)arg; + // Ignore if already created + if(m_LiveGlobals[c->ssaId]) + { + continue; + } + + GlobalConstant constantVar; + ConvertDXILTypeToShaderVariable(c->type, constantVar.var); + ConvertDXILConstantToShaderVariable(c, constantVar.var); + constantVar.var.name = m_Program->GetArgumentName(c); + constantVar.id = c->ssaId; + Id id = c->ssaId; + RDCASSERTNOTEQUAL(id, DXILDebug::INVALID_ID); + m_GlobalState.constants.push_back(constantVar); + m_LiveGlobals[constantVar.id] = true; + } + } + } + } + } rdcstr entryPoint = reflection.entryPoint; rdcstr entryFunction = m_Program->GetEntryFunction(); @@ -7732,8 +7774,8 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain if(!DXIL::IsSSA(arg)) continue; Id argId = GetSSAId(arg); - // Add GlobalVar args to the SSA refs (they won't be the result of an instruction) - if(cast(arg)) + // Add GlobalVar and Constant args to the SSA refs (they won't be the result of an instruction) + if(cast(arg) || cast(arg)) { if(ssaRefs.count(argId) == 0) ssaRefs.insert(argId); @@ -8222,6 +8264,10 @@ rdcarray Debugger::ContinueDebug(DebugAPIWrapper *apiWrapper) for(const GlobalVariable &gv : m_GlobalState.globals) initial.changes.push_back({ShaderVariable(), gv.var}); + // constants won't be filled out by entering the entry point, ensure their change is registered. + for(const GlobalConstant &c : m_GlobalState.constants) + initial.changes.push_back({ShaderVariable(), c.var}); + ret.push_back(std::move(initial)); m_Steps++; diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.h b/renderdoc/driver/shaders/dxil/dxil_debug.h index 85084b7fc..0cb2647bb 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.h +++ b/renderdoc/driver/shaders/dxil/dxil_debug.h @@ -121,6 +121,12 @@ struct GlobalVariable ShaderVariable var; }; +struct GlobalConstant +{ + Id id; + ShaderVariable var; +}; + struct ResourceReferenceInfo { ResourceReferenceInfo() : resClass(DXIL::ResourceClass::Invalid) {} @@ -408,6 +414,8 @@ struct GlobalState rdcarray samplers; // Globals across workgroups including inputs (immutable) and outputs (mutable) rdcarray globals; + // Constants across workgroups + rdcarray constants; // Memory created for global variables MemoryTracking memory; }; diff --git a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp index 5a2ea2cff..c6a5df1df 100644 --- a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp @@ -6090,6 +6090,14 @@ rdcstr Program::GetArgId(const Value *v) const return ret; } +rdcstr Program::GetArgumentName(const DXIL::Value *v) const +{ + if(const DXIL::Constant *c = cast(v)) + return StringFormat::Fmt("%c%u", '_', c->ssaId); + + return GetArgId(v); +} + DXILDebug::Id Program::GetResultSSAId(const DXIL::Instruction &inst) { return inst.slot;