From e8c9d68d2d4277460f650c8e1093b904b56bbff0 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 22 Mar 2013 13:45:36 -0700 Subject: Add tests for the GL_AMD_performance_monitor extension. One of the challenging aspects of testing this extension is that it defines an implementation-specific set of groups and counters. Many of the tests here arbitrarily operate on the counters in the first group, while a few sanity check all counters in all groups. All tests pass on AMD's Catalyst 12.06 driver on a Radeon 3650, except for: test_number_of_groups_partial_array, test_delete_monitor_invalid, and test_get_counter_data_byte_size. I believe the first two are legitimate bugs in AMD's implementation, and the latter is a disagreement about the associativity of text within a paragraph. Still, these are minor details and I believe the tests are valid. v2: Actually set the test name for the second test. Signed-off-by: Kenneth Graunke --- tests/all.tests | 5 + tests/spec/CMakeLists.txt | 1 + .../spec/amd_performance_monitor/CMakeLists.gl.txt | 13 + tests/spec/amd_performance_monitor/CMakeLists.txt | 1 + tests/spec/amd_performance_monitor/api.c | 1080 ++++++++++++++++++++ tests/spec/amd_performance_monitor/measure.c | 388 +++++++ 6 files changed, 1488 insertions(+) create mode 100644 tests/spec/amd_performance_monitor/CMakeLists.gl.txt create mode 100644 tests/spec/amd_performance_monitor/CMakeLists.txt create mode 100644 tests/spec/amd_performance_monitor/api.c create mode 100644 tests/spec/amd_performance_monitor/measure.c diff --git a/tests/all.tests b/tests/all.tests index 7c9551f0..39fcb3e6 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -863,6 +863,11 @@ add_shader_test_dir(spec['glsl-es-3.00'], recursive=True) add_concurrent_test(spec['glsl-es-3.00']['execution'], 'varying-struct-centroid_gles3') +# AMD_performance_monitor +profile.test_list['AMD_performance_monitor/api'] = + PlainExecTest('amd_performance_monitor_api -auto') +profile.test_list['AMD_performance_monitor/measure'] = + PlainExecTest('amd_performance_monitor_measure -auto') # Group AMD_conservative_depth spec['AMD_conservative_depth'] = Group() diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt index 18b1d37b..a1492cc1 100644 --- a/tests/spec/CMakeLists.txt +++ b/tests/spec/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory (amd_performance_monitor) add_subdirectory (arb_color_buffer_float) add_subdirectory (arb_debug_output) add_subdirectory (arb_draw_instanced) diff --git a/tests/spec/amd_performance_monitor/CMakeLists.gl.txt b/tests/spec/amd_performance_monitor/CMakeLists.gl.txt new file mode 100644 index 00000000..5ddc12dd --- /dev/null +++ b/tests/spec/amd_performance_monitor/CMakeLists.gl.txt @@ -0,0 +1,13 @@ +include_directories( + ${GLEXT_INCLUDE_DIR} + ${OPENGL_INCLUDE_PATH} +) + +link_libraries ( + piglitutil_${piglit_target_api} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +piglit_add_executable (amd_performance_monitor_api api.c) +piglit_add_executable (amd_performance_monitor_measure measure.c) diff --git a/tests/spec/amd_performance_monitor/CMakeLists.txt b/tests/spec/amd_performance_monitor/CMakeLists.txt new file mode 100644 index 00000000..144a306f --- /dev/null +++ b/tests/spec/amd_performance_monitor/CMakeLists.txt @@ -0,0 +1 @@ +piglit_include_target_api() diff --git a/tests/spec/amd_performance_monitor/api.c b/tests/spec/amd_performance_monitor/api.c new file mode 100644 index 00000000..81a26414 --- /dev/null +++ b/tests/spec/amd_performance_monitor/api.c @@ -0,0 +1,1080 @@ +/* + * Copyright © 2013 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 api.c + * + * Basic AMD_performance_monitor infrastructure tests. These test the + * mechanism to retrieve counter and group information, string processing, + * and various error conditions. They do not actually activate monitoring. + */ + +#define __STDC_FORMAT_MACROS +#include +#include "piglit-util-gl-common.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 10; + config.window_visual = PIGLIT_GL_VISUAL_RGB; + +PIGLIT_GL_TEST_CONFIG_END + +/******************************************************************************/ + +/** + * Get a list of group IDs. + */ +static void +get_groups(unsigned **groups, int *num_groups) +{ + glGetPerfMonitorGroupsAMD(num_groups, 0, NULL); + *groups = calloc(*num_groups, sizeof(unsigned)); + glGetPerfMonitorGroupsAMD(NULL, *num_groups, *groups); +} + +/** + * Get a list of counter IDs in a given group. + */ +static void +get_counters(unsigned group, unsigned **counters, int *num_counters) +{ + glGetPerfMonitorCountersAMD(group, num_counters, NULL, 0, NULL); + *counters = calloc(*num_counters, sizeof(unsigned)); + glGetPerfMonitorCountersAMD(group, NULL, NULL, *num_counters, *counters); +} + +/** + * Return true if x is in xs. + */ +static bool +in_list(int x, unsigned *xs, int elts) +{ + int i; + for (i = 0; i < elts; i++) { + if (x == xs[i]) + return true; + } + return false; +} + +/** + * Find an invalid group ID. + */ +static unsigned +find_invalid_group(unsigned *groups, int num_groups) +{ + unsigned invalid_group = ~0; + + /* Most implementations probably use small consecutive integers, so + * start at ~0 and work backwards. Hopefully we shouldn't loop. + */ + while (in_list(invalid_group, groups, num_groups)) + --invalid_group; + + return invalid_group; +} + +/** + * Find an invalid counter ID. + */ +static unsigned +find_invalid_counter(unsigned *counters, int num_counters) +{ + unsigned invalid_counter = ~0; + + /* Most implementations probably use small consecutive integers, so + * start at ~0 and work backwards. Hopefully we shouldn't loop. + */ + while (in_list(invalid_counter, counters, num_counters)) + --invalid_counter; + + return invalid_counter; +} + +#define report(pass) \ + piglit_report_subtest_result((pass) ? PIGLIT_PASS : PIGLIT_FAIL, __func__); \ + return + +/******************************************************************************/ + +/** + * Call glGetPerfMonitorGroupsAMD() with a NULL numGroups pointer. + * + * Verify that it doesn't attempt to write the number of groups and crash. + */ +static void +test_number_of_groups_null_num_groups_pointer(void) +{ + glGetPerfMonitorGroupsAMD(NULL, 0, NULL); + report(piglit_check_gl_error(GL_NO_ERROR)); +} + + +/** + * Call glGetPerfMonitorGroupsAMD() with NULL for groups but non-zero groupSize. + * + * Verify that it returns the number of groups but doesn't try to write any + * group IDs and crash. + */ +static void +test_number_of_groups_null_groups_pointer(void) +{ + bool pass = true; + int num_groups = -1; + + glGetPerfMonitorGroupsAMD(&num_groups, 777, NULL); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + pass = num_groups >= 0 && pass; + report(pass); +} + +/** + * Call glGetPerfMonitorGroupsAMD() with zero for groupSize. + * + * Verify that it doesn't write any group IDs. + */ +static void +test_number_of_groups_zero_size_array(void) +{ + bool pass = true; + unsigned groups[2] = {0xd0d0d0d0, 0xd1d1d1d1}; + int num_groups = -1; + + glGetPerfMonitorGroupsAMD(&num_groups, 0, groups); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + + /* num_groups must have changed */ + pass = num_groups >= 0 && pass; + + /* The groups array should not have changed. */ + pass = groups[0] == 0xd0d0d0d0 && pass; + pass = groups[1] == 0xd1d1d1d1 && pass; + report(pass); +} + +/** + * Call glGetPerfMonitorGroupsAMD() with a groups array bigger than groupSize. + * + * Verify that it fills the correct number of array slots with group IDs. + */ +static void +test_number_of_groups_partial_array(void) +{ + bool pass = true; + unsigned groups[] = {0xdddddddd, 0xdddddddd, 0xdddddddd, 0xdddddddd}; + + /* Artificially low array size */ + const int groups_array_size = 2; + int num_groups = -1; + int i; + + /* This should return the number of groups. It should not attempt to + * write any groups since the pointer is NULL. + */ + glGetPerfMonitorGroupsAMD(&num_groups, groups_array_size, groups); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + + /* num_groups must have changed */ + pass = num_groups >= 0 && pass; + + /* The first few elements should have changed. */ + for (i = 0; i < MIN2(num_groups, groups_array_size); i++) { + pass = groups[i] != 0xdddddddd && pass; + } + + /* Catalyst 12.6 on a Radeon 3650 appears to have a bug where this + * returns 3 elements instead of 2. According to the spec, + * "The number of entries that will be returned in is + * determined by ." + * + * Technically, it does not say that N elements will be returned if + * groupSize is N, but that's the only reasonable assumption. + */ + + /* The rest should remain untouched. */ + for (; i < ARRAY_SIZE(groups); i++) { + pass = groups[i] == 0xdddddddd && pass; + } + + report(pass); +} + +/******************************************************************************/ + +/** + * Call glGetPerfMonitorCountersAMD() with an invalid group ID. + * + * Verify that it produces INVALID_VALUE. + */ +static void +test_get_counters_invalid_group(unsigned invalid_group) +{ + glGetPerfMonitorCountersAMD(invalid_group, NULL, NULL, 0, NULL); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Call glGetPerfMonitorCountersAMD() with a bunch of NULL pointers. + * + * Verify that it doesn't crash attempting to write numCounters, + * maxActiveCounters, or the counters list. + */ +static void +test_get_counters_null_pointers(unsigned valid_group) +{ + glGetPerfMonitorCountersAMD(valid_group, NULL, NULL, 0, NULL); + report(piglit_check_gl_error(GL_NO_ERROR)); +} + +/** + * Call glGetPerfMonitorCountersAMD() with NULL for the array but non-zero size. + * + * Verify that it returns the number of groups but doesn't try to write any + * group IDs and crash. + */ +static void +test_get_counters_null_pointer_non_zero_size(unsigned valid_group) +{ + glGetPerfMonitorCountersAMD(valid_group, NULL, NULL, 777, NULL); + report(piglit_check_gl_error(GL_NO_ERROR)); +} + +/** + * Call glGetPerfMonitorCountersAMD() with zero for countersSize. + * + * Verify that it doesn't write any IDs, but does return other data. + */ +static void +test_get_counters_zero_size_array(unsigned valid_group) +{ + bool pass = true; + unsigned counters[2] = {0xd0d0d0d0, 0xd1d1d1d1}; + int num_counters = -1; + int max_active_counters = -1; + + glGetPerfMonitorCountersAMD(valid_group, &num_counters, + &max_active_counters, + 0, counters); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + + /* Expect a positive number of counters. */ + pass = num_counters >= 0 && pass; + + /* Expect a positive maximum active counters. */ + pass = max_active_counters >= 0 && pass; + + /* The counters array should not have changed. */ + pass = counters[0] == 0xd0d0d0d0 && pass; + pass = counters[1] == 0xd1d1d1d1 && pass; + report(pass); +} + +/** + * Call glGetPerfMonitorGroupsAMD() with a groups array bigger than groupSize. + * + * Verify that it fills the correct number of array slots with group IDs. + */ +static void +test_get_counters_partial_array(unsigned valid_group) +{ + bool pass = true; + unsigned counters[] = {0xdddddddd, 0xdddddddd, 0xdddddddd, 0xdddddddd}; + + /* Artificially low array size */ + const int counters_array_size = 2; + int num_counters = -1; + int i; + + /* This should return the number of groups. It should not attempt to + * write any groups since the pointer is NULL. + */ + glGetPerfMonitorCountersAMD(valid_group, &num_counters, NULL, + counters_array_size, counters); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + + /* num_counters must have changed */ + pass = num_counters >= 0 && pass; + + /* The first few elements should have changed. */ + for (i = 0; i < MIN2(num_counters, counters_array_size); i++) { + pass = counters[i] != 0xdddddddd && pass; + } + + /* The rest should remain untouched. */ + for (; i < ARRAY_SIZE(counters); i++) { + pass = counters[i] == 0xdddddddd && pass; + } + + report(pass); +} + +/******************************************************************************/ + +/** + * Call glGetPerfMonitorGroupStringAMD() with an invalid group ID. + * + * Verify that it produces INVALID_VALUE. + */ +static void +test_group_string_invalid_group(unsigned invalid_group) +{ + glGetPerfMonitorGroupStringAMD(invalid_group, 0, NULL, NULL); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Call glGetPerfMonitorGroupStringAMD() with a NULL length pointer. + * + * Verify that it doesn't crash. + */ +static void +test_group_string_null_length(unsigned valid_group) +{ + glGetPerfMonitorGroupStringAMD(valid_group, 0, NULL, NULL); + report(piglit_check_gl_error(GL_NO_ERROR)); +} + +/** + * Call glGetPerfMonitorGroupStringAMD() with a single character buffer. + * + * Verify that length is correct and no buffer overflows occur. + */ +static void +test_group_string_single_character_buffer(unsigned valid_group) +{ + bool pass = true; + char name[3] = "```"; + GLsizei length = 0xd0d0d0d0; + + glGetPerfMonitorGroupStringAMD(valid_group, 1, &length, name); + pass = piglit_check_gl_error(GL_NO_ERROR); + + /* Verify buffer contents: only the first character should change. */ + pass = name[0] != '`' && pass; + pass = name[1] == '`' && pass; + pass = name[2] == '`' && pass; + + /* length is the number of characters written excluding the null + * terminator. + */ + if (name[0] == '\0') { + pass = length == 0 && pass; + } else { + /* AMD Catalyst 12.06 (Radeon 3650) does not write a null + * terminator. Instead, it writes the first part of the name. + */ + pass = length == 1 && pass; + } + + report(pass); +} + +/** + * Call glGetPerfMonitorGroupStringAMD() with a small buffer. + * + * Verify that a name is returned, length is valid, and no overflows occur. + */ +static void +test_group_string_small_buffer(unsigned valid_group) +{ + bool pass = true; + char name[3] = "```"; + GLsizei length = 0xd0d0d0d0; + int i; + + glGetPerfMonitorGroupStringAMD(valid_group, 3, &length, name); + + pass = length <= 3 && pass; + + /* Verify buffer contents: accept no null terminator. */ + for (i = 0; i < length; i++) + pass = name[i] != '`' && pass; + + if (length < 3) { + pass = name[length] == '\0'; + for (i = length + 1; i < 3; i++) + pass = name[i] == '`' && pass; + } + + report(pass); +} + +/** + * Call glGetPerfMonitorGroupStringAMD() with an appropriately sized buffer. + * + * Verify that a name is returned, length is valid, and no overflows occur. + */ +static void +test_group_string_normal_buffer(unsigned valid_group) +{ + bool pass = true; + char *name; + GLsizei length = 0xd0d0d0d0; + int i; + + /* Get the length; bail if unwritten to avoid huge allocations. */ + glGetPerfMonitorGroupStringAMD(valid_group, 0, &length, NULL); + pass = pass && piglit_check_gl_error(GL_NO_ERROR); + if (length == 0xd0d0d0d0) + report(false); + + name = malloc(length + 1); + assert(name != NULL); + + /* Fill the buffer with a known character (` marks) */ + memset(name, '`', length + 1); + + /* Get the name; everything will fit. */ + glGetPerfMonitorGroupStringAMD(valid_group, length + 1, NULL, name); + pass = pass && piglit_check_gl_error(GL_NO_ERROR); + + /* Indexes in the interval [0, length) must have been written, or + * else length is wrong. + */ + for (i = 0; i < length; i++) + pass = name[i] != '`' && pass; + + /* The last character must be the null terminator. */ + pass = name[length] == '\0' && pass; + + report(pass); +} + +/******************************************************************************/ + +/** + * Call glGetPerfMonitorCounterStringAMD() with an invalid group ID. + * + * Verify that it produces INVALID_VALUE. + */ +static void +test_counter_string_invalid_group(unsigned invalid_group) +{ + glGetPerfMonitorCounterStringAMD(invalid_group, 0, 0, NULL, NULL); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Call glGetPerfMonitorCounterStringAMD() with an invalid counter ID. + * + * Verify that it produces INVALID_VALUE. + */ +static void +test_counter_string_invalid_counter(unsigned group, unsigned invalid_counter) +{ + glGetPerfMonitorCounterStringAMD(group, invalid_counter, 0, NULL, NULL); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Call glGetPerfMonitorCounterStringAMD() with a NULL length pointer. + * + * Verify that it doesn't crash. + */ +static void +test_counter_string_null_length(unsigned group, unsigned counter) +{ + glGetPerfMonitorCounterStringAMD(group, counter, 0, NULL, NULL); + report(piglit_check_gl_error(GL_NO_ERROR)); +} + +/** + * Call glGetPerfMonitorCounterStringAMD() with a single character buffer. + * + * Verify that length is correct and no buffer overflows occur. + */ +static void +test_counter_string_single_character_buffer(unsigned group, unsigned counter) +{ + bool pass = true; + char name[3] = "```"; + GLsizei length = 0xd0d0d0d0; + + glGetPerfMonitorCounterStringAMD(group, counter, 1, &length, name); + pass = piglit_check_gl_error(GL_NO_ERROR); + + /* Verify buffer contents */ + pass = name[0] != '`' && pass; + pass = name[1] == '`' && pass; + pass = name[2] == '`' && pass; + + /* length is the number of characters written excluding the null + * terminator. + */ + if (name[0] == '\0') { + pass = length == 0 && pass; + } else { + /* AMD Catalyst 12.06 (Radeon 3650) does not write a null + * terminator. Instead, it writes the first part of the name. + */ + pass = length == 1 && pass; + } + + report(pass); +} + +/** + * Call glGetPerfMonitorCounterStringAMD() with a small buffer. + * + * Verify that a name is returned, length is valid, and no overflows occur. + */ +static void +test_counter_string_small_buffer(unsigned group, unsigned counter) +{ + bool pass = true; + char name[3] = "```"; + GLsizei length = 0xd0d0d0d0; + int i; + + glGetPerfMonitorCounterStringAMD(group, counter, 3, &length, name); + + pass = length <= 3 && pass; + + /* Verify buffer contents: accept no null terminator. */ + for (i = 0; i < length; i++) + pass = name[i] != '`' && pass; + + if (length < 3) { + pass = name[length] == '\0'; + for (i = length + 1; i < 3; i++) + pass = name[i] == '`' && pass; + } + + report(pass); +} + +/** + * Call glGetPerfMonitorCounterStringAMD() with an appropriately sized buffer. + * + * Verify that a name is returned, length is valid, and no overflows occur. + */ +static void +test_counter_string_normal_buffer(unsigned group, unsigned counter) +{ + bool pass = true; + char *name; + GLsizei length = 0xd0d0d0d0; + int i; + + /* Get the length; bail if unwritten to avoid huge allocations. */ + glGetPerfMonitorCounterStringAMD(group, counter, 0, &length, NULL); + pass = pass && piglit_check_gl_error(GL_NO_ERROR); + if (length == 0xd0d0d0d0) + report(false); + + name = malloc(length + 1); + assert(name != NULL); + + /* Fill the buffer with a known character (` marks) */ + memset(name, '`', length + 1); + + /* Get the name; everything will fit. */ + glGetPerfMonitorCounterStringAMD(group, counter, length + 1, NULL, name); + pass = pass && piglit_check_gl_error(GL_NO_ERROR); + + /* Indexes in the interval [0, length) must have been written, or + * else length is wrong. + */ + for (i = 0; i < length; i++) + pass = name[i] != '`' && pass; + + /* The last character must be the null terminator. */ + pass = name[length] == '\0' && pass; + + report(pass); +} + +/******************************************************************************/ + +/** + * Call glGetPerfMonitorCounterInfoAMD() with an invalid group ID. + * + * Verify that it produces INVALID_VALUE. + */ +static void +test_counter_info_invalid_group(unsigned invalid_group) +{ + GLenum type; + glGetPerfMonitorCounterInfoAMD(invalid_group, 0, GL_COUNTER_TYPE_AMD, + &type); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Call glGetPerfMonitorCounterInfoAMD() with an invalid counter ID. + * + * Verify that it produces INVALID_VALUE. + */ +static void +test_counter_info_invalid_counter(unsigned group, unsigned invalid_counter) +{ + GLenum type; + glGetPerfMonitorCounterInfoAMD(group, invalid_counter, + GL_COUNTER_TYPE_AMD, &type); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Call glGetPerfMonitorCounterInfoAMD() on every group/counter and verify that: + * - All counters must have a valid type. + * - Percentage counters must have a range of [0.0f, 100.0f] + * - Counter ranges should return a minimum strictly less than the maximum. + * - The counter range query doesn't return too much data. + */ +static void +test_counter_info(unsigned *groups, int num_groups) +{ + int i; + int j; + + for (i = 0; i < num_groups; i++) { + unsigned *counters; + int num_counters; + get_counters(groups[i], &counters, &num_counters); + + for (j = 0; j < num_counters; j++) { + GLenum type = GL_NONE; + uint64_t data[3]; + uint64_t min_u, max_u; + float min_f, max_f; + uint32_t unchanged; + bool is_unsigned = false; + + glGetPerfMonitorCounterInfoAMD(groups[i], counters[j], + GL_COUNTER_TYPE_AMD, + &type); + + /* Get the range */ + memset(data, 0xff, sizeof(uint64_t) * 3); + glGetPerfMonitorCounterInfoAMD(groups[i], counters[j], + GL_COUNTER_RANGE_AMD, + data); + + /* Validate the type and use it to interpret the + * minimum/maximum information. + */ + switch (type) { + case GL_UNSIGNED_INT: + min_u = ((uint32_t *) data)[0]; + max_u = ((uint32_t *) data)[1]; + unchanged = ((uint32_t *) data)[2]; + is_unsigned = true; + break; + case GL_UNSIGNED_INT64_AMD: + min_u = data[0]; + max_u = data[1]; + unchanged = ((uint32_t *) data)[4]; + is_unsigned = true; + break; + case GL_PERCENTAGE_AMD: + case GL_FLOAT: + min_f = ((float *) data)[0]; + max_f = ((float *) data)[1]; + unchanged = ((uint32_t *) data)[2]; + break; + default: + printf("Group %u/Counter %u has an invalid type: %x\n", groups[i], counters[j], type); + report(false); + } + + /* Make sure it didn't write too much data. */ + if (unchanged != 0xffffffff) { + printf("COUNTER_RANGE_AMD query for group %u/Counter %u wrote too much data to the buffer.\n", groups[i], counters[j]); + report(false); + } + + /* "If type value returned is PERCENTAGE_AMD, then this + * describes a float value that is in the range [0.0 .. + * 100.0]." So we can check this. + */ + if (type == GL_PERCENTAGE_AMD) { + if (min_f != 0.0f || max_f != 100.0f) { + printf("Group %u/Counter %u's minimum (%f) and maximum (%f) must be 0.0f and 100.0f, respectively.\n", groups[i], counters[j], min_f, max_f); + report(false); + } + } else if (is_unsigned) { + /* The spec doesn't explicitly state it, but it + * makes sense for the minimum to be strictly + * less than the maximum. Do a service to + * driver authors and validate that. + */ + if (min_u >= max_u) { + printf("Group %u/Counter %u's minimum (%" PRIu64 ") is >= the maximum (%" PRIu64 ").\n", groups[i], counters[j], min_u, max_u); + report(false); + } + } else if (type == GL_FLOAT) { + if (min_f >= max_f) { + printf("Group %u/Counter %u's minimum (%f) is >= the maximum (%f).\n", groups[i], counters[j], min_f, max_f); + report(false); + } + } + } + + free(counters); + } + report(true); +} + +/******************************************************************************/ + + +/** + * Call glBeginPerfMonitorAMD() on an invalid monitor ID. + * (Should be run before any Gen tests to ensure this ID is invalid.) + * + * XXX: This isn't actually specified, but it seems like it ought to be. + */ +void +test_begin_invalid_monitor(void) +{ + glBeginPerfMonitorAMD(777); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Call glEndPerfMonitorAMD() on an invalid monitor ID. + * (Should be run before any Gen tests to ensure this ID is invalid.) + * + * XXX: This isn't actually specified, but it seems like it ought to be. + * + * AMD Catalyst 12.6 (Radeon 3650) instead produces INVALID_OPERATION, + * presumably because the (invalid) monitor hasn't been started. (See + * test_end_without_begin.) So we allow either here. + */ +void +test_end_invalid_monitor(void) +{ + GLenum error; + glEndPerfMonitorAMD(777); + error = glGetError(); + report(error == GL_INVALID_VALUE || error == GL_INVALID_OPERATION); +} + +/** + * Call glGetPerfMonitorCounterDataAMD() with an invalid monitor ID. + * + * XXX: This isn't actually specified, but it seems like it ought to be. + */ +static void +test_get_counter_data_invalid_monitor(void) +{ + unsigned value; + glGetPerfMonitorCounterDataAMD(777, GL_PERFMON_RESULT_AVAILABLE_AMD, + 0, &value, NULL); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Call glSelectPerfMonitorCountersAMD() with an invalid monitor ID. + * + * "If is not a valid monitor created by GenPerfMonitorsAMD, then + * INVALID_VALUE will be generated." + */ +static void +test_select_counters_invalid_monitor(void) +{ + unsigned junk; + glSelectPerfMonitorCountersAMD(777, false, 0, 0, &junk); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Call glDeletePerfMonitorsAMD() on an invalid monitor ID. + * (Should be run before any Gen tests to ensure this ID is invalid.) + * + * "If a monitor ID in the list does not reference a previously + * generated performance monitor, an INVALID_VALUE error is generated." + * + * AMD Catalyst 12.6 (Radeon 3650) fails this test, producing NO_ERROR. + */ +static void +test_delete_monitor_invalid(void) +{ + unsigned monitor = 777; + glDeletePerfMonitorsAMD(1, &monitor); + report(piglit_check_gl_error(GL_INVALID_VALUE)); +} + +/** + * Mean tests for glGetPerfMonitorCounterDataAMD()'s data return mechanism. + * + * AMD Catalyst 12.6 (Radeon 3650) fails this test. It does not set + * bytes_written, yet writes 0 for each of these queries. It apparently + * interprets these fields as only relevant to the PERFMON_RESULT_AMD query. + */ +static void +test_get_counter_data_byte_size(void) +{ + bool pass = true; + unsigned monitor; + unsigned value; + GLsizei bytes_written; + + glGenPerfMonitorsAMD(1, &monitor); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + + /* "It is an INVALID_OPERATION error far to be NULL." */ + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD, + 0, NULL, NULL); + pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass; + + /* "The argument specifies the number of bytes available in + * the buffer for writing." + * + * It would be easy to accidentally treat this as 4-byte units, so + * be mean and try < sizeof(int) sizes. + */ + + /* dataSize = 0: Nothing should be written. */ + value = bytes_written = 0xd0d0d0d0; + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD, + 0, &value, &bytes_written); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + pass = value == 0xd0d0d0d0 && pass; + pass = bytes_written == 0 && pass; + + /* dataSize = 1: Unclear. Accept nothing or 1 byte written. */ + value = bytes_written = 0xd0d0d0d0; + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD, + 1, &value, &bytes_written); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + pass = value == 0xd0d0d0d0 && pass; + if (bytes_written == 1) { + pass = value == 0xd0d0d000 && pass; + } else if (bytes_written == 0) { + pass = value == 0xd0d0d0d0 && pass; + } else { + pass = false; + } + + glDeletePerfMonitorsAMD(1, &monitor); + report(pass); +} + +static void +test_gen_initial_state(void) +{ + bool pass = true; + unsigned monitor; + unsigned value; + + glGenPerfMonitorsAMD(1, &monitor); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + + /* "The value of the PERFMON_RESULT_AVAILABLE_AMD, PERMON_RESULT_AMD, + * and PERFMON_RESULT_SIZE queries will all initially be 0." + */ + value = 0xd0d0d0d0; + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD, + 4, &value, NULL); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + pass = value == 0 && pass; + + /* AMD Catalyst 12.6 (Radeon 3650) actually does write 0 for the + * PERFMON_RESULT query even though it isn't available. This + * matches the spec, but is strange. + */ + value = 0xd0d0d0d0; + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AMD, + 4, &value, NULL); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + pass = value == 0 && pass; + + value = 0xd0d0d0d0; + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD, + 4, &value, NULL); + pass = piglit_check_gl_error(GL_NO_ERROR) && pass; + pass = value == 0 && pass; + + glDeletePerfMonitorsAMD(1, &monitor); + report(pass); +} + +/** + * "INVALID_OPERATION error will be generated if EndPerfMonitorAMD is + * called when a performance monitor is not currently started." + */ +void +test_end_without_begin(void) +{ + unsigned monitor; + glGenPerfMonitorsAMD(1, &monitor); + glEndPerfMonitorAMD(monitor); + glDeletePerfMonitorsAMD(1, &monitor); + report(piglit_check_gl_error(GL_INVALID_OPERATION)); +} + +/** + * "INVALID_OPERATION error will be generated if BeginPerfMonitorAMD is + * called when a performance monitor is already active." + */ +void +test_double_begin(void) +{ + GLenum error; + bool pass; + unsigned monitor; + glGenPerfMonitorsAMD(1, &monitor); + glBeginPerfMonitorAMD(monitor); + + error = glGetError(); + if (error != GL_NO_ERROR) { + glDeletePerfMonitorsAMD(1, &monitor); + /* Monitoring couldn't start for some reason; bail. */ + if (error == GL_INVALID_OPERATION) + return; + /* We weren't expecting this other error. */ + report(false); + } + + /* Double begin */ + glBeginPerfMonitorAMD(monitor); + pass = piglit_check_gl_error(GL_INVALID_OPERATION); + + glDeletePerfMonitorsAMD(1, &monitor); + report(pass); +} + +/******************************************************************************/ + +/** + * Call glSelectPerfMonitorCountersAMD() with an invalid group ID. + * + * "If is not a valid group, the INVALID_VALUE error will be generated." + */ +static void +test_select_counters_invalid_group(unsigned invalid_group) +{ + unsigned monitor; + unsigned junk; + bool pass; + glGenPerfMonitorsAMD(1, &monitor); + glSelectPerfMonitorCountersAMD(monitor, false, invalid_group, 0, &junk); + pass = piglit_check_gl_error(GL_INVALID_VALUE); + glDeletePerfMonitorsAMD(1, &monitor); + report(pass); +} + + +/** + * Call glSelectPerfMonitorCountersAMD() with numCounters < 0. + * + * "If is less than 0, an INVALID_VALUE error will be generated." + */ +static void +test_select_counters_invalid_num_counters(unsigned group) +{ + unsigned monitor; + unsigned junk; + bool pass; + glGenPerfMonitorsAMD(1, &monitor); + glSelectPerfMonitorCountersAMD(monitor, false, group, -1, &junk); + pass = piglit_check_gl_error(GL_INVALID_VALUE); + glDeletePerfMonitorsAMD(1, &monitor); + report(pass); +} + +/******************************************************************************/ + +enum piglit_result +piglit_display(void) +{ + return PIGLIT_FAIL; +} + +/** + * The main test program. + */ +void +piglit_init(int argc, char **argv) +{ + unsigned *groups; + int num_groups; + unsigned *g0_counters; + int num_g0_counters; + unsigned invalid_group; + unsigned invalid_counter; + + piglit_require_extension("GL_AMD_performance_monitor"); + + /* Basic glGetPerfMonitorGroupsAMD() tests */ + test_number_of_groups_null_num_groups_pointer(); + test_number_of_groups_null_groups_pointer(); + test_number_of_groups_zero_size_array(); + test_number_of_groups_partial_array(); + + get_groups(&groups, &num_groups); + invalid_group = find_invalid_group(groups, num_groups); + + test_get_counters_invalid_group(invalid_group); + test_group_string_invalid_group(invalid_group); + test_counter_string_invalid_group(invalid_group); + test_counter_info_invalid_group(invalid_group); + + test_begin_invalid_monitor(); + test_end_invalid_monitor(); + test_delete_monitor_invalid(); + test_get_counter_data_invalid_monitor(); + test_select_counters_invalid_monitor(); + test_get_counter_data_byte_size(); + test_gen_initial_state(); + test_end_without_begin(); + test_double_begin(); + + test_select_counters_invalid_group(invalid_group); + + /* If there are no groups, the rest of the tests can't run. Bail. */ + if (num_groups == 0) + exit(0); + + test_get_counters_null_pointers(groups[0]); + test_get_counters_null_pointer_non_zero_size(groups[0]); + test_get_counters_zero_size_array(groups[0]); + test_get_counters_partial_array(groups[0]); + test_group_string_null_length(groups[0]); + test_group_string_single_character_buffer(groups[0]); + test_group_string_small_buffer(groups[0]); + test_group_string_normal_buffer(groups[0]); + + test_counter_info(groups, num_groups); + + test_select_counters_invalid_num_counters(groups[0]); + + get_counters(groups[0], &g0_counters, &num_g0_counters); + invalid_counter = find_invalid_counter(g0_counters, num_g0_counters); + + test_counter_string_invalid_counter(groups[0], invalid_counter); + test_counter_info_invalid_counter(groups[0], invalid_counter); + + /* If there are no counters, the rest of the tests can't run. Bail. */ + if (num_g0_counters == 0) + exit(0); + + test_counter_string_null_length(groups[0], g0_counters[0]); + test_counter_string_single_character_buffer(groups[0], g0_counters[0]); + test_counter_string_small_buffer(groups[0], g0_counters[0]); + test_counter_string_normal_buffer(groups[0], g0_counters[0]); + + exit(0); +} diff --git a/tests/spec/amd_performance_monitor/measure.c b/tests/spec/amd_performance_monitor/measure.c new file mode 100644 index 00000000..bc39c846 --- /dev/null +++ b/tests/spec/amd_performance_monitor/measure.c @@ -0,0 +1,388 @@ +/* + * Copyright © 2013 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 measure.c + * + * Some AMD_performance_monitor tests that actually measure things. + */ + +#define __STDC_FORMAT_MACROS +#include +#include "piglit-util-gl-common.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 10; + config.window_visual = PIGLIT_GL_VISUAL_RGB; + +PIGLIT_GL_TEST_CONFIG_END + +/******************************************************************************/ + +/** + * Get a list of group IDs. + */ +static void +get_groups(unsigned **groups, int *num_groups) +{ + glGetPerfMonitorGroupsAMD(num_groups, 0, NULL); + *groups = calloc(*num_groups, sizeof(unsigned)); + glGetPerfMonitorGroupsAMD(NULL, *num_groups, *groups); +} + +/** + * Get a list of counter IDs in a given group. + */ +static void +get_counters(unsigned group, unsigned **counters, int *num_counters, + int *max_active_counters) +{ + glGetPerfMonitorCountersAMD(group, num_counters, NULL, 0, NULL); + *counters = calloc(*num_counters, sizeof(unsigned)); + glGetPerfMonitorCountersAMD(group, NULL, max_active_counters, + *num_counters, *counters); +} + +#define verify(x) \ + if (!(x)) { \ + piglit_report_subtest_result(PIGLIT_FAIL, test_name); \ + return; \ + } + +/******************************************************************************/ + +/** + * Poll until PERFMON_RESULT_AVAILABLE returns 1; glFinish() on each iteration. + * + * Only loop for 5 times to guard against implementations that never finish. + */ +static bool +wait_until_available(unsigned monitor) +{ + int i; + unsigned available = 0; + for (i = 0; !available && i < 5; i++) { + glFinish(); + glGetPerfMonitorCounterDataAMD(monitor, + GL_PERFMON_RESULT_AVAILABLE_AMD, + sizeof(unsigned), &available, + NULL); + } + return available; +} + +/** + * Basic functional test: enable all the counters in the first group + * (up to the maximum that can be active at a time), begin monitoring, + * end monitoring, make sure results are available, sanity check the + * result size, and get the results. + */ +static void +test_basic_measurement(unsigned group) +{ + unsigned monitor; + unsigned *counters; + int num_counters; + int max_active_counters; + unsigned usable_counters; + unsigned result_size = 0; + GLsizei bytes_written = 0; + unsigned *data; + + uint32_t *p; + unsigned value; + + const char *test_name; + + /** + * Test #1: Basic Measurement. + * + * Enable all the counters in the first group (up to the maximum that + * can be active at a time), begin monitoring, end monitoring, make + * sure results are available, sanity check the result size, and get + * the results. + */ + test_name = "basic measurement"; + + get_counters(group, &counters, &num_counters, + &max_active_counters); + verify(max_active_counters >= 0); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + usable_counters = MIN2(num_counters, max_active_counters); + + glGenPerfMonitorsAMD(1, &monitor); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Enable counters 0 .. usable_counters from the list. */ + glSelectPerfMonitorCountersAMD(monitor, true, group, usable_counters, + counters); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Start monitoring */ + glBeginPerfMonitorAMD(monitor); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Drawing...meh */ + glFinish(); + + /* End monitoring */ + glEndPerfMonitorAMD(monitor); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Wait for the result to be available. */ + verify(wait_until_available(monitor)); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Get the result size. */ + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD, + sizeof(unsigned), &result_size, NULL); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Make sure the size is in bytes. */ + verify(result_size % sizeof(unsigned) == 0); + + /* The format is . The first two are + * uint32_ts. Value is either a float, uint32_t, or uint64_t. + * As a sanity check, make sure the result size is within + * reasonable limits. Don't bother checking the actual types + * since that's a bunch of work. + */ + verify(result_size >= 3 * sizeof(uint32_t) * usable_counters) + verify(result_size <= + (2 * sizeof(uint32_t) + sizeof(uint64_t)) * usable_counters); + + /* Get the results. */ + data = calloc(1, result_size); + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AMD, + result_size, data, &bytes_written); + + verify(bytes_written == result_size); + + piglit_report_subtest_result(PIGLIT_PASS, test_name); + + /** + * Test #2: Verify counter results against specified range. + */ + test_name = "counters in range"; + p = data; + while ((char *) p < ((char *) data) + bytes_written) { + uint32_t group_id = p[0]; + uint32_t counter_id = p[1]; + + /* Counter values */ + uint32_t u32 = p[2]; + float f = ((float *) p)[2]; + uint64_t u64 = ((uint64_t *) p)[1]; + + /* Query results */ + GLenum counter_type = GL_NONE; + uint64_t range[2]; + + /* There's only one group, so it better match */ + verify(group_id == group); + + /* Getting the counter data also validates the counter ID + * without having to walk through the whole list of counters. + */ + glGetPerfMonitorCounterInfoAMD(group_id, counter_id, + GL_COUNTER_TYPE_AMD, + &counter_type); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + glGetPerfMonitorCounterInfoAMD(group_id, counter_id, + GL_COUNTER_RANGE_AMD, + range); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Make sure it falls within the proper range */ + switch (counter_type) { + case GL_UNSIGNED_INT: { + uint32_t min = ((uint32_t *) range)[0]; + uint32_t max = ((uint32_t *) range)[1]; + verify(u32 >= min); + verify(u32 <= max); + break; + } + case GL_UNSIGNED_INT64_AMD: { + verify(u64 >= range[0]); + verify(u64 <= range[1]); + break; + } + case GL_PERCENTAGE_AMD: + case GL_FLOAT: { + float min = ((float *) range)[0]; + float max = ((float *) range)[1]; + verify(f >= min); + verify(f <= max); + break; + } + } + + p += (counter_type == GL_UNSIGNED_INT64_AMD) ? 4 : 3; + } + verify(result_size == ((char *) p - (char *) data)); + + free(data); + + /** + * Test #3: Changing the set of active counters resets queries. + * + * "When SelectPerfMonitorCountersAMD is called on a monitor, any + * outstanding results for that monitor become invalidated and the + * result queries PERFMON_RESULT_SIZE_AMD and + * PERFMON_RESULT_AVAILABLE_AMD are reset to 0." + */ + test_name = "selecting counters resets queries"; + + /* Turn off the first counter. */ + glSelectPerfMonitorCountersAMD(monitor, false, group, 1, counters); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Results should no longer be available. All queries should + * return 0. + */ + value = 0xd0d0d0d0; + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD, + sizeof(unsigned), &value, NULL); + verify(piglit_check_gl_error(GL_NO_ERROR)); + verify(value == 0); + + value = 0xd0d0d0d0; + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD, + sizeof(unsigned), &value, NULL); + verify(piglit_check_gl_error(GL_NO_ERROR)); + verify(value == 0); + + piglit_report_subtest_result(PIGLIT_PASS, test_name); + + glDeletePerfMonitorsAMD(1, &monitor); +} + + +/** + * Make sure that calling SelectPerfMonitorCountersAMD on an active monitor + * is possible, resets active queries, and restarts monitoring (so it remains + * active). + * + * This is not actually specified, but matches the behavior of AMD's driver. + * Being an AMD extension, other implementations should probably match theirs. + */ +static void +test_change_counters_while_active(unsigned group) +{ + unsigned monitor; + unsigned *counters; + int num_counters; + int max_active_counters; + unsigned usable_counters; + unsigned data; + const char *test_name = "change counters while active"; + + get_counters(group, &counters, &num_counters, + &max_active_counters); + verify(max_active_counters >= 0); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + usable_counters = MIN2(num_counters, max_active_counters); + + if (usable_counters == 0) + return; /* skip */ + + glGenPerfMonitorsAMD(1, &monitor); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Enable counters 0 .. usable_counters from the list. */ + glSelectPerfMonitorCountersAMD(monitor, true, group, usable_counters, + counters); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Start monitoring */ + glBeginPerfMonitorAMD(monitor); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Turn off the first counter. The specification is unclear whether + * or not this should be allowed while monitoring is active, but it + * apparently is (Catalyst 12.06 on a Radeon 3650). + */ + glSelectPerfMonitorCountersAMD(monitor, false, group, 1, counters); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + /* Verify that all queries have been reset to 0 */ + data = 0xd0d0d0d0; + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD, + sizeof(unsigned), &data, NULL); + verify(piglit_check_gl_error(GL_NO_ERROR)); + verify(data == 0); + + data = 0xd0d0d0d0; + glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD, + sizeof(unsigned), &data, NULL); + verify(piglit_check_gl_error(GL_NO_ERROR)); + verify(data == 0); + + /* The spec doesn't explicitly mention whether or not monitoring + * is still active, but apparently it is. + */ + glEndPerfMonitorAMD(monitor); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + glDeletePerfMonitorsAMD(1, &monitor); + verify(piglit_check_gl_error(GL_NO_ERROR)); + + piglit_report_subtest_result(PIGLIT_PASS, test_name); +} + + +/******************************************************************************/ + +enum piglit_result +piglit_display(void) +{ + return PIGLIT_FAIL; +} + +/** + * The main test program. + */ +void +piglit_init(int argc, char **argv) +{ + unsigned *groups; + int num_groups; + + piglit_require_extension("GL_AMD_performance_monitor"); + + /* Basic glGetPerfMonitorGroupsAMD() tests */ + get_groups(&groups, &num_groups); + + /* If there are no groups, the rest of the tests can't run. Bail. */ + if (num_groups == 0) + exit(0); + + test_basic_measurement(groups[0]); + test_change_counters_while_active(groups[0]); + + exit(0); +} -- cgit v1.2.3