zink: handle edgeflags
authorantonino <antonino.maniscalco@collabora.com>
Fri, 3 Feb 2023 10:44:39 +0000 (11:44 +0100)
committerMarge Bot <emma+marge@anholt.net>
Wed, 29 Mar 2023 19:18:40 +0000 (19:18 +0000)
Vulkan has no support for edgeflags.

If the user has a geometry shader bound nothing needs to be done as edgeflags
don't work with them, otherwise a geometry shader that emulates them
is generated.

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21238>

src/gallium/drivers/zink/ci/zink-anv-tgl-fails.txt
src/gallium/drivers/zink/ci/zink-lvp-fails.txt
src/gallium/drivers/zink/ci/zink-radv-navi10-fails.txt
src/gallium/drivers/zink/ci/zink-radv-vangogh-fails.txt
src/gallium/drivers/zink/zink_draw.cpp
src/gallium/drivers/zink/zink_program.c
src/gallium/drivers/zink/zink_program.h

index c1fedfe..ac4c7d8 100644 (file)
@@ -132,9 +132,6 @@ shaders@point-vertex-id gl_vertexid gl_instanceid divisor,Fail
 shaders@point-vertex-id gl_vertexid gl_instanceid,Fail
 shaders@point-vertex-id gl_vertexid,Fail
 
-spec@!opengl 1.0@gl-1.0-edgeflag-quads,Fail
-spec@!opengl 1.0@gl-1.0-edgeflag,Fail
-
 spec@!opengl 1.0@gl-1.0-no-op-paths,Fail
 
 spec@!opengl 1.0@gl-1.0-spot-light,Fail
@@ -178,9 +175,6 @@ spec@!opengl 1.1@linestipple,Fail
 # (and more)
 spec@!opengl 1.1@polygon-mode,Fail
 
-spec@!opengl 2.0@gl-2.0-edgeflag-immediate,Fail
-spec@!opengl 2.0@gl-2.0-edgeflag,Fail
-
 spec@!opengl 2.0@vs-point_size-zero,Fail
 
 spec@!opengl 2.1@pbo,Fail
index d7cef83..d7f5154 100644 (file)
@@ -52,8 +52,6 @@ shaders@point-vertex-id gl_vertexid,Fail
 shaders@point-vertex-id gl_vertexid divisor,Fail
 shaders@point-vertex-id gl_vertexid gl_instanceid,Fail
 shaders@point-vertex-id gl_vertexid gl_instanceid divisor,Fail
-spec@!opengl 1.0@gl-1.0-edgeflag,Fail
-spec@!opengl 1.0@gl-1.0-edgeflag-quads,Fail
 spec@!opengl 1.0@gl-1.0-no-op-paths,Fail
 spec@!opengl 1.1@linestipple,Fail
 spec@!opengl 1.1@linestipple@Factor 2x,Fail
@@ -77,8 +75,6 @@ spec@!opengl 1.1@polygon-mode-offset@config 6: Expected blue pixel in center,Fai
 spec@!opengl 1.1@polygon-mode-offset@config 6: Expected white pixel on right edge,Fail
 spec@!opengl 1.1@polygon-mode-offset@config 6: Expected white pixel on top edge,Fail
 spec@!opengl 1.2@copyteximage 3d,Fail
-spec@!opengl 2.0@gl-2.0-edgeflag,Fail
-spec@!opengl 2.0@gl-2.0-edgeflag-immediate,Fail
 spec@!opengl 2.1@pbo,Fail
 spec@!opengl 2.1@pbo@test_polygon_stip,Fail
 spec@!opengl 2.1@polygon-stipple-fs,Fail
index 0c0d650..3876670 100644 (file)
@@ -301,8 +301,6 @@ spec@khr_texture_compression_astc@sliced-3d-miptree-gl srgb-fp,Fail
 spec@khr_texture_compression_astc@sliced-3d-miptree-gl srgb-fp@sRGB decode full precision,Fail
 spec@oes_shader_io_blocks@compiler@layout-location-aliasing.vert,Fail
 
-spec@!opengl 1.0@gl-1.0-edgeflag,Fail
-spec@!opengl 1.0@gl-1.0-edgeflag-quads,Fail
 spec@!opengl 1.0@gl-1.0-no-op-paths,Fail
 spec@!opengl 1.1@linestipple@Factor 2x,Fail
 spec@!opengl 1.1@linestipple@Factor 3x,Fail
