mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Don't save every queue creation in D3D12 device record
* Otherwise we try to create every queue that has ever existed on replay. * Check for resource leaks in Resource_Lifetimes tests.
This commit is contained in:
@@ -105,7 +105,7 @@ class WrappedID3D12CommandQueue : public ID3D12CommandQueue,
|
||||
HWND m_pPresentHWND = NULL;
|
||||
|
||||
ResourceId m_ResourceID;
|
||||
D3D12ResourceRecord *m_QueueRecord;
|
||||
D3D12ResourceRecord *m_QueueRecord, *m_CreationRecord;
|
||||
|
||||
CaptureState &m_State;
|
||||
|
||||
@@ -148,6 +148,7 @@ public:
|
||||
ResourceId GetResourceID() { return m_ResourceID; }
|
||||
ID3D12CommandQueue *GetReal() { return m_pReal; }
|
||||
D3D12ResourceRecord *GetResourceRecord() { return m_QueueRecord; }
|
||||
D3D12ResourceRecord *GetCreationRecord() { return m_CreationRecord; }
|
||||
WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; }
|
||||
const rdcarray<D3D12ResourceRecord *> &GetCmdLists() { return m_CmdListRecords; }
|
||||
D3D12DrawcallTreeNode &GetParentDrawcall() { return m_Cmd.m_ParentDrawcall; }
|
||||
|
||||
@@ -339,6 +339,7 @@ WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real,
|
||||
m_ResourceID = ResourceIDGen::GetNewUniqueID();
|
||||
|
||||
m_QueueRecord = NULL;
|
||||
m_CreationRecord = NULL;
|
||||
|
||||
m_Cmd.m_pDevice = m_pDevice;
|
||||
|
||||
@@ -349,6 +350,15 @@ WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real,
|
||||
m_QueueRecord->DataInSerialiser = false;
|
||||
m_QueueRecord->InternalResource = true;
|
||||
m_QueueRecord->Length = 0;
|
||||
|
||||
// a bit of a hack, we make a parallel resource record with the same lifetime as the command
|
||||
// queue. It will hold onto our create chunk and not get thrown away as we clear and re-fill
|
||||
// submissions into the queue record itself. We'll pull it into the capture by marking the
|
||||
// queues as referenced.
|
||||
m_CreationRecord =
|
||||
m_pDevice->GetResourceManager()->AddResourceRecord(ResourceIDGen::GetNewUniqueID());
|
||||
m_CreationRecord->type = Resource_CommandQueue;
|
||||
m_CreationRecord->InternalResource = true;
|
||||
}
|
||||
|
||||
m_pDevice->GetResourceManager()->AddCurrentResource(GetResourceID(), this);
|
||||
@@ -360,6 +370,9 @@ WrappedID3D12CommandQueue::~WrappedID3D12CommandQueue()
|
||||
{
|
||||
SAFE_DELETE(m_FrameReader);
|
||||
|
||||
if(m_CreationRecord)
|
||||
m_CreationRecord->Delete(m_pDevice->GetResourceManager());
|
||||
|
||||
if(m_QueueRecord)
|
||||
m_QueueRecord->Delete(m_pDevice->GetResourceManager());
|
||||
m_pDevice->GetResourceManager()->ReleaseCurrentResource(GetResourceID());
|
||||
|
||||
@@ -1812,11 +1812,16 @@ void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd)
|
||||
m_HeaderChunk = scope.Get();
|
||||
}
|
||||
|
||||
// keep all queues alive during the capture, by adding a refcount
|
||||
for(auto it = m_Queues.begin(); it != m_Queues.end(); ++it)
|
||||
(*it)->AddRef();
|
||||
|
||||
m_State = CaptureState::ActiveCapturing;
|
||||
|
||||
// keep all queues alive during the capture, by adding a refcount. Also reference the creation
|
||||
// record so that it's pulled in as initialisation chunks.
|
||||
for(auto it = m_Queues.begin(); it != m_Queues.end(); ++it)
|
||||
{
|
||||
(*it)->AddRef();
|
||||
GetResourceManager()->MarkResourceFrameReferenced((*it)->GetCreationRecord()->GetResourceID(),
|
||||
eFrameRef_Read);
|
||||
}
|
||||
}
|
||||
|
||||
GetResourceManager()->MarkResourceFrameReferenced(m_ResourceID, eFrameRef_Read);
|
||||
|
||||
@@ -114,7 +114,7 @@ HRESULT WrappedID3D12Device::CreateCommandQueue(const D3D12_COMMAND_QUEUE_DESC *
|
||||
SCOPED_SERIALISE_CHUNK(D3D12Chunk::Device_CreateCommandQueue);
|
||||
Serialise_CreateCommandQueue(ser, pDesc, riid, (void **)&wrapped);
|
||||
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
wrapped->GetCreationRecord()->AddChunk(scope.Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -141,7 +141,11 @@ HRESULT WrappedID3D12Device::CreateCommandQueue(const D3D12_COMMAND_QUEUE_DESC *
|
||||
// while capturing don't allow any queues to be freed, by adding another refcount, since we
|
||||
// gather any commands submitted to them at the end of the capture.
|
||||
if(capframe)
|
||||
{
|
||||
GetResourceManager()->MarkResourceFrameReferenced(
|
||||
wrapped->GetCreationRecord()->GetResourceID(), eFrameRef_Read);
|
||||
wrapped->AddRef();
|
||||
}
|
||||
|
||||
*ppCommandQueue = (ID3D12CommandQueue *)wrapped;
|
||||
}
|
||||
|
||||
@@ -397,11 +397,17 @@ float4 main(v2f IN) : SV_Target0
|
||||
descheap = NULL;
|
||||
};
|
||||
|
||||
ID3D12ResourcePtr rtvtex = MakeTexture(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, screenWidth, screenHeight)
|
||||
.RTV()
|
||||
.InitialState(D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
|
||||
ID3D12ResourcePtr cb = SetupBuf();
|
||||
ID3D12ResourcePtr img = SetupImg();
|
||||
ID3D12DescriptorHeapPtr descheap = SetupDescHeap(cb, img);
|
||||
while(Running())
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE offrtv = MakeRTV(rtvtex).CreateCPU(1);
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtv;
|
||||
|
||||
// acquire and clear the backbuffer
|
||||
@@ -457,6 +463,45 @@ float4 main(v2f IN) : SV_Target0
|
||||
TrashDescHeap(descheap);
|
||||
}
|
||||
|
||||
// use a temporary queue
|
||||
{
|
||||
GPUSync();
|
||||
|
||||
ID3D12CommandQueuePtr tempQueue;
|
||||
|
||||
{
|
||||
D3D12_COMMAND_QUEUE_DESC desc = {};
|
||||
desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
dev->CreateCommandQueue(&desc, __uuidof(ID3D12CommandQueue), (void **)&tempQueue);
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer();
|
||||
|
||||
Reset(cmd);
|
||||
|
||||
ClearRenderTargetView(cmd, offrtv, {0.6f, 0.5f, 0.4f, 1.0f});
|
||||
|
||||
OMSetRenderTargets(cmd, {offrtv}, {});
|
||||
|
||||
cmd->Close();
|
||||
|
||||
ID3D12CommandList *submit = cmd.GetInterfacePtr();
|
||||
|
||||
tempQueue->ExecuteCommandLists(1, &submit);
|
||||
|
||||
// manually insert this into freeCommandBuffers since our normal lifetime management doesn't
|
||||
// handle submissino on other queues.
|
||||
freeCommandBuffers.push_back(cmd);
|
||||
|
||||
m_GPUSyncCounter++;
|
||||
|
||||
CHECK_HR(tempQueue->Signal(m_GPUSyncFence, m_GPUSyncCounter));
|
||||
CHECK_HR(m_GPUSyncFence->SetEventOnCompletion(m_GPUSyncCounter, m_GPUSyncHandle));
|
||||
WaitForSingleObject(m_GPUSyncHandle, 10000);
|
||||
|
||||
tempQueue = NULL;
|
||||
}
|
||||
|
||||
// create resources mid-frame and use then trash them
|
||||
{
|
||||
cb = SetupBuf();
|
||||
|
||||
@@ -4,6 +4,13 @@ import rdtest
|
||||
|
||||
class D3D11_Resource_Lifetimes(rdtest.TestCase):
|
||||
demos_test_name = 'D3D11_Resource_Lifetimes'
|
||||
demos_frame_cap = 200
|
||||
|
||||
def check_capture(self):
|
||||
self.check_final_backbuffer()
|
||||
|
||||
# Check for resource leaks
|
||||
if len(self.controller.GetResources()) > 75:
|
||||
raise rdtest.TestFailureException(
|
||||
"Too many resources found: {}".format(len(self.controller.GetResources())))
|
||||
|
||||
|
||||
@@ -4,6 +4,12 @@ import rdtest
|
||||
|
||||
class D3D12_Resource_Lifetimes(rdtest.TestCase):
|
||||
demos_test_name = 'D3D12_Resource_Lifetimes'
|
||||
demos_frame_cap = 200
|
||||
|
||||
def check_capture(self):
|
||||
self.check_final_backbuffer()
|
||||
|
||||
# Check for resource leaks
|
||||
if len(self.controller.GetResources()) > 75:
|
||||
raise rdtest.TestFailureException(
|
||||
"Too many resources found: {}".format(len(self.controller.GetResources())))
|
||||
|
||||
@@ -4,6 +4,13 @@ import rdtest
|
||||
|
||||
class GL_Resource_Lifetimes(rdtest.TestCase):
|
||||
demos_test_name = 'GL_Resource_Lifetimes'
|
||||
demos_frame_cap = 200
|
||||
|
||||
def check_capture(self):
|
||||
self.check_final_backbuffer()
|
||||
|
||||
# Check for resource leaks
|
||||
if len(self.controller.GetResources()) > 75:
|
||||
raise rdtest.TestFailureException(
|
||||
"Too many resources found: {}".format(len(self.controller.GetResources())))
|
||||
|
||||
|
||||
@@ -4,6 +4,13 @@ import rdtest
|
||||
|
||||
class VK_Resource_Lifetimes(rdtest.TestCase):
|
||||
demos_test_name = 'VK_Resource_Lifetimes'
|
||||
demos_frame_cap = 200
|
||||
|
||||
def check_capture(self):
|
||||
self.check_final_backbuffer()
|
||||
|
||||
# Check for resource leaks
|
||||
if len(self.controller.GetResources()) > 75:
|
||||
raise rdtest.TestFailureException(
|
||||
"Too many resources found: {}".format(len(self.controller.GetResources())))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user