@@ -989,13 +989,7 @@ impl CommandSink {
989989 }
990990 }
991991 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 ( ) ) ;
999993 let mut range = journal. render_commands . len ( ) .. 0 ;
1000994 journal. render_commands . extend ( init_commands. map ( soft:: RenderCommand :: own) ) ;
1001995 match door {
@@ -1005,14 +999,9 @@ impl CommandSink {
1005999 journal. passes . push ( ( pass, range) )
10061000 }
10071001 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- } ;
10131002 let mut list = Vec :: with_capacity ( capacity. render ) ;
10141003 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 ( ) ) ;
10161005 match door {
10171006 PassDoor :: Open => * pass = Some ( new_pass) ,
10181007 PassDoor :: Closed { .. } => new_pass. schedule ( queue, cmd_buffer) ,
@@ -2696,61 +2685,8 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
26962685 T :: Item : Borrow < com:: ClearValueRaw > ,
26972686 {
26982687 // 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) ;
27542690
27552691 self . state . render_pso_is_compatible = match self . state . render_pso {
27562692 Some ( ref ps) => ps. at_formats . len ( ) == render_pass. attachments . len ( ) &&
@@ -2759,6 +2695,7 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
27592695 } ;
27602696
27612697 self . state . framebuffer_inner = framebuffer. inner . clone ( ) ;
2698+
27622699 let ds_store = & self . shared . service_pipes . depth_stencil_states ;
27632700 let ds_state;
27642701 let com_ds = if full_aspects. intersects ( Aspects :: DEPTH | Aspects :: STENCIL ) {
@@ -2776,9 +2713,62 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
27762713 . make_render_commands ( full_aspects)
27772714 . chain ( com_ds) ;
27782715
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 ( )
27802770 . sink ( )
2781- . begin_render_pass ( PassDoor :: Open , & * descriptor , init_commands) ;
2771+ . begin_render_pass ( PassDoor :: Open , & * * desc_guard , init_commands) ;
27822772 }
27832773
27842774 fn next_subpass ( & mut self , _contents : com:: SubpassContents ) {
@@ -2821,38 +2811,39 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
28212811 let mut pre = inner. sink ( ) . pre_render ( ) ;
28222812
28232813 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+ }
28262818 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 ( ) ;
28332820 ps. vbuf_map . clear ( ) ;
28342821 ps. vbuf_map . extend ( & pipeline. vertex_buffer_map ) ;
2822+ ps. ds_desc = pipeline. depth_stencil_desc . clone ( ) ;
28352823 ps. at_formats . clear ( ) ;
28362824 ps. at_formats . extend_from_slice ( & pipeline. attachment_formats ) ;
2825+ true
28372826 }
28382827 None => {
2839- set_pipeline = true ;
28402828 self . state . render_pso = Some ( RenderPipelineState {
28412829 raw : pipeline. raw . to_owned ( ) ,
28422830 ds_desc : pipeline. depth_stencil_desc . clone ( ) ,
28432831 vbuf_map : pipeline. vertex_buffer_map . clone ( ) ,
28442832 at_formats : pipeline. attachment_formats . clone ( ) ,
28452833 } ) ;
2834+ true
28462835 }
2847- }
2836+ } ;
28482837 if set_pipeline {
28492838 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) ;
28562847 }
28572848
28582849 if let Some ( desc) = self . state . build_depth_stencil ( ) {
0 commit comments