[Mesa-stable] [PATCH 2/4] gallium/radeon: set VPORT_ZMIN/MAX registers correctly

Marek Olšák maraeo at gmail.com
Mon Sep 5 21:10:59 UTC 2016


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

Calculate depth ranges from viewport states and
pipe_rasterizer_state::clip_halfz.

The evergreend.h change is required to silence a warning.

This fixes this recently updated piglit: arb_depth_clamp/depth-clamp-range

Reviewed-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>
Cc: 12.0 <mesa-stable at lists.freedesktop.org>
---
 src/gallium/drivers/r600/evergreen_state.c    |  1 +
 src/gallium/drivers/r600/evergreend.h         |  4 +-
 src/gallium/drivers/r600/r600_hw_context.c    |  1 +
 src/gallium/drivers/r600/r600_pipe.h          |  1 +
 src/gallium/drivers/r600/r600_state.c         |  1 +
 src/gallium/drivers/r600/r600_state_common.c  |  2 +-
 src/gallium/drivers/radeon/r600_pipe_common.h |  5 +-
 src/gallium/drivers/radeon/r600_viewport.c    | 73 ++++++++++++++++++++++++---
 src/gallium/drivers/radeon/r600d_common.h     |  2 +
 src/gallium/drivers/radeonsi/si_hw_context.c  |  1 +
 src/gallium/drivers/radeonsi/si_state.c       |  3 +-
 src/gallium/drivers/radeonsi/si_state.h       |  1 +
 12 files changed, 82 insertions(+), 13 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index 36d3b4b..3433021 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -473,6 +473,7 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx,
 	r600_init_command_buffer(&rs->buffer, 30);
 
 	rs->scissor_enable = state->scissor;
+	rs->clip_halfz = state->clip_halfz;
 	rs->flatshade = state->flatshade;
 	rs->sprite_coord_enable = state->sprite_coord_enable;
 	rs->two_side = state->light_twoside;
diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h
index c1c6169..10c23e8 100644
--- a/src/gallium/drivers/r600/evergreend.h
+++ b/src/gallium/drivers/r600/evergreend.h
@@ -1862,8 +1862,8 @@
 #define R_0283F8_SQ_VTX_SEMANTIC_30                  0x000283F8
 #define R_0283FC_SQ_VTX_SEMANTIC_31                  0x000283FC
 #define R_0288F0_SQ_VTX_SEMANTIC_CLEAR               0x000288F0
-#define R_0282D0_PA_SC_VPORT_ZMIN_0                  0x000282D0
-#define R_0282D4_PA_SC_VPORT_ZMAX_0                  0x000282D4
+#define R_0282D0_PA_SC_VPORT_ZMIN_0                  0x0282D0
+#define R_0282D4_PA_SC_VPORT_ZMAX_0                  0x0282D4
 #define R_028400_VGT_MAX_VTX_INDX                    0x00028400
 #define R_028404_VGT_MIN_VTX_INDX                    0x00028404
 #define R_028408_VGT_INDX_OFFSET                     0x00028408
diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c
index 98b5c7c..99c58cc 100644
--- a/src/gallium/drivers/r600/r600_hw_context.c
+++ b/src/gallium/drivers/r600/r600_hw_context.c
@@ -308,6 +308,7 @@ void r600_begin_new_cs(struct r600_context *ctx)
 	ctx->b.scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
 	r600_mark_atom_dirty(ctx, &ctx->b.scissors.atom);
 	ctx->b.viewports.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
