From b9945d563e29fdae0d207960fe11e893ffc7cfad Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Mon, 28 Jul 2025 11:50:59 +0100 Subject: [PATCH] Active thread runs scope changes on the device thread Run EnterFunction(), EnterEntryPoint(), ProcessScopeChange() on device thread --- .../driver/shaders/spirv/spirv_debug.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.cpp b/renderdoc/driver/shaders/spirv/spirv_debug.cpp index a83c041f0..04eabc069 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug.cpp @@ -191,8 +191,12 @@ void ThreadState::FillCallstack(rdcarray &funcs) funcs.push_back(frame->function); } +// Must run on the device thread for the active simulation thread void ThreadState::EnterFunction(const rdcarray &arguments) { + if(m_State) + RDCASSERT(debugger.IsDeviceThread()); + ConstIter it = debugger.GetIterForInstruction(nextInstruction); RDCASSERT(OpDecoder(it).op == Op::Function); @@ -532,12 +536,15 @@ void ThreadState::SetDst(Id id, const ShaderVariable &val) } } +// Must run on the device thread for the active simulation thread void ThreadState::ProcessScopeChange(const rdcarray &oldLive, const rdcarray &newLive) { // nothing to do if we aren't tracking into a state if(!m_State) return; + RDCASSERT(debugger.IsDeviceThread()); + // all oldLive (except globals) are going out of scope. all newLive (except globals) are coming // into scope @@ -806,10 +813,14 @@ void ThreadState::SkipIgnoredInstructions() } } +// Must run on the device thread for the active simulation thread void ThreadState::EnterEntryPoint(ShaderDebugState *state) { m_State = state; + if(m_State) + RDCASSERT(debugger.IsDeviceThread()); + EnterFunction({}); m_State = NULL; @@ -4105,6 +4116,13 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray // function. The second time we do have a return value so we process it and continue if(returnValue.name.empty()) { + // for the active thread EnterFunction must be run on the device thread + if(m_State && !debugger.IsDeviceThread()) + { + SetStepNeedsDeviceThread(); + break; + } + // The instruction after a function call is defined to be a convergence point functionReturnPoint = nextInstruction; uint32_t returnInstruction = nextInstruction - 1; @@ -4167,6 +4185,14 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray } else { + // for the active thread ProcessScopeChange must be run on the device thread + if(m_State && !debugger.IsDeviceThread()) + { + callstack.push_back(exitingFrame); + SetStepNeedsDeviceThread(); + break; + } + returnValue.name = ""; hasReturnValueData = false; if(opdata.op == Op::ReturnValue)