diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index dcd2cd9..67ed9d8 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -52,6 +52,7 @@ pub struct FilterChainD3D11 { history_framebuffers: VecDeque, state: D3D11State, default_options: FrameOptionsD3D11, + draw_last_pass_feedback: bool, } pub(crate) struct Direct3D11 { @@ -187,6 +188,7 @@ impl FilterChainD3D11 { let draw_quad = DrawQuad::new(device)?; let state = D3D11State::new(device)?; Ok(FilterChainD3D11 { + draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(), passes: filters, output_framebuffers, feedback_framebuffers, @@ -510,21 +512,23 @@ impl FilterChainD3D11 { // Draw to output_framebuffers for proper handling of feedback. let feedback_target = &self.output_framebuffers[index]; - pass.draw( - &ctx, - index, - &self.common, - pass.config.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - RenderTarget::viewport_with_output( - &feedback_target.create_render_target_view()?, + if self.draw_last_pass_feedback { + pass.draw( + &ctx, + index, + &self.common, + pass.config.get_frame_count(frame_count), + options, viewport, - ), - QuadType::Final, - )?; + &original, + &source, + RenderTarget::viewport_with_output( + &feedback_target.create_render_target_view()?, + viewport, + ), + QuadType::Final, + )?; + } pass.draw( &ctx, diff --git a/librashader-runtime-d3d11/tests/triangle.rs b/librashader-runtime-d3d11/tests/triangle.rs index 8f1e272..ed68b1a 100644 --- a/librashader-runtime-d3d11/tests/triangle.rs +++ b/librashader-runtime-d3d11/tests/triangle.rs @@ -15,9 +15,9 @@ use librashader_runtime_d3d11::options::FilterChainOptionsD3D11; // const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-royale.slangp"; // const FILTER_PATH: &str = "../test/slang-shaders/test/history.slangp"; -// const FILTER_PATH: &str = "../test/shaders_slang/test/feedback.slangp"; +const FILTER_PATH: &str = "../test/shaders_slang/test/feedback.slangp"; -const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-royale.slangp"; +// const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-geom-deluxe.slangp"; const IMAGE_PATH: &str = "../triangle.png"; #[test] fn triangle_d3d11_args() { diff --git a/librashader-runtime-d3d12/src/filter_chain.rs b/librashader-runtime-d3d12/src/filter_chain.rs index b5924c6..06eb721 100644 --- a/librashader-runtime-d3d12/src/filter_chain.rs +++ b/librashader-runtime-d3d12/src/filter_chain.rs @@ -79,6 +79,7 @@ pub struct FilterChainD3D12 { disable_mipmaps: bool, default_options: FrameOptionsD3D12, + draw_last_pass_feedback: bool, } pub(crate) struct FilterCommon { @@ -386,6 +387,7 @@ impl FilterChainD3D12 { let (history_framebuffers, history_textures) = framebuffer_init.init_history()?; Ok(FilterChainD3D12 { + draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(), common: FilterCommon { d3d12: device.clone(), samplers, @@ -848,48 +850,50 @@ impl FilterChainD3D12 { source.filter = pass.config.filter; source.wrap_mode = pass.config.wrap_mode; - let feedback_target = &self.output_framebuffers[index]; + if self.draw_last_pass_feedback { + let feedback_target = &self.output_framebuffers[index]; - if pass.pipeline.format != feedback_target.format { - // eprintln!("recompiling final pipeline"); - pass.pipeline.recompile( - feedback_target.format, - &self.common.root_signature, - &self.common.d3d12, + if pass.pipeline.format != feedback_target.format { + // eprintln!("recompiling final pipeline"); + pass.pipeline.recompile( + feedback_target.format, + &self.common.root_signature, + &self.common.d3d12, + )?; + } + + self.residuals + .dispose_barriers(util::d3d12_resource_transition( + cmd, + &feedback_target.handle.resource(), + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + D3D12_RESOURCE_STATE_RENDER_TARGET, + )); + + let view = feedback_target.create_render_target_view(&mut self.rtv_heap)?; + let out = RenderTarget::viewport_with_output(&view, viewport); + pass.draw( + cmd, + index, + &self.common, + pass.config.get_frame_count(frame_count), + options, + viewport, + &original, + &source, + &out, + QuadType::Final, )?; + + self.residuals + .dispose_barriers(util::d3d12_resource_transition( + cmd, + &feedback_target.handle.resource(), + D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + )); } - self.residuals - .dispose_barriers(util::d3d12_resource_transition( - cmd, - &feedback_target.handle.resource(), - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - D3D12_RESOURCE_STATE_RENDER_TARGET, - )); - - let view = feedback_target.create_render_target_view(&mut self.rtv_heap)?; - let out = RenderTarget::viewport_with_output(&view, viewport); - pass.draw( - cmd, - index, - &self.common, - pass.config.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - &out, - QuadType::Final, - )?; - - self.residuals - .dispose_barriers(util::d3d12_resource_transition( - cmd, - &feedback_target.handle.resource(), - D3D12_RESOURCE_STATE_RENDER_TARGET, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - )); - if pass.pipeline.format != viewport.output.format { // eprintln!("recompiling final pipeline"); pass.pipeline.recompile( diff --git a/librashader-runtime-d3d9/src/filter_chain.rs b/librashader-runtime-d3d9/src/filter_chain.rs index b7d7895..b713b72 100644 --- a/librashader-runtime-d3d9/src/filter_chain.rs +++ b/librashader-runtime-d3d9/src/filter_chain.rs @@ -56,6 +56,7 @@ pub struct FilterChainD3D9 { feedback_framebuffers: Box<[D3D9Texture]>, history_framebuffers: VecDeque, default_options: FrameOptionsD3D9, + draw_last_pass_feedback: bool, } mod compile { @@ -252,6 +253,7 @@ impl FilterChainD3D9 { let draw_quad = DrawQuad::new(device)?; Ok(FilterChainD3D9 { + draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(), passes: filters, output_framebuffers, feedback_framebuffers, @@ -397,21 +399,23 @@ impl FilterChainD3D9 { source.wrap = pass.config.wrap_mode; source.is_srgb = pass.config.srgb_framebuffer; - let feedback_target = &self.output_framebuffers[index]; - let feedback_target_rtv = feedback_target.as_output()?; + if self.draw_last_pass_feedback { + let feedback_target = &self.output_framebuffers[index]; + let feedback_target_rtv = feedback_target.as_output()?; - pass.draw( - &self.common.d3d9, - index, - &self.common, - pass.config.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - RenderTarget::viewport_with_output(&feedback_target_rtv, viewport), - QuadType::Final, - )?; + pass.draw( + &self.common.d3d9, + index, + &self.common, + pass.config.get_frame_count(frame_count), + options, + viewport, + &original, + &source, + RenderTarget::viewport_with_output(&feedback_target_rtv, viewport), + QuadType::Final, + )?; + } pass.draw( &self.common.d3d9, diff --git a/librashader-runtime-gl/src/filter_chain/filter_impl.rs b/librashader-runtime-gl/src/filter_chain/filter_impl.rs index b2f5faf..ff600a6 100644 --- a/librashader-runtime-gl/src/filter_chain/filter_impl.rs +++ b/librashader-runtime-gl/src/filter_chain/filter_impl.rs @@ -39,6 +39,7 @@ pub(crate) struct FilterChainImpl { feedback_framebuffers: Box<[GLFramebuffer]>, history_framebuffers: VecDeque, default_options: FrameOptionsGL, + draw_last_pass_feedback: bool, } pub(crate) struct FilterCommon { @@ -175,6 +176,7 @@ impl FilterChainImpl { let draw_quad = T::DrawQuad::new(); Ok(FilterChainImpl { + draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(), passes: filters, output_framebuffers, feedback_framebuffers, @@ -373,17 +375,19 @@ impl FilterChainImpl { source.mip_filter = pass.config.filter; source.wrap_mode = pass.config.wrap_mode; - let target = &self.output_framebuffers[index]; - pass.draw( - index, - &self.common, - pass.config.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - RenderTarget::viewport_with_output(target, viewport), - ); + if self.draw_last_pass_feedback { + let target = &self.output_framebuffers[index]; + pass.draw( + index, + &self.common, + pass.config.get_frame_count(frame_count), + options, + viewport, + &original, + &source, + RenderTarget::viewport_with_output(target, viewport), + ); + } pass.draw( index, diff --git a/librashader-runtime-mtl/src/filter_chain.rs b/librashader-runtime-mtl/src/filter_chain.rs index fecb850..7803008 100644 --- a/librashader-runtime-mtl/src/filter_chain.rs +++ b/librashader-runtime-mtl/src/filter_chain.rs @@ -82,6 +82,7 @@ pub struct FilterChainMetal { prev_frame_history_buffer: OwnedTexture, disable_mipmaps: bool, default_options: FrameOptionsMetal, + draw_last_pass_feedback: bool } impl Debug for FilterChainMetal { @@ -317,6 +318,7 @@ impl FilterChainMetal { let draw_quad = DrawQuad::new(&device)?; Ok(FilterChainMetal { + draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(), common: FilterCommon { luts, samplers, @@ -487,21 +489,22 @@ impl FilterChainMetal { source.mip_filter = pass.config.filter; let index = passes_len - 1; - let output_image = &self.output_framebuffers[index].texture; - - let out = RenderTarget::viewport_with_output(output_image.as_ref(), viewport); - pass.draw( - &cmd, - passes_len - 1, - &self.common, - pass.config.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - &out, - QuadType::Final, - )?; + if self.draw_last_pass_feedback { + let output_image = &self.output_framebuffers[index].texture; + let out = RenderTarget::viewport_with_output(output_image.as_ref(), viewport); + pass.draw( + &cmd, + passes_len - 1, + &self.common, + pass.config.get_frame_count(frame_count), + options, + viewport, + &original, + &source, + &out, + QuadType::Final, + )?; + } let output_image = viewport.output; let out = RenderTarget::viewport_with_output(output_image, viewport); diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index c21a7d9..c4c6998 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -126,6 +126,7 @@ pub struct FilterChainVulkan { disable_mipmaps: bool, residuals: Box<[FrameResiduals]>, default_options: FrameOptionsVulkan, + draw_last_pass_feedback: bool, } pub(crate) struct FilterCommon { @@ -386,6 +387,7 @@ impl FilterChainVulkan { }); Ok(FilterChainVulkan { + draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(), common: FilterCommon { luts, samplers, @@ -727,28 +729,30 @@ impl FilterChainVulkan { source.wrap_mode = pass.config.wrap_mode; source.mip_filter = pass.config.filter; - let target = &self.output_framebuffers[index]; + if self.draw_last_pass_feedback { + let target = &self.output_framebuffers[index]; - let output_image = OutputImage::new(&self.vulkan.device, target.image.clone())?; - let out = RenderTarget::viewport_with_output(&output_image, viewport); + let output_image = OutputImage::new(&self.vulkan.device, target.image.clone())?; + let out = RenderTarget::viewport_with_output(&output_image, viewport); - let residual_fb = pass.draw( - cmd, - target.image.format, - index, - &self.common, - pass.config.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - &out, - QuadType::Final, - true, - )?; - out.output.end_pass(&self.vulkan.device, cmd); - intermediates.dispose_outputs(output_image); - intermediates.dispose_framebuffers(residual_fb); + let residual_fb = pass.draw( + cmd, + target.image.format, + index, + &self.common, + pass.config.get_frame_count(frame_count), + options, + viewport, + &original, + &source, + &out, + QuadType::Final, + true, + )?; + out.output.end_pass(&self.vulkan.device, cmd); + intermediates.dispose_outputs(output_image); + intermediates.dispose_framebuffers(residual_fb); + } let output_image = OutputImage::new(&self.vulkan.device, viewport.output.clone())?; let out = RenderTarget::viewport_with_output(&output_image, viewport); diff --git a/librashader-runtime-wgpu/src/filter_chain.rs b/librashader-runtime-wgpu/src/filter_chain.rs index e39ad31..f815b92 100644 --- a/librashader-runtime-wgpu/src/filter_chain.rs +++ b/librashader-runtime-wgpu/src/filter_chain.rs @@ -74,6 +74,7 @@ pub struct FilterChainWgpu { disable_mipmaps: bool, mipmapper: MipmapGen, default_frame_options: FrameOptionsWgpu, + draw_last_pass_feedback: bool, } pub(crate) struct FilterCommon { @@ -197,6 +198,7 @@ impl FilterChainWgpu { let draw_quad = DrawQuad::new(&device); Ok(FilterChainWgpu { + draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(), common: FilterCommon { luts, samplers, @@ -492,22 +494,24 @@ impl FilterChainWgpu { source.wrap_mode = pass.config.wrap_mode; source.mip_filter = pass.config.filter; - let target = &self.output_framebuffers[index]; - let output_image = WgpuOutputView::from(target); - let out = RenderTarget::viewport_with_output(&output_image, viewport); + if self.draw_last_pass_feedback { + let target = &self.output_framebuffers[index]; + let output_image = WgpuOutputView::from(target); + let out = RenderTarget::viewport_with_output(&output_image, viewport); - pass.draw( - cmd, - index, - &self.common, - pass.config.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - &out, - QuadType::Final, - )?; + pass.draw( + cmd, + index, + &self.common, + pass.config.get_frame_count(frame_count), + options, + viewport, + &original, + &source, + &out, + QuadType::Final, + )?; + } let output_image = &viewport.output; let out = RenderTarget::viewport_with_output(output_image, viewport);