]> git.cworth.org Git - fips/commitdiff
Fix fips to work even without the AMD_performance_monitor extension.
authorCarl Worth <cworth@cworth.org>
Mon, 4 Nov 2013 23:44:23 +0000 (15:44 -0800)
committerCarl Worth <cworth@cworth.org>
Mon, 4 Nov 2013 23:44:23 +0000 (15:44 -0800)
Even without the extension, we can still do timer queries and print
the time spent in each operation. So detect that the extension is
available, and then use that information to avoid calling into any
functions that are only made available with that extension.

context.c
metrics-info.c
metrics-info.h
metrics.c

index 133c37c168d6b04016579cbf3ccbd3938f11e241..6bc3e0af7365e0ec104073a146ba5b2e6b78d5fb 100644 (file)
--- a/context.c
+++ b/context.c
@@ -28,12 +28,18 @@ typedef struct context
        /* Pointer to the system's context ID, (such as a GLXContext) */
        void *system_id;
 
+       /* Does this context have the AMD_performance_monitor extension? */
+       bool have_perfmon;
+
        metrics_info_t metrics_info;
        metrics_t *metrics;
 } context_t;
 
 context_t *current_context;
 
+static bool
+check_extension (const char *extension);
+
 static context_t *
 context_create (fips_api_t api, void *system_context_id)
 {
@@ -45,7 +51,9 @@ context_create (fips_api_t api, void *system_context_id)
 
        fips_dispatch_init (api);
 
-       metrics_info_init (&ctx->metrics_info);
+       ctx->have_perfmon = check_extension ("AMD_performance_monitor");
+
+       metrics_info_init (&ctx->metrics_info, ctx->have_perfmon);
        ctx->metrics = metrics_create (&ctx->metrics_info);
 
        return ctx;
@@ -115,3 +123,22 @@ context_end_frame (void)
 {
        return metrics_end_frame (current_context->metrics);
 }
+
+/* Is the given extension available? */
+static bool
+check_extension (const char *extension)
+{
+       int i, num_extensions;
+       const char *available;
+
+       glGetIntegerv (GL_NUM_EXTENSIONS, &num_extensions);
+
+       for (i = 0; i < num_extensions; i++) {
+               available = (char *) glGetStringi (GL_EXTENSIONS, i);
+               if (strcmp (extension, available) == 0) {
+                       return true;
+               }
+       }
+
+       return false;
+}
index 860e4359a3d7e8907c2b03c8970d48b4d1fbc2b8..b450e39b531d6e2212f249aeb07945375fa5ba89 100644 (file)
@@ -156,11 +156,23 @@ _add_shader_stage (metrics_info_t *info, const char *name,
 }
 
 void
-metrics_info_init (metrics_info_t *info)
+metrics_info_init (metrics_info_t *info, bool have_perfmon)
 {
        unsigned i, j;
        GLuint *group_ids;
 
+       info->have_perfmon = have_perfmon;
+
+       if (! have_perfmon) {
+               info->groups = NULL;
+               info->num_groups = 0;
+               info->num_shader_stages = 0;
+               info->stages = NULL;
+               info->initialized = 1;
+
+               return;
+       }
+
        glGetPerfMonitorGroupsAMD ((int *) &info->num_groups, 0, NULL);
 
        group_ids = xmalloc (info->num_groups * sizeof (GLuint));
index 1340c836ef764a36aebd4f63fa4adfab67e6c115..11043be3b6052f2de8ced21c7898fc63eaad2a0a 100644 (file)
@@ -54,6 +54,8 @@ typedef struct metrics_info
 {
        int initialized;
 
+       bool have_perfmon;
+
        unsigned num_groups;
        metrics_group_info_t *groups;
 
@@ -67,9 +69,13 @@ typedef struct metrics_info
  * This queries the names and ranges for all available performance counters.
  *
  * This should be called before any other metrics functions.
+ *
+ * The Boolean have_perfmon must be set to correctly indicate whether
+ * the current OpenGL context has the AMD_performance_monitor
+ * extension.
  */
 void
-metrics_info_init (metrics_info_t *info);
+metrics_info_init (metrics_info_t *info, bool have_perfmon);
 
 /* Finalize metrics info state.
  *
index 004c3399522ce907533a73f0a75d297f895316a4..71e2164bc4a4fb3f1bba6069bf4a86980634f7e3 100644 (file)
--- a/metrics.c
+++ b/metrics.c
@@ -153,22 +153,26 @@ metrics_fini (metrics_t *metrics)
        metrics->timer_head = NULL;
        metrics->timer_tail = NULL;
 
-       if (metrics->monitor_begun_id) {
-               glEndPerfMonitorAMD (metrics->monitor_begun_id);
-               glDeletePerfMonitorsAMD (1, &metrics->monitor_begun_id);
-               metrics->monitor_begun_id = 0;
-       }
+       if (metrics->info->have_perfmon) {
+
+               if (metrics->monitor_begun_id) {
+                       glEndPerfMonitorAMD (metrics->monitor_begun_id);
+                       glDeletePerfMonitorsAMD (1, &metrics->monitor_begun_id);
+                       metrics->monitor_begun_id = 0;
+               }
+
+               for (monitor = metrics->monitor_head;
+                    monitor;
+                    monitor = monitor_next)
+               {
+                       glDeletePerfMonitorsAMD (1, &monitor->id);
+                       monitor_next = monitor->next;
+                       free (monitor);
+               }
+               metrics->monitor_head = NULL;
+               metrics->monitor_tail = NULL;
 
-       for (monitor = metrics->monitor_head;
-            monitor;
-            monitor = monitor_next)
-       {
-               glDeletePerfMonitorsAMD (1, &monitor->id);
-               monitor_next = monitor->next;
-               free (monitor);
        }
-       metrics->monitor_head = NULL;
-       metrics->monitor_tail = NULL;
 
        metrics->monitors_in_flight = 0;
 }
@@ -231,9 +235,18 @@ metrics_counter_start (metrics_t *metrics)
 {
        unsigned i;
 
-       /* Initialize the timer_query and monitor objects */
+       /* Initialize the timer_query object. */
        glGenQueries (1, &metrics->timer_begun_id);
 
+       /* Most everything else in this function is
+        * performance-monitor related. If we don't have that
+        * extension, just start the timer query and be done. */
+       if (! metrics->info->have_perfmon) {
+               glBeginQuery (GL_TIME_ELAPSED, metrics->timer_begun_id);
+               return;
+       }
+
+       /* Initialize the performance-monitor object */
        glGenPerfMonitorsAMD (1, &metrics->monitor_begun_id);
 
        for (i = 0; i < metrics->info->num_groups; i++)
@@ -273,7 +286,9 @@ metrics_counter_stop (metrics_t *metrics)
 
        /* Stop the current timer and monitor. */
        glEndQuery (GL_TIME_ELAPSED);
-       glEndPerfMonitorAMD (metrics->monitor_begun_id);
+
+       if (metrics->info->have_perfmon)
+               glEndPerfMonitorAMD (metrics->monitor_begun_id);
 
        /* Add these IDs to our lists of outstanding queries and
         * monitors so the results can be collected later. */
@@ -291,19 +306,21 @@ metrics_counter_stop (metrics_t *metrics)
                metrics->timer_head = timer;
        }
 
-       /* Create a new performance-monitor query */
-       monitor = xmalloc (sizeof (monitor_t));
+       if (metrics->info->have_perfmon) {
+               /* Create a new performance-monitor query */
+               monitor = xmalloc (sizeof (monitor_t));
 
-       monitor->op = metrics->op;
-       monitor->id = metrics->monitor_begun_id;
-       monitor->next = NULL;
+               monitor->op = metrics->op;
+               monitor->id = metrics->monitor_begun_id;
+               monitor->next = NULL;
 
-       if (metrics->monitor_tail) {
-               metrics->monitor_tail->next = monitor;
-               metrics->monitor_tail = monitor;
-       } else {
-               metrics->monitor_tail = monitor;
-               metrics->monitor_head = monitor;
+               if (metrics->monitor_tail) {
+                       metrics->monitor_tail->next = monitor;
+                       metrics->monitor_tail = monitor;
+               } else {
+                       metrics->monitor_tail = monitor;
+                       metrics->monitor_head = monitor;
+               }
        }
 
        metrics->monitors_in_flight++;
@@ -700,6 +717,9 @@ metrics_collect_available (metrics_t *metrics)
                timer = metrics->timer_head;
        }
 
+       if (! metrics->info->have_perfmon)
+               return;
+
        /* And similarly for all performance monitors that are ready. */
        monitor_t *monitor = metrics->monitor_head;