summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2013-04-11 06:11:29 -0700
committerZack Rusin <[email protected]>2013-04-16 23:38:47 -0700
commit80ee4a407a2668f6a6a410c3e56ae9910510f773 (patch)
treefef704d3c130eb615a0e9f4d9631288d45513749 /src/gallium/auxiliary
parentb739376cffec19870804b1ebd4bef3c2f654e943 (diff)
draw: implement pipeline statistics in the draw module
This is a basic implementation of the pipeline statistics in the draw module. The interface is similar to the stream output statistics and also requires that the callers explicitly enable it. Included is the implementation of the interface in llvmpipe and softpipe. Only softpipe enables the pipeline statistics capability though because llvmpipe is lacking gathering of the fragment shading and rasterization statistics. Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: Jose Fonseca <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c16
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h7
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.c24
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h3
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c11
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_emit.c15
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c7
-rw-r--r--src/gallium/auxiliary/draw/draw_vbuf.h8
-rw-r--r--src/gallium/auxiliary/util/u_prim.h35
10 files changed, 112 insertions, 20 deletions
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 2fb9bacf4c6..0f98021247a 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -842,3 +842,19 @@ draw_get_shader_param(unsigned shader, enum pipe_shader_cap param)
return draw_get_shader_param_no_llvm(shader, param);
}
+/**
+ * Enables or disables collection of statistics.
+ *
+ * Draw module is capable of generating statistics for the vertex
+ * processing pipeline. Collection of that data isn't free and so
+ * it's disabled by default. The users of the module can enable
+ * (or disable) this functionality through this function.
+ * The actual data will be emitted through the VBUF interface,
+ * the 'pipeline_statistics' callback to be exact.
+ */
+void
+draw_collect_pipeline_statistics(struct draw_context *draw,
+ boolean enable)
+{
+ draw->collect_statistics = enable;
+}
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index 1d25b7f255e..94fac880c68 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -264,6 +264,13 @@ void draw_set_driver_clipping( struct draw_context *draw,
void draw_set_force_passthrough( struct draw_context *draw,
boolean enable );
+
+/*******************************************************************************
+ * Draw statistics
+ */
+void draw_collect_pipeline_statistics(struct draw_context *draw,
+ boolean enable);
+
/*******************************************************************************
* Draw pipeline
*/
diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
index d95a4c5705b..f8cb04a8f39 100644
--- a/src/gallium/auxiliary/draw/draw_gs.c
+++ b/src/gallium/auxiliary/draw/draw_gs.c
@@ -353,6 +353,10 @@ static void gs_flush(struct draw_geometry_shader *shader)
unsigned input_primitives = shader->fetched_prim_count;
+ if (shader->draw->collect_statistics) {
+ shader->draw->statistics.gs_invocations += input_primitives;
+ }
+
debug_assert(input_primitives > 0 &&
input_primitives <= 4);
@@ -493,11 +497,14 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
input_prim->count;
unsigned num_in_primitives =
align(
- MAX2(u_gs_prims_for_vertices(input_prim->prim, num_input_verts),
- u_gs_prims_for_vertices(shader->input_primitive, num_input_verts)),
+ MAX2(u_decomposed_prims_for_vertices(input_prim->prim,
+ num_input_verts),
+ u_decomposed_prims_for_vertices(shader->input_primitive,
+ num_input_verts)),
shader->vector_length);
- unsigned max_out_prims = u_gs_prims_for_vertices(shader->output_primitive,
- shader->max_output_vertices)
+ unsigned max_out_prims =
+ u_decomposed_prims_for_vertices(shader->output_primitive,
+ shader->max_output_vertices)
* num_in_primitives;
//Assume at least one primitive
@@ -593,6 +600,15 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
output_prims->primitive_count = shader->emitted_primitives;
output_verts->count = shader->emitted_vertices;
+ if (shader->draw->collect_statistics) {
+ unsigned i;
+ for (i = 0; i < shader->emitted_primitives; ++i) {
+ shader->draw->statistics.gs_primitives +=
+ u_decomposed_prims_for_vertices(shader->output_primitive,
+ shader->primitive_lengths[i]);
+ }
+ }
+
#if 0
debug_printf("GS finished, prims = %d, verts = %d\n",
output_prims->primitive_count,
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 757ed2645ef..d6a3e7c2cee 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -312,6 +312,9 @@ struct draw_context
const struct pipe_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
unsigned num_samplers[PIPE_SHADER_TYPES];
+ struct pipe_query_data_pipeline_statistics statistics;
+ boolean collect_statistics;
+
void *driver_private;
};
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 853bd6716e6..10f32fd929f 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -34,6 +34,7 @@
#include "draw/draw_gs.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
+#include "draw/draw_vbuf.h"
#include "draw/draw_vs.h"
#include "tgsi/tgsi_dump.h"
#include "util/u_math.h"
@@ -545,6 +546,11 @@ draw_vbo(struct draw_context *draw,
return;
}
+ /* If we're collecting stats then make sure we start from scratch */
+ if (draw->collect_statistics) {
+ memset(&draw->statistics, 0, sizeof(draw->statistics));
+ }
+
draw->pt.max_index = index_limit - 1;
/*
@@ -562,4 +568,9 @@ draw_vbo(struct draw_context *draw,
draw_pt_arrays(draw, info->mode, info->start, count);
}
}
+
+ /* If requested emit the pipeline statistics for this run */
+ if (draw->collect_statistics) {
+ draw->render->pipeline_statistics(draw->render, &draw->statistics);
+ }
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
index 942ddc4d7bc..b3d3546402d 100644
--- a/src/gallium/auxiliary/draw/draw_pt_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -33,6 +33,7 @@
#include "draw/draw_pt.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
+#include "util/u_prim.h"
struct pt_emit {
struct draw_context *draw;
@@ -179,6 +180,12 @@ draw_pt_emit(struct pt_emit *emit,
i < prim_info->primitive_count;
start += prim_info->primitive_lengths[i], i++)
{
+ if (draw->collect_statistics) {
+ draw->statistics.c_invocations +=
+ u_decomposed_prims_for_vertices(prim_info->prim,
+ prim_info->primitive_lengths[i]);
+ }
+
render->draw_elements(render,
elts + start,
prim_info->primitive_lengths[i]);
@@ -252,11 +259,17 @@ draw_pt_emit_linear(struct pt_emit *emit,
i < prim_info->primitive_count;
start += prim_info->primitive_lengths[i], i++)
{
+ if (draw->collect_statistics) {
+ draw->statistics.c_invocations +=
+ u_decomposed_prims_for_vertices(prim_info->prim,
+ prim_info->primitive_lengths[i]);
+ }
+
render->draw_arrays(render,
start,
prim_info->primitive_lengths[i]);
}
-
+
render->release_vertices(render);
return;
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index 72d391257aa..e17f16147b2 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -240,6 +240,12 @@ static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
assert(0);
return;
}
+ if (draw->collect_statistics) {
+ draw->statistics.ia_vertices += fetch_info->count;
+ draw->statistics.ia_primitives +=
+ u_decomposed_prims_for_vertices(prim_info->prim, fetch_info->count);
+ draw->statistics.vs_invocations += fetch_info->count;
+ }
/* Fetch into our vertex buffer.
*/
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
index ec0f758d453..d312dc48289 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
@@ -27,6 +27,7 @@
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_prim.h"
#include "draw/draw_context.h"
#include "draw/draw_gs.h"
#include "draw/draw_vbuf.h"
@@ -333,6 +334,12 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
assert(0);
return;
}
+ if (draw->collect_statistics) {
+ draw->statistics.ia_vertices += fetch_info->count;
+ draw->statistics.ia_primitives +=
+ u_decomposed_prims_for_vertices(prim_info->prim, fetch_info->count);
+ draw->statistics.vs_invocations += fetch_info->count;
+ }
if (fetch_info->linear)
clipped = fpme->current_variant->jit_func( &fpme->llvm->jit_context,
diff --git a/src/gallium/auxiliary/draw/draw_vbuf.h b/src/gallium/auxiliary/draw/draw_vbuf.h
index f10d185868d..bf1c73cad5f 100644
--- a/src/gallium/auxiliary/draw/draw_vbuf.h
+++ b/src/gallium/auxiliary/draw/draw_vbuf.h
@@ -43,6 +43,7 @@
struct pipe_rasterizer_state;
struct draw_context;
struct vertex_info;
+struct pipe_query_data_pipeline_statistics;
/**
@@ -126,6 +127,13 @@ struct vbuf_render {
unsigned primitive_count,
unsigned vertices_count,
unsigned primitive_generated );
+
+ /**
+ * Called after all relevant statistics have been accumulated.
+ */
+ void (*pipeline_statistics)(
+ struct vbuf_render *vbufr,
+ const struct pipe_query_data_pipeline_statistics *stats );
};
diff --git a/src/gallium/auxiliary/util/u_prim.h b/src/gallium/auxiliary/util/u_prim.h
index d62c636f2ee..99bb66c9b89 100644
--- a/src/gallium/auxiliary/util/u_prim.h
+++ b/src/gallium/auxiliary/util/u_prim.h
@@ -165,12 +165,14 @@ u_vertices_per_prim(int primitive)
/**
* Returns the number of decomposed primitives for the given
* vertex count.
- * Geometry shader is invoked once for each triangle in
+ * Parts of the pipline are invoked once for each triangle in
* triangle strip, triangle fans and triangles and once
- * for each line in line strip, line loop, lines.
+ * for each line in line strip, line loop, lines. Also
+ * statistics depend on knowing the exact number of decomposed
+ * primitives for a set of vertices.
*/
static INLINE unsigned
-u_gs_prims_for_vertices(int primitive, int vertices)
+u_decomposed_prims_for_vertices(int primitive, int vertices)
{
switch(primitive) {
case PIPE_PRIM_POINTS:
@@ -180,31 +182,34 @@ u_gs_prims_for_vertices(int primitive, int vertices)
case PIPE_PRIM_LINE_LOOP:
return vertices;
case PIPE_PRIM_LINE_STRIP:
- return vertices - 1;
+ return (vertices > 1) ? vertices - 1 : 0;
case PIPE_PRIM_TRIANGLES:
return vertices / 3;
case PIPE_PRIM_TRIANGLE_STRIP:
- return vertices - 2;
+ return (vertices > 2) ? vertices - 2 : 0;
case PIPE_PRIM_TRIANGLE_FAN:
- return vertices - 2;
+ return (vertices > 2) ? vertices - 2 : 0;
case PIPE_PRIM_LINES_ADJACENCY:
return vertices / 2;
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
- return vertices - 1;
+ return (vertices > 1) ? vertices - 1 : 0;
case PIPE_PRIM_TRIANGLES_ADJACENCY:
return vertices / 3;
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
- return vertices - 2;
-
- /* following primitives should never be used
- * with geometry shaders abd their size is
- * undefined */
- case PIPE_PRIM_POLYGON:
+ return (vertices > 2) ? vertices - 2 : 0;
case PIPE_PRIM_QUADS:
+ return vertices / 4;
case PIPE_PRIM_QUAD_STRIP:
+ return (vertices > 4) ? (vertices - 2) / 2 : 0;
+ /* Polygons can't be decomposed
+ * because the number of their vertices isn't known so
+ * for them and whatever else we don't recognize just
+ * return 1 if the number of vertices is greater than
+ * 3 and zero otherwise */
+ case PIPE_PRIM_POLYGON:
default:
- debug_printf("Unrecognized geometry shader primitive");
- return 3;
+ debug_printf("Invalid decomposition primitive!\n");
+ return (vertices > 3) ? 1 : 0;
}
}