summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <marek.olsak@amd.com>2015-09-28 17:21:10 +0200
committerMarek Olšák <marek.olsak@amd.com>2015-10-03 22:06:09 +0200
commit9652bfcf2d2f3be5158ed88b49917bb5a2d8323d (patch)
tree331a3d8f4592abc15f464825efa3c7d4a018fbe9
parent214de2d815360aa3986eb52a3b3060c33523f1b3 (diff)
radeonsi: implement the simple case of force_persample_interp
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
-rw-r--r--src/gallium/drivers/radeonsi/si_pipe.h1
-rw-r--r--src/gallium/drivers/radeonsi/si_state.c1
-rw-r--r--src/gallium/drivers/radeonsi/si_state.h1
-rw-r--r--src/gallium/drivers/radeonsi/si_state_shaders.c35
4 files changed, 37 insertions, 1 deletions
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 60e97015cce..3ff4b46251e 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -209,6 +209,7 @@ struct si_context {
struct si_vertex_element *vertex_elements;
unsigned sprite_coord_enable;
bool flatshade;
+ bool force_persample_interp;
/* shader descriptors */
struct si_descriptors vertex_buffers;
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 85074bdbf5b..00d4bc1fbc2 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -686,6 +686,7 @@ static void *si_create_rs_state(struct pipe_context *ctx,
rs->two_side = state->light_twoside;
rs->multisample_enable = state->multisample;
+ rs->force_persample_interp = state->force_persample_interp;
rs->clip_plane_enable = state->clip_plane_enable;
rs->line_stipple_enable = state->line_stipple_enable;
rs->poly_stipple_enable = state->poly_stipple_enable;
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index 2257499f33c..6a567688ee4 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -50,6 +50,7 @@ struct si_state_rasterizer {
bool flatshade;
bool two_side;
bool multisample_enable;
+ bool force_persample_interp;
bool line_stipple_enable;
unsigned sprite_coord_enable;
unsigned pa_sc_line_stipple;
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index 43985330f6b..aeb28797ace 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -1067,6 +1067,36 @@ static void si_emit_spi_ps_input(struct si_context *sctx, struct r600_atom *atom
G_0286CC_LINEAR_CENTROID_ENA(input_ena) ||
G_0286CC_LINE_STIPPLE_TEX_ENA(input_ena));
+ if (sctx->force_persample_interp) {
+ unsigned num_persp = G_0286CC_PERSP_SAMPLE_ENA(input_ena) +
+ G_0286CC_PERSP_CENTER_ENA(input_ena) +
+ G_0286CC_PERSP_CENTROID_ENA(input_ena);
+ unsigned num_linear = G_0286CC_LINEAR_SAMPLE_ENA(input_ena) +
+ G_0286CC_LINEAR_CENTER_ENA(input_ena) +
+ G_0286CC_LINEAR_CENTROID_ENA(input_ena);
+
+ /* If only one set of (i,j) coordinates is used, we can disable
+ * CENTER/CENTROID, enable SAMPLE and it will load SAMPLE coordinates
+ * where CENTER/CENTROID are expected, effectively forcing per-sample
+ * interpolation.
+ */
+ if (num_persp == 1) {
+ input_ena &= C_0286CC_PERSP_CENTER_ENA;
+ input_ena &= C_0286CC_PERSP_CENTROID_ENA;
+ input_ena |= G_0286CC_PERSP_SAMPLE_ENA(1);
+ }
+ if (num_linear == 1) {
+ input_ena &= C_0286CC_LINEAR_CENTER_ENA;
+ input_ena &= C_0286CC_LINEAR_CENTROID_ENA;
+ input_ena |= G_0286CC_LINEAR_SAMPLE_ENA(1);
+ }
+
+ /* If at least 2 sets of coordinates are used, we can't use this
+ * trick and have to select SAMPLE using a conditional assignment
+ * in the shader with "force_persample_interp" being a shader constant.
+ */
+ }
+
radeon_set_context_reg_seq(cs, R_0286CC_SPI_PS_INPUT_ENA, 2);
radeon_emit(cs, input_ena);
radeon_emit(cs, input_ena);
@@ -1543,8 +1573,11 @@ bool si_update_shaders(struct si_context *sctx)
si_mark_atom_dirty(sctx, &sctx->spi_map);
}
- if (si_pm4_state_changed(sctx, ps))
+ if (si_pm4_state_changed(sctx, ps) ||
+ sctx->force_persample_interp != rs->force_persample_interp) {
+ sctx->force_persample_interp = rs->force_persample_interp;
si_mark_atom_dirty(sctx, &sctx->spi_ps_input);
+ }
if (si_pm4_state_changed(sctx, ls) ||
si_pm4_state_changed(sctx, hs) ||