[Mesa-dev] [PATCH 6/6] freedreno: support invalidate_{sub_}surface
Rob Clark
robdclark at gmail.com
Tue Dec 11 22:50:08 UTC 2018
Signed-off-by: Rob Clark <robdclark at 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 | 41 ++++++++
.../drivers/freedreno/freedreno_state.h | 10 ++
.../drivers/freedreno/freedreno_surface.h | 18 ++++
7 files changed, 145 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..b5c1c321bf0 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_scissor_state zsbuf;
+ struct pipe_scissor_state 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..07c3ecfa805 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_rect;
} 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_rect;
+ } 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..283f7de89bc 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,34 @@ 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)
+{
+ fd_surface(psurf)->invalid = true;
+}
+
+/**
+ * Invalidate a portion of a surface. This is used to
+ *
+ * (1) implement glInvalidateSubFramebuffer() and friends
+ * (2) as a hint before a scissored clear (which is turned into draw_vbo()
+ * that the cleared rect can be discarded
+ */
+static void
+fd_invalidate_sub_surface(struct pipe_context *pctx,
+ struct pipe_surface *psurf, const struct pipe_scissor_state *rect)
+{
+ struct fd_surface *surf = fd_surface(psurf);
+
+ surf->partial_invalid = true;
+ surf->invalid_rect = *rect;
+}
+
static enum pipe_format
fd_resource_get_internal_format(struct pipe_resource *prsc)
{
@@ -1261,5 +1300,7 @@ 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->invalidate_sub_surface = fd_invalidate_sub_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..489bc705e9a 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_scissor_state invalid_rect;
};
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
More information about the mesa-dev
mailing list