zink: fix stipple pattern in oblique lines
authorantonino <antonino.maniscalco@collabora.com>
Mon, 6 Feb 2023 15:16:04 +0000 (16:16 +0100)
committerMarge Bot <emma+marge@anholt.net>
Fri, 10 Mar 2023 14:52:01 +0000 (14:52 +0000)
Stipple lines now appear correctly when they are oblique.

Previously the number of steps of the stipple counter between two vertices
was calculated as the euclidian distance between them in screen space, however
the length occupied by pixel along a line is only `1` for lines that are either
vertical or horizontal and will be anywhere between `1` and `sqrt(2)`
for other cases.

Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21290>

src/gallium/drivers/zink/zink_compiler.c
src/gallium/drivers/zink/zink_program.c
src/gallium/drivers/zink/zink_program.h
src/gallium/drivers/zink/zink_shader_keys.h
src/gallium/drivers/zink/zink_state.c

index ae6aed5..d516091 100644 (file)
@@ -390,6 +390,7 @@ struct lower_line_stipple_state {
    nir_variable *prev_pos;
    nir_variable *pos_counter;
    nir_variable *stipple_counter;
+   bool line_rectangular;
 };
 
 static nir_ssa_def *
@@ -428,7 +429,13 @@ lower_line_stipple_gs_instr(nir_builder *b, nir_instr *instr, void *data)
    curr = viewport_map(b, curr, vp_scale);
 
    // calculate length of line
-   nir_ssa_def *len = nir_fast_distance(b, prev, curr);
+   nir_ssa_def *len;
+   if (state->line_rectangular)
+      len = nir_fast_distance(b, prev, curr);
+   else {
+      nir_ssa_def *diff = nir_fabs(b, nir_fsub(b, prev, curr));
+      len = nir_fmax(b, nir_channel(b, diff, 0), nir_channel(b, diff, 1));
+   }
    // update stipple_counter
    nir_store_var(b, state->stipple_counter,
                     nir_fadd(b, nir_load_var(b, state->stipple_counter),
@@ -448,7 +455,7 @@ lower_line_stipple_gs_instr(nir_builder *b, nir_instr *instr, void *data)
 }
 
 static bool
-lower_line_stipple_gs(nir_shader *shader)
+lower_line_stipple_gs(nir_shader *shader, bool line_rectangular)
 {
    nir_builder b;
    struct lower_line_stipple_state state;
@@ -480,6 +487,7 @@ lower_line_stipple_gs(nir_shader *shader)
                                                glsl_float_type(),
                                                "__stipple_counter");
 
+   state.line_rectangular = line_rectangular;
    // initialize pos_counter and stipple_counter
    nir_function_impl *entry = nir_shader_get_entrypoint(shader);
    nir_builder_init(&b, entry);
@@ -3073,7 +3081,7 @@ zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs,
 
          case MESA_SHADER_GEOMETRY:
             if (zink_gs_key(key)->lower_line_stipple) {
-               NIR_PASS_V(nir, lower_line_stipple_gs);
+               NIR_PASS_V(nir, lower_line_stipple_gs, zink_gs_key(key)->line_rectangular);
                NIR_PASS_V(nir, nir_lower_var_copies);
                need_optimize = true;
             }
index 41ddfb5..a9c6236 100644 (file)
@@ -1713,6 +1713,13 @@ zink_update_fs_key_samples(struct zink_context *ctx)
    }
 }
 
+void zink_update_gs_key_rectangular_line(struct zink_context *ctx)
+{
+   bool line_rectangular = zink_get_gs_key(ctx)->line_rectangular;
+   if (line_rectangular != ctx->rast_state->base.line_rectangular)
+      zink_set_gs_key(ctx)->line_rectangular = ctx->rast_state->base.line_rectangular;
+}
+
 static void
 zink_bind_fs_state(struct pipe_context *pctx,
                    void *cso)
index 2cc917d..d608a2c 100644 (file)
@@ -312,6 +312,9 @@ zink_get_tcs_key(const struct zink_context *ctx)
 void
 zink_update_fs_key_samples(struct zink_context *ctx);
 
+void
+zink_update_gs_key_rectangular_line(struct zink_context *ctx);
+
 static inline struct zink_vs_key *
 zink_set_vs_key(struct zink_context *ctx)
 {
index 3bbf2be..b5929ef 100644 (file)
@@ -63,6 +63,7 @@ struct zink_gs_key {
    bool lower_line_stipple : 1;
    bool lower_line_smooth : 1;
    bool lower_gl_point : 1;
+   bool line_rectangular : 1;
    // not hashed
    unsigned size;
 };
index 4661475..3938109 100644 (file)
@@ -709,6 +709,9 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
 
       if (ctx->rast_state->base.half_pixel_center != half_pixel_center)
          ctx->vp_state_changed = true;
+
+      if (!screen->optimal_keys)
+         zink_update_gs_key_rectangular_line(ctx);
    }
 }