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').
This commit is contained in:
baldurk
2016-10-18 12:12:54 +02:00
parent ca3e394c19
commit 99b45aefb5
5 changed files with 117 additions and 9 deletions
+3
View File
@@ -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();
+70 -4
View File
@@ -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<ID3D12Pageable *>(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<ID3D12Pageable *>(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);
}
//////////////////////////////////////////////////////////////////////
+32 -4
View File
@@ -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 **)&copyDst);
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 **)&copyDst);
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));
@@ -264,6 +264,8 @@ WrappedID3D12DescriptorHeap::WrappedID3D12DescriptorHeap(ID3D12DescriptorHeap *r
realCPUBase = real->GetCPUDescriptorHandleForHeapStart();
realGPUBase = real->GetGPUDescriptorHandleForHeapStart();
SetResident(true);
increment = device->GetUnwrappedDescriptorIncrement(desc.Type);
numDescriptors = desc.NumDescriptors;
+10 -1
View File
@@ -316,7 +316,8 @@ class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12<ID3D12Descriptor
D3D12_CPU_DESCRIPTOR_HANDLE realCPUBase;
D3D12_GPU_DESCRIPTOR_HANDLE realGPUBase;
UINT increment;
UINT increment : 24;
UINT resident : 8;
UINT numDescriptors;
D3D12Descriptor *descriptors;
@@ -335,6 +336,8 @@ public:
const D3D12Descriptor *GetDescriptors() { return descriptors; }
UINT GetNumDescriptors() { return numDescriptors; }
bool Resident() { return resident != 0; }
void SetResident(bool r) { resident = r ? 1 : 0; }
//////////////////////////////
// implement ID3D12DescriptorHeap
@@ -646,6 +649,8 @@ class WrappedID3D12Resource : public WrappedDeviceChild12<ID3D12Resource>
static std::vector<AddressRange> 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