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.
This commit is contained in:
parent
76450da41f
commit
636c44b29f
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1054,6 +1054,7 @@ name = "renderer"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ash",
|
"ash",
|
||||||
|
"ash-window",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,15 @@ impl ApplicationHandler for App {
|
||||||
let required_extensions = ash_window::enumerate_required_extensions(display_handle)
|
let required_extensions = ash_window::enumerate_required_extensions(display_handle)
|
||||||
.expect("Failed to enumerate required extensions");
|
.expect("Failed to enumerate required extensions");
|
||||||
|
|
||||||
let renderer = renderer::Renderer::new(display_handle, window_handle, required_extensions)
|
let size = self.window.as_ref().unwrap().inner_size();
|
||||||
.expect("Failed to initialize Vulkan renderer");
|
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);
|
self.renderer = Some(renderer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ use thiserror::Error;
|
||||||
pub enum RendererError {
|
pub enum RendererError {
|
||||||
#[error("Failed to load Vulkan library")]
|
#[error("Failed to load Vulkan library")]
|
||||||
LoadFailed(#[from] ash::LoadingError),
|
LoadFailed(#[from] ash::LoadingError),
|
||||||
#[error("Failed to create Vulkan instance")]
|
#[error("Vulkan error")]
|
||||||
InstanceCreateFailed(#[from] ash::vk::Result),
|
VulkanError(#[from] ash::vk::Result),
|
||||||
#[error("No suitable GPU found")]
|
#[error("No suitable GPU found")]
|
||||||
NoSuitableGpu,
|
NoSuitableGpu,
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
use std::ffi::{CStr, c_char};
|
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 raw_window_handle::{RawDisplayHandle, RawWindowHandle};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
|
|
@ -52,6 +52,8 @@ impl Renderer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
display_handle: RawDisplayHandle,
|
display_handle: RawDisplayHandle,
|
||||||
window_handle: RawWindowHandle,
|
window_handle: RawWindowHandle,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
required_extensions: &[*const c_char],
|
required_extensions: &[*const c_char],
|
||||||
) -> Result<Self, RendererError> {
|
) -> Result<Self, RendererError> {
|
||||||
let entry = unsafe { Entry::load() }?;
|
let entry = unsafe { Entry::load() }?;
|
||||||
|
|
@ -117,7 +119,9 @@ impl Renderer {
|
||||||
// Create the logical device
|
// Create the logical device
|
||||||
let (device, graphics_queue) = Self::create_logical_device(&instance, physical_device, graphics_queue_index)?;
|
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 {
|
Ok(Self {
|
||||||
_entry: entry,
|
_entry: entry,
|
||||||
|
|
@ -242,6 +246,8 @@ impl Renderer {
|
||||||
device: &Device,
|
device: &Device,
|
||||||
surface_loader: &khr::surface::Instance,
|
surface_loader: &khr::surface::Instance,
|
||||||
surface: vk::SurfaceKHR,
|
surface: vk::SurfaceKHR,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(khr::swapchain::Device, vk::SwapchainKHR, Vec<vk::Image>, vk::Format, vk::Extent2D),
|
(khr::swapchain::Device, vk::SwapchainKHR, Vec<vk::Image>, vk::Format, vk::Extent2D),
|
||||||
RendererError,
|
RendererError,
|
||||||
|
|
@ -262,7 +268,16 @@ impl Renderer {
|
||||||
.find(|&m| m == vk::PresentModeKHR::MAILBOX)
|
.find(|&m| m == vk::PresentModeKHR::MAILBOX)
|
||||||
.unwrap_or(vk::PresentModeKHR::FIFO);
|
.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;
|
let mut image_count = surface_capabilities.min_image_count + 1;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue