freedreno/a6xx: New subpass on mid-frame clears

If we get a mid-frame clear, split out a new subpass rather than having
to fall-back to u_blitter clears.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22895>
This commit is contained in:
Rob Clark 2023-04-22 13:06:15 -07:00 committed by Marge Bot
parent 3738969710
commit c823460f2f
3 changed files with 63 additions and 13 deletions

View file

@ -433,6 +433,20 @@ is_z32(enum pipe_format format)
}
}
static bool
do_lrz_clear(struct fd_context *ctx, enum fd_buffer_mask buffers)
{
struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
if (!pfb->zsbuf)
return false;
struct fd_resource *zsbuf = fd_resource(pfb->zsbuf->texture);
return (buffers & FD_BUFFER_DEPTH) &&
zsbuf->lrz && !is_z32(pfb->zsbuf->format);
}
template <chip CHIP>
static bool
fd6_clear(struct fd_context *ctx, enum fd_buffer_mask buffers,
@ -440,29 +454,45 @@ fd6_clear(struct fd_context *ctx, enum fd_buffer_mask buffers,
unsigned stencil) assert_dt
{
struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
const bool has_depth = pfb->zsbuf;
struct fd_batch_subpass *subpass = ctx->batch->subpass;
unsigned color_buffers = buffers >> 2;
/* If we're clearing after draws, fallback to 3D pipe clears. We could
* use blitter clears in the draw batch but then we'd have to patch up the
* gmem offsets. This doesn't seem like a useful thing to optimize for
* however.*/
if (ctx->batch->num_draws > 0)
return false;
/* If we are clearing after draws, split out a new subpass:
*/
if (subpass->num_draws > 0) {
/* If we won't be able to do any fast-clears, avoid pointlessly
* splitting out a new subpass:
*/
if (pfb->samples > 1 && !do_lrz_clear(ctx, buffers))
return false;
if (has_depth && (buffers & FD_BUFFER_DEPTH)) {
struct fd_resource *zsbuf = fd_resource(pfb->zsbuf->texture);
if (zsbuf->lrz && !is_z32(pfb->zsbuf->format)) {
fd6_clear_lrz<CHIP>(ctx->batch, zsbuf, depth);
subpass = fd_batch_create_subpass(ctx->batch);
/* If doing an LRZ clear, replace the existing LRZ buffer with a
* freshly allocated one so that we have valid LRZ state for the
* new pass. Otherwise unconditional writes to the depth buffer
* would cause LRZ state to be invalid.
*/
if (do_lrz_clear(ctx, buffers)) {
struct fd_resource *zsbuf = fd_resource(pfb->zsbuf->texture);
fd_bo_del(subpass->lrz);
subpass->lrz = fd_bo_new(ctx->screen->dev, fd_bo_size(zsbuf->lrz),
FD_BO_NOMAP, "lrz");
fd_bo_del(zsbuf->lrz);
zsbuf->lrz = fd_bo_ref(subpass->lrz);
}
}
if (do_lrz_clear(ctx, buffers)) {
struct fd_resource *zsbuf = fd_resource(pfb->zsbuf->texture);
fd6_clear_lrz<CHIP>(ctx->batch, zsbuf, depth);
}
/* we need to do multisample clear on 3d pipe, so fallback to u_blitter: */
if (pfb->samples > 1)
return false;
struct fd_batch_subpass *subpass = ctx->batch->subpass;
u_foreach_bit (i, color_buffers)
subpass->clear_color[i] = *color;
if (buffers & FD_BUFFER_DEPTH)

View file

@ -152,6 +152,24 @@ fd_batch_create(struct fd_context *ctx, bool nondraw)
return batch;
}
struct fd_batch_subpass *
fd_batch_create_subpass(struct fd_batch *batch)
{
assert(!batch->nondraw);
struct fd_batch_subpass *subpass = subpass_create(batch);
/* This new subpass inherits the current subpass.. this is replaced
* if there is a depth clear
*/
if (batch->subpass->lrz)
subpass->lrz = fd_bo_ref(batch->subpass->lrz);
batch->subpass = subpass;
return subpass;
}
/**
* Cleanup that we normally do when the submit is flushed, like dropping
* rb references. But also called when batch is destroyed just in case

View file

@ -315,6 +315,8 @@ struct fd_batch {
struct fd_batch *fd_batch_create(struct fd_context *ctx, bool nondraw);
struct fd_batch_subpass *fd_batch_create_subpass(struct fd_batch *batch) assert_dt;
void fd_batch_set_fb(struct fd_batch *batch, const struct pipe_framebuffer_state *pfb) assert_dt;
void fd_batch_flush(struct fd_batch *batch) assert_dt;