r600: evergreen stencil/depth mipmap blit workaround
In certain cases, the hardware fails to properly process a mipmap level
of these special stencil and depth formats. This happens at width=16.
This change adds a software workaround.
Modifying the corresponding mipmap nblk_x, and the other related
values, could make the tests below to work. Anyway, this method
generates regressions.
This change was tested on palm and cayman and fixes the following tests:
spec/arb_framebuffer_object/framebuffer-blit-levels read stencil: fail pass
spec/arb_depth_buffer_float/fbo-clear-formats stencil/gl_depth32f_stencil8: fail pass
Cc: mesa-stable
Signed-off-by: Patrick Lerda <patrick9876@free.fr>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31957>
(cherry picked from commit ac78692be4
)
This commit is contained in:

committed by
Dylan Baker

parent
afcbe85940
commit
48e5c246c4
@@ -574,7 +574,7 @@
|
||||
"description": "r600: evergreen stencil/depth mipmap blit workaround",
|
||||
"nominated": true,
|
||||
"nomination_type": 1,
|
||||
"resolution": 0,
|
||||
"resolution": 1,
|
||||
"main_sha": null,
|
||||
"because_sha": null,
|
||||
"notes": null
|
||||
|
@@ -891,6 +891,64 @@ static bool do_hardware_msaa_resolve(struct pipe_context *ctx,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void r600_stencil_z24unorms8_to_z24unorms8uint(struct pipe_context *ctx,
|
||||
struct pipe_resource *dst, struct pipe_resource *src,
|
||||
const struct pipe_box *box_dst, const struct pipe_box *box_src,
|
||||
const unsigned dst_level, const unsigned src_level)
|
||||
{
|
||||
struct pipe_transfer *tsrc;
|
||||
uint8_t *slice_src = pipe_texture_map_3d(ctx, src, src_level, PIPE_MAP_READ,
|
||||
box_src->x, box_src->y, box_src->z,
|
||||
box_src->width, box_src->height, box_src->depth, &tsrc);
|
||||
if (slice_src) {
|
||||
struct pipe_transfer *tdst;
|
||||
uint8_t *slice_dst = pipe_texture_map_3d(ctx, dst, dst_level, PIPE_MAP_READ_WRITE,
|
||||
box_dst->x, box_dst->y, box_dst->z,
|
||||
box_src->width, box_src->height, box_src->depth, &tdst);
|
||||
if (slice_dst) {
|
||||
for (unsigned slice = 0; slice < box_src->depth; slice++)
|
||||
for (unsigned row = 0; row < box_src->height; row++) {
|
||||
for (unsigned k = 0; k < box_src->width; k++) {
|
||||
slice_dst[k * 4 + 3] = slice_src[k * 4 + 3];
|
||||
}
|
||||
slice_src += tsrc->stride / sizeof(*slice_src);
|
||||
slice_dst += tdst->stride / sizeof(*slice_dst);
|
||||
}
|
||||
pipe_texture_unmap(ctx, tdst);
|
||||
}
|
||||
pipe_texture_unmap(ctx, tsrc);
|
||||
}
|
||||
}
|
||||
|
||||
static void r600_stencil_z32floats8x24_to_z24unorms8(struct pipe_context *ctx,
|
||||
struct pipe_resource *dst, struct pipe_resource *src,
|
||||
const struct pipe_box *box_dst, const struct pipe_box *box_src,
|
||||
const unsigned dst_level, const unsigned src_level)
|
||||
{
|
||||
struct pipe_transfer *tsrc;
|
||||
uint8_t *slice_src = pipe_texture_map_3d(ctx, src, src_level, PIPE_MAP_READ,
|
||||
box_src->x, box_src->y, box_src->z,
|
||||
box_src->width, box_src->height, box_src->depth, &tsrc);
|
||||
if (slice_src) {
|
||||
struct pipe_transfer *tdst;
|
||||
uint8_t *slice_dst = pipe_texture_map_3d(ctx, dst, dst_level, PIPE_MAP_READ_WRITE,
|
||||
box_dst->x, box_dst->y, box_dst->z,
|
||||
box_src->width, box_src->height, box_src->depth, &tdst);
|
||||
if (slice_dst) {
|
||||
for (unsigned slice = 0; slice < box_src->depth; slice++)
|
||||
for (unsigned row = 0; row < box_src->height; row++) {
|
||||
for (unsigned k = 0; k < box_src->width; k++) {
|
||||
slice_dst[k * 4 + 3] = slice_src[k * 8 + 4];
|
||||
}
|
||||
slice_src += tsrc->stride / sizeof(*slice_src);
|
||||
slice_dst += tdst->stride / sizeof(*slice_dst);
|
||||
}
|
||||
pipe_texture_unmap(ctx, tdst);
|
||||
}
|
||||
pipe_texture_unmap(ctx, tsrc);
|
||||
}
|
||||
}
|
||||
|
||||
static void r600_blit(struct pipe_context *ctx,
|
||||
const struct pipe_blit_info *info)
|
||||
{
|
||||
@@ -933,6 +991,48 @@ static void r600_blit(struct pipe_context *ctx,
|
||||
util_try_blit_via_copy_region(ctx, info, rctx->b.render_cond != NULL))
|
||||
return;
|
||||
|
||||
{
|
||||
const bool blit_box_same_size = info->src.box.width == info->dst.box.width &&
|
||||
info->src.box.height == info->dst.box.height &&
|
||||
info->src.box.depth == info->dst.box.depth;
|
||||
const bool blit_stencil = (info->mask & PIPE_MASK_S) != 0;
|
||||
const bool src_is_ZS = info->src.format == PIPE_FORMAT_Z24_UNORM_S8_UINT ||
|
||||
info->src.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT;
|
||||
|
||||
if (unlikely(rctx->b.gfx_level >= EVERGREEN &&
|
||||
blit_stencil && blit_box_same_size && src_is_ZS &&
|
||||
info->dst.format == PIPE_FORMAT_Z24_UNORM_S8_UINT &&
|
||||
info->src.resource->last_level &&
|
||||
!info->dst.resource->last_level &&
|
||||
info->src.box.width >= 16 && info->src.box.width < 32)) {
|
||||
if (info->mask & ~PIPE_MASK_S) {
|
||||
struct pipe_blit_info blit;
|
||||
memcpy(&blit, info, sizeof(blit));
|
||||
blit.mask = info->mask & ~PIPE_MASK_S;
|
||||
r600_blitter_begin(ctx, R600_BLIT |
|
||||
(info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND));
|
||||
util_blitter_blit(rctx->blitter, &blit, NULL);
|
||||
r600_blitter_end(ctx);
|
||||
}
|
||||
|
||||
assert(util_format_get_blocksize(PIPE_FORMAT_Z24_UNORM_S8_UINT) == 4);
|
||||
assert(util_format_get_blocksize(PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) == 8);
|
||||
|
||||
if (info->src.format == info->dst.format)
|
||||
r600_stencil_z24unorms8_to_z24unorms8uint(ctx,
|
||||
info->dst.resource, info->src.resource,
|
||||
&info->dst.box, &info->src.box,
|
||||
info->dst.level, info->src.level);
|
||||
else
|
||||
r600_stencil_z32floats8x24_to_z24unorms8(ctx,
|
||||
info->dst.resource, info->src.resource,
|
||||
&info->dst.box, &info->src.box,
|
||||
info->dst.level, info->src.level);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
r600_blitter_begin(ctx, R600_BLIT |
|
||||
(info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND));
|
||||
util_blitter_blit(rctx->blitter, info, NULL);
|
||||
|
Reference in New Issue
Block a user