@@ -989,13 +989,7 @@ impl CommandSink {
989
989
}
990
990
}
991
991
CommandSink :: Deferred { ref mut is_encoding, ref mut journal } => {
992
- //Note: the original descriptor belongs to the framebuffer,
993
- // and will me mutated afterwards.
994
- let pass = soft:: Pass :: Render ( unsafe {
995
- let desc: metal:: RenderPassDescriptor = msg_send ! [ descriptor, copy] ;
996
- msg_send ! [ desc. as_ptr( ) , retain] ;
997
- desc
998
- } ) ;
992
+ let pass = soft:: Pass :: Render ( descriptor. to_owned ( ) ) ;
999
993
let mut range = journal. render_commands . len ( ) .. 0 ;
1000
994
journal. render_commands . extend ( init_commands. map ( soft:: RenderCommand :: own) ) ;
1001
995
match door {
@@ -1005,14 +999,9 @@ impl CommandSink {
1005
999
journal. passes . push ( ( pass, range) )
1006
1000
}
1007
1001
CommandSink :: Remote { ref queue, ref cmd_buffer, ref mut pass, ref capacity, .. } => {
1008
- let desc = unsafe {
1009
- let desc: metal:: RenderPassDescriptor = msg_send ! [ descriptor, copy] ;
1010
- msg_send ! [ desc. as_ptr( ) , retain] ;
1011
- desc
1012
- } ;
1013
1002
let mut list = Vec :: with_capacity ( capacity. render ) ;
1014
1003
list. extend ( init_commands. map ( soft:: RenderCommand :: own) ) ;
1015
- let new_pass = EncodePass :: Render ( list, desc ) ;
1004
+ let new_pass = EncodePass :: Render ( list, descriptor . to_owned ( ) ) ;
1016
1005
match door {
1017
1006
PassDoor :: Open => * pass = Some ( new_pass) ,
1018
1007
PassDoor :: Closed { .. } => new_pass. schedule ( queue, cmd_buffer) ,
@@ -2696,61 +2685,8 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
2696
2685
T :: Item : Borrow < com:: ClearValueRaw > ,
2697
2686
{
2698
2687
// FIXME: subpasses
2699
- let _ap = AutoreleasePool :: new ( ) ;
2700
-
2701
- // We are going to modify the RP descriptor here, so
2702
- // locking to avoid data races.
2703
- //TODO: if we know that we aren't in the `Immediate` recording mode,
2704
- // we can copy here right away and void the lock entirely.
2705
- let descriptor = framebuffer. descriptor . lock ( ) ;
2706
-
2707
- let mut num_colors = 0 ;
2708
- let mut full_aspects = Aspects :: empty ( ) ;
2709
- let mut inner = self . inner . borrow_mut ( ) ;
2710
-
2711
- let dummy_value = com:: ClearValueRaw {
2712
- color : com:: ClearColorRaw {
2713
- int32 : [ 0 ; 4 ] ,
2714
- } ,
2715
- } ;
2716
- let clear_values_iter = clear_values
2717
- . into_iter ( )
2718
- . map ( |c| * c. borrow ( ) )
2719
- . chain ( iter:: repeat ( dummy_value) ) ;
2720
-
2721
- for ( rat, clear_value) in render_pass. attachments . iter ( ) . zip ( clear_values_iter) {
2722
- let ( aspects, channel) = match rat. format {
2723
- Some ( format) => ( format. surface_desc ( ) . aspects , Channel :: from ( format. base_format ( ) . 1 ) ) ,
2724
- None => continue ,
2725
- } ;
2726
- full_aspects |= aspects;
2727
- if aspects. contains ( Aspects :: COLOR ) {
2728
- let color_desc = descriptor
2729
- . color_attachments ( )
2730
- . object_at ( num_colors)
2731
- . unwrap ( ) ;
2732
- if set_operations ( color_desc, rat. ops ) == AttachmentLoadOp :: Clear {
2733
- let mtl_color = channel
2734
- . interpret ( unsafe { clear_value. color } ) ;
2735
- color_desc. set_clear_color ( mtl_color) ;
2736
- }
2737
- num_colors += 1 ;
2738
- }
2739
- if aspects. contains ( Aspects :: DEPTH ) {
2740
- let depth_desc = descriptor. depth_attachment ( ) . unwrap ( ) ;
2741
- if set_operations ( depth_desc, rat. ops ) == AttachmentLoadOp :: Clear {
2742
- let mtl_depth = unsafe { clear_value. depth_stencil . depth as f64 } ;
2743
- depth_desc. set_clear_depth ( mtl_depth) ;
2744
- }
2745
- }
2746
- if aspects. contains ( Aspects :: STENCIL ) {
2747
- let stencil_desc = descriptor. stencil_attachment ( ) . unwrap ( ) ;
2748
- if set_operations ( stencil_desc, rat. stencil_ops ) == AttachmentLoadOp :: Clear {
2749
- let mtl_stencil = unsafe { clear_value. depth_stencil . stencil } ;
2750
- stencil_desc. set_clear_stencil ( mtl_stencil) ;
2751
- }
2752
- }
2753
- }
2688
+ let desc_guard;
2689
+ let ( rp_key, full_aspects) = render_pass. build_key ( clear_values) ;
2754
2690
2755
2691
self . state . render_pso_is_compatible = match self . state . render_pso {
2756
2692
Some ( ref ps) => ps. at_formats . len ( ) == render_pass. attachments . len ( ) &&
@@ -2759,6 +2695,7 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
2759
2695
} ;
2760
2696
2761
2697
self . state . framebuffer_inner = framebuffer. inner . clone ( ) ;
2698
+
2762
2699
let ds_store = & self . shared . service_pipes . depth_stencil_states ;
2763
2700
let ds_state;
2764
2701
let com_ds = if full_aspects. intersects ( Aspects :: DEPTH | Aspects :: STENCIL ) {
@@ -2776,9 +2713,62 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
2776
2713
. make_render_commands ( full_aspects)
2777
2714
. chain ( com_ds) ;
2778
2715
2779
- inner
2716
+ desc_guard = framebuffer. desc_storage
2717
+ . get_or_create_with ( & rp_key, || {
2718
+ let _ap = AutoreleasePool :: new ( ) ;
2719
+ let mut clear_id = 0 ;
2720
+ let mut num_colors = 0 ;
2721
+ let rp_desc = unsafe {
2722
+ let desc: metal:: RenderPassDescriptor = msg_send ! [ framebuffer. descriptor, copy] ;
2723
+ msg_send ! [ desc. as_ptr( ) , retain] ;
2724
+ desc
2725
+ } ;
2726
+
2727
+ for rat in & render_pass. attachments {
2728
+ let ( aspects, channel) = match rat. format {
2729
+ Some ( format) => ( format. surface_desc ( ) . aspects , Channel :: from ( format. base_format ( ) . 1 ) ) ,
2730
+ None => continue ,
2731
+ } ;
2732
+ if aspects. contains ( Aspects :: COLOR ) {
2733
+ let color_desc = rp_desc
2734
+ . color_attachments ( )
2735
+ . object_at ( num_colors)
2736
+ . unwrap ( ) ;
2737
+ if set_operations ( color_desc, rat. ops ) == AttachmentLoadOp :: Clear {
2738
+ let d = & rp_key. clear_data [ clear_id .. clear_id + 4 ] ;
2739
+ clear_id += 4 ;
2740
+ let raw = com:: ClearColorRaw {
2741
+ uint32 : [ d[ 0 ] , d[ 1 ] , d[ 2 ] , d[ 3 ] ] ,
2742
+ } ;
2743
+ color_desc. set_clear_color ( channel. interpret ( raw) ) ;
2744
+ }
2745
+ num_colors += 1 ;
2746
+ }
2747
+ if aspects. contains ( Aspects :: DEPTH ) {
2748
+ let depth_desc = rp_desc. depth_attachment ( ) . unwrap ( ) ;
2749
+ if set_operations ( depth_desc, rat. ops ) == AttachmentLoadOp :: Clear {
2750
+ let raw = unsafe { * ( & rp_key. clear_data [ clear_id] as * const _ as * const f32 ) } ;
2751
+ clear_id += 1 ;
2752
+ depth_desc. set_clear_depth ( raw as f64 ) ;
2753
+ }
2754
+ }
2755
+ if aspects. contains ( Aspects :: STENCIL ) {
2756
+ let stencil_desc = rp_desc. stencil_attachment ( ) . unwrap ( ) ;
2757
+ if set_operations ( stencil_desc, rat. stencil_ops ) == AttachmentLoadOp :: Clear {
2758
+ let raw = rp_key. clear_data [ clear_id] ;
2759
+ clear_id += 1 ;
2760
+ stencil_desc. set_clear_stencil ( raw) ;
2761
+ }
2762
+ }
2763
+ }
2764
+
2765
+ rp_desc
2766
+ } ) ;
2767
+
2768
+ self . inner
2769
+ . borrow_mut ( )
2780
2770
. sink ( )
2781
- . begin_render_pass ( PassDoor :: Open , & * descriptor , init_commands) ;
2771
+ . begin_render_pass ( PassDoor :: Open , & * * desc_guard , init_commands) ;
2782
2772
}
2783
2773
2784
2774
fn next_subpass ( & mut self , _contents : com:: SubpassContents ) {
@@ -2821,38 +2811,39 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
2821
2811
let mut pre = inner. sink ( ) . pre_render ( ) ;
2822
2812
2823
2813
self . state . render_pso_is_compatible = true ; //assume good intent :)
2824
- let mut set_pipeline = false ;
2825
- match self . state . render_pso {
2814
+ let set_pipeline = match self . state . render_pso {
2815
+ Some ( ref ps) if ps. raw . as_ptr ( ) == pipeline. raw . as_ptr ( ) => {
2816
+ false // chill out
2817
+ }
2826
2818
Some ( ref mut ps) => {
2827
- // try to avoid extra states or new heap allocations
2828
- if ps. raw . as_ptr ( ) != pipeline. raw . as_ptr ( ) {
2829
- ps. raw = pipeline. raw . to_owned ( ) ;
2830
- set_pipeline = true ;
2831
- }
2832
- ps. ds_desc = pipeline. depth_stencil_desc . clone ( ) ;
2819
+ ps. raw = pipeline. raw . to_owned ( ) ;
2833
2820
ps. vbuf_map . clear ( ) ;
2834
2821
ps. vbuf_map . extend ( & pipeline. vertex_buffer_map ) ;
2822
+ ps. ds_desc = pipeline. depth_stencil_desc . clone ( ) ;
2835
2823
ps. at_formats . clear ( ) ;
2836
2824
ps. at_formats . extend_from_slice ( & pipeline. attachment_formats ) ;
2825
+ true
2837
2826
}
2838
2827
None => {
2839
- set_pipeline = true ;
2840
2828
self . state . render_pso = Some ( RenderPipelineState {
2841
2829
raw : pipeline. raw . to_owned ( ) ,
2842
2830
ds_desc : pipeline. depth_stencil_desc . clone ( ) ,
2843
2831
vbuf_map : pipeline. vertex_buffer_map . clone ( ) ,
2844
2832
at_formats : pipeline. attachment_formats . clone ( ) ,
2845
2833
} ) ;
2834
+ true
2846
2835
}
2847
- }
2836
+ } ;
2848
2837
if set_pipeline {
2849
2838
pre. issue ( soft:: RenderCommand :: BindPipeline ( & * pipeline. raw ) ) ;
2850
- }
2851
-
2852
- self . state . rasterizer_state = pipeline. rasterizer_state . clone ( ) ;
2853
- self . state . primitive_type = pipeline. primitive_type ;
2854
- if let Some ( ref rs) = pipeline. rasterizer_state {
2855
- pre. issue ( soft:: RenderCommand :: SetRasterizerState ( rs. clone ( ) ) )
2839
+ self . state . rasterizer_state = pipeline. rasterizer_state . clone ( ) ;
2840
+ self . state . primitive_type = pipeline. primitive_type ;
2841
+ if let Some ( ref rs) = pipeline. rasterizer_state {
2842
+ pre. issue ( soft:: RenderCommand :: SetRasterizerState ( rs. clone ( ) ) )
2843
+ }
2844
+ } else {
2845
+ debug_assert_eq ! ( self . state. rasterizer_state, pipeline. rasterizer_state) ;
2846
+ debug_assert_eq ! ( self . state. primitive_type, pipeline. primitive_type) ;
2856
2847
}
2857
2848
2858
2849
if let Some ( desc) = self . state . build_depth_stencil ( ) {
0 commit comments