Fixed framebuffer resize issue on wayland(gpu gives 0xFFFFFFFF as size for 'pick one')

main
noah metz 2026-07-30 01:23:15 -06:00
parent d3691bd146
commit 446361f9f1
3 changed files with 39 additions and 10 deletions

@ -139,6 +139,11 @@ typedef struct RenderContextStruct {
VkExtent2D swapchain_extent; VkExtent2D swapchain_extent;
VkSwapchainKHR swapchain; VkSwapchainKHR swapchain;
// Latest framebuffer size in pixels, updated by the GLFW framebuffer-size
// callback. Used by choose_swapchain_extent when the surface reports
// currentExtent = 0xFFFFFFFF (Wayland).
VkExtent2D framebuffer_size;
uint32_t swapchain_image_count; uint32_t swapchain_image_count;
VkImage* swapchain_images; VkImage* swapchain_images;
VkImageView* swapchain_image_views; VkImageView* swapchain_image_views;

@ -4,6 +4,12 @@
#include "draw.h" #include "draw.h"
#include <stdlib.h> #include <stdlib.h>
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window);
context->render.framebuffer_size.width = (uint32_t)width;
context->render.framebuffer_size.height = (uint32_t)height;
}
void text_callback(GLFWwindow* window, unsigned int codepoint) { void text_callback(GLFWwindow* window, unsigned int codepoint) {
ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window);
if(context->ui.active_container != NULL if(context->ui.active_container != NULL
@ -288,6 +294,7 @@ int run_app(
glfwSetScrollCallback(context->window, scroll_callback); glfwSetScrollCallback(context->window, scroll_callback);
glfwSetCursorPosCallback(context->window, cursor_callback); glfwSetCursorPosCallback(context->window, cursor_callback);
glfwSetCharCallback(context->window, text_callback); glfwSetCharCallback(context->window, text_callback);
glfwSetFramebufferSizeCallback(context->window, framebuffer_size_callback);
if(init_vulkan(context->window, &context->render) != VK_SUCCESS) return -2; if(init_vulkan(context->window, &context->render) != VK_SUCCESS) return -2;

@ -277,7 +277,7 @@ VkResult create_logical_device(
graphics_queue->family = idx; graphics_queue->family = idx;
graphics_queue->index = 0; graphics_queue->index = 0;
} else if (present_support && (present_queue->family == 0xFFFFFFFF)) { } else if (present_support && (present_queue->family == 0xFFFFFFFF)) {
graphics_queue->family = idx; present_queue->family = idx;
present_queue->index = 0; present_queue->index = 0;
} }
} }
@ -358,10 +358,10 @@ VkResult create_logical_device(
queue_create_info[1].queueCount = 1; queue_create_info[1].queueCount = 1;
queue_create_info[1].pQueuePriorities = &default_queue_priority; queue_create_info[1].pQueuePriorities = &default_queue_priority;
queue_create_info[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_create_info[2].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info[1].queueFamilyIndex = transfer_queue->family; queue_create_info[2].queueFamilyIndex = transfer_queue->family;
queue_create_info[1].queueCount = 1; queue_create_info[2].queueCount = 1;
queue_create_info[1].pQueuePriorities = &default_queue_priority; queue_create_info[2].pQueuePriorities = &default_queue_priority;
} }
VkPhysicalDeviceDynamicRenderingFeatures dynamic_rendering = { VkPhysicalDeviceDynamicRenderingFeatures dynamic_rendering = {
@ -538,8 +538,20 @@ VkPresentModeKHR choose_present_mode(SwapchainDetails swapchain_details) {
return VK_PRESENT_MODE_FIFO_KHR; return VK_PRESENT_MODE_FIFO_KHR;
} }
VkExtent2D choose_swapchain_extent(SwapchainDetails swapchain_details) { VkExtent2D choose_swapchain_extent(SwapchainDetails swapchain_details, VkExtent2D framebuffer_size) {
return swapchain_details.capabilities.currentExtent; VkSurfaceCapabilitiesKHR caps = swapchain_details.capabilities;
// 0xFFFFFFFF means "app chooses" (common on Wayland). Fall back to the
// caller-supplied framebuffer size and clamp to the surface's allowed range.
if(caps.currentExtent.width != 0xFFFFFFFF) {
return caps.currentExtent;
}
VkExtent2D extent = framebuffer_size;
if(extent.width < caps.minImageExtent.width) extent.width = caps.minImageExtent.width;
if(extent.height < caps.minImageExtent.height) extent.height = caps.minImageExtent.height;
if(extent.width > caps.maxImageExtent.width) extent.width = caps.maxImageExtent.width;
if(extent.height > caps.maxImageExtent.height) extent.height = caps.maxImageExtent.height;
return extent;
} }
VkResult create_swapchain( VkResult create_swapchain(
@ -570,7 +582,7 @@ VkResult create_swapchain(
.imageArrayLayers = 1, .imageArrayLayers = 1,
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.preTransform = capabilities.currentTransform, .preTransform = capabilities.currentTransform,
.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
.presentMode = present_mode, .presentMode = present_mode,
.clipped = VK_TRUE, .clipped = VK_TRUE,
.oldSwapchain = old_swapchain, .oldSwapchain = old_swapchain,
@ -874,6 +886,11 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) {
GLFWmonitor** monitors = glfwGetMonitors(&monitor_count); GLFWmonitor** monitors = glfwGetMonitors(&monitor_count);
glfwGetMonitorContentScale(monitors[0], &context->window_scale[0], &context->window_scale[1]); glfwGetMonitorContentScale(monitors[0], &context->window_scale[0], &context->window_scale[1]);
int fb_width, fb_height;
glfwGetFramebufferSize(window, &fb_width, &fb_height);
context->framebuffer_size.width = (uint32_t)fb_width;
context->framebuffer_size.height = (uint32_t)fb_height;
VK_RESULT(create_instance(&context->instance)); VK_RESULT(create_instance(&context->instance));
VK_RESULT(create_debug_messenger(context->instance, &context->debug_messenger)); VK_RESULT(create_debug_messenger(context->instance, &context->debug_messenger));
@ -916,7 +933,7 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) {
context->swapchain_format = choose_swapchain_format(context->swapchain_details); context->swapchain_format = choose_swapchain_format(context->swapchain_details);
context->swapchain_present_mode = choose_present_mode(context->swapchain_details); context->swapchain_present_mode = choose_present_mode(context->swapchain_details);
context->swapchain_extent = choose_swapchain_extent(context->swapchain_details); context->swapchain_extent = choose_swapchain_extent(context->swapchain_details, context->framebuffer_size);
context->framebuffer_recreated = true; context->framebuffer_recreated = true;
context->swapchain = VK_NULL_HANDLE; context->swapchain = VK_NULL_HANDLE;
VK_RESULT(create_swapchain( VK_RESULT(create_swapchain(
@ -1277,7 +1294,7 @@ VkResult recreate_framebuffer(RenderContext* gpu) {
&gpu->swapchain_details)) &gpu->swapchain_details))
gpu->swapchain_format = choose_swapchain_format(gpu->swapchain_details); gpu->swapchain_format = choose_swapchain_format(gpu->swapchain_details);
gpu->swapchain_present_mode = choose_present_mode(gpu->swapchain_details); gpu->swapchain_present_mode = choose_present_mode(gpu->swapchain_details);
gpu->swapchain_extent = choose_swapchain_extent(gpu->swapchain_details); gpu->swapchain_extent = choose_swapchain_extent(gpu->swapchain_details, gpu->framebuffer_size);
VK_RESULT(create_swapchain( VK_RESULT(create_swapchain(
gpu->device, gpu->device,
gpu->swapchain_format, gpu->swapchain_format,