On 09/20/2013 04:42 PM, Kenneth Graunke wrote: > On 09/20/2013 07:55 AM, Brian Paul wrote: >> On Thu, Sep 19, 2013 at 5:27 PM, Kenneth Graunke <kenn...@whitecape.org> >> wrote: > [snip] >>> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h >>> index 6d700ec..70dba6e 100644 >>> --- a/src/mesa/main/mtypes.h >>> +++ b/src/mesa/main/mtypes.h >>> @@ -1778,6 +1778,89 @@ struct gl_transform_feedback_state >>> >>> >>> /** >>> + * A "performance monitor" as described in AMD_performance_monitor. >>> + */ >>> +struct gl_perf_monitor_object >>> +{ >>> + GLboolean Active; >>> + >>> + /** >>> + * A list of groups with currently active counters. >>> + * >>> + * ActiveGroups[g] == n if there are n counters active from group 'g'. >>> + */ >>> + unsigned *ActiveGroups; >> >> GLuint? >> > > I chose 'unsigned' over 'GLuint' here since it's only used internally, > and never exposed by the API. But I can switch if you prefer that. > >>> + >>> + /** >>> + * An array of bitsets, subscripted by group ID, then indexed by >>> counter ID. >>> + * >>> + * Checking whether counter 'c' in group 'g' is active can be done via: >>> + * >>> + * BITSET_TEST(ActiveCounters[g], c) >>> + */ >>> + GLuint **ActiveCounters; >> >> GLbitfield? > > The type here is actually BITSET_WORD (from bitset.h), which is a > #define for GLuint. Including bitset.h from mtypes.h led to all kinds > of problems, so I just used GLuint. > > It seems like we could do something better, but I'm not sure what.
Could we make BITSET_WORD be uint32_t? I suspect that's a type from before we had our own inttypes.h... >>> +}; >>> + >>> + >>> +union gl_perf_monitor_counter_value >>> +{ >>> + float f; >>> + uint64_t u64; >>> + uint32_t u32; >>> +}; >>> + >>> + >>> +struct gl_perf_monitor_counter >>> +{ >>> + /** Human readable name for the counter. */ >>> + const char *Name; >>> + >>> + /** >>> + * Data type of the counter. Valid values are FLOAT, UNSIGNED_INT, >>> + * UNSIGNED_INT64_AMD, and PERCENTAGE_AMD. >>> + */ >>> + GLenum Type; >>> + >>> + /** Minimum counter value. */ >>> + union gl_perf_monitor_counter_value Minimum; >>> + >>> + /** Maximum counter value. */ >>> + union gl_perf_monitor_counter_value Maximum; >>> +}; >>> + >>> + >>> +struct gl_perf_monitor_group >>> +{ >>> + /** Human readable name for the group. */ >>> + const char *Name; >>> + >>> + /** >>> + * Maximum number of counters in this group which can be active at the >>> + * same time. >>> + */ >>> + GLint MaxActiveCounters; >> >> GLuint? > > That would make sense, but for some reason the AMD_performance_monitor > extension exposes this value as a GLint: > > void GetPerfMonitorCountersAMD(uint group, int *numCounters, > int *maxActiveCounters, sizei countersSize, > uint *counters) > > I figured it should probably match... > >>> + >>> + /** Array of counters within this group. */ >>> + const struct gl_perf_monitor_counter *Counters; >>> + GLint NumCounters; >>> +}; >>> + >>> + >>> +/** >>> + * Context state for AMD_performance_monitor. >>> + */ >>> +struct gl_perf_monitor_state >>> +{ >>> + /** Array of performance monitor groups (indexed by group ID) */ >>> + const struct gl_perf_monitor_group *Groups; >>> + GLint NumGroups; >> >> GLuint? > > Likewise, the extension exposes this as a GLint: > > void GetPerfMonitorGroupsAMD(int *numGroups, sizei groupsSize, > uint *groups) > > I don't know why...GLuint would have made more sense. Of course, nobody > is going to have enough groups for it to make a difference :) > >> >>> + >>> + /** The table of all performance monitors. */ >>> + struct _mesa_HashTable *Monitors; >>> +}; >>> + >>> + >>> +/** >>> * Names of the various vertex/fragment program register files, etc. >>> * >>> * NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c) >>> @@ -3153,6 +3236,7 @@ struct gl_extensions >>> GLboolean EXT_vertex_array_bgra; >>> GLboolean OES_standard_derivatives; >>> /* vendor extensions */ >>> + GLboolean AMD_performance_monitor; >>> GLboolean AMD_seamless_cubemap_per_texture; >>> GLboolean AMD_vertex_shader_layer; >>> GLboolean APPLE_object_purgeable; >>> @@ -3618,6 +3702,8 @@ struct gl_context >>> >>> struct gl_transform_feedback_state TransformFeedback; >>> >>> + struct gl_perf_monitor_state PerfMonitor; >>> + >>> struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */ >>> struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */ >>> >>> diff --git a/src/mesa/main/performance_monitor.c >>> b/src/mesa/main/performance_monitor.c >>> new file mode 100644 >>> index 0000000..0782219 >>> --- /dev/null >>> +++ b/src/mesa/main/performance_monitor.c >>> @@ -0,0 +1,606 @@ >>> +/* >>> + * Copyright © 2012 Intel Corporation >>> + * >>> + * Permission is hereby granted, free of charge, to any person obtaining a >>> + * copy of this software and associated documentation files (the >>> "Software"), >>> + * to deal in the Software without restriction, including without >>> limitation >>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense, >>> + * and/or sell copies of the Software, and to permit persons to whom the >>> + * Software is furnished to do so, subject to the following conditions: >>> + * >>> + * The above copyright notice and this permission notice (including the >>> next >>> + * paragraph) shall be included in all copies or substantial portions of >>> the >>> + * Software. >>> + * >>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS >>> OR >>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, >>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL >>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR >>> OTHER >>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING >>> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER >>> + * DEALINGS IN THE SOFTWARE. >>> + */ >>> + >>> +/** >>> + * \file performance_monitor.c >>> + * Core Mesa support for the AMD_performance_monitor extension. >>> + * >>> + * In order to implement this extension, start by defining two enums: >>> + * one for Groups, and one for Counters. These will be used as indexes >>> into >>> + * arrays, so they should start at 0 and increment from there. >>> + * >>> + * Counter IDs need to be globally unique. That is, you can't have >>> counter 7 >>> + * in group A and counter 7 in group B. A global enum of all available >>> + * counters is a convenient way to guarantee this. >>> + */ >>> + >>> +#include <stdbool.h> >>> +#include "glheader.h" >>> +#include "context.h" >>> +#include "enums.h" >>> +#include "hash.h" >>> +#include "macros.h" >>> +#include "mtypes.h" >>> +#include "performance_monitor.h" >>> +#include "bitset.h" >>> +#include "ralloc.h" >>> + >>> +void >>> +_mesa_init_performance_monitors(struct gl_context *ctx) >>> +{ >>> + ctx->PerfMonitor.Monitors = _mesa_NewHashTable(); >>> + ctx->PerfMonitor.NumGroups = 0; >>> + ctx->PerfMonitor.Groups = NULL; >>> +} >>> + >>> +static struct gl_perf_monitor_object * >>> +_mesa_new_performance_monitor(struct gl_context *ctx, GLuint index) > > I've removed the _mesa_ prefix on this function in response to your > later comments, as it's static. > >>> +{ >>> + int i; >> >> If NumGroups is changed to unsigned (above), this should be unsigned too. >> >> >>> + struct gl_perf_monitor_object *m = ctx->Driver.NewPerfMonitor(ctx); >> >> Check for m=NULL and raise GL_OUT_OF_MEMORY? > > Good catch. I've added: > > if (m == NULL) > return NULL; > > The caller already detected a NULL return value and raises > GL_OUT_OF_MEMORY. We just would have crashed first. :) > >>> + >>> + m->ActiveGroups = >>> + rzalloc_array(NULL, unsigned, ctx->PerfMonitor.NumGroups); >>> + >>> + m->ActiveCounters = >>> + ralloc_array(NULL, BITSET_WORD *, ctx->PerfMonitor.NumGroups); >> >> NULL ptr checks? > > Right...I've added: > > if (m->ActiveGroups == NULL || m->ActiveCounters == NULL) > goto fail; > >>> + >>> + for (i = 0; i < ctx->PerfMonitor.NumGroups; i++) { >>> + const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[i]; >>> + >>> + m->ActiveCounters[i] = rzalloc_array(m->ActiveCounters, BITSET_WORD, >>> + BITSET_WORDS(g->NumCounters)); > > and: > if (m->ActiveCounters[i] == NULL) > goto fail; > >>> + } >>> + >>> + return m; > > and finally: > > fail: > ralloc_free(m->ActiveGroups); > ralloc_free(m->ActiveCounters); > ctx->Driver.DeletePerfMonitor(ctx, m); > return NULL; > >>> +} >>> + >>> +static inline struct gl_perf_monitor_object * >>> +lookup_monitor(struct gl_context *ctx, GLuint id) >>> +{ >>> + return (struct gl_perf_monitor_object *) >>> + _mesa_HashLookup(ctx->PerfMonitor.Monitors, id); >>> +} >>> + >>> +static inline const struct gl_perf_monitor_group * >>> +get_group(const struct gl_context *ctx, GLuint id) >>> +{ >>> + if (id >= ctx->PerfMonitor.NumGroups) >>> + return NULL; >>> + >>> + return &ctx->PerfMonitor.Groups[id]; >>> +} >>> + >>> +static inline const struct gl_perf_monitor_counter * >>> +get_counter(const struct gl_perf_monitor_group *group_obj, GLuint id) >>> +{ >>> + if (id >= group_obj->NumCounters) >>> + return NULL; >>> + >>> + return &group_obj->Counters[id]; >>> +} >>> + >>> +/*****************************************************************************/ >>> + >>> +void GLAPIENTRY >>> +_mesa_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize, >>> + GLuint *groups) >>> +{ >>> + GET_CURRENT_CONTEXT(ctx); >>> + >>> + if (numGroups != NULL) >>> + *numGroups = ctx->PerfMonitor.NumGroups; >>> + >>> + if (groupsSize > 0 && groups != NULL) { >>> + int i; >>> + int n = MIN2(groupsSize, ctx->PerfMonitor.NumGroups); >>> + >>> + /* We just use the index in the Groups array as the ID. */ >>> + for (i = 0; i < n; i++) >>> + groups[i] = i; >>> + } >>> +} >>> + >>> +void GLAPIENTRY >>> +_mesa_GetPerfMonitorCountersAMD(GLuint group, GLint *numCounters, >>> + GLint *maxActiveCounters, >>> + GLsizei countersSize, GLuint *counters) >>> +{ >>> + GET_CURRENT_CONTEXT(ctx); >>> + const struct gl_perf_monitor_group *group_obj = get_group(ctx, group); >>> + if (group_obj == NULL) { >>> + _mesa_error(ctx, GL_INVALID_VALUE, >>> + "glGetPerfMonitorCountersAMD(invalid group)"); >>> + return; >>> + } >>> + >>> + if (maxActiveCounters != NULL) >>> + *maxActiveCounters = group_obj->MaxActiveCounters; >>> + >>> + if (numCounters != NULL) >>> + *numCounters = group_obj->NumCounters; >>> + >>> + if (counters != NULL) { >>> + int i; >>> + for (i = 0; i < MIN2(group_obj->NumCounters, countersSize); i++) { >> >> If MIN2 gets evaluated for each iteration, maybe put it in an 'n' var >> like above. > > Good call. Changed. > >>> + /* We just use the index in the Counters array as the ID. */ >>> + counters[i] = i; >>> + } >>> + } >>> +} >>> + >>> +void GLAPIENTRY >>> +_mesa_GetPerfMonitorGroupStringAMD(GLuint group, GLsizei bufSize, >>> + GLsizei *length, GLchar *groupString) >>> +{ >>> + GET_CURRENT_CONTEXT(ctx); >>> + >>> + const struct gl_perf_monitor_group *group_obj = get_group(ctx, group); >>> + >>> + if (group_obj == NULL) { >>> + _mesa_error(ctx, GL_INVALID_VALUE, "glGetPerfMonitorGroupStringAMD"); >>> + return; >>> + } >>> + >>> + if (bufSize == 0) { >>> + /* Return the number of characters that would be required to hold the >>> + * group string, excluding the null terminator. >>> + */ >>> + if (length != NULL) >>> + *length = strlen(group_obj->Name); >>> + } else { >>> + if (length != NULL) >>> + *length = MIN2(strlen(group_obj->Name), bufSize); >>> + if (groupString != NULL) >>> + strncpy(groupString, group_obj->Name, bufSize); >> >> I think you need to replace bufSize there with the value you put in *length. > > It shouldn't matter. The names should all be proper NULL-terminated C > strings, so the strncpy will automatically stop at > strlen(group_obj->Name). Passing bufSize to strncpy catches the case > where the buffer is smaller than the group name. > > If the caller supplies a length pointer, we'll write the actual number > of bytes copied, which is the minimum of the actual string length and > the buffer size. > > I'm pretty sure I hit all of these cases in Piglit's > tests/spec/amd_performance_monitor/api.c test. > >> >>> + } >>> +} >>> + >>> +void GLAPIENTRY >>> +_mesa_GetPerfMonitorCounterStringAMD(GLuint group, GLuint counter, >>> + GLsizei bufSize, GLsizei *length, >>> + GLchar *counterString) >>> +{ >>> + GET_CURRENT_CONTEXT(ctx); >>> + >>> + const struct gl_perf_monitor_group *group_obj; >>> + const struct gl_perf_monitor_counter *counter_obj; >>> + >>> + group_obj = get_group(ctx, group); >>> + >>> + if (group_obj == NULL) { >>> + _mesa_error(ctx, GL_INVALID_VALUE, >>> + "glGetPerfMonitorCounterStringAMD(invalid group)"); >>> + return; >>> + } >>> + >>> + counter_obj = get_counter(group_obj, counter); >>> + >>> + if (counter_obj == NULL) { >>> + _mesa_error(ctx, GL_INVALID_VALUE, >>> + "glGetPerfMonitorCounterStringAMD(invalid counter)"); >>> + return; >>> + } >>> + >>> + if (bufSize == 0) { >>> + /* Return the number of characters that would be required to hold the >>> + * counter string, excluding the null terminator. >>> + */ >>> + if (length != NULL) >>> + *length = strlen(counter_obj->Name); >>> + } else { >>> + if (length != NULL) >>> + *length = MIN2(strlen(counter_obj->Name), bufSize); >>> + if (counterString != NULL) >>> + strncpy(counterString, counter_obj->Name, bufSize); >> >> bufSize issue again. >> > [snip] >>> +void GLAPIENTRY >>> +_mesa_BeginPerfMonitorAMD(GLuint monitor) >>> +{ >>> + GET_CURRENT_CONTEXT(ctx); >>> + >>> + struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor); >>> + >>> + if (m == NULL) { >>> + _mesa_error(ctx, GL_INVALID_VALUE, >>> + "glBeginPerfMonitorAMD(invalid monitor)"); >>> + return; >>> + } >>> + >>> + /* "INVALID_OPERATION error will be generated if BeginPerfMonitorAMD is >>> + * called when a performance monitor is already active." >>> + */ >>> + if (m->Active) { >>> + _mesa_error(ctx, GL_INVALID_OPERATION, >>> + "glBeginPerfMonitor(already active)"); >>> + return; >>> + } >>> + >>> + /* The driver should either set m->Active to true or raise an error: >>> + * "INVALID_OPERATION error will be generated if BeginPerfMonitorAMD is >>> + * unable to begin monitoring with the currently selected counters." >>> + */ >>> + ctx->Driver.BeginPerfMonitor(ctx, m); >> >> Set m->Active = true here? We set it to false in the End function below. > > See the above comment. The spec allows drivers to arbitrarily refuse to > start monitoring due to unknown constraints. It's sort of a cop-out; > the extension is general, and each GPU has weird restrictions on > performance counters that would be hard to expose. > > So the driver needs to set m->Active or raise an error. > > In contrast, it should always be possible to /stop/ counting, so I made > the core code set m->Active = false. I could move that to the driver > for consistency, I suppose. Do you have a preference? > >> >>> +} >>> + >>> +void GLAPIENTRY >>> +_mesa_EndPerfMonitorAMD(GLuint monitor) >>> +{ >>> + GET_CURRENT_CONTEXT(ctx); >>> + >>> + struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor); >>> + >>> + if (m == NULL) { >>> + _mesa_error(ctx, GL_INVALID_VALUE, "glEndPerfMonitorAMD(invalid >>> monitor)"); >>> + return; >>> + } >>> + >>> + /* "INVALID_OPERATION error will be generated if EndPerfMonitorAMD is >>> called >>> + * when a performance monitor is not currently started." >>> + */ >>> + if (!m->Active) { >>> + _mesa_error(ctx, GL_INVALID_OPERATION, >>> + "glBeginPerfMonitor(already inactive)"); >> >> "glEndPerfMonitor(not active)" > > I like that better. Changed. > >> >>> + return; >>> + } >>> + >>> + ctx->Driver.EndPerfMonitor(ctx, m); >>> + >>> + m->Active = false; >>> +} >>> + >>> +/** >>> + * Return the number of bytes needed to store a monitor's result. >>> + */ >>> +static unsigned >>> +_mesa_perf_monitor_result_size(const struct gl_context *ctx, >>> + const struct gl_perf_monitor_object *m) >> >> I don't usually put _mesa_ on static functions like this. I think ctx >> could be const-qualified too. > > Oops, right. I've removed the _mesa_ prefix. ctx was already const > qualified. > >> >>> +{ >>> + unsigned size = 0; >>> + int group, counter; >> >> unsigned group, counter vars to avoid MSVC signed/unsigned comparison >> warnings below. >> >> >>> + >>> + for (group = 0; group < ctx->PerfMonitor.NumGroups; group++) { >>> + const struct gl_perf_monitor_group *g = >>> &ctx->PerfMonitor.Groups[group]; >>> + for (counter = 0; counter < g->NumCounters; counter++) { >>> + const struct gl_perf_monitor_counter *c = &g->Counters[counter]; >>> + >>> + if (!BITSET_TEST(m->ActiveCounters[group], counter)) >>> + continue; >>> + >>> + size += sizeof(uint32_t); /* Group ID */ >>> + size += sizeof(uint32_t); /* Counter ID */ >>> + size += _mesa_perf_monitor_counter_size(c); >>> + } >>> + } >>> + return size; >>> +} >>> + >>> +void GLAPIENTRY >>> +_mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, >>> + GLsizei dataSize, GLuint *data, >>> + GLint *bytesWritten) >>> +{ >>> + GET_CURRENT_CONTEXT(ctx); >>> + >>> + struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor); >>> + >>> + if (m == NULL) { >>> + _mesa_error(ctx, GL_INVALID_VALUE, >>> + "glGetPerfMonitorCounterDataAMD(invalid monitor)"); >>> + return; >>> + } >>> + >>> + /* "It is an INVALID_OPERATION error for <data> to be NULL." */ >>> + if (data == NULL) { >>> + _mesa_error(ctx, GL_INVALID_OPERATION, >>> + "glGetPerfMonitorCounterDataAMD(data == NULL)"); >>> + return; >>> + } >>> + >>> + /* We need at least enough room for a single value. */ >>> + if (dataSize < sizeof(GLuint)) { >>> + if (bytesWritten != NULL) >>> + *bytesWritten = 0; >>> + return; >>> + } >>> + >>> + /* AMD appears to return 0 for all queries unless a result is >>> available. */ >>> + if (!ctx->Driver.IsPerfMonitorResultAvailable(ctx, m)) { >>> + *data = 0; >>> + if (bytesWritten != NULL) >>> + *bytesWritten = sizeof(GLuint); >>> + return; >>> + } >>> + >>> + switch (pname) { >>> + case GL_PERFMON_RESULT_AVAILABLE_AMD: >>> + *data = 1; >>> + if (bytesWritten != NULL) >>> + *bytesWritten = sizeof(GLuint); >>> + break; >>> + case GL_PERFMON_RESULT_SIZE_AMD: >>> + *data = _mesa_perf_monitor_result_size(ctx, m); >>> + if (bytesWritten != NULL) >>> + *bytesWritten = sizeof(GLuint); >>> + break; >>> + case GL_PERFMON_RESULT_AMD: >>> + ctx->Driver.GetPerfMonitorResult(ctx, m, dataSize, data, >>> bytesWritten); >>> + break; >>> + default: >>> + _mesa_error(ctx, GL_INVALID_ENUM, >>> + "glGetPerfMonitorCounterDataAMD(pname)"); >>> + } >>> +} >>> + >>> +/** >>> + * Returns how many bytes a counter's value takes up. >>> + */ >>> +unsigned >>> +_mesa_perf_monitor_counter_size(const struct gl_perf_monitor_counter *c) >>> +{ >>> + switch (c->Type) { >>> + case GL_FLOAT: >>> + case GL_PERCENTAGE_AMD: >>> + return sizeof(GLfloat); >>> + case GL_UNSIGNED_INT: >>> + return sizeof(GLuint); >>> + case GL_UNSIGNED_INT64_AMD: >>> + return sizeof(uint64_t); >>> + default: >>> + assert(!"Should not get here: invalid counter type"); >>> + return 0; >>> + } >>> +} >>> + >>> +/* >>> +void >>> +_mesa_init_perf_monitors(struct gl_context *ctx, >>> + const struct gl_perf_monitor_counter *counters, >>> + unsigned num_counters, >>> + const struct gl_perf_monitor_group *groups, >>> + unsigned num_groups) >>> +{ >>> + ctx->PerfMonitor.Groups = groups; >>> + ctx->PerfMonitor.NumGroups = num_groups; >>> + ctx->PerfMonitor.Counters = counters; >>> + ctx->PerfMonitor.NumCounters = num_counters; >>> +} >>> +*/ >>> diff --git a/src/mesa/main/performance_monitor.h >>> b/src/mesa/main/performance_monitor.h >>> new file mode 100644 >>> index 0000000..a852a41 >>> --- /dev/null >>> +++ b/src/mesa/main/performance_monitor.h >>> @@ -0,0 +1,85 @@ >>> +/* >>> + * Copyright © 2012 Intel Corporation >>> + * >>> + * Permission is hereby granted, free of charge, to any person obtaining a >>> + * copy of this software and associated documentation files (the >>> "Software"), >>> + * to deal in the Software without restriction, including without >>> limitation >>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense, >>> + * and/or sell copies of the Software, and to permit persons to whom the >>> + * Software is furnished to do so, subject to the following conditions: >>> + * >>> + * The above copyright notice and this permission notice (including the >>> next >>> + * paragraph) shall be included in all copies or substantial portions of >>> the >>> + * Software. >>> + * >>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS >>> OR >>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, >>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL >>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR >>> OTHER >>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING >>> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER >>> + * DEALINGS IN THE SOFTWARE. >>> + */ >>> + >>> +/** >>> + * \file performance_monitor.h >>> + * Core Mesa support for the AMD_performance_monitor extension. >>> + */ >>> + >>> +#pragma once >>> +#ifndef PERFORMANCE_MONITOR_H >>> +#define PERFORMANCE_MONITOR_H >>> + >>> +#include "glheader.h" >>> + >>> +extern void >>> +_mesa_init_performance_monitors(struct gl_context *ctx); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize, >>> + GLuint *groups); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_GetPerfMonitorCountersAMD(GLuint group, GLint *numCounters, >>> + GLint *maxActiveCounters, >>> + GLsizei countersSize, GLuint *counters); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_GetPerfMonitorGroupStringAMD(GLuint group, GLsizei bufSize, >>> + GLsizei *length, GLchar *groupString); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_GetPerfMonitorCounterStringAMD(GLuint group, GLuint counter, >>> + GLsizei bufSize, GLsizei *length, >>> + GLchar *counterString); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_GetPerfMonitorCounterInfoAMD(GLuint group, GLuint counter, GLenum >>> pname, >>> + GLvoid *data); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_GenPerfMonitorsAMD(GLsizei n, GLuint *monitors); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_DeletePerfMonitorsAMD(GLsizei n, GLuint *monitors); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_SelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable, >>> + GLuint group, GLint numCounters, >>> + GLuint *counterList); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_BeginPerfMonitorAMD(GLuint monitor); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_EndPerfMonitorAMD(GLuint monitor); >>> + >>> +extern void GLAPIENTRY >>> +_mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, >>> + GLsizei dataSize, GLuint *data, >>> + GLint *bytesWritten); >>> + >>> +unsigned >>> +_mesa_perf_monitor_counter_size(const struct gl_perf_monitor_counter *); >>> + >>> +#endif >> >> >> >> Reviewed-by: Brian Paul <bri...@vmware.com> > > Thanks Brian! > > --Ken > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev