draw: implement pipeline statistics in the draw module
authorZack Rusin <zackr@vmware.com>
Thu, 11 Apr 2013 13:11:29 +0000 (06:11 -0700)
committerZack Rusin <zackr@vmware.com>
Wed, 17 Apr 2013 06:38:47 +0000 (23:38 -0700)
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 <zackr@vmware.com>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
23 files changed:
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_context.h
src/gallium/auxiliary/draw/draw_gs.c
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt.c
src/gallium/auxiliary/draw/draw_pt_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
src/gallium/auxiliary/draw/draw_vbuf.h
src/gallium/auxiliary/util/u_prim.h
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_draw_arrays.c
src/gallium/drivers/llvmpipe/lp_query.c
src/gallium/drivers/llvmpipe/lp_query.h
src/gallium/drivers/llvmpipe/lp_rast.c
src/gallium/drivers/llvmpipe/lp_setup_vbuf.c
src/gallium/drivers/softpipe/sp_context.h
src/gallium/drivers/softpipe/sp_draw_arrays.c
src/gallium/drivers/softpipe/sp_prim_vbuf.c
src/gallium/drivers/softpipe/sp_quad_fs.c
src/gallium/drivers/softpipe/sp_query.c
src/gallium/drivers/softpipe/sp_screen.c
src/gallium/drivers/softpipe/sp_setup.c

index 2fb9bacf4c6765fb1cd9630818101225f6559d0e..0f98021247ab799719dca79752710cd6875ff341 100644 (file)
@@ -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;
+}
index 1d25b7f255e07f2723b6b2d2d0dd1c21801c683e..94fac880c68c8975d0d7fbfab1891aebb9171672 100644 (file)
@@ -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 
  */
index d95a4c5705bb236feb8326c4f000380a39fae8cf..f8cb04a8f39e70637e7976b0240b9095f1bf8620 100644 (file)
@@ -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,
index 757ed2645efe8a125b3cffb8651694c863de0a67..d6a3e7c2cee8e6bf84d84c87c0807b954646c846 100644 (file)
@@ -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;
 };
 
index 853bd6716e635e4c90d8e280921a1e7892b2fefd..10f32fd929f0a5d2921a6bb6f37430285b90ebdb 100644 (file)
@@ -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);
+   }
 }
index 942ddc4d7bc9278c427230ed65250d7c03b1079c..b3d3546402dde0f08c31bc31c4b9a34014a9b5d7 100644 (file)
@@ -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;
index 72d391257aa5ffdf5f0dc6c6d21a6b90f0690853..e17f16147b26b55d3bf5ac42abbfafe16fe28354 100644 (file)
@@ -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.
     */
index ec0f758d45341bd90e0d467685bf28439fe8af1b..d312dc482896e55d352bf1583fdca5add472a92c 100644 (file)
@@ -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,
index f10d185868d0bb1a7b1906f713a5408246e9f7c8..bf1c73cad5f1c62ee4fd26395d6d6d266c1b1a5f 100644 (file)
@@ -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 );
 };
 
 
index d62c636f2eec27249fcb6f2f8d7e0da2f55be3c0..99bb66c9b8974e0686d59ce829e691385b9de4dd 100644 (file)
@@ -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;
    }
 }
 
index 6ee7b99f478dc516a9c8c82e0ce43ab392aaabfa..d605dba2260c76992c676b96884f97f2a1f6d88a 100644 (file)
@@ -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;
index efeca255755a231428948ca2bfe30789195c4af6..e8a5880deef6fd330ce7fde3cfdfabc5ecaaa3b9 100644 (file)
@@ -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);
index 013d1928c11f4a347c5b2d96620fa752ea5d553f..96e1e3ff1f395e31de891f32699dbe312e955b89 100644 (file)
@@ -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;
index 19d977fd2e446f5b077d698e12f9bf1d508dab7f..68dfe99f42835d3da5431988153fe11ed0fd3920 100644 (file)
@@ -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;
 };
 
 
index 6cb27020566d744ed09ad144e08259a543b7f093..29dd933c64476a9ec89814750db0e9f05dd94524 100644 (file)
@@ -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);
index 9e0a5b399549985df5d2ef12e1243bb73032d4ef..8173994e5c1e31e4f7fa55a6df1143d734c0edff 100644 (file)
@@ -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;
 }
index d78352ab630481306841215c00ef71917f775abe..431864ae087e1b4cc3335adb9e5f7d7bbedc54e5 100644 (file)
@@ -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];
 
index ba9e7817cebad05d716370f6d5363e0949675fa3..4378312bc3622ca0138a5415ae6b4192efb979c4 100644 (file)
@@ -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);
 
index bb5ebcc7aee570e07e40569c31b2605e72e39779..5d0b5e1c5883f0f225b35de8e342d06357a4378f 100644 (file)
@@ -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;
index f32fe5f40686ab9c05554594f7e6395bf4539f44..d379f6457e3d8eaea4924c39a2bcf6c52f9edd4a 100644 (file)
@@ -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 );
index 2dd82c81d6fd76ebedb575c3b14cdc607e28c19f..62411de5036de0f22fa1271bf1ce6f8f4cbaf12e 100644 (file)
@@ -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;
index 6915f9180070c7e9a172945bbf1c03332dd12a98..b2b7f2e32087b056c511c4ff60b96ddfd508a33a 100644 (file)
@@ -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:
index 3dad131d88180f2c582f561d57ad380480f64f3b..08cd4da5bd0a5f0dbdef96217779bb9acbb24e14 100644 (file)
@@ -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,