From 03a01e5d23a566cdde989cd98f6a757cb98b7154 Mon Sep 17 00:00:00 2001 From: "Kristian H. Kristensen" Date: Fri, 1 Feb 2019 17:15:45 -0800 Subject: [PATCH] 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 Signed-off-by: Kristian H. Kristensen --- src/gallium/drivers/freedreno/a6xx/fd6_blitter.c | 85 +++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c index b107d48..0a741ac 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c @@ -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); -- 2.7.4