diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index 10b95e4..1c81a5d 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -6,8 +6,8 @@ use crate::samplers::SamplerSet; use crate::texture::{OwnedImage, InputImage, VulkanImage, OwnedImageLayout}; use crate::ubo_ring::VkUboRing; use crate::vulkan_state::VulkanGraphicsPipeline; -use ash::vk::{CommandPoolCreateFlags, PFN_vkGetInstanceProcAddr, Queue, StaticFn}; -use ash::{vk, Device}; +use ash::vk::{CommandPoolCreateFlags, DebugUtilsObjectNameInfoEXT, Handle, PFN_vkGetInstanceProcAddr, Queue, StaticFn}; +use ash::{vk, Device, Entry}; use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_preprocess::ShaderSource; use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; @@ -22,7 +22,9 @@ use librashader_runtime::image::{Image, UVDirection}; use librashader_runtime::uniforms::UniformStorage; use rustc_hash::FxHashMap; use std::error::Error; +use std::ffi::CStr; use std::path::Path; +use ash::extensions::ext::DebugUtils; use crate::draw_quad::DrawQuad; use crate::framebuffer::OutputImage; use crate::render_target::{DEFAULT_MVP, RenderTarget}; @@ -36,6 +38,7 @@ pub struct Vulkan { command_pool: vk::CommandPool, pipeline_cache: vk::PipelineCache, pub(crate) memory_properties: vk::PhysicalDeviceMemoryProperties, + debug: DebugUtils } type ShaderPassMeta = ( @@ -82,6 +85,10 @@ impl TryFrom> for Vulkan { )? }; + let debug = DebugUtils::new(&Entry::from_static_fn(StaticFn { + get_instance_proc_addr: vulkan.get_instance_proc_addr, + }), &instance); + Ok(Vulkan { device, // instance, @@ -89,15 +96,16 @@ impl TryFrom> for Vulkan { command_pool, pipeline_cache, memory_properties: vulkan.memory_properties.clone(), + debug }) } } } -impl TryFrom<(ash::Device, vk::Queue, vk::PhysicalDeviceMemoryProperties)> for Vulkan { +impl TryFrom<(ash::Device, vk::Queue, vk::PhysicalDeviceMemoryProperties, DebugUtils)> for Vulkan { type Error = Box; - fn try_from(value: (Device, Queue, vk::PhysicalDeviceMemoryProperties)) -> error::Result { + fn try_from(value: (Device, Queue, vk::PhysicalDeviceMemoryProperties, DebugUtils)) -> error::Result { unsafe { let device = value.0; @@ -120,6 +128,7 @@ impl TryFrom<(ash::Device, vk::Queue, vk::PhysicalDeviceMemoryProperties)> for V command_pool, pipeline_cache, memory_properties: value.2, + debug: value.3 }) } } @@ -144,8 +153,8 @@ pub(crate) struct FilterCommon { pub samplers: SamplerSet, pub(crate) draw_quad: DrawQuad, - pub output_textures: Box<[Option]>, - pub feedback_textures: Box<[Option]>, + pub output_inputs: Box<[Option]>, + pub feedback_inputs: Box<[Option]>, pub history_textures: Box<[Option]>, pub config: FilterMutable, pub device: ash::Device, @@ -267,8 +276,8 @@ impl FilterChainVulkan { }, draw_quad: DrawQuad::new(&device.device, &device.memory_properties)?, device: device.device.clone(), - output_textures: output_textures.into_boxed_slice(), - feedback_textures: feedback_textures.into_boxed_slice(), + output_inputs: output_textures.into_boxed_slice(), + feedback_inputs: feedback_textures.into_boxed_slice(), history_textures, }, passes: filters, @@ -609,7 +618,7 @@ impl FilterChainVulkan { .iter_mut() .zip(self.history_framebuffers.iter()) { - *texture = Some(image.as_input(filter, wrap_mode)?); + *texture = Some(image.as_input(filter, wrap_mode)); } let original = InputImage { @@ -620,7 +629,10 @@ impl FilterChainVulkan { mip_filter: filter, }; - let mut source = original.clone(); + let mut source = &original; + + // swap output and feedback **before** recording command buffers + std::mem::swap(&mut self.output_framebuffers, &mut self.feedback_framebuffers); // rescale render buffers to ensure all bindings are valid. for (index, pass) in passes.iter_mut().enumerate() { @@ -629,7 +641,7 @@ impl FilterChainVulkan { pass.get_format(), &viewport.output.size, &original, - &source, + source, // todo: need to check **next** pass.config.mipmap_input, None, @@ -640,16 +652,18 @@ impl FilterChainVulkan { pass.get_format(), &viewport.output.size, &original, - &source, + source, // todo: need to check **next** pass.config.mipmap_input, None )?; - if self.common.feedback_textures[index].is_none() { - self.common.feedback_textures[index] = - Some(source.clone()); - } + // self.feedback_framebuffers[index].image.image + // refresh inputs + self.common.feedback_inputs[index] = + Some(self.feedback_framebuffers[index].as_input(pass.config.filter, pass.config.wrap_mode)); + self.common.output_inputs[index] = + Some(self.output_framebuffers[index].as_input(pass.config.filter, pass.config.wrap_mode)); } let passes_len = passes.len(); @@ -657,6 +671,7 @@ impl FilterChainVulkan { for (index, pass) in pass.iter_mut().enumerate() { let target = &self.output_framebuffers[index]; + // todo: use proper mode // todo: the output framebuffers can only be dropped after command queue submission. @@ -668,7 +683,12 @@ impl FilterChainVulkan { target.image.clone())?, }; - pass.draw(cmd, index, &self.common, count as u32, 0, + pass.draw(cmd, index, &self.common, if pass.config.frame_count_mod > 0 { + count % pass.config.frame_count_mod as usize + } else { + count + } as u32 + , 0, viewport, &original, &source, &out)?; if target.max_miplevels > 1 { @@ -677,17 +697,15 @@ impl FilterChainVulkan { out.output.end_pass(cmd); } - source = target.as_input(pass.config.filter, pass.config.wrap_mode)?; - - let feedback = self.common.output_textures[index].replace(source.clone()); + source = &self.common.output_inputs[index].as_ref().unwrap(); intermediates.dispose_outputs(out.output); } // try to hint the optimizer assert_eq!(last.len(), 1); if let Some(pass) = last.iter_mut().next() { - source.filter_mode = pass.config.filter; - source.mip_filter = pass.config.filter; + // source.filter_mode = pass.config.filter; + // source.mip_filter = pass.config.filter; let out = RenderTarget { x: viewport.x, @@ -700,7 +718,7 @@ impl FilterChainVulkan { pass.draw(cmd, passes_len - 1, &self.common, count as u32, - 0, viewport, &original, &source, &out)?; + 0, viewport, &original, source, &out)?; intermediates.dispose_outputs(out.output); } diff --git a/librashader-runtime-vk/src/filter_pass.rs b/librashader-runtime-vk/src/filter_pass.rs index bada238..051b08d 100644 --- a/librashader-runtime-vk/src/filter_pass.rs +++ b/librashader-runtime-vk/src/filter_pass.rs @@ -312,7 +312,7 @@ impl FilterPass { } // PassOutput - for (index, output) in parent.output_textures.iter().enumerate() { + for (index, output) in parent.output_inputs.iter().enumerate() { let Some(output) = output else { continue; }; @@ -341,7 +341,7 @@ impl FilterPass { } // PassFeedback - for (index, feedback) in parent.feedback_textures.iter().enumerate() { + for (index, feedback) in parent.feedback_inputs.iter().enumerate() { let Some(feedback) = feedback else { eprintln!("no passfeedback {index}"); continue; diff --git a/librashader-runtime-vk/src/hello_triangle/mod.rs b/librashader-runtime-vk/src/hello_triangle/mod.rs index 309d7c3..f6b4c1f 100644 --- a/librashader-runtime-vk/src/hello_triangle/mod.rs +++ b/librashader-runtime-vk/src/hello_triangle/mod.rs @@ -49,7 +49,9 @@ impl VulkanWindow { vulkan: VulkanDraw, mut filter_chain: FilterChainVulkan, ) { - event_loop.run(move |event, _, control_flow| match event { + let mut counter = 0; + event_loop.run(move |event, _, control_flow| { + match event { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, WindowEvent::KeyboardInput { input, .. } => match input { @@ -70,10 +72,13 @@ impl VulkanWindow { window.request_redraw(); } Event::RedrawRequested(_window_id) => { - VulkanWindow::draw_frame(&vulkan, &mut filter_chain); + VulkanWindow::draw_frame(counter, &vulkan, &mut filter_chain); + counter += 1; } _ => (), + } }) + } unsafe fn record_command_buffer( @@ -133,7 +138,7 @@ impl VulkanWindow { vulkan.base.device.cmd_end_render_pass(cmd); } - fn draw_frame(vulkan: &VulkanDraw, filter: &mut FilterChainVulkan) { + fn draw_frame(frame: usize, vulkan: &VulkanDraw, filter: &mut FilterChainVulkan) { unsafe { vulkan .base @@ -207,7 +212,7 @@ impl VulkanWindow { // vk::QUEUE_FAMILY_IGNORED // ); - let intermediates = filter.frame(0, &Viewport { + let intermediates = filter.frame(frame, &Viewport { x: 0.0, y: 0.0, output: VulkanImage { diff --git a/librashader-runtime-vk/src/hello_triangle/vulkan_base.rs b/librashader-runtime-vk/src/hello_triangle/vulkan_base.rs index 0b9ad60..e708293 100644 --- a/librashader-runtime-vk/src/hello_triangle/vulkan_base.rs +++ b/librashader-runtime-vk/src/hello_triangle/vulkan_base.rs @@ -166,6 +166,7 @@ impl TryFrom<&VulkanBase> for Vulkan { value.device.clone(), value.graphics_queue.clone(), value.mem_props, + value.debug.loader.clone() )) } } diff --git a/librashader-runtime-vk/src/texture.rs b/librashader-runtime-vk/src/texture.rs index eb3ea01..807326b 100644 --- a/librashader-runtime-vk/src/texture.rs +++ b/librashader-runtime-vk/src/texture.rs @@ -165,14 +165,14 @@ impl OwnedImage { Ok(size) } - pub fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> error::Result { - Ok(InputImage { + pub fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> InputImage { + InputImage { image: self.image.clone(), image_view: self.image_view.clone(), wrap_mode, filter_mode: filter, mip_filter: filter, - }) + } } pub fn generate_mipmaps_and_end_pass(&self, cmd: vk::CommandBuffer) {