st/mesa: fix reporting of float perf counters max value
[mesa.git] / src / mesa / state_tracker / st_cb_perfmon.c
index 8628e2301ff871840024f79b18a7cb3b407651bf..0f5aa371d6adb0b1ff65ab294d8aa8fe9f6741b2 100644 (file)
@@ -29,6 +29,7 @@
 #include "st_context.h"
 #include "st_cb_bitmap.h"
 #include "st_cb_perfmon.h"
+#include "st_util.h"
 
 #include "util/bitset.h"
 
@@ -42,7 +43,10 @@ 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 *batch = NULL;
    unsigned num_active_counters = 0;
+   unsigned max_batch_counters = 0;
+   unsigned num_batch_counters = 0;
    int gid, cid;
 
    st_flush_bitmap_cache(st);
@@ -50,6 +54,7 @@ init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
    /* 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];
 
       if (m->ActiveGroups[gid] > g->MaxActiveCounters) {
          /* Maximum number of counters reached. Cannot start the session. */
@@ -61,6 +66,8 @@ init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
       }
 
       num_active_counters += m->ActiveGroups[gid];
+      if (stg->has_batch)
+         max_batch_counters += m->ActiveGroups[gid];
    }
 
    if (!num_active_counters)
@@ -71,24 +78,51 @@ init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
    if (!stm->active_counters)
       return false;
 
+   if (max_batch_counters) {
+      batch = CALLOC(max_batch_counters, sizeof(*batch));
+      if (!batch)
+         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) {
+      BITSET_FOREACH_SET(cid, m->ActiveCounters[gid], g->NumCounters) {
          const struct st_perf_monitor_counter *stc = &stg->counters[cid];
          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;
+         if (stc->flags & PIPE_DRIVER_QUERY_FLAG_BATCH) {
+            cntr->batch_index = num_batch_counters;
+            batch[num_batch_counters++] = stc->query_type;
+         } else {
+            cntr->query = pipe->create_query(pipe, stc->query_type, 0);
+            if (!cntr->query)
+               goto fail;
+         }
          ++stm->num_active_counters;
       }
    }
+
+   /* Create the batch query. */
+   if (num_batch_counters) {
+      stm->batch_query = pipe->create_batch_query(pipe, num_batch_counters,
+                                                  batch);
+      stm->batch_result = CALLOC(num_batch_counters, sizeof(stm->batch_result->batch[0]));
+      if (!stm->batch_query || !stm->batch_result)
+         goto fail;
+   }
+
+   FREE(batch);
    return true;
+
+fail:
+   FREE(batch);
+   return false;
 }
 
 static void
@@ -105,6 +139,13 @@ reset_perf_monitor(struct st_perf_monitor_object *stm,
    FREE(stm->active_counters);
    stm->active_counters = NULL;
    stm->num_active_counters = 0;
+
+   if (stm->batch_query) {
+      pipe->destroy_query(pipe, stm->batch_query);
+      stm->batch_query = NULL;
+   }
+   FREE(stm->batch_result);
+   stm->batch_result = NULL;
 }
 
 static struct gl_perf_monitor_object *
@@ -143,9 +184,13 @@ st_BeginPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
    /* Start the query for each active counter. */
    for (i = 0; i < stm->num_active_counters; ++i) {
       struct pipe_query *query = stm->active_counters[i].query;
-      if (!pipe->begin_query(pipe, query))
+      if (query && !pipe->begin_query(pipe, query))
           goto fail;
    }
+
+   if (stm->batch_query && !pipe->begin_query(pipe, stm->batch_query))
+      goto fail;
+
    return true;
 
 fail:
@@ -164,8 +209,12 @@ st_EndPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
    /* Stop the query for each active counter. */
    for (i = 0; i < stm->num_active_counters; ++i) {
       struct pipe_query *query = stm->active_counters[i].query;
-      pipe->end_query(pipe, query);
+      if (query)
+         pipe->end_query(pipe, query);
    }
+
+   if (stm->batch_query)
+      pipe->end_query(pipe, stm->batch_query);
 }
 
 static void
@@ -199,11 +248,16 @@ st_IsPerfMonitorResultAvailable(struct gl_context *ctx,
    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, query, FALSE, &result)) {
+      if (query && !pipe->get_query_result(pipe, query, FALSE, &result)) {
          /* The query is busy. */
          return false;
       }
    }
+
+   if (stm->batch_query &&
+       !pipe->get_query_result(pipe, stm->batch_query, FALSE, stm->batch_result))
+      return false;
+
    return true;
 }
 
