mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-12 13:00:32 +00:00
SPIRV ControlFlow helper class
Implements maximal reconvergence
This commit is contained in:
@@ -99,6 +99,7 @@ set(sources
|
||||
glslang_compile.h
|
||||
spirv_common.cpp
|
||||
spirv_common.h
|
||||
spirv_controlflow.cpp
|
||||
spirv_editor.cpp
|
||||
spirv_editor.h
|
||||
spirv_gen.cpp
|
||||
|
||||
@@ -155,6 +155,12 @@
|
||||
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
|
||||
<ForcedIncludeFiles>precompiled.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<ClCompile Include="spirv_controlflow.cpp">
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
|
||||
<ForcedIncludeFiles>precompiled.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<ClCompile Include="spirv_debug.cpp">
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
@@ -267,6 +273,7 @@
|
||||
<ClInclude Include="precompiled.h" />
|
||||
<ClInclude Include="spirv_common.h" />
|
||||
<ClInclude Include="spirv_compile.h" />
|
||||
<ClInclude Include="spirv_controlflow.h" />
|
||||
<ClInclude Include="spirv_debug.h" />
|
||||
<ClInclude Include="spirv_editor.h" />
|
||||
<ClInclude Include="spirv_gen.h" />
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
<ClCompile Include="spirv_gen.cpp">
|
||||
<Filter>JSON-Generated helpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="spirv_controlflow.cpp" />
|
||||
<ClCompile Include="spirv_reflect.cpp" />
|
||||
<ClCompile Include="glslang_compile.cpp" />
|
||||
<ClCompile Include="spirv_processor.cpp" />
|
||||
@@ -297,6 +298,7 @@
|
||||
<ClInclude Include="spirv_op_helpers.h">
|
||||
<Filter>JSON-Generated helpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="spirv_controlflow.h" />
|
||||
<ClInclude Include="spirv_processor.h" />
|
||||
<ClInclude Include="spirv_debug.h" />
|
||||
<ClInclude Include="..\..\..\3rdparty\glslang\SPIRV\GLSL.ext.ARM.h">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,214 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2025 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api/replay/rdcarray.h"
|
||||
#include "api/replay/rdcflatmap.h"
|
||||
#include "os/os_specific.h"
|
||||
|
||||
namespace rdcspv
|
||||
{
|
||||
class Tangle;
|
||||
class ControlFlow;
|
||||
|
||||
typedef uint32_t ExecutionPoint;
|
||||
typedef uint32_t ThreadIndex;
|
||||
typedef rdcarray<Tangle> TangleGroup;
|
||||
typedef rdcarray<ExecutionPoint> EnteredExecutionPoints;
|
||||
typedef rdcflatmap<ThreadIndex, EnteredExecutionPoints> ThreadExecutionStates;
|
||||
|
||||
const ExecutionPoint INVALID_EXECUTION_POINT = (uint32_t)-1;
|
||||
const uint32_t INVALID_THREAD_INDEX = (uint32_t)-1;
|
||||
|
||||
struct ThreadReference
|
||||
{
|
||||
ExecutionPoint execPoint = INVALID_EXECUTION_POINT;
|
||||
ThreadIndex id = INVALID_THREAD_INDEX;
|
||||
bool m_Alive = true;
|
||||
};
|
||||
|
||||
class Tangle
|
||||
{
|
||||
public:
|
||||
Tangle() = default;
|
||||
|
||||
bool IsAliveActive() const { return m_Alive && m_Active; }
|
||||
ExecutionPoint GetExecutionPoint() const { return m_ThreadRefs[0].execPoint; }
|
||||
uint32_t GetThreadCount() const { return (uint32_t)m_ThreadRefs.count(); }
|
||||
bool ContainsThread(ThreadIndex threadId) const;
|
||||
const rdcarray<ThreadReference> &GetThreadRefs() const { return m_ThreadRefs; }
|
||||
void SetDiverged(bool value)
|
||||
{
|
||||
m_Diverged = value;
|
||||
m_StateChanged = true;
|
||||
}
|
||||
void SetThreadDead(ThreadIndex threadId)
|
||||
{
|
||||
SetThreadAlive(threadId, false);
|
||||
m_StateChanged = true;
|
||||
}
|
||||
void AddMergePoint(ExecutionPoint execPoint)
|
||||
{
|
||||
m_MergePoints.push_back(execPoint);
|
||||
m_StateChanged = true;
|
||||
}
|
||||
void AddFunctionReturnPoint(ExecutionPoint execPoint)
|
||||
{
|
||||
m_MergePoints.push_back(execPoint);
|
||||
m_FunctionReturnPoints.push_back(execPoint);
|
||||
m_StateChanged = true;
|
||||
}
|
||||
bool IsAlive() const { return m_Alive; }
|
||||
|
||||
private:
|
||||
int32_t GetId() const { return m_Id; }
|
||||
void SetThreadExecutionPoint(ThreadIndex threadId, ExecutionPoint execPoint);
|
||||
bool Entangled(const Tangle &other) const;
|
||||
void AddThreadReference(const ThreadReference &threadRef)
|
||||
{
|
||||
m_ThreadRefs.push_back(threadRef);
|
||||
m_StateChanged = true;
|
||||
}
|
||||
void RemoveThreadReference(const ThreadIndex &threadId)
|
||||
{
|
||||
m_ThreadRefs.removeIf(
|
||||
[threadId](const ThreadReference &threadRef) { return threadRef.id == threadId; });
|
||||
m_StateChanged = true;
|
||||
}
|
||||
void SetThreadAlive(ThreadIndex threadId, bool value);
|
||||
void SetId(int32_t id) { m_Id = id; }
|
||||
void SetAlive(bool value)
|
||||
{
|
||||
if(m_Alive != value)
|
||||
{
|
||||
m_Alive = value;
|
||||
m_StateChanged = true;
|
||||
}
|
||||
}
|
||||
void SetActive(bool value)
|
||||
{
|
||||
if(m_Active != value)
|
||||
{
|
||||
m_Active = value;
|
||||
m_StateChanged = true;
|
||||
}
|
||||
}
|
||||
bool IsConverged() const { return m_Converged; }
|
||||
bool IsDiverged() const { return m_Diverged; }
|
||||
void SetConverged(bool value)
|
||||
{
|
||||
if(m_Converged != value)
|
||||
{
|
||||
m_Converged = value;
|
||||
m_StateChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsStateChanged() const { return m_StateChanged; }
|
||||
void SetStateChanged(bool value) { m_StateChanged = value; }
|
||||
void AppendThreadReferences(const rdcarray<ThreadReference> &threadRefs)
|
||||
{
|
||||
m_ThreadRefs.append(threadRefs);
|
||||
m_StateChanged = true;
|
||||
}
|
||||
void ClearThreadReferences()
|
||||
{
|
||||
m_ThreadRefs.clear();
|
||||
m_StateChanged = true;
|
||||
}
|
||||
ExecutionPoint GetMergePoint() const { return m_MergePoints.back(); }
|
||||
void PopMergePoint(void)
|
||||
{
|
||||
m_MergePoints.pop_back();
|
||||
m_StateChanged = true;
|
||||
}
|
||||
const rdcarray<ExecutionPoint> &GetMergePoints(void) const { return m_MergePoints; }
|
||||
void ClearMergePoints(void)
|
||||
{
|
||||
m_MergePoints.clear();
|
||||
m_StateChanged = true;
|
||||
}
|
||||
void SetMergePoints(const rdcarray<ExecutionPoint> &points)
|
||||
{
|
||||
m_MergePoints = points;
|
||||
m_StateChanged = true;
|
||||
}
|
||||
ExecutionPoint GetFunctionReturnPoint() const { return m_FunctionReturnPoints.back(); }
|
||||
void PopFunctionReturnPoint(void)
|
||||
{
|
||||
m_FunctionReturnPoints.pop_back();
|
||||
m_StateChanged = true;
|
||||
}
|
||||
const rdcarray<ExecutionPoint> &GetFunctionReturnPoints(void) const
|
||||
{
|
||||
return m_FunctionReturnPoints;
|
||||
}
|
||||
void ClearFunctionReturnPoints(void)
|
||||
{
|
||||
m_FunctionReturnPoints.clear();
|
||||
m_StateChanged = true;
|
||||
}
|
||||
void SetFunctionReturnPoints(const rdcarray<ExecutionPoint> &points)
|
||||
{
|
||||
m_FunctionReturnPoints = points;
|
||||
m_StateChanged = true;
|
||||
}
|
||||
void PruneMergePoints(ExecutionPoint execPoint);
|
||||
void CheckForDivergence();
|
||||
|
||||
rdcarray<ThreadReference> m_ThreadRefs;
|
||||
rdcarray<ExecutionPoint> m_MergePoints;
|
||||
rdcarray<ExecutionPoint> m_FunctionReturnPoints;
|
||||
int32_t m_Id = -1;
|
||||
bool m_Active = false;
|
||||
bool m_Alive = false;
|
||||
bool m_Diverged = false;
|
||||
bool m_Converged = false;
|
||||
bool m_StateChanged = false;
|
||||
|
||||
friend ControlFlow;
|
||||
};
|
||||
|
||||
class ControlFlow
|
||||
{
|
||||
public:
|
||||
void Construct(const rdcarray<ThreadIndex> &threadIds);
|
||||
TangleGroup &GetTangles() { return m_Tangles; }
|
||||
void UpdateState(const ThreadExecutionStates &threadExecutionStates);
|
||||
|
||||
private:
|
||||
TangleGroup DivergeTangle(Tangle &tangle);
|
||||
void ProcessTangleDivergence();
|
||||
void ProcessTangleDeactivation();
|
||||
void ActivateIndependentTangles();
|
||||
void ProcessTangleConvergence();
|
||||
void MergeConvergedTangles();
|
||||
int32_t GetNewTangleId() { return Atomic::Inc32(&s_NextTangleId); }
|
||||
|
||||
TangleGroup m_Tangles;
|
||||
static int32_t s_NextTangleId;
|
||||
};
|
||||
|
||||
}; // namespace rdcspv
|
||||
Reference in New Issue
Block a user