summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Halase <jordan@halase.me>2019-11-08 10:08:18 -0600
committerJordan Halase <jordan@halase.me>2019-11-08 10:08:18 -0600
commitb82ab62675256f47f3476421fddcbd4cebf09b64 (patch)
treebaa4b48173415471f28ab13adc69711f8988e4e6
parent9e3b1faeddacb78d342ae630815cb19030846a6f (diff)
Query surfaceCapabilities every new swapchain
-rwxr-xr-xmain.c46
1 files 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;