diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index 2a7d755..78cb04a 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -357,9 +357,10 @@ impl FilterChainVulkan { vulkan: &Vulkan, passes: Vec, semantics: &ShaderSemantics, - images: u32, + frames_in_flight: u32, ) -> error::Result> { let mut filters = Vec::new(); + let frames_in_flight = std::cmp::max(1, frames_in_flight); // initialize passes for (index, (config, mut source, mut reflect)) in passes.into_iter().enumerate() { @@ -399,13 +400,13 @@ impl FilterChainVulkan { &vulkan.pipeline_cache, &spirv_words, &reflection, - images, + frames_in_flight, )?; let ubo_ring = VkUboRing::new( &vulkan.device, &vulkan.memory_properties, - images as usize, + frames_in_flight as usize, ubo_size, )?; // shader_vulkan: 2026 @@ -419,6 +420,7 @@ impl FilterChainVulkan { config, graphics_pipeline, ubo_ring, + frames_in_flight }); } @@ -702,14 +704,12 @@ impl FilterChainVulkan { let target = &self.output_framebuffers[index]; // todo: use proper mode - // todo: the output framebuffers can only be dropped after command queue submission. - let out = RenderTarget { x: 0.0, y: 0.0, mvp: DEFAULT_MVP, output: OutputImage::new( - &self.vulkan, /*&pass.graphics_pipeline.render_pass,*/ + &self.vulkan, target.image.clone(), )?, }; diff --git a/librashader-runtime-vk/src/filter_pass.rs b/librashader-runtime-vk/src/filter_pass.rs index 330a510..cd80c2e 100644 --- a/librashader-runtime-vk/src/filter_pass.rs +++ b/librashader-runtime-vk/src/filter_pass.rs @@ -29,6 +29,7 @@ pub struct FilterPass { pub config: ShaderPassConfig, pub graphics_pipeline: VulkanGraphicsPipeline, pub ubo_ring: VkUboRing, + pub frames_in_flight: u32, } impl FilterPass { @@ -82,7 +83,7 @@ impl FilterPass { source: &InputImage, output: &RenderTarget, ) -> error::Result<()> { - let descriptor = *&self.graphics_pipeline.layout.descriptor_sets[0]; + let descriptor = *&self.graphics_pipeline.layout.descriptor_sets[(frame_count % self.frames_in_flight) as usize]; self.build_semantics( pass_index, @@ -135,7 +136,7 @@ impl FilterPass { vk::PipelineBindPoint::GRAPHICS, self.graphics_pipeline.layout.layout, 0, - &[self.graphics_pipeline.layout.descriptor_sets[0]], + &[descriptor], &[], ); diff --git a/librashader-runtime-vk/src/hello_triangle/mod.rs b/librashader-runtime-vk/src/hello_triangle/mod.rs index d054634..e20a5ef 100644 --- a/librashader-runtime-vk/src/hello_triangle/mod.rs +++ b/librashader-runtime-vk/src/hello_triangle/mod.rs @@ -30,6 +30,7 @@ use winit::platform::windows::EventLoopBuilderExtWindows; const WINDOW_TITLE: &'static str = "librashader Vulkan"; const WINDOW_WIDTH: u32 = 800; const WINDOW_HEIGHT: u32 = 600; +const MAX_FRAMES_IN_FLIGHT: usize = 3; struct VulkanWindow; @@ -136,16 +137,22 @@ impl VulkanWindow { } fn draw_frame(frame: usize, vulkan: &VulkanDraw, filter: &mut FilterChainVulkan) { + + let index = frame % MAX_FRAMES_IN_FLIGHT; + let in_flight = vulkan.sync.in_flight[index]; + let image_available = vulkan.sync.image_available[index]; + let render_finished = vulkan.sync.render_finished[index]; + unsafe { vulkan .base .device - .wait_for_fences(&[vulkan.sync.in_flight], true, u64::MAX) + .wait_for_fences(&[in_flight], true, u64::MAX) .unwrap(); vulkan .base .device - .reset_fences(&[vulkan.sync.in_flight]) + .reset_fences(&[in_flight]) .unwrap(); let (swapchain_index, _) = vulkan @@ -154,12 +161,12 @@ impl VulkanWindow { .acquire_next_image( vulkan.swapchain.swapchain, u64::MAX, - vulkan.sync.image_available, + image_available, vk::Fence::null(), ) .unwrap(); - let cmd = vulkan.render_command_pool.buffers[swapchain_index as usize]; + let cmd = vulkan.render_command_pool.buffers[index]; let framebuffer = vulkan.render_framebuffers[swapchain_index as usize].framebuffer; let framebuffer_image = vulkan.swapchain.render_images[swapchain_index as usize].0; let swapchain_image = vulkan.swapchain.swapchain_images[swapchain_index as usize]; @@ -309,8 +316,8 @@ impl VulkanWindow { let submit_info = vk::SubmitInfo::builder() .wait_dst_stage_mask(&[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]) - .wait_semaphores(&[vulkan.sync.image_available]) - .signal_semaphores(&[vulkan.sync.render_finished]) + .wait_semaphores(&[image_available]) + .signal_semaphores(&[render_finished]) .command_buffers(&[cmd]) .build(); @@ -320,12 +327,12 @@ impl VulkanWindow { .queue_submit( vulkan.base.graphics_queue, &[submit_info], - vulkan.sync.in_flight, + in_flight, ) .expect("failed to submit queue"); let present_info = vk::PresentInfoKHR::builder() - .wait_semaphores(&[vulkan.sync.render_finished]) + .wait_semaphores(&[render_finished]) .swapchains(&[vulkan.swapchain.swapchain]) .image_indices(&[swapchain_index]) .build(); @@ -336,8 +343,10 @@ impl VulkanWindow { .queue_present(vulkan.base.graphics_queue, &present_info) .unwrap(); - vulkan.base.device.device_wait_idle().unwrap(); - drop(intermediates) + //oops i pooped my pants + std::mem::forget(intermediates); + // vulkan.base.device.device_wait_idle().unwrap(); + // drop(intermediates) } } } @@ -395,10 +404,10 @@ pub fn main(vulkan: VulkanBase, filter_chain: FilterChainVulkan) { ) } - let swapchain_command_pool = VulkanCommandPool::new(&vulkan, 3).unwrap(); - let render_command_pool = VulkanCommandPool::new(&vulkan, 3).unwrap(); + let swapchain_command_pool = VulkanCommandPool::new(&vulkan, MAX_FRAMES_IN_FLIGHT as u32).unwrap(); + let render_command_pool = VulkanCommandPool::new(&vulkan, MAX_FRAMES_IN_FLIGHT as u32).unwrap(); - let sync = SyncObjects::new(&vulkan.device).unwrap(); + let sync = SyncObjects::new(&vulkan.device, MAX_FRAMES_IN_FLIGHT).unwrap(); let vulkan = VulkanDraw { surface, diff --git a/librashader-runtime-vk/src/hello_triangle/syncobjects.rs b/librashader-runtime-vk/src/hello_triangle/syncobjects.rs index 877f47c..2302a87 100644 --- a/librashader-runtime-vk/src/hello_triangle/syncobjects.rs +++ b/librashader-runtime-vk/src/hello_triangle/syncobjects.rs @@ -2,24 +2,28 @@ use ash::prelude::VkResult; use ash::vk; pub struct SyncObjects { - pub image_available: vk::Semaphore, - pub render_finished: vk::Semaphore, - pub in_flight: vk::Fence, + pub image_available: Vec, + pub render_finished: Vec, + pub in_flight: Vec, } impl SyncObjects { - pub fn new(device: &ash::Device) -> VkResult { + pub fn new(device: &ash::Device, frames_in_flight: usize) -> VkResult { unsafe { - let image_available = - device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?; - let render_finished = - device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?; - let in_flight = device.create_fence( - &vk::FenceCreateInfo::builder() - .flags(vk::FenceCreateFlags::SIGNALED) - .build(), - None, - )?; + let mut image_available = Vec::new(); + let mut render_finished = Vec::new(); + let mut in_flight = Vec::new(); + + for _ in 0..frames_in_flight { + image_available.push(device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?); + render_finished.push(device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?); + in_flight.push(device.create_fence( + &vk::FenceCreateInfo::builder() + .flags(vk::FenceCreateFlags::SIGNALED) + .build(), + None, + )?) + } Ok(SyncObjects { image_available,