Device Loss handle GetBindGroupLayout and test
This includes moving the destruction of vkDevice from Destroy to the
Device Destructor since we need vkDevice to destroy child objects.
Bug: dawn:68
Change-Id: Id477206b2e3f80138b3708eedcee073303f1b696
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15220
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Natasha Lee <natlee@microsoft.com>
diff --git a/src/dawn_native/Pipeline.cpp b/src/dawn_native/Pipeline.cpp
index ad819d1..4c2439b 100644
--- a/src/dawn_native/Pipeline.cpp
+++ b/src/dawn_native/Pipeline.cpp
@@ -67,6 +67,7 @@
}
MaybeError PipelineBase::ValidateGetBindGroupLayout(uint32_t group) {
+ DAWN_TRY(GetDevice()->ValidateIsAlive());
DAWN_TRY(GetDevice()->ValidateObject(this));
DAWN_TRY(GetDevice()->ValidateObject(mLayout.Get()));
if (group >= kMaxBindGroups) {
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 6b44d49..13a7824 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -88,6 +88,25 @@
Device::~Device() {
BaseDestructor();
+
+ mDescriptorSetService = nullptr;
+
+ // We still need to properly handle Vulkan object deletion even if the device has been lost,
+ // so the Deleter and vkDevice cannot be destroyed in Device::Destroy().
+ // We need handle deleting all child objects by calling Tick() again with a large serial to
+ // force all operations to look as if they were completed, and delete all objects before
+ // destroying the Deleter and vkDevice.
+ mCompletedSerial = std::numeric_limits<Serial>::max();
+ mDeleter->Tick(mCompletedSerial);
+ mDeleter = nullptr;
+
+ // VkQueues are destroyed when the VkDevice is destroyed
+ // The VkDevice is needed to destroy child objects, so it must be destroyed last after all
+ // child objects have been deleted.
+ if (mVkDevice != VK_NULL_HANDLE) {
+ fn.DestroyDevice(mVkDevice, nullptr);
+ mVkDevice = VK_NULL_HANDLE;
+ }
}
ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl(
@@ -766,24 +785,16 @@
// Free services explicitly so that they can free Vulkan objects before vkDestroyDevice
mDynamicUploader = nullptr;
- mDescriptorSetService = nullptr;
// Releasing the uploader enqueues buffers to be released.
// Call Tick() again to clear them before releasing the deleter.
mDeleter->Tick(mCompletedSerial);
- mDeleter = nullptr;
mMapRequestTracker = nullptr;
// The VkRenderPasses in the cache can be destroyed immediately since all commands referring
// to them are guaranteed to be finished executing.
mRenderPassCache = nullptr;
-
- // VkQueues are destroyed when the VkDevice is destroyed
- if (mVkDevice != VK_NULL_HANDLE) {
- fn.DestroyDevice(mVkDevice, nullptr);
- mVkDevice = VK_NULL_HANDLE;
- }
}
}} // namespace dawn_native::vulkan
diff --git a/src/tests/end2end/DeviceLostTests.cpp b/src/tests/end2end/DeviceLostTests.cpp
index ab8f260..722e5d0 100644
--- a/src/tests/end2end/DeviceLostTests.cpp
+++ b/src/tests/end2end/DeviceLostTests.cpp
@@ -81,6 +81,28 @@
ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&descriptor));
}
+// Test that GetBindGroupLayout fails when device is lost
+TEST_P(DeviceLostTest, GetBindGroupLayoutFails) {
+ wgpu::ShaderModule csModule =
+ utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
+ #version 450
+ layout(set = 0, binding = 0) uniform UniformBuffer {
+ vec4 pos;
+ };
+ void main() {
+ })");
+
+ wgpu::ComputePipelineDescriptor descriptor;
+ descriptor.layout = nullptr;
+ descriptor.computeStage.module = csModule;
+ descriptor.computeStage.entryPoint = "main";
+
+ wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&descriptor);
+
+ SetCallbackAndLoseForTesting();
+ ASSERT_DEVICE_ERROR(pipeline.GetBindGroupLayout(0).Get());
+}
+
// Test that CreateBindGroup fails when device is lost
TEST_P(DeviceLostTest, CreateBindGroupFails) {
SetCallbackAndLoseForTesting();
@@ -189,4 +211,5 @@
SetCallbackAndLoseForTesting();
ASSERT_DEVICE_ERROR(device.Tick());
}
+
DAWN_INSTANTIATE_TEST(DeviceLostTest, D3D12Backend, VulkanBackend);
\ No newline at end of file