From 636c44b29f693130a18e71034223b27ab002d2f6 Mon Sep 17 00:00:00 2001 From: Serkyo Date: Thu, 30 Apr 2026 15:16:55 +0200 Subject: [PATCH] fix(renderer): handle u32::MAX swapchain extent Fixed a crash where the renderer would attempt to create a swapchain with u32::MAX dimensions when the OS didn't provide a preferred extent. Updated Renderer::new to accept window dimensions and use them as a fallback. Also renamed InstanceCreateFailed to VulkanError for better generality. --- Cargo.lock | 1 + crates/client/src/main.rs | 11 +++++++++-- crates/renderer/src/error.rs | 4 ++-- crates/renderer/src/lib.rs | 21 ++++++++++++++++++--- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7593380..277d568 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1054,6 +1054,7 @@ name = "renderer" version = "0.1.0" dependencies = [ "ash", + "ash-window", "raw-window-handle", "thiserror 2.0.18", "tracing", diff --git a/crates/client/src/main.rs b/crates/client/src/main.rs index 5fd098b..1ba5349 100644 --- a/crates/client/src/main.rs +++ b/crates/client/src/main.rs @@ -31,8 +31,15 @@ impl ApplicationHandler for App { let required_extensions = ash_window::enumerate_required_extensions(display_handle) .expect("Failed to enumerate required extensions"); - let renderer = renderer::Renderer::new(display_handle, window_handle, required_extensions) - .expect("Failed to initialize Vulkan renderer"); + let size = self.window.as_ref().unwrap().inner_size(); + let renderer = renderer::Renderer::new( + display_handle, + window_handle, + size.width, + size.height, + required_extensions, + ) + .expect("Failed to initialize Vulkan renderer"); self.renderer = Some(renderer); } diff --git a/crates/renderer/src/error.rs b/crates/renderer/src/error.rs index 6f44e31..e6132db 100644 --- a/crates/renderer/src/error.rs +++ b/crates/renderer/src/error.rs @@ -4,8 +4,8 @@ use thiserror::Error; pub enum RendererError { #[error("Failed to load Vulkan library")] LoadFailed(#[from] ash::LoadingError), - #[error("Failed to create Vulkan instance")] - InstanceCreateFailed(#[from] ash::vk::Result), + #[error("Vulkan error")] + VulkanError(#[from] ash::vk::Result), #[error("No suitable GPU found")] NoSuitableGpu, } \ No newline at end of file diff --git a/crates/renderer/src/lib.rs b/crates/renderer/src/lib.rs index 95981b7..3657bdf 100644 --- a/crates/renderer/src/lib.rs +++ b/crates/renderer/src/lib.rs @@ -1,7 +1,7 @@ pub mod error; use std::ffi::{CStr, c_char}; -use ash::{Device, Entry, Instance, ext, khr, vk::{self, SurfaceKHR}}; +use ash::{Device, Entry, Instance, ext, khr, vk}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use tracing::{debug, error, info, warn}; @@ -52,6 +52,8 @@ impl Renderer { pub fn new( display_handle: RawDisplayHandle, window_handle: RawWindowHandle, + width: u32, + height: u32, required_extensions: &[*const c_char], ) -> Result { let entry = unsafe { Entry::load() }?; @@ -117,7 +119,9 @@ impl Renderer { // Create the logical device let (device, graphics_queue) = Self::create_logical_device(&instance, physical_device, graphics_queue_index)?; - let (swapchain_loader, swapchain, swapchain_images, swapchain_format, swapchain_extent) = Self::create_swapchain(&instance, physical_device, &device, &surface_loader, surface)?; + // Create the swapchain + let (swapchain_loader, swapchain, swapchain_images, swapchain_format, swapchain_extent) = + Self::create_swapchain(&instance, physical_device, &device, &surface_loader, surface, width, height)?; Ok(Self { _entry: entry, @@ -242,6 +246,8 @@ impl Renderer { device: &Device, surface_loader: &khr::surface::Instance, surface: vk::SurfaceKHR, + width: u32, + height: u32, ) -> Result< (khr::swapchain::Device, vk::SwapchainKHR, Vec, vk::Format, vk::Extent2D), RendererError, @@ -262,7 +268,16 @@ impl Renderer { .find(|&m| m == vk::PresentModeKHR::MAILBOX) .unwrap_or(vk::PresentModeKHR::FIFO); - let extent = surface_capabilities.current_extent; + // 3. Match the window resolution + // If the surface says u32::MAX, it means we can pick any size within bounds. + let extent = if surface_capabilities.current_extent.width != u32::MAX { + surface_capabilities.current_extent + } else { + vk::Extent2D { + width: width.clamp(surface_capabilities.min_image_extent.width, surface_capabilities.max_image_extent.width), + height: height.clamp(surface_capabilities.min_image_extent.height, surface_capabilities.max_image_extent.height), + } + }; let mut image_count = surface_capabilities.min_image_count + 1;