mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Changed ExecutionPointPerId to be an rdcarray instead of std::map
DXIL Debugger optimisation
This commit is contained in:
@@ -6563,6 +6563,39 @@ void ThreadState::StepOverNopInstructions()
|
|||||||
} while(true);
|
} while(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ThreadState::RetireLiveIDs()
|
||||||
|
{
|
||||||
|
m_State->flags = ShaderEvents::NoEvent;
|
||||||
|
m_State->changes.clear();
|
||||||
|
|
||||||
|
// Remove variables which have gone out of scope
|
||||||
|
ExecPointReference current(m_Block, m_FunctionInstructionIdx);
|
||||||
|
for(uint32_t id = 0; id < m_Live.size(); ++id)
|
||||||
|
{
|
||||||
|
if(!m_Live[id])
|
||||||
|
continue;
|
||||||
|
// The fake output variable is always in scope
|
||||||
|
if(id == m_Output.id)
|
||||||
|
continue;
|
||||||
|
// Globals are always in scope
|
||||||
|
if(m_IsGlobal[id])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RDCASSERT(id < m_FunctionInfo->maxExecPointPerId.size());
|
||||||
|
const ExecPointReference maxPoint = m_FunctionInfo->maxExecPointPerId[id];
|
||||||
|
RDCASSERT(maxPoint.IsValid());
|
||||||
|
// Use control flow to determine if the current execution point is after the maximum point
|
||||||
|
if(current.IsAfter(maxPoint, m_FunctionInfo->controlFlow))
|
||||||
|
{
|
||||||
|
m_Live[id] = false;
|
||||||
|
|
||||||
|
ShaderVariableChange change;
|
||||||
|
change.before = m_Variables[id];
|
||||||
|
m_State->changes.push_back(change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ThreadState::StepNext(ShaderDebugState *state, DebugAPIWrapper *apiWrapper,
|
void ThreadState::StepNext(ShaderDebugState *state, DebugAPIWrapper *apiWrapper,
|
||||||
const rdcarray<ThreadState> &workgroup, const rdcarray<bool> &activeMask)
|
const rdcarray<ThreadState> &workgroup, const rdcarray<bool> &activeMask)
|
||||||
{
|
{
|
||||||
@@ -6578,33 +6611,7 @@ void ThreadState::StepNext(ShaderDebugState *state, DebugAPIWrapper *apiWrapper,
|
|||||||
{
|
{
|
||||||
m_State->flags = ShaderEvents::NoEvent;
|
m_State->flags = ShaderEvents::NoEvent;
|
||||||
m_State->changes.clear();
|
m_State->changes.clear();
|
||||||
|
RetireLiveIDs();
|
||||||
// Remove variables which have gone out of scope
|
|
||||||
ExecPointReference current(m_Block, m_FunctionInstructionIdx);
|
|
||||||
for(uint32_t id = 0; id < m_Live.size(); ++id)
|
|
||||||
{
|
|
||||||
if(!m_Live[id])
|
|
||||||
continue;
|
|
||||||
// The fake output variable is always in scope
|
|
||||||
if(id == m_Output.id)
|
|
||||||
continue;
|
|
||||||
// Globals are always in scope
|
|
||||||
if(m_IsGlobal[id])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto itRange = m_FunctionInfo->maxExecPointPerId.find(id);
|
|
||||||
RDCASSERT(itRange != m_FunctionInfo->maxExecPointPerId.end());
|
|
||||||
const ExecPointReference maxPoint = itRange->second;
|
|
||||||
// Use control flow to determine if the current execution point is after the maximum point
|
|
||||||
if(current.IsAfter(maxPoint, m_FunctionInfo->controlFlow))
|
|
||||||
{
|
|
||||||
m_Live[id] = false;
|
|
||||||
|
|
||||||
ShaderVariableChange change;
|
|
||||||
change.before = m_Variables[id];
|
|
||||||
m_State->changes.push_back(change);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ExecuteInstruction(apiWrapper, workgroup, activeMask);
|
ExecuteInstruction(apiWrapper, workgroup, activeMask);
|
||||||
|
|
||||||
@@ -8777,13 +8784,13 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
|||||||
m_Stage = shaderStage;
|
m_Stage = shaderStage;
|
||||||
|
|
||||||
uint32_t outputSSAId = m_Program->m_NextSSAId;
|
uint32_t outputSSAId = m_Program->m_NextSSAId;
|
||||||
uint32_t nextSSAId = outputSSAId + 1;
|
uint32_t maxSSAId = outputSSAId + 1;
|
||||||
|
|
||||||
ShaderDebugTrace *ret = new ShaderDebugTrace;
|
ShaderDebugTrace *ret = new ShaderDebugTrace;
|
||||||
ret->stage = shaderStage;
|
ret->stage = shaderStage;
|
||||||
|
|
||||||
for(uint32_t i = 0; i < threadsInWorkgroup; i++)
|
for(uint32_t i = 0; i < threadsInWorkgroup; i++)
|
||||||
m_Workgroup.push_back(ThreadState(*this, m_GlobalState, nextSSAId));
|
m_Workgroup.push_back(ThreadState(*this, m_GlobalState, maxSSAId));
|
||||||
|
|
||||||
ThreadState &state = GetActiveLane();
|
ThreadState &state = GetActiveLane();
|
||||||
|
|
||||||
@@ -8900,7 +8907,7 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
|||||||
sourceVar.variables.push_back(ref);
|
sourceVar.variables.push_back(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_LiveGlobals.resize(nextSSAId);
|
m_LiveGlobals.resize(maxSSAId);
|
||||||
MemoryTracking &globalMemory = m_GlobalState.memory;
|
MemoryTracking &globalMemory = m_GlobalState.memory;
|
||||||
for(const DXIL::GlobalVar *gv : m_Program->m_GlobalVars)
|
for(const DXIL::GlobalVar *gv : m_Program->m_GlobalVars)
|
||||||
{
|
{
|
||||||
@@ -9066,6 +9073,8 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
|||||||
|
|
||||||
FunctionInfo::ReferencedIds &ssaRefs = info.referencedIds;
|
FunctionInfo::ReferencedIds &ssaRefs = info.referencedIds;
|
||||||
FunctionInfo::ExecutionPointPerId &ssaMaxExecPoints = info.maxExecPointPerId;
|
FunctionInfo::ExecutionPointPerId &ssaMaxExecPoints = info.maxExecPointPerId;
|
||||||
|
ssaMaxExecPoints.resize(maxSSAId);
|
||||||
|
std::set<Id> ssaMaxRefs;
|
||||||
|
|
||||||
uint32_t curBlock = 0;
|
uint32_t curBlock = 0;
|
||||||
info.instructionToBlock.resize(countInstructions);
|
info.instructionToBlock.resize(countInstructions);
|
||||||
@@ -9087,12 +9096,17 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
|||||||
RDCASSERTEQUAL(ssaRefs.count(resultId), 0);
|
RDCASSERTEQUAL(ssaRefs.count(resultId), 0);
|
||||||
ssaRefs.insert(resultId);
|
ssaRefs.insert(resultId);
|
||||||
|
|
||||||
auto it = ssaMaxExecPoints.find(resultId);
|
auto it = ssaMaxRefs.find(resultId);
|
||||||
if(it == ssaMaxExecPoints.end())
|
if(it == ssaMaxRefs.end())
|
||||||
|
{
|
||||||
ssaMaxExecPoints[resultId] = current;
|
ssaMaxExecPoints[resultId] = current;
|
||||||
|
ssaMaxRefs.insert(resultId);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
// If the result SSA has tracking then this access should be at a later execution point
|
{
|
||||||
RDCASSERT(it->second.IsAfter(current, controlFlow));
|
// If the result SSA has tracking then that access should be after setting the result
|
||||||
|
RDCASSERT(current.IsAfter(ssaMaxExecPoints[resultId], controlFlow));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Track maximum execution point when an SSA is referenced as an argument
|
// Track maximum execution point when an SSA is referenced as an argument
|
||||||
// Arguments to phi instructions are handled separately
|
// Arguments to phi instructions are handled separately
|
||||||
@@ -9112,16 +9126,17 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
|||||||
if(ssaRefs.count(argId) == 0)
|
if(ssaRefs.count(argId) == 0)
|
||||||
ssaRefs.insert(argId);
|
ssaRefs.insert(argId);
|
||||||
}
|
}
|
||||||
auto it = ssaMaxExecPoints.find(argId);
|
auto it = ssaMaxRefs.find(argId);
|
||||||
if(it == ssaMaxExecPoints.end())
|
if(it == ssaMaxRefs.end())
|
||||||
{
|
{
|
||||||
ssaMaxExecPoints[argId] = maxPoint;
|
ssaMaxExecPoints[argId] = maxPoint;
|
||||||
|
ssaMaxRefs.insert(argId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Update the maximum execution point if access is later than the existing access
|
// Update the maximum execution point if access is later than the existing access
|
||||||
if(maxPoint.IsAfter(it->second, controlFlow))
|
if(maxPoint.IsAfter(ssaMaxExecPoints[argId], controlFlow))
|
||||||
it->second = maxPoint;
|
ssaMaxExecPoints[argId] = maxPoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(inst.op == Operation::Branch || inst.op == Operation::Unreachable ||
|
if(inst.op == Operation::Branch || inst.op == Operation::Unreachable ||
|
||||||
@@ -9129,13 +9144,13 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
|||||||
++curBlock;
|
++curBlock;
|
||||||
}
|
}
|
||||||
// If these do not match in size that means there is a result SSA that is never read
|
// If these do not match in size that means there is a result SSA that is never read
|
||||||
RDCASSERTEQUAL(ssaRefs.size(), ssaMaxExecPoints.size());
|
RDCASSERTEQUAL(ssaRefs.size(), ssaMaxRefs.size());
|
||||||
|
|
||||||
// Update any SSA max points which are inside a loop to the next uniform block
|
// Update any SSA max points which are inside a loop to the next uniform block
|
||||||
// This covers the case of SSA IDs that are assigned to but never accessed
|
// This covers the case of SSA IDs that are assigned to but never accessed
|
||||||
for(auto &it : ssaMaxExecPoints)
|
for(Id id : ssaMaxRefs)
|
||||||
{
|
{
|
||||||
ExecPointReference &maxPoint = it.second;
|
ExecPointReference &maxPoint = ssaMaxExecPoints[id];
|
||||||
uint32_t block = maxPoint.block;
|
uint32_t block = maxPoint.block;
|
||||||
// If the current block is in a loop, set the execution point to the next uniform block
|
// If the current block is in a loop, set the execution point to the next uniform block
|
||||||
if(loopBlocks.contains(block))
|
if(loopBlocks.contains(block))
|
||||||
@@ -9312,10 +9327,11 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
|||||||
{
|
{
|
||||||
for(LocalMapping &localMapping : scope->localMappings)
|
for(LocalMapping &localMapping : scope->localMappings)
|
||||||
{
|
{
|
||||||
auto it = info.maxExecPointPerId.find(localMapping.debugVarSSAId);
|
if(localMapping.debugVarSSAId < info.maxExecPointPerId.size())
|
||||||
if(it != info.maxExecPointPerId.end())
|
|
||||||
{
|
{
|
||||||
const ExecPointReference ¤t = it->second;
|
const ExecPointReference ¤t = info.maxExecPointPerId[localMapping.debugVarSSAId];
|
||||||
|
if(!current.IsValid())
|
||||||
|
continue;
|
||||||
uint32_t scopeEndInst = scope->maxInstruction + 1;
|
uint32_t scopeEndInst = scope->maxInstruction + 1;
|
||||||
scopeEndInst = RDCMIN(scopeEndInst, (uint32_t)info.instructionToBlock.size() - 1);
|
scopeEndInst = RDCMIN(scopeEndInst, (uint32_t)info.instructionToBlock.size() - 1);
|
||||||
const uint32_t scopeEndBlock = info.instructionToBlock[scopeEndInst];
|
const uint32_t scopeEndBlock = info.instructionToBlock[scopeEndInst];
|
||||||
@@ -9327,7 +9343,7 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
|||||||
scopeEnd.instruction = info.function->blocks[nextUniformBlock]->startInstructionIdx + 1;
|
scopeEnd.instruction = info.function->blocks[nextUniformBlock]->startInstructionIdx + 1;
|
||||||
}
|
}
|
||||||
if(scopeEnd.IsAfter(current, controlFlow))
|
if(scopeEnd.IsAfter(current, controlFlow))
|
||||||
it->second = scopeEnd;
|
info.maxExecPointPerId[localMapping.debugVarSSAId] = scopeEnd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ struct ExecPointReference
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
bool IsAfter(const ExecPointReference &from, const DXIL::ControlFlow &controlFlow) const;
|
bool IsAfter(const ExecPointReference &from, const DXIL::ControlFlow &controlFlow) const;
|
||||||
|
bool IsValid() const { return block != ~0U && instruction != ~0U; }
|
||||||
|
|
||||||
uint32_t block;
|
uint32_t block;
|
||||||
uint32_t instruction;
|
uint32_t instruction;
|
||||||
@@ -91,7 +92,7 @@ struct InputData
|
|||||||
struct FunctionInfo
|
struct FunctionInfo
|
||||||
{
|
{
|
||||||
typedef std::set<Id> ReferencedIds;
|
typedef std::set<Id> ReferencedIds;
|
||||||
typedef std::map<Id, ExecPointReference> ExecutionPointPerId;
|
typedef rdcarray<ExecPointReference> ExecutionPointPerId;
|
||||||
typedef std::map<uint32_t, ReferencedIds> PhiReferencedIdsPerBlock;
|
typedef std::map<uint32_t, ReferencedIds> PhiReferencedIdsPerBlock;
|
||||||
typedef rdcarray<rdcstr> Callstack;
|
typedef rdcarray<rdcstr> Callstack;
|
||||||
|
|
||||||
@@ -263,6 +264,7 @@ struct ThreadState
|
|||||||
Id GetArgumentId(uint32_t i) const;
|
Id GetArgumentId(uint32_t i) const;
|
||||||
ResourceReferenceInfo GetResource(Id handleId, bool &annotatedHandle);
|
ResourceReferenceInfo GetResource(Id handleId, bool &annotatedHandle);
|
||||||
void FillCallstack(ShaderDebugState &state);
|
void FillCallstack(ShaderDebugState &state);
|
||||||
|
void RetireLiveIDs();
|
||||||
|
|
||||||
bool GetShaderVariable(const DXIL::Value *dxilValue, DXIL::Operation op, DXIL::DXOp dxOpCode,
|
bool GetShaderVariable(const DXIL::Value *dxilValue, DXIL::Operation op, DXIL::DXOp dxOpCode,
|
||||||
ShaderVariable &var, bool flushDenormInput = true) const
|
ShaderVariable &var, bool flushDenormInput = true) const
|
||||||
|
|||||||
Reference in New Issue
Block a user