Mesa (master): r600g: fix miptree calculations

Dave Airlie airlied at kemper.freedesktop.org
Tue Feb 15 04:39:25 UTC 2011


Module: Mesa
Branch: master
Commit: a661dacf143d7187abc2360ac945db75296f7e23
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a661dacf143d7187abc2360ac945db75296f7e23

Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Feb 15 13:21:50 2011 +1000

r600g: fix miptree calculations

the miptree setup and pitch storing didn't work so well for block
based things like compressed textures. The CB takes blocks, where
the texture sampler takes pixels, and transfers need bytes,

So now we store blocks/bytes and translate to pixels in the sampler.

This is necessary for s3tc to work properly.

---

 src/gallium/drivers/r600/evergreen_state.c |   10 ++--
 src/gallium/drivers/r600/r600_resource.h   |    4 +-
 src/gallium/drivers/r600/r600_state.c      |   10 ++--
 src/gallium/drivers/r600/r600_texture.c    |   64 +++++++++++++---------------
 4 files changed, 41 insertions(+), 47 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index 45469db..261dd8d 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -389,7 +389,7 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte
 	bo[0] = rbuffer->bo;
 	bo[1] = rbuffer->bo;
 
-	pitch = align(tmp->pitch_in_pixels[0], 8);
+	pitch = align(tmp->pitch_in_blocks[0] * util_format_get_blockwidth(state->format), 8);
 	array_mode = tmp->array_mode[0];
 	tile_type = tmp->tile_type;
 
@@ -664,8 +664,8 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state
 	/* XXX quite sure for dx10+ hw don't need any offset hacks */
 	offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture,
 					 level, state->cbufs[cb]->u.tex.first_layer);
-	pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-	slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+	pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+	slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
 	ntype = 0;
 	desc = util_format_description(surf->base.format);
 	if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
@@ -747,8 +747,8 @@ static void evergreen_db(struct r600_pipe_context *rctx, struct r600_pipe_state
 	/* XXX quite sure for dx10+ hw don't need any offset hacks */
 	offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture,
 					 level, state->zsbuf->u.tex.first_layer);
-	pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-	slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+	pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+	slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
 	format = r600_translate_dbformat(state->zsbuf->texture->format);
 	stencil_format = r600_translate_stencilformat(state->zsbuf->texture->format);
 
diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h
index a6d2141..fdcfcd5 100644
--- a/src/gallium/drivers/r600/r600_resource.h
+++ b/src/gallium/drivers/r600/r600_resource.h
@@ -53,8 +53,8 @@ struct r600_resource {
 struct r600_resource_texture {
 	struct r600_resource		resource;
 	unsigned			offset[PIPE_MAX_TEXTURE_LEVELS];
-	unsigned			pitch_in_bytes[PIPE_MAX_TEXTURE_LEVELS];
-	unsigned			pitch_in_pixels[PIPE_MAX_TEXTURE_LEVELS];
+	unsigned			pitch_in_bytes[PIPE_MAX_TEXTURE_LEVELS];  /* transfer */
+	unsigned			pitch_in_blocks[PIPE_MAX_TEXTURE_LEVELS]; /* texture resource */
 	unsigned			layer_size[PIPE_MAX_TEXTURE_LEVELS];
 	unsigned			array_mode[PIPE_MAX_TEXTURE_LEVELS];
 	unsigned			pitch_override;
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index bf74511..bd591bd 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -437,7 +437,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
 	rbuffer = &tmp->resource;
 	bo[0] = rbuffer->bo;
 	bo[1] = rbuffer->bo;
-	pitch = align(tmp->pitch_in_pixels[0], 8);
+	pitch = align(tmp->pitch_in_blocks[0] * util_format_get_blockwidth(state->format), 8);
 	array_mode = tmp->array_mode[0];
 	tile_type = tmp->tile_type;
 
@@ -709,8 +709,8 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
 	/* XXX quite sure for dx10+ hw don't need any offset hacks */
 	offset = r600_texture_get_offset(rtex,
 					 level, state->cbufs[cb]->u.tex.first_layer);
-	pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-	slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+	pitch = rtex->pitch_in_blocks[0] / 8 - 1;
+	slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
 	ntype = 0;
 	desc = util_format_description(surf->base.format);
 	if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
@@ -784,8 +784,8 @@ static void r600_db(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
 	/* XXX quite sure for dx10+ hw don't need any offset hacks */
 	offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture,
 					 level, state->zsbuf->u.tex.first_layer);
-	pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-	slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+	pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+	slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
 	format = r600_translate_dbformat(state->zsbuf->texture->format);
 
 	r600_pipe_state_add_reg(rstate, R_02800C_DB_DEPTH_BASE,
diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
index 30e31e5..db39383 100644
--- a/src/gallium/drivers/r600/r600_texture.c
+++ b/src/gallium/drivers/r600/r600_texture.c
@@ -85,7 +85,7 @@ unsigned r600_texture_get_offset(struct r600_resource_texture *rtex,
 	}
 }
 
-static unsigned r600_get_pixel_alignment(struct pipe_screen *screen,
+static unsigned r600_get_block_alignment(struct pipe_screen *screen,
 					 enum pipe_format format,
 					 unsigned array_mode)
 {
@@ -128,6 +128,7 @@ static unsigned r600_get_height_alignment(struct pipe_screen *screen,
 	case V_038000_ARRAY_LINEAR_ALIGNED:
 		h_align = 8;
 		break;
+	case V_038000_ARRAY_LINEAR_GENERAL:
 	default:
 		h_align = 1;
 		break;
@@ -141,7 +142,7 @@ static unsigned r600_get_base_alignment(struct pipe_screen *screen,
 {
 	struct r600_screen* rscreen = (struct r600_screen *)screen;
 	unsigned pixsize = util_format_get_blocksize(format);
-	int p_align = r600_get_pixel_alignment(screen, format, array_mode);
+	int p_align = r600_get_block_alignment(screen, format, array_mode);
 	int h_align = r600_get_height_alignment(screen, array_mode);
 	int b_align;
 
@@ -169,25 +170,24 @@ static unsigned mip_minify(unsigned size, unsigned level)
 	return val;
 }
 
-static unsigned r600_texture_get_stride(struct pipe_screen *screen,
-					struct r600_resource_texture *rtex,
-					unsigned level)
+static unsigned r600_texture_get_nblocksx(struct pipe_screen *screen,
+					  struct r600_resource_texture *rtex,
+					  unsigned level)
 {
 	struct pipe_resource *ptex = &rtex->resource.b.b.b;
-	unsigned width, stride, tile_width;
+	unsigned nblocksx, block_align, width;
+	unsigned blocksize = util_format_get_blocksize(ptex->format);
 
 	if (rtex->pitch_override)
-		return rtex->pitch_override;
+		return rtex->pitch_override / blocksize;
 
 	width = mip_minify(ptex->width0, level);
-	if (util_format_is_plain(ptex->format)) {
-		tile_width = r600_get_pixel_alignment(screen, ptex->format,
-						      rtex->array_mode[level]);
-		width = align(width, tile_width);
-	}
-	stride = util_format_get_stride(ptex->format, width);
+	nblocksx = util_format_get_nblocksx(ptex->format, width);
 
-	return stride;
+	block_align = r600_get_block_alignment(screen, ptex->format,
+					      rtex->array_mode[level]);
+	nblocksx = align(nblocksx, block_align);
+	return nblocksx;
 }
 
 static unsigned r600_texture_get_nblocksy(struct pipe_screen *screen,
@@ -198,19 +198,11 @@ static unsigned r600_texture_get_nblocksy(struct pipe_screen *screen,
 	unsigned height, tile_height;
 
 	height = mip_minify(ptex->height0, level);
-	if (util_format_is_plain(ptex->format)) {
-		tile_height = r600_get_height_alignment(screen,
-							rtex->array_mode[level]);
-		height = align(height, tile_height);
-	}
-	return util_format_get_nblocksy(ptex->format, height);
-}
-
-/* Get a width in pixels from a stride in bytes. */
-static unsigned pitch_to_width(enum pipe_format format, unsigned pitch_in_bytes)
-{
-	return (pitch_in_bytes / util_format_get_blocksize(format)) *
-		util_format_get_blockwidth(format);
+	height = util_format_get_nblocksy(ptex->format, height);
+	tile_height = r600_get_height_alignment(screen,
+						rtex->array_mode[level]);
+	height = align(height, tile_height);
+	return height;
 }
 
 static void r600_texture_set_array_mode(struct pipe_screen *screen,
@@ -231,7 +223,7 @@ static void r600_texture_set_array_mode(struct pipe_screen *screen,
 		unsigned w, h, tile_height, tile_width;
 
 		tile_height = r600_get_height_alignment(screen, array_mode);
-		tile_width = r600_get_pixel_alignment(screen, ptex->format, array_mode);
+		tile_width = r600_get_block_alignment(screen, ptex->format, array_mode);
 
 		w = mip_minify(ptex->width0, level);
 		h = mip_minify(ptex->height0, level);
@@ -251,17 +243,18 @@ static void r600_setup_miptree(struct pipe_screen *screen,
 	struct pipe_resource *ptex = &rtex->resource.b.b.b;
 	struct radeon *radeon = (struct radeon *)screen->winsys;
 	enum chip_class chipc = r600_get_family_class(radeon);
-	unsigned pitch, size, layer_size, i, offset;
-	unsigned nblocksy;
+	unsigned size, layer_size, i, offset;
+	unsigned nblocksx, nblocksy;
 
 	for (i = 0, offset = 0; i <= ptex->last_level; i++) {
+		unsigned blocksize = util_format_get_blocksize(ptex->format);
+
 		r600_texture_set_array_mode(screen, rtex, i, array_mode);
 
-		pitch = r600_texture_get_stride(screen, rtex, i);
+		nblocksx = r600_texture_get_nblocksx(screen, rtex, i);
 		nblocksy = r600_texture_get_nblocksy(screen, rtex, i);
 
-		layer_size = pitch * nblocksy;
-
+		layer_size = nblocksx * nblocksy * blocksize;
 		if (ptex->target == PIPE_TEXTURE_CUBE) {
 			if (chipc >= R700)
 				size = layer_size * 8;
@@ -275,8 +268,9 @@ static void r600_setup_miptree(struct pipe_screen *screen,
 			offset = align(offset, r600_get_base_alignment(screen, ptex->format, array_mode));
 		rtex->offset[i] = offset;
 		rtex->layer_size[i] = layer_size;
-		rtex->pitch_in_bytes[i] = pitch;
-		rtex->pitch_in_pixels[i] = pitch_to_width(ptex->format, pitch);
+		rtex->pitch_in_blocks[i] = nblocksx; /* CB talks in elements */
+		rtex->pitch_in_bytes[i] = nblocksx * blocksize;
+
 		offset += size;
 	}
 	rtex->size = offset;




More information about the mesa-commit mailing list