freedreno/a6xx: Support some depth/stencil blits on blitter

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>
This commit is contained in:
Kristian H. Kristensen
2019-02-01 17:15:45 -08:00
parent e9592da2b4
commit 03a01e5d23

View 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);