From: Carl Worth Date: Mon, 4 Nov 2013 23:44:23 +0000 (-0800) Subject: Fix fips to work even without the AMD_performance_monitor extension. X-Git-Url: https://git.cworth.org/git?p=fips;a=commitdiff_plain;h=ba91fa6199a75aea42e40221489d259f1f723e4e Fix fips to work even without the AMD_performance_monitor extension. 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. --- diff --git a/context.c b/context.c index 133c37c..6bc3e0a 100644 --- 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; +} diff --git a/metrics-info.c b/metrics-info.c index 860e435..b450e39 100644 --- a/metrics-info.c +++ b/metrics-info.c @@ -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)); diff --git a/metrics-info.h b/metrics-info.h index 1340c83..11043be 100644 --- a/metrics-info.h +++ b/metrics-info.h @@ -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. * diff --git a/metrics.c b/metrics.c index 004c339..71e2164 100644 --- 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;