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>
This commit is contained in:
Natasha Lee 2020-01-21 18:48:45 +00:00 committed by Commit Bot service account
parent 3003aa622b
commit 80880ee998
3 changed files with 43 additions and 8 deletions

View File

@ -67,6 +67,7 @@ namespace dawn_native {
} }
MaybeError PipelineBase::ValidateGetBindGroupLayout(uint32_t group) { MaybeError PipelineBase::ValidateGetBindGroupLayout(uint32_t group) {
DAWN_TRY(GetDevice()->ValidateIsAlive());
DAWN_TRY(GetDevice()->ValidateObject(this)); DAWN_TRY(GetDevice()->ValidateObject(this));
DAWN_TRY(GetDevice()->ValidateObject(mLayout.Get())); DAWN_TRY(GetDevice()->ValidateObject(mLayout.Get()));
if (group >= kMaxBindGroups) { if (group >= kMaxBindGroups) {

View File

@ -88,6 +88,25 @@ namespace dawn_native { namespace vulkan {
Device::~Device() { Device::~Device() {
BaseDestructor(); 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( ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl(
@ -766,24 +785,16 @@ namespace dawn_native { namespace vulkan {
// Free services explicitly so that they can free Vulkan objects before vkDestroyDevice // Free services explicitly so that they can free Vulkan objects before vkDestroyDevice
mDynamicUploader = nullptr; mDynamicUploader = nullptr;
mDescriptorSetService = nullptr;
// Releasing the uploader enqueues buffers to be released. // Releasing the uploader enqueues buffers to be released.
// Call Tick() again to clear them before releasing the deleter. // Call Tick() again to clear them before releasing the deleter.
mDeleter->Tick(mCompletedSerial); mDeleter->Tick(mCompletedSerial);
mDeleter = nullptr;
mMapRequestTracker = nullptr; mMapRequestTracker = nullptr;
// The VkRenderPasses in the cache can be destroyed immediately since all commands referring // The VkRenderPasses in the cache can be destroyed immediately since all commands referring
// to them are guaranteed to be finished executing. // to them are guaranteed to be finished executing.
mRenderPassCache = nullptr; 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 }} // namespace dawn_native::vulkan

View File

@ -81,6 +81,28 @@ TEST_P(DeviceLostTest, CreateBindGroupLayoutFails) {
ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&descriptor)); 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 that CreateBindGroup fails when device is lost
TEST_P(DeviceLostTest, CreateBindGroupFails) { TEST_P(DeviceLostTest, CreateBindGroupFails) {
SetCallbackAndLoseForTesting(); SetCallbackAndLoseForTesting();
@ -189,4 +211,5 @@ TEST_P(DeviceLostTest, TickFails) {
SetCallbackAndLoseForTesting(); SetCallbackAndLoseForTesting();
ASSERT_DEVICE_ERROR(device.Tick()); ASSERT_DEVICE_ERROR(device.Tick());
} }
DAWN_INSTANTIATE_TEST(DeviceLostTest, D3D12Backend, VulkanBackend); DAWN_INSTANTIATE_TEST(DeviceLostTest, D3D12Backend, VulkanBackend);