From f0f5b8d47ca42ba76f90f0df2bcbe9d5e9eda66c Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Wed, 3 Nov 2021 09:51:26 -0700 Subject: [PATCH] freedreno/a6xx: Fix partial z/s clears with sysmem. We have to set 8c01 to say "leave these channels alone" when clearing/storing just Z or S of z24s8. Fixes the bypass path for KHR-GLES3.packed_depth_stencil.verify_read_pixels.depth24_stencil8. Cc: mesa-stable Fixes: #5592 Part-of: --- src/freedreno/ci/freedreno-a630-fails.txt | 2 -- src/gallium/drivers/freedreno/a6xx/fd6_blitter.c | 19 +++++++------- src/gallium/drivers/freedreno/a6xx/fd6_blitter.h | 4 +-- src/gallium/drivers/freedreno/a6xx/fd6_gmem.c | 32 +++++++++++++++++++----- 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/freedreno/ci/freedreno-a630-fails.txt b/src/freedreno/ci/freedreno-a630-fails.txt index cb9a33a..e4c4ea9 100644 --- a/src/freedreno/ci/freedreno-a630-fails.txt +++ b/src/freedreno/ci/freedreno-a630-fails.txt @@ -599,6 +599,4 @@ spec@!opengl 2.1@pbo,Fail spec@!opengl 2.1@pbo@test_polygon_stip,Fail spec@!opengl 2.1@polygon-stipple-fs,Fail spec@!opengl 3.0@clearbuffer-depth-cs-probe,Timeout -spec@!opengl 3.0@clearbuffer-depth,Fail -spec@!opengl 3.0@clearbuffer-stencil,Fail spec@!opengl 3.1@primitive-restart-xfb generated,Fail diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c index 9435aaf..cc6d6d5 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c @@ -250,7 +250,8 @@ emit_setup(struct fd_batch *batch) static void emit_blit_setup(struct fd_ringbuffer *ring, enum pipe_format pfmt, - bool scissor_enable, union pipe_color_union *color) + bool scissor_enable, union pipe_color_union *color, + uint32_t unknown_8c01) { enum a6xx_format fmt = fd6_color_format(pfmt, TILE6_LINEAR); bool is_srgb = util_format_is_srgb(pfmt); @@ -290,7 +291,7 @@ emit_blit_setup(struct fd_ringbuffer *ring, enum pipe_format pfmt, A6XX_SP_2D_DST_FORMAT_MASK(0xf)); OUT_PKT4(ring, REG_A6XX_RB_2D_UNKNOWN_8C01, 1); - OUT_RING(ring, 0); + OUT_RING(ring, unknown_8c01); } /* buffers need to be handled specially since x/width can exceed the bounds @@ -345,7 +346,7 @@ emit_blit_buffer(struct fd_context *ctx, struct fd_ringbuffer *ring, sshift = sbox->x & 0x3f; dshift = dbox->x & 0x3f; - emit_blit_setup(ring, PIPE_FORMAT_R8_UNORM, false, NULL); + emit_blit_setup(ring, PIPE_FORMAT_R8_UNORM, false, NULL, 0); for (unsigned off = 0; off < sbox->width; off += (0x4000 - 0x40)) { unsigned soff, doff, w, p; @@ -430,7 +431,7 @@ fd6_clear_ubwc(struct fd_batch *batch, struct fd_resource *rsc) assert_dt struct fd_ringbuffer *ring = fd_batch_get_prologue(batch); union pipe_color_union color = {}; - emit_blit_setup(ring, PIPE_FORMAT_R8_UNORM, false, &color); + emit_blit_setup(ring, PIPE_FORMAT_R8_UNORM, false, &color, 0); OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 13); OUT_RING(ring, 0x00000000); @@ -669,7 +670,7 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring, A6XX_GRAS_2D_RESOLVE_CNTL_1_Y(info->scissor.maxy - 1)); } - emit_blit_setup(ring, info->dst.format, info->scissor_enable, NULL); + emit_blit_setup(ring, info->dst.format, info->scissor_enable, NULL, 0); for (unsigned i = 0; i < info->dst.box.depth; i++) { @@ -782,7 +783,7 @@ convert_color(enum pipe_format format, union pipe_color_union *pcolor) 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) + union pipe_color_union *color, uint32_t unknown_8c01) { if (DEBUG_BLIT) { fprintf(stderr, "surface clear:\ndst resource: "); @@ -799,7 +800,7 @@ fd6_clear_surface(struct fd_context *ctx, struct fd_ringbuffer *ring, union pipe_color_union clear_color = convert_color(psurf->format, color); emit_clear_color(ring, psurf->format, &clear_color); - emit_blit_setup(ring, psurf->format, false, &clear_color); + emit_blit_setup(ring, psurf->format, false, &clear_color, unknown_8c01); for (unsigned i = psurf->u.tex.first_layer; i <= psurf->u.tex.last_layer; i++) { @@ -827,7 +828,7 @@ fd6_clear_surface(struct fd_context *ctx, struct fd_ringbuffer *ring, void fd6_resolve_tile(struct fd_batch *batch, struct fd_ringbuffer *ring, - uint32_t base, struct pipe_surface *psurf) + uint32_t base, struct pipe_surface *psurf, uint32_t unknown_8c01) { const struct fd_gmem_stateobj *gmem = batch->gmem_state; uint64_t gmem_base = batch->ctx->screen->gmem_base + base; @@ -848,7 +849,7 @@ fd6_resolve_tile(struct fd_batch *batch, struct fd_ringbuffer *ring, /* Enable scissor bit, which will take into account the window scissor * which is set per-tile */ - emit_blit_setup(ring, psurf->format, true, NULL); + emit_blit_setup(ring, psurf->format, true, NULL, unknown_8c01); /* We shouldn't be using GMEM in the layered rendering case: */ assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h index dd423cf..a354dd6 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h @@ -43,8 +43,8 @@ unsigned fd6_tile_mode(const struct pipe_resource *tmpl); 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) assert_dt; + union pipe_color_union *color, uint32_t unknown_8c01) assert_dt; void fd6_resolve_tile(struct fd_batch *batch, struct fd_ringbuffer *ring, - uint32_t base, struct pipe_surface *psurf) assert_dt; + uint32_t base, struct pipe_surface *psurf, uint32_t unknown_8c01) assert_dt; #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 d6a316c..3b92434 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c @@ -1311,6 +1311,22 @@ needs_resolve(struct pipe_surface *psurf) (psurf->nr_samples != psurf->texture->nr_samples); } +/** + * Returns the UNKNOWN_8C01 value for handling partial depth/stencil + * clear/stores to Z24S8. + */ +static uint32_t +fd6_unknown_8c01(enum pipe_format format, unsigned buffers) +{ + if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT) { + if (buffers == FD_BUFFER_DEPTH) + return 0x08000041; + else if (buffers == FD_BUFFER_STENCIL) + return 0x00084001; + } + return 0; +} + static void emit_resolve_blit(struct fd_batch *batch, struct fd_ringbuffer *ring, uint32_t base, struct pipe_surface *psurf, @@ -1330,7 +1346,12 @@ emit_resolve_blit(struct fd_batch *batch, struct fd_ringbuffer *ring, */ if (needs_resolve(psurf) && !blit_can_resolve(psurf->format) && (buffer != FD_BUFFER_STENCIL)) { - fd6_resolve_tile(batch, ring, base, psurf); + /* We could potentially use fd6_unknown_8c01() to handle partial z/s + * resolve to packed z/s, but we would need a corresponding ability in the + * !resolve case below, so batch_draw_tracking_for_dirty_bits() has us + * just do a restore of the other channel for partial packed z/s writes. + */ + fd6_resolve_tile(batch, ring, base, psurf, 0); return; } @@ -1489,7 +1510,7 @@ emit_sysmem_clears(struct fd_batch *batch, struct fd_ringbuffer *ring) assert_dt continue; fd6_clear_surface(ctx, ring, pfb->cbufs[i], pfb->width, pfb->height, - &color); + &color, 0); } } if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) { @@ -1501,12 +1522,11 @@ emit_sysmem_clears(struct fd_batch *batch, struct fd_ringbuffer *ring) assert_dt ? &fd_resource(pfb->zsbuf->texture)->stencil->b.b : NULL; - if ((has_depth && (buffers & PIPE_CLEAR_DEPTH)) || - (!separate_stencil && (buffers & PIPE_CLEAR_STENCIL))) { + if ((buffers & PIPE_CLEAR_DEPTH) || (!separate_stencil && (buffers & PIPE_CLEAR_STENCIL))) { value.f[0] = batch->clear_depth; value.ui[1] = batch->clear_stencil; fd6_clear_surface(ctx, ring, pfb->zsbuf, pfb->width, pfb->height, - &value); + &value, fd6_unknown_8c01(pfb->zsbuf->format, buffers)); } if (separate_stencil && (buffers & PIPE_CLEAR_STENCIL)) { @@ -1517,7 +1537,7 @@ emit_sysmem_clears(struct fd_batch *batch, struct fd_ringbuffer *ring) assert_dt stencil_surf.texture = separate_stencil; fd6_clear_surface(ctx, ring, &stencil_surf, pfb->width, pfb->height, - &value); + &value, 0); } } -- 2.7.4