+	ctx->b.viewports.depth_range_dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
 	r600_mark_atom_dirty(ctx, &ctx->b.viewports.atom);
 	if (ctx->b.chip_class <= EVERGREEN) {
 		r600_mark_atom_dirty(ctx, &ctx->config_state.atom);
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index cdb8e82..aaad2a3 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -274,6 +274,7 @@ struct r600_rasterizer_state {
 	bool				offset_enable;
 	bool				scissor_enable;
 	bool				multisample_enable;
+	bool				clip_halfz;
 };
 
 struct r600_poly_offset_state {
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 9a33ab9..f3798b3 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -459,6 +459,7 @@ static void *r600_create_rs_state(struct pipe_context *ctx,
 	r600_init_command_buffer(&rs->buffer, 30);
 
 	rs->scissor_enable = state->scissor;
+	rs->clip_halfz = state->clip_halfz;
 	rs->flatshade = state->flatshade;
 	rs->sprite_coord_enable = state->sprite_coord_enable;
 	rs->two_side = state->light_twoside;
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index b3814fb..572f3ac 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -364,7 +364,7 @@ static void r600_bind_rs_state(struct pipe_context *ctx, void *state)
 		r600_mark_atom_dirty(rctx, &rctx->clip_misc_state.atom);
 	}
 
-	r600_set_scissor_enable(&rctx->b, rs->scissor_enable);
+	r600_viewport_set_rast_deps(&rctx->b, rs->scissor_enable, rs->clip_halfz);
 
 	/* Re-emit PA_SC_LINE_STIPPLE. */
 	rctx->last_primitive_type = -1;
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index 3e54534..2e2d3a8 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -430,6 +430,7 @@ struct r600_scissors {
 struct r600_viewports {
 	struct r600_atom		atom;
 	unsigned			dirty_mask;
+	unsigned			depth_range_dirty_mask;
 	struct pipe_viewport_state	states[R600_MAX_VIEWPORTS];
 	struct r600_signed_scissor	as_scissor[R600_MAX_VIEWPORTS];
 };
@@ -469,6 +470,7 @@ struct r600_common_context {
 	struct r600_scissors		scissors;
 	struct r600_viewports		viewports;
 	bool				scissor_enabled;
+	bool				clip_halfz;
 	bool				vs_writes_viewport_index;
 	bool				vs_disables_clipping_viewport;
 
@@ -669,7 +671,8 @@ void r600_init_context_texture_functions(struct r600_common_context *rctx);
 /* r600_viewport.c */
 void evergreen_apply_scissor_bug_workaround(struct r600_common_context *rctx,
 					    struct pipe_scissor_state *scissor);
-void r600_set_scissor_enable(struct r600_common_context *rctx, bool enable);
+void r600_viewport_set_rast_deps(struct r600_common_context *rctx,
+				 bool scissor_enable, bool clip_halfz);
 void r600_update_vs_writes_viewport_index(struct r600_common_context *rctx,
 					  struct tgsi_shader_info *info);
 void r600_init_viewport_functions(struct r600_common_context *rctx);
diff --git a/src/gallium/drivers/radeon/r600_viewport.c b/src/gallium/drivers/radeon/r600_viewport.c
index 2d68783..2de1382 100644
--- a/src/gallium/drivers/radeon/r600_viewport.c
+++ b/src/gallium/drivers/radeon/r600_viewport.c
@@ -22,6 +22,7 @@
  */
 
 #include "r600_cs.h"
+#include "util/u_viewport.h"
 #include "tgsi/tgsi_scan.h"
 
 #define GET_MAX_SCISSOR(rctx) (rctx->chip_class >= EVERGREEN ? 16384 : 8192)
@@ -260,6 +261,7 @@ static void r600_set_viewport_states(struct pipe_context *ctx,
 				     const struct pipe_viewport_state *state)
 {
 	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
+	unsigned mask;
 	int i;
 
 	for (i = 0; i < num_viewports; i++) {
@@ -270,8 +272,10 @@ static void r600_set_viewport_states(struct pipe_context *ctx,
 					       &rctx->viewports.as_scissor[index]);
 	}
 
-	rctx->viewports.dirty_mask |= ((1 << num_viewports) - 1) << start_slot;
-	rctx->scissors.dirty_mask |= ((1 << num_viewports) - 1) << start_slot;
+	mask = ((1 << num_viewports) - 1) << start_slot;
+	rctx->viewports.dirty_mask |= mask;
+	rctx->viewports.depth_range_dirty_mask |= mask;
+	rctx->scissors.dirty_mask |= mask;
 	rctx->set_atom_dirty(rctx, &rctx->viewports.atom, true);
 	rctx->set_atom_dirty(rctx, &rctx->scissors.atom, true);
 }
@@ -289,7 +293,7 @@ static void r600_emit_one_viewport(struct r600_common_context *rctx,
 	radeon_emit(cs, fui(state->translate[2]));
 }
 
-static void r600_emit_viewports(struct r600_common_context *rctx, struct r600_atom *atom)
+static void r600_emit_viewports(struct r600_common_context *rctx)
 {
 	struct radeon_winsys_cs *cs = rctx->gfx.cs;
 	struct pipe_viewport_state *states = rctx->viewports.states;
@@ -319,13 +323,64 @@ static void r600_emit_viewports(struct r600_common_context *rctx, struct r600_at
 	rctx->viewports.dirty_mask = 0;
 }
 
-void r600_set_scissor_enable(struct r600_common_context *rctx, bool enable)
+static void r600_emit_depth_ranges(struct r600_common_context *rctx)
 {
-	if (rctx->scissor_enabled != enable) {
-		rctx->scissor_enabled = enable;
+	struct radeon_winsys_cs *cs = rctx->gfx.cs;
+	struct pipe_viewport_state *states = rctx->viewports.states;
+	unsigned mask = rctx->viewports.depth_range_dirty_mask;
+	float zmin, zmax;
+
+	/* The simple case: Only 1 viewport is active. */
+	if (!rctx->vs_writes_viewport_index) {
+		if (!(mask & 1))
+			return;
+
+		util_viewport_zmin_zmax(&states[0], rctx->clip_halfz, &zmin, &zmax);
+
+		radeon_set_context_reg_seq(cs, R_0282D0_PA_SC_VPORT_ZMIN_0, 2);
+		radeon_emit(cs, fui(zmin));
+		radeon_emit(cs, fui(zmax));
+		rctx->viewports.depth_range_dirty_mask &= ~1; /* clear one bit */
+		return;
+	}
+
+	while (mask) {
+		int start, count, i;
+
+		u_bit_scan_consecutive_range(&mask, &start, &count);
+
+		radeon_set_context_reg_seq(cs, R_0282D0_PA_SC_VPORT_ZMIN_0 +
+					   start * 4 * 2, count * 2);
+		for (i = start; i < start+count; i++) {
+			util_viewport_zmin_zmax(&states[i], rctx->clip_halfz, &zmin, &zmax);
+			radeon_emit(cs, fui(zmin));
+			radeon_emit(cs, fui(zmax));
+		}
+	}
+	rctx->viewports.depth_range_dirty_mask = 0;
+}
+
+static void r600_emit_viewport_states(struct r600_common_context *rctx,
+				      struct r600_atom *atom)
+{
+	r600_emit_viewports(rctx);
+	r600_emit_depth_ranges(rctx);
+}
+
+/* Set viewport dependencies on pipe_rasterizer_state. */
+void r600_viewport_set_rast_deps(struct r600_common_context *rctx,
+				 bool scissor_enable, bool clip_halfz)
+{
+	if (rctx->scissor_enabled != scissor_enable) {
+		rctx->scissor_enabled = scissor_enable;
 		rctx->scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
 		rctx->set_atom_dirty(rctx, &rctx->scissors.atom, true);
 	}
+	if (rctx->clip_halfz != clip_halfz) {
+		rctx->clip_halfz = clip_halfz;
+		rctx->viewports.depth_range_dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
+		rctx->set_atom_dirty(rctx, &rctx->viewports.atom, true);
+	}
 }
 
 /**
@@ -359,14 +414,16 @@ void r600_update_vs_writes_viewport_index(struct r600_common_context *rctx,
 
 	if (rctx->scissors.dirty_mask)
 	    rctx->set_atom_dirty(rctx, &rctx->scissors.atom, true);
-	if (rctx->viewports.dirty_mask)
+
+	if (rctx->viewports.dirty_mask ||
+	    rctx->viewports.depth_range_dirty_mask)
 	    rctx->set_atom_dirty(rctx, &rctx->viewports.atom, true);
 }
 
 void r600_init_viewport_functions(struct r600_common_context *rctx)
 {
 	rctx->scissors.atom.emit = r600_emit_scissors;
-	rctx->viewports.atom.emit = r600_emit_viewports;
+	rctx->viewports.atom.emit = r600_emit_viewport_states;
 
 	rctx->scissors.atom.num_dw = (2 + 16 * 2) + 6;
 	rctx->viewports.atom.num_dw = 2 + 16 * 6;
diff --git a/src/gallium/drivers/radeon/r600d_common.h b/src/gallium/drivers/radeon/r600d_common.h
index fd9d79e..08ec5cd 100644
--- a/src/gallium/drivers/radeon/r600d_common.h
+++ b/src/gallium/drivers/radeon/r600d_common.h
@@ -241,5 +241,7 @@
 #define   S_028254_BR_Y(x)                                            (((unsigned)(x) & 0x7FFF) << 16)
 #define   G_028254_BR_Y(x)                                            (((x) >> 16) & 0x7FFF)
 #define   C_028254_BR_Y                                               0x8000FFFF
+#define R_0282D0_PA_SC_VPORT_ZMIN_0                                     0x0282D0
+#define R_0282D4_PA_SC_VPORT_ZMAX_0                                     0x0282D4
 
 #endif
diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c b/src/gallium/drivers/radeonsi/si_hw_context.c
index 69478a8..ebb66ea 100644
--- a/src/gallium/drivers/radeonsi/si_hw_context.c
+++ b/src/gallium/drivers/radeonsi/si_hw_context.c
@@ -231,6 +231,7 @@ void si_begin_new_cs(struct si_context *ctx)
 
 	ctx->b.scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
 	ctx->b.viewports.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
+	ctx->b.viewports.depth_range_dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
 	si_mark_atom_dirty(ctx, &ctx->b.scissors.atom);
 	si_mark_atom_dirty(ctx, &ctx->b.viewports.atom);
 
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 2cef615..0874d49 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -728,6 +728,7 @@ static void *si_create_rs_state(struct pipe_context *ctx,
 	}
 
 	rs->scissor_enable = state->scissor;
+	rs->clip_halfz = state->clip_halfz;
 	rs->two_side = state->light_twoside;
 	rs->multisample_enable = state->multisample;
 	rs->force_persample_interp = state->force_persample_interp;
@@ -857,7 +858,7 @@ static void si_bind_rs_state(struct pipe_context *ctx, void *state)
 			si_mark_atom_dirty(sctx, &sctx->msaa_sample_locs.atom);
 	}
 
-	r600_set_scissor_enable(&sctx->b, rs->scissor_enable);
+	r600_viewport_set_rast_deps(&sctx->b, rs->scissor_enable, rs->clip_halfz);
 
 	si_pm4_bind_state(sctx, rasterizer, rs);
 	si_update_poly_offset_state(sctx);
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index 97f6dfa..f000619 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -78,6 +78,7 @@ struct si_state_rasterizer {
 	bool			clamp_fragment_color;
 	bool			rasterizer_discard;
 	bool			scissor_enable;
+	bool			clip_halfz;
 };
 
 struct si_dsa_stencil_ref_part {
-- 
2.7.4



More information about the mesa-stable mailing list