diff options
Diffstat (limited to 'src/gallium')
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, |