From 933772c3ec8eaa3ca3c129377353c655bb71681b Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Fri, 6 Dec 2024 09:48:26 +0000 Subject: [PATCH] DXIL ControlFlow Updates added IsForwardConnection() Cache 2D bool array of IsBlock B in any path ahead of Block A --- .../driver/shaders/dxil/dxil_controlflow.cpp | 61 +++++++++++-------- .../driver/shaders/dxil/dxil_controlflow.h | 3 + 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/renderdoc/driver/shaders/dxil/dxil_controlflow.cpp b/renderdoc/driver/shaders/dxil/dxil_controlflow.cpp index 86bfa0564..b0dd23b31 100644 --- a/renderdoc/driver/shaders/dxil/dxil_controlflow.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_controlflow.cpp @@ -56,6 +56,32 @@ already computed namespace DXIL { +bool ControlFlow::IsBlockConnected(uint32_t from, uint32_t to) const +{ + for(uint32_t pathIdx = 0; pathIdx < m_Paths.size(); ++pathIdx) + { + m_CheckedPaths.clear(); + m_CheckedPaths.resize(m_Paths.size()); + for(size_t i = 0; i < m_CheckedPaths.size(); ++i) + m_CheckedPaths[i] = false; + int32_t startIdx = -1; + for(uint32_t i = 0; i < m_Paths[pathIdx].size() - 1; ++i) + { + if(m_Paths[pathIdx][i] == from) + { + startIdx = i; + break; + } + } + // BlockInAnyPath will also check all paths linked to from the end node of the path + if(startIdx != -1 && (BlockInAnyPath(to, pathIdx, startIdx + 1, 0) != -1)) + { + return true; + } + } + return false; +} + bool ControlFlow::TraceBlockFlow(const uint32_t from, BlockPath &path) { if(from == PATH_END) @@ -267,33 +293,20 @@ void ControlFlow::Construct(const rdcarray> &links) } } + // Generate the connections 2D map for quick lookup of forward connections + // IsBlock B in any path ahead of Block A + m_Connections.resize(maxBlockIndex); + for(uint32_t from = 0; from < maxBlockIndex; ++from) + { + m_Connections[from].resize(maxBlockIndex); + for(uint32_t to = 0; to < maxBlockIndex; ++to) + m_Connections[from][to] = IsBlockConnected(from, to); + } + // A loop block is defined by any block which appears in any path starting from the block for(uint32_t block : m_Blocks) { - bool loop = false; - for(uint32_t pathIdx = 0; pathIdx < m_Paths.size(); ++pathIdx) - { - m_CheckedPaths.clear(); - m_CheckedPaths.resize(m_Paths.size()); - for(size_t i = 0; i < m_CheckedPaths.size(); ++i) - m_CheckedPaths[i] = false; - int32_t startIdx = -1; - for(uint32_t i = 0; i < m_Paths[pathIdx].size() - 1; ++i) - { - if(m_Paths[pathIdx][i] == block) - { - startIdx = i; - break; - } - } - // BlockInAnyPath will also check all paths linked to from the end node of the path - if(startIdx != -1 && (BlockInAnyPath(block, pathIdx, startIdx + 1, 0) != -1)) - { - loop = true; - break; - } - } - if(loop) + if(IsForwardConnection(block, block)) m_LoopBlocks.push_back(block); } diff --git a/renderdoc/driver/shaders/dxil/dxil_controlflow.h b/renderdoc/driver/shaders/dxil/dxil_controlflow.h index 55acfa40f..cae68bba2 100644 --- a/renderdoc/driver/shaders/dxil/dxil_controlflow.h +++ b/renderdoc/driver/shaders/dxil/dxil_controlflow.h @@ -39,6 +39,7 @@ public: rdcarray GetUniformBlocks() const { return m_UniformBlocks; } rdcarray GetLoopBlocks() const { return m_LoopBlocks; } uint32_t GetNextUniformBlock(uint32_t from) const; + bool IsForwardConnection(uint32_t from, uint32_t to) const { return m_Connections[from][to]; } private: typedef rdcarray BlockPath; @@ -46,6 +47,7 @@ private: bool TraceBlockFlow(const uint32_t from, BlockPath &path); bool BlockInAllPaths(uint32_t block, uint32_t pathIdx, int32_t startIdx) const; int32_t BlockInAnyPath(uint32_t block, uint32_t pathIdx, int32_t startIdx, int32_t steps) const; + bool ControlFlow::IsBlockConnected(uint32_t from, uint32_t to) const; const uint32_t PATH_END = ~0U; @@ -59,5 +61,6 @@ private: rdcarray m_UniformBlocks; rdcarray m_LoopBlocks; + rdcarray> m_Connections; }; }; // namespace DXIL