diff --git a/src/gallium/drivers/v3d/v3d_blit.c b/src/gallium/drivers/v3d/v3d_blit.c index b337218cb00..b44b6cd78ec 100644 --- a/src/gallium/drivers/v3d/v3d_blit.c +++ b/src/gallium/drivers/v3d/v3d_blit.c @@ -467,8 +467,13 @@ v3d_tlb_blit(struct pipe_context *pctx, struct pipe_blit_info *info) if (is_color_blit) surfaces[0] = dst_surf; + bool double_buffer = + unlikely(V3D_DEBUG & V3D_DEBUG_DOUBLE_BUFFER) && !msaa; + uint32_t tile_width, tile_height, max_bpp; - v3d_get_tile_buffer_size(msaa, is_color_blit ? 1 : 0, surfaces, src_surf, &tile_width, &tile_height, &max_bpp); + v3d_get_tile_buffer_size(msaa, double_buffer, + is_color_blit ? 1 : 0, surfaces, src_surf, + &tile_width, &tile_height, &max_bpp); int dst_surface_width = u_minify(info->dst.resource->width0, info->dst.level); @@ -491,6 +496,7 @@ v3d_tlb_blit(struct pipe_context *pctx, struct pipe_blit_info *info) is_color_blit ? NULL : dst_surf, src_surf); job->msaa = msaa; + job->double_buffer = double_buffer; job->tile_width = tile_width; job->tile_height = tile_height; job->internal_bpp = max_bpp; diff --git a/src/gallium/drivers/v3d/v3d_context.c b/src/gallium/drivers/v3d/v3d_context.c index 6ae58d7518d..a35bd3666cd 100644 --- a/src/gallium/drivers/v3d/v3d_context.c +++ b/src/gallium/drivers/v3d/v3d_context.c @@ -242,6 +242,7 @@ v3d_create_texture_shader_state_bo(struct v3d_context *v3d, void v3d_get_tile_buffer_size(bool is_msaa, + bool double_buffer, uint32_t nr_cbufs, struct pipe_surface **cbufs, struct pipe_surface *bbuf, @@ -249,6 +250,8 @@ v3d_get_tile_buffer_size(bool is_msaa, uint32_t *tile_height, uint32_t *max_bpp) { + assert(!is_msaa || !double_buffer); + uint32_t max_cbuf_idx = 0; *max_bpp = 0; for (int i = 0; i < nr_cbufs; i++) { @@ -265,8 +268,8 @@ v3d_get_tile_buffer_size(bool is_msaa, *max_bpp = MAX2(*max_bpp, bsurf->internal_bpp); } - v3d_choose_tile_size(max_cbuf_idx + 1, *max_bpp, is_msaa, - false /* double-buffer */, + v3d_choose_tile_size(max_cbuf_idx + 1, *max_bpp, + is_msaa, double_buffer, tile_width, tile_height); } diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index b283929e38b..2fe0cfb3ddd 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -430,6 +430,9 @@ struct v3d_job { float clear_z; uint8_t clear_s; + /* If TLB double-buffering is enabled for this job */ + bool double_buffer; + /** * Set if some drawing (triangles, blits, or just a glClear()) has * been done to the FBO, meaning that we need to @@ -777,6 +780,7 @@ void v3d_create_texture_shader_state_bo(struct v3d_context *v3d, struct v3d_sampler_view *so); void v3d_get_tile_buffer_size(bool is_msaa, + bool double_buffer, uint32_t nr_cbufs, struct pipe_surface **cbufs, struct pipe_surface *bbuf, diff --git a/src/gallium/drivers/v3d/v3d_job.c b/src/gallium/drivers/v3d/v3d_job.c index 8e62130f96c..f2260292e75 100644 --- a/src/gallium/drivers/v3d/v3d_job.c +++ b/src/gallium/drivers/v3d/v3d_job.c @@ -358,6 +358,9 @@ v3d_get_job(struct v3d_context *v3d, } } + job->double_buffer = + unlikely(V3D_DEBUG & V3D_DEBUG_DOUBLE_BUFFER) && !job->msaa; + memcpy(&job->key, &local_key, sizeof(local_key)); _mesa_hash_table_insert(v3d->jobs, &job->key, job); @@ -375,13 +378,14 @@ v3d_get_job_for_fbo(struct v3d_context *v3d) struct pipe_surface *zsbuf = v3d->framebuffer.zsbuf; struct v3d_job *job = v3d_get_job(v3d, nr_cbufs, cbufs, zsbuf, NULL); - if (v3d->framebuffer.samples >= 1) + if (v3d->framebuffer.samples >= 1) { job->msaa = true; + job->double_buffer = false; + } - v3d_get_tile_buffer_size(job->msaa, job->nr_cbufs, - job->cbufs, job->bbuf, - &job->tile_width, - &job->tile_height, + v3d_get_tile_buffer_size(job->msaa, job->double_buffer, + job->nr_cbufs, job->cbufs, job->bbuf, + &job->tile_width, &job->tile_height, &job->internal_bpp); /* The dirty flags are tracking what's been updated while v3d->job has diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index e9e8f1889af..86330ddf9f8 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -94,6 +94,7 @@ v3dX(start_binning)(struct v3d_context *v3d, struct v3d_job *job) } #endif + assert(!job->msaa || !job->double_buffer); #if V3D_VERSION >= 40 cl_emit(&job->bcl, TILE_BINNING_MODE_CFG, config) { config.width_in_pixels = job->draw_width; @@ -102,6 +103,7 @@ v3dX(start_binning)(struct v3d_context *v3d, struct v3d_job *job) MAX2(job->nr_cbufs, 1); config.multisample_mode_4x = job->msaa; + config.double_buffer_in_non_ms_mode = job->double_buffer; config.maximum_bpp_of_all_render_targets = job->internal_bpp; } @@ -128,6 +130,7 @@ v3dX(start_binning)(struct v3d_context *v3d, struct v3d_job *job) MAX2(job->nr_cbufs, 1); config.multisample_mode_4x = job->msaa; + config.double_buffer_in_non_ms_mode = job->double_buffer; config.maximum_bpp_of_all_render_targets = job->internal_bpp; } diff --git a/src/gallium/drivers/v3d/v3dx_rcl.c b/src/gallium/drivers/v3d/v3dx_rcl.c index 92e7c06cd60..f62e490cee9 100644 --- a/src/gallium/drivers/v3d/v3dx_rcl.c +++ b/src/gallium/drivers/v3d/v3dx_rcl.c @@ -561,6 +561,21 @@ supertile_in_job_scissors(struct v3d_job *job, return false; } +static inline bool +do_double_initial_tile_clear(const struct v3d_job *job) +{ + /* Our rendering code emits an initial clear per layer, unlike the + * Vulkan driver, which only executes a single initial clear for all + * layers. This is because in GL we don't use the + * 'clear_buffer_being_stored' bit when storing tiles, so each layer + * needs the iniital clear. This is also why this helper, unlike the + * Vulkan version, doesn't check the layer count to decide if double + * clear for double buffer mode is required. + */ + return job->double_buffer && + (job->draw_tiles_x > 1 || job->draw_tiles_y > 1); +} + static void emit_render_layer(struct v3d_job *job, uint32_t layer) { @@ -638,7 +653,7 @@ emit_render_layer(struct v3d_job *job, uint32_t layer) cl_emit(&job->rcl, STORE_TILE_BUFFER_GENERAL, store) { store.buffer_to_store = NONE; } - if (i == 0) { + if (i == 0 || do_double_initial_tile_clear(job)) { cl_emit(&job->rcl, CLEAR_TILE_BUFFERS, clear) { clear.clear_z_stencil_buffer = true; clear.clear_all_render_targets = true; @@ -732,7 +747,9 @@ v3dX(emit_rcl)(struct v3d_job *job) config.number_of_render_targets = MAX2(job->nr_cbufs, 1); + assert(!job->msaa || !job->double_buffer); config.multisample_mode_4x = job->msaa; + config.double_buffer_in_non_ms_mode = job->double_buffer; config.maximum_bpp_of_all_render_targets = job->internal_bpp; }