From 36317d9839963a2b10b2b6443f9c8cc46196253b Mon Sep 17 00:00:00 2001 From: Rafael Cintron Date: Thu, 24 Nov 2022 01:10:35 +0000 Subject: [PATCH] Release D3D12 command queue in Device::DestroyImpl Repeatedly creating and destroying WebGPU devices in a loop causes large amounts of memory to pile up in the GPU process. Much of this memory comes from the D3D12 command queue. Releasing the command queue early in DestroyImpl before the destructor runs goes a long way towards relieving the memory pressure. Bug: chromium:1377789 Change-Id: I3ff9a5f6cb3ea3136e41079343532cbe732b6cc4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/111280 Reviewed-by: Corentin Wallez Kokoro: Kokoro Commit-Queue: Rafael Cintron --- src/dawn/native/d3d12/DeviceD3D12.cpp | 4 ++++ src/dawn/tests/end2end/DestroyTests.cpp | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp index 8c79f06fe3..b0076491c2 100644 --- a/src/dawn/native/d3d12/DeviceD3D12.cpp +++ b/src/dawn/native/d3d12/DeviceD3D12.cpp @@ -859,6 +859,10 @@ void Device::DestroyImpl() { ASSERT(mUsedComObjectRefs.Empty()); ASSERT(!mPendingCommands.IsOpen()); + + // Now that we've cleared out pending work from the queue, we can safely release it and reclaim + // memory. + mCommandQueue.Reset(); } ShaderVisibleDescriptorAllocator* Device::GetViewShaderVisibleDescriptorAllocator() const { diff --git a/src/dawn/tests/end2end/DestroyTests.cpp b/src/dawn/tests/end2end/DestroyTests.cpp index fcf53b2a0b..a6ec75aad6 100644 --- a/src/dawn/tests/end2end/DestroyTests.cpp +++ b/src/dawn/tests/end2end/DestroyTests.cpp @@ -156,7 +156,7 @@ TEST_P(DestroyTest, TextureSubmitDestroySubmit) { } // Attempting to set an object label after it has been destroyed should not cause an error. -TEST_P(DestroyTest, DestroyThenSetLabel) { +TEST_P(DestroyTest, DestroyObjectThenSetLabel) { DAWN_TEST_UNSUPPORTED_IF(UsesWire()); std::string label = "test"; wgpu::BufferDescriptor descriptor; @@ -167,6 +167,14 @@ TEST_P(DestroyTest, DestroyThenSetLabel) { buffer.SetLabel(label.c_str()); } +// Attempting to set a device label after it has been destroyed should not cause an error. +TEST_P(DestroyTest, DestroyDeviceThenSetLabel) { + DAWN_TEST_UNSUPPORTED_IF(UsesWire()); + std::string label = "test"; + device.Destroy(); + device.SetLabel(label.c_str()); +} + // Device destroy before buffer submit will result in error. TEST_P(DestroyTest, DestroyDeviceBeforeSubmit) { // TODO(crbug.com/dawn/628) Add more comprehensive tests with destroy and backends.