Signed-off-by: Rob Clark <robdcl...@gmail.com> --- src/gallium/drivers/freedreno/a6xx/fd6_gmem.c | 3 +- .../drivers/freedreno/freedreno_batch.c | 1 + .../drivers/freedreno/freedreno_batch.h | 8 +- .../drivers/freedreno/freedreno_draw.c | 99 ++++++++++++------- .../drivers/freedreno/freedreno_resource.c | 33 +++++++ .../drivers/freedreno/freedreno_state.h | 10 ++ .../drivers/freedreno/freedreno_surface.h | 18 ++++ 7 files changed, 137 insertions(+), 35 deletions(-)
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c index 8cda7d6ddae..0a82f69fc62 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c @@ -36,6 +36,7 @@ #include "freedreno_draw.h" #include "freedreno_state.h" #include "freedreno_resource.h" +#include "freedreno_surface.h" #include "fd6_gmem.h" #include "fd6_context.h" @@ -901,7 +902,7 @@ emit_resolve_blit(struct fd_batch *batch, { uint32_t info = 0; - if (!rsc->valid) + if (!fd_surface_valid(psurf)) return; switch (buffer) { diff --git a/src/gallium/drivers/freedreno/freedreno_batch.c b/src/gallium/drivers/freedreno/freedreno_batch.c index eae2f68ce11..280a412222a 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.c +++ b/src/gallium/drivers/freedreno/freedreno_batch.c @@ -78,6 +78,7 @@ batch_init(struct fd_batch *batch) batch->cleared = 0; batch->fast_cleared = 0; batch->invalidated = 0; + batch->partial_invalidated = 0; batch->restore = batch->resolve = 0; batch->needs_flush = false; batch->flushed = false; diff --git a/src/gallium/drivers/freedreno/freedreno_batch.h b/src/gallium/drivers/freedreno/freedreno_batch.h index a40d36094cd..9846ceea6ff 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.h +++ b/src/gallium/drivers/freedreno/freedreno_batch.h @@ -95,7 +95,13 @@ struct fd_batch { FD_BUFFER_DEPTH = PIPE_CLEAR_DEPTH, FD_BUFFER_STENCIL = PIPE_CLEAR_STENCIL, FD_BUFFER_ALL = FD_BUFFER_COLOR | FD_BUFFER_DEPTH | FD_BUFFER_STENCIL, - } invalidated, cleared, fast_cleared, restore, resolve; + } invalidated, partial_invalidated, cleared, fast_cleared, restore, resolve; + + /* for partially invalidated fb surfaces, track the invalidated rect: */ + struct { + struct pipe_box zsbuf; + struct pipe_box cbuf[8]; + } invalid; /* is this a non-draw batch (ie compute/blit which has no pfb state)? */ bool nondraw : 1; diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index f17cb563063..5b4b728b6d3 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -36,6 +36,7 @@ #include "freedreno_context.h" #include "freedreno_fence.h" #include "freedreno_state.h" +#include "freedreno_surface.h" #include "freedreno_resource.h" #include "freedreno_query_acc.h" #include "freedreno_query_hw.h" @@ -57,6 +58,14 @@ resource_written(struct fd_batch *batch, struct pipe_resource *prsc) fd_batch_resource_used(batch, fd_resource(prsc), true); } +static void +surface_valid(struct pipe_surface *psurf) +{ + struct fd_surface *surf = fd_surface(psurf); + surf->invalid = false; + surf->partial_invalid = false; +} + static void fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) { @@ -138,59 +147,78 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) mtx_lock(&ctx->screen->lock); if (ctx->dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_ZSA)) { + unsigned b = 0; if (fd_depth_enabled(ctx)) { - if (fd_resource(pfb->zsbuf->texture)->valid) { - restore_buffers |= FD_BUFFER_DEPTH; - } else { - batch->invalidated |= FD_BUFFER_DEPTH; - } - buffers |= FD_BUFFER_DEPTH; - resource_written(batch, pfb->zsbuf->texture); + b |= FD_BUFFER_DEPTH; batch->gmem_reason |= FD_GMEM_DEPTH_ENABLED; } if (fd_stencil_enabled(ctx)) { - if (fd_resource(pfb->zsbuf->texture)->valid) { - restore_buffers |= FD_BUFFER_STENCIL; + b |= FD_BUFFER_STENCIL; + batch->gmem_reason |= FD_GMEM_STENCIL_ENABLED; + } + + if (b) { + if (fd_surface_valid(pfb->zsbuf)) { + restore_buffers |= b; + } else if (fd_surface_partially_valid(pfb->zsbuf)) { + restore_buffers |= b; + batch->partial_invalidated |= b; + batch->invalid.zsbuf = fd_surface(pfb->zsbuf)->invalid_region; } else { - batch->invalidated |= FD_BUFFER_STENCIL; + batch->invalidated |= b; + } + buffers |= b; + + if (fd_depth_write_enabled(ctx) || + fd_stencil_write_enabled(ctx)) { + resource_written(batch, pfb->zsbuf->texture); + } else { + resource_read(batch, pfb->zsbuf->texture); } - buffers |= FD_BUFFER_STENCIL; - resource_written(batch, pfb->zsbuf->texture); - batch->gmem_reason |= FD_GMEM_STENCIL_ENABLED; } } if (ctx->dirty & FD_DIRTY_FRAMEBUFFER) { for (i = 0; i < pfb->nr_cbufs; i++) { - if (!pfb->cbufs[i]) + struct pipe_surface *psurf = pfb->cbufs[i]; + + if (!psurf) continue; + if (fd_surface_valid(psurf)) { + restore_buffers |= PIPE_CLEAR_COLOR0 << i; + } else if (fd_surface_partially_valid(psurf)) { + restore_buffers |= PIPE_CLEAR_COLOR0 << i; + batch->partial_invalidated |= PIPE_CLEAR_COLOR0 << i; + batch->invalid.cbuf[i] = fd_surface(psurf)->invalid_region; + } else { + batch->invalidated |= PIPE_CLEAR_COLOR0 << i; + } + + buffers |= PIPE_CLEAR_COLOR0 << i; + resource_written(batch, pfb->cbufs[i]->texture); } } - if (fd_logicop_enabled(ctx)) - batch->gmem_reason |= FD_GMEM_LOGICOP_ENABLED; + if (pfb->zsbuf) + surface_valid(pfb->zsbuf); - for (i = 0; i < pfb->nr_cbufs; i++) { - struct pipe_resource *surf; + for (i = 0; i < pfb->nr_cbufs; i++) + surface_valid(pfb->cbufs[i]); - if (!pfb->cbufs[i]) - continue; + if (fd_logicop_enabled(ctx)) + batch->gmem_reason |= FD_GMEM_LOGICOP_ENABLED; - surf = pfb->cbufs[i]->texture; + if (ctx->dirty & FD_DIRTY_BLEND) { + for (i = 0; i < pfb->nr_cbufs; i++) { + if (!pfb->cbufs[i]) + continue; - if (fd_resource(surf)->valid) { - restore_buffers |= PIPE_CLEAR_COLOR0 << i; - } else { - batch->invalidated |= PIPE_CLEAR_COLOR0 << i; + if (fd_blend_enabled(ctx, i)) + batch->gmem_reason |= FD_GMEM_BLEND_ENABLED; } - - buffers |= PIPE_CLEAR_COLOR0 << i; - - if (fd_blend_enabled(ctx, i)) - batch->gmem_reason |= FD_GMEM_BLEND_ENABLED; } /* Mark SSBOs as being written.. we don't actually know which ones are @@ -420,13 +448,18 @@ fd_clear(struct pipe_context *pctx, unsigned buffers, mtx_lock(&ctx->screen->lock); - if (buffers & PIPE_CLEAR_COLOR) - for (i = 0; i < pfb->nr_cbufs; i++) - if (buffers & (PIPE_CLEAR_COLOR0 << i)) + if (buffers & PIPE_CLEAR_COLOR) { + for (i = 0; i < pfb->nr_cbufs; i++) { + if (buffers & (PIPE_CLEAR_COLOR0 << i)) { resource_written(batch, pfb->cbufs[i]->texture); + surface_valid(pfb->cbufs[i]); + } + } + } if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) { resource_written(batch, pfb->zsbuf->texture); + surface_valid(pfb->zsbuf); batch->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL; } diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 85bbbe271f9..68a5cf24505 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -1124,6 +1124,17 @@ fd_blitter_pipe_end(struct fd_context *ctx) ctx->in_blit = false; } +/** + * Invalidate the contents of the resource. This is used to + * + * (1) implement EGL's semantic of undefined depth/stencil + * contents after a swapbuffers. This allows a tiled renderer (for + * example) to not store the depth buffer. + * + * (2) implement GL's InvalidateBufferData. For backwards compatibility, + * you must only rely on the usability for this purpose when + * PIPE_CAP_INVALIDATE_BUFFER is enabled. + */ static void fd_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc) { @@ -1152,6 +1163,27 @@ fd_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc) rsc->valid = false; } +/** + * Like ->invalidate_surface, but can invalidate a specific layer and level + * of a resource. If the backing surf->texture has just a single layer and + * level (like window system buffers) it is equiv to ->invalidate_resource + */ +static void +fd_invalidate_surface(struct pipe_context *pctx, struct pipe_surface *psurf, + struct pipe_box *region) +{ + struct fd_surface *surf = fd_surface(psurf); + + if (region) { + /* partial invalidate: */ + surf->partial_invalid = true; + surf->invalid_region = *region; + } else { + /* full invalidate: */ + surf->invalid = true; + } +} + static enum pipe_format fd_resource_get_internal_format(struct pipe_resource *prsc) { @@ -1261,5 +1293,6 @@ fd_resource_context_init(struct pipe_context *pctx) pctx->blit = fd_blit; pctx->flush_resource = fd_flush_resource; pctx->invalidate_resource = fd_invalidate_resource; + pctx->invalidate_surface = fd_invalidate_surface; pctx->get_sample_position = fd_get_sample_position; } diff --git a/src/gallium/drivers/freedreno/freedreno_state.h b/src/gallium/drivers/freedreno/freedreno_state.h index 35584e41e3a..18e90dc0056 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.h +++ b/src/gallium/drivers/freedreno/freedreno_state.h @@ -35,11 +35,21 @@ static inline bool fd_depth_enabled(struct fd_context *ctx) return ctx->zsa && ctx->zsa->depth.enabled; } +static inline bool fd_depth_write_enabled(struct fd_context *ctx) +{ + return ctx->zsa && ctx->zsa->depth.writemask; +} + static inline bool fd_stencil_enabled(struct fd_context *ctx) { return ctx->zsa && ctx->zsa->stencil[0].enabled; } +static inline bool fd_stencil_write_enabled(struct fd_context *ctx) +{ + return ctx->zsa && ctx->zsa->stencil[0].writemask; +} + static inline bool fd_logicop_enabled(struct fd_context *ctx) { return ctx->blend && ctx->blend->logicop_enable; diff --git a/src/gallium/drivers/freedreno/freedreno_surface.h b/src/gallium/drivers/freedreno/freedreno_surface.h index 8898f890eda..ce6ac142472 100644 --- a/src/gallium/drivers/freedreno/freedreno_surface.h +++ b/src/gallium/drivers/freedreno/freedreno_surface.h @@ -29,8 +29,13 @@ #include "pipe/p_state.h" +#include "freedreno_resource.h" + struct fd_surface { struct pipe_surface base; + bool invalid; + bool partial_invalid; + struct pipe_box invalid_region; }; static inline struct fd_surface * @@ -39,6 +44,19 @@ fd_surface(struct pipe_surface *psurf) return (struct fd_surface *)psurf; } +static inline bool +fd_surface_valid(struct pipe_surface *psurf) +{ + return fd_resource(psurf->texture)->valid && + !fd_surface(psurf)->invalid; +} + +static inline bool +fd_surface_partially_valid(struct pipe_surface *psurf) +{ + return fd_surface(psurf)->partial_invalid; +} + struct pipe_surface* fd_create_surface(struct pipe_context *pctx, struct pipe_resource *ptex, const struct pipe_surface *surf_tmpl); -- 2.19.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev