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);