Mesa (master): r600g: partialy fix texturing from depth buffer + initial support for untiling

Jerome Glisse glisse at kemper.freedesktop.org
Sun Aug 22 02:52:52 UTC 2010


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

Author: Jerome Glisse <jglisse at redhat.com>
Date:   Sat Aug 21 22:49:22 2010 -0400

r600g: partialy fix texturing from depth buffer + initial support for untiling

Partialy fix texturing from depth buffer, depth buffer is tiled
following different tile organisation that color buffer. This
properly set the tile type & array mode field of texture sampler
when sampling from db resource.

Add initial support to untiling buffer when transfering them,
it's kind of broken by corruption the vertex buffer of previous
draw.

Signed-off-by: Jerome Glisse <jglisse at redhat.com>

---

 src/gallium/drivers/r600/r600_blit.c     |   27 ++++-
 src/gallium/drivers/r600/r600_context.c  |    8 +-
 src/gallium/drivers/r600/r600_resource.h |    3 +
 src/gallium/drivers/r600/r600_screen.h   |    1 +
 src/gallium/drivers/r600/r600_shader.c   |    6 +-
 src/gallium/drivers/r600/r600_state.c    |    7 +-
 src/gallium/drivers/r600/r600_texture.c  |  179 ++++++++++++++++++++---------
 7 files changed, 165 insertions(+), 66 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index aef4fbd..dc57b33 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -120,7 +120,8 @@ static void r600_clear_depth_stencil(struct pipe_context *ctx,
 	r600_queries_resume(ctx);
 }
 
