@@ -27,7 +27,7 @@ use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtif
2727use librashader_reflect:: reflect:: semantics:: ShaderSemantics ;
2828use librashader_reflect:: reflect:: ReflectShader ;
2929use librashader_runtime:: binding:: BindingUtil ;
30- use librashader_runtime:: framebuffer:: FramebufferInit ;
30+ use librashader_runtime:: framebuffer:: { FramebufferInit , FramebufferPool } ;
3131use librashader_runtime:: image:: { ImageError , LoadedTexture , UVDirection , BGRA8 } ;
3232use librashader_runtime:: quad:: QuadType ;
3333use librashader_runtime:: render_target:: RenderTarget ;
@@ -172,8 +172,8 @@ pub struct FilterChainVulkan {
172172 pub ( crate ) common : FilterCommon ,
173173 passes : Box < [ FilterPass ] > ,
174174 vulkan : VulkanObjects ,
175- output_framebuffers : Box < [ OwnedImage ] > ,
176- feedback_framebuffers : Box < [ OwnedImage ] > ,
175+ output_framebuffers : FramebufferPool < OwnedImage > ,
176+ feedback_framebuffers : FramebufferPool < OwnedImage > ,
177177 history_framebuffers : VecDeque < OwnedImage > ,
178178 disable_mipmaps : bool ,
179179 residuals : Box < [ FrameResiduals ] > ,
@@ -471,8 +471,7 @@ impl FilterChainVulkan {
471471 let ( output_framebuffers, output_textures) = framebuffer_init. init_output_framebuffers ( ) ?;
472472
473473 // initialize feedback framebuffers
474- let ( feedback_framebuffers, feedback_textures) =
475- framebuffer_init. init_output_framebuffers ( ) ?;
474+ let ( feedback_framebuffers, feedback_textures) = framebuffer_init. init_feedback_framebuffers ( ) ?;
476475
477476 // initialize history
478477 let ( history_framebuffers, history_textures) = framebuffer_init. init_history ( ) ?;
@@ -733,159 +732,158 @@ impl FilterChainVulkan {
733732
734733 let mut source = original. clone ( ) ;
735734
735+ let passes_len = passes. len ( ) ;
736+ let options = options. unwrap_or ( & self . default_options ) ;
737+
736738 // swap output and feedback **before** recording command buffers
737- std:: mem:: swap (
738- & mut self . output_framebuffers ,
739- & mut self . feedback_framebuffers ,
740- ) ;
739+ for index in 0 ..passes_len {
740+ if self . feedback_framebuffers . contains ( index) {
741+ std:: mem:: swap ( & mut self . output_framebuffers [ index] , & mut self . feedback_framebuffers [ index] ) ;
742+ }
743+ }
744+
745+ let scale_context = Some ( OwnedImageLayout {
746+ dst_layout : vk:: ImageLayout :: SHADER_READ_ONLY_OPTIMAL ,
747+ dst_access : vk:: AccessFlags :: SHADER_READ ,
748+ src_stage : vk:: PipelineStageFlags :: TOP_OF_PIPE ,
749+ dst_stage : vk:: PipelineStageFlags :: FRAGMENT_SHADER ,
750+ cmd,
751+ } ) ;
741752
742- // rescale render buffers to ensure all bindings are valid .
743- OwnedImage :: scale_framebuffers_with_context (
753+ // rescale feedback buffers and refresh their bound textures .
754+ OwnedImage :: scale_feedback_framebuffers_with_context (
744755 source. image . size ,
745756 viewport. output . size ,
746757 original. image . size ,
747- & mut self . output_framebuffers ,
748758 & mut self . feedback_framebuffers ,
749759 passes,
750- & Some ( OwnedImageLayout {
751- dst_layout : vk:: ImageLayout :: SHADER_READ_ONLY_OPTIMAL ,
752- dst_access : vk:: AccessFlags :: SHADER_READ ,
753- src_stage : vk:: PipelineStageFlags :: TOP_OF_PIPE ,
754- dst_stage : vk:: PipelineStageFlags :: FRAGMENT_SHADER ,
755- cmd,
756- } ) ,
757- Some ( & mut |index : usize ,
758- pass : & FilterPass ,
759- output : & OwnedImage ,
760- feedback : & OwnedImage | {
761- // refresh inputs
760+ & scale_context,
761+ |index, pass, feedback| {
762762 self . common . feedback_textures [ index] =
763763 Some ( feedback. as_input ( pass. meta . filter , pass. meta . wrap_mode ) ) ;
764- self . common . output_textures [ index] =
765- Some ( output. as_input ( pass. meta . filter , pass. meta . wrap_mode ) ) ;
766764 Ok ( ( ) )
767- } ) ,
765+ } ,
768766 ) ?;
769767
770- let passes_len = passes. len ( ) ;
771- let ( pass, last) = passes. split_at_mut ( passes_len - 1 ) ;
772-
773- let options = options. unwrap_or ( & self . default_options ) ;
774-
775768 self . common
776769 . draw_quad
777770 . bind_vbo_for_frame ( & self . vulkan . device , cmd) ;
778- for ( index, pass) in pass. iter_mut ( ) . enumerate ( ) {
779- let target = & self . output_framebuffers [ index] ;
780- source. filter_mode = pass. meta . filter ;
781- source. wrap_mode = pass. meta . wrap_mode ;
782- source. mip_filter = pass. meta . filter ;
783-
784- let output_image = OutputImage :: new ( & self . vulkan . device , target. image . clone ( ) ) ?;
785- let out = RenderTarget :: identity ( & output_image) ?;
786-
787- let residual_fb = pass. draw (
788- cmd,
789- target. image . format ,
790- index,
791- & self . common ,
792- pass. meta . get_frame_count ( frame_count) ,
793- options,
794- viewport,
795- & original,
796- & source,
797- & out,
798- None ,
799- QuadType :: Offscreen ,
800- false ,
801- ) ?;
802-
803- if target. max_miplevels > 1 && !self . disable_mipmaps {
804- target. generate_mipmaps_and_end_pass ( cmd) ;
805- } else {
806- out. output . end_pass ( & self . vulkan . device , cmd) ;
807- }
808771
809- source = self . common . output_textures [ index] . clone ( ) . unwrap ( ) ;
810- intermediates. dispose_outputs ( output_image) ;
811- intermediates. dispose_framebuffers ( residual_fb) ;
812- }
813-
814- // try to hint the optimizer
815- assert_eq ! ( last. len( ) , 1 ) ;
816- if let Some ( pass) = last. iter_mut ( ) . next ( ) {
817- let index = passes_len - 1 ;
818- if pass
819- . graphics_pipeline
820- . render_passes
821- . get ( & viewport. output . format )
822- . is_none ( )
823- {
824- // need to recompile
825- pass. graphics_pipeline . recompile ( viewport. output . format ) ?;
826- }
772+ OwnedImage :: scale_output_framebuffers_with_context (
773+ source. image . size ,
774+ viewport. output . size ,
775+ original. image . size ,
776+ & mut self . output_framebuffers ,
777+ passes,
778+ & scale_context,
779+ |index, pass, target, _size| {
780+ source. filter_mode = pass. meta . filter ;
781+ source. wrap_mode = pass. meta . wrap_mode ;
782+ source. mip_filter = pass. meta . filter ;
783+ let frame_count_pass = pass. meta . get_frame_count ( frame_count) ;
784+
785+ if index != passes_len - 1 {
786+ let output_image = OutputImage :: new ( & self . vulkan . device , target. image . clone ( ) ) ?;
787+ let out = RenderTarget :: identity ( & output_image) ?;
788+
789+ let residual_fb = pass. draw (
790+ cmd,
791+ target. image . format ,
792+ index,
793+ & self . common ,
794+ frame_count_pass,
795+ options,
796+ viewport,
797+ & original,
798+ & source,
799+ & out,
800+ None ,
801+ QuadType :: Offscreen ,
802+ false ,
803+ ) ?;
804+
805+ if target. max_miplevels > 1 && !self . disable_mipmaps {
806+ target. generate_mipmaps_and_end_pass ( cmd) ;
807+ } else {
808+ out. output . end_pass ( & self . vulkan . device , cmd) ;
809+ }
810+
811+ self . common . output_textures [ index] =
812+ Some ( target. as_input ( pass. meta . filter , pass. meta . wrap_mode ) ) ;
813+ source = self . common . output_textures [ index] . clone ( ) . unwrap ( ) ;
814+ intermediates. dispose_outputs ( output_image) ;
815+ intermediates. dispose_framebuffers ( residual_fb) ;
816+ return Ok ( ( ) ) ;
817+ }
827818
828- source. filter_mode = pass. meta . filter ;
829- source. wrap_mode = pass. meta . wrap_mode ;
830- source. mip_filter = pass. meta . filter ;
819+ if pass
820+ . graphics_pipeline
821+ . render_passes
822+ . get ( & viewport. output . format )
823+ . is_none ( )
824+ {
825+ // need to recompile
826+ pass. graphics_pipeline . recompile ( viewport. output . format ) ?;
827+ }
831828
832- // When feedback is enabled, render the last pass to the intermediate
833- // framebuffer first then render to the viewport with the OutputSize semantic
834- // overridden to the FB scale.
835- //
836- // Shaders need to see the pass's declared scale rather than the viewport size,
837- // or they won't render correctly for feedback.
838- let output_size_override = if self . draw_last_pass_feedback {
839- let target = & self . output_framebuffers [ index] ;
829+ // When feedback is enabled, render the last pass to the intermediate
830+ // framebuffer first then render to the viewport with the OutputSize semantic
831+ // overridden to the FB scale.
832+ //
833+ // Shaders need to see the pass's declared scale rather than the viewport size,
834+ // or they won't render correctly for feedback.
835+ let output_size_override = if self . draw_last_pass_feedback {
836+ let output_image = OutputImage :: new ( & self . vulkan . device , target. image . clone ( ) ) ?;
837+ let out = RenderTarget :: viewport_with_output ( & output_image, viewport) ;
838+
839+ let residual_fb = pass. draw (
840+ cmd,
841+ target. image . format ,
842+ index,
843+ & self . common ,
844+ frame_count_pass,
845+ options,
846+ viewport,
847+ & original,
848+ & source,
849+ & out,
850+ None ,
851+ QuadType :: Final ,
852+ true ,
853+ ) ?;
854+ out. output . end_pass ( & self . vulkan . device , cmd) ;
855+ intermediates. dispose_outputs ( output_image) ;
856+ intermediates. dispose_framebuffers ( residual_fb) ;
857+ Some ( target. image . size )
858+ } else {
859+ None
860+ } ;
840861
841- let output_image = OutputImage :: new ( & self . vulkan . device , target. image . clone ( ) ) ?;
862+ let output_image =
863+ OutputImage :: new ( & self . vulkan . device , viewport. output . clone ( ) ) ?;
842864 let out = RenderTarget :: viewport_with_output ( & output_image, viewport) ;
843865
844866 let residual_fb = pass. draw (
845867 cmd,
846- target . image . format ,
868+ viewport . output . format ,
847869 index,
848870 & self . common ,
849- pass . meta . get_frame_count ( frame_count ) ,
871+ frame_count_pass ,
850872 options,
851873 viewport,
852874 & original,
853875 & source,
854876 & out,
855- None ,
877+ output_size_override ,
856878 QuadType :: Final ,
857- true ,
879+ false ,
858880 ) ?;
859- out . output . end_pass ( & self . vulkan . device , cmd ) ;
881+
860882 intermediates. dispose_outputs ( output_image) ;
861883 intermediates. dispose_framebuffers ( residual_fb) ;
862- Some ( target. image . size )
863- } else {
864- None
865- } ;
866-
867- let output_image = OutputImage :: new ( & self . vulkan . device , viewport. output . clone ( ) ) ?;
868- let out = RenderTarget :: viewport_with_output ( & output_image, viewport) ;
869-
870- let residual_fb = pass. draw (
871- cmd,
872- viewport. output . format ,
873- index,
874- & self . common ,
875- pass. meta . get_frame_count ( frame_count) ,
876- options,
877- viewport,
878- & original,
879- & source,
880- & out,
881- output_size_override,
882- QuadType :: Final ,
883- false ,
884- ) ?;
885-
886- intermediates. dispose_outputs ( output_image) ;
887- intermediates. dispose_framebuffers ( residual_fb) ;
888- }
884+ Ok ( ( ) )
885+ } ,
886+ ) ?;
889887
890888 intermediates. dispose_image_view ( original_image_view) ;
891889
0 commit comments