Mesa (master): radeonsi: fix blitting the last 2 mipmap levels of compressed textures
Marek Olšák
mareko at kemper.freedesktop.org
Wed Sep 25 18:50:34 UTC 2013
Module: Mesa
Branch: master
Commit: 57f38e9f921bcfac0087765b4acb2c258604ea29
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=57f38e9f921bcfac0087765b4acb2c258604ea29
Author: Marek Olšák <marek.olsak at amd.com>
Date: Tue Sep 24 14:15:00 2013 +0200
radeonsi: fix blitting the last 2 mipmap levels of compressed textures
This fixes compressedteximage piglit tests.
+10 piglits
Evergreen and Cayman have the same issue. R600 and R700 don't.
Cc: "9.2" <mesa-stable at lists.freedesktop.org>
Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
---
src/gallium/drivers/radeonsi/r600_blit.c | 16 ++++++++++++++++
src/gallium/drivers/radeonsi/r600_resource.h | 1 +
src/gallium/drivers/radeonsi/si_state.c | 5 +++--
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/src/gallium/drivers/radeonsi/r600_blit.c b/src/gallium/drivers/radeonsi/r600_blit.c
index fef4ccc..483596e 100644
--- a/src/gallium/drivers/radeonsi/r600_blit.c
+++ b/src/gallium/drivers/radeonsi/r600_blit.c
@@ -430,6 +430,21 @@ static void r600_compressed_to_blittable(struct pipe_resource *tex,
rtex->surface.level[0].npix_y = util_format_get_nblocksy(orig->format, orig->npix0_y);
rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x);
rtex->surface.level[level].npix_y = util_format_get_nblocksy(orig->format, orig->npix_y);
+
+ /* By dividing the dimensions by 4, we effectively decrement
+ * last_level by 2, therefore the last 2 mipmap levels disappear and
+ * aren't blittable. Note that the last 3 mipmap levels (4x4, 2x2,
+ * 1x1) have equal slice sizes, which is an important assumption
+ * for this to work.
+ *
+ * In order to make the last 2 mipmap levels blittable, we have to
+ * add the slice size of the last mipmap level to the texture
+ * address, so that even though the hw thinks it reads last_level-2,
+ * it will actually read last_level-1, and if we add the slice size*2,
+ * it will read last_level. That's how this workaround works.
+ */
+ if (level > rtex->resource.b.b.last_level-2)
+ rtex->mipmap_shift = level - (rtex->resource.b.b.last_level-2);
}
static void r600_change_format(struct pipe_resource *tex,
@@ -463,6 +478,7 @@ static void r600_reset_blittable_to_orig(struct pipe_resource *tex,
rtex->surface.level[0].npix_y = orig->npix0_y;
rtex->surface.level[level].npix_x = orig->npix_x;
rtex->surface.level[level].npix_y = orig->npix_y;
+ rtex->mipmap_shift = 0;
}
static void r600_resource_copy_region(struct pipe_context *ctx,
diff --git a/src/gallium/drivers/radeonsi/r600_resource.h b/src/gallium/drivers/radeonsi/r600_resource.h
index 3f9c769..185ae25 100644
--- a/src/gallium/drivers/radeonsi/r600_resource.h
+++ b/src/gallium/drivers/radeonsi/r600_resource.h
@@ -67,6 +67,7 @@ struct r600_texture {
struct r600_texture *flushed_depth_texture;
boolean is_flushing_texture;
struct radeon_surface surface;
+ unsigned mipmap_shift;
/* Colorbuffer compression and fast clear. */
struct r600_fmask_info fmask;
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 3be17a5..8cec3e2 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -2469,6 +2469,7 @@ static struct pipe_sampler_view *si_create_sampler_view(struct pipe_context *ctx
va = r600_resource_va(ctx->screen, texture);
va += surflevel[0].offset;
+ va += tmp->mipmap_shift * surflevel[texture->last_level].slice_size;
view->state[0] = va >> 8;
view->state[1] = (S_008F14_BASE_ADDRESS_HI(va >> 40) |
S_008F14_DATA_FORMAT(format) |
@@ -2480,10 +2481,10 @@ static struct pipe_sampler_view *si_create_sampler_view(struct pipe_context *ctx
S_008F1C_DST_SEL_Z(si_map_swizzle(swizzle[2])) |
S_008F1C_DST_SEL_W(si_map_swizzle(swizzle[3])) |
S_008F1C_BASE_LEVEL(texture->nr_samples > 1 ?
- 0 : state->u.tex.first_level) |
+ 0 : state->u.tex.first_level - tmp->mipmap_shift) |
S_008F1C_LAST_LEVEL(texture->nr_samples > 1 ?
util_logbase2(texture->nr_samples) :
- state->u.tex.last_level) |
+ state->u.tex.last_level - tmp->mipmap_shift) |
S_008F1C_TILING_INDEX(si_tile_mode_index(tmp, 0, false)) |
S_008F1C_POW2_PAD(texture->last_level > 0) |
S_008F1C_TYPE(si_tex_dim(texture->target, texture->nr_samples)));
More information about the mesa-commit
mailing list