diff --git a/filament/backend/src/vulkan/VulkanContext.cpp b/filament/backend/src/vulkan/VulkanContext.cpp index f92b277274..c239cfe6c3 100644 --- a/filament/backend/src/vulkan/VulkanContext.cpp +++ b/filament/backend/src/vulkan/VulkanContext.cpp @@ -448,7 +448,14 @@ void destroySwapChain(VulkanContext& context, VulkanSurfaceContext& surfaceConte disposer.release(swapContext.commands.resources); vkFreeCommandBuffers(context.device, context.commandPool, 1, &swapContext.commands.cmdbuffer); + + // The wrapper object for the submission fence has shared ownership semantics, so here + // we notify other owners that the swap chain (and its associated command buffers) have + // been destroyed. + swapContext.commands.fence->swapChainDestroyed = true; + swapContext.commands.fence.reset(); + vkDestroyImageView(context.device, swapContext.attachment.view, VKALLOC); swapContext.commands.fence = VK_NULL_HANDLE; swapContext.attachment.view = VK_NULL_HANDLE; diff --git a/filament/backend/src/vulkan/VulkanContext.h b/filament/backend/src/vulkan/VulkanContext.h index aaaa25a635..58a8a94bce 100644 --- a/filament/backend/src/vulkan/VulkanContext.h +++ b/filament/backend/src/vulkan/VulkanContext.h @@ -59,6 +59,7 @@ struct VulkanCmdFence { utils::Condition condition; utils::Mutex mutex; std::atomic status; + bool swapChainDestroyed = false; // TODO: for non-work buffers the following field indicates if the fence has EVER been // submitted, which is a bit misleading or un-useful. This needs to be refactored. diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 76c2021141..ce603ccbed 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -679,6 +679,9 @@ FenceStatus VulkanDriver::wait(Handle fh, uint64_t timeout) { } else { lock.unlock(); } + if (cmdfence->swapChainDestroyed) { + return FenceStatus::ERROR; + } VkResult result = vkWaitForFences(mContext.device, 1, &cmdfence->fence, VK_FALSE, timeout); return result == VK_SUCCESS ? FenceStatus::CONDITION_SATISFIED : FenceStatus::TIMEOUT_EXPIRED; } @@ -830,6 +833,9 @@ SyncStatus VulkanDriver::getSyncStatus(Handle sh) { if (sync->fence == nullptr) { return SyncStatus::NOT_SIGNALED; } + if (sync->fence->swapChainDestroyed) { + return SyncStatus::ERROR; + } VkResult status = sync->fence->status.load(std::memory_order_relaxed); switch (status) { case VK_SUCCESS: return SyncStatus::SIGNALED;