radeonsi: implement the simple case of force_persample_interp
authorMarek Olšák <marek.olsak@amd.com>
Mon, 28 Sep 2015 15:21:10 +0000 (17:21 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Sat, 3 Oct 2015 20:06:09 +0000 (22:06 +0200)
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_state.c
src/gallium/drivers/radeonsi/si_state.h
src/gallium/drivers/radeonsi/si_state_shaders.c

index 60e9701..3ff4b46 100644 (file)
@@ -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;
index 85074bd..00d4bc1 100644 (file)
@@ -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;
index 2257499..6a56768 100644 (file)
@@ -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;
index 4398533..aeb2879 100644 (file)
@@ -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) ||