radeonsi: implement line and polygon smoothing
authorMarek Olšák <marek.olsak@amd.com>
Sun, 15 Mar 2015 17:20:19 +0000 (18:20 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 16 Mar 2015 11:54:19 +0000 (12:54 +0100)
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 1bc664a50ec4f37e4c16bc5ee01f9737bb608025..7c37a3e6fc98e2f61fdd8916e3cf14acc134518c 100644 (file)
@@ -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;
index f844fc192013b70ac767f69b3a58e0acbe1f805f..c7633dcfa39b47747af5238a9a396a8b2f539c1d 100644 (file)
@@ -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 */
index 4e6b1e27c46c06e06fb5fe713f7b6598a4eca6d3..27dd2c30d96375b1c98ad97f9a807da7fd682ab5 100644 (file)
@@ -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 {
index 8c3bdc5fda581ace3abd8e16b6578ffcc3db7a9f..382738a21212e0f6a38ecfe23e6141ccb909f108 100644 (file)
@@ -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)