[Mesa-stable] [PATCH] radeonsi: fix blitting the last 2 mipmap levels of compressed textures

Marek Olšák maraeo at gmail.com
Tue Oct 29 23:29:18 CET 2013


From: Marek Olšák <marek.olsak at amd.com>

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>
(cherry picked from commit 57f38e9f921bcfac0087765b4acb2c258604ea29)

Conflicts:
	src/gallium/drivers/radeonsi/r600_resource.h
	src/gallium/drivers/radeonsi/si_state.c
---
 src/gallium/drivers/radeonsi/r600_blit.c     | 16 ++++++++++++++++
 src/gallium/drivers/radeonsi/r600_resource.h |  2 ++
 src/gallium/drivers/radeonsi/si_state.c      |  5 +++--
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/r600_blit.c b/src/gallium/drivers/radeonsi/r600_blit.c
index 34f14ba..baf3c14 100644
--- a/src/gallium/drivers/radeonsi/r600_blit.c
+++ b/src/gallium/drivers/radeonsi/r600_blit.c
@@ -322,6 +322,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,
@@ -355,6 +370,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 f7b60ed..6a766c1 100644
--- a/src/gallium/drivers/radeonsi/r600_resource.h
+++ b/src/gallium/drivers/radeonsi/r600_resource.h
@@ -53,6 +53,8 @@ struct r600_resource_texture {
 	struct r600_resource_texture	*flushed_depth_texture;
 	boolean				is_flushing_texture;
 	struct radeon_surface		surface;
+
+	unsigned mipmap_shift;
 };
 
 struct r600_surface {
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 58e5a56..bd8a59f 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -2394,6 +2394,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) |
@@ -2404,8 +2405,8 @@ static struct pipe_sampler_view *si_create_sampler_view(struct pipe_context *ctx
 			  S_008F1C_DST_SEL_Y(si_map_swizzle(swizzle[1])) |
 			  S_008F1C_DST_SEL_Z(si_map_swizzle(swizzle[2])) |
 			  S_008F1C_DST_SEL_W(si_map_swizzle(swizzle[3])) |
-			  S_008F1C_BASE_LEVEL(state->u.tex.first_level) |
-			  S_008F1C_LAST_LEVEL(state->u.tex.last_level) |
+			  S_008F1C_BASE_LEVEL(state->u.tex.first_level - tmp->mipmap_shift) |
+			  S_008F1C_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)));
-- 
1.8.1.2



More information about the mesa-stable mailing list