From 99b45aefb5af82c5845276bb9a07803473420230 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 18 Oct 2016 12:12:54 +0200 Subject: [PATCH] Minimal possible residency handling code * We unwrap objects and track residency state, and when preparing init states if necessary then we make those resources resident and sync the list execute so we can evict them again immediately afterwards. * On replay, all resources are created and left as resident, which could go over the budget available. If a frame uses close to or more than its total budget over the course of a frame this could fail. One fix to that would be to track referenced resources in command lists at replay time, and only make resident what we need for each list and execute them in isolation, then evict right after (so all frame resources are 'default evicted'). --- renderdoc/driver/d3d12/d3d12_device.cpp | 3 + renderdoc/driver/d3d12/d3d12_device_wrap.cpp | 74 ++++++++++++++++++-- renderdoc/driver/d3d12/d3d12_manager.cpp | 36 ++++++++-- renderdoc/driver/d3d12/d3d12_resources.cpp | 2 + renderdoc/driver/d3d12/d3d12_resources.h | 11 ++- 5 files changed, 117 insertions(+), 9 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index dabb7d0c3..9374fbec9 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -901,6 +901,9 @@ void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd) SCOPED_LOCK(m_CapTransitionLock); GetResourceManager()->PrepareInitialContents(); + ExecuteLists(); + FlushLists(); + RDCDEBUG("Attempting capture"); m_FrameCaptureRecord->DeleteChunks(); diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index f79390086..1accd0a8d 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -1594,14 +1594,80 @@ HRESULT WrappedID3D12Device::OpenSharedHandleByName(LPCWSTR Name, DWORD Access, HRESULT WrappedID3D12Device::MakeResident(UINT NumObjects, ID3D12Pageable *const *ppObjects) { - RDCUNIMPLEMENTED("MakeResident"); // need to unwrap objects - return m_pDevice->MakeResident(NumObjects, ppObjects); + ID3D12Pageable **unwrapped = GetTempArray(NumObjects); + + for(UINT i = 0; i < NumObjects; i++) + { + if(WrappedID3D12DescriptorHeap::IsAlloc(ppObjects[i])) + { + WrappedID3D12DescriptorHeap *heap = (WrappedID3D12DescriptorHeap *)ppObjects[i]; + heap->SetResident(true); + unwrapped[i] = heap->GetReal(); + } + else if(WrappedID3D12Resource::IsAlloc(ppObjects[i])) + { + WrappedID3D12Resource *res = (WrappedID3D12Resource *)ppObjects[i]; + res->SetResident(true); + unwrapped[i] = res->GetReal(); + } + else + { + unwrapped[i] = (ID3D12Pageable *)Unwrap((ID3D12DeviceChild *)ppObjects[i]); + } + } + + bool capframe = false; + + { + SCOPED_LOCK(m_CapTransitionLock); + capframe = (m_State == WRITING_CAPFRAME); + } + + if(capframe) + { + // serialise + } + + return m_pDevice->MakeResident(NumObjects, unwrapped); } HRESULT WrappedID3D12Device::Evict(UINT NumObjects, ID3D12Pageable *const *ppObjects) { - RDCUNIMPLEMENTED("Evict"); // need to unwrap objects - return m_pDevice->Evict(NumObjects, ppObjects); + ID3D12Pageable **unwrapped = GetTempArray(NumObjects); + + for(UINT i = 0; i < NumObjects; i++) + { + if(WrappedID3D12DescriptorHeap::IsAlloc(ppObjects[i])) + { + WrappedID3D12DescriptorHeap *heap = (WrappedID3D12DescriptorHeap *)ppObjects[i]; + heap->SetResident(false); + unwrapped[i] = heap->GetReal(); + } + else if(WrappedID3D12Resource::IsAlloc(ppObjects[i])) + { + WrappedID3D12Resource *res = (WrappedID3D12Resource *)ppObjects[i]; + res->SetResident(false); + unwrapped[i] = res->GetReal(); + } + else + { + unwrapped[i] = (ID3D12Pageable *)Unwrap((ID3D12DeviceChild *)ppObjects[i]); + } + } + + bool capframe = false; + + { + SCOPED_LOCK(m_CapTransitionLock); + capframe = (m_State == WRITING_CAPFRAME); + } + + if(capframe) + { + // serialise + } + + return m_pDevice->Evict(NumObjects, unwrapped); } ////////////////////////////////////////////////////////////////////// diff --git a/renderdoc/driver/d3d12/d3d12_manager.cpp b/renderdoc/driver/d3d12/d3d12_manager.cpp index c7e60062f..e886a3d16 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.cpp +++ b/renderdoc/driver/d3d12/d3d12_manager.cpp @@ -483,13 +483,19 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) } else if(type == Resource_Resource) { - ID3D12Resource *r = (ID3D12Resource *)res; + WrappedID3D12Resource *r = (WrappedID3D12Resource *)res; + ID3D12Pageable *pageable = r; + + bool nonresident = false; + if(!r->Resident()) + nonresident = true; D3D12_RESOURCE_DESC desc = r->GetDesc(); if(desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && desc.SampleDesc.Count > 1) { D3D12NOTIMP("Multisampled initial contents"); + SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(NULL, 2, NULL)); return true; } @@ -518,11 +524,14 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) &heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_DEST, NULL, __uuidof(ID3D12Resource), (void **)©Dst); + if(nonresident) + m_Device->MakeResident(1, &pageable); + if(SUCCEEDED(hr)) { ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetNewList()); - list->CopyResource(copyDst, Unwrap(r)); + list->CopyResource(copyDst, r->GetReal()); list->Close(); } @@ -531,6 +540,14 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) RDCERR("Couldn't create readback buffer: 0x%08x", hr); } + if(nonresident) + { + m_Device->ExecuteLists(); + m_Device->FlushLists(); + + m_Device->Evict(1, &pageable); + } + SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(copyDst, 0, NULL)); return true; } @@ -572,6 +589,9 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) &heapProps, D3D12_HEAP_FLAG_NONE, &bufDesc, D3D12_RESOURCE_STATE_COPY_DEST, NULL, __uuidof(ID3D12Resource), (void **)©Dst); + if(nonresident) + m_Device->MakeResident(1, &pageable); + if(SUCCEEDED(hr)) { ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetNewList()); @@ -590,7 +610,7 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) D3D12_RESOURCE_BARRIER barrier; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = Unwrap(r); + barrier.Transition.pResource = r->GetReal(); barrier.Transition.Subresource = (UINT)i; barrier.Transition.StateBefore = states[i]; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; @@ -607,7 +627,7 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) D3D12_TEXTURE_COPY_LOCATION dst, src; src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - src.pResource = Unwrap(r); + src.pResource = r->GetReal(); src.SubresourceIndex = i; dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; @@ -631,6 +651,14 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) RDCERR("Couldn't create readback buffer: 0x%08x", hr); } + if(nonresident) + { + m_Device->ExecuteLists(); + m_Device->FlushLists(); + + m_Device->Evict(1, &pageable); + } + SAFE_DELETE_ARRAY(layouts); SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(copyDst, 0, NULL)); diff --git a/renderdoc/driver/d3d12/d3d12_resources.cpp b/renderdoc/driver/d3d12/d3d12_resources.cpp index 3f2348d6a..dec9b8d0d 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.cpp +++ b/renderdoc/driver/d3d12/d3d12_resources.cpp @@ -264,6 +264,8 @@ WrappedID3D12DescriptorHeap::WrappedID3D12DescriptorHeap(ID3D12DescriptorHeap *r realCPUBase = real->GetCPUDescriptorHandleForHeapStart(); realGPUBase = real->GetGPUDescriptorHandleForHeapStart(); + SetResident(true); + increment = device->GetUnwrappedDescriptorIncrement(desc.Type); numDescriptors = desc.NumDescriptors; diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index 2e60fe15c..0db25d11e 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -316,7 +316,8 @@ class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12 static std::vector m_Addresses; + bool resident; + public: ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12Resource); @@ -690,6 +695,7 @@ public: : WrappedDeviceChild12(real, device) { m_List[GetResourceID()] = this; + SetResident(true); // assuming only valid for buffers if(m_pReal->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) @@ -725,6 +731,9 @@ public: Shutdown(); } + + bool Resident() { return resident; } + void SetResident(bool r) { resident = r; } ////////////////////////////// // implement ID3D12Resource