From 6c46890325e66dc2d3451872f67e8b836a08d711 Mon Sep 17 00:00:00 2001 From: Jose Maria Casanova Crespo Date: Wed, 24 Jul 2024 01:43:38 +0200 Subject: [PATCH] v3d: avoid load/store of tile buffer on invalidated framebuffer With the information of the invalidated framebuffer we avoid the stores of the results of tile buffer rendering that are not going to be used again or the loads of the tile buffer when the buffer data can be ignored as it would be never read. Reviewed-by: Iago Toral Quiroga Part-of: --- src/gallium/drivers/v3d/v3d_context.c | 12 +++++++++- src/gallium/drivers/v3d/v3d_context.h | 4 ++++ src/gallium/drivers/v3d/v3d_resource.h | 6 +++++ src/gallium/drivers/v3d/v3dx_draw.c | 31 +++++++++++++++++++++----- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/v3d/v3d_context.c b/src/gallium/drivers/v3d/v3d_context.c index 4d6b6f956b0..6abda780262 100644 --- a/src/gallium/drivers/v3d/v3d_context.c +++ b/src/gallium/drivers/v3d/v3d_context.c @@ -118,6 +118,7 @@ v3d_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc) struct v3d_resource *rsc = v3d_resource(prsc); rsc->initialized_buffers = 0; + rsc->invalidated = true; struct hash_entry *entry = _mesa_hash_table_search(v3d->write_jobs, prsc); @@ -125,8 +126,17 @@ v3d_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc) return; struct v3d_job *job = entry->data; - if (job->key.zsbuf && job->key.zsbuf->texture == prsc) + if (job->key.zsbuf && job->key.zsbuf->texture == prsc) { job->store &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL); + return; + } + + for (int i = 0; i < job->nr_cbufs; i++) { + if (job->cbufs[i] && job->cbufs[i]->texture == prsc) { + job->store &= ~(PIPE_CLEAR_COLOR0 << i); + return; + } + } } /** diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index 67949614c0a..4bd48b78fcd 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -448,6 +448,10 @@ struct v3d_job { * clear. */ uint32_t clear_draw; + /* Bitmask of PIPE_CLEAR_* of attached buffers that were invalidated + * by glInvalidateFramebuffer so we can avoid loading them. + */ + uint32_t invalidated_load; /* Bitmask of PIPE_CLEAR_* of buffers that have been read by a draw * call without having been cleared first. */ diff --git a/src/gallium/drivers/v3d/v3d_resource.h b/src/gallium/drivers/v3d/v3d_resource.h index 751933a2475..146d8f92902 100644 --- a/src/gallium/drivers/v3d/v3d_resource.h +++ b/src/gallium/drivers/v3d/v3d_resource.h @@ -124,6 +124,12 @@ struct v3d_resource { */ uint32_t initialized_buffers; + /** + * The resource has been invalidated by glInvalidateFramebuffer so + * it doesn't need to be loaded until another job writes to it. + */ + bool invalidated; + /** * A serial ID that is incremented every time a new BO is bound to a * resource. We use this to track scenarios where we might need to diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index 0dfeac0bf6b..03f01f9ed1e 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -1357,14 +1357,29 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, u_stream_outputs_for_vertices(info->mode, draws[0].count); } - uint32_t clear_mask = job->clear_tlb | job->clear_draw; + if (v3d->zsa && job->zsbuf) { + struct v3d_resource *rsc = v3d_resource(job->zsbuf->texture); + if (rsc->invalidated) { + /* Currently gallium only applies invalidates if it + * affects both depth and stencil together. + */ + job->invalidated_load |= + PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL; + rsc->invalidated = false; + if (rsc->separate_stencil) + rsc->separate_stencil->invalidated = false; + } + } + + uint32_t no_load_mask = + job->clear_tlb | job->clear_draw | job->invalidated_load; if (v3d->zsa && job->zsbuf && v3d->zsa->base.depth_enabled) { struct v3d_resource *rsc = v3d_resource(job->zsbuf->texture); v3d_job_add_bo(job, rsc->bo); - job->load |= PIPE_CLEAR_DEPTH & ~clear_mask; + job->load |= PIPE_CLEAR_DEPTH & ~no_load_mask; if (v3d->zsa->base.depth_writemask) job->store |= PIPE_CLEAR_DEPTH; - rsc->initialized_buffers = PIPE_CLEAR_DEPTH; + rsc->initialized_buffers |= PIPE_CLEAR_DEPTH; } if (v3d->zsa && job->zsbuf && v3d->zsa->base.stencil[0].enabled) { @@ -1374,7 +1389,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, v3d_job_add_bo(job, rsc->bo); - job->load |= PIPE_CLEAR_STENCIL & ~clear_mask; + job->load |= PIPE_CLEAR_STENCIL & ~no_load_mask; if (v3d->zsa->base.stencil[0].writemask || v3d->zsa->base.stencil[1].writemask) { job->store |= PIPE_CLEAR_STENCIL; @@ -1382,6 +1397,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, rsc->initialized_buffers |= PIPE_CLEAR_STENCIL; } + for (int i = 0; i < job->nr_cbufs; i++) { uint32_t bit = PIPE_CLEAR_COLOR0 << i; int blend_rt = v3d->blend->base.independent_blend_enable ? i : 0; @@ -1390,7 +1406,12 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, continue; struct v3d_resource *rsc = v3d_resource(job->cbufs[i]->texture); - job->load |= bit & ~clear_mask; + if (rsc->invalidated) { + job->invalidated_load |= bit; + rsc->invalidated = false; + } else { + job->load |= bit & ~no_load_mask; + } if (v3d->blend->base.rt[blend_rt].colormask) job->store |= bit; v3d_job_add_bo(job, rsc->bo);