Non-Local Residency 1: Get Non-Local Memory Info
Adds functionality to query VideoMemoryInfo for the NON_LOCAL memory
segment.
Bug: dawn:193
Change-Id: I63c2f5a649c37617e7b39a60faa2d3b5b5077156
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/19900
Commit-Queue: Brandon Jones <brandon1.jones@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/d3d12/D3D12Backend.cpp b/src/dawn_native/d3d12/D3D12Backend.cpp
index fbf4344..3543c63 100644
--- a/src/dawn_native/d3d12/D3D12Backend.cpp
+++ b/src/dawn_native/d3d12/D3D12Backend.cpp
@@ -51,11 +51,13 @@
: ExternalImageDescriptor(ExternalImageDescriptorType::DXGISharedHandle) {
}
- uint64_t SetExternalMemoryReservation(WGPUDevice device, uint64_t requestedReservationSize) {
+ uint64_t SetExternalMemoryReservation(WGPUDevice device,
+ uint64_t requestedReservationSize,
+ MemorySegment memorySegment) {
Device* backendDevice = reinterpret_cast<Device*>(device);
return backendDevice->GetResidencyManager()->SetExternalMemoryReservation(
- requestedReservationSize);
+ memorySegment, requestedReservationSize);
}
WGPUTexture WrapSharedHandle(WGPUDevice device,
diff --git a/src/dawn_native/d3d12/ResidencyManagerD3D12.cpp b/src/dawn_native/d3d12/ResidencyManagerD3D12.cpp
index 237ee54..be91612 100644
--- a/src/dawn_native/d3d12/ResidencyManagerD3D12.cpp
+++ b/src/dawn_native/d3d12/ResidencyManagerD3D12.cpp
@@ -1,3 +1,4 @@
+#include "ResidencyManagerD3D12.h"
// Copyright 2020 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,8 +21,6 @@
#include "dawn_native/d3d12/Forward.h"
#include "dawn_native/d3d12/HeapD3D12.h"
-#include "dawn_native/d3d12/d3d12_platform.h"
-
namespace dawn_native { namespace d3d12 {
ResidencyManager::ResidencyManager(Device* device)
@@ -84,24 +83,43 @@
}
}
- // Allows an application component external to Dawn to cap Dawn's residency budget to prevent
- // competition for device local memory. Returns the amount of memory reserved, which may be less
+ // Allows an application component external to Dawn to cap Dawn's residency budgets to prevent
+ // competition for device memory. Returns the amount of memory reserved, which may be less
// that the requested reservation when under pressure.
- uint64_t ResidencyManager::SetExternalMemoryReservation(uint64_t requestedReservationSize) {
- mVideoMemoryInfo.externalRequest = requestedReservationSize;
- UpdateVideoMemoryInfo();
- return mVideoMemoryInfo.externalReservation;
+ uint64_t ResidencyManager::SetExternalMemoryReservation(MemorySegment segment,
+ uint64_t requestedReservationSize) {
+ MemorySegmentInfo* segmentInfo = nullptr;
+ switch (segment) {
+ case MemorySegment::Local:
+ segmentInfo = &mVideoMemoryInfo.local;
+ break;
+ case MemorySegment::NonLocal:
+ segmentInfo = &mVideoMemoryInfo.nonLocal;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ segmentInfo->externalRequest = requestedReservationSize;
+
+ UpdateMemorySegmentInfo(segmentInfo);
+
+ return segmentInfo->externalReservation;
}
void ResidencyManager::UpdateVideoMemoryInfo() {
- if (!mResidencyManagementEnabled) {
- return;
+ UpdateMemorySegmentInfo(&mVideoMemoryInfo.local);
+ if (!mDevice->GetDeviceInfo().isUMA) {
+ UpdateMemorySegmentInfo(&mVideoMemoryInfo.nonLocal);
}
+ }
+ void ResidencyManager::UpdateMemorySegmentInfo(MemorySegmentInfo* segmentInfo) {
DXGI_QUERY_VIDEO_MEMORY_INFO queryVideoMemoryInfo;
+
ToBackend(mDevice->GetAdapter())
->GetHardwareAdapter()
- ->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &queryVideoMemoryInfo);
+ ->QueryVideoMemoryInfo(0, segmentInfo->dxgiSegment, &queryVideoMemoryInfo);
// The video memory budget provided by QueryVideoMemoryInfo is defined by the operating
// system, and may be lower than expected in certain scenarios. Under memory pressure, we
@@ -109,11 +127,10 @@
// component from consuming a disproportionate share of memory and ensures that Dawn can
// continue to make forward progress. Note the choice to halve memory is arbitrarily chosen
// and subject to future experimentation.
- mVideoMemoryInfo.externalReservation =
- std::min(queryVideoMemoryInfo.Budget / 2, mVideoMemoryInfo.externalRequest);
+ segmentInfo->externalReservation =
+ std::min(queryVideoMemoryInfo.Budget / 2, segmentInfo->externalRequest);
- mVideoMemoryInfo.dawnUsage =
- queryVideoMemoryInfo.CurrentUsage - mVideoMemoryInfo.externalReservation;
+ segmentInfo->usage = queryVideoMemoryInfo.CurrentUsage - segmentInfo->externalReservation;
// If we're restricting the budget for testing, leave the budget as is.
if (mRestrictBudgetForTesting) {
@@ -125,8 +142,8 @@
// for both Dawn and other applications on the system. Note the value of 95% is arbitrarily
// chosen and subject to future experimentation.
static constexpr float kBudgetCap = 0.95;
- mVideoMemoryInfo.dawnBudget =
- (queryVideoMemoryInfo.Budget - mVideoMemoryInfo.externalReservation) * kBudgetCap;
+ segmentInfo->budget =
+ (queryVideoMemoryInfo.Budget - segmentInfo->externalReservation) * kBudgetCap;
}
// Removes from the LRU and returns the least recently used heap when possible. Returns nullptr
@@ -161,18 +178,18 @@
return {};
}
- UpdateVideoMemoryInfo();
+ UpdateMemorySegmentInfo(&mVideoMemoryInfo.local);
- uint64_t memoryUsageAfterMakeResident = sizeToMakeResident + mVideoMemoryInfo.dawnUsage;
+ uint64_t memoryUsageAfterMakeResident = sizeToMakeResident + mVideoMemoryInfo.local.usage;
// Return when we can call MakeResident and remain under budget.
- if (memoryUsageAfterMakeResident < mVideoMemoryInfo.dawnBudget) {
+ if (memoryUsageAfterMakeResident < mVideoMemoryInfo.local.budget) {
return {};
}
std::vector<ID3D12Pageable*> resourcesToEvict;
uint64_t sizeNeededToBeUnderBudget =
- memoryUsageAfterMakeResident - mVideoMemoryInfo.dawnBudget;
+ memoryUsageAfterMakeResident - mVideoMemoryInfo.local.budget;
uint64_t sizeEvicted = 0;
while (sizeEvicted < sizeNeededToBeUnderBudget) {
Heap* heap;
@@ -301,7 +318,11 @@
// value can vary depending on the environment Dawn is running in. By adding this in
// addition to the artificial budget cap, we can create a predictable and reproducible
// budget for testing.
- mVideoMemoryInfo.dawnBudget = mVideoMemoryInfo.dawnUsage + artificialBudgetCap;
+ mVideoMemoryInfo.local.budget = mVideoMemoryInfo.local.usage + artificialBudgetCap;
+ if (!mDevice->GetDeviceInfo().isUMA) {
+ mVideoMemoryInfo.nonLocal.budget =
+ mVideoMemoryInfo.nonLocal.usage + artificialBudgetCap;
+ }
}
}} // namespace dawn_native::d3d12
\ No newline at end of file
diff --git a/src/dawn_native/d3d12/ResidencyManagerD3D12.h b/src/dawn_native/d3d12/ResidencyManagerD3D12.h
index f9370de..29d4e1d 100644
--- a/src/dawn_native/d3d12/ResidencyManagerD3D12.h
+++ b/src/dawn_native/d3d12/ResidencyManagerD3D12.h
@@ -17,9 +17,12 @@
#include "common/LinkedList.h"
#include "common/Serial.h"
+#include "dawn_native/D3D12Backend.h"
#include "dawn_native/Error.h"
#include "dawn_native/dawn_platform.h"
+#include "dawn_native/d3d12/d3d12_platform.h"
+
namespace dawn_native { namespace d3d12 {
class Device;
@@ -34,22 +37,31 @@
MaybeError EnsureCanMakeResident(uint64_t allocationSize);
MaybeError EnsureHeapsAreResident(Heap** heaps, size_t heapCount);
- uint64_t SetExternalMemoryReservation(uint64_t requestedReservationSize);
+ uint64_t SetExternalMemoryReservation(MemorySegment segment,
+ uint64_t requestedReservationSize);
void TrackResidentAllocation(Heap* heap);
- void RestrictBudgetForTesting(uint64_t);
+ void RestrictBudgetForTesting(uint64_t artificialBudgetCap);
private:
- struct VideoMemoryInfo {
- uint64_t dawnBudget;
- uint64_t dawnUsage;
+ struct MemorySegmentInfo {
+ const DXGI_MEMORY_SEGMENT_GROUP dxgiSegment;
+ uint64_t budget;
+ uint64_t usage;
uint64_t externalReservation;
uint64_t externalRequest;
};
+
+ struct VideoMemoryInfo {
+ MemorySegmentInfo local = {DXGI_MEMORY_SEGMENT_GROUP_LOCAL, 0, 0, 0, 0};
+ MemorySegmentInfo nonLocal = {DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, 0, 0, 0, 0};
+ };
+
ResultOrError<Heap*> RemoveSingleEntryFromLRU();
bool ShouldTrackHeap(Heap* heap) const;
void UpdateVideoMemoryInfo();
+ void UpdateMemorySegmentInfo(MemorySegmentInfo* segmentInfo);
Device* mDevice;
LinkedList<Heap> mLRUCache;
diff --git a/src/include/dawn_native/D3D12Backend.h b/src/include/dawn_native/D3D12Backend.h
index 0cef24c..bdefdf3 100644
--- a/src/include/dawn_native/D3D12Backend.h
+++ b/src/include/dawn_native/D3D12Backend.h
@@ -30,6 +30,15 @@
DAWN_NATIVE_EXPORT WGPUTextureFormat
GetNativeSwapChainPreferredFormat(const DawnSwapChainImplementation* swapChain);
+ enum MemorySegment {
+ Local,
+ NonLocal,
+ };
+
+ DAWN_NATIVE_EXPORT uint64_t SetExternalMemoryReservation(WGPUDevice device,
+ uint64_t requestedReservationSize,
+ MemorySegment memorySegment);
+
struct DAWN_NATIVE_EXPORT ExternalImageDescriptorDXGISharedHandle : ExternalImageDescriptor {
public:
ExternalImageDescriptorDXGISharedHandle();
@@ -39,9 +48,6 @@
bool isSwapChainTexture = false;
};
- DAWN_NATIVE_EXPORT uint64_t SetExternalMemoryReservation(WGPUDevice device,
- uint64_t requestedReservationSize);
-
// Note: SharedHandle must be a handle to a texture object.
DAWN_NATIVE_EXPORT WGPUTexture
WrapSharedHandle(WGPUDevice device, const ExternalImageDescriptorDXGISharedHandle* descriptor);
diff --git a/src/tests/white_box/D3D12ResidencyTests.cpp b/src/tests/white_box/D3D12ResidencyTests.cpp
index 214ede8..4386cdd 100644
--- a/src/tests/white_box/D3D12ResidencyTests.cpp
+++ b/src/tests/white_box/D3D12ResidencyTests.cpp
@@ -12,11 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "dawn_native/ResourceMemoryAllocation.h"
+#include "dawn_native/D3D12Backend.h"
#include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/ResidencyManagerD3D12.h"
-#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
#include "tests/DawnTest.h"
#include "utils/WGPUHelpers.h"
@@ -301,4 +300,19 @@
}
}
+TEST_P(D3D12ResidencyTests, SetExternalReservation) {
+ // Set an external reservation of 20% the budget. We should succesfully reserve the amount we
+ // request.
+ uint64_t amountReserved = dawn_native::d3d12::SetExternalMemoryReservation(
+ device.Get(), kRestrictedBudgetSize * .2, dawn_native::d3d12::MemorySegment::Local);
+ EXPECT_EQ(amountReserved, kRestrictedBudgetSize * .2);
+
+ // If we're on a non-UMA device, we should also check the NON_LOCAL memory segment.
+ if (!IsUMA()) {
+ amountReserved = dawn_native::d3d12::SetExternalMemoryReservation(
+ device.Get(), kRestrictedBudgetSize * .2, dawn_native::d3d12::MemorySegment::NonLocal);
+ EXPECT_EQ(amountReserved, kRestrictedBudgetSize * .2);
+ }
+}
+
DAWN_INSTANTIATE_TEST(D3D12ResidencyTests, D3D12Backend());