draw/gs: reverse the polarity of the invocation/prims execution
authorDave Airlie <airlied@redhat.com>
Tue, 14 Apr 2020 02:39:42 +0000 (12:39 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 7 Jul 2020 20:06:05 +0000 (06:06 +1000)
The current code runs primitives per invocation, but the spec wants
invocations per primitive. However it means having to flush
after each invocation to get correct XFB behaviour

Fixes:
GTF-GL41.gtf40.GL3Tests.transform_feedback3.transform_feedback3_geometry_instanced

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5555>

src/gallium/auxiliary/draw/draw_gs.c

index f648a96db7b785f3d564cb081764247458514680..2d11430b274af2b5c83f7e089a82a7dbe8e00968 100644 (file)
@@ -69,7 +69,7 @@ draw_gs_get_input_index(int semantic, int index,
 static inline boolean
 draw_gs_should_flush(struct draw_geometry_shader *shader)
 {
-   return (shader->fetched_prim_count == shader->vector_length);
+   return (shader->fetched_prim_count == shader->vector_length || shader->num_invocations > 1);
 }
 
 /*#define DEBUG_OUTPUTS 1*/
@@ -192,15 +192,8 @@ static void tgsi_gs_prepare(struct draw_geometry_shader *shader,
                             const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS])
 {
    struct tgsi_exec_machine *machine = shader->machine;
-   int j;
    tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
                                   constants, constants_size);
-
-   if (shader->info.uses_invocationid) {
-      unsigned i = machine->SysSemanticToIndex[TGSI_SEMANTIC_INVOCATIONID];
-      for (j = 0; j < TGSI_QUAD_SIZE; j++)
-         machine->SystemValue[i].xyzw[0].i[j] = shader->invocation_id;
-   }
 }
 
 static void tgsi_gs_run(struct draw_geometry_shader *shader,
@@ -210,6 +203,12 @@ static void tgsi_gs_run(struct draw_geometry_shader *shader,
    struct tgsi_exec_machine *machine = shader->machine;
    int i;
 
+   if (shader->info.uses_invocationid) {
+      unsigned i = machine->SysSemanticToIndex[TGSI_SEMANTIC_INVOCATIONID];
+      for (int j = 0; j < TGSI_QUAD_SIZE; j++)
+         machine->SystemValue[i].xyzw[0].i[j] = shader->invocation_id;
+   }
+
    /* run interpreter */
    tgsi_exec_machine_run(machine, 0);
 
@@ -437,10 +436,13 @@ static void gs_flush(struct draw_geometry_shader *shader)
    debug_assert(input_primitives > 0 &&
                 input_primitives <= 4);
 
-   shader->run(shader, input_primitives, out_prim_count);
-   for (i = 0; i < shader->num_vertex_streams; i++) {
-      shader->fetch_outputs(shader, i, out_prim_count[i],
-                            &shader->stream[i].tmp_output);
+   for (unsigned invocation = 0; invocation < shader->num_invocations; invocation++) {
+      shader->invocation_id = invocation;
+      shader->run(shader, input_primitives, out_prim_count);
+      for (i = 0; i < shader->num_vertex_streams; i++) {
+         shader->fetch_outputs(shader, i, out_prim_count[i],
+                               &shader->stream[i].tmp_output);
+      }
    }
 
 #if 0
@@ -592,7 +594,6 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
     * overflown vertices into some area where they won't harm anyone */
    unsigned total_verts_per_buffer = shader->primitive_boundary *
       num_in_primitives;
-   unsigned invocation;
    int i;
    //Assume at least one primitive
    max_out_prims = MAX2(max_out_prims, 1);
@@ -666,26 +667,22 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
    }
 #endif
 
-   for (invocation = 0; invocation < shader->num_invocations; invocation++) {
-      shader->invocation_id = invocation;
+   shader->prepare(shader, constants, constants_size);
 
-      shader->prepare(shader, constants, constants_size);
+   if (input_prim->linear)
+      gs_run(shader, input_prim, input_verts,
+             output_prims, output_verts);
+   else
+      gs_run_elts(shader, input_prim, input_verts,
+                  output_prims, output_verts);
 
-      if (input_prim->linear)
-         gs_run(shader, input_prim, input_verts,
-                output_prims, output_verts);
-      else
-         gs_run_elts(shader, input_prim, input_verts,
-                     output_prims, output_verts);
-
-      /* Flush the remaining primitives. Will happen if
-       * num_input_primitives % 4 != 0
-       */
-      if (shader->fetched_prim_count > 0) {
-         gs_flush(shader);
-      }
-      debug_assert(shader->fetched_prim_count == 0);
+   /* Flush the remaining primitives. Will happen if
+    * num_input_primitives % 4 != 0
+    */
+   if (shader->fetched_prim_count > 0) {
+      gs_flush(shader);
    }
+   debug_assert(shader->fetched_prim_count == 0);
 
    /* Update prim_info:
     */