From 9a9f2812519f7282a91f86e3e5758a4920de1be3 Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Thu, 18 Jul 2024 09:15:20 +0200 Subject: [PATCH] v3d: support blitting straight from tile buffer This allows us to handle blitting (including MSAA resolve) directly from the tile buffer to memory. We will use this soon to provide a faster implementation of TLB blits. Reviewed-by: Jose Maria Casanova Crespo Part-of: --- src/gallium/drivers/v3d/v3d_context.h | 10 +++++++ src/gallium/drivers/v3d/v3dx_rcl.c | 41 ++++++++++++++++++++------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index 6dfb817f57d..63fb0ffefbb 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -378,11 +378,14 @@ struct v3d_job { * Surfaces to submit rendering for. * For blit operations, bbuf is the source surface, and cbufs[0] is * the destination surface. + * For blit operations straight from the job's tile buffer, dbuf is the + * blit destination surface. */ uint32_t nr_cbufs; struct pipe_surface *cbufs[V3D_MAX_DRAW_BUFFERS]; struct pipe_surface *zsbuf; struct pipe_surface *bbuf; + struct pipe_surface *dbuf; /** @} */ /** @{ * Bounding box of the scissor across all queued drawing. @@ -453,6 +456,13 @@ struct v3d_job { * (either clears or draws) and should be stored. */ uint32_t store; + /* Bitmask of PIPE_CLEAR_* of buffers that need to be blitted into + * a destination buffer other than the jobs RT. Used to implement + * blits from jobs that have not yet been flushed, including MSAA + * resolve. + */ + uint32_t blit_tlb; + uint32_t clear_color[V3D_MAX_DRAW_BUFFERS][4]; float clear_z; uint8_t clear_s; diff --git a/src/gallium/drivers/v3d/v3dx_rcl.c b/src/gallium/drivers/v3d/v3dx_rcl.c index 216521cdb83..80b2c2a7591 100644 --- a/src/gallium/drivers/v3d/v3dx_rcl.c +++ b/src/gallium/drivers/v3d/v3dx_rcl.c @@ -97,7 +97,8 @@ store_general(struct v3d_job *job, surf = v3d_surface(psurf); } - *stores_pending &= ~pipe_bit; + if (stores_pending) + *stores_pending &= ~pipe_bit; struct v3d_resource *rsc = v3d_resource(psurf->texture); @@ -131,13 +132,18 @@ store_general(struct v3d_job *job, store.height_in_ub_or_stride = slice->stride; } - assert(!resolve_4x || job->bbuf); - if (psurf->texture->nr_samples > 1) + if (psurf->texture->nr_samples > 1) { store.decimate_mode = V3D_DECIMATE_MODE_ALL_SAMPLES; - else if (resolve_4x && job->bbuf->texture->nr_samples > 1) + } else if (resolve_4x) { + /* We are resolving from a MSAA blit buffer or we are + * resolving directly from TLB to a resolve buffer + */ + assert((job->bbuf && job->bbuf->texture->nr_samples > 1) || + (job->dbuf && job->dbuf->texture->nr_samples <= 1)); store.decimate_mode = V3D_DECIMATE_MODE_4X; - else + } else { store.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0; + } } } @@ -223,18 +229,31 @@ v3d_rcl_emit_stores(struct v3d_job *job, struct v3d_cl *cl, int layer) * perspective. Non-MSAA surfaces will use * STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED. */ - assert(!job->bbuf || job->nr_cbufs <= 1); + assert((!job->bbuf && !job->dbuf) || job->nr_cbufs <= 1); for (int i = 0; i < job->nr_cbufs; i++) { - uint32_t bit = PIPE_CLEAR_COLOR0 << i; - if (!(job->store & bit)) - continue; - struct pipe_surface *psurf = job->cbufs[i]; if (!psurf) continue; + uint32_t bit = PIPE_CLEAR_COLOR0 << i; + if (job->blit_tlb & bit) { + assert(job->dbuf); + bool blit_resolve = + job->dbuf->texture->nr_samples <= 1 && + psurf->texture->nr_samples > 1; + store_general(job, cl, job->dbuf, layer, + RENDER_TARGET_0 + i, bit, NULL, + false, blit_resolve); + } + + if (!(job->store & bit)) + continue; + + bool blit_resolve = + job->bbuf && job->bbuf->texture->nr_samples > 1 && + psurf->texture->nr_samples <= 1; store_general(job, cl, psurf, layer, RENDER_TARGET_0 + i, bit, - &stores_pending, general_color_clear, job->bbuf); + &stores_pending, general_color_clear, blit_resolve); } if (job->store & PIPE_CLEAR_DEPTHSTENCIL && job->zsbuf) {