summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/renderer/vulkan.rs118
1 files changed, 110 insertions, 8 deletions
diff --git a/src/renderer/vulkan.rs b/src/renderer/vulkan.rs
index 325ad5e..6e2c806 100644
--- a/src/renderer/vulkan.rs
+++ b/src/renderer/vulkan.rs
@@ -6,6 +6,8 @@ use winit::{
error as werror,
event::{DeviceEvent, DeviceId, Event, WindowEvent},
event_loop::{ActiveEventLoop, ControlFlow, EventLoop},
+ raw_window_handle::HasDisplayHandle,
+ raw_window_handle::HasWindowHandle,
window::{Window, WindowId},
};
@@ -71,33 +73,91 @@ impl VulkanRenderer {
}
unsafe fn recreate_swapchain(&mut self) -> Result<(), MainError> {
+ dbg!("start recreating");
+
unsafe {
if let Some(device) = &self.device {
device.device_wait_idle()?;
}
+ dbg!("before destroy swapchain");
+
self.destroy_swapchain();
+ dbg!("after destroy swapchain");
+
+ // --- Destroy and recreate the Vulkan surface ---
+ if let (Some(instance), Some(window)) = (&self.instance, &self.window) {
+ dbg!(
+ "Creating new surface (macOS workaround - skipping old surface destruction)..."
+ );
+ // IMPORTANT: We are intentionally skipping
+ // `instance.destroy_surface_khr(self.data.surface,
+ // None);` and the `is_null()` check for the old
+ // surface here.
+ //
+ // On macOS, the existing surface handle often becomes
+ // invalid after a resize event even if its value is
+ // not null, causing a crash upon explicit
+ // destruction.
+ //
+ // A new surface will be created, and the old,
+ // implicitly invalidated one will be cleaned up when
+ // the VkInstance is destroyed at application exit.
+
+ // dbg!("Creating new surface...");
+
+ let window_handle = window.window_handle().unwrap();
+ let display_handle = window.display_handle().unwrap();
+
+ dbg!(&display_handle);
+ dbg!(&window_handle);
+
+ // Use vulkanalia::window::create_surface with the current window handles
+ self.data.surface = vw::create_surface(instance, &display_handle, &window_handle)?;
+ dbg!("New surface created.");
+ } else {
+ // This case should ideally not be reached if the application is properly initialized.
+ panic!("Instance or Window is None during surface recreation");
+ }
+ // -- END --
+
if let (Some(device), Some(instance), Some(window)) =
(&self.device, &self.instance, &self.window)
{
+ dbg!("before create_swapchain");
create_swapchain(window, instance, device, &mut self.data)?;
+ dbg!("after create_swapchain");
+ dbg!("before create_swapchain_image_views");
create_swapchain_image_views(device, &mut self.data)?;
+ dbg!("after create_swapchain_image_views");
+ dbg!("before create_render_pass");
create_render_pass(instance, device, &mut self.data)?;
+ dbg!("after create_render_pass");
+ dbg!("before create_pipeline");
create_pipeline(device, &mut self.data)?;
+ dbg!("after create_pipeline");
+ dbg!("before create_framebuffers");
create_framebuffers(device, &mut self.data)?;
+ dbg!("after create_framebuffers");
+ dbg!("before create_command_buffers");
create_command_buffers(device, &mut self.data)?;
+ dbg!("after create_command_buffers");
}
+ dbg!("after create groups");
+
self.data
.images_in_flight
.resize(self.data.swapchain_images.len(), vk::Fence::null());
+ dbg!("end recreating");
+
Ok(())
}
}
@@ -142,23 +202,32 @@ impl VulkanRenderer {
vk::Fence::null(),
);
+ dbg!("Acquired next image");
+
let image_index = match acquire_image_result {
Ok((image_index, _)) => image_index,
Err(vk::ErrorCode::OUT_OF_DATE_KHR) => return self.recreate_swapchain(),
Err(code) => return Err(code.into()),
};
+ dbg!("Image index obtained", image_index);
+
if !self.data.images_in_flight[image_index as usize].is_null() {
+ dbg!("Image in flight is not null");
device.wait_for_fences(
&[self.data.images_in_flight[image_index as usize]],
true,
u64::MAX,
)?;
+
+ dbg!("Waited for image in flight fence");
}
self.data.images_in_flight[image_index as usize] =
self.data.in_flight_fences[self.frame];
+ dbg!("Updated images_in_flight");
+
let waiting_sps = [self.data.image_available_sp[self.frame]];
let waiting_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
@@ -172,6 +241,7 @@ impl VulkanRenderer {
.command_buffers(&command_buffer)
.signal_semaphores(&render_sps);
+ dbg!("Submitting queue");
device.reset_fences(&[self.data.in_flight_fences[self.frame]])?;
device.queue_submit(
@@ -179,6 +249,7 @@ impl VulkanRenderer {
&[submit_info],
self.data.in_flight_fences[self.frame],
)?;
+ dbg!("Queue submitted");
let swapchains = [self.data.swapchain];
@@ -189,7 +260,9 @@ impl VulkanRenderer {
.swapchains(&swapchains)
.image_indices(&image_indices);
+ dbg!("Presenting queue");
let present_result = device.queue_present_khr(self.data.pqueue, &presentation_info);
+ dbg!("Queue presented");
if self.resized
|| matches!(
@@ -197,14 +270,18 @@ impl VulkanRenderer {
Ok(vk::SuccessCode::SUBOPTIMAL_KHR) | Err(vk::ErrorCode::OUT_OF_DATE_KHR)
)
{
+ dbg!("Recreating swapchain due to resize/suboptimal");
self.resized = false;
self.recreate_swapchain()?;
} else if let Err(e) = present_result {
+ dbg!("Present result error", &e);
return Err(e.into());
}
self.frame = (self.frame + 1).rem_euclid(MAX_FRAMES_IN_FLIGHT);
+
+ dbg!("Render function finished successfully");
}
Ok(())
@@ -246,7 +323,7 @@ impl VulkanRenderer {
unsafe fn handle_resize(&mut self, new_size: PhysicalSize<u32>) {
// recreate swapchain and framebuffers
unsafe {
- // self.recreate_swapchain().unwrap();
+ self.recreate_swapchain().unwrap();
}
println!("Window resized to {:?}", new_size);
@@ -316,6 +393,8 @@ impl ApplicationHandler for VulkanRenderer {
self.data = data;
}
+
+ dbg!();
}
fn window_event(
@@ -337,15 +416,20 @@ impl ApplicationHandler for VulkanRenderer {
// self.present();
unsafe {
+ dbg!();
self.render().unwrap();
}
self.window.as_ref().unwrap().request_redraw();
}
WindowEvent::Resized(new_size) => unsafe {
+ dbg!("before handle resize");
self.handle_resize(new_size);
+ dbg!("after handle resize");
self.window.as_ref().unwrap().request_redraw();
+
+ dbg!("after request redraw");
},
_ => (),
}
@@ -653,16 +737,28 @@ unsafe fn create_swapchain(
let image_count = (min_image_count + 1).clamp(min_image_count, max_image_count);
- let mut queue_family_indices = Vec::new();
-
- let image_sharing_mode = if indices.graphics != indices.presentation {
- queue_family_indices.extend([indices.graphics, indices.presentation]);
-
- vk::SharingMode::CONCURRENT
+ // let mut queue_family_indices = Vec::new();
+
+ let (image_sharing_mode, queue_family_indices) = if indices.graphics != indices.presentation
+ {
+ // If graphics and presentation queues are different,
+ // use CONCURRENT mode and provide both queue family
+ // indices.
+ (
+ vk::SharingMode::CONCURRENT,
+ vec![indices.graphics, indices.presentation],
+ )
} else {
- vk::SharingMode::EXCLUSIVE
+ // If graphics and presentation queues are the same,
+ // use EXCLUSIVE mode.
+ //
+ // For EXCLUSIVE mode, `queue_family_index_count` MUST
+ // be 0.
+ (vk::SharingMode::EXCLUSIVE, vec![])
};
+ dbg!("before info");
+
let info = vk::SwapchainCreateInfoKHR::builder()
.surface(data.surface)
.min_image_count(image_count)
@@ -679,13 +775,19 @@ unsafe fn create_swapchain(
.clipped(true)
.old_swapchain(vk::SwapchainKHR::null());
+ dbg!("before create khr");
+
data.swapchain = device.create_swapchain_khr(&info, None)?;
+ dbg!("before get image khr");
+
data.swapchain_images = device.get_swapchain_images_khr(data.swapchain)?;
data.swapchain_format = format.format;
data.swapchain_extent = extent;
+ dbg!("end of create_swapchain");
+
Ok(())
}
}