From 61bf255ea0d29b07fdef256c3eee9ec799b9d4f9 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Thu, 27 Nov 2025 07:51:07 +1300 Subject: [PATCH] Updates to SSA lifetime and UI changes related to shader base pointers Mark potential pointer bases as having no end lifetime (similar to global variables) Do no make an out of scope change and an in scope change if the ID is in the old and new live lists (can happen for pointer base variables) --- .../driver/shaders/spirv/spirv_debug.cpp | 19 +++++++++++++------ .../shaders/spirv/spirv_debug_setup.cpp | 12 ++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.cpp b/renderdoc/driver/shaders/spirv/spirv_debug.cpp index e1f05b07f..ceebf03e6 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug.cpp @@ -393,7 +393,7 @@ DeviceOpResult ThreadState::WritePointerValue(Id pointer, const ShaderVariable & // Mark the pointer as being live bool wasLive = SetLive(pointer); - bool baseWasLive = (pointer == ptrid) ? wasLive : true; + bool baseWasLive = (pointer == ptrid) ? wasLive : live.contains(ptrid); rdcarray changes; rdcarray &pointers = pointersForId[ptrid]; @@ -497,13 +497,16 @@ DeviceOpResult ThreadState::WritePointerValue(Id pointer, const ShaderVariable & includeBaseChange = true; } - // if this is the first local write, mark this variable as becoming alive here, instead of at - // its declaration or if the variable wasn't live - if(firstLocalWrite || !baseWasLive) - basechange.before = {}; - if(includeBaseChange) { + // mark this variable as becoming alive here, + // if this is the first local write (instead of at its declaration) + if(firstLocalWrite) + basechange.before = {}; + + if(!baseWasLive) + basechange.before = {}; + pendingDebugState.changes.push_back(basechange); SetLive(ptrid); } @@ -634,6 +637,8 @@ void ThreadState::ProcessScopeChange(const rdcarray &oldLive, const rdcarray { if(liveGlobals.contains(id)) continue; + if(newLive.contains(id)) + continue; DeviceOpResult opResult = debugger.GetPointerValue(ids[id], val); SPIRV_DEBUG_RDCASSERTEQUAL(opResult, DeviceOpResult::Succeeded); @@ -652,6 +657,8 @@ void ThreadState::ProcessScopeChange(const rdcarray &oldLive, const rdcarray { if(liveGlobals.contains(id)) continue; + if(oldLive.contains(id)) + continue; DeviceOpResult opResult = debugger.GetPointerValue(ids[id], val); SPIRV_DEBUG_RDCASSERTEQUAL(opResult, DeviceOpResult::Succeeded); diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp index 9259cb3aa..5b8946c47 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_setup.cpp @@ -4477,6 +4477,18 @@ void Debugger::RegisterOp(Iter it) m_DebugInfo.valid = true; } } + else if((opdata.op == Op::AccessChain) || (opdata.op == Op::InBoundsAccessChain)) + { + OpAccessChain chain(it); + // Base pointers never retire + idLiveRange[chain.base].second = ~0U; + } + else if((opdata.op == Op::PtrAccessChain) || (opdata.op == Op::InBoundsPtrAccessChain)) + { + OpPtrAccessChain chain(it); + // Base pointers never retire + idLiveRange[chain.base].second = ~0U; + } if(opdata.op == Op::Source) {