mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-08 16:50:44 +00:00
Support nested GetTempMemory calls on replay
* On capture we have a fast temporary thread-local memory allocator that only supports one allocation at a time, which is sufficient for unwrapping the parameters to a single function call. * On replay though we might want to unwrap a function's parameters, and then inside do things like e.g. call a drawcall callback which makes its own calls that need to be unwrapped. * To support these nested calls we instead allocate 4MB per thread on replay and use it like a ring buffer.
This commit is contained in:
@@ -608,8 +608,40 @@ void WrappedVulkan::SetDebugMessageSink(WrappedVulkan::ScopedDebugMessageSink *s
|
||||
Threading::SetTLSValue(debugMessageSinkTLSSlot, (void *)sink);
|
||||
}
|
||||
|
||||
byte *WrappedVulkan::GetRingTempMemory(size_t s)
|
||||
{
|
||||
TempMem *mem = (TempMem *)Threading::GetTLSValue(tempMemoryTLSSlot);
|
||||
|
||||
if(!mem || mem->size < s)
|
||||
{
|
||||
if(mem && mem->size < s)
|
||||
RDCWARN("More than %zu bytes needed to unwrap!", mem->size);
|
||||
|
||||
mem = new TempMem();
|
||||
mem->size = AlignUp(s, size_t(4 * 1024 * 1024));
|
||||
mem->memory = mem->cur = new byte[mem->size];
|
||||
|
||||
SCOPED_LOCK(m_ThreadTempMemLock);
|
||||
m_ThreadTempMem.push_back(mem);
|
||||
|
||||
Threading::SetTLSValue(tempMemoryTLSSlot, (void *)mem);
|
||||
}
|
||||
|
||||
// if we'd wrap, go back to the start
|
||||
if(mem->cur + s >= mem->memory + mem->size)
|
||||
mem->cur = mem->memory;
|
||||
|
||||
// save the return value and update the cur pointer
|
||||
byte *ret = mem->cur;
|
||||
mem->cur = AlignUpPtr(mem->cur + s, 16);
|
||||
return ret;
|
||||
}
|
||||
|
||||
byte *WrappedVulkan::GetTempMemory(size_t s)
|
||||
{
|
||||
if(IsReplayMode(m_State))
|
||||
return GetRingTempMemory(s);
|
||||
|
||||
TempMem *mem = (TempMem *)Threading::GetTLSValue(tempMemoryTLSSlot);
|
||||
if(mem && mem->size >= s)
|
||||
return mem->memory;
|
||||
|
||||
@@ -309,8 +309,9 @@ private:
|
||||
uint64_t tempMemoryTLSSlot;
|
||||
struct TempMem
|
||||
{
|
||||
TempMem() : memory(NULL), size(0) {}
|
||||
TempMem() : memory(NULL), cur(NULL), size(0) {}
|
||||
byte *memory;
|
||||
byte *cur;
|
||||
size_t size;
|
||||
};
|
||||
Threading::CriticalSection m_ThreadTempMemLock;
|
||||
@@ -821,6 +822,12 @@ private:
|
||||
|
||||
bytebuf m_MaskedMapData;
|
||||
|
||||
// on replay we may need to allocate several bits of temporary memory, so the single-region
|
||||
// doesn't work as well. We're not quite as performance-sensitive so we allocate 4MB per thread
|
||||
// and use it in a ring-buffer fashion. This allows multiple allocations to live at once as long
|
||||
// as we don't need it all in one stack.
|
||||
byte *GetRingTempMemory(size_t s);
|
||||
|
||||
// returns thread-local temporary memory
|
||||
byte *GetTempMemory(size_t s);
|
||||
template <class T>
|
||||
|
||||
Reference in New Issue
Block a user