st/mesa: Replace UsesStreams by ActiveStreamMask for GS
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>
Thu, 19 Mar 2020 08:59:27 +0000 (04:59 -0400)
committerMarge Bot <eric+marge@anholt.net>
Tue, 18 Aug 2020 11:17:26 +0000 (11:17 +0000)
Some drivers need to know which streams are used by a geometry
shader. Adding a mask of active streams makes the use of
UsesStreams superfluous as it's the equivalent of:

    ActiveStreamMask != (1 << 0)

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5984>

src/compiler/glsl/linker.cpp
src/compiler/nir/nir_gather_info.c
src/compiler/nir/nir_lower_gs_intrinsics.c
src/compiler/shader_info.h
src/intel/compiler/brw_vec4_gs_visitor.cpp
src/mesa/main/mtypes.h
src/mesa/main/shaderapi.c
src/mesa/main/shaderobj.c

index 8761c16e2fefca58acdf7871810b1a281c844ee8..52646752c977c08426de190954204198467a521d 100644 (file)
@@ -332,7 +332,7 @@ public:
         invalid_stream_id(0),
         invalid_stream_id_from_emit_vertex(false),
         end_primitive_found(false),
-        uses_non_zero_stream(false)
+        used_streams(0)
    {
       /* empty */
    }
@@ -353,8 +353,7 @@ public:
          return visit_stop;
       }
 
-      if (stream_id != 0)
-         uses_non_zero_stream = true;
+      used_streams |= 1 << stream_id;
 
       return visit_continue;
    }
@@ -377,8 +376,7 @@ public:
          return visit_stop;
       }
 
-      if (stream_id != 0)
-         uses_non_zero_stream = true;
+      used_streams |= 1 << stream_id;
 
       return visit_continue;
    }
@@ -399,9 +397,9 @@ public:
       return invalid_stream_id;
    }
 
-   bool uses_streams()
+   unsigned active_stream_mask()
    {
-      return uses_non_zero_stream;
+      return used_streams;
    }
 
    bool uses_end_primitive()
@@ -414,7 +412,7 @@ private:
    int invalid_stream_id;
    bool invalid_stream_id_from_emit_vertex;
    bool end_primitive_found;
-   bool uses_non_zero_stream;
+   unsigned used_streams;
 };
 
 /* Class that finds array derefs and check if indexes are dynamic. */
@@ -811,7 +809,7 @@ validate_geometry_shader_emissions(struct gl_context *ctx,
                       emit_vertex.error_stream(),
                       ctx->Const.MaxVertexStreams - 1);
       }
-      prog->Geom.UsesStreams = emit_vertex.uses_streams();
+      prog->Geom.ActiveStreamMask = emit_vertex.active_stream_mask();
       prog->Geom.UsesEndPrimitive = emit_vertex.uses_end_primitive();
 
       /* From the ARB_gpu_shader5 spec:
@@ -834,11 +832,11 @@ validate_geometry_shader_emissions(struct gl_context *ctx,
        * Since we can call EmitVertex() and EndPrimitive() when we output
        * primitives other than points, calling EmitStreamVertex(0) or
        * EmitEndPrimitive(0) should not produce errors. This it also what Nvidia
-       * does. Currently we only set prog->Geom.UsesStreams to TRUE when
-       * EmitStreamVertex() or EmitEndPrimitive() are called with a non-zero
+       * does. We can use prog->Geom.ActiveStreamMask to check whether only the
+       * first (zero) stream is active.
        * stream.
        */
-      if (prog->Geom.UsesStreams &&
+      if (prog->Geom.ActiveStreamMask & ~(1 << 0) &&
           sh->Program->info.gs.output_primitive != GL_POINTS) {
          linker_error(prog, "EmitStreamVertex(n) and EndStreamPrimitive(n) "
                       "with n>0 requires point output\n");
index 0e2624c4219298c633f21ebeaff53757ed4dc1d8..5f59dd21dd0c833b46ae760cf932616fe869fe18 100644 (file)
@@ -390,8 +390,7 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
 
    case nir_intrinsic_emit_vertex:
    case nir_intrinsic_emit_vertex_with_counter:
-      if (nir_intrinsic_stream_id(instr) > 0)
-         shader->info.gs.uses_streams = true;
+      shader->info.gs.active_stream_mask |= 1 << nir_intrinsic_stream_id(instr);
 
       break;
 
index 9d7cfbee4270f006b0cf79ce37a08ae64a2a3419..6e0f4da360e931888c51f65eb1414b1c59516563 100644 (file)
@@ -76,6 +76,7 @@ rewrite_emit_vertex(nir_intrinsic_instr *intrin, struct state *state)
 
    /* Load the vertex count */
    b->cursor = nir_before_instr(&intrin->instr);
+   assert(state->vertex_count_vars[stream] != NULL);
    nir_ssa_def *count = nir_load_var(b, state->vertex_count_vars[stream]);
 
    nir_ssa_def *max_vertices =
@@ -117,6 +118,7 @@ rewrite_end_primitive(nir_intrinsic_instr *intrin, struct state *state)
    unsigned stream = nir_intrinsic_stream_id(intrin);
 
    b->cursor = nir_before_instr(&intrin->instr);
+   assert(state->vertex_count_vars[stream] != NULL);
    nir_ssa_def *count = nir_load_var(b, state->vertex_count_vars[stream]);
 
    nir_intrinsic_instr *lowered =
@@ -197,20 +199,23 @@ nir_lower_gs_intrinsics(nir_shader *shader, bool per_stream)
 
    /* Create the counter variables */
    b.cursor = nir_before_cf_list(&impl->body);
-   unsigned num_counters = per_stream && shader->info.gs.uses_streams ?
-                           NIR_MAX_XFB_STREAMS : 1;
-   for (unsigned i = 0; i < num_counters; i++) {
-      state.vertex_count_vars[i] =
-         nir_local_variable_create(impl, glsl_uint_type(), "vertex_count");
-      /* initialize to 0 */
-      nir_store_var(&b, state.vertex_count_vars[i], nir_imm_int(&b, 0), 0x1);
+   for (unsigned i = 0; i < NIR_MAX_XFB_STREAMS; i++) {
+      if (per_stream && !(shader->info.gs.active_stream_mask & (1 << i)))
+         continue;
+
+      if (i == 0 || per_stream) {
+         state.vertex_count_vars[i] =
+            nir_local_variable_create(impl, glsl_uint_type(), "vertex_count");
+         /* initialize to 0 */
+         nir_store_var(&b, state.vertex_count_vars[i], nir_imm_int(&b, 0), 0x1);
+      } else {
+         /* If per_stream is false, we only have one counter which we want to use
+          * for all streams.  Duplicate the counter pointer so all streams use the
+          * same counter.
+          */
+         state.vertex_count_vars[i] = state.vertex_count_vars[0];
+      }
    }
-   /* If per_stream is false, we only have one counter which we want to use
-    * for all streams.  Duplicate the counter pointer so all streams use the
-    * same counter.
-    */
-   for (unsigned i = num_counters; i < NIR_MAX_XFB_STREAMS; i++)
-      state.vertex_count_vars[i] = state.vertex_count_vars[0];
 
    nir_foreach_block_safe(block, impl)
       rewrite_intrinsics(block, &state);
index c4294b3b1406876b599b5cd40eb90387e5ac7da6..8c632de53871c49a3ab5c6934bb3fdbfc38aed46 100644 (file)
@@ -234,8 +234,8 @@ typedef struct shader_info {
          /** Whether or not this shader uses EndPrimitive */
          bool uses_end_primitive:1;
 
-         /** Whether or not this shader uses non-zero streams */
-         bool uses_streams:1;
+         /** The streams used in this shaders (max. 4) */
+         uint8_t active_stream_mask:4;
       } gs;
 
       struct {
index ce341806c7b93ebe3ca79e775f67e7cae45aac3a..58f6f1212ac0758a85480948bc212469c57b5857 100644 (file)
@@ -667,8 +667,8 @@ brw_compile_gs(const struct brw_compiler *compiler, void *log_data,
           */
          prog_data->control_data_format = GEN7_GS_CONTROL_DATA_FORMAT_GSCTL_SID;
 
-         /* We only have to emit control bits if we are using streams */
-         if (shader->info.gs.uses_streams)
+         /* We only have to emit control bits if we are using non-zero streams */
+         if (shader->info.gs.active_stream_mask != (1 << 0))
             c.control_data_bits_per_vertex = 2;
          else
             c.control_data_bits_per_vertex = 0;
index f78d2b5d980e33c02c71a4f20c9b02b2308151c7..0feebc5f5d01bb6412110cea21f46a1c4fd72d91 100644 (file)
@@ -3050,7 +3050,7 @@ struct gl_shader_program
       GLint VerticesIn;
 
       bool UsesEndPrimitive;
-      bool UsesStreams;
+      unsigned ActiveStreamMask;
    } Geom;
 
    /**
index 19d7a3ab44003261b2bc601481fec61f093cbded..86c8c8597d9a90c4dfa4c3c6b0a1413d22b826c8 100644 (file)
@@ -2610,7 +2610,7 @@ _mesa_copy_linked_program_data(const struct gl_shader_program *src,
    case MESA_SHADER_GEOMETRY: {
       dst->info.gs.vertices_in = src->Geom.VerticesIn;
       dst->info.gs.uses_end_primitive = src->Geom.UsesEndPrimitive;
-      dst->info.gs.uses_streams = src->Geom.UsesStreams;
+      dst->info.gs.active_stream_mask = src->Geom.ActiveStreamMask;
       break;
    }
    case MESA_SHADER_FRAGMENT: {
index a2478d969759e5932600f839852c41882ed4e497..9a4225d608a026df7e81e215bb6f28d46ccc403f 100644 (file)
@@ -291,7 +291,7 @@ init_shader_program(struct gl_shader_program *prog)
    prog->FragDataIndexBindings = string_to_uint_map_ctor();
 
    prog->Geom.UsesEndPrimitive = false;
-   prog->Geom.UsesStreams = false;
+   prog->Geom.ActiveStreamMask = 0;
 
    prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS;