From c83be4088aecdd7e8cf06ac3e65d783e73a4751b Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Thu, 3 Apr 2025 09:48:51 +0100 Subject: [PATCH] Change DXIL debugger control flow to use rdcshaders::ControlFlow This emulates maximal re-convergence behaviour and matches how the SPRIV shader debugger control flow works. Remove the quick fix for discard to skip over degenerate branches Remove StepOverDegenerateBranch() method --- renderdoc/driver/shaders/dxil/dxil_debug.cpp | 262 ++++++++++++------- renderdoc/driver/shaders/dxil/dxil_debug.h | 14 +- 2 files changed, 181 insertions(+), 95 deletions(-) diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.cpp b/renderdoc/driver/shaders/dxil/dxil_debug.cpp index 25e004e4d..af350c4a0 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_debug.cpp @@ -27,10 +27,13 @@ #include "core/settings.h" #include "maths/formatpacking.h" #include "replay/common/var_dispatch_helpers.h" +#include "shaders/controlflow.h" RDOC_CONFIG(bool, D3D12_DXILShaderDebugger_Logging, false, "Debug logging for the DXIL shader debugger"); +using namespace rdcshaders; + // TODO: Extend support for Compound Constants: arithmetic, logical ops // TODO: Assert m_Block in ThreadState is correct per instruction // TODO: Automatically execute phi instructions after a branch @@ -1653,7 +1656,7 @@ bool IsNopInstruction(const Instruction &inst) return false; } -bool ThreadState::JumpToBlock(const Block *target) +bool ThreadState::JumpToBlock(const Block *target, bool divergencePoint) { m_PreviousBlock = m_Block; m_PhiVariables.clear(); @@ -1680,6 +1683,24 @@ bool ThreadState::JumpToBlock(const Block *target) uint32_t nextInstruction = m_FunctionInfo->globalInstructionOffset + m_FunctionInstructionIdx; if(m_State && !m_Ended) m_State->nextInstruction = nextInstruction; + + m_EnteredPoints.push_back(m_Block); + RDCASSERTEQUAL(m_FunctionInfo->divergentBlocks.contains(m_PreviousBlock), divergencePoint); + if(divergencePoint) + { + m_Diverged = true; + RDCASSERTEQUAL(m_ConvergencePoint, INVALID_EXECUTION_POINT); + for(const ConvergentBlockData &convergentBlock : m_FunctionInfo->convergentBlocks) + { + if(convergentBlock.first == m_PreviousBlock) + { + m_ConvergencePoint = convergentBlock.second; + break; + } + } + RDCASSERTNOTEQUAL(m_ConvergencePoint, INVALID_EXECUTION_POINT); + } + return true; } @@ -2991,9 +3012,6 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, m_Dead = true; return true; } - // Quick fix : need maximal reconvergence style control flow to handle discard properly - // * If the next instruction is a de-generate jump then skip over it - StepOverDegenerateBranch(); } break; } @@ -4147,8 +4165,10 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, // Branch