diff --git a/renderdoc/shaders/controlflow.cpp b/renderdoc/shaders/controlflow.cpp index 38c8921c0..33b04e6a3 100644 --- a/renderdoc/shaders/controlflow.cpp +++ b/renderdoc/shaders/controlflow.cpp @@ -133,6 +133,18 @@ void Tangle::SetThreadExecutionPoint(ThreadIndex threadId, ExecutionPoint execPo RDCASSERTMSG("Thread not found", threadId); } +void Tangle::SetThreadMergePoint(ThreadIndex threadId, ExecutionPoint execPoint) +{ + for(ThreadReference &threadRef : m_ThreadRefs) + { + if(threadRef.id == threadId) + { + threadRef.mergePoint = execPoint; + return; + } + } +} + void Tangle::SetThreadAlive(ThreadIndex threadId, bool value) { for(ThreadReference &threadRef : m_ThreadRefs) @@ -197,6 +209,30 @@ void Tangle::PruneMergePoints(ExecutionPoint execPoint) m_MergePoints.erase(index + 1, m_MergePoints.size() - index); } +// Get the merge point from the threads in the tangle and add it to the merge point stack +void Tangle::AddMergePointFromThreads() +{ + ExecutionPoint threadMergePoint = INVALID_EXECUTION_POINT; + size_t countNewMergePoints = 0; + for(ThreadReference &threadRef : m_ThreadRefs) + { + if(threadRef.mergePoint != INVALID_EXECUTION_POINT) + { + ++countNewMergePoints; + if(threadMergePoint == INVALID_EXECUTION_POINT) + threadMergePoint = threadRef.mergePoint; + + RDCASSERTEQUAL(threadMergePoint, threadRef.mergePoint); + threadRef.mergePoint = INVALID_EXECUTION_POINT; + } + } + if(threadMergePoint == INVALID_EXECUTION_POINT) + return; + + RDCASSERTEQUAL(countNewMergePoints, m_ThreadRefs.size()); + AddMergePoint(threadMergePoint); +} + // Define tangles to be entangled if the merge point stack of one tangle is contained within the other bool Tangle::Entangled(const Tangle &other) const { @@ -236,7 +272,6 @@ TangleGroup ControlFlow::DivergeTangle(Tangle &tangle) { Tangle newTangle; newTangle.SetId(GetNewTangleId()); - newTangle.AddThreadReference(threadRef); newTangle.SetMergePoints(tangle.GetMergePoints()); newTangle.SetFunctionReturnPoints(tangle.GetFunctionReturnPoints()); newTangle.SetDiverged(false); @@ -244,12 +279,14 @@ TangleGroup ControlFlow::DivergeTangle(Tangle &tangle) newTangle.SetActive(!tangle.IsConverged()); newTangle.SetAlive(true); newTangle.SetStateChanged(true); + newTangle.AddThreadReference(threadRef); newTangles.push_back(newTangle); } } for(Tangle &newTangle : newTangles) { + newTangle.AddMergePointFromThreads(); for(const ThreadReference &threadRef : newTangle.GetThreadRefs()) tangle.RemoveThreadReference(threadRef.id); } @@ -280,6 +317,8 @@ void ControlFlow::ProcessTangleDivergence() tangle.CheckForDivergence(); if(tangle.IsDiverged()) newTangles.append(DivergeTangle(tangle)); + else + tangle.AddMergePointFromThreads(); } m_Tangles.append(newTangles); diff --git a/renderdoc/shaders/controlflow.h b/renderdoc/shaders/controlflow.h index 61bd33b44..0762bb319 100644 --- a/renderdoc/shaders/controlflow.h +++ b/renderdoc/shaders/controlflow.h @@ -45,6 +45,7 @@ const uint32_t INVALID_THREAD_INDEX = (uint32_t)-1; struct ThreadReference { ExecutionPoint execPoint = INVALID_EXECUTION_POINT; + ExecutionPoint mergePoint = INVALID_EXECUTION_POINT; ThreadIndex id = INVALID_THREAD_INDEX; bool m_Alive = true; }; @@ -69,12 +70,15 @@ public: SetThreadAlive(threadId, false); m_StateChanged = true; } + void SetThreadMergePoint(ThreadIndex threadId, ExecutionPoint execPoint); + void AddMergePointFromThreads(); void AddMergePoint(ExecutionPoint execPoint) { // only add a new merge point if(!m_MergePoints.contains(execPoint)) m_MergePoints.push_back(execPoint); m_StateChanged = true; + ClearThreadMergePoints(); } void AddFunctionReturnPoint(ExecutionPoint execPoint) { @@ -141,6 +145,11 @@ private: m_StateChanged = true; } ExecutionPoint GetMergePoint() const { return m_MergePoints.back(); } + void ClearThreadMergePoints() + { + for(ThreadReference &threadRef : m_ThreadRefs) + threadRef.mergePoint = INVALID_EXECUTION_POINT; + } void PopMergePoint(void) { m_MergePoints.pop_back(); @@ -151,11 +160,13 @@ private: { m_MergePoints.clear(); m_StateChanged = true; + ClearThreadMergePoints(); } void SetMergePoints(const rdcarray &points) { m_MergePoints = points; m_StateChanged = true; + ClearThreadMergePoints(); } ExecutionPoint GetFunctionReturnPoint() const { return m_FunctionReturnPoints.back(); } void PopFunctionReturnPoint(void)