@@ -224,6 +278,11 @@ st_GetPerfMonitorResult(struct gl_context *ctx,
     * active counter. The API allows counters to appear in any order.
     */
    GLsizei offset = 0;
+   bool have_batch_query = false;
+
+   if (stm->batch_query)
+      have_batch_query = pipe->get_query_result(pipe, stm->batch_query, TRUE,
+                                                stm->batch_result);
 
    /* Read query results for each active counter. */
    for (i = 0; i < stm->num_active_counters; ++i) {
@@ -236,23 +295,29 @@ st_GetPerfMonitorResult(struct gl_context *ctx,
       gid  = cntr->group_id;
       type = ctx->PerfMonitor.Groups[gid].Counters[cid].Type;
 
-      if (!pipe->get_query_result(pipe, cntr->query, TRUE, &result))
-         continue;
+      if (cntr->query) {
+         if (!pipe->get_query_result(pipe, cntr->query, TRUE, &result))
+            continue;
+      } else {
+         if (!have_batch_query)
+            continue;
+         result.batch[0] = stm->batch_result->batch[cntr->batch_index];
+      }
 
       data[offset++] = gid;
       data[offset++] = cid;
       switch (type) {
       case GL_UNSIGNED_INT64_AMD:
-         *(uint64_t *)&data[offset] = result.u64;
+         memcpy(&data[offset], &result.u64, sizeof(uint64_t));
          offset += sizeof(uint64_t) / sizeof(GLuint);
          break;
       case GL_UNSIGNED_INT:
-         *(uint32_t *)&data[offset] = result.u32;
+         memcpy(&data[offset], &result.u32, sizeof(uint32_t));
          offset += sizeof(uint32_t) / sizeof(GLuint);
          break;
       case GL_FLOAT:
       case GL_PERCENTAGE_AMD:
-         *(GLfloat *)&data[offset] = result.f;
+         memcpy(&data[offset], &result.f, sizeof(GLfloat));
          offset += sizeof(GLfloat) / sizeof(GLuint);
          break;
       }
@@ -264,29 +329,35 @@ st_GetPerfMonitorResult(struct gl_context *ctx,
 
 
 bool
-st_init_perfmon(struct st_context *st)
+st_have_perfmon(struct st_context *st)
 {
-   struct gl_perf_monitor_state *perfmon = &st->ctx->PerfMonitor;
+   struct pipe_screen *screen = st->pipe->screen;
+
+   if (!screen->get_driver_query_info || !screen->get_driver_query_group_info)
+      return false;
+
+   return screen->get_driver_query_group_info(screen, 0, NULL) != 0;
+}
+
+static void
+st_InitPerfMonitorGroups(struct gl_context *ctx)
+{
+   struct st_context *st = st_context(ctx);
+   struct gl_perf_monitor_state *perfmon = &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;
 
-   if (!screen->get_driver_query_info || !screen->get_driver_query_group_info)
-      return false;
-
    /* Get the number of available queries. */
    num_counters = screen->get_driver_query_info(screen, 0, NULL);
-   if (!num_counters)
-      return false;
 
    /* Get the number of available groups. */
    num_groups = screen->get_driver_query_group_info(screen, 0, NULL);
-   if (num_groups)
-      groups = CALLOC(num_groups, sizeof(*groups));
+   groups = CALLOC(num_groups, sizeof(*groups));
    if (!groups)
-      return false;
+      return;
 
    stgroups = CALLOC(num_groups, sizeof(*stgroups));
    if (!stgroups)
@@ -294,6 +365,7 @@ st_init_perfmon(struct st_context *st)
 
    for (gid = 0; gid < num_groups; gid++) {
       struct gl_perf_monitor_group *g = &groups[perfmon->NumGroups];
+      struct st_perf_monitor_group *stg = &stgroups[perfmon->NumGroups];
       struct pipe_driver_query_group_info group_info;
       struct gl_perf_monitor_counter *counters = NULL;
       struct st_perf_monitor_counter *stcounters = NULL;
@@ -313,7 +385,7 @@ st_init_perfmon(struct st_context *st)
       stcounters = CALLOC(group_info.num_queries, sizeof(*stcounters));
       if (!stcounters)
          goto fail;
-      stgroups[perfmon->NumGroups].counters = stcounters;
+      stg->counters = stcounters;
 
       for (cid = 0; cid < num_counters; cid++) {
          struct gl_perf_monitor_counter *c = &counters[g->NumCounters];
@@ -332,17 +404,17 @@ st_init_perfmon(struct st_context *st)
             case PIPE_DRIVER_QUERY_TYPE_MICROSECONDS:
             case PIPE_DRIVER_QUERY_TYPE_HZ:
                c->Minimum.u64 = 0;
-               c->Maximum.u64 = info.max_value.u64 ? info.max_value.u64 : -1;
+               c->Maximum.u64 = info.max_value.u64 ? info.max_value.u64 : UINT64_MAX;
                c->Type = GL_UNSIGNED_INT64_AMD;
                break;
             case PIPE_DRIVER_QUERY_TYPE_UINT:
                c->Minimum.u32 = 0;
-               c->Maximum.u32 = info.max_value.u32 ? info.max_value.u32 : -1;
+               c->Maximum.u32 = info.max_value.u32 ? info.max_value.u32 : UINT32_MAX;
                c->Type = GL_UNSIGNED_INT;
                break;
             case PIPE_DRIVER_QUERY_TYPE_FLOAT:
                c->Minimum.f = 0.0;
-               c->Maximum.f = info.max_value.f ? info.max_value.f : -1;
+               c->Maximum.f = info.max_value.f ? info.max_value.f : FLT_MAX;
                c->Type = GL_FLOAT;
                break;
             case PIPE_DRIVER_QUERY_TYPE_PERCENTAGE:
@@ -355,6 +427,9 @@ st_init_perfmon(struct st_context *st)
          }
 
          stc->query_type = info.query_type;
+         stc->flags = info.flags;
+         if (stc->flags & PIPE_DRIVER_QUERY_FLAG_BATCH)
+            stg->has_batch = true;
 
          g->NumCounters++;
       }
@@ -363,7 +438,7 @@ st_init_perfmon(struct st_context *st)
    perfmon->Groups = groups;
    st->perfmon = stgroups;
 
-   return true;
+   return;
 
 fail:
    for (gid = 0; gid < num_groups; gid++) {
@@ -373,7 +448,6 @@ fail:
    FREE(stgroups);
 fail_only_groups:
    FREE(groups);
-   return false;
 }
 
 void
@@ -392,6 +466,7 @@ st_destroy_perfmon(struct st_context *st)
 
 void st_init_perfmon_functions(struct dd_function_table *functions)
 {
+   functions->InitPerfMonitorGroups = st_InitPerfMonitorGroups;
    functions->NewPerfMonitor = st_NewPerfMonitor;
    functions->DeletePerfMonitor = st_DeletePerfMonitor;
    functions->BeginPerfMonitor = st_BeginPerfMonitor;