Skip to content

Commit

Permalink
vk: properly destroy swapchain on recreate (#8365)
Browse files Browse the repository at this point in the history
Fixes #8185, #6445
  • Loading branch information
poweifeng authored Jan 17, 2025
1 parent 7c6463d commit c49d72e
Showing 1 changed file with 23 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void VulkanPlatformSwapChainImpl::destroy() {
mSwapChainBundle.colors.clear();
}

VkImage VulkanPlatformSwapChainImpl::createImage(VkExtent2D extent, VkFormat format,
VkImage VulkanPlatformSwapChainImpl::createImage(VkExtent2D extent, VkFormat format,
bool isProtected) {
auto [image, memory] = createImageAndMemory(mContext, mDevice, extent, format, isProtected);
mMemory.insert({image, memory});
Expand All @@ -140,9 +140,8 @@ VulkanPlatformSurfaceSwapChain::VulkanPlatformSurfaceSwapChain(VulkanContext con
}

VulkanPlatformSurfaceSwapChain::~VulkanPlatformSurfaceSwapChain() {
vkDestroySwapchainKHR(mDevice, mSwapchain, VKALLOC);
vkDestroySurfaceKHR(mInstance, mSurface, VKALLOC);
destroy();
vkDestroySurfaceKHR(mInstance, mSurface, VKALLOC);
}

VkResult VulkanPlatformSurfaceSwapChain::create() {
Expand Down Expand Up @@ -256,7 +255,7 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
mSwapChainBundle.colorFormat = surfaceFormat.format;
mSwapChainBundle.depthFormat =
selectDepthFormat(mContext.getAttachmentDepthStencilFormats(), mHasStencil);
mSwapChainBundle.depth = createImage(mSwapChainBundle.extent,
mSwapChainBundle.depth = createImage(mSwapChainBundle.extent,
mSwapChainBundle.depthFormat, mIsProtected);
mSwapChainBundle.isProtected = mIsProtected;

Expand Down Expand Up @@ -344,6 +343,22 @@ VkResult VulkanPlatformSurfaceSwapChain::recreate() {
}

void VulkanPlatformSurfaceSwapChain::destroy() {
// The next part is not ideal. We don't have a good signal on when it's ok to destroy
// a swapchain. This is a spec oversight and mentioned as much:
// https://github.com/KhronosGroup/Vulkan-Docs/issues/1678
//
// One workaround [1] is:
// https://docs.vulkan.org/samples/latest/samples/api/swapchain_recreation/README.html
//
// The proper fix is to use VK_EXT_swapchain_maintenance1, but availability of this extension is
// unknown (not yet ratified).
//
// Instead of adding too much mechanics, we're taking a hacksaw to the problem - just wait for
// the queue to be idle. The hope is that this only happens on resize, where performance
// degradation is less obvious (until, of course, people complain about lag when rotating their
// phone). If necessary, we can revisit and implement the workaround [1].
vkQueueWaitIdle(mQueue);

VulkanPlatformSwapChainImpl::destroy();

for (uint32_t i = 0; i < IMAGE_READY_SEMAPHORE_COUNT; ++i) {
Expand All @@ -352,6 +367,10 @@ void VulkanPlatformSurfaceSwapChain::destroy() {
mImageReady[i] = VK_NULL_HANDLE;
}
}
if (mSwapchain) {
vkDestroySwapchainKHR(mDevice, mSwapchain, VKALLOC);
mSwapchain = VK_NULL_HANDLE;
}
}

VulkanPlatformHeadlessSwapChain::VulkanPlatformHeadlessSwapChain(VulkanContext const& context,
Expand Down

0 comments on commit c49d72e

Please sign in to comment.