[Mesa-dev] [PATCH 2/2] r600: add gs tri strip adjacency fix.

Dave Airlie airlied at gmail.com
Mon Nov 13 04:18:07 UTC 2017


From: Dave Airlie <airlied at redhat.com>

Like
radeonsi: generate GS prolog to (partially) fix triangle strip adjacency rotation

evergreen hw suffers from the same problem, so rotate the
geometry inputs to fix this.

This fixes:
./bin/glsl-1.50-geometry-primitive-types GL_TRIANGLE_STRIP_ADJACENCY
on evergreen.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/gallium/drivers/r600/r600_pipe.h         |  1 +
 src/gallium/drivers/r600/r600_shader.c       | 48 +++++++++++++++++++++++++---
 src/gallium/drivers/r600/r600_shader.h       |  3 +-
 src/gallium/drivers/r600/r600_state_common.c | 15 +++++++++
 4 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 3dae56e..4fbc82b 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -510,6 +510,7 @@ struct r600_context {
 	struct r600_rasterizer_state	*rasterizer;
 	bool				alpha_to_one;
 	bool				force_blend_disable;
+	bool                            gs_tri_strip_adj_fix;
 	boolean				dual_src_blend;
 	unsigned			zwritemask;
 	int					ps_iter_samples;
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index c6e4457..fd0cc78 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -348,6 +348,7 @@ struct r600_shader_ctx {
 	int					gs_next_vertex;
 	struct r600_shader	*gs_for_vs;
 	int					gs_export_gpr_tregs[4];
+	int                                     gs_rotated_input[2];
 	const struct pipe_stream_output_info	*gs_stream_output_info;
 	unsigned				enabled_stream_buffers_mask;
 	unsigned                                tess_input_info; /* temp with tess input offsets */
@@ -760,7 +761,7 @@ static int single_alu_op3(struct r600_shader_ctx *ctx, int op,
 	int r;
 
 	/* validate this for other ops */
-	assert(op == ALU_OP3_MULADD_UINT24);
+	assert(op == ALU_OP3_MULADD_UINT24 || op == ALU_OP3_CNDE_INT);
 	memset(&alu, 0, sizeof(struct r600_bytecode_alu));
 	alu.op = op;
 	alu.src[0].sel = src0_sel;
@@ -1479,14 +1480,14 @@ static int fetch_gs_input(struct r600_shader_ctx *ctx, struct tgsi_full_src_regi
 	int r;
 	unsigned index = src->Register.Index;
 	unsigned vtx_id = src->Dimension.Index;
-	int offset_reg = vtx_id / 3;
+	int offset_reg = ctx->gs_rotated_input[vtx_id / 3];
 	int offset_chan = vtx_id % 3;
 	int t2 = 0;
 
 	/* offsets of per-vertex data in ESGS ring are passed to GS in R0.x, R0.y,
 	 * R0.w, R1.x, R1.y, R1.z (it seems R0.z is used for PrimitiveID) */
 
-	if (offset_reg == 0 && offset_chan == 2)
+	if (offset_reg == ctx->gs_rotated_input[0] && offset_chan == 2)
 		offset_chan = 3;
 
 	if (src->Dimension.Indirect || src->Register.Indirect)
@@ -1517,7 +1518,7 @@ static int fetch_gs_input(struct r600_shader_ctx *ctx, struct tgsi_full_src_regi
 		for (i = 0; i < 3; i++) {
 			memset(&alu, 0, sizeof(struct r600_bytecode_alu));
 			alu.op = ALU_OP1_MOV;
-			alu.src[0].sel = 0;
+			alu.src[0].sel = ctx->gs_rotated_input[0];
 			alu.src[0].chan = i == 2 ? 3 : i;
 			alu.dst.sel = treg[i];
 			alu.dst.chan = 0;
@@ -2983,6 +2984,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
 	case PIPE_SHADER_GEOMETRY:
 		ring_outputs = true;
 		shader->atomic_base = key.gs.first_atomic_counter;
+		shader->gs_tri_strip_adj_fix = key.gs.tri_strip_adj_fix;
 		break;
 	case PIPE_SHADER_TESS_CTRL:
 		shader->tcs_prim_mode = key.tcs.prim_mode;
@@ -3116,6 +3118,14 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
 		ctx.gs_export_gpr_tregs[2] = ctx.bc->ar_reg + 5;
 		ctx.gs_export_gpr_tregs[3] = ctx.bc->ar_reg + 6;
 		ctx.temp_reg = ctx.bc->ar_reg + 7;
+		if (ctx.shader->gs_tri_strip_adj_fix) {
+			ctx.gs_rotated_input[0] = ctx.bc->ar_reg + 7;
+			ctx.gs_rotated_input[1] = ctx.bc->ar_reg + 8;
+			ctx.temp_reg += 2;
+		} else {
+			ctx.gs_rotated_input[0] = 0;
+			ctx.gs_rotated_input[1] = 1;
+		}
 	} else {
 		ctx.temp_reg = ctx.bc->ar_reg + 3;
 	}
@@ -3283,6 +3293,36 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
 			if (r)
 				return r;
 		}
+
+		if (ctx.shader->gs_tri_strip_adj_fix) {
+			r = single_alu_op2(&ctx, ALU_OP2_AND_INT,
+					   ctx.gs_rotated_input[0], 2,
+					   0, 2,
+					   V_SQ_ALU_SRC_LITERAL, 1);
+			if (r)
+				return r;
+
+			for (i = 0; i < 6; i++) {
+				int rotated = (i + 4) % 6;
+				int offset_reg = i / 3;
+				int offset_chan = i % 3;
+				int rotated_offset_reg = rotated / 3;
+				int rotated_offset_chan = rotated % 3;
+
+				if (offset_reg == 0 && offset_chan == 2)
+					offset_chan = 3;
+				if (rotated_offset_reg == 0 && rotated_offset_chan == 2)
+					rotated_offset_chan = 3;
+
+				r = single_alu_op3(&ctx, ALU_OP3_CNDE_INT,
+						   ctx.gs_rotated_input[offset_reg], offset_chan,
+						   ctx.gs_rotated_input[0], 2,
+						   offset_reg, offset_chan,
+						   rotated_offset_reg, rotated_offset_chan);
+				if (r)
+					return r;
+			}
+		}
 	}
 
 	if (ctx.type == PIPE_SHADER_TESS_CTRL)
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index 3fecda4..40719d9 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -96,7 +96,7 @@ struct r600_shader {
 	boolean			has_txq_cube_array_z_comp;
 	boolean			uses_tex_buffers;
 	boolean                 gs_prim_id_input;
-
+	boolean                 gs_tri_strip_adj_fix;
 	uint8_t			ps_conservative_z;
 
 	/* Size in bytes of a data item in the ring(s) (single vertex data).
@@ -143,6 +143,7 @@ union r600_shader_key {
 	} tcs;
 	struct {
 		unsigned        first_atomic_counter:4;
+		unsigned        tri_strip_adj_fix:1;
 	} gs;
 };
 
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 750fd41..ead5b86 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -753,6 +753,7 @@ static inline void r600_shader_selector_key(const struct pipe_context *ctx,
 	}
 	case PIPE_SHADER_GEOMETRY:
 		key->gs.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_GEOMETRY);
+		key->gs.tri_strip_adj_fix = rctx->gs_tri_strip_adj_fix;
 		break;
 	case PIPE_SHADER_FRAGMENT: {
 		key->ps.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_FRAGMENT);
@@ -1767,6 +1768,20 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
 		rctx->framebuffer.do_update_surf_dirtiness = true;
 	}
 
+	if (rctx->gs_shader) {
+		/* Determine whether the GS triangle strip adjacency fix should
+		 * be applied. Rotate every other triangle if
+		 * - triangle strips with adjacency are fed to the GS and
+		 * - primitive restart is disabled (the rotation doesn't help
+		 *   when the restart occurs after an odd number of triangles).
+		 */
+		bool gs_tri_strip_adj_fix =
+			!rctx->tes_shader &&
+			info->mode == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY &&
+			!info->primitive_restart;
+		if (gs_tri_strip_adj_fix != rctx->gs_tri_strip_adj_fix)
+			rctx->gs_tri_strip_adj_fix = gs_tri_strip_adj_fix;
+	}
 	if (!r600_update_derived_state(rctx)) {
 		/* useless to render because current rendering command
 		 * can't be achieved
-- 
2.9.5



More information about the mesa-dev mailing list