It is easy enough to pre-determine the required size, and arrays are generally better behaved especially when they get large.
v2: make sure init_perf_monitor returns true when no counters are active (spotted by Samuel Pitoiset) Reviewed-by: Samuel Pitoiset <samuel.pitoi...@gmail.com> --- src/mesa/state_tracker/st_cb_perfmon.c | 81 ++++++++++++++++++++-------------- src/mesa/state_tracker/st_cb_perfmon.h | 18 ++++---- 2 files changed, 58 insertions(+), 41 deletions(-) diff --git a/src/mesa/state_tracker/st_cb_perfmon.c b/src/mesa/state_tracker/st_cb_perfmon.c index ec12eb2..8628e23 100644 --- a/src/mesa/state_tracker/st_cb_perfmon.c +++ b/src/mesa/state_tracker/st_cb_perfmon.c @@ -42,15 +42,14 @@ 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_context *pipe = st->pipe; + unsigned num_active_counters = 0; int gid, cid; st_flush_bitmap_cache(st); - /* Create a query for each active counter. */ + /* Determine the number of active counters. */ 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]; - BITSET_WORD tmp; if (m->ActiveGroups[gid] > g->MaxActiveCounters) { /* Maximum number of counters reached. Cannot start the session. */ @@ -61,19 +60,32 @@ init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) return false; } + num_active_counters += m->ActiveGroups[gid]; + } + + if (!num_active_counters) + return true; + + stm->active_counters = CALLOC(num_active_counters, + sizeof(*stm->active_counters)); + if (!stm->active_counters) + return false; + + /* 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]; + BITSET_WORD tmp; + BITSET_FOREACH_SET(cid, tmp, m->ActiveCounters[gid], g->NumCounters) { const struct st_perf_monitor_counter *stc = &stg->counters[cid]; - struct st_perf_counter_object *cntr; - - cntr = CALLOC_STRUCT(st_perf_counter_object); - if (!cntr) - return false; + struct st_perf_counter_object *cntr = + &stm->active_counters[stm->num_active_counters]; cntr->query = pipe->create_query(pipe, stc->query_type, 0); cntr->id = cid; cntr->group_id = gid; - - list_addtail(&cntr->list, &stm->active_counters); + ++stm->num_active_counters; } } return true; @@ -83,24 +95,24 @@ static void reset_perf_monitor(struct st_perf_monitor_object *stm, struct pipe_context *pipe) { - struct st_perf_counter_object *cntr, *tmp; + unsigned i; - LIST_FOR_EACH_ENTRY_SAFE(cntr, tmp, &stm->active_counters, list) { - if (cntr->query) - pipe->destroy_query(pipe, cntr->query); - list_del(&cntr->list); - free(cntr); + for (i = 0; i < stm->num_active_counters; ++i) { + struct pipe_query *query = stm->active_counters[i].query; + if (query) + pipe->destroy_query(pipe, query); } + FREE(stm->active_counters); + stm->active_counters = NULL; + stm->num_active_counters = 0; } static struct gl_perf_monitor_object * st_NewPerfMonitor(struct gl_context *ctx) { struct st_perf_monitor_object *stq = ST_CALLOC_STRUCT(st_perf_monitor_object); - if (stq) { - list_inithead(&stq->active_counters); + if (stq) return &stq->base; - } return NULL; } @@ -119,9 +131,9 @@ st_BeginPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) { struct st_perf_monitor_object *stm = st_perf_monitor_object(m); struct pipe_context *pipe = st_context(ctx)->pipe; - struct st_perf_counter_object *cntr; + unsigned i; - if (LIST_IS_EMPTY(&stm->active_counters)) { + if (!stm->num_active_counters) { /* Create a query for each active counter before starting * a new monitoring session. */ if (!init_perf_monitor(ctx, m)) @@ -129,8 +141,9 @@ st_BeginPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) } /* Start the query for each active counter. */ - LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) { - if (!pipe->begin_query(pipe, cntr->query)) + for (i = 0; i < stm->num_active_counters; ++i) { + struct pipe_query *query = stm->active_counters[i].query; + if (!pipe->begin_query(pipe, query)) goto fail; } return true; @@ -146,11 +159,13 @@ st_EndPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) { struct st_perf_monitor_object *stm = st_perf_monitor_object(m); struct pipe_context *pipe = st_context(ctx)->pipe; - struct st_perf_counter_object *cntr; + unsigned i; /* Stop the query for each active counter. */ - LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) - pipe->end_query(pipe, cntr->query); + for (i = 0; i < stm->num_active_counters; ++i) { + struct pipe_query *query = stm->active_counters[i].query; + pipe->end_query(pipe, query); + } } static void @@ -174,16 +189,17 @@ st_IsPerfMonitorResultAvailable(struct gl_context *ctx, { struct st_perf_monitor_object *stm = st_perf_monitor_object(m); struct pipe_context *pipe = st_context(ctx)->pipe; - struct st_perf_counter_object *cntr; + unsigned i; - if (LIST_IS_EMPTY(&stm->active_counters)) + if (!stm->num_active_counters) return false; /* The result of a monitoring session is only available if the query of * each active counter is idle. */ - LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) { + for (i = 0; i < stm->num_active_counters; ++i) { + struct pipe_query *query = stm->active_counters[i].query; union pipe_query_result result; - if (!pipe->get_query_result(pipe, cntr->query, FALSE, &result)) { + if (!pipe->get_query_result(pipe, query, FALSE, &result)) { /* The query is busy. */ return false; } @@ -200,7 +216,7 @@ st_GetPerfMonitorResult(struct gl_context *ctx, { struct st_perf_monitor_object *stm = st_perf_monitor_object(m); struct pipe_context *pipe = st_context(ctx)->pipe; - struct st_perf_counter_object *cntr; + unsigned i; /* Copy data to the supplied array (data). * @@ -210,7 +226,8 @@ st_GetPerfMonitorResult(struct gl_context *ctx, GLsizei offset = 0; /* Read query results for each active counter. */ - LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) { + for (i = 0; i < stm->num_active_counters; ++i) { + struct st_perf_counter_object *cntr = &stm->active_counters[i]; union pipe_query_result result = { 0 }; int gid, cid; GLenum type; diff --git a/src/mesa/state_tracker/st_cb_perfmon.h b/src/mesa/state_tracker/st_cb_perfmon.h index 9864b0a..79e0421 100644 --- a/src/mesa/state_tracker/st_cb_perfmon.h +++ b/src/mesa/state_tracker/st_cb_perfmon.h @@ -26,21 +26,21 @@ #include "util/list.h" +struct st_perf_counter_object +{ + struct pipe_query *query; + int id; + int group_id; +}; + /** * Subclass of gl_perf_monitor_object */ struct st_perf_monitor_object { struct gl_perf_monitor_object base; - struct list_head active_counters; -}; - -struct st_perf_counter_object -{ - struct list_head list; - struct pipe_query *query; - int id; - int group_id; + unsigned num_active_counters; + struct st_perf_counter_object *active_counters; }; /** -- 2.5.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev