[Mesa-dev] [PATCH] [RFC] r600g: improve flushed depth texture allocation

Vadim Girlin vadimgirlin at gmail.com
Sun Jun 24 06:43:19 PDT 2012


Allocate flushed depth texture in the VRAM if we aren't going to access it by
CPU. If we need CPU access later, then it'll be reallocated in the GTT. 
Currently it's not reallocated in the opposite direction (GTT->VRAM), though
probably we might want to do it too. Anyway, it helps the apps that don't need
to access flushed depth texture by CPU at all, e.g. Lightsmark.

Improves performance for Lightsmark.

Signed-off-by: Vadim Girlin <vadimgirlin at gmail.com>
---

No regressions on evergreen, also it somehow fixes fbo-clear-formats and 
fbo-generate-mipmap-formats, that were failing on depth/stencil formats.

 src/gallium/drivers/r600/evergreen_state.c |    5 +++--
 src/gallium/drivers/r600/r600_blit.c       |    2 +-
 src/gallium/drivers/r600/r600_resource.h   |    3 ++-
 src/gallium/drivers/r600/r600_state.c      |    2 +-
 src/gallium/drivers/r600/r600_texture.c    |   31 ++++++++++++++++++++--------
 5 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index b618ca8..281781e 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -988,7 +988,7 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte
 	}
 
 	if (tmp->is_depth && !tmp->is_flushing_texture) {
-		r600_texture_depth_flush(ctx, texture, TRUE);
+		r600_texture_depth_flush(ctx, texture, TRUE, FALSE);
 		tmp = tmp->flushed_depth_texture;
 	}
 
@@ -1310,7 +1310,8 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta
 		rctx->have_depth_fb = TRUE;
 
 	if (rtex->is_depth && !rtex->is_flushing_texture) {
-	        r600_texture_depth_flush(&rctx->context, state->cbufs[cb]->texture, TRUE);
+		r600_texture_depth_flush(&rctx->context, state->cbufs[cb]->texture,
+				TRUE, FALSE);
 		rtex = rtex->flushed_depth_texture;
 	}
 
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index 1122f3e..4a78f80 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -342,7 +342,7 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
 	}
 
 	if (rsrc->is_depth && !rsrc->is_flushing_texture)
-		r600_texture_depth_flush(ctx, src, FALSE);
+		r600_texture_depth_flush(ctx, src, FALSE, FALSE);
 
 	restore_orig[0] = restore_orig[1] = FALSE;
 
diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h
index d401e40..6c19eb7 100644
--- a/src/gallium/drivers/r600/r600_resource.h
+++ b/src/gallium/drivers/r600/r600_resource.h
@@ -87,7 +87,8 @@ static INLINE struct r600_resource *r600_resource(struct pipe_resource *r)
 	return (struct r600_resource*)r;
 }
 
-int r600_texture_depth_flush(struct pipe_context *ctx, struct pipe_resource *texture, boolean just_create);
+int r600_texture_depth_flush(struct pipe_context *ctx,
+		struct pipe_resource *texture, boolean just_create, boolean cpu_access);
 
 /* r600_texture.c texture transfer functions. */
 struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index fc75781..555fb82 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -1000,7 +1000,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
 	}
 
 	if (tmp->is_depth && !tmp->is_flushing_texture) {
-	        r600_texture_depth_flush(ctx, texture, TRUE);
+	        r600_texture_depth_flush(ctx, texture, TRUE, FALSE);
 		tmp = tmp->flushed_depth_texture;
 	}
 
diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
index fe9a923..f7b2b8f 100644
--- a/src/gallium/drivers/r600/r600_texture.c
+++ b/src/gallium/drivers/r600/r600_texture.c
@@ -298,7 +298,8 @@ static int r600_init_surface(struct radeon_surface *surface,
 	if (ptex->bind & PIPE_BIND_SCANOUT) {
 		surface->flags |= RADEON_SURF_SCANOUT;
 	}
-	if (util_format_is_depth_and_stencil(ptex->format) && !is_transfer) {
+	if (util_format_is_depth_and_stencil(ptex->format) &&
+			(ptex->bind & PIPE_BIND_DEPTH_STENCIL) && !is_transfer) {
 		surface->flags |= RADEON_SURF_ZBUFFER;
 		surface->flags |= RADEON_SURF_SBUFFER;
 	}
@@ -517,7 +518,7 @@ r600_texture_create_object(struct pipe_screen *screen,
 	rtex->real_format = base->format;
 
 	/* We must split depth and stencil into two separate buffers on Evergreen. */
-	if (!(base->flags & R600_RESOURCE_FLAG_TRANSFER) &&
+	if ((base->bind & PIPE_BIND_DEPTH_STENCIL) &&
 	    ((struct r600_screen*)screen)->chip_class >= EVERGREEN &&
 	    util_format_is_depth_and_stencil(base->format) &&
 	    !rscreen->use_surface_alloc) {
@@ -729,13 +730,20 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
 }
 
 int r600_texture_depth_flush(struct pipe_context *ctx,
-			     struct pipe_resource *texture, boolean just_create)
+			     struct pipe_resource *texture, boolean just_create,
+			     boolean cpu_access)
 {
 	struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
 	struct pipe_resource resource;
 
-	if (rtex->flushed_depth_texture)
-		goto out;
+	if (rtex->flushed_depth_texture) {
+		if ((rtex->flushed_depth_texture->resource.b.b.usage ==
+				PIPE_USAGE_DYNAMIC) || !cpu_access)
+			goto out;
+
+		pipe_resource_reference((struct pipe_resource **)&rtex->flushed_depth_texture, NULL);
+		rtex->dirty_db = TRUE;
+	}
 
 	resource.target = texture->target;
 	resource.format = texture->format;
@@ -745,9 +753,12 @@ int r600_texture_depth_flush(struct pipe_context *ctx,
 	resource.array_size = texture->array_size;
 	resource.last_level = texture->last_level;
 	resource.nr_samples = texture->nr_samples;
-	resource.usage = PIPE_USAGE_DYNAMIC;
-	resource.bind = texture->bind | PIPE_BIND_DEPTH_STENCIL;
-	resource.flags = R600_RESOURCE_FLAG_TRANSFER | texture->flags;
+	resource.usage = cpu_access ? PIPE_USAGE_DYNAMIC : PIPE_USAGE_DEFAULT;
+	resource.bind = texture->bind & ~PIPE_BIND_DEPTH_STENCIL;
+	resource.flags = texture->flags;
+
+	if (cpu_access)
+		resource.flags |= R600_RESOURCE_FLAG_TRANSFER;
 
 	rtex->flushed_depth_texture = (struct r600_resource_texture *)ctx->screen->resource_create(ctx->screen, &resource);
 	if (rtex->flushed_depth_texture == NULL) {
@@ -828,7 +839,9 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
 		*/
 		/* XXX: when discard is true, no need to read back from depth texture
 		*/
-		r = r600_texture_depth_flush(ctx, texture, FALSE);
+
+		r = r600_texture_depth_flush(ctx, texture, FALSE, TRUE);
+
 		if (r < 0) {
 			R600_ERR("failed to create temporary texture to hold untiled copy\n");
 			pipe_resource_reference(&trans->transfer.resource, NULL);
-- 
1.7.10.4



More information about the mesa-dev mailing list