2 * Copyright © 2013 Intel Corporation
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:
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
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 DEALINGS
27 * Some AMD_performance_monitor tests that actually measure things.
30 #define __STDC_FORMAT_MACROS
32 #include "piglit-util-gl.h"
34 PIGLIT_GL_TEST_CONFIG_BEGIN
36 config
.supports_gl_compat_version
= 10;
37 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
;
39 PIGLIT_GL_TEST_CONFIG_END
41 /******************************************************************************/
44 * Get a list of group IDs.
47 get_groups(unsigned **groups
, int *num_groups
)
49 glGetPerfMonitorGroupsAMD(num_groups
, 0, NULL
);
50 *groups
= calloc(*num_groups
, sizeof(unsigned));
51 glGetPerfMonitorGroupsAMD(NULL
, *num_groups
, *groups
);
55 * Get a list of counter IDs in a given group.
58 get_counters(unsigned group
, unsigned **counters
, int *num_counters
,
59 int *max_active_counters
)
61 glGetPerfMonitorCountersAMD(group
, num_counters
, NULL
, 0, NULL
);
62 *counters
= calloc(*num_counters
, sizeof(unsigned));
63 glGetPerfMonitorCountersAMD(group
, NULL
, max_active_counters
,
64 *num_counters
, *counters
);
69 piglit_report_subtest_result(PIGLIT_FAIL, "%s", test_name); \
73 /******************************************************************************/
76 * Poll until PERFMON_RESULT_AVAILABLE returns 1; glFinish() on each iteration.
78 * Only loop for 5 times to guard against implementations that never finish.
81 wait_until_available(unsigned monitor
)
84 unsigned available
= 0;
85 for (i
= 0; !available
&& i
< 5; i
++) {
87 glGetPerfMonitorCounterDataAMD(monitor
,
88 GL_PERFMON_RESULT_AVAILABLE_AMD
,
89 sizeof(unsigned), &available
,
96 * Basic functional test: enable all the counters in the first group
97 * (up to the maximum that can be active at a time), begin monitoring,
98 * end monitoring, make sure results are available, sanity check the
99 * result size, and get the results.
102 test_basic_measurement(unsigned group
)
107 int max_active_counters
;
108 unsigned usable_counters
;
109 unsigned result_size
= 0;
110 GLsizei bytes_written
= 0;
116 const char *test_name
;
119 * Test #1: Basic Measurement.
121 * Enable all the counters in the first group (up to the maximum that
122 * can be active at a time), begin monitoring, end monitoring, make
123 * sure results are available, sanity check the result size, and get
126 test_name
= "basic measurement";
128 get_counters(group
, &counters
, &num_counters
,
129 &max_active_counters
);
130 verify(max_active_counters
>= 0);
131 verify(piglit_check_gl_error(GL_NO_ERROR
));
133 usable_counters
= MIN2(num_counters
, max_active_counters
);
135 glGenPerfMonitorsAMD(1, &monitor
);
136 verify(piglit_check_gl_error(GL_NO_ERROR
));
138 /* Enable counters 0 .. usable_counters from the list. */
139 glSelectPerfMonitorCountersAMD(monitor
, true, group
, usable_counters
,
141 verify(piglit_check_gl_error(GL_NO_ERROR
));
143 /* Start monitoring */
144 glBeginPerfMonitorAMD(monitor
);
145 verify(piglit_check_gl_error(GL_NO_ERROR
));
151 glEndPerfMonitorAMD(monitor
);
152 verify(piglit_check_gl_error(GL_NO_ERROR
));
154 /* Wait for the result to be available. */
155 verify(wait_until_available(monitor
));
156 verify(piglit_check_gl_error(GL_NO_ERROR
));
158 /* Get the result size. */
159 glGetPerfMonitorCounterDataAMD(monitor
, GL_PERFMON_RESULT_SIZE_AMD
,
160 sizeof(unsigned), &result_size
, NULL
);
161 verify(piglit_check_gl_error(GL_NO_ERROR
));
163 /* Make sure the size is in bytes. */
164 verify(result_size
% sizeof(unsigned) == 0);
166 /* The format is <Group ID, Group, Value>. The first two are
167 * uint32_ts. Value is either a float, uint32_t, or uint64_t.
168 * As a sanity check, make sure the result size is within
169 * reasonable limits. Don't bother checking the actual types
170 * since that's a bunch of work.
172 verify(result_size
>= 3 * sizeof(uint32_t) * usable_counters
)
173 verify(result_size
<=
174 (2 * sizeof(uint32_t) + sizeof(uint64_t)) * usable_counters
);
176 /* Get the results. */
177 data
= calloc(1, result_size
);
178 glGetPerfMonitorCounterDataAMD(monitor
, GL_PERFMON_RESULT_AMD
,
179 result_size
, data
, &bytes_written
);
181 verify(bytes_written
== result_size
);
183 piglit_report_subtest_result(PIGLIT_PASS
, "%s", test_name
);
186 * Test #2: Verify counter results against specified range.
188 test_name
= "counters in range";
190 while ((char *) p
< ((char *) data
) + bytes_written
) {
191 uint32_t group_id
= p
[0];
192 uint32_t counter_id
= p
[1];
196 float f
= ((float *) p
)[2];
199 GLenum counter_type
= GL_NONE
;
202 /* There's only one group, so it better match */
203 verify(group_id
== group
);
205 /* Getting the counter data also validates the counter ID
206 * without having to walk through the whole list of counters.
208 glGetPerfMonitorCounterInfoAMD(group_id
, counter_id
,
211 verify(piglit_check_gl_error(GL_NO_ERROR
));
213 glGetPerfMonitorCounterInfoAMD(group_id
, counter_id
,
214 GL_COUNTER_RANGE_AMD
,
216 verify(piglit_check_gl_error(GL_NO_ERROR
));
218 /* Make sure it falls within the proper range */
219 switch (counter_type
) {
220 case GL_UNSIGNED_INT
: {
221 uint32_t min
= ((uint32_t *) range
)[0];
222 uint32_t max
= ((uint32_t *) range
)[1];
227 case GL_UNSIGNED_INT64_AMD
: {
228 uint64_t u64
= ((uint64_t *) p
)[1];
229 verify(u64
>= range
[0]);
230 verify(u64
<= range
[1]);
233 case GL_PERCENTAGE_AMD
:
235 float min
= ((float *) range
)[0];
236 float max
= ((float *) range
)[1];
243 p
+= (counter_type
== GL_UNSIGNED_INT64_AMD
) ? 4 : 3;
245 verify(result_size
== ((char *) p
- (char *) data
));
247 piglit_report_subtest_result(PIGLIT_PASS
, "%s", test_name
);
252 * Test #3: Changing the set of active counters resets queries.
254 * "When SelectPerfMonitorCountersAMD is called on a monitor, any
255 * outstanding results for that monitor become invalidated and the
256 * result queries PERFMON_RESULT_SIZE_AMD and
257 * PERFMON_RESULT_AVAILABLE_AMD are reset to 0."
259 test_name
= "selecting counters resets queries";
261 /* Turn off the first counter. */
262 glSelectPerfMonitorCountersAMD(monitor
, false, group
, 1, counters
);
263 verify(piglit_check_gl_error(GL_NO_ERROR
));
265 /* Results should no longer be available. All queries should
269 glGetPerfMonitorCounterDataAMD(monitor
, GL_PERFMON_RESULT_AVAILABLE_AMD
,
270 sizeof(unsigned), &value
, NULL
);
271 verify(piglit_check_gl_error(GL_NO_ERROR
));
275 glGetPerfMonitorCounterDataAMD(monitor
, GL_PERFMON_RESULT_SIZE_AMD
,
276 sizeof(unsigned), &value
, NULL
);
277 verify(piglit_check_gl_error(GL_NO_ERROR
));
280 piglit_report_subtest_result(PIGLIT_PASS
, "%s", test_name
);
282 glDeletePerfMonitorsAMD(1, &monitor
);
287 * Make sure that calling SelectPerfMonitorCountersAMD on an active monitor
288 * is possible, resets active queries, and restarts monitoring (so it remains
291 * This is not actually specified, but matches the behavior of AMD's driver.
292 * Being an AMD extension, other implementations should probably match theirs.
295 test_change_counters_while_active(unsigned group
)
300 int max_active_counters
;
301 unsigned usable_counters
;
303 const char *test_name
= "change counters while active";
305 get_counters(group
, &counters
, &num_counters
,
306 &max_active_counters
);
307 verify(max_active_counters
>= 0);
308 verify(piglit_check_gl_error(GL_NO_ERROR
));
310 usable_counters
= MIN2(num_counters
, max_active_counters
);
312 if (usable_counters
== 0)
315 glGenPerfMonitorsAMD(1, &monitor
);
316 verify(piglit_check_gl_error(GL_NO_ERROR
));
318 /* Enable counters 0 .. usable_counters from the list. */
319 glSelectPerfMonitorCountersAMD(monitor
, true, group
, usable_counters
,
321 verify(piglit_check_gl_error(GL_NO_ERROR
));
323 /* Start monitoring */
324 glBeginPerfMonitorAMD(monitor
);
325 verify(piglit_check_gl_error(GL_NO_ERROR
));
327 /* Turn off the first counter. The specification is unclear whether
328 * or not this should be allowed while monitoring is active, but it
329 * apparently is (Catalyst 12.06 on a Radeon 3650).
331 glSelectPerfMonitorCountersAMD(monitor
, false, group
, 1, counters
);
332 verify(piglit_check_gl_error(GL_NO_ERROR
));
334 /* Verify that all queries have been reset to 0 */
336 glGetPerfMonitorCounterDataAMD(monitor
, GL_PERFMON_RESULT_AVAILABLE_AMD
,
337 sizeof(unsigned), &data
, NULL
);
338 verify(piglit_check_gl_error(GL_NO_ERROR
));
342 glGetPerfMonitorCounterDataAMD(monitor
, GL_PERFMON_RESULT_SIZE_AMD
,
343 sizeof(unsigned), &data
, NULL
);
344 verify(piglit_check_gl_error(GL_NO_ERROR
));
347 /* The spec doesn't explicitly mention whether or not monitoring
348 * is still active, but apparently it is.
350 glEndPerfMonitorAMD(monitor
);
351 verify(piglit_check_gl_error(GL_NO_ERROR
));
353 glDeletePerfMonitorsAMD(1, &monitor
);
354 verify(piglit_check_gl_error(GL_NO_ERROR
));
356 piglit_report_subtest_result(PIGLIT_PASS
, "%s", test_name
);
360 /******************************************************************************/
369 * The main test program.
372 piglit_init(int argc
, char **argv
)
377 piglit_require_extension("GL_AMD_performance_monitor");
379 /* Basic glGetPerfMonitorGroupsAMD() tests */
380 get_groups(&groups
, &num_groups
);
382 /* If there are no groups, the rest of the tests can't run. Bail. */
386 test_basic_measurement(groups
[0]);
387 test_change_counters_while_active(groups
[0]);