draw/gs: reverse the polarity of the invocation/prims execution

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>
This commit is contained in:
Dave Airlie 2020-04-14 12:39:42 +10:00
parent 1c9bf586e7
commit 3e455d6ad3

View 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:
*/