Skip to content

Commit 0809a6d

Browse files
committed
Changed ExecutionPointPerId to be an rdcarray instead of std::map
DXIL Debugger optimisation
1 parent b70b79e commit 0809a6d

File tree

2 files changed

+64
-46
lines changed

2 files changed

+64
-46
lines changed

renderdoc/driver/shaders/dxil/dxil_debug.cpp

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6563,6 +6563,39 @@ void ThreadState::StepOverNopInstructions()
65636563
} while(true);
65646564
}
65656565

6566+
void ThreadState::RetireLiveIDs()
6567+
{
6568+
m_State->flags = ShaderEvents::NoEvent;
6569+
m_State->changes.clear();
6570+
6571+
// Remove variables which have gone out of scope
6572+
ExecPointReference current(m_Block, m_FunctionInstructionIdx);
6573+
for(uint32_t id = 0; id < m_Live.size(); ++id)
6574+
{
6575+
if(!m_Live[id])
6576+
continue;
6577+
// The fake output variable is always in scope
6578+
if(id == m_Output.id)
6579+
continue;
6580+
// Globals are always in scope
6581+
if(m_IsGlobal[id])
6582+
continue;
6583+
6584+
RDCASSERT(id < m_FunctionInfo->maxExecPointPerId.size());
6585+
const ExecPointReference maxPoint = m_FunctionInfo->maxExecPointPerId[id];
6586+
RDCASSERT(maxPoint.IsValid());
6587+
// Use control flow to determine if the current execution point is after the maximum point
6588+
if(current.IsAfter(maxPoint, m_FunctionInfo->controlFlow))
6589+
{
6590+
m_Live[id] = false;
6591+
6592+
ShaderVariableChange change;
6593+
change.before = m_Variables[id];
6594+
m_State->changes.push_back(change);
6595+
}
6596+
}
6597+
}
6598+
65666599
void ThreadState::StepNext(ShaderDebugState *state, DebugAPIWrapper *apiWrapper,
65676600
const rdcarray<ThreadState> &workgroup, const rdcarray<bool> &activeMask)
65686601
{
@@ -6578,33 +6611,7 @@ void ThreadState::StepNext(ShaderDebugState *state, DebugAPIWrapper *apiWrapper,
65786611
{
65796612
m_State->flags = ShaderEvents::NoEvent;
65806613
m_State->changes.clear();
6581-
6582-
// Remove variables which have gone out of scope
6583-
ExecPointReference current(m_Block, m_FunctionInstructionIdx);
6584-
for(uint32_t id = 0; id < m_Live.size(); ++id)
6585-
{
6586-
if(!m_Live[id])
6587-
continue;
6588-
// The fake output variable is always in scope
6589-
if(id == m_Output.id)
6590-
continue;
6591-
// Globals are always in scope
6592-
if(m_IsGlobal[id])
6593-
continue;
6594-
6595-
auto itRange = m_FunctionInfo->maxExecPointPerId.find(id);
6596-
RDCASSERT(itRange != m_FunctionInfo->maxExecPointPerId.end());
6597-
const ExecPointReference maxPoint = itRange->second;
6598-
// Use control flow to determine if the current execution point is after the maximum point
6599-
if(current.IsAfter(maxPoint, m_FunctionInfo->controlFlow))
6600-
{
6601-
m_Live[id] = false;
6602-
6603-
ShaderVariableChange change;
6604-
change.before = m_Variables[id];
6605-
m_State->changes.push_back(change);
6606-
}
6607-
}
6614+
RetireLiveIDs();
66086615
}
66096616
ExecuteInstruction(apiWrapper, workgroup, activeMask);
66106617

@@ -8777,13 +8784,13 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
87778784
m_Stage = shaderStage;
87788785

87798786
uint32_t outputSSAId = m_Program->m_NextSSAId;
8780-
uint32_t nextSSAId = outputSSAId + 1;
8787+
uint32_t maxSSAId = outputSSAId + 1;
87818788

87828789
ShaderDebugTrace *ret = new ShaderDebugTrace;
87838790
ret->stage = shaderStage;
87848791

87858792
for(uint32_t i = 0; i < threadsInWorkgroup; i++)
8786-
m_Workgroup.push_back(ThreadState(*this, m_GlobalState, nextSSAId));
8793+
m_Workgroup.push_back(ThreadState(*this, m_GlobalState, maxSSAId));
87878794

87888795
ThreadState &state = GetActiveLane();
87898796

@@ -8900,7 +8907,7 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
89008907
sourceVar.variables.push_back(ref);
89018908
}
89028909

8903-
m_LiveGlobals.resize(nextSSAId);
8910+
m_LiveGlobals.resize(maxSSAId);
89048911
MemoryTracking &globalMemory = m_GlobalState.memory;
89058912
for(const DXIL::GlobalVar *gv : m_Program->m_GlobalVars)
89068913
{
@@ -9066,6 +9073,8 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
90669073

90679074
FunctionInfo::ReferencedIds &ssaRefs = info.referencedIds;
90689075
FunctionInfo::ExecutionPointPerId &ssaMaxExecPoints = info.maxExecPointPerId;
9076+
ssaMaxExecPoints.resize(maxSSAId);
9077+
std::set<Id> ssaMaxRefs;
90699078

90709079
uint32_t curBlock = 0;
90719080
info.instructionToBlock.resize(countInstructions);
@@ -9087,12 +9096,17 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
90879096
RDCASSERTEQUAL(ssaRefs.count(resultId), 0);
90889097
ssaRefs.insert(resultId);
90899098

9090-
auto it = ssaMaxExecPoints.find(resultId);
9091-
if(it == ssaMaxExecPoints.end())
9099+
auto it = ssaMaxRefs.find(resultId);
9100+
if(it == ssaMaxRefs.end())
9101+
{
90929102
ssaMaxExecPoints[resultId] = current;
9103+
ssaMaxRefs.insert(resultId);
9104+
}
90939105
else
9094-
// If the result SSA has tracking then this access should be at a later execution point
9095-
RDCASSERT(it->second.IsAfter(current, controlFlow));
9106+
{
9107+
// If the result SSA has tracking then that access should be after setting the result
9108+
RDCASSERT(current.IsAfter(ssaMaxExecPoints[resultId], controlFlow));
9109+
}
90969110
}
90979111
// Track maximum execution point when an SSA is referenced as an argument
90989112
// Arguments to phi instructions are handled separately
@@ -9112,30 +9126,31 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
91129126
if(ssaRefs.count(argId) == 0)
91139127
ssaRefs.insert(argId);
91149128
}
9115-
auto it = ssaMaxExecPoints.find(argId);
9116-
if(it == ssaMaxExecPoints.end())
9129+
auto it = ssaMaxRefs.find(argId);
9130+
if(it == ssaMaxRefs.end())
91179131
{
91189132
ssaMaxExecPoints[argId] = maxPoint;
9133+
ssaMaxRefs.insert(argId);
91199134
}
91209135
else
91219136
{
91229137
// Update the maximum execution point if access is later than the existing access
9123-
if(maxPoint.IsAfter(it->second, controlFlow))
9124-
it->second = maxPoint;
9138+
if(maxPoint.IsAfter(ssaMaxExecPoints[argId], controlFlow))
9139+
ssaMaxExecPoints[argId] = maxPoint;
91259140
}
91269141
}
91279142
if(inst.op == Operation::Branch || inst.op == Operation::Unreachable ||
91289143
inst.op == Operation::Switch || inst.op == Operation::Ret)
91299144
++curBlock;
91309145
}
91319146
// If these do not match in size that means there is a result SSA that is never read
9132-
RDCASSERTEQUAL(ssaRefs.size(), ssaMaxExecPoints.size());
9147+
RDCASSERTEQUAL(ssaRefs.size(), ssaMaxRefs.size());
91339148