-static void r600_resource_copy_region(struct pipe_context *pipe,
+
+static void r600_resource_copy_region(struct pipe_context *ctx,
 				      struct pipe_resource *dst,
 				      struct pipe_subresource subdst,
 				      unsigned dstx, unsigned dsty, unsigned dstz,
@@ -129,8 +130,28 @@ static void r600_resource_copy_region(struct pipe_context *pipe,
 				      unsigned srcx, unsigned srcy, unsigned srcz,
 				      unsigned width, unsigned height)
 {
-	util_resource_copy_region(pipe, dst, subdst, dstx, dsty, dstz,
-				  src, subsrc, srcx, srcy, srcz, width, height);
+	struct r600_context *rctx = r600_context(ctx);
+	struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
+	struct pipe_sampler_state *samplers[PIPE_MAX_ATTRIBS];
+	struct pipe_sampler_view_state *sampler_views[PIPE_MAX_ATTRIBS];
+	unsigned i;
+
+	for (i = 0; i < rctx->ps_nsampler_view; i++) {
+		sampler_views[i] = &rctx->ps_sampler_view[i]->state.sampler_view;
+	}
+	for (i = 0; i < rctx->ps_nsampler; i++) {
+		samplers[i] = &rctx->ps_sampler[i]->state.sampler;
+	}
+	r600_blitter_save_states(ctx);
+	util_blitter_save_framebuffer(rctx->blitter, fb);
+	util_blitter_save_fragment_sampler_states(rctx->blitter, rctx->ps_nsampler, samplers);
+	util_blitter_save_fragment_sampler_views(rctx->blitter, rctx->ps_nsampler_view, sampler_views);
+
+	util_blitter_copy_region(rctx->blitter, dst, subdst, dstx, dsty, dstz,
+			src, subsrc, srcx, srcy, srcz, width, height,
+			TRUE);
+	/* resume queries */
+	r600_queries_resume(ctx);
 }
 
 void r600_init_blit_functions(struct r600_context *rctx)
diff --git a/src/gallium/drivers/r600/r600_context.c b/src/gallium/drivers/r600/r600_context.c
index 2f59a55..9af2835 100644
--- a/src/gallium/drivers/r600/r600_context.c
+++ b/src/gallium/drivers/r600/r600_context.c
@@ -52,7 +52,7 @@ void r600_flush(struct pipe_context *ctx, unsigned flags,
 	char dname[256];
 
 	/* suspend queries */
-	r600_queries_suspend(rctx);
+	r600_queries_suspend(ctx);
 	if (radeon_ctx_pm4(rctx->ctx))
 		goto out;
 	/* FIXME dumping should be removed once shader support instructions
@@ -61,8 +61,10 @@ void r600_flush(struct pipe_context *ctx, unsigned flags,
 	if (!rctx->ctx->cpm4)
 		goto out;
 	sprintf(dname, "gallium-%08d.bof", dc);
-	if (dc < 10)
+	if (dc < 2) {
 		radeon_ctx_dump_bof(rctx->ctx, dname);
+		R600_ERR("dumped %s\n", dname);
+	}
 #if 1
 	radeon_ctx_submit(rctx->ctx);
 #endif
@@ -74,7 +76,7 @@ out:
 	rctx->ctx = radeon_ctx_decref(rctx->ctx);
 	rctx->ctx = radeon_ctx(rscreen->rw);
 	/* resume queries */
-	r600_queries_resume(rctx);
+	r600_queries_resume(ctx);
 }
 
 static void r600_init_config(struct r600_context *rctx)
diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h
index bb90e76..5ebda02 100644
--- a/src/gallium/drivers/r600/r600_resource.h
+++ b/src/gallium/drivers/r600/r600_resource.h
@@ -48,6 +48,9 @@ struct r600_resource_texture {
 	unsigned long			pitch_override;
 	unsigned long			bpt;
 	unsigned long			size;
+	unsigned			tilled;
+	unsigned			array_mode;
+	unsigned			tile_type;
 };
 
 void r600_init_context_resource_functions(struct r600_context *r600);
diff --git a/src/gallium/drivers/r600/r600_screen.h b/src/gallium/drivers/r600/r600_screen.h
index 53b560c..147be3c 100644
--- a/src/gallium/drivers/r600/r600_screen.h
+++ b/src/gallium/drivers/r600/r600_screen.h
@@ -38,6 +38,7 @@ struct r600_transfer {
 	/* Buffer transfer. */
 	struct pipe_transfer		*buffer_transfer;
 	unsigned			offset;
+	struct pipe_resource		*linear_texture;
 };
 
 struct r600_screen {
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index da1af67..79fc04a 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -105,8 +105,8 @@ int r600_pipe_shader_create(struct pipe_context *ctx,
 	struct r600_screen *rscreen = r600_screen(ctx->screen);
 	int r;
 
-fprintf(stderr, "--------------------------------------------------------------\n");
-tgsi_dump(tokens, 0);
+//fprintf(stderr, "--------------------------------------------------------------\n");
+//tgsi_dump(tokens, 0);
 	if (rpshader == NULL)
 		return -ENOMEM;
 	rpshader->shader.family = radeon_get_family(rscreen->rw);
@@ -120,7 +120,7 @@ tgsi_dump(tokens, 0);
 		R600_ERR("building bytecode failed !\n");
 		return r;
 	}
-fprintf(stderr, "______________________________________________________________\n");
+//fprintf(stderr, "______________________________________________________________\n");
 	return 0;
 }
 
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 93fc68e..e9b03f5 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -773,6 +773,9 @@ static struct radeon_state *r600_db(struct r600_context *rctx)
 		return NULL;
 
 	rtex = (struct r600_resource_texture*)state->zsbuf->texture;
+	rtex->tilled = 1;
+	rtex->array_mode = 2;
+	rtex->tile_type = 1;
 	rbuffer = &rtex->resource;
 	rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
 	rstate->nbo = 1;
@@ -1258,7 +1261,9 @@ static struct radeon_state *r600_resource(struct r600_context *rctx,
 	/* FIXME properly handle first level != 0 */
 	rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD0] =
 			S_038000_DIM(r600_tex_dim(view->texture->target)) |
-	                S_038000_PITCH((pitch / 8) - 1) |
+			S_038000_TILE_MODE(tmp->array_mode) |
+			S_038000_TILE_TYPE(tmp->tile_type) |
+			S_038000_PITCH((pitch / 8) - 1) |
 			S_038000_TEX_WIDTH(view->texture->width0 - 1);
 	rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD1] =
 			S_038004_TEX_HEIGHT(view->texture->height0 - 1) |
diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
index 8a6b5f8..92b4f43 100644
--- a/src/gallium/drivers/r600/r600_texture.c
+++ b/src/gallium/drivers/r600/r600_texture.c
@@ -37,6 +37,21 @@
 
 extern struct u_resource_vtbl r600_texture_vtbl;
 
+/* Copy from a tiled texture to a detiled one. */
+static void r600_copy_from_tiled_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
+{
+	struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
+	struct pipe_resource *texture = transfer->resource;
+	struct pipe_subresource subdst;
+
+	subdst.face = 0;
+	subdst.level = 0;
+	ctx->resource_copy_region(ctx, rtransfer->linear_texture,
+				subdst, 0, 0, 0, texture, transfer->sr,
+				transfer->box.x, transfer->box.y, transfer->box.z,
+				transfer->box.width, transfer->box.height);
+}
+
 static unsigned long r600_texture_get_offset(struct r600_resource_texture *rtex,
 					unsigned level, unsigned zslice,
 					unsigned face)
@@ -106,7 +121,6 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
 		FREE(rtex);
 		return NULL;
 	}
