draw/tgsi: implement geom shader invocation support.
authorDave Airlie <airlied@redhat.com>
Wed, 20 May 2015 00:32:32 +0000 (10:32 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 23 Jun 2015 05:53:49 +0000 (15:53 +1000)
This is just for softpipe, llvmpipe won't work without
some changes.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/auxiliary/draw/draw_gs.c
src/gallium/auxiliary/draw/draw_gs.h
src/gallium/auxiliary/tgsi/tgsi_scan.c
src/gallium/auxiliary/tgsi/tgsi_scan.h

index 6375d41295c24c88b1bce42c257b47f6485e8e5a..755e52793a80429b2fc75eb09f4a41842dcb8428 100644 (file)
@@ -190,9 +190,15 @@ 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].i[j] = shader->invocation_id;
+   }
 }
 
 static unsigned tgsi_gs_run(struct draw_geometry_shader *shader,
@@ -555,7 +561,7 @@ 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;
    //Assume at least one primitive
    max_out_prims = MAX2(max_out_prims, 1);
 
@@ -564,7 +570,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
    output_verts->stride = output_verts->vertex_size;
    output_verts->verts =
       (struct vertex_header *)MALLOC(output_verts->vertex_size *
-                                     total_verts_per_buffer);
+                                     total_verts_per_buffer * shader->num_invocations);
    debug_assert(output_verts->verts);
 
 #if 0
@@ -592,7 +598,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
    shader->input = input;
    shader->input_info = input_info;
    FREE(shader->primitive_lengths);
-   shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));
+   shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned) * shader->num_invocations);
 
 
 #ifdef HAVE_LLVM
@@ -622,23 +628,26 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
    }
 #endif
 
-   shader->prepare(shader, constants, constants_size);
+   for (invocation = 0; invocation < shader->num_invocations; invocation++) {
+      shader->invocation_id = invocation;
 
-   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);
+      shader->prepare(shader, constants, constants_size);
 
-   /* Flush the remaining primitives. Will happen if
-    * num_input_primitives % 4 != 0
-    */
-   if (shader->fetched_prim_count > 0) {
-      gs_flush(shader);
-   }
+      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);
 
-   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:
     */
@@ -771,6 +780,8 @@ draw_create_geometry_shader(struct draw_context *draw,
          gs->info.properties[TGSI_PROPERTY_GS_OUTPUT_PRIM];
    gs->max_output_vertices =
          gs->info.properties[TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES];
+   gs->num_invocations =
+      gs->info.properties[TGSI_PROPERTY_GS_INVOCATIONS];
    if (!gs->max_output_vertices)
       gs->max_output_vertices = 32;
 
index 49e93d55a51eea082a391bd3f8385e8670612bc1..663ba847cfe7ad9eb84a19c83db65ed9b3ef6537 100644 (file)
@@ -90,6 +90,8 @@ struct draw_geometry_shader {
    unsigned vector_length;
    unsigned max_out_prims;
 
+   unsigned num_invocations;
+   unsigned invocation_id;
 #ifdef HAVE_LLVM
    struct draw_gs_inputs *gs_input;
    struct draw_gs_jit_context *jit_context;
index 369f56a1955558c9eabe692e6a785985b4fba817..711413cdaf6ec50379cadf1e1c9cdf2f09e10ddb 100644 (file)
@@ -248,6 +248,8 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
                   }
                   else if (semName == TGSI_SEMANTIC_PRIMID) {
                      info->uses_primid = TRUE;
+                  } else if (semName == TGSI_SEMANTIC_INVOCATIONID) {
+                     info->uses_invocationid = TRUE;
                   }
                }
                else if (file == TGSI_FILE_OUTPUT) {
index af4b128fcaf3d07a7be10f87ce8dbcaa17448c68..b81bdd71f143cdd8075da8093eb1ea78e672c159 100644 (file)
@@ -89,6 +89,7 @@ struct tgsi_shader_info
    boolean uses_basevertex;
    boolean uses_primid;
    boolean uses_frontface;
+   boolean uses_invocationid;
    boolean writes_psize;
    boolean writes_clipvertex;
    boolean writes_viewport_index;