[Mesa-dev] [PATCH 4/9] st/mesa: store mapping from perfmon counter to query type

Samuel Pitoiset samuel.pitoiset at gmail.com
Fri Nov 13 09:34:41 PST 2015



On 11/13/2015 04:57 PM, Nicolai Hähnle wrote:
> Previously, when a performance monitor was initialized, an inner loop through
> all driver queries with string comparisons for each enabled performance
> monitor counter was used. This hurts when a driver exposes lots of queries.

When I wrote this code one year ago for the nvc0 driver, this wasn't a 
real issue because it didn't expose lots of queries.

Anyway, this looks like a good improvement. Thanks!

Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>


> ---
>   src/mesa/state_tracker/st_cb_perfmon.c | 74 +++++++++++++++-------------------
>   src/mesa/state_tracker/st_cb_perfmon.h | 14 +++++++
>   src/mesa/state_tracker/st_context.h    |  3 ++
>   3 files changed, 49 insertions(+), 42 deletions(-)
>
> diff --git a/src/mesa/state_tracker/st_cb_perfmon.c b/src/mesa/state_tracker/st_cb_perfmon.c
> index dedb8f5..80ff170 100644
> --- a/src/mesa/state_tracker/st_cb_perfmon.c
> +++ b/src/mesa/state_tracker/st_cb_perfmon.c
> @@ -36,48 +36,20 @@
>   #include "pipe/p_screen.h"
>   #include "util/u_memory.h"
>
> -/**
> - * Return a PIPE_QUERY_x type >= PIPE_QUERY_DRIVER_SPECIFIC, or -1 if
> - * the driver-specific query doesn't exist.
> - */
> -static int
> -find_query_type(struct pipe_screen *screen, const char *name)
> -{
> -   int num_queries;
> -   int type = -1;
> -   int i;
> -
> -   num_queries = screen->get_driver_query_info(screen, 0, NULL);
> -   if (!num_queries)
> -      return type;
> -
> -   for (i = 0; i < num_queries; i++) {
> -      struct pipe_driver_query_info info;
> -
> -      if (!screen->get_driver_query_info(screen, i, &info))
> -         continue;
> -
> -      if (!strncmp(info.name, name, strlen(name))) {
> -         type = info.query_type;
> -         break;
> -      }
> -   }
> -   return type;
> -}
> -
>   static bool
>   init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
>   {
> +   struct st_context *st = st_context(ctx);
>      struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
> -   struct pipe_screen *screen = st_context(ctx)->pipe->screen;
> -   struct pipe_context *pipe = st_context(ctx)->pipe;
> +   struct pipe_context *pipe = st->pipe;
>      int gid, cid;
>
> -   st_flush_bitmap_cache(st_context(ctx));
> +   st_flush_bitmap_cache(st);
>
>      /* Create a query for each active counter. */
>      for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) {
>         const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid];
> +      const struct st_perf_monitor_group *stg = &st->perfmon[gid];
>
>         if (m->ActiveGroups[gid] > g->MaxActiveCounters) {
>            /* Maximum number of counters reached. Cannot start the session. */
> @@ -90,20 +62,17 @@ init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
>
>         for (cid = 0; cid < g->NumCounters; cid++) {
>            const struct gl_perf_monitor_counter *c = &g->Counters[cid];
> +         const struct st_perf_monitor_counter *stc = &stg->counters[cid];
>            struct st_perf_counter_object *cntr;
> -         int query_type;
>
>            if (!BITSET_TEST(m->ActiveCounters[gid], cid))
>               continue;
>
> -         query_type = find_query_type(screen, c->Name);
> -         assert(query_type != -1);
> -
>            cntr = CALLOC_STRUCT(st_perf_counter_object);
>            if (!cntr)
>               return false;
>
> -         cntr->query    = pipe->create_query(pipe, query_type, 0);
> +         cntr->query    = pipe->create_query(pipe, stc->query_type, 0);
>            cntr->id       = cid;
>            cntr->group_id = gid;
>
> @@ -286,6 +255,7 @@ st_init_perfmon(struct st_context *st)
>      struct gl_perf_monitor_state *perfmon = &st->ctx->PerfMonitor;
>      struct pipe_screen *screen = st->pipe->screen;
>      struct gl_perf_monitor_group *groups = NULL;
> +   struct st_perf_monitor_group *stgroups = NULL;
>      int num_counters, num_groups;
>      int gid, cid;
>
> @@ -304,26 +274,36 @@ st_init_perfmon(struct st_context *st)
>      if (!groups)
>         return false;
>
> +   stgroups = CALLOC(num_groups, sizeof(*stgroups));
> +   if (!stgroups)
> +      goto fail_only_groups;
> +
>      for (gid = 0; gid < num_groups; gid++) {
>         struct gl_perf_monitor_group *g = &groups[perfmon->NumGroups];
>         struct pipe_driver_query_group_info group_info;
>         struct gl_perf_monitor_counter *counters = NULL;
> +      struct st_perf_monitor_counter *stcounters = NULL;
>
>         if (!screen->get_driver_query_group_info(screen, gid, &group_info))
>            continue;
>
>         g->Name = group_info.name;
>         g->MaxActiveCounters = group_info.max_active_queries;
> -      g->NumCounters = 0;
> -      g->Counters = NULL;
>
>         if (group_info.num_queries)
>            counters = CALLOC(group_info.num_queries, sizeof(*counters));
>         if (!counters)
>            goto fail;
> +      g->Counters = counters;
> +
> +      stcounters = CALLOC(group_info.num_queries, sizeof(*stcounters));
> +      if (!stcounters)
> +         goto fail;
> +      stgroups[perfmon->NumGroups].counters = stcounters;
>
>         for (cid = 0; cid < num_counters; cid++) {
>            struct gl_perf_monitor_counter *c = &counters[g->NumCounters];
> +         struct st_perf_monitor_counter *stc = &stcounters[g->NumCounters];
>            struct pipe_driver_query_info info;
>
>            if (!screen->get_driver_query_info(screen, cid, &info))
> @@ -359,18 +339,25 @@ st_init_perfmon(struct st_context *st)
>               default:
>                  unreachable("Invalid driver query type!");
>            }
> +
> +         stc->query_type = info.query_type;
> +
>            g->NumCounters++;
>         }
> -      g->Counters = counters;
>         perfmon->NumGroups++;
>      }
>      perfmon->Groups = groups;
> +   st->perfmon = stgroups;
>
>      return true;
>
>   fail:
> -   for (gid = 0; gid < num_groups; gid++)
> +   for (gid = 0; gid < num_groups; gid++) {
> +      FREE(stgroups[gid].counters);
>         FREE((void *)groups[gid].Counters);
> +   }
> +   FREE(stgroups);
> +fail_only_groups:
>      FREE(groups);
>      return false;
>   }
> @@ -381,8 +368,11 @@ st_destroy_perfmon(struct st_context *st)
>      struct gl_perf_monitor_state *perfmon = &st->ctx->PerfMonitor;
>      int gid;
>
> -   for (gid = 0; gid < perfmon->NumGroups; gid++)
> +   for (gid = 0; gid < perfmon->NumGroups; gid++) {
> +      FREE(st->perfmon[gid].counters);
>         FREE((void *)perfmon->Groups[gid].Counters);
> +   }
> +   FREE(st->perfmon);
>      FREE((void *)perfmon->Groups);
>   }
>
> diff --git a/src/mesa/state_tracker/st_cb_perfmon.h b/src/mesa/state_tracker/st_cb_perfmon.h
> index 0b195de..9864b0a 100644
> --- a/src/mesa/state_tracker/st_cb_perfmon.h
> +++ b/src/mesa/state_tracker/st_cb_perfmon.h
> @@ -44,6 +44,20 @@ struct st_perf_counter_object
>   };
>
>   /**
> + * Extra data per counter, supplementing gl_perf_monitor_counter with
> + * driver-specific information.
> + */
> +struct st_perf_monitor_counter
> +{
> +   unsigned query_type;
> +};
> +
> +struct st_perf_monitor_group
> +{
> +   struct st_perf_monitor_counter *counters;
> +};
> +
> +/**
>    * Cast wrapper
>    */
>   static inline struct st_perf_monitor_object *
> diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
> index c243f5c..60a9a4b 100644
> --- a/src/mesa/state_tracker/st_context.h
> +++ b/src/mesa/state_tracker/st_context.h
> @@ -46,6 +46,7 @@ struct draw_stage;
>   struct gen_mipmap_state;
>   struct st_context;
>   struct st_fragment_program;
> +struct st_perf_monitor_group;
>   struct u_upload_mgr;
>
>
> @@ -217,6 +218,8 @@ struct st_context
>      int32_t read_stamp;
>
>      struct st_config_options options;
> +
> +   struct st_perf_monitor_group *perfmon;
>   };
>
>
>

-- 
-Samuel


More information about the mesa-dev mailing list