Mesa (master): freedreno/a6xx: Add r2d support for GMEM resolves
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Sat Jan 16 17:49:32 UTC 2021
Module: Mesa
Branch: master
Commit: 07a1a341bf78cbfcd1c41491a69f1e4a7be20a93
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=07a1a341bf78cbfcd1c41491a69f1e4a7be20a93
Author: Rob Clark <robdclark at chromium.org>
Date: Wed Jan 13 15:56:27 2021 -0800
freedreno/a6xx: Add r2d support for GMEM resolves
For cases where we need to do an MSAA resolve that BLIT events cannot
handle, fall back to CP_BLIT (r2d)
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4085
Signed-off-by: Rob Clark <robdclark at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8509>
---
src/gallium/drivers/freedreno/a6xx/fd6_blitter.c | 74 +++++++++++++++++++++++-
src/gallium/drivers/freedreno/a6xx/fd6_blitter.h | 10 +++-
src/gallium/drivers/freedreno/a6xx/fd6_gmem.c | 53 +++++++++++++++++
3 files changed, 132 insertions(+), 5 deletions(-)
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
index f7e66ef05ee..6ea48b04470 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
@@ -256,9 +256,6 @@ emit_blit_setup(struct fd_ringbuffer *ring,
bool is_srgb = util_format_is_srgb(pfmt);
enum a6xx_2d_ifmt ifmt = fd6_ifmt(fmt);
- OUT_PKT7(ring, CP_SET_MARKER, 1);
- OUT_RING(ring, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
-
if (is_srgb) {
assert(ifmt == R2D_UNORM8);
ifmt = R2D_UNORM8_SRGB;
@@ -789,6 +786,77 @@ fd6_clear_surface(struct fd_context *ctx,
}
}
+void
+fd6_resolve_tile(struct fd_batch *batch, struct fd_ringbuffer *ring,
+ uint32_t base, struct pipe_surface *psurf)
+{
+ const struct fd_gmem_stateobj *gmem = batch->gmem_state;
+ uint64_t gmem_base = batch->ctx->screen->gmem_base + base;
+ uint32_t gmem_pitch = gmem->bin_w * batch->framebuffer.samples *
+ util_format_get_blocksize(psurf->format);
+
+ OUT_PKT4(ring, REG_A6XX_GRAS_2D_DST_TL, 2);
+ OUT_RING(ring, A6XX_GRAS_2D_DST_TL_X(0) | A6XX_GRAS_2D_DST_TL_Y(0));
+ OUT_RING(ring, A6XX_GRAS_2D_DST_BR_X(psurf->width - 1) |
+ A6XX_GRAS_2D_DST_BR_Y(psurf->height - 1));
+
+ OUT_PKT4(ring, REG_A6XX_GRAS_2D_SRC_TL_X, 4);
+ OUT_RING(ring, A6XX_GRAS_2D_SRC_TL_X(0));
+ OUT_RING(ring, A6XX_GRAS_2D_SRC_BR_X(psurf->width - 1));
+ OUT_RING(ring, A6XX_GRAS_2D_SRC_TL_Y(0));
+ OUT_RING(ring, A6XX_GRAS_2D_SRC_BR_Y(psurf->height - 1));
+
+ /* Enable scissor bit, which will take into account the window scissor
+ * which is set per-tile
+ */
+ emit_blit_setup(ring, psurf->format, true, NULL);
+
+ /* We shouldn't be using GMEM in the layered rendering case: */
+ assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
+
+ emit_blit_dst(ring, psurf->texture, psurf->format, psurf->u.tex.level,
+ psurf->u.tex.first_layer);
+
+ enum a6xx_format sfmt = fd6_pipe2color(psurf->format);
+ enum a3xx_msaa_samples samples = fd_msaa_samples(batch->framebuffer.samples);
+
+ OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 10);
+ OUT_RING(ring, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(sfmt) |
+ A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(TILE6_2) |
+ A6XX_SP_PS_2D_SRC_INFO_SAMPLES(samples) |
+ COND(samples > MSAA_ONE, A6XX_SP_PS_2D_SRC_INFO_SAMPLES_AVERAGE) |
+ COND(util_format_is_srgb(psurf->format), A6XX_SP_PS_2D_SRC_INFO_SRGB) |
+ A6XX_SP_PS_2D_SRC_INFO_UNK20 |
+ A6XX_SP_PS_2D_SRC_INFO_UNK22);
+ OUT_RING(ring, A6XX_SP_PS_2D_SRC_SIZE_WIDTH(psurf->width) |
+ A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(psurf->height));
+ OUT_RING(ring, gmem_base); /* SP_PS_2D_SRC_LO */
+ OUT_RING(ring, gmem_base >> 32); /* SP_PS_2D_SRC_HI */
+ OUT_RING(ring, A6XX_SP_PS_2D_SRC_PITCH_PITCH(gmem_pitch));
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, 0x00000000);
+
+ /* sync GMEM writes with CACHE. */
+ fd6_cache_inv(batch, ring);
+
+ /* Wait for CACHE_INVALIDATE to land */
+ fd_wfi(batch, ring);
+
+ OUT_PKT7(ring, CP_BLIT, 1);
+ OUT_RING(ring, CP_BLIT_0_OP(BLIT_OP_SCALE));
+
+ OUT_WFI5(ring);
+
+ /* CP_BLIT writes to the CCU, unlike CP_EVENT_WRITE::BLIT which writes to
+ * sysmem, and we generally assume that GMEM renderpasses leave their
+ * results in sysmem, so we need to flush manually here.
+ */
+ fd6_event_write(batch, ring, PC_CCU_FLUSH_COLOR_TS, true);
+}
+
static bool
handle_rgba_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
{
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h
index b75013c6d04..6494e96c4dd 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h
@@ -35,9 +35,15 @@
void fd6_blitter_init(struct pipe_context *pctx);
unsigned fd6_tile_mode(const struct pipe_resource *tmpl);
-void
-fd6_clear_surface(struct fd_context *ctx,
+/*
+ * Blitter APIs used by gmem for cases that need CP_BLIT's (r2d)
+ * instead of CP_EVENT_WRITE::BLITs
+ */
+
+void fd6_clear_surface(struct fd_context *ctx,
struct fd_ringbuffer *ring, struct pipe_surface *psurf,
uint32_t width, uint32_t height, union pipe_color_union *color);
+void fd6_resolve_tile(struct fd_batch *batch, struct fd_ringbuffer *ring,
+ uint32_t base, struct pipe_surface *psurf);
#endif /* FD6_BLIT_H_ */
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
index affba171fc1..0bb01eb7fa7 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
@@ -1129,6 +1129,47 @@ fd6_emit_tile_renderprep(struct fd_batch *batch, const struct fd_tile *tile)
trace_end_clear_restore(&batch->trace);
}
+static bool
+blit_can_resolve(enum pipe_format format)
+{
+ const struct util_format_description *desc = util_format_description(format);
+
+ /* blit event can only do resolve for simple cases:
+ * averaging samples as unsigned integers or choosing only one sample
+ */
+ if (util_format_is_snorm(format) || util_format_is_srgb(format))
+ return false;
+
+ /* can't do formats with larger channel sizes
+ * note: this includes all float formats
+ * note2: single channel integer formats seem OK
+ */
+ if (desc->channel[0].size > 10)
+ return false;
+
+ switch (format) {
+ /* for unknown reasons blit event can't msaa resolve these formats when tiled
+ * likely related to these formats having different layout from other cpp=2 formats
+ */
+ case PIPE_FORMAT_R8G8_UNORM:
+ case PIPE_FORMAT_R8G8_UINT:
+ case PIPE_FORMAT_R8G8_SINT:
+ /* TODO: this one should be able to work? */
+ case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+ return false;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static bool
+needs_resolve(struct pipe_surface *psurf)
+{
+ return psurf->nr_samples && (psurf->nr_samples != psurf->texture->nr_samples);
+}
+
static void
emit_resolve_blit(struct fd_batch *batch,
struct fd_ringbuffer *ring,
@@ -1142,6 +1183,18 @@ emit_resolve_blit(struct fd_batch *batch,
if (!fd_resource(psurf->texture)->valid)
return;
+ /* if we need to resolve, but cannot with BLIT event, we instead need
+ * to generate per-tile CP_BLIT (r2d) commands:
+ *
+ * The separate-stencil is a special case, we might need to use CP_BLIT
+ * for depth, but we can still resolve stencil with a BLIT event
+ */
+ if (needs_resolve(psurf) && !blit_can_resolve(psurf->format) &&
+ (buffer != FD_BUFFER_STENCIL)) {
+ fd6_resolve_tile(batch, ring, base, psurf);
+ return;
+ }
+
switch (buffer) {
case FD_BUFFER_COLOR:
break;
More information about the mesa-commit
mailing list