From 9ef554b97ed63c99f62f8114d07f5879384089af Mon Sep 17 00:00:00 2001 From: catbot Date: Tue, 16 Jun 2026 15:28:35 +0000 Subject: [PATCH] perf(window): drop dead present-mode queries from swapchain recreate (#45) CreateSwapchain unconditionally used VK_PRESENT_MODE_FIFO_KHR, but still ran two vkGetPhysicalDeviceSurfacePresentModesKHR calls plus a heap-allocated std::vector to enumerate present modes that were never consulted. Delete them and assign the constant directly. compositeAlpha is a surface property that does not change across swapchain recreation, so select it once at construction instead of re-deriving it (with another heap-allocated vector) on every resize configure. The vkQueueWaitIdle before recreation is left intact as required. Co-Authored-By: Claude Opus 4.8 --- implementations/Crafter.Graphics-Window.cpp | 52 +++++++++------------ interfaces/Crafter.Graphics-Window.cppm | 5 ++ 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/implementations/Crafter.Graphics-Window.cpp b/implementations/Crafter.Graphics-Window.cpp index 411ffb1..ae8c029 100644 --- a/implementations/Crafter.Graphics-Window.cpp +++ b/implementations/Crafter.Graphics-Window.cpp @@ -405,6 +405,26 @@ Window::Window(std::uint32_t width, std::uint32_t height) : width(width), height colorFormat = selectedFormat.format; colorSpace = selectedFormat.colorSpace; + // Select a supported composite alpha format (not all devices support alpha + // opaque). This is a surface property, so pick it once here rather than on + // every CreateSwapchain. Simply select the first available. + { + VkSurfaceCapabilitiesKHR surfCaps; + Device::CheckVkResult(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Device::physDevice, vulkanSurface, &surfCaps)); + const VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[] = { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, + }; + for (const VkCompositeAlphaFlagBitsKHR compositeAlphaFlag : compositeAlphaFlags) { + if (surfCaps.supportedCompositeAlpha & compositeAlphaFlag) { + compositeAlpha = compositeAlphaFlag; + break; + } + } + } + CreateSwapchain(); VkCommandBufferAllocateInfo cmdBufAllocateInfo {}; @@ -896,18 +916,6 @@ void Window::CreateSwapchain() } - // Select a present mode for the swapchain - uint32_t presentModeCount; - Device::CheckVkResult(vkGetPhysicalDeviceSurfacePresentModesKHR(Device::physDevice, vulkanSurface, &presentModeCount, NULL)); - assert(presentModeCount > 0); - - std::vector presentModes(presentModeCount); - Device::CheckVkResult(vkGetPhysicalDeviceSurfacePresentModesKHR(Device::physDevice, vulkanSurface, &presentModeCount, presentModes.data())); - - // The VK_PRESENT_MODE_FIFO_KHR mode must always be present as per spec - // This mode waits for the vertical blank ("v-sync") - VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; - // Find the transformation of the surface VkSurfaceTransformFlagsKHR preTransform; if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) @@ -920,22 +928,6 @@ void Window::CreateSwapchain() preTransform = surfCaps.currentTransform; } - // Find a supported composite alpha format (not all devices support alpha opaque) - VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - // Simply select the first composite alpha format available - std::vector compositeAlphaFlags = { - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, - VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, - VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, - }; - for (auto& compositeAlphaFlag : compositeAlphaFlags) { - if (surfCaps.supportedCompositeAlpha & compositeAlphaFlag) { - compositeAlpha = compositeAlphaFlag; - break; - }; - } - VkSwapchainCreateInfoKHR swapchainCI = {}; swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainCI.surface = vulkanSurface; @@ -948,7 +940,9 @@ void Window::CreateSwapchain() swapchainCI.imageArrayLayers = 1; swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainCI.queueFamilyIndexCount = 0; - swapchainCI.presentMode = swapchainPresentMode; + // VK_PRESENT_MODE_FIFO_KHR ("v-sync") is guaranteed available per spec, so + // it is used unconditionally — no present-mode enumeration is needed. + swapchainCI.presentMode = VK_PRESENT_MODE_FIFO_KHR; // Setting oldSwapChain to the saved handle of the previous swapchain aids in resource reuse and makes sure that we can still present already acquired images swapchainCI.oldSwapchain = oldSwapchain; // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the surface area diff --git a/interfaces/Crafter.Graphics-Window.cppm b/interfaces/Crafter.Graphics-Window.cppm index 9068267..24773a6 100644 --- a/interfaces/Crafter.Graphics-Window.cppm +++ b/interfaces/Crafter.Graphics-Window.cppm @@ -253,6 +253,11 @@ export namespace Crafter { VkSwapchainKHR swapChain = VK_NULL_HANDLE; VkFormat colorFormat; VkColorSpaceKHR colorSpace; + // Supported composite-alpha mode for vulkanSurface. A surface property + // that does not change across swapchain recreation, so it is selected + // once at construction rather than re-derived on every CreateSwapchain + // (i.e. on every resize configure). + VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; VkImage images[numFrames]; VkImageViewCreateInfo imageViews[numFrames]; // Tracks whether each swapchain image has been rendered (and thus -- 2.54.0