panfrost: Constant stencil value tracking

If stencil is constant across the resource, then it can be treated as
if it was cleared.

Improves performance in applications which create a stencil buffer but
do not use it. Originally the same was done for depth to help some 2D
applications, but that gave mixed results so the patch was dropped.

v2: Don't do anything if a fragment job wouldn't be needed otherwise.
v3: Set stencil_value when a batch is cleared (Alyssa)
v4: Handle clears when the stencil is already known (Alyssa)
v5: Make sure shared resources are not used (Alyssa)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16646>
This commit is contained in:
Icecream95 2022-05-05 13:50:16 +12:00 committed by Marge Bot
parent 79877d5df5
commit a2463ec271
3 changed files with 43 additions and 1 deletions

View file

@ -656,6 +656,12 @@ panfrost_batch_submit_ioctl(struct panfrost_batch *batch,
return 0;
}
static bool
panfrost_has_fragment_job(struct panfrost_batch *batch)
{
return batch->scoreboard.first_tiler || batch->clear;
}
/* Submit both vertex/tiler and fragment jobs for a batch, possibly with an
* outsync corresponding to the later of the two (since there will be an
* implicit dep between them) */
@ -670,7 +676,7 @@ panfrost_batch_submit_jobs(struct panfrost_batch *batch,
struct panfrost_device *dev = pan_device(pscreen);
bool has_draws = batch->scoreboard.first_job;
bool has_tiler = batch->scoreboard.first_tiler;
bool has_frag = has_tiler || batch->clear;
bool has_frag = panfrost_has_fragment_job(batch);
int ret = 0;
/* Take the submit lock to make sure no tiler jobs from other context
@ -736,6 +742,28 @@ panfrost_batch_submit(struct panfrost_context *ctx,
if (!batch->scoreboard.first_job && !batch->clear)
goto out;
if (batch->key.zsbuf && panfrost_has_fragment_job(batch)) {
struct pipe_surface *surf = batch->key.zsbuf;
struct panfrost_resource *z_rsrc = pan_resource(surf->texture);
/* Shared depth/stencil resources are not supported, and would
* break this optimisation. */
assert(!(z_rsrc->base.bind & (PIPE_BIND_SHARED |
PIPE_BIND_SCANOUT |
PIPE_BIND_DISPLAY_TARGET)));
if (batch->clear & PIPE_CLEAR_STENCIL) {
z_rsrc->stencil_value = batch->clear_stencil;
z_rsrc->constant_stencil = true;
} else if (z_rsrc->constant_stencil) {
batch->clear_stencil = z_rsrc->stencil_value;
batch->clear |= PIPE_CLEAR_STENCIL;
}
if (batch->draws & PIPE_CLEAR_STENCIL)
z_rsrc->constant_stencil = false;
}
struct pan_fb_info fb;
struct pan_image_view rts[8], zs, s;

View file

@ -719,6 +719,8 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
so->image.data.bo =
panfrost_bo_create(dev, so->image.layout.data_size, PAN_BO_DELAY_MMAP, label);
so->constant_stencil = true;
}
if (drm_is_afbc(so->image.layout.modifier))
@ -962,6 +964,9 @@ panfrost_ptr_map(struct pipe_context *pctx,
pipe_resource_reference(&transfer->base.resource, resource);
*out_transfer = &transfer->base;
if (usage & PIPE_MAP_WRITE)
rsrc->constant_stencil = false;
/* We don't have s/w routines for AFBC, so use a staging texture */
if (drm_is_afbc(rsrc->image.layout.modifier)) {
struct panfrost_resource *staging = pan_alloc_staging(ctx, rsrc, level, box);
@ -1361,6 +1366,9 @@ panfrost_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *pr
{
struct panfrost_context *ctx = pan_context(pctx);
struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
struct panfrost_resource *rsrc = pan_resource(prsrc);
rsrc->constant_stencil = true;
/* Handle the glInvalidateFramebuffer case */
if (batch->key.zsbuf && batch->key.zsbuf->texture == prsrc)

View file

@ -82,6 +82,12 @@ struct panfrost_resource {
/* Used to decide when to convert to another modifier */
uint16_t modifier_updates;
/* Do all pixels have the same stencil value? */
bool constant_stencil;
/* The stencil value if constant_stencil is set */
uint8_t stencil_value;
/* Cached min/max values for index buffers */
struct panfrost_minmax_cache *index_cache;
};