Skip to content

Commit

Permalink
DXIL Debugger memory handling improvements
Browse files Browse the repository at this point in the history
Moved memory tracking into struct MemoryTracking
Global variables go into global memory
All threads memory tracking is populated with global memory tracking
  • Loading branch information
Zorro666 committed Nov 21, 2024
1 parent 7136385 commit 497f7c3
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 55 deletions.
99 changes: 60 additions & 39 deletions renderdoc/driver/shaders/dxil/dxil_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,23 @@ void ApplyAllDerivatives(GlobalState &global, rdcarray<ThreadState> &quad, int d
}
}

void MemoryTracking::AllocateMemoryForType(const DXIL::Type *type, Id allocId, bool global,
ShaderVariable &var)
{
RDCASSERTEQUAL(type->type, Type::TypeKind::Pointer);
ConvertDXILTypeToShaderVariable(type->inner, var);

// Add the SSA to m_MemoryAllocs with its backing memory and size
size_t byteSize = ComputeDXILTypeByteSize(type->inner);
void *backingMem = malloc(byteSize);
memset(backingMem, 0, byteSize);
MemoryTracking::Alloc &alloc = m_Allocs[allocId];
alloc = {backingMem, byteSize, global};

// set the backing memory
m_AllocPointers[allocId] = {allocId, backingMem, byteSize};
}

