radeonsi: adjust clip discard based on line width / point size
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Tue, 26 Sep 2017 18:36:10 +0000 (20:36 +0200)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Mon, 2 Oct 2017 13:07:45 +0000 (15:07 +0200)
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/radeonsi/si_state.c
src/gallium/drivers/radeonsi/si_state.h
src/gallium/drivers/radeonsi/si_state_viewport.c

index 78a3fbd086ef562fcdebfe08eb8819d109b61e15..4965a8374ff853283ddf3fea9ddc7972d8c75ddc 100644 (file)
@@ -858,6 +858,7 @@ static void *si_create_rs_state(struct pipe_context *ctx,
        rs->line_stipple_enable = state->line_stipple_enable;
        rs->poly_stipple_enable = state->poly_stipple_enable;
        rs->line_smooth = state->line_smooth;
+       rs->line_width = state->line_width;
        rs->poly_smooth = state->poly_smooth;
        rs->uses_poly_offset = state->offset_point || state->offset_line ||
                               state->offset_tri;
@@ -897,6 +898,8 @@ static void *si_create_rs_state(struct pipe_context *ctx,
                psize_min = state->point_size;
                psize_max = state->point_size;
        }
+       rs->max_point_size = psize_max;
+
        /* Divide by two, because 0.5 = 1 pixel. */
        si_pm4_set_reg(pm4, R_028A04_PA_SU_POINT_MINMAX,
                        S_028A04_MIN_SIZE(si_pack_float_12p4(psize_min/2)) |
@@ -1007,7 +1010,9 @@ static void si_bind_rs_state(struct pipe_context *ctx, void *state)
        si_update_poly_offset_state(sctx);
 
        if (!old_rs ||
-           old_rs->scissor_enable != rs->scissor_enable) {
+           (old_rs->scissor_enable != rs->scissor_enable ||
+            old_rs->line_width != rs->line_width ||
+            old_rs->max_point_size != rs->max_point_size)) {
                sctx->scissors.dirty_mask = (1 << SI_MAX_VIEWPORTS) - 1;
                si_mark_atom_dirty(sctx, &sctx->scissors.atom);
        }
index 4388ea99daf2bdc8730210562e6d37142a85cd83..8e414a0817caeb2909f024fd59f586acd51c4c0a 100644 (file)
@@ -68,6 +68,8 @@ struct si_state_rasterizer {
        struct si_pm4_state     *pm4_poly_offset;
        unsigned                pa_sc_line_stipple;
        unsigned                pa_cl_clip_cntl;
+       float                   line_width;
+       float                   max_point_size;
        unsigned                sprite_coord_enable:8;
        unsigned                clip_plane_enable:8;
        unsigned                flatshade:1;
index 1201be8779e4cf9054085de6435cc6a521ffbb2b..a96eb8adc1349358ce1143fa0697f96ca614bbf1 100644 (file)
@@ -187,17 +187,26 @@ static void si_emit_guardband(struct si_context *ctx,
        discard_x = 1.0;
        discard_y = 1.0;
 
-       if (ctx->current_rast_prim < PIPE_PRIM_TRIANGLES) {
+       if (unlikely(ctx->current_rast_prim < PIPE_PRIM_TRIANGLES) &&
+           ctx->queued.named.rasterizer) {
                /* When rendering wide points or lines, we need to be more
-                * conservative about when to discard them entirely. Since
-                * point size can be determined by the VS output, we basically
-                * disable discard completely completely here.
-                *
-                * TODO: This can hurt performance when rendering lines and
-                * points with fixed size, and could be improved.
-                */
-               discard_x = guardband_x;
-               discard_y = guardband_y;
+                * conservative about when to discard them entirely. */
+               const struct si_state_rasterizer *rs = ctx->queued.named.rasterizer;
+               float pixels;
+
+               if (ctx->current_rast_prim == PIPE_PRIM_POINTS)
+                       pixels = rs->max_point_size;
+               else
+                       pixels = rs->line_width;
+
+               /* Add half the point size / line width */
+               discard_x += pixels / (2.0 * vp.scale[0]);
+               discard_y += pixels / (2.0 * vp.scale[1]);
+
+               /* Discard primitives that would lie entirely outside the clip
+                * region. */
+               discard_x = MIN2(discard_x, guardband_x);
+               discard_y = MIN2(discard_y, guardband_y);
        }
 
        /* If any of the GB registers is updated, all of them must be updated. */