summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_draw_arrays.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.c37
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_vbuf.c23
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h3
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c3
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_vbuf.c23
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_fs.c5
-rw-r--r--src/gallium/drivers/softpipe/sp_query.c39
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_setup.c4
23 files changed, 258 insertions, 22 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;
}
}
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index 6ee7b99f478..d605dba2260 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -94,6 +94,9 @@ struct llvmpipe_context {
struct pipe_query_data_so_statistics so_stats;
unsigned num_primitives_generated;
+ struct pipe_query_data_pipeline_statistics pipeline_statistics;
+ unsigned active_statistics_queries;
+
unsigned dirty; /**< Mask of LP_NEW_x flags */
unsigned active_occlusion_query;
diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
index efeca255755..e8a5880deef 100644
--- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
+++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
@@ -108,6 +108,8 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
draw_vs_attach_so(lp->vs->draw_data, &lp->gs->shader.stream_output);
}
}
+ draw_collect_pipeline_statistics(draw,
+ lp->active_statistics_queries > 0);
/* draw! */
draw_vbo(draw, info);
diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c
index 013d1928c11..96e1e3ff1f3 100644
--- a/src/gallium/drivers/llvmpipe/lp_query.c
+++ b/src/gallium/drivers/llvmpipe/lp_query.c
@@ -144,6 +144,12 @@ llvmpipe_get_query_result(struct pipe_context *pipe,
stats->primitives_storage_needed = pq->num_primitives_generated;
}
break;
+ case PIPE_QUERY_PIPELINE_STATISTICS: {
+ struct pipe_query_data_pipeline_statistics *stats =
+ (struct pipe_query_data_pipeline_statistics *)vresult;
+ *stats = pq->stats;
+ }
+ break;
default:
assert(0);
break;
@@ -188,6 +194,16 @@ llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
llvmpipe->num_primitives_generated = 0;
}
+ if (pq->type == PIPE_QUERY_PIPELINE_STATISTICS) {
+ /* reset our cache */
+ if (llvmpipe->active_statistics_queries == 0) {
+ memset(&llvmpipe->pipeline_statistics, 0,
+ sizeof(llvmpipe->pipeline_statistics));
+ }
+ memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats));
+ llvmpipe->active_statistics_queries++;
+ }
+
if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER) {
llvmpipe->active_occlusion_query = TRUE;
llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
@@ -216,6 +232,27 @@ llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
pq->num_primitives_generated = llvmpipe->num_primitives_generated;
}
+ if (pq->type == PIPE_QUERY_PIPELINE_STATISTICS) {
+ pq->stats.ia_vertices =
+ llvmpipe->pipeline_statistics.ia_vertices - pq->stats.ia_vertices;
+ pq->stats.ia_primitives =
+ llvmpipe->pipeline_statistics.ia_primitives - pq->stats.ia_primitives;
+ pq->stats.vs_invocations =
+ llvmpipe->pipeline_statistics.vs_invocations - pq->stats.vs_invocations;
+ pq->stats.gs_invocations =
+ llvmpipe->pipeline_statistics.gs_invocations - pq->stats.gs_invocations;
+ pq->stats.gs_primitives =
+ llvmpipe->pipeline_statistics.gs_primitives - pq->stats.gs_primitives;
+ pq->stats.c_invocations =
+ llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations;
+ pq->stats.c_primitives =
+ llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives;
+ pq->stats.ps_invocations =
+ llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations;
+
+ llvmpipe->active_statistics_queries--;
+ }
+
if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER) {
assert(llvmpipe->active_occlusion_query);
llvmpipe->active_occlusion_query = FALSE;
diff --git a/src/gallium/drivers/llvmpipe/lp_query.h b/src/gallium/drivers/llvmpipe/lp_query.h
index 19d977fd2e4..68dfe99f428 100644
--- a/src/gallium/drivers/llvmpipe/lp_query.h
+++ b/src/gallium/drivers/llvmpipe/lp_query.h
@@ -47,6 +47,8 @@ struct llvmpipe_query {
unsigned type; /* PIPE_QUERY_* */
unsigned num_primitives_generated;
unsigned num_primitives_written;
+
+ struct pipe_query_data_pipeline_statistics stats;
};
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 6cb27020566..29dd933c644 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -477,6 +477,7 @@ lp_rast_begin_query(struct lp_rasterizer_task *task,
case PIPE_QUERY_PRIMITIVES_GENERATED:
case PIPE_QUERY_PRIMITIVES_EMITTED:
case PIPE_QUERY_SO_STATISTICS:
+ case PIPE_QUERY_PIPELINE_STATISTICS:
break;
default:
assert(0);
@@ -509,6 +510,7 @@ lp_rast_end_query(struct lp_rasterizer_task *task,
case PIPE_QUERY_PRIMITIVES_GENERATED:
case PIPE_QUERY_PRIMITIVES_EMITTED:
case PIPE_QUERY_SO_STATISTICS:
+ case PIPE_QUERY_PIPELINE_STATISTICS:
break;
default:
assert(0);
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c
index 9e0a5b39954..8173994e5c1 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c
@@ -547,6 +547,28 @@ lp_setup_so_info(struct vbuf_render *vbr, uint primitives, uint vertices,
lp->num_primitives_generated += prim_generated;
}
+static void
+lp_setup_pipeline_statistics(
+ struct vbuf_render *vbr,
+ const struct pipe_query_data_pipeline_statistics *stats)
+{
+ struct lp_setup_context *setup = lp_setup_context(vbr);
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(setup->pipe);
+
+ llvmpipe->pipeline_statistics.ia_vertices +=
+ stats->ia_vertices;
+ llvmpipe->pipeline_statistics.ia_primitives +=
+ stats->ia_primitives;
+ llvmpipe->pipeline_statistics.vs_invocations +=
+ stats->vs_invocations;
+ llvmpipe->pipeline_statistics.gs_invocations +=
+ stats->gs_invocations;
+ llvmpipe->pipeline_statistics.gs_primitives +=
+ stats->gs_primitives;
+ llvmpipe->pipeline_statistics.c_invocations +=
+ stats->c_invocations;
+}
+
/**
* Create the post-transform vertex handler for the given context.
*/
@@ -566,4 +588,5 @@ lp_setup_init_vbuf(struct lp_setup_context *setup)
setup->base.release_vertices = lp_setup_release_vertices;
setup->base.destroy = lp_setup_vbuf_destroy;
setup->base.set_stream_output_info = lp_setup_so_info;
+ setup->base.pipeline_statistics = lp_setup_pipeline_statistics;
}
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index d78352ab630..431864ae087 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -92,6 +92,9 @@ struct softpipe_context {
struct pipe_query_data_so_statistics so_stats;
unsigned num_primitives_generated;
+ struct pipe_query_data_pipeline_statistics pipeline_statistics;
+ unsigned active_statistics_queries;
+
unsigned num_samplers[PIPE_SHADER_TYPES];
unsigned num_sampler_views[PIPE_SHADER_TYPES];
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
index ba9e7817ceb..4378312bc36 100644
--- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -105,6 +105,9 @@ softpipe_draw_vbo(struct pipe_context *pipe,
draw_set_mapped_so_targets(draw, sp->num_so_targets,
sp->so_targets);
+ draw_collect_pipeline_statistics(draw,
+ sp->active_statistics_queries > 0);
+
/* draw! */
draw_vbo(draw, info);
diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
index bb5ebcc7aee..5d0b5e1c588 100644
--- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c
+++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
@@ -600,6 +600,28 @@ sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices,
softpipe->num_primitives_generated += prim_generated;
}
+static void
+sp_vbuf_pipeline_statistics(
+ struct vbuf_render *vbr,
+ const struct pipe_query_data_pipeline_statistics *stats)
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ struct softpipe_context *softpipe = cvbr->softpipe;
+
+ softpipe->pipeline_statistics.ia_vertices +=
+ stats->ia_vertices;
+ softpipe->pipeline_statistics.ia_primitives +=
+ stats->ia_primitives;
+ softpipe->pipeline_statistics.vs_invocations +=
+ stats->vs_invocations;
+ softpipe->pipeline_statistics.gs_invocations +=
+ stats->gs_invocations;
+ softpipe->pipeline_statistics.gs_primitives +=
+ stats->gs_primitives;
+ softpipe->pipeline_statistics.c_invocations +=
+ stats->c_invocations;
+}
+
static void
sp_vbuf_destroy(struct vbuf_render *vbr)
@@ -634,6 +656,7 @@ sp_create_vbuf_backend(struct softpipe_context *sp)
cvbr->base.draw_arrays = sp_vbuf_draw_arrays;
cvbr->base.release_vertices = sp_vbuf_release_vertices;
cvbr->base.set_stream_output_info = sp_vbuf_so_info;
+ cvbr->base.pipeline_statistics = sp_vbuf_pipeline_statistics;
cvbr->base.destroy = sp_vbuf_destroy;
cvbr->softpipe = sp;
diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c
index f32fe5f4068..d379f6457e3 100644
--- a/src/gallium/drivers/softpipe/sp_quad_fs.c
+++ b/src/gallium/drivers/softpipe/sp_quad_fs.c
@@ -73,6 +73,11 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad)
struct softpipe_context *softpipe = qs->softpipe;
struct tgsi_exec_machine *machine = softpipe->fs_machine;
+ if (softpipe->active_statistics_queries) {
+ softpipe->pipeline_statistics.ps_invocations +=
+ util_bitcount(quad->inout.mask);
+ }
+
/* run shader */
machine->flatshade_color = softpipe->rasterizer->flatshade ? TRUE : FALSE;
return softpipe->fs_variant->run( softpipe->fs_variant, machine, quad );
diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c
index 2dd82c81d6f..62411de5036 100644
--- a/src/gallium/drivers/softpipe/sp_query.c
+++ b/src/gallium/drivers/softpipe/sp_query.c
@@ -43,6 +43,8 @@ struct softpipe_query {
uint64_t end;
struct pipe_query_data_so_statistics so;
unsigned num_primitives_generated;
+
+ struct pipe_query_data_pipeline_statistics stats;
};
@@ -61,7 +63,8 @@ softpipe_create_query(struct pipe_context *pipe,
type == PIPE_QUERY_TIME_ELAPSED ||
type == PIPE_QUERY_SO_STATISTICS ||
type == PIPE_QUERY_PRIMITIVES_EMITTED ||
- type == PIPE_QUERY_PRIMITIVES_GENERATED ||
+ type == PIPE_QUERY_PRIMITIVES_GENERATED ||
+ type == PIPE_QUERY_PIPELINE_STATISTICS ||
type == PIPE_QUERY_GPU_FINISHED ||
type == PIPE_QUERY_TIMESTAMP ||
type == PIPE_QUERY_TIMESTAMP_DISJOINT);
@@ -106,6 +109,16 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
case PIPE_QUERY_TIMESTAMP:
case PIPE_QUERY_GPU_FINISHED:
break;
+ case PIPE_QUERY_PIPELINE_STATISTICS:
+ /* reset our cache */
+ if (softpipe->active_statistics_queries == 0) {
+ memset(&softpipe->pipeline_statistics, 0,
+ sizeof(softpipe->pipeline_statistics));
+ }
+ memcpy(&sq->stats, &softpipe->pipeline_statistics,
+ sizeof(sq->stats));
+ softpipe->active_statistics_queries++;
+ break;
default:
assert(0);
break;
@@ -145,6 +158,26 @@ softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
break;
case PIPE_QUERY_GPU_FINISHED:
break;
+ case PIPE_QUERY_PIPELINE_STATISTICS:
+ sq->stats.ia_vertices =
+ softpipe->pipeline_statistics.ia_vertices - sq->stats.ia_vertices;
+ sq->stats.ia_primitives =
+ softpipe->pipeline_statistics.ia_primitives - sq->stats.ia_primitives;
+ sq->stats.vs_invocations =
+ softpipe->pipeline_statistics.vs_invocations - sq->stats.vs_invocations;
+ sq->stats.gs_invocations =
+ softpipe->pipeline_statistics.gs_invocations - sq->stats.gs_invocations;
+ sq->stats.gs_primitives =
+ softpipe->pipeline_statistics.gs_primitives - sq->stats.gs_primitives;
+ sq->stats.c_invocations =
+ softpipe->pipeline_statistics.c_invocations - sq->stats.c_invocations;
+ sq->stats.c_primitives =
+ softpipe->pipeline_statistics.c_primitives - sq->stats.c_primitives;
+ sq->stats.ps_invocations =
+ softpipe->pipeline_statistics.ps_invocations - sq->stats.ps_invocations;
+
+ softpipe->active_statistics_queries--;
+ break;
default:
assert(0);
break;
@@ -167,6 +200,10 @@ softpipe_get_query_result(struct pipe_context *pipe,
memcpy(vresult, &sq->so,
sizeof(struct pipe_query_data_so_statistics));
break;
+ case PIPE_QUERY_PIPELINE_STATISTICS:
+ memcpy(vresult, &sq->stats,
+ sizeof(struct pipe_query_data_pipeline_statistics));;
+ break;
case PIPE_QUERY_GPU_FINISHED:
*result = TRUE;
break;
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 6915f918007..b2b7f2e3208 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -87,7 +87,7 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_QUERY_TIME_ELAPSED:
return 1;
case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
- return 0;
+ return 1;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
return 1;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c
index 3dad131d881..08cd4da5bd0 100644
--- a/src/gallium/drivers/softpipe/sp_setup.c
+++ b/src/gallium/drivers/softpipe/sp_setup.c
@@ -857,6 +857,10 @@ sp_setup_tri(struct setup_context *setup,
flush_spans( setup );
+ if (setup->softpipe->active_statistics_queries) {
+ setup->softpipe->pipeline_statistics.c_primitives++;
+ }
+
#if DEBUG_FRAGS
printf("Tri: %u frags emitted, %u written\n",
setup->numFragsEmitted,