v3d: implement double-buffer mode
As with Vulkan, we are not enabling this by default since it may improve of hurt performance depending on the case. Instead, we can selectively enable it by using the V3D_DEBUG environment variable. Reviewed-by: Juan A. Suarez <jasuarez@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14551>
This commit is contained in:
committed by
Marge Bot
parent
b9f9474577
commit
b0f7f1afac
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user