freedreno/a6xx: Support some depth/stencil blits on blitter
authorKristian H. Kristensen <hoegsberg@chromium.org>
Sat, 2 Feb 2019 01:15:45 +0000 (17:15 -0800)
committerKristian H. Kristensen <hoegsberg@chromium.org>
Mon, 11 Feb 2019 20:26:21 +0000 (12:26 -0800)
We can rewrite almost all depth stencil blits to various red-only
blits.  The exception is depth-only or stencil-only blits into z24s8
combined depth stencil buffer. We can fall back for depth-only, but
stencil-only remains broken.

Fixes

  dEQP-GLES3.functional.fbo.blit.depth_stencil.depth24_stencil8_basic
  dEQP-GLES3.functional.fbo.blit.depth_stencil.depth24_stencil8_scale
  dEQP-GLES3.functional.fbo.blit.depth_stencil.depth32f_stencil8_basic
  dEQP-GLES3.functional.fbo.blit.depth_stencil.depth32f_stencil8_scale
  dEQP-GLES3.functional.fbo.blit.depth_stencil.depth32f_stencil8_stencil_only

Reviewed-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Kristian H. Kristensen <hoegsberg@chromium.org>
src/gallium/drivers/freedreno/a6xx/fd6_blitter.c

index b107d4840504aafad6c8b6aa712bcfd5254c583d..0a741acf1d82c69095c143f3df67e893c1178a10 100644 (file)
@@ -56,6 +56,18 @@ static bool
 ok_format(enum pipe_format pfmt)
 {
        enum a6xx_color_fmt fmt = fd6_pipe2color(pfmt);
+
+       switch (pfmt) {
+       case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+       case PIPE_FORMAT_Z24X8_UNORM:
+       case PIPE_FORMAT_Z16_UNORM:
+       case PIPE_FORMAT_Z32_UNORM:
+       case PIPE_FORMAT_Z32_FLOAT:
+       case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+       case PIPE_FORMAT_S8_UINT:
+               return true;
+       }
+
        if (fmt == ~0)
                return false;
 
@@ -138,6 +150,11 @@ can_do_blit(const struct pipe_blit_info *info)
 
        fail_if(info->alpha_blend);
 
+       /* We can blit depth and stencil in most cases, except for depth only or
+        * stencil only to combined zs. */
+       fail_if(info->dst.format == PIPE_FORMAT_Z24_UNORM_S8_UINT &&
+                       info->mask != PIPE_MASK_ZS);
+
        return true;
 }
 
@@ -505,6 +522,67 @@ emit_blit_texture(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
        }
 }
 
+static void
+rewrite_zs_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
+{
+       struct pipe_blit_info separate = *info;
+
+       switch (info->src.format) {
+       case PIPE_FORMAT_S8_UINT:
+               debug_assert(info->mask == PIPE_MASK_S);
+               separate.mask = PIPE_MASK_R;
+               separate.src.format = PIPE_FORMAT_R8_UNORM;
+               separate.dst.format = PIPE_FORMAT_R8_UNORM;
+               emit_blit_texture(ring, &separate);
+               break;
+
+       case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+               if (info->mask & PIPE_MASK_Z) {
+                       separate.mask = PIPE_MASK_R;
+                       separate.src.format = PIPE_FORMAT_R32_FLOAT;
+                       separate.dst.format = PIPE_FORMAT_R32_FLOAT;
+                       emit_blit_texture(ring, &separate);
+               }
+               if (info->mask & PIPE_MASK_S) {
+                       separate.mask = PIPE_MASK_R;
+                       separate.src.format = PIPE_FORMAT_R8_UNORM;
+                       separate.dst.format = PIPE_FORMAT_R8_UNORM;
+                       separate.src.resource = &fd_resource(info->src.resource)->stencil->base;
+                       separate.dst.resource = &fd_resource(info->dst.resource)->stencil->base;
+                       emit_blit_texture(ring, &separate);
+               }
+               break;
+
+       case PIPE_FORMAT_Z16_UNORM:
+               separate.mask = PIPE_MASK_R;
+               separate.src.format = PIPE_FORMAT_R16_UNORM;
+               separate.dst.format = PIPE_FORMAT_R16_UNORM;
+               emit_blit_texture(ring, &separate);
+               break;
+
+       case PIPE_FORMAT_Z32_UNORM:
+       case PIPE_FORMAT_Z32_FLOAT:
+               debug_assert(info->mask == PIPE_MASK_Z);
+               separate.mask = PIPE_MASK_R;
+               separate.src.format = PIPE_FORMAT_R32_UINT;
+               separate.dst.format = PIPE_FORMAT_R32_UINT;
+               emit_blit_texture(ring, &separate);
+               break;
+
+       case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+       case PIPE_FORMAT_Z24X8_UNORM:
+       case PIPE_FORMAT_X8Z24_UNORM:
+               separate.mask = PIPE_MASK_R;
+               separate.src.format = PIPE_FORMAT_R32_UINT;
+               separate.dst.format = PIPE_FORMAT_R32_UINT;
+               emit_blit_texture(ring, &separate);
+               break;
+
+       default:
+               unreachable("");
+       }
+}
+
 static bool
 fd6_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
 {
@@ -538,7 +616,12 @@ fd6_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
                /* I don't *think* we need to handle blits between buffer <-> !buffer */
                debug_assert(info->src.resource->target != PIPE_BUFFER);
                debug_assert(info->dst.resource->target != PIPE_BUFFER);
-               emit_blit_texture(batch->draw, info);
+
+               if (info->mask & (PIPE_MASK_ZS)) {
+                       rewrite_zs_blit(batch->draw, info);
+               } else {
+                       emit_blit_texture(batch->draw, info);
+               }
        }
 
        fd6_event_write(batch, batch->draw, 0x1d, true);