91349149
// Update any SSA max points which are inside a loop to the next uniform block
91359150
// This covers the case of SSA IDs that are assigned to but never accessed
9136-
for(auto &it : ssaMaxExecPoints)
9151+
for(Id id : ssaMaxRefs)
91379152
{
9138-
ExecPointReference &maxPoint = it.second;
9153+
ExecPointReference &maxPoint = ssaMaxExecPoints[id];
91399154
uint32_t block = maxPoint.block;
91409155
// If the current block is in a loop, set the execution point to the next uniform block
91419156
if(loopBlocks.contains(block))
@@ -9312,10 +9327,11 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
93129327
{
93139328
for(LocalMapping &localMapping : scope->localMappings)
93149329
{
9315-
auto it = info.maxExecPointPerId.find(localMapping.debugVarSSAId);
9316-
if(it != info.maxExecPointPerId.end())
9330+
if(localMapping.debugVarSSAId < info.maxExecPointPerId.size())
93179331
{
9318-
const ExecPointReference &current = it->second;
9332+
const ExecPointReference &current = info.maxExecPointPerId[localMapping.debugVarSSAId];
9333+
if(!current.IsValid())
9334+
continue;
93199335
uint32_t scopeEndInst = scope->maxInstruction + 1;
93209336
scopeEndInst = RDCMIN(scopeEndInst, (uint32_t)info.instructionToBlock.size() - 1);
93219337
const uint32_t scopeEndBlock = info.instructionToBlock[scopeEndInst];
@@ -9327,7 +9343,7 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
93279343
scopeEnd.instruction = info.function->blocks[nextUniformBlock]->startInstructionIdx + 1;
93289344
}
93299345
if(scopeEnd.IsAfter(current, controlFlow))
9330-
it->second = scopeEnd;
9346+
info.maxExecPointPerId[localMapping.debugVarSSAId] = scopeEnd;
93319347
}
93329348
}
93339349
}

renderdoc/driver/shaders/dxil/dxil_debug.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct ExecPointReference
5858
{
5959
}
6060
bool IsAfter(const ExecPointReference &from, const DXIL::ControlFlow &controlFlow) const;
61+
bool IsValid() const { return block != ~0U && instruction != ~0U; }
6162

6263
uint32_t block;
6364
uint32_t instruction;
@@ -91,7 +92,7 @@ struct InputData
9192
struct FunctionInfo
9293
{
9394
typedef std::set<Id> ReferencedIds;
94-
typedef std::map<Id, ExecPointReference> ExecutionPointPerId;
95+
typedef rdcarray<ExecPointReference> ExecutionPointPerId;
9596
typedef std::map<uint32_t, ReferencedIds> PhiReferencedIdsPerBlock;
9697
typedef rdcarray<rdcstr> Callstack;
9798

@@ -263,6 +264,7 @@ struct ThreadState
263264
Id GetArgumentId(uint32_t i) const;
264265
ResourceReferenceInfo GetResource(Id handleId, bool &annotatedHandle);
265266
void FillCallstack(ShaderDebugState &state);
267+
void RetireLiveIDs();
266268

267269
bool GetShaderVariable(const DXIL::Value *dxilValue, DXIL::Operation op, DXIL::DXOp dxOpCode,
268270
ShaderVariable &var, bool flushDenormInput = true) const

0 commit comments

Comments
 (0)