vk_swapchain: Silence TOCTOU race condition

It's possible that the window is resized from the moment we ask for its
size to the moment a swapchain is created, causing validation issues.

To workaround this Vulkan issue request the capabilities again just
before creating the swapchain, making the race condition less likely.
This commit is contained in:
ReinUsesLisp 2020-02-26 16:51:53 -03:00
parent 01a05b48b7
commit 0aaa69e4d7

View File

@ -141,11 +141,6 @@ void VKSwapchain::CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities
const vk::SurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats, srgb)}; const vk::SurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats, srgb)};
const vk::PresentModeKHR present_mode{ChooseSwapPresentMode(present_modes)}; const vk::PresentModeKHR present_mode{ChooseSwapPresentMode(present_modes)};
extent = ChooseSwapExtent(capabilities, width, height);
current_width = extent.width;
current_height = extent.height;
current_srgb = srgb;
u32 requested_image_count{capabilities.minImageCount + 1}; u32 requested_image_count{capabilities.minImageCount + 1};
if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) { if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) {
@ -153,10 +148,9 @@ void VKSwapchain::CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities
} }
vk::SwapchainCreateInfoKHR swapchain_ci( vk::SwapchainCreateInfoKHR swapchain_ci(
{}, surface, requested_image_count, surface_format.format, surface_format.colorSpace, {}, surface, requested_image_count, surface_format.format, surface_format.colorSpace, {}, 1,
extent, 1, vk::ImageUsageFlagBits::eColorAttachment, {}, {}, {}, vk::ImageUsageFlagBits::eColorAttachment, {}, {}, {}, capabilities.currentTransform,
capabilities.currentTransform, vk::CompositeAlphaFlagBitsKHR::eOpaque, present_mode, false, vk::CompositeAlphaFlagBitsKHR::eOpaque, present_mode, false, {});
{});
const u32 graphics_family{device.GetGraphicsFamily()}; const u32 graphics_family{device.GetGraphicsFamily()};
const u32 present_family{device.GetPresentFamily()}; const u32 present_family{device.GetPresentFamily()};
@ -169,9 +163,18 @@ void VKSwapchain::CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities
swapchain_ci.imageSharingMode = vk::SharingMode::eExclusive; swapchain_ci.imageSharingMode = vk::SharingMode::eExclusive;
} }
// Request the size again to reduce the possibility of a TOCTOU race condition.
const auto updated_capabilities = physical_device.getSurfaceCapabilitiesKHR(surface, dld);
swapchain_ci.imageExtent = ChooseSwapExtent(updated_capabilities, width, height);
// Don't add code within this and the swapchain creation.
const auto dev{device.GetLogical()}; const auto dev{device.GetLogical()};
swapchain = dev.createSwapchainKHRUnique(swapchain_ci, nullptr, dld); swapchain = dev.createSwapchainKHRUnique(swapchain_ci, nullptr, dld);
extent = swapchain_ci.imageExtent;
current_width = extent.width;
current_height = extent.height;
current_srgb = srgb;
images = dev.getSwapchainImagesKHR(*swapchain, dld); images = dev.getSwapchainImagesKHR(*swapchain, dld);
image_count = static_cast<u32>(images.size()); image_count = static_cast<u32>(images.size());
image_format = surface_format.format; image_format = surface_format.format;