@@ -326,8 +324,6 @@ spec@!opengl 1.1@polygon-mode-offset@config 6: Expected white pixel on top edge,
 spec@!opengl 1.1@polygon-mode-offset,Fail
 spec@!opengl 1.5@depth-tex-compare,Fail
 
-spec@!opengl 2.0@gl-2.0-edgeflag,Fail
-spec@!opengl 2.0@gl-2.0-edgeflag-immediate,Fail
 spec@!opengl 2.0@vs-point_size-zero,Fail
 spec@!opengl 2.1@pbo,Fail
 spec@!opengl 2.1@pbo@test_polygon_stip,Fail
index 538a1c8..31358e0 100644 (file)
@@ -300,8 +300,6 @@ spec@khr_texture_compression_astc@sliced-3d-miptree-gl srgb-fp,Fail
 spec@khr_texture_compression_astc@sliced-3d-miptree-gl srgb-fp@sRGB decode full precision,Fail
 spec@oes_shader_io_blocks@compiler@layout-location-aliasing.vert,Fail
 
-spec@!opengl 1.0@gl-1.0-edgeflag,Fail
-spec@!opengl 1.0@gl-1.0-edgeflag-quads,Fail
 spec@!opengl 1.0@gl-1.0-no-op-paths,Fail
 spec@!opengl 1.1@linestipple@Factor 2x,Fail
 spec@!opengl 1.1@linestipple@Factor 3x,Fail
@@ -325,8 +323,6 @@ spec@!opengl 1.1@polygon-mode-offset@config 6: Expected white pixel on top edge,
 spec@!opengl 1.1@polygon-mode-offset,Fail
 spec@!opengl 1.5@depth-tex-compare,Fail
 
-spec@!opengl 2.0@gl-2.0-edgeflag,Fail
-spec@!opengl 2.0@gl-2.0-edgeflag-immediate,Fail
 spec@!opengl 2.0@vs-point_size-zero,Fail
 spec@!opengl 2.1@pbo,Fail
 spec@!opengl 2.1@pbo@test_polygon_stip,Fail
index 19c89c8..f370bc7 100644 (file)
@@ -506,9 +506,12 @@ zink_draw(struct pipe_context *pctx,
    }
    ctx->gfx_pipeline_state.gfx_prim_mode = mode;
 
