From b82ab62675256f47f3476421fddcbd4cebf09b64 Mon Sep 17 00:00:00 2001 From: Jordan Halase Date: Fri, 8 Nov 2019 10:08:18 -0600 Subject: Query surfaceCapabilities every new swapchain --- main.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/main.c b/main.c index 794a0dd..4a32cd0 100755 --- a/main.c +++ b/main.c @@ -223,7 +223,6 @@ struct RenderVulkan { VkInstance instance; VkDebugReportCallbackEXT debugCallback; VkSurfaceKHR surface; - VkSurfaceCapabilitiesKHR surfaceCapabilities; VkSurfaceFormatKHR surfaceFormat; VkPresentModeKHR presentMode; VkPhysicalDeviceProperties deviceProperties; // TODO: Make this a pointer. It's really big. @@ -1242,15 +1241,9 @@ static bool isPresentModeSupported(const VkPresentModeKHR *const presentModes, /** Configure the surface for the currently opened device. */ int rvkConfigureSurface(struct RenderVulkan *vk) { - VkSurfaceCapabilitiesKHR surfaceCapabilities; VkSurfaceFormatKHR *surfaceFormats; VkPresentModeKHR *presentModes; VkResult result; - if ((result = vk->api->vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - vk->physicalDevice, vk->surface, &surfaceCapabilities))) { - rvkSetErrMsg(vk, "Could not get surface capabilities: %d", result); - return -1; - } uint32_t nFormats; vk->api->vkGetPhysicalDeviceSurfaceFormatsKHR(vk->physicalDevice, vk->surface, &nFormats, NULL); if (!nFormats) { @@ -1317,21 +1310,45 @@ int rvkConfigureSurface(struct RenderVulkan *vk) free(presentModes); vk->presentMode = presentMode; printf("Using present mode:\t\t`%s`\t(%d)\n", strPresentMode(presentMode), presentMode); - vk->surfaceCapabilities = surfaceCapabilities; return 0; } static int rvkCreateRawSwapchain(struct RenderVulkan *vk, uint32_t width, uint32_t height) { - // FIXME: We actually need a new surfaceCapabilities for every new swapchain. - //width = CLAMP(width, vk->surfaceCapabilities.minImageExtent.width, vk->surfaceCapabilities.maxImageExtent.width); - //height = CLAMP(height, vk->surfaceCapabilities.minImageExtent.height, vk->surfaceCapabilities.maxImageExtent.height); + VkSurfaceCapabilitiesKHR surfaceCapabilities; + VkResult result; + if ((result = vk->api->vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + vk->physicalDevice, vk->surface, &surfaceCapabilities))) { + rvkSetErrMsg(vk, "Could not get surface capabilities: %d", result); + return -1; + } + + /* The current window size isn't always equivalent to the Vulkan surface + * drawable size, which can be observed when resizing the window on the + * fly with some devices and drivers. I suspect this is the result of a + * race condition between the window size and the drawable size, with + * the reported window size lagging behind the drawable size, or that + * the surface is proactively resized internally by the Vulkan driver + * before the window system finalizes this new size. + * + * This has been observed on multiple platforms and seems inherent to + * the window system. + * + * Nonetheless, clamping the returned window size to the minimum and + * maximum surface capabilities seems to fix the problem completely. + * + * Furthermore, it may be possible that we don't even need to query the + * window system for its size at all, and could possibly simply use the + * `currentExtent` of the `VkSurfaceCapabilitiesKHR`. + */ + width = CLAMP(width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width); + height = CLAMP(height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height); vk->swapchain->extent.width = width; vk->swapchain->extent.height = height; - vk->swapchain->nImages = vk->surfaceCapabilities.minImageCount; - //vk->swapchain->nImages = vk->surfaceCapabilities.maxImageCount; + vk->swapchain->nImages = surfaceCapabilities.minImageCount; + //vk->swapchain->nImages = surfaceCapabilities.maxImageCount; VkSwapchainCreateInfoKHR createInfo = { 0 }; createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; @@ -1342,14 +1359,13 @@ static int rvkCreateRawSwapchain(struct RenderVulkan *vk, uint32_t width, uint32 createInfo.imageArrayLayers = 1; createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - createInfo.preTransform = vk->surfaceCapabilities.currentTransform; + createInfo.preTransform = surfaceCapabilities.currentTransform; createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; createInfo.presentMode = vk->presentMode; createInfo.clipped = VK_TRUE; if (vk->swapchain->old) { createInfo.oldSwapchain = vk->swapchain->old->rawSwapchain; } - VkResult result; if ((result = vk->dev->vkCreateSwapchainKHR(vk->device, &createInfo, ALLOC_VK, &vk->swapchain->rawSwapchain))) { rvkSetErrMsg(vk, "Could not create swapchain: %d", result); return -1; -- cgit v1.2.1