[Mesa-dev] [PATCH] r600g: fix lockups with dual_src_blend v2

Vadim Girlin vadimgirlin at gmail.com
Tue Aug 21 04:42:49 PDT 2012


Disable blending when dual_src_blend is enabled and number of color exports
in the current fragment shader is less than 2.

Fixes lockups with ext_framebuffer_multisample-
alpha-to-coverage-dual-src-blend piglit test.

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

Tested on evergreen only.

 src/gallium/drivers/r600/r600_pipe.c         |  7 +++++
 src/gallium/drivers/r600/r600_pipe.h         |  8 ++++++
 src/gallium/drivers/r600/r600_state_common.c | 39 +++++++++++++++++++++-------
 3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index cf29833..7936c47 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -156,6 +156,9 @@ static void r600_destroy_context(struct pipe_context *context)
 {
 	struct r600_context *rctx = (struct r600_context *)context;
 
+	if (rctx->no_blend) {
+		rctx->context.delete_blend_state(&rctx->context, rctx->no_blend);
+	}
 	if (rctx->dummy_pixel_shader) {
 		rctx->context.delete_fs_state(&rctx->context, rctx->dummy_pixel_shader);
 	}
@@ -195,6 +198,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 {
 	struct r600_context *rctx = CALLOC_STRUCT(r600_context);
 	struct r600_screen* rscreen = (struct r600_screen *)screen;
+	struct pipe_blend_state no_blend = {};
 
 	if (rctx == NULL)
 		return NULL;
@@ -296,6 +300,9 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 						     TGSI_INTERPOLATE_CONSTANT);
 	rctx->context.bind_fs_state(&rctx->context, rctx->dummy_pixel_shader);
 
+	no_blend.rt[0].colormask = 0xF;
+	rctx->no_blend = rctx->context.create_blend_state(&rctx->context, &no_blend);
+
 	return &rctx->context;
 
 fail:
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 7046573..3686521 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -389,6 +389,14 @@ struct r600_context {
 	struct r600_cs_shader_state	cs_shader_state;
 	struct r600_sample_mask		sample_mask;
 
+	/* current external blend state (from state tracker) */
+	struct r600_pipe_blend		*blend;
+	/* state with disabled blending - used internally with blend_override */
+	struct r600_pipe_blend		*no_blend;
+
+	/* 1 - override current blend state with no_blend, 0 - use external state */
+	unsigned	blend_override;
+
 	struct radeon_winsys_cs	*cs;
 
 	struct r600_range	*range;
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index ba5e26c..0870cc7 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -165,19 +165,15 @@ static bool r600_conv_pipe_prim(unsigned pprim, unsigned *prim)
 }
 
 /* common state between evergreen and r600 */
-void r600_bind_blend_state(struct pipe_context *ctx, void *state)
+
+static void r600_bind_blend_state_internal(struct r600_context *rctx,
+		struct r600_pipe_blend *blend)
 {
-	struct r600_context *rctx = (struct r600_context *)ctx;
-	struct r600_pipe_blend *blend = (struct r600_pipe_blend *)state;
 	struct r600_pipe_state *rstate;
 	bool update_cb = false;
 
-	if (state == NULL)
-		return;
 	rstate = &blend->rstate;
 	rctx->states[rstate->id] = rstate;
-	rctx->dual_src_blend = blend->dual_src_blend;
-	rctx->alpha_to_one = blend->alpha_to_one;
 	r600_context_pipe_state_set(rctx, rstate);
 
 	if (rctx->cb_misc_state.blend_colormask != blend->cb_target_mask) {
@@ -198,6 +194,22 @@ void r600_bind_blend_state(struct pipe_context *ctx, void *state)
 	}
 }
 
+void r600_bind_blend_state(struct pipe_context *ctx, void *state)
+{
+	struct r600_context *rctx = (struct r600_context *)ctx;
+	struct r600_pipe_blend *blend = (struct r600_pipe_blend *)state;
+
+	if (blend == NULL)
+		return;
+
+	rctx->blend = blend;
+	rctx->alpha_to_one = blend->alpha_to_one;
+	rctx->dual_src_blend = blend->dual_src_blend;
+
+	if (!rctx->blend_override)
+		r600_bind_blend_state_internal(rctx, blend);
+}
+
 void r600_set_blend_color(struct pipe_context *ctx,
 			  const struct pipe_blend_color *state)
 {
@@ -1024,7 +1036,7 @@ void r600_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
 static void r600_update_derived_state(struct r600_context *rctx)
 {
 	struct pipe_context * ctx = (struct pipe_context*)rctx;
-	unsigned ps_dirty = 0;
+	unsigned ps_dirty = 0, blend_override;
 
 	if (!rctx->blitter->running) {
 		/* Flush depth textures which need to be flushed. */
@@ -1052,7 +1064,16 @@ static void r600_update_derived_state(struct r600_context *rctx)
 
 	if (ps_dirty)
 		r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate);
-		
+
+	blend_override = (rctx->dual_src_blend &&
+			rctx->ps_shader->current->nr_ps_color_outputs < 2);
+
+	if (blend_override != rctx->blend_override) {
+		rctx->blend_override = blend_override;
+		r600_bind_blend_state_internal(rctx,
+				blend_override ? rctx->no_blend : rctx->blend);
+	}
+
 	if (rctx->chip_class >= EVERGREEN) {
 		evergreen_update_dual_export_state(rctx);
 	} else {
-- 
1.7.11.4



More information about the mesa-dev mailing list