ThreadState::ThreadState(uint32_t workgroupIndex, Debugger &debugger, const GlobalState &globalState)
: m_Debugger(debugger), m_GlobalState(globalState), m_Program(debugger.GetProgram())
{
Expand All @@ -1436,8 +1453,11 @@ ThreadState::ThreadState(uint32_t workgroupIndex, Debugger &debugger, const Glob

ThreadState::~ThreadState()
{
for(auto it : m_MemoryAllocs)
free(it.second.backingMemory);
for(auto it : m_Memory.m_Allocs)
{
if(!it.second.global)
free(it.second.backingMemory);
}
}

void ThreadState::InitialiseHelper(const ThreadState &activeState)
Expand Down Expand Up @@ -1524,6 +1544,9 @@ void ThreadState::EnterEntryPoint(const Function *function, ShaderDebugState *st
for(const GlobalVariable &gv : m_GlobalState.globals)
m_Variables[gv.id] = gv.var;

// Start with the global memory allocations
m_Memory = m_GlobalState.memory;

m_State = NULL;
}

Expand Down Expand Up @@ -2987,7 +3010,7 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
{
// Load(ptr)
Id ptrId = GetArgumentId(0);
RDCASSERT(m_MemoryAllocPointers.count(ptrId) == 1);
RDCASSERT(m_Memory.m_AllocPointers.count(ptrId) == 1);
ShaderVariable arg;
RDCASSERT(GetShaderVariable(inst.args[0], opCode, dxOpCode, arg));
result.value = arg.value;
Expand All @@ -3002,16 +3025,16 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
size_t allocSize = 0;
void *allocMemoryBackingPtr = NULL;
Id ptrId = GetArgumentId(0);
auto itPtr = m_MemoryAllocPointers.find(ptrId);
RDCASSERT(itPtr != m_MemoryAllocPointers.end());
auto itPtr = m_Memory.m_AllocPointers.find(ptrId);
RDCASSERT(itPtr != m_Memory.m_AllocPointers.end());

const MemoryAllocPointer &ptr = itPtr->second;
const MemoryTracking::AllocPointer &ptr = itPtr->second;
baseMemoryId = ptr.baseMemoryId;
baseMemoryBackingPtr = ptr.backingMemory;

auto itAlloc = m_MemoryAllocs.find(baseMemoryId);
RDCASSERT(itAlloc != m_MemoryAllocs.end());
const MemoryAlloc &alloc = itAlloc->second;
auto itAlloc = m_Memory.m_Allocs.find(baseMemoryId);
RDCASSERT(itAlloc != m_Memory.m_Allocs.end());
const MemoryTracking::Alloc &alloc = itAlloc->second;
allocSize = alloc.size;
allocMemoryBackingPtr = alloc.backingMemory;

Expand Down Expand Up @@ -3044,15 +3067,15 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
case Operation::Alloca:
{
result.name = DXBC::BasicDemangle(result.name);
AllocateMemoryForType(inst.type, resultId, result);
m_Memory.AllocateMemoryForType(inst.type, resultId, false, result);
break;
}
case Operation::GetElementPtr:
{
const DXIL::Type *resultType = inst.type->inner;
Id ptrId = GetArgumentId(0);

RDCASSERT(m_MemoryAllocs.count(ptrId) == 1);
RDCASSERT(m_Memory.m_Allocs.count(ptrId) == 1);
RDCASSERT(m_Variables.count(ptrId) == 1);

// arg[1..] : indices 1...N
Expand Down Expand Up @@ -3083,13 +3106,17 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
size_t size = countElems * GetElementByteSize(baseType);

// Copy from the backing memory to the result
MemoryAlloc &alloc = m_MemoryAllocs[ptrId];
const MemoryTracking::Alloc &alloc = m_Memory.m_Allocs[ptrId];
uint8_t *backingMemory = (uint8_t *)alloc.backingMemory;

// Ensure global variables use global memory
// Ensure non-global variables do not use global memory
RDCASSERT(!((cast<GlobalVar>(inst.args[0]) != NULL) ^ alloc.global));

result.type = baseType;
result.rows = (uint8_t)countElems;
backingMemory += offset;
m_MemoryAllocPointers[resultId] = {ptrId, backingMemory, size};
m_Memory.m_AllocPointers[resultId] = {ptrId, backingMemory, size};

RDCASSERT(offset + size <= alloc.size);
RDCASSERT(size < sizeof(result.value.f32v));
Expand Down Expand Up @@ -3930,16 +3957,16 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
Id baseMemoryId = DXILDebug::INVALID_ID;
Id ptrId = GetArgumentId(0);
{
auto itPtr = m_MemoryAllocPointers.find(ptrId);
RDCASSERT(itPtr != m_MemoryAllocPointers.end());
auto itPtr = m_Memory.m_AllocPointers.find(ptrId);
RDCASSERT(itPtr != m_Memory.m_AllocPointers.end());

const MemoryAllocPointer &ptr = itPtr->second;
const MemoryTracking::AllocPointer &ptr = itPtr->second;
baseMemoryId = ptr.baseMemoryId;
baseMemoryBackingPtr = ptr.backingMemory;

auto itAlloc = m_MemoryAllocs.find(baseMemoryId);
RDCASSERT(itAlloc != m_MemoryAllocs.end());
const MemoryAlloc &alloc = itAlloc->second;
auto itAlloc = m_Memory.m_Allocs.find(baseMemoryId);
RDCASSERT(itAlloc != m_Memory.m_Allocs.end());
const MemoryTracking::Alloc &alloc = itAlloc->second;
allocSize = alloc.size;
allocMemoryBackingPtr = alloc.backingMemory;
}
Expand Down Expand Up @@ -4406,22 +4433,6 @@ void ThreadState::MarkResourceAccess(const rdcstr &name, const ShaderBindIndex &
accessed.push_back(bindIndex);
}

void ThreadState::AllocateMemoryForType(const DXIL::Type *type, Id allocId, ShaderVariable &var)
{
RDCASSERTEQUAL(type->type, Type::TypeKind::Pointer);
ConvertDXILTypeToShaderVariable(type->inner, var);

// Add the SSA to m_MemoryAllocs with its backing memory and size
size_t byteSize = ComputeDXILTypeByteSize(type->inner);
void *backingMem = malloc(byteSize);
memset(backingMem, 0, byteSize);
MemoryAlloc &alloc = m_MemoryAllocs[allocId];
alloc = {backingMem, byteSize};

// set the backing memory
m_MemoryAllocPointers[allocId] = {allocId, backingMem, byteSize};
}

void ThreadState::UpdateBackingMemoryFromVariable(void *ptr, size_t &allocSize,
const ShaderVariable &var)
{
Expand Down Expand Up @@ -4860,6 +4871,15 @@ ShaderValue ThreadState::DDY(bool fine, Operation opCode, DXOp dxOpCode,
return ret;
}

GlobalState::~GlobalState()
{
for(auto it : memory.m_Allocs)
{
RDCASSERT(it.second.global);
free(it.second.backingMemory);
}
}

bool ThreadState::ThreadsAreDiverged(const rdcarray<ThreadState> &workgroups)
{
const uint32_t block0 = workgroups[0].m_Block;
Expand Down Expand Up @@ -6084,6 +6104,7 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
sourceVar.variables.push_back(ref);
}

MemoryTracking &globalMemory = m_GlobalState.memory;
for(const DXIL::GlobalVar *gv : m_Program->m_GlobalVars)
{
// Ignore DXIL global variables which start with "dx.nothing."
Expand All @@ -6095,17 +6116,17 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
DXIL::SanitiseName(n);
globalVar.var.name = n;
globalVar.id = gv->ssaId;
state.AllocateMemoryForType(gv->type, globalVar.id, globalVar.var);
globalMemory.AllocateMemoryForType(gv->type, globalVar.id, true, globalVar.var);
if(gv->flags & GlobalFlags::IsConst)
{
if(gv->initialiser)
{
const Constant *initialData = gv->initialiser;
RDCASSERT(ConvertDXILConstantToShaderVariable(initialData, globalVar.var));
// Write ShaderVariable data back to memory
auto itAlloc = state.m_MemoryAllocs.find(globalVar.id);
RDCASSERT(itAlloc != state.m_MemoryAllocs.end());
const ThreadState::MemoryAlloc &alloc = itAlloc->second;
auto itAlloc = globalMemory.m_Allocs.find(globalVar.id);
RDCASSERT(itAlloc != globalMemory.m_Allocs.end());
const MemoryTracking::Alloc &alloc = itAlloc->second;
void *allocMemoryBackingPtr = alloc.backingMemory;
size_t allocSize = alloc.size;
state.UpdateBackingMemoryFromVariable(allocMemoryBackingPtr, allocSize, globalVar.var);
Expand Down
42 changes: 26 additions & 16 deletions renderdoc/driver/shaders/dxil/dxil_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,28 @@ class DebugAPIWrapper
virtual bool IsResourceBound(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot) = 0;
};

struct MemoryTracking
{
void AllocateMemoryForType(const DXIL::Type *type, Id allocId, bool global, ShaderVariable &var);

struct Alloc
{
void *backingMemory;
size_t size;
bool global;
};

struct AllocPointer
{
Id baseMemoryId;
void *backingMemory;
size_t size;
};

std::map<Id, Alloc> m_Allocs;
std::map<Id, AllocPointer> m_AllocPointers;
};

struct ThreadState
{
ThreadState(uint32_t workgroupIndex, Debugger &debugger, const GlobalState &globalState);
Expand Down Expand Up @@ -177,7 +199,6 @@ struct ThreadState
bool GetPhiVariable(const Id &id, DXIL::Operation opCode, DXIL::DXOp dxOpCode,
ShaderVariable &var) const;
bool GetVariableHelper(DXIL::Operation op, DXIL::DXOp dxOpCode, ShaderVariable &var) const;
void AllocateMemoryForType(const DXIL::Type *type, Id allocId, ShaderVariable &var);
void UpdateBackingMemoryFromVariable(void *ptr, size_t &allocSize, const ShaderVariable &var);
void UpdateMemoryVariableFromBackingMemory(Id memoryId, const void *ptr);

Expand All @@ -199,19 +220,6 @@ struct ThreadState

bool GetShaderVariableHelper(const DXIL::Value *dxilValue, DXIL::Operation op, DXIL::DXOp dxOpCode,
ShaderVariable &var, bool flushDenormInput, bool isLive) const;
struct MemoryAlloc
{
void *backingMemory;
size_t size;
};

struct MemoryAllocPointer
{
Id baseMemoryId;
void *backingMemory;
size_t size;
};

struct AnnotationProperties
{
DXIL::ResourceKind resKind;
Expand Down Expand Up @@ -252,8 +260,7 @@ struct ThreadState

// Track memory allocations
// For stack allocations do not bother freeing when leaving functions
std::map<Id, MemoryAlloc> m_MemoryAllocs;
std::map<Id, MemoryAllocPointer> m_MemoryAllocPointers;
MemoryTracking m_Memory;

// The instruction index within the current function
uint32_t m_FunctionInstructionIdx = ~0U;
Expand All @@ -278,6 +285,7 @@ struct ThreadState
struct GlobalState
{
GlobalState() = default;
~GlobalState();
BuiltinInputs builtinInputs;

struct ViewFmt
Expand Down Expand Up @@ -345,6 +353,8 @@ struct GlobalState
rdcarray<ShaderVariable> samplers;
// Globals across workgroups including inputs (immutable) and outputs (mutable)
rdcarray<GlobalVariable> globals;
// Memory created for global variables
MemoryTracking memory;
};

struct LocalMapping
Expand Down

0 comments on commit 497f7c3

Please sign in to comment.