[Mesa-dev] [PATCH 06/10] radeonsi: implement line and polygon smoothing

Marek Olšák maraeo at gmail.com
Sun Mar 15 12:48:26 PDT 2015


From: Marek Olšák <marek.olsak at amd.com>

---
 src/gallium/drivers/radeonsi/si_pipe.h          |  1 +
 src/gallium/drivers/radeonsi/si_state.c         | 35 ++++++++++++++++++++-----
 src/gallium/drivers/radeonsi/si_state.h         |  2 ++
 src/gallium/drivers/radeonsi/si_state_shaders.c | 21 ++++++++++++---
 4 files changed, 49 insertions(+), 10 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 1bc664a..7c37a3e 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -186,6 +186,7 @@ struct si_context {
 	struct r600_atom		msaa_sample_locs;
 	struct r600_atom		msaa_config;
 	int				ps_iter_samples;
+	bool				smoothing_enabled;
 
 	/* Vertex and index buffers. */
 	bool			vertex_buffers_dirty;
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index f844fc1..c7633dc 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -617,6 +617,8 @@ static void *si_create_rs_state(struct pipe_context *ctx,
 	rs->clip_plane_enable = state->clip_plane_enable;
 	rs->line_stipple_enable = state->line_stipple_enable;
 	rs->poly_stipple_enable = state->poly_stipple_enable;
+	rs->line_smooth = state->line_smooth;
+	rs->poly_smooth = state->poly_smooth;
 
 	polygon_dual_mode = (state->fill_front != PIPE_POLYGON_MODE_FILL ||
 				state->fill_back != PIPE_POLYGON_MODE_FILL);
@@ -686,7 +688,9 @@ static void *si_create_rs_state(struct pipe_context *ctx,
 	si_pm4_set_reg(pm4, R_028A08_PA_SU_LINE_CNTL, S_028A08_WIDTH(tmp));
 	si_pm4_set_reg(pm4, R_028A48_PA_SC_MODE_CNTL_0,
 		       S_028A48_LINE_STIPPLE_ENABLE(state->line_stipple_enable) |
-		       S_028A48_MSAA_ENABLE(state->multisample) |
+		       S_028A48_MSAA_ENABLE(state->multisample ||
+					    state->poly_smooth ||
+					    state->line_smooth) |
 		       S_028A48_VPORT_SCISSOR_ENABLE(state->scissor));
 
 	si_pm4_set_reg(pm4, R_028BE4_PA_SU_VTX_CNTL,
@@ -945,10 +949,15 @@ static void si_emit_db_render_state(struct si_context *sctx, struct r600_atom *s
 		r600_write_context_reg(cs, R_028010_DB_RENDER_OVERRIDE2, 0);
 	}
 
-	db_shader_control = S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z) |
-			    S_02880C_ALPHA_TO_MASK_DISABLE(sctx->framebuffer.cb0_is_integer) |
+	db_shader_control = S_02880C_ALPHA_TO_MASK_DISABLE(sctx->framebuffer.cb0_is_integer) |
 		            sctx->ps_db_shader_control;
 
+	/* Bug workaround for smoothing (overrasterization) on SI. */
+	if (sctx->b.chip_class == SI && sctx->smoothing_enabled)
+		db_shader_control |= S_02880C_Z_ORDER(V_02880C_LATE_Z);
+	else
+		db_shader_control |= S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z);
+
 	/* Disable the gl_SampleMask fragment shader output if MSAA is disabled. */
 	if (sctx->framebuffer.nr_samples <= 1 || (rs && !rs->multisample_enable))
 		db_shader_control &= C_02880C_MASK_EXPORT_ENABLE;
@@ -2094,7 +2103,18 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
 		ctx->set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT,
 					 SI_DRIVER_STATE_CONST_BUF, &constbuf);
 
-		sctx->msaa_sample_locs.dirty = true;
+		/* Smoothing (only possible with nr_samples == 1) uses the same
+		 * sample locations as the MSAA it simulates.
+		 *
+		 * Therefore, don't update the sample locations when
+		 * transitioning from no AA to smoothing-equivalent AA, and
+		 * vice versa.
+		 */
+		if ((sctx->framebuffer.nr_samples != 1 ||
+		     old_nr_samples != SI_NUM_SMOOTH_AA_SAMPLES) &&
+		    (sctx->framebuffer.nr_samples != SI_NUM_SMOOTH_AA_SAMPLES ||
+		     old_nr_samples != 1))
+			sctx->msaa_sample_locs.dirty = true;
 	}
 }
 
