Residency 4: Add Facilities For Budgeting Device Memory
Use D3D12's QueryDeviceVideoMemoryInfo to get the OS-determined process
budget. Also introduces an export for reserving some amount of process
memory - which keeps Dawn from using the entire process's budget.
Bug: dawn:193
Change-Id: I6c17bd703d7cb24759bcee89c03add46944fec8c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/16383
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/d3d12/ResidencyManagerD3D12.cpp b/src/dawn_native/d3d12/ResidencyManagerD3D12.cpp
new file mode 100644
index 0000000..c105748
--- /dev/null
+++ b/src/dawn_native/d3d12/ResidencyManagerD3D12.cpp
@@ -0,0 +1,69 @@
+// Copyright 2020 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/d3d12/ResidencyManagerD3D12.h"
+
+#include "dawn_native/d3d12/AdapterD3D12.h"
+#include "dawn_native/d3d12/DeviceD3D12.h"
+#include "dawn_native/d3d12/Forward.h"
+#include "dawn_native/d3d12/d3d12_platform.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ ResidencyManager::ResidencyManager(Device* device)
+ : mDevice(device),
+ mResidencyManagementEnabled(
+ device->IsToggleEnabled(Toggle::UseD3D12ResidencyManagement)) {
+ UpdateVideoMemoryInfo();
+ }
+
+ // 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
+ // that the requested reservation when under pressure.
+ uint64_t ResidencyManager::SetExternalMemoryReservation(uint64_t requestedReservationSize) {
+ mVideoMemoryInfo.externalRequest = requestedReservationSize;
+ UpdateVideoMemoryInfo();
+ return mVideoMemoryInfo.externalReservation;
+ }
+
+ void ResidencyManager::UpdateVideoMemoryInfo() {
+ if (!mResidencyManagementEnabled) {
+ return;
+ }
+
+ DXGI_QUERY_VIDEO_MEMORY_INFO queryVideoMemoryInfo;
+ ToBackend(mDevice->GetAdapter())
+ ->GetHardwareAdapter()
+ ->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &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
+ // cap the external reservation to half the available budget, which prevents the external
+ // 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.externalReservation);
+
+ // We cap Dawn's budget to 95% of the provided budget. Leaving some budget unused
+ // decreases fluctuations in the operating-system-defined budget, which improves stability
+ // 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;
+ mVideoMemoryInfo.dawnUsage =
+ queryVideoMemoryInfo.CurrentUsage - mVideoMemoryInfo.externalReservation;
+ }
+}} // namespace dawn_native::d3d12
\ No newline at end of file