From f2a8120a5d79379062ad01e52a3a9e8fb263dcfa Mon Sep 17 00:00:00 2001 From: wallisc Date: Mon, 31 Jul 2023 09:18:32 -0700 Subject: [PATCH 1/2] Several Residency Manager improvements/fixes from UE5/The Coalition This adds several new functions to the residency manager as well as a bug fix: New Functionality: 1. The ability to query the amount of resident and evicted memory from the residency manager. The ability to view evicted memory has also been added to the sample. 2. The ability to specify a custom local memory budget. In UE5, this is can be used with value 0 when the app is detected to be out of focus so that it can trigger extremely aggressive memory eviction. This is particularly important for when using the UE5 editor and you're launching the game as a separate process. Bug Fix: 1. Fixing the parameters for EnqueueMakeResident, according to the Epic change history this fix came from Microsoft originally so unclear why this isn't reflected in the github repo --- .../D3D12Residency/src/D3D12Residency.cpp | 4 +- .../D3D12Residency/src/d3dx12Residency.h | 41 +++++++++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/Samples/Desktop/D3D12Residency/src/D3D12Residency.cpp b/Samples/Desktop/D3D12Residency/src/D3D12Residency.cpp index d06d70b51..64c64c5b6 100644 --- a/Samples/Desktop/D3D12Residency/src/D3D12Residency.cpp +++ b/Samples/Desktop/D3D12Residency/src/D3D12Residency.cpp @@ -535,8 +535,10 @@ void D3D12Residency::PopulateCommandList(std::shared_ptr pMa DXGI_QUERY_VIDEO_MEMORY_INFO memoryInfo = {}; ThrowIfFailed(m_adapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &memoryInfo)); + UINT64 unused, EvictedMemoryInBytes; + m_residencyManager.QueryResidencyStats(unused, EvictedMemoryInBytes); WCHAR message[200]; - swprintf_s(message, L"Total Allocated: %llu MB | Budget: %llu MB | Using: %llu MB", m_totalAllocations >> 20, memoryInfo.Budget >> 20, memoryInfo.CurrentUsage >> 20); + swprintf_s(message, L"Total Allocated: %llu MB | Budget: %llu MB | Using: %llu MB | Evicted: %lld MB", m_totalAllocations >> 20, memoryInfo.Budget >> 20, memoryInfo.CurrentUsage >> 20, EvictedMemoryInBytes >> 20); this->SetCustomWindowText(message); auto commandList = pManagedCommandList->commandList; diff --git a/Samples/Desktop/D3D12Residency/src/d3dx12Residency.h b/Samples/Desktop/D3D12Residency/src/d3dx12Residency.h index 1ff3f0ed6..1e096d5ce 100644 --- a/Samples/Desktop/D3D12Residency/src/d3dx12Residency.h +++ b/Samples/Desktop/D3D12Residency/src/d3dx12Residency.h @@ -504,6 +504,7 @@ namespace D3DX12Residency LRUCache() : NumResidentObjects(0), NumEvictedObjects(0), + EvictedSize(0), ResidentSize(0) { Internal::InitializeListHead(&ResidentObjectListHead); @@ -522,6 +523,7 @@ namespace D3DX12Residency { Internal::InsertHeadList(&EvictedObjectListHead, &pObject->ListEntry); NumEvictedObjects++; + EvictedSize += pObject->Size; } } @@ -536,6 +538,7 @@ namespace D3DX12Residency else { NumEvictedObjects--; + EvictedSize -= pObject->Size; } } @@ -561,6 +564,7 @@ namespace D3DX12Residency NumEvictedObjects--; NumResidentObjects++; ResidentSize += pObject->Size; + EvictedSize -= pObject->Size; } void Evict(ManagedObject* pObject) @@ -574,6 +578,7 @@ namespace D3DX12Residency NumResidentObjects--; ResidentSize -= pObject->Size; NumEvictedObjects++; + EvictedSize += pObject->Size; } // Evict all of the resident objects used in sync points up to the specficied one (inclusive) @@ -640,6 +645,7 @@ namespace D3DX12Residency UINT32 NumEvictedObjects; UINT64 ResidentSize; + UINT64 EvictedSize; }; class ResidencyManagerInternal @@ -896,6 +902,13 @@ namespace D3DX12Residency return hr; } + UINT64 LocalMemoryBudgetLimit = ~0ull; + + void QueryResidencyStats(UINT64& ResidentMemoryInBytes, UINT64& EvictedMemoryInBytes) + { + ResidentMemoryInBytes = LRU.ResidentSize; + EvictedMemoryInBytes = LRU.EvictedSize; + } private: HRESULT GetFence(ID3D12CommandQueue *Queue, Internal::Fence *&QueueFence) { @@ -1198,6 +1211,10 @@ namespace D3DX12Residency GetCurrentBudget(&LocalMemory, DXGI_MEMORY_SEGMENT_GROUP_LOCAL); UINT64 EvictionGracePeriod = GetCurrentEvictionGracePeriod(&LocalMemory); + if (LocalMemoryBudgetLimit == 0) + { + EvictionGracePeriod = 0; + } LRU.TrimAgedAllocations(FirstUncompletedSyncPoint, pEvictionList, NumObjectsToEvict, CurrentTime.QuadPart, EvictionGracePeriod); if (NumObjectsToEvict) @@ -1296,8 +1313,8 @@ namespace D3DX12Residency if (Device3) { hr = Device3->EnqueueMakeResident(D3D12_RESIDENCY_FLAG_NONE, - NumObjectsInBatch, - &pMakeResidentList[BatchStart].pUnderlying, + NumObjects, + &pMakeResidentList[MakeResidentIndex].pUnderlying, AsyncThreadFence.pFence, AsyncThreadFence.FenceValue + 1); if (SUCCEEDED(hr)) @@ -1329,7 +1346,9 @@ namespace D3DX12Residency // Wait until the GPU is done WaitForSyncPoint(GenerationToWaitFor); - LRU.TrimToSyncPointInclusive(TotalUsage + INT64(SizeToMakeResident), TotalBudget, pEvictionList, NumObjectsToEvict, GenerationToWaitFor); + LRU.TrimToSyncPointInclusive(TotalUsage + INT64(SizeToMakeResident), + LocalMemoryBudgetLimit == 0 ? 0 : TotalBudget, + pEvictionList, NumObjectsToEvict, GenerationToWaitFor); RESIDENCY_CHECK_RESULT(Device->Evict(NumObjectsToEvict, pEvictionList)); } @@ -1406,6 +1425,10 @@ namespace D3DX12Residency RESIDENCY_CHECK_RESULT(DeviceDownlevel->QueryVideoMemoryInfo(NodeIndex, Segment, InfoOut)); } #endif + if (Segment == DXGI_MEMORY_SEGMENT_GROUP_LOCAL) + { + InfoOut->Budget = RESIDENCY_MIN(LocalMemoryBudgetLimit, InfoOut->Budget); + } } HRESULT EnqueueSyncPoint() @@ -1613,8 +1636,18 @@ namespace D3DX12Residency delete(pSet); } + FORCEINLINE void QueryResidencyStats(UINT64& ResidentMemoryInBytes, UINT64& EvictedMemoryInBytes) + { + Manager.QueryResidencyStats(ResidentMemoryInBytes, EvictedMemoryInBytes); + } + + void SetLocalMemoryBudgetLimit(UINT64 InLocalMemoryBudgetLimit) + { + Manager.LocalMemoryBudgetLimit = InLocalMemoryBudgetLimit; + } + private: Internal::ResidencyManagerInternal Manager; Internal::SyncManager SyncManager; }; -}; +}; \ No newline at end of file From 92c48f8ff8e43583ece8763b84ef2bb43b454896 Mon Sep 17 00:00:00 2001 From: wallisc Date: Mon, 31 Jul 2023 09:23:16 -0700 Subject: [PATCH 2/2] One character fix --- Samples/Desktop/D3D12Residency/src/D3D12Residency.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Samples/Desktop/D3D12Residency/src/D3D12Residency.cpp b/Samples/Desktop/D3D12Residency/src/D3D12Residency.cpp index 64c64c5b6..dd48da2dc 100644 --- a/Samples/Desktop/D3D12Residency/src/D3D12Residency.cpp +++ b/Samples/Desktop/D3D12Residency/src/D3D12Residency.cpp @@ -538,7 +538,7 @@ void D3D12Residency::PopulateCommandList(std::shared_ptr pMa UINT64 unused, EvictedMemoryInBytes; m_residencyManager.QueryResidencyStats(unused, EvictedMemoryInBytes); WCHAR message[200]; - swprintf_s(message, L"Total Allocated: %llu MB | Budget: %llu MB | Using: %llu MB | Evicted: %lld MB", m_totalAllocations >> 20, memoryInfo.Budget >> 20, memoryInfo.CurrentUsage >> 20, EvictedMemoryInBytes >> 20); + swprintf_s(message, L"Total Allocated: %llu MB | Budget: %llu MB | Using: %llu MB | Evicted: %llu MB", m_totalAllocations >> 20, memoryInfo.Budget >> 20, memoryInfo.CurrentUsage >> 20, EvictedMemoryInBytes >> 20); this->SetCustomWindowText(message); auto commandList = pManagedCommandList->commandList;