@@ -2205,8 +2225,10 @@ static void si_emit_msaa_sample_locs(struct r600_common_context *rctx,
 {
 	struct si_context *sctx = (struct si_context *)rctx;
 	struct radeon_winsys_cs *cs = sctx->b.rings.gfx.cs;
+	unsigned nr_samples = sctx->framebuffer.nr_samples;
 
-	cayman_emit_msaa_sample_locs(cs, sctx->framebuffer.nr_samples);
+	cayman_emit_msaa_sample_locs(cs, nr_samples > 1 ? nr_samples :
+						SI_NUM_SMOOTH_AA_SAMPLES);
 }
 
 const struct r600_atom si_atom_msaa_sample_locs = { si_emit_msaa_sample_locs, 18 }; /* number of CS dwords */
@@ -2217,7 +2239,8 @@ static void si_emit_msaa_config(struct r600_common_context *rctx, struct r600_at
 	struct radeon_winsys_cs *cs = sctx->b.rings.gfx.cs;
 
 	cayman_emit_msaa_config(cs, sctx->framebuffer.nr_samples,
-				sctx->ps_iter_samples, 0);
+				sctx->ps_iter_samples,
+				sctx->smoothing_enabled ? SI_NUM_SMOOTH_AA_SAMPLES : 0);
 }
 
 const struct r600_atom si_atom_msaa_config = { si_emit_msaa_config, 10 }; /* number of CS dwords */
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index 4e6b1e2..27dd2c3 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -68,6 +68,8 @@ struct si_state_rasterizer {
 	float			offset_units;
 	float			offset_scale;
 	bool			poly_stipple_enable;
+	bool			line_smooth;
+	bool			poly_smooth;
 };
 
 struct si_state_dsa {
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index 8c3bdc5..382738a 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -373,6 +373,11 @@ static INLINE void si_shader_selector_key(struct pipe_context *ctx,
 		key->ps.export_16bpc = sctx->framebuffer.export_16bpc;
 
 		if (rs) {
+			bool is_poly = (sctx->current_rast_prim >= PIPE_PRIM_TRIANGLES &&
+					sctx->current_rast_prim <= PIPE_PRIM_POLYGON) ||
+				       sctx->current_rast_prim >= PIPE_PRIM_TRIANGLES_ADJACENCY;
+			bool is_line = !is_poly && sctx->current_rast_prim != PIPE_PRIM_POINTS;
+
 			key->ps.color_two_side = rs->two_side;
 
 			if (sctx->queued.named.blend) {
@@ -381,10 +386,10 @@ static INLINE void si_shader_selector_key(struct pipe_context *ctx,
 						       !sctx->framebuffer.cb0_is_integer;
 			}
 
-			key->ps.poly_stipple = rs->poly_stipple_enable &&
-					       ((sctx->current_rast_prim >= PIPE_PRIM_TRIANGLES &&
-						 sctx->current_rast_prim <= PIPE_PRIM_POLYGON) ||
-						sctx->current_rast_prim >= PIPE_PRIM_TRIANGLES_ADJACENCY);
+			key->ps.poly_stipple = rs->poly_stipple_enable && is_poly;
+			key->ps.poly_line_smoothing = ((is_poly && rs->poly_smooth) ||
+						       (is_line && rs->line_smooth)) &&
+						      sctx->framebuffer.nr_samples <= 1;
 		}
 
 		key->ps.alpha_func = PIPE_FUNC_ALWAYS;
@@ -921,6 +926,14 @@ void si_update_shaders(struct si_context *sctx)
 		sctx->ps_db_shader_control = sctx->ps_shader->current->db_shader_control;
 		sctx->db_render_state.dirty = true;
 	}
+
+	if (sctx->smoothing_enabled != sctx->ps_shader->current->key.ps.poly_line_smoothing) {
+		sctx->smoothing_enabled = sctx->ps_shader->current->key.ps.poly_line_smoothing;
+		sctx->msaa_config.dirty = true;
+
+		if (sctx->b.chip_class == SI)
+			sctx->db_render_state.dirty = true;
+	}
 }
 
 void si_init_shader_functions(struct si_context *sctx)
-- 
2.1.0



More information about the mesa-dev mailing list