Mesa (master): r600g: eg+ support for FS_COLOR0_WRITES_ALL_CBUFS

Alex Deucher agd5f at kemper.freedesktop.org
Fri Jun 24 22:24:03 UTC 2011


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

Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Jun 24 18:05:53 2011 -0400

r600g: eg+ support for FS_COLOR0_WRITES_ALL_CBUFS

Evergreen+ don't support multi-writes so we need to emulate
it in the shader. Fixes the following piglit tests:
fbo-drawbuffers-fragcolor
ati_draw_buffers-arbfp-no-option

Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

---

 src/gallium/drivers/r600/evergreen_state.c   |    6 ++-
 src/gallium/drivers/r600/r600_asm.c          |    2 +
 src/gallium/drivers/r600/r600_pipe.h         |    1 +
 src/gallium/drivers/r600/r600_shader.c       |   77 ++++++++++++++++---------
 src/gallium/drivers/r600/r600_shader.h       |    1 +
 src/gallium/drivers/r600/r600_state_common.c |    4 +-
 6 files changed, 61 insertions(+), 30 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index dfe7896..dc18261 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -885,6 +885,7 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
 
 	/* build states */
 	rctx->have_depth_fb = 0;
+	rctx->nr_cbufs = state->nr_cbufs;
 	for (int i = 0; i < state->nr_cbufs; i++) {
 		evergreen_cb(rctx, rstate, state, i);
 	}
@@ -1631,7 +1632,10 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader
 		    rshader->output[i].name == TGSI_SEMANTIC_STENCIL)
 			exports_ps |= 1;
 		else if (rshader->output[i].name == TGSI_SEMANTIC_COLOR) {
-			num_cout++;
+			if (rshader->fs_write_all)
+				num_cout = rshader->nr_cbufs;
+			else
+				num_cout++;
 		}
 	}
 	exports_ps |= S_02884C_EXPORT_COLORS(num_cout);
diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c
index c447a03..065f955 100644
--- a/src/gallium/drivers/r600/r600_asm.c
+++ b/src/gallium/drivers/r600/r600_asm.c
@@ -1863,6 +1863,8 @@ void r600_bc_dump(struct r600_bc *bc)
 			break;
 		case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
 		case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
