]> git.cworth.org Git - fips/commitdiff
Fix fips to work even without the GL_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, 11 Nov 2013 17:43:38 +0000 (09:43 -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.

The first report generated with a context that does not have the
extension will include a warning that the extension was not available.

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

index 133c37c168d6b04016579cbf3ccbd3938f11e241..3c58a60e6b2fbd76ca7a13dfaa3248f67fd43828 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 ("GL_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..4136467e61c7baeb281392f9b7be51d7c74eff62 100644 (file)
@@ -156,11 +156,24 @@ _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;
+       info->printed_missing_perfmon_warning = false;
+
+       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..f03352eb913ec5eaac4dfa8d4ddda0819dba3eb4 100644 (file)
@@ -54,6 +54,9 @@ typedef struct metrics_info
 {
        int initialized;
 
+       bool have_perfmon;
+       bool printed_missing_perfmon_warning;
+
        unsigned num_groups;
        metrics_group_info_t *groups;
 
@@ -67,9 +70,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..79aeb6dacaec55c331fd92af3007daae1d4ebfe2 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++;
@@ -576,6 +593,17 @@ print_program_metrics (metrics_t *metrics)
        unsigned group_index, counter_index;
        unsigned i, j, num_sorted;
 
+       if (! info->have_perfmon &&
+           ! info->printed_missing_perfmon_warning)
+       {
+               fprintf (stderr,
+                        "Warning: The GL_AMD_performance_monitor extensions is not available.\n"
+                        "         Some fips features, (such as per-shader-stage timings),\n"
+                        "         will not be available.\n");
+
+               info->printed_missing_perfmon_warning = true;
+       }
+
        /* Make a sorted list of the per-stage operations by time
         * used, and figure out the total so we can print percentages.
         */
@@ -700,6 +728,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;