-   if (!screen->optimal_keys &&
-       (lines_changed || points_changed || rast_state_changed || ctx->gfx_pipeline_state.modules_changed))
-      zink_set_primitive_emulation_keys(ctx);
+   if ((mode_changed || points_changed || lines_changed || rast_state_changed || ctx->gfx_pipeline_state.modules_changed)) {
+      if (screen->optimal_keys)
+         zink_create_primitive_emulation_gs(ctx);
+      else
+         zink_set_primitive_emulation_keys(ctx);
+   }
 
    if (index_size) {
       const VkIndexType index_type[3] = {
index e535ad0..34f64a9 100644 (file)
@@ -2172,6 +2172,34 @@ zink_driver_thread_add_job(struct pipe_screen *pscreen, void *data,
    util_queue_add_job(&screen->cache_get_thread, data, fence, execute, cleanup, job_size);
 }
 
+static bool
+has_edge_flags(struct zink_context *ctx)
+{
+   switch(ctx->gfx_pipeline_state.gfx_prim_mode) {
+   case PIPE_PRIM_POINTS:
+   case PIPE_PRIM_LINE_STRIP:
+   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+   case PIPE_PRIM_LINES:
+   case PIPE_PRIM_LINE_LOOP:
+   case PIPE_PRIM_LINES_ADJACENCY:
+   case PIPE_PRIM_TRIANGLE_STRIP:
+   case PIPE_PRIM_TRIANGLE_FAN:
+   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+   case PIPE_PRIM_QUAD_STRIP:
+      return false;
+   case PIPE_PRIM_TRIANGLES:
+   case PIPE_PRIM_TRIANGLES_ADJACENCY:
+   case PIPE_PRIM_QUADS:
+   case PIPE_PRIM_POLYGON:
+   case PIPE_PRIM_PATCHES:
+   case PIPE_PRIM_MAX:
+   default:
+      break;
+   }
+   return ctx->gfx_pipeline_state.rast_prim == PIPE_PRIM_LINES &&
+          ctx->gfx_stages[MESA_SHADER_VERTEX]->has_edgeflags;
+}
+
 void
 zink_set_primitive_emulation_keys(struct zink_context *ctx)
 {
@@ -2197,6 +2225,8 @@ zink_set_primitive_emulation_keys(struct zink_context *ctx)
                             ctx->rast_state->base.line_smooth &&
                             !ctx->num_so_targets;
 
+   bool lower_edge_flags = has_edge_flags(ctx);
+
    if (zink_get_fs_key(ctx)->lower_line_smooth != lower_line_smooth) {
       assert(zink_get_gs_key(ctx)->lower_line_smooth ==
              zink_get_fs_key(ctx)->lower_line_smooth);
@@ -2208,7 +2238,7 @@ zink_set_primitive_emulation_keys(struct zink_context *ctx)
       zink_set_fs_key(ctx)->lower_point_smooth = lower_point_smooth;
    }
 
-   if (lower_line_stipple || lower_line_smooth ||
+   if (lower_line_stipple || lower_line_smooth || lower_edge_flags ||
        zink_get_gs_key(ctx)->lower_gl_point) {
       enum pipe_shader_type prev_vertex_stage =
          ctx->gfx_stages[MESA_SHADER_TESS_EVAL] ?
@@ -2222,8 +2252,42 @@ zink_set_primitive_emulation_keys(struct zink_context *ctx)
             nir_shader *nir = nir_create_passthrough_gs(
                &screen->nir_options,
                ctx->gfx_stages[prev_vertex_stage]->nir,
-               (lower_line_stipple || lower_line_smooth) ? SHADER_PRIM_LINE_STRIP :  SHADER_PRIM_POINTS,
-               false);
+               ctx->gfx_pipeline_state.gfx_prim_mode,
+               lower_edge_flags);
+
+            struct zink_shader *shader = zink_shader_create(screen, nir, NULL);
+            ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs[ctx->gfx_pipeline_state.gfx_prim_mode] = shader;
+            shader->non_fs.is_generated = true;
+         }
+
+         bind_gfx_stage(ctx, MESA_SHADER_GEOMETRY,
+                        ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs[ctx->gfx_pipeline_state.gfx_prim_mode]);
+      }
+   } else if (ctx->gfx_stages[MESA_SHADER_GEOMETRY] &&
+              ctx->gfx_stages[MESA_SHADER_GEOMETRY]->non_fs.is_generated)
+         bind_gfx_stage(ctx, MESA_SHADER_GEOMETRY, NULL);
+}
+
+void
+zink_create_primitive_emulation_gs(struct zink_context *ctx)
+{
+   struct zink_screen *screen = zink_screen(ctx->base.screen);
+   bool lower_edge_flags = has_edge_flags(ctx);
+
+   if (lower_edge_flags) {
+      enum pipe_shader_type prev_vertex_stage =
+         ctx->gfx_stages[MESA_SHADER_TESS_EVAL] ?
+            MESA_SHADER_TESS_EVAL : MESA_SHADER_VERTEX;
+
+      if (!ctx->gfx_stages[MESA_SHADER_GEOMETRY] ||
+          (ctx->gfx_stages[MESA_SHADER_GEOMETRY]->nir->info.gs.input_primitive != ctx->gfx_pipeline_state.gfx_prim_mode)) {
+
+         if (!ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs[ctx->gfx_pipeline_state.gfx_prim_mode]) {
+            nir_shader *nir = nir_create_passthrough_gs(
+               &screen->nir_options,
+               ctx->gfx_stages[prev_vertex_stage]->nir,
+               ctx->gfx_pipeline_state.gfx_prim_mode,
+               lower_edge_flags);
 
             struct zink_shader *shader = zink_shader_create(screen, nir, NULL);
             ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs[ctx->gfx_pipeline_state.gfx_prim_mode] = shader;
index 1a8d287..5633ea5 100644 (file)
@@ -363,6 +363,9 @@ zink_set_fs_point_coord_key(struct zink_context *ctx)
 void
 zink_set_primitive_emulation_keys(struct zink_context *ctx);
 
+void
+zink_create_primitive_emulation_gs(struct zink_context *ctx);
+
 static inline const struct zink_shader_key_base *
 zink_get_shader_key_base(const struct zink_context *ctx, gl_shader_stage pstage)
 {