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:
parent
01a05b48b7
commit
0aaa69e4d7
1 changed files with 12 additions and 9 deletions
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue