From 6d54a5514cb3be5cf4aa51d4b75c2e4eaa3faf79 Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Tue, 29 Oct 2024 11:53:49 +0100 Subject: [PATCH] v3d: use heuristic to enable double-buffer mode This is still experimental and only enabled if V3D_DEBUG=db is set. Reviewed-by: Jose Maria Casanova Crespo Part-of: --- src/gallium/drivers/v3d/v3d_blit.c | 1 + src/gallium/drivers/v3d/v3d_context.h | 9 +++++++++ src/gallium/drivers/v3d/v3d_job.c | 21 +++++++++++++++------ src/gallium/drivers/v3d/v3dx_draw.c | 24 ++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/v3d/v3d_blit.c b/src/gallium/drivers/v3d/v3d_blit.c index a3735360fb6..e065775fbf4 100644 --- a/src/gallium/drivers/v3d/v3d_blit.c +++ b/src/gallium/drivers/v3d/v3d_blit.c @@ -530,6 +530,7 @@ v3d_tlb_blit(struct pipe_context *pctx, struct pipe_blit_info *info) src_surf); job->msaa = msaa; job->double_buffer = double_buffer; + job->can_use_double_buffer = !job->msaa && V3D_DBG(DOUBLE_BUFFER); job->internal_bpp = max_bpp; job->draw_min_x = info->dst.box.x; job->draw_min_y = info->dst.box.y; diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index 672b492ac61..4902a773451 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -40,6 +40,7 @@ #include "drm-uapi/v3d_drm.h" #include "v3d_screen.h" #include "broadcom/common/v3d_limits.h" +#include "broadcom/common/v3d_util.h" #include "broadcom/simulator/v3d_simulator.h" #include "broadcom/compiler/v3d_compiler.h" @@ -474,9 +475,17 @@ struct v3d_job { float clear_z; uint8_t clear_s; + /* If we found anything in the job that is not compatible with + * double-buffer mode + */ + bool can_use_double_buffer; + /* If TLB double-buffering is enabled for this job */ bool double_buffer; + /* Tracks score for double-buffer mode heuristic */ + struct v3d_double_buffer_score double_buffer_score; + /** * Set if some drawing (triangles, blits, or just a glClear()) has * been done to the FBO, meaning that we need to diff --git a/src/gallium/drivers/v3d/v3d_job.c b/src/gallium/drivers/v3d/v3d_job.c index 95e387b557e..c7362a14264 100644 --- a/src/gallium/drivers/v3d/v3d_job.c +++ b/src/gallium/drivers/v3d/v3d_job.c @@ -376,7 +376,12 @@ v3d_get_job(struct v3d_context *v3d, } } - job->double_buffer = false; + /* By default we disable double buffer but we allow it to be enabled + * later on (except for msaa) if we don't find any other reason + * to disable it. + */ + job->can_use_double_buffer = !job->msaa && V3D_DBG(DOUBLE_BUFFER); + job->double_buffer = false; memcpy(&job->key, &local_key, sizeof(local_key)); _mesa_hash_table_insert(v3d->jobs, &job->key, job); @@ -546,13 +551,14 @@ alloc_tile_state(struct v3d_job *job) static void enable_double_buffer_mode(struct v3d_job *job) { - /* For now we only allow double-buffer mode through envvar */ - if (!V3D_DBG(DOUBLE_BUFFER)) + /* Don't enable if we have seen incompatibilities */ + if (!job->can_use_double_buffer) return; - /* MSAA is not compatible with double buffering */ - if (job->msaa) - return; + /* For now we only allow double buffer via envvar and only for jobs + * that are not MSAA, which is incompatible. + */ + assert(V3D_DBG(DOUBLE_BUFFER) && !job->msaa); /* Tile loads are serialized against stores, in which case we don't get * any benefits from enabling double-buffer and would just pay the price @@ -567,6 +573,9 @@ enable_double_buffer_mode(struct v3d_job *job) if (!job->store) return; + if (!v3d_double_buffer_score_ok(&job->double_buffer_score)) + return; + /* Enable double-buffer mode. * * This will reduce the tile size so we need to recompute state diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index 48713b0aa01..447f257d4b6 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -1034,6 +1034,25 @@ v3d_check_compiled_shaders(struct v3d_context *v3d) return false; } +static void +update_double_buffer_score(struct v3d_job *job, uint32_t vertex_count) +{ + if (!job->can_use_double_buffer) + return; + + if (job->v3d->prog.gs) { + job->can_use_double_buffer = false; + return; + } + + struct v3d_compiled_shader *vs = job->v3d->prog.vs; + struct v3d_compiled_shader *fs = job->v3d->prog.fs; + v3d_update_double_buffer_score(vertex_count, + vs->qpu_size, fs->qpu_size, + vs->prog_data.base, fs->prog_data.base, + &job->double_buffer_score); +} + static void v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, unsigned drawid_offset, @@ -1388,6 +1407,11 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, v3d_job_add_bo(job, rsc->bo); } + if (indirect && indirect->buffer) + job->can_use_double_buffer = false; + else + update_double_buffer_score(job, draws[0].count * info->instance_count); + if (job->referenced_size > 768 * 1024 * 1024) { perf_debug("Flushing job with %dkb to try to free up memory\n", job->referenced_size / 1024);