-
 	return &resource->base.b;
 }
 
@@ -208,6 +222,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
 						const struct pipe_box *box)
 {
 	struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
+	struct pipe_resource resource;
 	struct r600_transfer *trans;
 
 	trans = CALLOC_STRUCT(r600_transfer);
@@ -219,14 +234,56 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
 	trans->transfer.box = *box;
 	trans->transfer.stride = rtex->pitch[sr.level];
 	trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face);
+	if (rtex->tilled) {
+		resource.target = PIPE_TEXTURE_2D;
+		resource.format = texture->format;
+		resource.width0 = box->width;
+		resource.height0 = box->height;
+		resource.depth0 = 0;
+		resource.last_level = 0;
+		resource.nr_samples = 0;
+		resource.usage = PIPE_USAGE_DYNAMIC;
+		resource.bind = 0;
+		resource.flags = 0;
+		/* For texture reading, the temporary (detiled) texture is used as
+		 * a render target when blitting from a tiled texture. */
+		if (usage & PIPE_TRANSFER_READ) {
+			resource.bind |= PIPE_BIND_RENDER_TARGET;
+		}
+		/* For texture writing, the temporary texture is used as a sampler
+		 * when blitting into a tiled texture. */
+		if (usage & PIPE_TRANSFER_WRITE) {
+			resource.bind |= PIPE_BIND_SAMPLER_VIEW;
+		}
+		/* Create the temporary texture. */
+		trans->linear_texture = ctx->screen->resource_create(ctx->screen, &resource);
+		if (trans->linear_texture == NULL) {
+			R600_ERR("failed to create temporary texture to hold untiled copy\n");
+			pipe_resource_reference(&trans->transfer.resource, NULL);
+			FREE(trans);
+			return NULL;
+		}
+		if (usage & PIPE_TRANSFER_READ) {
+			/* We cannot map a tiled texture directly because the data is
+			 * in a different order, therefore we do detiling using a blit. */
+			r600_copy_from_tiled_texture(ctx, trans);
+			/* Always referenced in the blit. */
+			ctx->flush(ctx, 0, NULL);
+		}
+	}
 	return &trans->transfer;
 }
 
 void r600_texture_transfer_destroy(struct pipe_context *ctx,
-				   struct pipe_transfer *trans)
+				   struct pipe_transfer *transfer)
 {
-	pipe_resource_reference(&trans->resource, NULL);
-	FREE(trans);
+	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
+
+	if (rtransfer->linear_texture) {
+		pipe_resource_reference(&rtransfer->linear_texture, NULL);
+	}
+	pipe_resource_reference(&transfer->resource, NULL);
+	FREE(transfer);
 }
 
 void* r600_texture_transfer_map(struct pipe_context *ctx,
@@ -239,14 +296,20 @@ void* r600_texture_transfer_map(struct pipe_context *ctx,
 	char *map;
 
 	r600_flush(ctx, 0, NULL);
-
-	resource = (struct r600_resource *)transfer->resource;
+	if (rtransfer->linear_texture) {
+		resource = (struct r600_resource *)rtransfer->linear_texture;
+	} else {
+		resource = (struct r600_resource *)transfer->resource;
+	}
 	if (radeon_bo_map(rscreen->rw, resource->bo)) {
 		return NULL;
 	}
 	radeon_bo_wait(rscreen->rw, resource->bo);
 
 	map = resource->bo->data;
+	if (rtransfer->linear_texture) {
+		return map;
+	}
 
 	return map + rtransfer->offset +
 		transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
@@ -256,10 +319,15 @@ void* r600_texture_transfer_map(struct pipe_context *ctx,
 void r600_texture_transfer_unmap(struct pipe_context *ctx,
 				 struct pipe_transfer* transfer)
 {
+	struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
 	struct r600_screen *rscreen = r600_screen(ctx->screen);
 	struct r600_resource *resource;
 
-	resource = (struct r600_resource *)transfer->resource;
+	if (rtransfer->linear_texture) {
+		resource = (struct r600_resource *)rtransfer->linear_texture;
+	} else {
+		resource = (struct r600_resource *)transfer->resource;
+	}
 	radeon_bo_unmap(rscreen->rw, resource->bo);
 }
 
@@ -283,51 +351,51 @@ void r600_init_screen_texture_functions(struct pipe_screen *screen)
 }
 
 static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format,
-					  const unsigned char *swizzle_view)
+		const unsigned char *swizzle_view)
 {
-    unsigned i;
-    unsigned char swizzle[4];
-    unsigned result = 0;
-    const uint32_t swizzle_shift[4] = {
-	    16, 19, 22, 25,
-    };
-    const uint32_t swizzle_bit[4] = {
-	    0, 1, 2, 3,
-    };
-
-    if (swizzle_view) {
-        /* Combine two sets of swizzles. */
-        for (i = 0; i < 4; i++) {
-            swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
-                         swizzle_format[swizzle_view[i]] : swizzle_view[i];
-        }
-    } else {
-        memcpy(swizzle, swizzle_format, 4);
-    }
-
-    /* Get swizzle. */
-    for (i = 0; i < 4; i++) {
-        switch (swizzle[i]) {
-            case UTIL_FORMAT_SWIZZLE_Y:
-                result |= swizzle_bit[1] << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_Z:
-                result |= swizzle_bit[2] << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_W:
-                result |= swizzle_bit[3] << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_0:
-                result |= V_038010_SQ_SEL_0 << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_1:
-                result |= V_038010_SQ_SEL_1 << swizzle_shift[i];
-                break;
-            default: /* UTIL_FORMAT_SWIZZLE_X */
-                result |= swizzle_bit[0] << swizzle_shift[i];
-        }
-    }
-    return result;
+	unsigned i;
+	unsigned char swizzle[4];
+	unsigned result = 0;
+	const uint32_t swizzle_shift[4] = {
+		16, 19, 22, 25,
+	};
+	const uint32_t swizzle_bit[4] = {
+		0, 1, 2, 3,
+	};
+
+	if (swizzle_view) {
+		/* Combine two sets of swizzles. */
+		for (i = 0; i < 4; i++) {
+			swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
+				swizzle_format[swizzle_view[i]] : swizzle_view[i];
+		}
+	} else {
+		memcpy(swizzle, swizzle_format, 4);
+	}
+
+	/* Get swizzle. */
+	for (i = 0; i < 4; i++) {
+		switch (swizzle[i]) {
+		case UTIL_FORMAT_SWIZZLE_Y:
+			result |= swizzle_bit[1] << swizzle_shift[i];
+			break;
+		case UTIL_FORMAT_SWIZZLE_Z:
+			result |= swizzle_bit[2] << swizzle_shift[i];
+			break;
+		case UTIL_FORMAT_SWIZZLE_W:
+			result |= swizzle_bit[3] << swizzle_shift[i];
+			break;
+		case UTIL_FORMAT_SWIZZLE_0:
+			result |= V_038010_SQ_SEL_0 << swizzle_shift[i];
+			break;
+		case UTIL_FORMAT_SWIZZLE_1:
+			result |= V_038010_SQ_SEL_1 << swizzle_shift[i];
+			break;
+		default: /* UTIL_FORMAT_SWIZZLE_X */
+			result |= swizzle_bit[0] << swizzle_shift[i];
+		}
+	}
+	return result;
 }
 
 /* texture format translate */
@@ -353,13 +421,13 @@ uint32_t r600_translate_texformat(enum pipe_format format,
 	case UTIL_FORMAT_COLORSPACE_ZS:
 		switch (format) {
 		case PIPE_FORMAT_Z16_UNORM:
-			result = V_028010_DEPTH_16;
+			result = V_0280A0_COLOR_16;
 			goto out_word4;
 		case PIPE_FORMAT_Z24X8_UNORM:
-			result = V_028010_DEPTH_X8_24;
+			result = V_0280A0_COLOR_8_24;
 			goto out_word4;
 		case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
-			result = V_028010_DEPTH_8_24;
+			result = V_0280A0_COLOR_8_24;
 			goto out_word4;
 		default:
 			goto out_unknown;
@@ -522,9 +590,8 @@ out_word4:
 		*word4_p = word4;
 	if (yuv_format_p)
 		*yuv_format_p = yuv_format;
-//	fprintf(stderr,"returning %08x %08x %08x\n", result, word4, yuv_format);
 	return result;
 out_unknown:
-//	R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format));
+	R600_ERR("Unable to handle texformat %d %s\n", format, util_format_name(format));
 	return ~0;
 }




More information about the mesa-commit mailing list