+		case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
+		case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
 			fprintf(stderr, "%04d %08X EXPORT ", id, bc->bytecode[id]);
 			fprintf(stderr, "GPR:%X ", cf->output.gpr);
 			fprintf(stderr, "ELEM_SIZE:%X ", cf->output.elem_size);
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index dc9aad0..2667c80 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -213,6 +213,7 @@ struct r600_pipe_context {
 	boolean				export_16bpc;
 	unsigned			alpha_ref;
 	boolean				alpha_ref_dirty;
+	unsigned			nr_cbufs;
 	struct r600_textures_info	ps_samplers;
 
 	struct r600_pipe_fences		fences;
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 2e5d4a6..f83d707 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -606,7 +606,7 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
 	struct r600_bc_output output[32];
 	unsigned output_done, noutput;
 	unsigned opcode;
-	int i, r = 0, pos0;
+	int i, j, r = 0, pos0;
 
 	ctx.bc = &shader->bc;
 	ctx.shader = shader;
@@ -623,6 +623,8 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
 	shader->clamp_color = (((ctx.type == TGSI_PROCESSOR_FRAGMENT) && rctx->clamp_fragment_color) ||
 		((ctx.type == TGSI_PROCESSOR_VERTEX) && rctx->clamp_vertex_color));
 
+	shader->nr_cbufs = rctx->nr_cbufs;
+
 	/* register allocations */
 	/* Values [0,127] correspond to GPR[0..127].
 	 * Values [128,159] correspond to constant buffer bank 0
@@ -767,50 +769,68 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
 	}
 
 	/* export output */
+	j = 0;
 	for (i = 0, pos0 = 0; i < noutput; i++) {
 		memset(&output[i], 0, sizeof(struct r600_bc_output));
-		output[i].gpr = shader->output[i].gpr;
-		output[i].elem_size = 3;
-		output[i].swizzle_x = 0;
-		output[i].swizzle_y = 1;
-		output[i].swizzle_z = 2;
-		output[i].swizzle_w = 3;
-		output[i].burst_count = 1;
-		output[i].barrier = 1;
-		output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
-		output[i].array_base = i - pos0;
-		output[i].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
+		output[i + j].gpr = shader->output[i].gpr;
+		output[i + j].elem_size = 3;
+		output[i + j].swizzle_x = 0;
+		output[i + j].swizzle_y = 1;
+		output[i + j].swizzle_z = 2;
+		output[i + j].swizzle_w = 3;
+		output[i + j].burst_count = 1;
+		output[i + j].barrier = 1;
+		output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
+		output[i + j].array_base = i - pos0;
+		output[i + j].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
 		switch (ctx.type) {
 		case TGSI_PROCESSOR_VERTEX:
 			if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
-				output[i].array_base = 60;
-				output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
+				output[i + j].array_base = 60;
+				output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
 				/* position doesn't count in array_base */
 				pos0++;
 			}
 			if (shader->output[i].name == TGSI_SEMANTIC_PSIZE) {
-				output[i].array_base = 61;
-				output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
+				output[i + j].array_base = 61;
+				output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
 				/* position doesn't count in array_base */
 				pos0++;
 			}
 			break;
 		case TGSI_PROCESSOR_FRAGMENT:
 			if (shader->output[i].name == TGSI_SEMANTIC_COLOR) {
-				output[i].array_base = shader->output[i].sid;
-				output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+				output[i + j].array_base = shader->output[i].sid;
+				output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+				if (shader->fs_write_all && (shader->family >= CHIP_CEDAR)) {
+					for (j = 1; j < shader->nr_cbufs; j++) {
+						memset(&output[i + j], 0, sizeof(struct r600_bc_output));
+						output[i + j].gpr = shader->output[i].gpr;
+						output[i + j].elem_size = 3;
+						output[i + j].swizzle_x = 0;
+						output[i + j].swizzle_y = 1;
+						output[i + j].swizzle_z = 2;
+						output[i + j].swizzle_w = 3;
+						output[i + j].burst_count = 1;
+						output[i + j].barrier = 1;
+						output[i + j].array_base = shader->output[i].sid + j;
+						output[i + j].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
+						output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+					}
+					j--;
+				}
 			} else if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
-				output[i].array_base = 61;
-				output[i].swizzle_x = 2;
-				output[i].swizzle_y = 7;
-				output[i].swizzle_z = output[i].swizzle_w = 7;
-				output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+				output[i + j].array_base = 61;
+				output[i + j].swizzle_x = 2;
+				output[i + j].swizzle_y = 7;
+				output[i + j].swizzle_z = output[i + j].swizzle_w = 7;
+				output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
 			} else if (shader->output[i].name == TGSI_SEMANTIC_STENCIL) {
-				output[i].array_base = 61;
-				output[i].swizzle_x = 7;
-				output[i].swizzle_y = 1;
-				output[i].swizzle_z = output[i].swizzle_w = 7;
-				output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+				output[i + j].array_base = 61;
+				output[i + j].swizzle_x = 7;
+				output[i + j].swizzle_y = 1;
+				output[i + j].swizzle_z = output[i + j].swizzle_w = 7;
+				output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
 			} else {
 				R600_ERR("unsupported fragment output name %d\n", shader->output[i].name);
 				r = -EINVAL;
@@ -823,6 +843,7 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
 			goto out_err;
 		}
 	}
+	noutput += j;
 	/* add fake param output for vertex shader if no param is exported */
 	if (ctx.type == TGSI_PROCESSOR_VERTEX) {
 		for (i = 0, pos0 = 0; i < noutput; i++) {
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index c1e00f3..76aebf2 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -47,6 +47,7 @@ struct r600_shader {
 	boolean			uses_kill;
 	boolean			fs_write_all;
 	boolean			clamp_color;
+	unsigned		nr_cbufs;
 };
 
 #endif
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index f1b0fc3..bf4e90e 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -599,7 +599,9 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 	if (rctx->vs_shader->shader.clamp_color != rctx->clamp_vertex_color)
 		r600_shader_rebuild(ctx, rctx->vs_shader);
 
-	if (rctx->ps_shader->shader.clamp_color != rctx->clamp_fragment_color)
+	if ((rctx->ps_shader->shader.clamp_color != rctx->clamp_fragment_color) ||
+	    (rctx->ps_shader->shader.fs_write_all &&
+	     (rctx->ps_shader->shader.nr_cbufs != rctx->nr_cbufs)))
 		r600_shader_rebuild(ctx, rctx->ps_shader);
 
 	if (rctx->spi_dirty)




More information about the mesa-commit mailing list