@@ -2541,6 +2541,14 @@ impl Renderer {
2541
2541
let mut frame_profiles = Vec :: new ( ) ;
2542
2542
let mut profile_timers = RendererProfileTimers :: new ( ) ;
2543
2543
2544
+ // The texture resolver scope should be outside of any rendering, including
2545
+ // debug rendering. This ensures that when we return render targets to the
2546
+ // pool via glInvalidateFramebuffer, we don't do any debug rendering after
2547
+ // that point. Otherwise, the bind / invalidate / bind logic trips up the
2548
+ // render pass logic in tiled / mobile GPUs, resulting in an extra copy /
2549
+ // resolve step when the debug overlay is enabled.
2550
+ self . texture_resolver . begin_frame ( ) ;
2551
+
2544
2552
let profile_samplers = {
2545
2553
let _gm = self . gpu_profile . start_marker ( "build samples" ) ;
2546
2554
// Block CPU waiting for last frame's GPU profiles to arrive.
@@ -2575,58 +2583,62 @@ impl Renderer {
2575
2583
} ) ;
2576
2584
2577
2585
profile_timers. cpu_time . profile ( || {
2578
- let clear_depth_value = if self . are_documents_intersecting_depth ( ) {
2579
- None
2580
- } else {
2581
- Some ( 1.0 )
2582
- } ;
2586
+ // If the documents don't intersect for depth, we can just do
2587
+ // a single, global depth clear.
2588
+ let clear_depth_per_doc = self . are_documents_intersecting_depth ( ) ;
2583
2589
2584
2590
//Note: another borrowck dance
2585
2591
let mut active_documents = mem:: replace ( & mut self . active_documents , Vec :: default ( ) ) ;
2586
2592
// sort by the document layer id
2587
2593
active_documents. sort_by_key ( |& ( _, ref render_doc) | render_doc. frame . layer ) ;
2588
2594
2589
- // don't clear the framebuffer if one of the rendered documents will overwrite it
2590
- if let Some ( framebuffer_size) = framebuffer_size {
2591
- let needs_color_clear = !active_documents
2592
- . iter ( )
2593
- . any ( |& ( _, RenderedDocument { ref frame, .. } ) | {
2594
- frame. background_color . is_some ( ) &&
2595
- frame. inner_rect . origin == DeviceIntPoint :: zero ( ) &&
2596
- frame. inner_rect . size == framebuffer_size
2597
- } ) ;
2598
-
2599
- if needs_color_clear || clear_depth_value. is_some ( ) {
2600
- let clear_color = if needs_color_clear {
2601
- self . clear_color . map ( |color| color. to_array ( ) )
2602
- } else {
2603
- None
2604
- } ;
2605
- self . device . reset_draw_target ( ) ;
2606
- self . device . enable_depth_write ( ) ;
2607
- self . device . clear_target ( clear_color, clear_depth_value, None ) ;
2608
- self . device . disable_depth_write ( ) ;
2609
- }
2610
- }
2611
-
2612
2595
#[ cfg( feature = "replay" ) ]
2613
2596
self . texture_resolver . external_images . extend (
2614
2597
self . owned_external_images . iter ( ) . map ( |( key, value) | ( * key, value. clone ( ) ) )
2615
2598
) ;
2616
2599
2617
- for & mut ( _, RenderedDocument { ref mut frame, .. } ) in & mut active_documents {
2600
+ for ( doc_index , ( _, RenderedDocument { ref mut frame, .. } ) ) in active_documents. iter_mut ( ) . enumerate ( ) {
2618
2601
frame. profile_counters . reset_targets ( ) ;
2619
2602
self . prepare_gpu_cache ( frame) ;
2620
2603
assert ! ( frame. gpu_cache_frame_id <= self . gpu_cache_frame_id,
2621
2604
"Received frame depends on a later GPU cache epoch ({:?}) than one we received last via `UpdateGpuCache` ({:?})" ,
2622
2605
frame. gpu_cache_frame_id, self . gpu_cache_frame_id) ;
2623
2606
2607
+ // Work out what color to clear the frame buffer for this document.
2608
+ // The document's supplied clear color is used, unless:
2609
+ // (a) The document has no specified clear color AND
2610
+ // (b) We are rendering the first document.
2611
+ // If both those conditions are true, the overall renderer
2612
+ // clear color will be used, if specified.
2613
+
2614
+ // Get the default clear color from the renderer.
2615
+ let mut fb_clear_color = if doc_index == 0 {
2616
+ self . clear_color
2617
+ } else {
2618
+ None
2619
+ } ;
2620
+
2621
+ // Override with document clear color if no overall clear
2622
+ // color or not on the first document.
2623
+ if fb_clear_color. is_none ( ) {
2624
+ fb_clear_color = frame. background_color ;
2625
+ }
2626
+
2627
+ // Only clear the depth buffer for this document if this is
2628
+ // the first document, or we need to clear depth per document.
2629
+ let fb_clear_depth = if clear_depth_per_doc || doc_index == 0 {
2630
+ Some ( 1.0 )
2631
+ } else {
2632
+ None
2633
+ } ;
2634
+
2624
2635
self . draw_tile_frame (
2625
2636
frame,
2626
2637
framebuffer_size,
2627
- clear_depth_value. is_some ( ) ,
2628
2638
cpu_frame_id,
2629
- & mut results. stats
2639
+ & mut results. stats ,
2640
+ fb_clear_color,
2641
+ fb_clear_depth,
2630
2642
) ;
2631
2643
2632
2644
if self . debug_flags . contains ( DebugFlags :: PROFILER_DBG ) {
@@ -2733,6 +2745,12 @@ impl Renderer {
2733
2745
if let Some ( debug_renderer) = self . debug . try_get_mut ( ) {
2734
2746
debug_renderer. render ( & mut self . device , framebuffer_size) ;
2735
2747
}
2748
+ // See comment for texture_resolver.begin_frame() for explanation
2749
+ // of why this must be done after all rendering, including debug
2750
+ // overlays. The end_frame() call implicitly calls end_pass(), which
2751
+ // should ensure any left over render targets get invalidated and
2752
+ // returned to the pool correctly.
2753
+ self . texture_resolver . end_frame ( & mut self . device , cpu_frame_id) ;
2736
2754
self . device . end_frame ( ) ;
2737
2755
} ) ;
2738
2756
if framebuffer_size. is_some ( ) {
@@ -3107,8 +3125,8 @@ impl Renderer {
3107
3125
draw_target : DrawTarget ,
3108
3126
target : & ColorRenderTarget ,
3109
3127
framebuffer_target_rect : DeviceIntRect ,
3110
- depth_is_ready : bool ,
3111
3128
clear_color : Option < [ f32 ; 4 ] > ,
3129
+ clear_depth : Option < f32 > ,
3112
3130
render_tasks : & RenderTaskTree ,
3113
3131
projection : & Transform3D < f32 > ,
3114
3132
frame_id : GpuFrameId ,
@@ -3134,12 +3152,9 @@ impl Renderer {
3134
3152
self . device . disable_depth ( ) ;
3135
3153
self . set_blend ( false , framebuffer_kind) ;
3136
3154
3137
- let depth_clear = if !depth_is_ready && target . needs_depth ( ) {
3155
+ if clear_depth . is_some ( ) {
3138
3156
self . device . enable_depth_write ( ) ;
3139
- Some ( 1.0 )
3140
- } else {
3141
- None
3142
- } ;
3157
+ }
3143
3158
3144
3159
let clear_rect = if !draw_target. is_default ( ) {
3145
3160
if self . enable_clear_scissor {
@@ -3169,9 +3184,13 @@ impl Renderer {
3169
3184
Some ( rect)
3170
3185
} ;
3171
3186
3172
- self . device . clear_target ( clear_color, depth_clear, clear_rect) ;
3187
+ self . device . clear_target (
3188
+ clear_color,
3189
+ clear_depth,
3190
+ clear_rect,
3191
+ ) ;
3173
3192
3174
- if depth_clear . is_some ( ) {
3193
+ if clear_depth . is_some ( ) {
3175
3194
self . device . disable_depth_write ( ) ;
3176
3195
}
3177
3196
}
@@ -4042,9 +4061,10 @@ impl Renderer {
4042
4061
& mut self ,
4043
4062
frame : & mut Frame ,
4044
4063
framebuffer_size : Option < DeviceIntSize > ,
4045
- framebuffer_depth_is_ready : bool ,
4046
4064
frame_id : GpuFrameId ,
4047
4065
stats : & mut RendererStats ,
4066
+ fb_clear_color : Option < ColorF > ,
4067
+ fb_clear_depth : Option < f32 > ,
4048
4068
) {
4049
4069
let _gm = self . gpu_profile . start_marker ( "tile frame draw" ) ;
4050
4070
@@ -4058,7 +4078,6 @@ impl Renderer {
4058
4078
self . device . disable_stencil ( ) ;
4059
4079
4060
4080
self . bind_frame_data ( frame) ;
4061
- self . texture_resolver . begin_frame ( ) ;
4062
4081
4063
4082
for ( pass_index, pass) in frame. passes . iter_mut ( ) . enumerate ( ) {
4064
4083
let _gm = self . gpu_profile . start_marker ( & format ! ( "pass {}" , pass_index) ) ;
@@ -4074,12 +4093,11 @@ impl Renderer {
4074
4093
& mut self . device ,
4075
4094
) ;
4076
4095
4077
- let ( cur_alpha , cur_color ) = match pass. kind {
4096
+ match pass. kind {
4078
4097
RenderPassKind :: MainFramebuffer ( ref target) => {
4079
4098
if let Some ( framebuffer_size) = framebuffer_size {
4080
4099
stats. color_target_count += 1 ;
4081
4100
4082
- let clear_color = frame. background_color . map ( |color| color. to_array ( ) ) ;
4083
4101
let projection = Transform3D :: ortho (
4084
4102
0.0 ,
4085
4103
framebuffer_size. width as f32 ,
@@ -4093,16 +4111,14 @@ impl Renderer {
4093
4111
DrawTarget :: Default ( framebuffer_size) ,
4094
4112
target,
4095
4113
frame. inner_rect ,
4096
- framebuffer_depth_is_ready ,
4097
- clear_color ,
4114
+ fb_clear_color . map ( |color| color . to_array ( ) ) ,
4115
+ fb_clear_depth ,
4098
4116
& frame. render_tasks ,
4099
4117
& projection,
4100
4118
frame_id,
4101
4119
stats,
4102
4120
) ;
4103
4121
}
4104
-
4105
- ( None , None )
4106
4122
}
4107
4123
RenderPassKind :: OffScreen { ref mut alpha, ref mut color, ref mut texture_cache } => {
4108
4124
let alpha_tex = self . allocate_target_texture ( alpha, & mut frame. profile_counters ) ;
@@ -4166,32 +4182,39 @@ impl Renderer {
4166
4182
ORTHO_FAR_PLANE ,
4167
4183
) ;
4168
4184
4185
+ let clear_depth = if target. needs_depth ( ) {
4186
+ Some ( 1.0 )
4187
+ } else {
4188
+ None
4189
+ } ;
4190
+
4169
4191
self . draw_color_target (
4170
4192
draw_target,
4171
4193
target,
4172
4194
frame. inner_rect ,
4173
- false ,
4174
4195
Some ( [ 0.0 , 0.0 , 0.0 , 0.0 ] ) ,
4196
+ clear_depth,
4175
4197
& frame. render_tasks ,
4176
4198
& projection,
4177
4199
frame_id,
4178
4200
stats,
4179
4201
) ;
4180
4202
}
4181
4203
4182
- ( alpha_tex, color_tex)
4204
+ // Only end the pass here and invalidate previous textures for
4205
+ // off-screen targets. Deferring return of the inputs to the
4206
+ // frame buffer until the implicit end_pass in end_frame allows
4207
+ // debug draw overlays to be added without triggering a copy
4208
+ // resolve stage in mobile / tiled GPUs.
4209
+ self . texture_resolver . end_pass (
4210
+ & mut self . device ,
4211
+ alpha_tex,
4212
+ color_tex,
4213
+ ) ;
4183
4214
}
4184
- } ;
4185
-
4186
- self . texture_resolver . end_pass (
4187
- & mut self . device ,
4188
- cur_alpha,
4189
- cur_color,
4190
- ) ;
4215
+ }
4191
4216
}
4192
4217
4193
- self . texture_resolver . end_frame ( & mut self . device , frame_id) ;
4194
-
4195
4218
if let Some ( framebuffer_size) = framebuffer_size {
4196
4219
self . draw_frame_debug_items ( & frame. debug_items ) ;
4197
4220
self . draw_render_target_debug ( framebuffer_size) ;
0 commit comments