mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-20 20:55:42 +00:00
DXIL Debugger methods
void CalcActiveMask(rdcarray<bool> &activeMask); void ParseDbgOpDeclare(const DXIL::Instruction &inst, uint32_t instructionIndex); void ParseDbgOpValue(const DXIL::Instruction &inst, uint32_t instructionIndex); size_t AddScopedDebugData(const DXIL::Metadata *scopeMD, uint32_t instructionIndex); size_t FindScopedDebugDataIndex(const DXIL::Metadata *md) const; size_t Debugger::FindScopedDebugDataIndex(const uint32_t instructionIndex) const; void AddDebugType(const DXIL::Metadata *typeMD);
This commit is contained in:
@@ -3428,6 +3428,370 @@ rdcstr Debugger::GetResourceReferenceName(const DXIL::Program *program,
|
||||
}
|
||||
|
||||
// member functions
|
||||
void Debugger::CalcActiveMask(rdcarray<bool> &activeMask)
|
||||
{
|
||||
// one bool per workgroup thread
|
||||
activeMask.resize(m_Workgroups.size());
|
||||
|
||||
// mark any threads that have finished as inactive, otherwise they're active
|
||||
for(size_t i = 0; i < m_Workgroups.size(); i++)
|
||||
activeMask[i] = !m_Workgroups[i].Finished();
|
||||
|
||||
// only pixel shaders automatically converge workgroups, compute shaders need explicit sync
|
||||
if(m_Stage != ShaderStage::Pixel)
|
||||
return;
|
||||
|
||||
// TODO: implement pixel shader convergence
|
||||
return;
|
||||
}
|
||||
|
||||
size_t Debugger::FindScopedDebugDataIndex(const uint32_t instructionIndex) const
|
||||
{
|
||||
size_t countScopes = m_DebugInfo.scopedDebugDatas.size();
|
||||
size_t scopeIndex = countScopes;
|
||||
for(size_t i = 0; i < countScopes; i++)
|
||||
{
|
||||
if((m_DebugInfo.scopedDebugDatas[i].minInstruction <= instructionIndex) &&
|
||||
(instructionIndex <= m_DebugInfo.scopedDebugDatas[i].maxInstruction))
|
||||
scopeIndex = i;
|
||||
else if(scopeIndex < countScopes)
|
||||
break;
|
||||
}
|
||||
return scopeIndex;
|
||||
}
|
||||
|
||||
size_t Debugger::FindScopedDebugDataIndex(const DXIL::Metadata *md) const
|
||||
{
|
||||
size_t countScopes = m_DebugInfo.scopedDebugDatas.size();
|
||||
for(size_t i = 0; i < countScopes; i++)
|
||||
{
|
||||
if(m_DebugInfo.scopedDebugDatas[i].md == md)
|
||||
return i;
|
||||
}
|
||||
return countScopes;
|
||||
}
|
||||
|
||||
size_t Debugger::AddScopedDebugData(const DXIL::Metadata *scopeMD, uint32_t instructionIndex)
|
||||
{
|
||||
// Iterate upwards to find DISubprogram or DIFile scope
|
||||
while((scopeMD->dwarf->type != DIBase::File) && (scopeMD->dwarf->type != DIBase::Subprogram))
|
||||
scopeMD = m_Program->GetDebugScopeParent(scopeMD->dwarf);
|
||||
|
||||
size_t scopeIndex = FindScopedDebugDataIndex(scopeMD);
|
||||
// Add a new DebugScope
|
||||
if(scopeIndex == m_DebugInfo.scopedDebugDatas.size())
|
||||
{
|
||||
// Find the parent scope and add this to its children
|
||||
const DXIL::Metadata *parentScope = m_Program->GetDebugScopeParent(scopeMD->dwarf);
|
||||
|
||||
ScopedDebugData scope;
|
||||
scope.md = scopeMD;
|
||||
scope.minInstruction = instructionIndex;
|
||||
scope.maxInstruction = instructionIndex;
|
||||
// File scope should not have a parent
|
||||
if(scopeMD->dwarf->type != DIBase::File)
|
||||
{
|
||||
RDCASSERT(parentScope);
|
||||
scope.parentIndex = AddScopedDebugData(parentScope, instructionIndex);
|
||||
RDCASSERT(scope.parentIndex < m_DebugInfo.scopedDebugDatas.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCASSERT(!parentScope);
|
||||
scope.parentIndex = (size_t)-1;
|
||||
}
|
||||
scope.fileName = m_Program->GetDebugScopeFilePath(scope.md->dwarf);
|
||||
scope.line = (uint32_t)m_Program->GetDebugScopeLine(scope.md->dwarf);
|
||||
|
||||
m_DebugInfo.scopedDebugDatas.push_back(scope);
|
||||
}
|
||||
return scopeIndex;
|
||||
}
|
||||
|
||||
void Debugger::AddDebugType(const DXIL::Metadata *typeMD)
|
||||
{
|
||||
TypeData typeData;
|
||||
|
||||
const DXIL::DIBase *base = typeMD->dwarf;
|
||||
/*
|
||||
rdcstr name;
|
||||
VarType type = VarType::Unknown;
|
||||
uint32_t vecSize = 0;
|
||||
uint32_t matSize = 0;
|
||||
bool colMajorMat = false;
|
||||
|
||||
const DXIL::Metadata *baseType = NULL;
|
||||
rdcarray<uint32_t> arrayDimensions;
|
||||
rdcarray<rdcpair<rdcstr, const DXIL::Metadata *>> structMembers;
|
||||
rdcarray<uint32_t> memberOffsets;
|
||||
*/
|
||||
|
||||
switch(base->type)
|
||||
{
|
||||
case DXIL::DIBase::Type::BasicType:
|
||||
{
|
||||
const DIBasicType *basicType = base->As<DIBasicType>();
|
||||
typeData.name = *basicType->name;
|
||||
typeData.baseType = typeMD;
|
||||
typeData.vecSize = 1;
|
||||
uint32_t sizeInBits = (uint32_t)basicType->sizeInBits;
|
||||
switch(basicType->tag)
|
||||
{
|
||||
case DW_TAG_array_type:
|
||||
{
|
||||
// typeData.type = VAR TYPE OF THE ARRAY ELEMENTS
|
||||
// typeData.baseType = MD TYPE OF THE ARRAY ELEMENTS
|
||||
break;
|
||||
}
|
||||
case DW_TAG_base_type:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default: RDCERR("Unhandled DIBasicType tag %s", ToStr(basicType->tag).c_str()); break;
|
||||
}
|
||||
switch(basicType->encoding)
|
||||
{
|
||||
case DW_ATE_boolean:
|
||||
{
|
||||
RDCASSERTEQUAL(sizeInBits, 8);
|
||||
typeData.type = VarType ::Bool;
|
||||
break;
|
||||
}
|
||||
case DW_ATE_float:
|
||||
{
|
||||
if(sizeInBits == 16)
|
||||
typeData.type = VarType::Half;
|
||||
else if(sizeInBits == 32)
|
||||
typeData.type = VarType::Float;
|
||||
else if(sizeInBits == 64)
|
||||
typeData.type = VarType::Double;
|
||||
else
|
||||
RDCERR("Unhandled DIBasicType DW_ATE_float size %u", sizeInBits);
|
||||
break;
|
||||
}
|
||||
case DW_ATE_signed:
|
||||
{
|
||||
if(sizeInBits == 8)
|
||||
typeData.type = VarType::SByte;
|
||||
else if(sizeInBits == 16)
|
||||
typeData.type = VarType::SShort;
|
||||
else if(sizeInBits == 32)
|
||||
typeData.type = VarType::SInt;
|
||||
else if(sizeInBits == 32)
|
||||
typeData.type = VarType::SLong;
|
||||
else
|
||||
RDCERR("Unhandled DIBasicType DW_ATE_signed size %u", sizeInBits);
|
||||
break;
|
||||
}
|
||||
case DW_ATE_unsigned:
|
||||
{
|
||||
if(sizeInBits == 8)
|
||||
typeData.type = VarType::UByte;
|
||||
else if(sizeInBits == 16)
|
||||
typeData.type = VarType::UShort;
|
||||
else if(sizeInBits == 32)
|
||||
typeData.type = VarType::UInt;
|
||||
else if(sizeInBits == 32)
|
||||
typeData.type = VarType::ULong;
|
||||
else
|
||||
RDCERR("Unhandled DIBasicType DW_ATE_unsigned size %u", sizeInBits);
|
||||
break;
|
||||
}
|
||||
case DW_ATE_signed_char:
|
||||
{
|
||||
RDCASSERTEQUAL(sizeInBits, 8);
|
||||
typeData.type = VarType::SByte;
|
||||
break;
|
||||
}
|
||||
case DW_ATE_unsigned_char:
|
||||
{
|
||||
RDCASSERTEQUAL(sizeInBits, 8);
|
||||
typeData.type = VarType::UByte;
|
||||
break;
|
||||
}
|
||||
case DW_ATE_complex_float:
|
||||
case DW_ATE_address:
|
||||
case DW_ATE_imaginary_float:
|
||||
case DW_ATE_packed_decimal:
|
||||
case DW_ATE_numeric_string:
|
||||
case DW_ATE_edited:
|
||||
case DW_ATE_signed_fixed:
|
||||
case DW_ATE_unsigned_fixed:
|
||||
case DW_ATE_decimal_float:
|
||||
case DW_ATE_UTF:
|
||||
RDCERR("Unhandled DIBasicType encoding %s", ToStr(basicType->encoding).c_str());
|
||||
break;
|
||||
};
|
||||
break;
|
||||
}
|
||||
case DXIL::DIBase::Type::CompositeType:
|
||||
{
|
||||
const DICompositeType *compositeType = base->As<DICompositeType>();
|
||||
typeData.name = *compositeType->name;
|
||||
typeData.baseType = typeMD;
|
||||
switch(compositeType->tag)
|
||||
{
|
||||
case DW_TAG_class_type:
|
||||
case DW_TAG_structure_type:
|
||||
{
|
||||
typeData.type = VarType::Struct;
|
||||
// rdcarray<rdcpair<rdcstr, const DXIL::Metadata *>> structMembers;
|
||||
// rdcarray<uint32_t> memberOffsets;
|
||||
// AddDebugType(member);
|
||||
// RDCASSERT(m_DebugInfo.types.count(compositeType->base) == 1);
|
||||
// typeData = m_DebugInfo.types[compositeType->base];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
RDCERR("Unhandled DICompositeType tag %s", ToStr(compositeType->tag).c_str());
|
||||
break;
|
||||
};
|
||||
break;
|
||||
}
|
||||
case DXIL::DIBase::Type::DerivedType:
|
||||
{
|
||||
const DIDerivedType *derviedType = base->As<DIDerivedType>();
|
||||
switch(derviedType->tag)
|
||||
{
|
||||
case DW_TAG_typedef:
|
||||
AddDebugType(derviedType->base);
|
||||
RDCASSERT(m_DebugInfo.types.count(derviedType->base) == 1);
|
||||
typeData = m_DebugInfo.types[derviedType->base];
|
||||
break;
|
||||
default:
|
||||
RDCERR("Unhandled DIDerivedType DIDerviedType Tag type %s",
|
||||
ToStr(derviedType->tag).c_str());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: RDCERR("Unhandled DXIL type %s", ToStr(base->type).c_str()); break;
|
||||
}
|
||||
|
||||
m_DebugInfo.types[typeMD] = typeData;
|
||||
}
|
||||
|
||||
void Debugger::ParseDbgOpDeclare(const DXIL::Instruction &inst, uint32_t instructionIndex)
|
||||
{
|
||||
// arg 0 contains the SSA Id of the alloca result which represents the local variable (a pointer)
|
||||
const Metadata *allocaInstMD = cast<Metadata>(inst.args[0]);
|
||||
RDCASSERT(allocaInstMD);
|
||||
const Instruction *allocaInst = cast<Instruction>(allocaInstMD->value);
|
||||
RDCASSERT(allocaInst);
|
||||
RDCASSERTEQUAL(allocaInst->op, Operation::Alloca);
|
||||
rdcstr resultId;
|
||||
Program::MakeResultId(*allocaInst, resultId);
|
||||
|
||||
// arg 1 is DILocalVariable metadata
|
||||
// Tag
|
||||
// name
|
||||
// arguments
|
||||
// scope
|
||||
// file, line
|
||||
// type
|
||||
// flags
|
||||
const Metadata *localVariableMD = cast<Metadata>(inst.args[1]);
|
||||
RDCASSERT(localVariableMD);
|
||||
RDCASSERTEQUAL(localVariableMD->dwarf->type, DIBase::Type::LocalVariable);
|
||||
const DILocalVariable *localVariable = localVariableMD->dwarf->As<DILocalVariable>();
|
||||
|
||||
// arg 2 is DIExpression metadata
|
||||
const Metadata *expressionMD = cast<Metadata>(inst.args[2]);
|
||||
uint32_t countBytes = 0;
|
||||
if(expressionMD)
|
||||
{
|
||||
RDCASSERTEQUAL(expressionMD->dwarf->type, DIBase::Type::Expression);
|
||||
const DIExpression *expression = expressionMD->dwarf->As<DIExpression>();
|
||||
RDCLOG("Expression Op %s", ToStr(expression->op).c_str());
|
||||
}
|
||||
|
||||
size_t scopeIndex = AddScopedDebugData(localVariable->scope, instructionIndex);
|
||||
ScopedDebugData &scope = m_DebugInfo.scopedDebugDatas[scopeIndex];
|
||||
scope.minInstruction = RDCMIN(scope.minInstruction, instructionIndex);
|
||||
scope.maxInstruction = RDCMAX(scope.maxInstruction, instructionIndex);
|
||||
|
||||
rdcstr sourceVarName = m_Program->GetDebugVarName(localVariable);
|
||||
LocalMapping localMapping;
|
||||
localMapping.variable = localVariable;
|
||||
localMapping.sourceVarName = sourceVarName;
|
||||
localMapping.ssaIdName = resultId;
|
||||
localMapping.byteOffset = 0;
|
||||
localMapping.countBytes = countBytes;
|
||||
localMapping.instIndex = instructionIndex;
|
||||
localMapping.isDeclare = true;
|
||||
|
||||
scope.localMappings.push_back(localMapping);
|
||||
|
||||
const DXIL::Metadata *typeMD = localVariable->type;
|
||||
if(m_DebugInfo.types.count(typeMD) == 0)
|
||||
AddDebugType(typeMD);
|
||||
|
||||
if(m_DebugInfo.locals.count(sourceVarName) == 0)
|
||||
m_DebugInfo.locals[sourceVarName] = localMapping;
|
||||
}
|
||||
|
||||
void Debugger::ParseDbgOpValue(const DXIL::Instruction &inst, uint32_t instructionIndex)
|
||||
{
|
||||
// arg 0 is metadata containing the new value
|
||||
const Metadata *valueMD = cast<Metadata>(inst.args[0]);
|
||||
rdcstr resultId = m_Program->GetArgId(valueMD->value);
|
||||
// arg 1 is i64 byte offset in the source variable where the new value is written
|
||||
int64_t byteOffset;
|
||||
RDCASSERT(getival<int64_t>(inst.args[1], byteOffset));
|
||||
|
||||
// arg 2 is DILocalVariable metadata
|
||||
// Tag
|
||||
// name
|
||||
// arguments
|
||||
// scope
|
||||
// file, line
|
||||
// type
|
||||
// flags
|
||||
const Metadata *localVariableMD = cast<Metadata>(inst.args[2]);
|
||||
RDCASSERT(localVariableMD);
|
||||
RDCASSERTEQUAL(localVariableMD->dwarf->type, DIBase::Type::LocalVariable);
|
||||
const DILocalVariable *localVariable = localVariableMD->dwarf->As<DILocalVariable>();
|
||||
|
||||
// arg 3 is DIExpression metadata
|
||||
uint32_t countBytes = 0;
|
||||
const Metadata *expressionMD = cast<Metadata>(inst.args[2]);
|
||||
if(expressionMD)
|
||||
{
|
||||
if(expressionMD->dwarf->type == DIBase::Type::Expression)
|
||||
{
|
||||
// TODO: get the count bytes from the expression
|
||||
const DIExpression *expression = expressionMD->dwarf->As<DIExpression>();
|
||||
RDCLOG("Expression Op %s", ToStr(expression->op).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
size_t scopeIndex = AddScopedDebugData(localVariable->scope, instructionIndex);
|
||||
ScopedDebugData &scope = m_DebugInfo.scopedDebugDatas[scopeIndex];
|
||||
scope.minInstruction = RDCMIN(scope.minInstruction, instructionIndex);
|
||||
scope.maxInstruction = RDCMAX(scope.maxInstruction, instructionIndex);
|
||||
|
||||
byteOffset = 0;
|
||||
countBytes = 0;
|
||||
|
||||
rdcstr sourceVarName = m_Program->GetDebugVarName(localVariable);
|
||||
LocalMapping localMapping;
|
||||
localMapping.variable = localVariable;
|
||||
localMapping.sourceVarName = sourceVarName;
|
||||
localMapping.ssaIdName = resultId;
|
||||
localMapping.byteOffset = byteOffset;
|
||||
localMapping.countBytes = countBytes;
|
||||
localMapping.instIndex = instructionIndex;
|
||||
localMapping.isDeclare = false;
|
||||
|
||||
scope.localMappings.push_back(localMapping);
|
||||
|
||||
const DXIL::Metadata *typeMD = localVariable->type;
|
||||
if(m_DebugInfo.types.count(typeMD) == 0)
|
||||
AddDebugType(typeMD);
|
||||
|
||||
if(m_DebugInfo.locals.count(sourceVarName) == 0)
|
||||
m_DebugInfo.locals[sourceVarName] = localMapping;
|
||||
}
|
||||
|
||||
ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContainer *dxbcContainer,
|
||||
const ShaderReflection &reflection, uint32_t activeLaneIndex)
|
||||
@@ -3446,8 +3810,85 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
||||
|
||||
rdcarray<ShaderDebugState> Debugger::ContinueDebug(DebugAPIWrapper *apiWrapper)
|
||||
{
|
||||
ThreadState &active = GetActiveLane();
|
||||
|
||||
rdcarray<ShaderDebugState> ret;
|
||||
|
||||
// initialise the first ShaderDebugState if we haven't stepped yet
|
||||
if(m_Steps == 0)
|
||||
{
|
||||
ShaderDebugState initial;
|
||||
|
||||
for(size_t lane = 0; lane < m_Workgroups.size(); lane++)
|
||||
{
|
||||
ThreadState &thread = m_Workgroups[lane];
|
||||
|
||||
if(lane == m_ActiveLaneIndex)
|
||||
{
|
||||
thread.EnterEntryPoint(m_EntryPointFunction, &initial);
|
||||
// FillCallstack(thread, initial);
|
||||
initial.nextInstruction = thread.m_GlobalInstructionIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
thread.EnterEntryPoint(m_EntryPointFunction, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// globals won't be filled out by entering the entry point, ensure their change is registered.
|
||||
for(const ShaderVariable &v : m_GlobalState.globals)
|
||||
initial.changes.push_back({ShaderVariable(), v});
|
||||
|
||||
ret.push_back(std::move(initial));
|
||||
|
||||
m_Steps++;
|
||||
}
|
||||
|
||||
// if we've finished, return an empty set to signify that
|
||||
if(active.Finished())
|
||||
return ret;
|
||||
|
||||
rdcarray<bool> activeMask;
|
||||
|
||||
for(int stepEnd = m_Steps + 100; m_Steps < stepEnd;)
|
||||
{
|
||||
if(active.Finished())
|
||||
break;
|
||||
|
||||
// calculate the current mask of which threads are active
|
||||
CalcActiveMask(activeMask);
|
||||
|
||||
// step all active members of the workgroup
|
||||
for(size_t lane = 0; lane < m_Workgroups.size(); lane++)
|
||||
{
|
||||
if(activeMask[lane])
|
||||
{
|
||||
ThreadState &thread = m_Workgroups[lane];
|
||||
if(thread.Finished())
|
||||
{
|
||||
if(lane == m_ActiveLaneIndex)
|
||||
ret.emplace_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(lane == m_ActiveLaneIndex)
|
||||
{
|
||||
ShaderDebugState state;
|
||||
|
||||
state.stepIndex = m_Steps;
|
||||
thread.StepNext(&state, apiWrapper, m_Workgroups);
|
||||
|
||||
ret.push_back(std::move(state));
|
||||
|
||||
m_Steps++;
|
||||
}
|
||||
else
|
||||
{
|
||||
thread.StepNext(NULL, apiWrapper, m_Workgroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
|
||||
#include <set>
|
||||
#include "common/common.h"
|
||||
#include "driver/shaders/dxbc/dx_debug.h"
|
||||
#include "driver/shaders/dxbc/dxbc_bytecode.h"
|
||||
#include "driver/shaders/dxbc/dxbc_container.h"
|
||||
#include "dxil_bytecode.h"
|
||||
#include "dxil_debuginfo.h"
|
||||
|
||||
namespace DXILDebug
|
||||
{
|
||||
@@ -304,6 +306,95 @@ struct GlobalState
|
||||
rdcarray<ShaderVariable> globals;
|
||||
};
|
||||
|
||||
struct LocalMapping
|
||||
{
|
||||
bool operator<(const LocalMapping &o) const
|
||||
{
|
||||
if(sourceVarName != o.sourceVarName)
|
||||
return sourceVarName < o.sourceVarName;
|
||||
if(byteOffset != o.byteOffset)
|
||||
return byteOffset < o.byteOffset;
|
||||
if(countBytes != o.countBytes)
|
||||
return countBytes < o.countBytes;
|
||||
if(instIndex != o.instIndex)
|
||||
return instIndex < o.instIndex;
|
||||
if(isDeclare != o.isDeclare)
|
||||
return isDeclare;
|
||||
return ssaIdName < o.ssaIdName;
|
||||
}
|
||||
|
||||
bool isSourceSupersetOf(const LocalMapping &o) const
|
||||
{
|
||||
// this mapping is a superset of the other if:
|
||||
|
||||
// it's the same source var
|
||||
if(sourceVarName != o.sourceVarName)
|
||||
return false;
|
||||
|
||||
// it encompaases the other mapping
|
||||
if(byteOffset > o.byteOffset)
|
||||
return false;
|
||||
|
||||
// countBytes = 0 means entire variable
|
||||
if(countBytes == 0)
|
||||
return true;
|
||||
|
||||
if(o.countBytes == 0)
|
||||
return false;
|
||||
|
||||
const int64_t thisEnd = byteOffset + countBytes;
|
||||
const int64_t otherEnd = o.byteOffset + o.countBytes;
|
||||
if(thisEnd < otherEnd)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const DXIL::DILocalVariable *variable;
|
||||
rdcstr sourceVarName;
|
||||
rdcstr ssaIdName;
|
||||
int64_t byteOffset;
|
||||
uint32_t countBytes;
|
||||
uint32_t instIndex;
|
||||
bool isDeclare;
|
||||
};
|
||||
|
||||
struct ScopedDebugData
|
||||
{
|
||||
rdcarray<LocalMapping> localMappings;
|
||||
const DXIL::Metadata *md;
|
||||
size_t parentIndex;
|
||||
rdcstr fileName;
|
||||
uint32_t line;
|
||||
uint32_t minInstruction;
|
||||
uint32_t maxInstruction;
|
||||
|
||||
bool operator<(const ScopedDebugData &o) const
|
||||
{
|
||||
if(minInstruction != o.minInstruction)
|
||||
return minInstruction < o.minInstruction;
|
||||
if(maxInstruction != o.maxInstruction)
|
||||
return maxInstruction < o.maxInstruction;
|
||||
return line < o.line;
|
||||
}
|
||||
};
|
||||
|
||||
struct TypeData
|
||||
{
|
||||
const DXIL::DIBase *base;
|
||||
rdcstr name;
|
||||
|
||||
VarType type = VarType::Unknown;
|
||||
uint32_t vecSize = 0;
|
||||
uint32_t matSize = 0;
|
||||
bool colMajorMat = false;
|
||||
|
||||
const DXIL::Metadata *baseType = NULL;
|
||||
rdcarray<uint32_t> arrayDimensions;
|
||||
rdcarray<rdcpair<rdcstr, const DXIL::Metadata *>> structMembers;
|
||||
rdcarray<uint32_t> memberOffsets;
|
||||
};
|
||||
|
||||
class Debugger : public DXBCContainerDebugger
|
||||
{
|
||||
public:
|
||||
@@ -324,6 +415,14 @@ public:
|
||||
const FunctionInfo *GetFunctionInfo(const DXIL::Function *function) const;
|
||||
|
||||
private:
|
||||
void CalcActiveMask(rdcarray<bool> &activeMask);
|
||||
void ParseDbgOpDeclare(const DXIL::Instruction &inst, uint32_t instructionIndex);
|
||||
void ParseDbgOpValue(const DXIL::Instruction &inst, uint32_t instructionIndex);
|
||||
size_t AddScopedDebugData(const DXIL::Metadata *scopeMD, uint32_t instructionIndex);
|
||||
size_t FindScopedDebugDataIndex(const DXIL::Metadata *md) const;
|
||||
size_t Debugger::FindScopedDebugDataIndex(const uint32_t instructionIndex) const;
|
||||
void AddDebugType(const DXIL::Metadata *typeMD);
|
||||
|
||||
rdcarray<ThreadState> m_Workgroups;
|
||||
std::map<const DXIL::Function *, FunctionInfo> m_FunctionInfos;
|
||||
|
||||
@@ -332,11 +431,22 @@ private:
|
||||
|
||||
GlobalState m_GlobalState;
|
||||
|
||||
struct DebugInfo
|
||||
{
|
||||
rdcarray<ScopedDebugData> scopedDebugDatas;
|
||||
// TODO : Make sure the key is unique across scopes (need to mangle name or use an ID)
|
||||
std::map<rdcstr, LocalMapping> locals;
|
||||
std::map<const DXIL::Metadata *, TypeData> types;
|
||||
} m_DebugInfo;
|
||||
|
||||
const DXBC::DXBCContainer *m_DXBC = NULL;
|
||||
const DXIL::Program *m_Program = NULL;
|
||||
const DXIL::Function *m_EntryPointFunction = NULL;
|
||||
ShaderStage m_Stage;
|
||||
|
||||
uint32_t m_EventId = 0;
|
||||
uint32_t m_ActiveLaneIndex = 0;
|
||||
int m_Steps = 0;
|
||||
};
|
||||
|
||||
}; // namespace DXILDebug
|
||||
|
||||
Reference in New Issue
Block a user