1 /*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * \file performance_monitor.c
26 * Core Mesa support for the AMD_performance_monitor extension.
27 *
28 * In order to implement this extension, start by defining two enums:
29 * one for Groups, and one for Counters. These will be used as indexes into
30 * arrays, so they should start at 0 and increment from there.
31 *
32 * Counter IDs need to be globally unique. That is, you can't have counter 7
33 * in group A and counter 7 in group B. A global enum of all available
34 * counters is a convenient way to guarantee this.
35 */
36
37 #include <stdbool.h>
38 #include "glheader.h"
39 #include "context.h"
40 #include "enums.h"
41 #include "hash.h"
42 #include "macros.h"
43 #include "mtypes.h"
44 #include "performance_monitor.h"
45 #include "util/bitset.h"
46 #include "util/ralloc.h"
47
48 void
_mesa_init_performance_monitors(struct gl_context * ctx)49 _mesa_init_performance_monitors(struct gl_context *ctx)
50 {
51 ctx->PerfMonitor.Monitors = _mesa_NewHashTable();
52 ctx->PerfMonitor.NumGroups = 0;
53 ctx->PerfMonitor.Groups = NULL;
54 }
55
56 static inline void
init_groups(struct gl_context * ctx)57 init_groups(struct gl_context *ctx)
58 {
59 if (unlikely(!ctx->PerfMonitor.Groups))
60 ctx->Driver.InitPerfMonitorGroups(ctx);
61 }
62
63 static struct gl_perf_monitor_object *
new_performance_monitor(struct gl_context * ctx,GLuint index)64 new_performance_monitor(struct gl_context *ctx, GLuint index)
65 {
66 unsigned i;
67 struct gl_perf_monitor_object *m = ctx->Driver.NewPerfMonitor(ctx);
68
69 if (m == NULL)
70 return NULL;
71
72 m->Name = index;
73
74 m->Active = false;
75
76 m->ActiveGroups =
77 rzalloc_array(NULL, unsigned, ctx->PerfMonitor.NumGroups);
78
79 m->ActiveCounters =
80 ralloc_array(NULL, BITSET_WORD *, ctx->PerfMonitor.NumGroups);
81
82 if (m->ActiveGroups == NULL || m->ActiveCounters == NULL)
83 goto fail;
84
85 for (i = 0; i < ctx->PerfMonitor.NumGroups; i++) {
86 const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[i];
87
88 m->ActiveCounters[i] = rzalloc_array(m->ActiveCounters, BITSET_WORD,
89 BITSET_WORDS(g->NumCounters));
90 if (m->ActiveCounters[i] == NULL)
91 goto fail;
92 }
93
94 return m;
95
96 fail:
97 ralloc_free(m->ActiveGroups);
98 ralloc_free(m->ActiveCounters);
99 ctx->Driver.DeletePerfMonitor(ctx, m);
100 return NULL;
101 }
102
103 static void
free_performance_monitor(void * data,void * user)104 free_performance_monitor(void *data, void *user)
105 {
106 struct gl_perf_monitor_object *m = data;
107 struct gl_context *ctx = user;
108
109 ralloc_free(m->ActiveGroups);
110 ralloc_free(m->ActiveCounters);
111 ctx->Driver.DeletePerfMonitor(ctx, m);
112 }
113
114 void
_mesa_free_performance_monitors(struct gl_context * ctx)115 _mesa_free_performance_monitors(struct gl_context *ctx)
116 {
117 _mesa_HashDeleteAll(ctx->PerfMonitor.Monitors,
118 free_performance_monitor, ctx);
119 _mesa_DeleteHashTable(ctx->PerfMonitor.Monitors);
120 }
121
122 static inline struct gl_perf_monitor_object *
lookup_monitor(struct gl_context * ctx,GLuint id)123 lookup_monitor(struct gl_context *ctx, GLuint id)
124 {
125 return (struct gl_perf_monitor_object *)
126 _mesa_HashLookup(ctx->PerfMonitor.Monitors, id);
127 }
128
129 static inline const struct gl_perf_monitor_group *
get_group(const struct gl_context * ctx,GLuint id)130 get_group(const struct gl_context *ctx, GLuint id)
131 {
132 if (id >= ctx->PerfMonitor.NumGroups)
133 return NULL;
134
135 return &ctx->PerfMonitor.Groups[id];
136 }
137
138 static inline const struct gl_perf_monitor_counter *
get_counter(const struct gl_perf_monitor_group * group_obj,GLuint id)139 get_counter(const struct gl_perf_monitor_group *group_obj, GLuint id)
140 {
141 if (id >= group_obj->NumCounters)
142 return NULL;
143
144 return &group_obj->Counters[id];
145 }
146
147 /*****************************************************************************/
148
149 void GLAPIENTRY
_mesa_GetPerfMonitorGroupsAMD(GLint * numGroups,GLsizei groupsSize,GLuint * groups)150 _mesa_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize,
151 GLuint *groups)
152 {
153 GET_CURRENT_CONTEXT(ctx);
154 init_groups(ctx);
155
156 if (numGroups != NULL)
157 *numGroups = ctx->PerfMonitor.NumGroups;
158
159 if (groupsSize > 0 && groups != NULL) {
160 unsigned i;
161 unsigned n = MIN2((GLuint) groupsSize, ctx->PerfMonitor.NumGroups);
162
163 /* We just use the index in the Groups array as the ID. */
164 for (i = 0; i < n; i++)
165 groups[i] = i;
166 }
167 }
168
169 void GLAPIENTRY
_mesa_GetPerfMonitorCountersAMD(GLuint group,GLint * numCounters,GLint * maxActiveCounters,GLsizei countersSize,GLuint * counters)170 _mesa_GetPerfMonitorCountersAMD(GLuint group, GLint *numCounters,
171 GLint *maxActiveCounters,
172 GLsizei countersSize, GLuint *counters)
173 {
174 GET_CURRENT_CONTEXT(ctx);
175 const struct gl_perf_monitor_group *group_obj;
176
177 init_groups(ctx);
178
179 group_obj = get_group(ctx, group);
180 if (group_obj == NULL) {
181 _mesa_error(ctx, GL_INVALID_VALUE,
182 "glGetPerfMonitorCountersAMD(invalid group)");
183 return;
184 }
185
186 if (maxActiveCounters != NULL)
187 *maxActiveCounters = group_obj->MaxActiveCounters;
188
189 if (numCounters != NULL)
190 *numCounters = group_obj->NumCounters;
191
192 if (counters != NULL) {
193 unsigned i;
194 unsigned n = MIN2(group_obj->NumCounters, (GLuint) countersSize);
195 for (i = 0; i < n; i++) {
196 /* We just use the index in the Counters array as the ID. */
197 counters[i] = i;
198 }
199 }
200 }
201
202 void GLAPIENTRY
_mesa_GetPerfMonitorGroupStringAMD(GLuint group,GLsizei bufSize,GLsizei * length,GLchar * groupString)203 _mesa_GetPerfMonitorGroupStringAMD(GLuint group, GLsizei bufSize,
204 GLsizei *length, GLchar *groupString)
205 {
206 GET_CURRENT_CONTEXT(ctx);
207 const struct gl_perf_monitor_group *group_obj;
208
209 init_groups(ctx);
210
211 group_obj = get_group(ctx, group);
212 if (group_obj == NULL) {
213 _mesa_error(ctx, GL_INVALID_VALUE, "glGetPerfMonitorGroupStringAMD");
214 return;
215 }
216
217 if (bufSize == 0) {
218 /* Return the number of characters that would be required to hold the
219 * group string, excluding the null terminator.
220 */
221 if (length != NULL)
222 *length = strlen(group_obj->Name);
223 } else {
224 if (length != NULL)
225 *length = MIN2(strlen(group_obj->Name), bufSize);
226 if (groupString != NULL)
227 strncpy(groupString, group_obj->Name, bufSize);
228 }
229 }
230
231 void GLAPIENTRY
_mesa_GetPerfMonitorCounterStringAMD(GLuint group,GLuint counter,GLsizei bufSize,GLsizei * length,GLchar * counterString)232 _mesa_GetPerfMonitorCounterStringAMD(GLuint group, GLuint counter,
233 GLsizei bufSize, GLsizei *length,
234 GLchar *counterString)
235 {
236 GET_CURRENT_CONTEXT(ctx);
237
238 const struct gl_perf_monitor_group *group_obj;
239 const struct gl_perf_monitor_counter *counter_obj;
240
241 init_groups(ctx);
242
243 group_obj = get_group(ctx, group);
244
245 if (group_obj == NULL) {
246 _mesa_error(ctx, GL_INVALID_VALUE,
247 "glGetPerfMonitorCounterStringAMD(invalid group)");
248 return;
249 }
250
251 counter_obj = get_counter(group_obj, counter);
252
253 if (counter_obj == NULL) {
254 _mesa_error(ctx, GL_INVALID_VALUE,
255 "glGetPerfMonitorCounterStringAMD(invalid counter)");
256 return;
257 }
258
259 if (bufSize == 0) {
260 /* Return the number of characters that would be required to hold the
261 * counter string, excluding the null terminator.
262 */
263 if (length != NULL)
264 *length = strlen(counter_obj->Name);
265 } else {
266 if (length != NULL)
267 *length = MIN2(strlen(counter_obj->Name), bufSize);
268 if (counterString != NULL)
269 strncpy(counterString, counter_obj->Name, bufSize);
270 }
271 }
272
273 void GLAPIENTRY
_mesa_GetPerfMonitorCounterInfoAMD(GLuint group,GLuint counter,GLenum pname,GLvoid * data)274 _mesa_GetPerfMonitorCounterInfoAMD(GLuint group, GLuint counter, GLenum pname,
275 GLvoid *data)
276 {
277 GET_CURRENT_CONTEXT(ctx);
278
279 const struct gl_perf_monitor_group *group_obj;
280 const struct gl_perf_monitor_counter *counter_obj;
281
282 init_groups(ctx);
283
284 group_obj = get_group(ctx, group);
285
286 if (group_obj == NULL) {
287 _mesa_error(ctx, GL_INVALID_VALUE,
288 "glGetPerfMonitorCounterInfoAMD(invalid group)");
289 return;
290 }
291
292 counter_obj = get_counter(group_obj, counter);
293
294 if (counter_obj == NULL) {
295 _mesa_error(ctx, GL_INVALID_VALUE,
296 "glGetPerfMonitorCounterInfoAMD(invalid counter)");
297 return;
298 }
299
300 switch (pname) {
301 case GL_COUNTER_TYPE_AMD:
302 *((GLenum *) data) = counter_obj->Type;
303 break;
304
305 case GL_COUNTER_RANGE_AMD:
306 switch (counter_obj->Type) {
307 case GL_FLOAT:
308 case GL_PERCENTAGE_AMD: {
309 float *f_data = data;
310 f_data[0] = counter_obj->Minimum.f;
311 f_data[1] = counter_obj->Maximum.f;
312 break;
313 }
314 case GL_UNSIGNED_INT: {
315 uint32_t *u32_data = data;
316 u32_data[0] = counter_obj->Minimum.u32;
317 u32_data[1] = counter_obj->Maximum.u32;
318 break;
319 }
320 case GL_UNSIGNED_INT64_AMD: {
321 uint64_t *u64_data = data;
322 u64_data[0] = counter_obj->Minimum.u64;
323 u64_data[1] = counter_obj->Maximum.u64;
324 break;
325 }
326 default:
327 assert(!"Should not get here: invalid counter type");
328 }
329 break;
330
331 default:
332 _mesa_error(ctx, GL_INVALID_ENUM,
333 "glGetPerfMonitorCounterInfoAMD(pname)");
334 return;
335 }
336 }
337
338 void GLAPIENTRY
_mesa_GenPerfMonitorsAMD(GLsizei n,GLuint * monitors)339 _mesa_GenPerfMonitorsAMD(GLsizei n, GLuint *monitors)
340 {
341 GET_CURRENT_CONTEXT(ctx);
342
343 if (MESA_VERBOSE & VERBOSE_API)
344 _mesa_debug(ctx, "glGenPerfMonitorsAMD(%d)\n", n);
345
346 init_groups(ctx);
347
348 if (n < 0) {
349 _mesa_error(ctx, GL_INVALID_VALUE, "glGenPerfMonitorsAMD(n < 0)");
350 return;
351 }
352
353 if (monitors == NULL)
354 return;
355
356 if (_mesa_HashFindFreeKeys(ctx->PerfMonitor.Monitors, monitors, n)) {
357 GLsizei i;
358 for (i = 0; i < n; i++) {
359 struct gl_perf_monitor_object *m =
360 new_performance_monitor(ctx, monitors[i]);
361 if (!m) {
362 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenPerfMonitorsAMD");
363 return;
364 }
365 _mesa_HashInsert(ctx->PerfMonitor.Monitors, monitors[i], m, true);
366 }
367 } else {
368 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenPerfMonitorsAMD");
369 return;
370 }
371 }
372
373 void GLAPIENTRY
_mesa_DeletePerfMonitorsAMD(GLsizei n,GLuint * monitors)374 _mesa_DeletePerfMonitorsAMD(GLsizei n, GLuint *monitors)
375 {
376 GLint i;
377 GET_CURRENT_CONTEXT(ctx);
378
379 if (MESA_VERBOSE & VERBOSE_API)
380 _mesa_debug(ctx, "glDeletePerfMonitorsAMD(%d)\n", n);
381
382 if (n < 0) {
383 _mesa_error(ctx, GL_INVALID_VALUE, "glDeletePerfMonitorsAMD(n < 0)");
384 return;
385 }
386
387 if (monitors == NULL)
388 return;
389
390 for (i = 0; i < n; i++) {
391 struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitors[i]);
392
393 if (m) {
394 /* Give the driver a chance to stop the monitor if it's active. */
395 if (m->Active) {
396 ctx->Driver.ResetPerfMonitor(ctx, m);
397 m->Ended = false;
398 }
399
400 _mesa_HashRemove(ctx->PerfMonitor.Monitors, monitors[i]);
401 ralloc_free(m->ActiveGroups);
402 ralloc_free(m->ActiveCounters);
403 ctx->Driver.DeletePerfMonitor(ctx, m);
404 } else {
405 /* "INVALID_VALUE error will be generated if any of the monitor IDs
406 * in the <monitors> parameter to DeletePerfMonitorsAMD do not
407 * reference a valid generated monitor ID."
408 */
409 _mesa_error(ctx, GL_INVALID_VALUE,
410 "glDeletePerfMonitorsAMD(invalid monitor)");
411 }
412 }
413 }
414
415 void GLAPIENTRY
_mesa_SelectPerfMonitorCountersAMD(GLuint monitor,GLboolean enable,GLuint group,GLint numCounters,GLuint * counterList)416 _mesa_SelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable,
417 GLuint group, GLint numCounters,
418 GLuint *counterList)
419 {
420 GET_CURRENT_CONTEXT(ctx);
421 int i;
422 struct gl_perf_monitor_object *m;
423 const struct gl_perf_monitor_group *group_obj;
424
425 m = lookup_monitor(ctx, monitor);
426
427 /* "INVALID_VALUE error will be generated if the <monitor> parameter to
428 * SelectPerfMonitorCountersAMD does not reference a monitor created by
429 * GenPerfMonitorsAMD."
430 */
431 if (m == NULL) {
432 _mesa_error(ctx, GL_INVALID_VALUE,
433 "glSelectPerfMonitorCountersAMD(invalid monitor)");
434 return;
435 }
436
437 group_obj = get_group(ctx, group);
438
439 /* "INVALID_VALUE error will be generated if the <group> parameter to
440 * GetPerfMonitorCountersAMD, GetPerfMonitorCounterStringAMD,
441 * GetPerfMonitorCounterStringAMD, GetPerfMonitorCounterInfoAMD, or
442 * SelectPerfMonitorCountersAMD does not reference a valid group ID."
443 */
444 if (group_obj == NULL) {
445 _mesa_error(ctx, GL_INVALID_VALUE,
446 "glSelectPerfMonitorCountersAMD(invalid group)");
447 return;
448 }
449
450 /* "INVALID_VALUE error will be generated if the <numCounters> parameter to
451 * SelectPerfMonitorCountersAMD is less than 0."
452 */
453 if (numCounters < 0) {
454 _mesa_error(ctx, GL_INVALID_VALUE,
455 "glSelectPerfMonitorCountersAMD(numCounters < 0)");
456 return;
457 }
458
459 /* "When SelectPerfMonitorCountersAMD is called on a monitor, any outstanding
460 * results for that monitor become invalidated and the result queries
461 * PERFMON_RESULT_SIZE_AMD and PERFMON_RESULT_AVAILABLE_AMD are reset to 0."
462 */
463 ctx->Driver.ResetPerfMonitor(ctx, m);
464
465 /* Sanity check the counter ID list. */
466 for (i = 0; i < numCounters; i++) {
467 if (counterList[i] >= group_obj->NumCounters) {
468 _mesa_error(ctx, GL_INVALID_VALUE,
469 "glSelectPerfMonitorCountersAMD(invalid counter ID)");
470 return;
471 }
472 }
473
474 if (enable) {
475 /* Enable the counters */
476 for (i = 0; i < numCounters; i++) {
477 if (!BITSET_TEST(m->ActiveCounters[group], counterList[i])) {
478 ++m->ActiveGroups[group];
479 BITSET_SET(m->ActiveCounters[group], counterList[i]);
480 }
481 }
482 } else {
483 /* Disable the counters */
484 for (i = 0; i < numCounters; i++) {
485 if (BITSET_TEST(m->ActiveCounters[group], counterList[i])) {
486 --m->ActiveGroups[group];
487 BITSET_CLEAR(m->ActiveCounters[group], counterList[i]);
488 }
489 }
490 }
491 }
492
493 void GLAPIENTRY
_mesa_BeginPerfMonitorAMD(GLuint monitor)494 _mesa_BeginPerfMonitorAMD(GLuint monitor)
495 {
496 GET_CURRENT_CONTEXT(ctx);
497
498 struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor);
499
500 if (m == NULL) {
501 _mesa_error(ctx, GL_INVALID_VALUE,
502 "glBeginPerfMonitorAMD(invalid monitor)");
503 return;
504 }
505
506 /* "INVALID_OPERATION error will be generated if BeginPerfMonitorAMD is
507 * called when a performance monitor is already active."
508 */
509 if (m->Active) {
510 _mesa_error(ctx, GL_INVALID_OPERATION,
511 "glBeginPerfMonitor(already active)");
512 return;
513 }
514
515 /* The driver is free to return false if it can't begin monitoring for
516 * any reason. This translates into an INVALID_OPERATION error.
517 */
518 if (ctx->Driver.BeginPerfMonitor(ctx, m)) {
519 m->Active = true;
520 m->Ended = false;
521 } else {
522 _mesa_error(ctx, GL_INVALID_OPERATION,
523 "glBeginPerfMonitor(driver unable to begin monitoring)");
524 }
525 }
526
527 void GLAPIENTRY
_mesa_EndPerfMonitorAMD(GLuint monitor)528 _mesa_EndPerfMonitorAMD(GLuint monitor)
529 {
530 GET_CURRENT_CONTEXT(ctx);
531
532 struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor);
533
534 if (m == NULL) {
535 _mesa_error(ctx, GL_INVALID_VALUE, "glEndPerfMonitorAMD(invalid monitor)");
536 return;
537 }
538
539 /* "INVALID_OPERATION error will be generated if EndPerfMonitorAMD is called
540 * when a performance monitor is not currently started."
541 */
542 if (!m->Active) {
543 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndPerfMonitor(not active)");
544 return;
545 }
546
547 ctx->Driver.EndPerfMonitor(ctx, m);
548
549 m->Active = false;
550 m->Ended = true;
551 }
552
553 /**
554 * Return the number of bytes needed to store a monitor's result.
555 */
556 static unsigned
perf_monitor_result_size(const struct gl_context * ctx,const struct gl_perf_monitor_object * m)557 perf_monitor_result_size(const struct gl_context *ctx,
558 const struct gl_perf_monitor_object *m)
559 {
560 unsigned group, counter;
561 unsigned size = 0;
562
563 for (group = 0; group < ctx->PerfMonitor.NumGroups; group++) {
564 const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[group];
565
566 BITSET_FOREACH_SET(counter, m->ActiveCounters[group], g->NumCounters) {
567 const struct gl_perf_monitor_counter *c = &g->Counters[counter];
568
569 size += sizeof(uint32_t); /* Group ID */
570 size += sizeof(uint32_t); /* Counter ID */
571 size += _mesa_perf_monitor_counter_size(c);
572 }
573 }
574 return size;
575 }
576
577 void GLAPIENTRY
_mesa_GetPerfMonitorCounterDataAMD(GLuint monitor,GLenum pname,GLsizei dataSize,GLuint * data,GLint * bytesWritten)578 _mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname,
579 GLsizei dataSize, GLuint *data,
580 GLint *bytesWritten)
581 {
582 GET_CURRENT_CONTEXT(ctx);
583
584 struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor);
585 bool result_available;
586
587 if (m == NULL) {
588 _mesa_error(ctx, GL_INVALID_VALUE,
589 "glGetPerfMonitorCounterDataAMD(invalid monitor)");
590 return;
591 }
592
593 /* "It is an INVALID_OPERATION error for <data> to be NULL." */
594 if (data == NULL) {
595 _mesa_error(ctx, GL_INVALID_OPERATION,
596 "glGetPerfMonitorCounterDataAMD(data == NULL)");
597 return;
598 }
599
600 /* We need at least enough room for a single value. */
601 if (dataSize < sizeof(GLuint)) {
602 if (bytesWritten != NULL)
603 *bytesWritten = 0;
604 return;
605 }
606
607 /* If the monitor has never ended, there is no result. */
608 result_available = m->Ended &&
609 ctx->Driver.IsPerfMonitorResultAvailable(ctx, m);
610
611 /* AMD appears to return 0 for all queries unless a result is available. */
612 if (!result_available) {
613 *data = 0;
614 if (bytesWritten != NULL)
615 *bytesWritten = sizeof(GLuint);
616 return;
617 }
618
619 switch (pname) {
620 case GL_PERFMON_RESULT_AVAILABLE_AMD:
621 *data = 1;
622 if (bytesWritten != NULL)
623 *bytesWritten = sizeof(GLuint);
624 break;
625 case GL_PERFMON_RESULT_SIZE_AMD:
626 *data = perf_monitor_result_size(ctx, m);
627 if (bytesWritten != NULL)
628 *bytesWritten = sizeof(GLuint);
629 break;
630 case GL_PERFMON_RESULT_AMD:
631 ctx->Driver.GetPerfMonitorResult(ctx, m, dataSize, data, bytesWritten);
632 break;
633 default:
634 _mesa_error(ctx, GL_INVALID_ENUM,
635 "glGetPerfMonitorCounterDataAMD(pname)");
636 }
637 }
638
639 /**
640 * Returns how many bytes a counter's value takes up.
641 */
642 unsigned
_mesa_perf_monitor_counter_size(const struct gl_perf_monitor_counter * c)643 _mesa_perf_monitor_counter_size(const struct gl_perf_monitor_counter *c)
644 {
645 switch (c->Type) {
646 case GL_FLOAT:
647 case GL_PERCENTAGE_AMD:
648 return sizeof(GLfloat);
649 case GL_UNSIGNED_INT:
650 return sizeof(GLuint);
651 case GL_UNSIGNED_INT64_AMD:
652 return sizeof(uint64_t);
653 default:
654 assert(!"Should not get here: invalid counter type");
655 return 0;
656 }
657 }
658