diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c index 3d1a472de31..7c8df123a01 100644 --- a/src/gallium/drivers/panfrost/pan_job.c +++ b/src/gallium/drivers/panfrost/pan_job.c @@ -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; diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 8ae980e9a77..fcf5114eb11 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -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) diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h index 1d7bb817816..06ced7bd5af 100644 --- a/src/gallium/drivers/panfrost/pan_resource.h +++ b/src/gallium/drivers/panfrost/pan_resource.h @@ -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; };