Vulkan: fix Android after pause / resume.
This fixes the visual hang that would occur after going to the task switcher and back. After recreating the swap chain, all of its associated fences and sync objects become invalid. Since we were not tracking this, FrameSkipper was going into an infinite wait after the swap chain was created.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -59,6 +59,7 @@ struct VulkanCmdFence {
|
||||
utils::Condition condition;
|
||||
utils::Mutex mutex;
|
||||
std::atomic<VkResult> 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.
|
||||
|
||||
@@ -679,6 +679,9 @@ FenceStatus VulkanDriver::wait(Handle<HwFence> 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<HwSync> 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;
|
||||
|
||||
Reference in New Issue
Block a user