Set up instruction list when parsing SPIR-V

This commit is contained in:
baldurk
2020-02-14 16:30:45 +00:00
parent 013ea145d4
commit ffbb9a353a
2 changed files with 82 additions and 2 deletions
+17 -2
View File
@@ -115,20 +115,23 @@ private:
DebugVariableType sourceVarType, const rdcstr &sourceName, uint32_t offset,
const DataType &inType, ShaderVariable &outVar);
/////////////////////////////////////////////////////////
// debug data
DebugAPIWrapper *apiWrapper = NULL;
GlobalState global;
rdcarray<ThreadState> workgroup;
rdcarray<SourceVariableMapping> sourceVars;
rdcarray<size_t> instructionOffsets;
uint32_t activeLaneIndex = 0;
ShaderStage stage;
int steps = 0;
DenseIdMap<rdcstr> strings;
/////////////////////////////////////////////////////////
// parsed data
struct MemberName
{
@@ -137,7 +140,19 @@ private:
rdcstr name;
};
DenseIdMap<rdcstr> strings;
rdcarray<MemberName> memberNames;
std::map<rdcstr, Id> entryLookup;
struct Function
{
size_t begin = 0;
};
SparseIdMap<Function> functions;
Function *curFunction = NULL;
rdcarray<size_t> instructionOffsets;
rdcstr GetRawName(Id id) const;
rdcstr GetHumanName(Id id);
@@ -71,6 +71,14 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader
const std::map<size_t, uint32_t> &instructionLines,
uint32_t activeIndex)
{
Id entryId = entryLookup[entryPoint];
if(entryId == Id())
{
RDCERR("Invalid entry point '%s'", entryPoint.c_str());
return new ShaderDebugTrace;
}
ShaderDebugTrace *ret = new ShaderDebugTrace;
ret->debugger = this;
this->activeLaneIndex = activeIndex;
@@ -83,6 +91,8 @@ ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, const Shader
ThreadState &active = GetActiveLane();
active.nextInstruction = instructionOffsets.indexOf(functions[entryId].begin);
active.ids.resize(idOffsets.size());
// evaluate all constants
@@ -232,8 +242,35 @@ rdcarray<ShaderDebugState> Debugger::ContinueDebug()
// initialise a blank set of shader variable changes in the first ShaderDebugState
if(steps == 0)
{
// we should be sitting at the entry point function prologue, step forward into the first block
// and past any function-local variable declarations
{
Iter it(m_SPIRV, instructionOffsets[active.nextInstruction]);
RDCASSERT(OpDecoder(it).op == Op::Function);
it++;
// vulkan doesn't allow entry points with parameters, next should be a label
RDCASSERT(OpDecoder(it).op == Op::Label);
it++;
// handle any variable declarations
while(OpDecoder(it).op == Op::Variable)
{
OpVariable decl(it);
// TODO declare variable
it++;
}
// next instruction is the first actual instruction we'll execute
active.nextInstruction = instructionOffsets.indexOf(it.offs());
}
ShaderDebugState initial;
initial.nextInstruction = active.nextInstruction;
for(const Id &v : active.live)
initial.changes.push_back({ShaderVariable(), EvaluatePointerVariable(active.ids[v])});
@@ -660,6 +697,10 @@ void Debugger::RegisterOp(Iter it)
OpDecoder opdata(it);
if(opdata.op == Op::Line || opdata.op == Op::NoLine)
{
// ignore OpLine/OpNoLine
}
if(opdata.op == Op::String)
{
OpString string(it);
@@ -680,6 +721,30 @@ void Debugger::RegisterOp(Iter it)
memberNames.push_back({memberName.type, memberName.member, memberName.name});
}
else if(opdata.op == Op::EntryPoint)
{
OpEntryPoint entryPoint(it);
entryLookup[entryPoint.name] = entryPoint.entryPoint;
}
else if(opdata.op == Op::Function)
{
OpFunction func(it);
curFunction = &functions[func.result];
curFunction->begin = it.offs();
}
// everything else inside a function becomes an instruction, including the OpFunction and
// OpFunctionEnd. We won't actually execute these instructions
instructionOffsets.push_back(it.offs());
if(opdata.op == Op::FunctionEnd)
{
curFunction = NULL;
}
}
}; // namespace rdcspv