Mesa (master): radeonsi: decompress DCC in set_framebuffer_state instead of create_surface (v2)

Marek Olšák mareko at kemper.freedesktop.org
Fri Mar 31 18:58:15 UTC 2017


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

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Fri Mar 24 03:02:53 2017 +0100

radeonsi: decompress DCC in set_framebuffer_state instead of create_surface (v2)

for threaded gallium, which can't use pipe_context in create_surface

v2: don't add a new decompress helper function

Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>

---

 src/gallium/drivers/radeon/r600_pipe_common.h |  4 ++++
 src/gallium/drivers/radeon/r600_texture.c     | 22 ++++++++++++++------
 src/gallium/drivers/radeonsi/si_state.c       | 29 +++++++++++++++++++++++++++
 3 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index 2feca0172f..6a52247d45 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -287,6 +287,7 @@ struct r600_surface {
 	bool export_16bpc;
 	bool color_is_int8;
 	bool color_is_int10;
+	bool dcc_incompatible;
 
 	/* Color registers. */
 	unsigned cb_color_info;
@@ -801,6 +802,9 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
 					const struct pipe_resource *templ);
 bool vi_dcc_formats_compatible(enum pipe_format format1,
 			       enum pipe_format format2);
+bool vi_dcc_formats_are_incompatible(struct pipe_resource *tex,
+				     unsigned level,
+				     enum pipe_format view_format);
 void vi_disable_dcc_if_incompatible_format(struct r600_common_context *rctx,
 					   struct pipe_resource *tex,
 					   unsigned level,
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
index 0daa5ea53e..877f5552bd 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -1903,6 +1903,18 @@ bool vi_dcc_formats_compatible(enum pipe_format format1,
 	       type1 == type2;
 }
 
+bool vi_dcc_formats_are_incompatible(struct pipe_resource *tex,
+				     unsigned level,
+				     enum pipe_format view_format)
+{
+	struct r600_texture *rtex = (struct r600_texture *)tex;
+
+	return vi_dcc_enabled(rtex, level) &&
+	       !vi_dcc_formats_compatible(tex->format, view_format);
+}
+
+/* This can't be merged with the above function, because
+ * vi_dcc_formats_compatible should be called only when DCC is enabled. */
 void vi_disable_dcc_if_incompatible_format(struct r600_common_context *rctx,
 					   struct pipe_resource *tex,
 					   unsigned level,
@@ -1922,7 +1934,6 @@ struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
 						unsigned width0, unsigned height0,
 						unsigned width, unsigned height)
 {
-	struct r600_common_context *rctx = (struct r600_common_context*)pipe;
 	struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
 
 	if (!surface)
@@ -1942,11 +1953,10 @@ struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
 	surface->width0 = width0;
 	surface->height0 = height0;
 
-	if (texture->target != PIPE_BUFFER)
-		vi_disable_dcc_if_incompatible_format(rctx, texture,
-						      templ->u.tex.level,
-						      templ->format);
-
+	surface->dcc_incompatible =
+		texture->target != PIPE_BUFFER &&
+		vi_dcc_formats_are_incompatible(texture, templ->u.tex.level,
+						templ->format);
 	return &surface->base;
 }
 
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 866c206399..2c2e3c77f6 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -2439,6 +2439,7 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
 	struct r600_texture *rtex;
 	bool old_any_dst_linear = sctx->framebuffer.any_dst_linear;
 	unsigned old_nr_samples = sctx->framebuffer.nr_samples;
+	bool unbound = false;
 	int i;
 
 	for (i = 0; i < sctx->framebuffer.state.nr_cbufs; i++) {
@@ -2450,6 +2451,34 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
 			vi_separate_dcc_stop_query(ctx, rtex);
 	}
 
+	/* Disable DCC if the formats are incompatible. */
+	for (i = 0; i < state->nr_cbufs; i++) {
+		if (!state->cbufs[i])
+			continue;
+
+		surf = (struct r600_surface*)state->cbufs[i];
+		rtex = (struct r600_texture*)surf->base.texture;
+
+		if (!surf->dcc_incompatible)
+			continue;
+
+		/* Since the DCC decompression calls back into set_framebuffer-
+		 * _state, we need to unbind the framebuffer, so that
+		 * vi_separate_dcc_stop_query isn't called twice with the same
+		 * color buffer.
+		 */
+		if (!unbound) {
+			util_copy_framebuffer_state(&sctx->framebuffer.state, NULL);
+			unbound = true;
+		}
+
+		if (vi_dcc_enabled(rtex, surf->base.u.tex.level))
+			if (!r600_texture_disable_dcc(&sctx->b, rtex))
+				sctx->b.decompress_dcc(ctx, rtex);
+
+		surf->dcc_incompatible = false;
+	}
+
 	/* Only flush TC when changing the framebuffer state, because
 	 * the only client not using TC that can change textures is
 	 * the framebuffer.




More information about the mesa-commit mailing list