summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2013-03-14 01:07:28 -0700
committerZack Rusin <[email protected]>2013-03-27 03:53:01 -0700
commitedcebe665d1204269f5961079a63c5f632cf3f07 (patch)
tree7441556ac0a073b2c3070659d10db906aed4aa70
parent014c4d1cd7f147d5365302d15bdb35d9e4b040d0 (diff)
draw/gs: Fetch more than one primitive per invocation
Allows executing gs on up to 4 primitives at a time. Will also be required by the llvm code because there we definitely don't want to flush with just a single primitive. Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: Brian Paul <[email protected]> Reviewed-by: José Fonseca <[email protected]>
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.c60
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.h1
2 files changed, 48 insertions, 13 deletions
diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
index 81d9140d2f4..cde07563c3b 100644
--- a/src/gallium/auxiliary/draw/draw_gs.c
+++ b/src/gallium/auxiliary/draw/draw_gs.c
@@ -58,6 +58,18 @@ draw_gs_get_input_index(int semantic, int index,
return -1;
}
+/**
+ * We execute geometry shaders in the SOA mode, so ideally we want to
+ * flush when the number of currently fetched primitives is equal to
+ * the number of elements in the SOA vector. This ensures that the
+ * throughput is optimized for the given vector instrunction set.
+ */
+static INLINE boolean
+draw_gs_should_flush(struct draw_geometry_shader *shader)
+{
+ return (shader->fetched_prim_count == 4);
+}
+
/*#define DEBUG_OUTPUTS 1*/
static void
tgsi_fetch_gs_outputs(struct draw_geometry_shader *shader,
@@ -197,13 +209,14 @@ static unsigned tgsi_gs_run(struct draw_geometry_shader *shader,
machine->Temps[TGSI_EXEC_TEMP_PRIMITIVE_I].xyzw[TGSI_EXEC_TEMP_PRIMITIVE_C].u[0];
}
-static void gs_flush(struct draw_geometry_shader *shader,
- unsigned input_primitives)
+static void gs_flush(struct draw_geometry_shader *shader)
{
unsigned out_prim_count;
+ unsigned input_primitives = shader->fetched_prim_count;
+
debug_assert(input_primitives > 0 &&
- input_primitives < 4);
+ input_primitives <= 4);
out_prim_count = shader->run(shader, input_primitives);
#if 0
@@ -213,6 +226,7 @@ static void gs_flush(struct draw_geometry_shader *shader,
#endif
shader->fetch_outputs(shader, out_prim_count,
&shader->tmp_output);
+ shader->fetched_prim_count = 0;
}
static void gs_point(struct draw_geometry_shader *shader,
@@ -222,10 +236,12 @@ static void gs_point(struct draw_geometry_shader *shader,
indices[0] = idx;
- shader->fetch_inputs(shader, indices, 1, 0);
+ shader->fetch_inputs(shader, indices, 1,
+ shader->fetched_prim_count);
++shader->in_prim_idx;
+ ++shader->fetched_prim_count;
- gs_flush(shader, 1);
+ gs_flush(shader);
}
static void gs_line(struct draw_geometry_shader *shader,
@@ -236,10 +252,12 @@ static void gs_line(struct draw_geometry_shader *shader,
indices[0] = i0;
indices[1] = i1;
- shader->fetch_inputs(shader, indices, 2, 0);
+ shader->fetch_inputs(shader, indices, 2,
+ shader->fetched_prim_count);
++shader->in_prim_idx;
+ ++shader->fetched_prim_count;
- gs_flush(shader, 1);
+ gs_flush(shader);
}
static void gs_line_adj(struct draw_geometry_shader *shader,
@@ -252,10 +270,12 @@ static void gs_line_adj(struct draw_geometry_shader *shader,
indices[2] = i2;
indices[3] = i3;
- shader->fetch_inputs(shader, indices, 4, 0);
+ shader->fetch_inputs(shader, indices, 4,
+ shader->fetched_prim_count);
++shader->in_prim_idx;
+ ++shader->fetched_prim_count;
- gs_flush(shader, 1);
+ gs_flush(shader);
}
static void gs_tri(struct draw_geometry_shader *shader,
@@ -267,10 +287,12 @@ static void gs_tri(struct draw_geometry_shader *shader,
indices[1] = i1;
indices[2] = i2;
- shader->fetch_inputs(shader, indices, 3, 0);
+ shader->fetch_inputs(shader, indices, 3,
+ shader->fetched_prim_count);
++shader->in_prim_idx;
+ ++shader->fetched_prim_count;
- gs_flush(shader, 1);
+ gs_flush(shader);
}
static void gs_tri_adj(struct draw_geometry_shader *shader,
@@ -286,10 +308,12 @@ static void gs_tri_adj(struct draw_geometry_shader *shader,
indices[4] = i4;
indices[5] = i5;
- shader->fetch_inputs(shader, indices, 6, 0);
+ shader->fetch_inputs(shader, indices, 6,
+ shader->fetched_prim_count);
++shader->in_prim_idx;
+ ++shader->fetched_prim_count;
- gs_flush(shader, 1);
+ gs_flush(shader);
}
#define FUNC gs_run
@@ -354,6 +378,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
shader->vertex_size = vertex_size;
shader->tmp_output = (float (*)[4])output_verts->verts->data;
shader->in_prim_idx = 0;
+ shader->fetched_prim_count = 0;
shader->input_vertex_stride = input_stride;
shader->input = input;
shader->input_info = input_info;
@@ -369,6 +394,15 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
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);
+
/* Update prim_info:
*/
output_prims->linear = TRUE;
diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h
index b17a4485b16..7ab4f04a33d 100644
--- a/src/gallium/auxiliary/draw/draw_gs.h
+++ b/src/gallium/auxiliary/draw/draw_gs.h
@@ -63,6 +63,7 @@ struct draw_geometry_shader {
unsigned in_prim_idx;
unsigned input_vertex_stride;
+ unsigned fetched_prim_count;
const float (*input)[4];
const struct tgsi_shader_info *input_info;