diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c index 6375d41295c..755e52793a8 100644 --- a/src/gallium/auxiliary/draw/draw_gs.c +++ b/src/gallium/auxiliary/draw/draw_gs.c @@ -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,24 +628,27 @@ 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); + + /* 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); } - debug_assert(shader->fetched_prim_count == 0); - /* Update prim_info: */ output_prims->linear = TRUE; @@ -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; diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h index 49e93d55a51..663ba847cfe 100644 --- a/src/gallium/auxiliary/draw/draw_gs.h +++ b/src/gallium/auxiliary/draw/draw_gs.h @@ -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; diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c index 369f56a1955..711413cdaf6 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_scan.c +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c @@ -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) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.h b/src/gallium/auxiliary/tgsi/tgsi_scan.h index af4b128fcaf..b81bdd71f14 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_scan.h +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.h @@ -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;