[Piglit] [PATCH 3/3] Add tests for the INTEL_performance_query extension.
Petri Latvala
petri.latvala at intel.com
Wed Mar 12 05:53:53 PDT 2014
As with AMD_performance_monitor, 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 query, while a few sanity check
all counters in all queries.
Signed-off-by: Petri Latvala <petri.latvala at intel.com>
---
tests/all.py | 6 +
tests/spec/CMakeLists.txt | 1 +
.../spec/intel_performance_query/CMakeLists.gl.txt | 14 +
tests/spec/intel_performance_query/CMakeLists.txt | 1 +
tests/spec/intel_performance_query/api.c | 808 +++++++++++++++++++++
tests/spec/intel_performance_query/measure.c | 294 ++++++++
tests/spec/intel_performance_query/minmax.c | 58 ++
7 files changed, 1182 insertions(+)
create mode 100644 tests/spec/intel_performance_query/CMakeLists.gl.txt
create mode 100644 tests/spec/intel_performance_query/CMakeLists.txt
create mode 100644 tests/spec/intel_performance_query/api.c
create mode 100644 tests/spec/intel_performance_query/measure.c
create mode 100644 tests/spec/intel_performance_query/minmax.c
diff --git a/tests/all.py b/tests/all.py
index 1e1aa3d..ba1eb56 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -1425,6 +1425,12 @@ import_glsl_parser_tests(spec['AMD_shader_trinary_minmax'],
os.path.join(testsDir, 'spec', 'amd_shader_trinary_minmax'),
[''])
+# Group INTEL_performance_query
+spec['INTEL_performance_query'] = Group()
+profile.test_list['spec/INTEL_performance_query/api'] = PlainExecTest('intel_performance_query_api -auto')
+profile.test_list['spec/INTEL_performance_query/measure'] = PlainExecTest('intel_performance_query_measure -auto')
+profile.test_list['spec/INTEL_performance_query/minmax'] = PlainExecTest('intel_performance_query_minmax')
+
# Group ARB_point_sprite
arb_point_sprite = Group()
spec['ARB_point_sprite'] = arb_point_sprite
diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
index 0a513c1..037653e 100644
--- a/tests/spec/CMakeLists.txt
+++ b/tests/spec/CMakeLists.txt
@@ -100,3 +100,4 @@ add_subdirectory (ext_image_dma_buf_import)
add_subdirectory (arb_blend_func_extended)
add_subdirectory (ext_unpack_subimage)
add_subdirectory (arb_vertex_array_object)
+add_subdirectory (intel_performance_query)
diff --git a/tests/spec/intel_performance_query/CMakeLists.gl.txt b/tests/spec/intel_performance_query/CMakeLists.gl.txt
new file mode 100644
index 0000000..7d10e0b
--- /dev/null
+++ b/tests/spec/intel_performance_query/CMakeLists.gl.txt
@@ -0,0 +1,14 @@
+include_directories(
+ ${GLEXT_INCLUDE_DIR}
+ ${OPENGL_INCLUDE_PATH}
+)
+
+link_libraries (
+ piglitutil_${piglit_target_api}
+ ${OPENGL_gl_LIBRARY}
+ ${OPENGL_glu_LIBRARY}
+)
+
+piglit_add_executable (intel_performance_query_api api.c)
+piglit_add_executable (intel_performance_query_minmax minmax.c)
+piglit_add_executable (intel_performance_query_measure measure.c)
diff --git a/tests/spec/intel_performance_query/CMakeLists.txt b/tests/spec/intel_performance_query/CMakeLists.txt
new file mode 100644
index 0000000..144a306
--- /dev/null
+++ b/tests/spec/intel_performance_query/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git a/tests/spec/intel_performance_query/api.c b/tests/spec/intel_performance_query/api.c
new file mode 100644
index 0000000..afb7fcb
--- /dev/null
+++ b/tests/spec/intel_performance_query/api.c
@@ -0,0 +1,808 @@
+/*
+ * Copyright © 2014 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 INTEL_performance_query infrastructure tests. These test the
+ * mechanism to retrieve counter and query information, string
+ * processing, and various error conditions. They do not actually
+ * activate monitoring.
+ */
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include "piglit-util-gl-common.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+ config.supports_gl_compat_version = 30;
+ config.supports_gl_es_version = 20;
+ config.window_visual = PIGLIT_GL_VISUAL_RGB;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+/******************************************************************************/
+
+/**
+ * Get a list of query IDs.
+ */
+static void
+get_queries(GLuint ** queries, unsigned *num_queries)
+{
+ GLuint queryid;
+ unsigned i;
+
+ /* Enumerate all query ids first to get their count */
+ *num_queries = 0;
+ for (glGetFirstPerfQueryIdINTEL(&queryid);
+ queryid != 0;
+ glGetNextPerfQueryIdINTEL(queryid, &queryid)) {
+ ++(*num_queries);
+ }
+
+ *queries = calloc(*num_queries, sizeof(unsigned));
+
+ /* And now collect them */
+ i = 0;
+ for (glGetFirstPerfQueryIdINTEL(&queryid);
+ queryid != 0;
+ glGetNextPerfQueryIdINTEL(queryid, &queryid)) {
+ (*queries)[i++] = queryid;
+ }
+}
+
+/**
+ * Get a list of counter IDs in a given query.
+ */
+static void
+get_counters(GLuint query, GLuint ** counters, unsigned *num_counters)
+{
+ unsigned i;
+
+ glGetPerfQueryInfoINTEL(query, 0, NULL, NULL,
+ num_counters, NULL, NULL);
+
+ /* Counters start from 1 and are continuous */
+ *counters = calloc(*num_counters, sizeof(unsigned));
+ for (i = 0; i < *num_counters; ++i) {
+ (*counters)[i] = i + 1;
+ }
+}
+
+/**
+ * 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 query ID.
+ */
+static GLuint
+find_invalid_query(unsigned *queries, int num_queries)
+{
+ unsigned invalid_query = ~0;
+
+ /* Most implementations probably use small consecutive integers, so
+ * start at ~0 and work backwards. Hopefully we shouldn't loop.
+ */
+ while (in_list(invalid_query, queries, num_queries))
+ --invalid_query;
+
+ return invalid_query;
+}
+
+/**
+ * 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) \
+ do { \
+ piglit_report_subtest_result((pass) ? \
+ PIGLIT_PASS : PIGLIT_FAIL, __FUNCTION__); \
+ return; \
+ } while (0)
+
+/******************************************************************************/
+
+/** Call glGetFirstPerfQueryIdINTEL() with a NULL queryId pointer.
+ *
+ * Verify that it doesn't attempt to write the query id and crash.
+ */
+static void
+test_first_query_null_queryid_pointer(void)
+{
+ glGetFirstPerfQueryIdINTEL(NULL);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/******************************************************************************/
+
+/** Call glGetNextPerfQueryIdINTEL() with a NULL nextQueryId.
+ *
+ * Verify that it doesn't attempt to write the query id and crash.
+ */
+static void
+test_next_query_null_nextqueryid_pointer(unsigned validquery)
+{
+ glGetNextPerfQueryIdINTEL(validquery, NULL);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/** Call glGetNextPerfQueryIdINTEL() with an invalid query id.
+ *
+ * Verify that it produces INVALID_VALUE.
+ */
+static void
+test_next_query_invalid_queryid(unsigned invalidquery)
+{
+ unsigned dummy;
+
+ glGetNextPerfQueryIdINTEL(invalidquery, &dummy);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/******************************************************************************/
+
+/** Call glGetPerfQueryIdByNameINTEL() with a NULL query id pointer.
+ *
+ * Verify that it doesn't attempt to write a query id and crash.
+ */
+static void
+test_get_query_by_name_null_queryid_pointer(const char *validname)
+{
+ glGetPerfQueryIdByNameINTEL(validname, NULL);
+ /* The specification does not say that this should produce an error. */
+}
+
+/** Call glGetPerfQueryIdByNameINTEL() with a NULL name pointer.
+ *
+ * Verify that it doesn't attempt to read the name and crash.
+ */
+static void
+test_get_query_by_name_null_name_pointer(void)
+{
+ unsigned dummy;
+
+ glGetPerfQueryIdByNameINTEL(NULL, &dummy);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/** Call glGetPerfQueryIdByNameINTEL() with an invalid name.
+ *
+ * Verify that it produces INVALID_VALUE.
+ */
+static void
+test_get_query_by_name_invalid_name(const char *invalidname)
+{
+ unsigned dummy;
+
+ glGetPerfQueryIdByNameINTEL(invalidname, &dummy);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/******************************************************************************/
+
+/** Call glGetPerfQueryInfoINTEL() with an invalid query id.
+ *
+ * Verify that it produces INVALID_VALUE.
+ */
+static void
+test_get_perf_query_info_invalid_queryid(unsigned invalidquery)
+{
+ char name[256];
+ GLuint datasize;
+ GLuint counters;
+ GLuint instances;
+ GLuint caps;
+
+ glGetPerfQueryInfoINTEL(invalidquery,
+ sizeof(name), name,
+ &datasize, &counters, &instances, &caps);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/** Call glGetPerfQueryInfoINTEL() with NULL pointers.
+ *
+ * Verify that it doesn't attempt to write data to them and crash.
+ * Verify that it doesn't produce an error.
+ */
+static void
+test_get_perf_query_info_null_pointers(unsigned validquery)
+{
+ glGetPerfQueryInfoINTEL(validquery, 0, NULL, NULL, NULL, NULL, NULL);
+ report(piglit_check_gl_error(GL_NO_ERROR));
+}
+
+/** Call glGetPerfQueryInfoINTEL() with a single character buffer.
+ *
+ * Verify that length is correct, the string is zero-terminated,
+ * and no buffer overflows occur.
+ */
+static void
+test_get_perf_query_info_single_character_buffer(unsigned validquery)
+{
+ char name[3] = "```";
+ bool pass = true;
+
+ glGetPerfQueryInfoINTEL(validquery, 1, name, NULL, NULL, NULL, NULL);
+ pass = piglit_check_gl_error(GL_NO_ERROR);
+
+ /* Verify buffer contents: only the first character should change,
+ * and it should be the terminator.
+ */
+ pass = name[0] == '\0' && pass;
+ pass = name[1] == '`' && pass;
+ pass = name[2] == '`' && pass;
+
+ report(pass);
+}
+
+/******************************************************************************/
+
+/** Call glGetPerfCounterInfoINTEL() with an invalid query id.
+ *
+ * Verify that it produces INVALID_VALUE.
+ */
+static void
+test_get_perf_counter_info_invalid_queryid(unsigned invalidquery)
+{
+ char name[256];
+ char desc[1024];
+ GLuint offset;
+ GLuint datasize;
+ GLuint type;
+ GLuint datatype;
+ GLuint64 maxvalue;
+
+ /* 1 is a valid counter ID */
+ glGetPerfCounterInfoINTEL(invalidquery, 1,
+ sizeof(name), name,
+ sizeof(desc), desc,
+ &offset, &datasize, &type,
+ &datatype, &maxvalue);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/** Call glGetPerfCounterInfoINTEL() with a valid query id but invalid
+ * counter id.
+ *
+ * Verify that it produces INVALID_VALUE.
+ */
+static void
+test_get_perf_counter_info_invalid_counterid(unsigned validquery,
+ unsigned invalidcounter)
+{
+ char name[256];
+ char desc[1024];
+ GLuint offset;
+ GLuint datasize;
+ GLuint type;
+ GLuint datatype;
+ GLuint64 maxvalue;
+
+ glGetPerfCounterInfoINTEL(validquery, invalidcounter,
+ sizeof(name), name,
+ sizeof(desc), desc,
+ &offset, &datasize, &type,
+ &datatype, &maxvalue);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/** Call glGetPerfCounterInfoINTEL() with NULL pointers.
+ *
+ * Verify that it doesn't attempt to write data to them and crash.
+ * Verify that it doesn't produce an error.
+ */
+static void
+test_get_perf_counter_info_null_pointers(unsigned validquery,
+ unsigned validcounter)
+{
+ glGetPerfCounterInfoINTEL(validquery, validcounter,
+ 0, NULL,
+ 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ report(piglit_check_gl_error(GL_NO_ERROR));
+}
+
+/** Call glGetPerfCounterInfoINTEL() with single character buffers.
+ *
+ * Verify that length is correct, the string is zero-terminated,
+ * and no buffer overflows occur.
+ */
+static void
+test_get_perf_counter_info_single_character_buffer(unsigned validquery,
+ unsigned validcounter)
+{
+ char name[3] = "```";
+ char desc[3] = "```";
+ bool pass = true;
+
+ glGetPerfCounterInfoINTEL(validquery, validcounter,
+ 1, name,
+ 1, desc, NULL, NULL, NULL, NULL, NULL);
+ pass = piglit_check_gl_error(GL_NO_ERROR);
+
+ /* Verify buffer contents: only the first character should change,
+ * and it should be the terminator.
+ */
+ pass = name[0] == '\0' && pass;
+ pass = name[1] == '`' && pass;
+ pass = name[2] == '`' && pass;
+
+ pass = desc[0] == '\0' && pass;
+ pass = desc[1] == '`' && pass;
+ pass = desc[2] == '`' && pass;
+
+ report(pass);
+}
+
+/**
+ * Call glGetPerfQueryInfoINTEL() on every query and verify that all
+ * queries have a valid capsMask value.
+ */
+static void
+test_query_info(unsigned *queries, unsigned num_queries)
+{
+ int i;
+
+ for (i = 0; i < num_queries; ++i) {
+ char name[256];
+ GLuint datasize;
+ GLuint counters;
+ GLuint instances;
+ GLuint caps;
+
+ glGetPerfQueryInfoINTEL(queries[i],
+ sizeof(name), name,
+ &datasize, &counters,
+ &instances, &caps);
+
+ if (caps != GL_PERFQUERY_SINGLE_CONTEXT_INTEL &&
+ caps != GL_PERFQUERY_GLOBAL_CONTEXT_INTEL) {
+ printf("Query %u has an invalid capability mask: %x\n",
+ queries[i], caps);
+ report(false);
+ break;
+ }
+ }
+
+ report(true);
+}
+
+/**
+ * Call glGetPerfCounterInfoINTEL() on every query/counter pair and verify that
+ * all counters have a valid type and datatype.
+ */
+static void
+test_counter_info(unsigned *queries, unsigned num_queries)
+{
+ int i;
+ int j;
+
+ for (i = 0; i < num_queries; ++i) {
+ unsigned *counters;
+ unsigned num_counters;
+ get_counters(queries[i], &counters, &num_counters);
+
+ if (!piglit_automatic) {
+ char queryname[256];
+
+ glGetPerfQueryInfoINTEL(queries[i], sizeof(queryname),
+ queryname, NULL, NULL, NULL,
+ NULL);
+ printf("Query %u [%s]:\n", queries[i], queryname);
+ }
+
+ for (j = 0; j < num_counters; ++j) {
+ char name[256];
+ char desc[1024];
+ GLuint offset;
+ GLuint datasize;
+ GLuint type;
+ GLuint datatype;
+ GLuint64 maxvalue;
+
+ memset(name, 0, sizeof(name));
+ memset(desc, 0, sizeof(desc));
+
+ glGetPerfCounterInfoINTEL(queries[i], counters[j],
+ sizeof(name), name,
+ sizeof(desc), desc,
+ &offset, &datasize, &type,
+ &datatype, &maxvalue);
+
+ if (!piglit_automatic)
+ printf(" Counter %u [%s]: %s\n", counters[j],
+ name, desc);
+
+ switch (datatype) {
+ default:
+ printf("Query %u/Counter %u has an invalid datatype: %x\n",
+ queries[i], counters[j], datatype);
+ report(false);
+ break;
+ case GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL:
+ case GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL:
+ case GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL:
+ case GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL:
+ case GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL:
+ break;
+ }
+
+ switch (type) {
+ default:
+ printf("Query %u/Counter %u has an invalid type: %x\n",
+ queries[i], counters[j], type);
+ report(false);
+ break;
+ case GL_PERFQUERY_COUNTER_EVENT_INTEL:
+ case GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL:
+ case GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL:
+ case GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL:
+ case GL_PERFQUERY_COUNTER_RAW_INTEL:
+ case GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL:
+ break;
+ }
+ }
+ free(counters);
+ }
+
+ report(true);
+}
+
+/******************************************************************************/
+
+/**
+ * Call glBeginPerfQueryINTEL() on an invalid query handle.
+ * (Should be run before any Gen tests to ensure this handle is invalid.)
+ *
+ * Verify that it produces INVALID_VALUE.
+ */
+void
+test_begin_invalid_query_handle(void)
+{
+ glBeginPerfQueryINTEL(777);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/**
+ * Call glEndPerfQueryINTEL() on an invalid query handle.
+ * (Should be run before any Gen tests to ensure this ID is invalid.)
+ *
+ * Verify that it produces INVALID_VALUE or INVALID_OPERATION.
+ * XXX: Only INVALID_OPERATION is actually specified, assume
+ * INVALID_VALUE can also be generated.
+ */
+void
+test_end_invalid_query_handle(void)
+{
+ GLenum error;
+ glEndPerfQueryINTEL(777);
+ error = glGetError();
+ report(error == GL_INVALID_VALUE || error == GL_INVALID_OPERATION);
+}
+
+/**
+ * Call glCreatePerfQueryINTEL() with an invalid query id.
+ *
+ * Verify that it produces INVALID_VALUE.
+ */
+static void
+test_create_perf_query_invalid_query(unsigned invalidquery)
+{
+ GLuint handle;
+ glCreatePerfQueryINTEL(invalidquery, &handle);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/**
+ * Call glCreatePerfQueryINTEL() with a NULL queryhandle pointer.
+ *
+ * Verify that it doesn't attempt to write a handle and crash,
+ * and produces INVALID_VALUE.
+ * XXX: This isn't actually specified, but it seems like it ought to be.
+ */
+static void
+test_create_perf_query_null_handle_pointer(unsigned validquery)
+{
+ glCreatePerfQueryINTEL(validquery, NULL);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/**
+ * Call glDeletePerfQueryINTEL() with an invalid query handle.
+ *
+ * Verify that it produces INVALID_VALUE.
+ */
+static void
+test_delete_perf_query_invalid_handle(void)
+{
+ glDeletePerfQueryINTEL(777);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/**
+ * Call glGetPerfQueryDataINTEL() with an invalid query handle.
+ * (Should be run before any Gen tests to ensure this ID is invalid.)
+ *
+ * Verify that it produces INVALID_VALUE.
+ * XXX: This isn't actually specified, but it seems like it ought to be.
+ */
+static void
+test_get_query_data_invalid_query_handle(void)
+{
+ char data[1024];
+ GLuint bytes;
+ glGetPerfQueryDataINTEL(777, GL_PERFQUERY_DONOT_FLUSH_INTEL,
+ sizeof(data), data, &bytes);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/**
+ * Call glGetPerfQueryDataINTEL() with a NULL data pointer.
+ *
+ * Verify that it doesn't attempt to write data and crash, and
+ * produces INVALID_VALUE.
+ */
+static void
+test_get_query_data_null_data_pointer(void)
+{
+ GLuint query;
+ GLuint handle;
+ GLuint bytes;
+
+ glGetFirstPerfQueryIdINTEL(&query);
+ glCreatePerfQueryINTEL(query, &handle);
+
+ glGetPerfQueryDataINTEL(handle, GL_PERFQUERY_DONOT_FLUSH_INTEL,
+ 128, NULL, &bytes);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/**
+ * Call glGetPerfQueryDataINTEL() with a NULL byteswritten pointer.
+ *
+ * Verify that it doesn't attempt to write data and crash, and
+ * produces INVALID_VALUE.
+ */
+static void
+test_get_query_data_null_byteswritten_pointer(void)
+{
+ GLuint query;
+ GLuint handle;
+ char data[1024];
+
+ glGetFirstPerfQueryIdINTEL(&query);
+ glCreatePerfQueryINTEL(query, &handle);
+
+ glGetPerfQueryDataINTEL(handle, GL_PERFQUERY_DONOT_FLUSH_INTEL,
+ sizeof(data), data, NULL);
+ report(piglit_check_gl_error(GL_INVALID_VALUE));
+}
+
+/**
+ * Call glGetPerfQueryDataINTEL on a query handle that hasn't been started.
+ *
+ * Verify that no data is written in such case.
+ */
+static void
+test_initial_state(void)
+{
+ bool pass = true;
+ unsigned query;
+ unsigned handle;
+ unsigned bytes = 0xd0d0d0d0;
+ char data[1024];
+
+ glGetFirstPerfQueryIdINTEL(&query);
+ glCreatePerfQueryINTEL(query, &handle);
+ pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
+
+ memset(data, '`', sizeof(data));
+
+ glGetPerfQueryDataINTEL(handle, GL_PERFQUERY_DONOT_FLUSH_INTEL,
+ sizeof(data), data, &bytes);
+ pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
+
+ pass = bytes == 0 && pass;
+ pass = data[0] == '`' && pass;
+
+ glDeletePerfQueryINTEL(handle);
+ report(pass);
+}
+
+/**
+ * "If a performance query is not currently started, an
+ * INVALID_OPERATION error will be generated."
+ */
+static void
+test_end_without_begin(void)
+{
+ bool pass = true;
+ unsigned query;
+ unsigned handle;
+
+ glGetFirstPerfQueryIdINTEL(&query);
+ glCreatePerfQueryINTEL(query, &handle);
+ pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
+
+ glEndPerfQueryINTEL(handle);
+ report(piglit_check_gl_error(GL_INVALID_OPERATION));
+
+ glDeletePerfQueryINTEL(handle);
+}
+
+/**
+ * "Note that some query types, they cannot be collected in the same
+ * time. Therefore calls of BeginPerfQueryINTEL() cannot be nested if
+ * they refer to queries of such different types. In such case
+ * INVALID_OPERATION error is generated."
+ *
+ * Impossible to know for sure which different queries cannot be used
+ * at the same time. Assume that the same query cannot be started
+ * twice, so verify that calling Begin twice on the same query
+ * produces INVALID_OPERATION.
+ */
+static void
+test_double_begin(void)
+{
+ bool pass = true;
+ unsigned query;
+ unsigned handle;
+ GLenum error;
+
+ glGetFirstPerfQueryIdINTEL(&query);
+ glCreatePerfQueryINTEL(query, &handle);
+ pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
+
+ glBeginPerfQueryINTEL(handle);
+
+ error = glGetError();
+ if (error != GL_NO_ERROR) {
+ glDeletePerfQueryINTEL(handle);
+ /* Query couldn't start for some reason; bail. */
+ if (error == GL_INVALID_OPERATION)
+ return;
+ /* We weren't expecting this other error. */
+ report(false);
+ }
+
+ /* Double begin */
+ glBeginPerfQueryINTEL(handle);
+ pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass;
+
+ glDeletePerfQueryINTEL(handle);
+ report(pass);
+}
+
+/******************************************************************************/
+
+enum piglit_result
+piglit_display(void)
+{
+ return PIGLIT_FAIL;
+}
+
+/**
+ * The main test program.
+ */
+void
+piglit_init(int argc, char **argv)
+{
+ unsigned *queries;
+ unsigned num_queries;
+ unsigned *counters;
+ unsigned num_counters;
+ unsigned invalid_query;
+ unsigned valid_query;
+ unsigned invalid_counter;
+ unsigned valid_counter;
+ char valid_name[256];
+
+ piglit_require_extension("GL_INTEL_performance_query");
+
+ test_first_query_null_queryid_pointer();
+
+ get_queries(&queries, &num_queries);
+
+ /* If there are no valid queries, the rest of the tests can't run.
+ * Bail.
+ */
+ if (num_queries == 0)
+ exit(0);
+
+ invalid_query = find_invalid_query(queries, num_queries);
+ valid_query = queries[0];
+
+ test_next_query_null_nextqueryid_pointer(valid_query);
+ test_next_query_invalid_queryid(invalid_query);
+
+ glGetPerfQueryInfoINTEL(valid_query, sizeof(valid_name), valid_name,
+ NULL, NULL, NULL, NULL);
+
+ test_get_query_by_name_null_queryid_pointer(valid_name);
+ test_get_query_by_name_null_name_pointer();
+ test_get_query_by_name_invalid_name
+ ("We assume this is an invalid name of a query");
+ test_get_perf_query_info_invalid_queryid(invalid_query);
+ test_get_perf_query_info_null_pointers(valid_query);
+ test_get_perf_query_info_single_character_buffer(valid_query);
+ test_get_perf_counter_info_invalid_queryid(invalid_query);
+
+ get_counters(valid_query, &counters, &num_counters);
+
+ /* If there are no counters, the rest of the tests can't run.
+ * Bail.
+ */
+ if (num_counters == 0)
+ exit(0);
+
+ invalid_counter = find_invalid_counter(counters, num_counters);
+ valid_counter = counters[0];
+
+ test_get_perf_counter_info_invalid_counterid(valid_query,
+ invalid_counter);
+ test_get_perf_counter_info_null_pointers(valid_query, valid_counter);
+ test_get_perf_counter_info_single_character_buffer(valid_query,
+ valid_counter);
+ test_query_info(queries, num_queries);
+ test_counter_info(queries, num_queries);
+ test_begin_invalid_query_handle();
+ test_end_invalid_query_handle();
+ test_create_perf_query_invalid_query(invalid_query);
+ test_create_perf_query_null_handle_pointer(valid_query);
+ test_delete_perf_query_invalid_handle();
+ test_get_query_data_invalid_query_handle();
+ test_get_query_data_null_data_pointer();
+ test_get_query_data_null_byteswritten_pointer();
+ test_initial_state();
+ test_end_without_begin();
+ test_double_begin();
+
+ free(counters);
+ free(queries);
+
+ exit(0);
+}
diff --git a/tests/spec/intel_performance_query/measure.c b/tests/spec/intel_performance_query/measure.c
new file mode 100644
index 0000000..e11b5f7
--- /dev/null
+++ b/tests/spec/intel_performance_query/measure.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright © 2014 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 INTEL_performance_query tests that actually measure things.
+ */
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include "piglit-util-gl-common.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+ config.supports_gl_compat_version = 30;
+ config.supports_gl_es_version = 20;
+ config.window_visual = PIGLIT_GL_VISUAL_RGB;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+/******************************************************************************/
+
+/**
+ * Get a list of query IDs.
+ */
+static void
+get_queries(unsigned **queries, unsigned *num_queries)
+{
+ unsigned queryid;
+ unsigned i;
+
+ /* Enumerate all query ids first to get their count */
+ *num_queries = 0;
+ for (glGetFirstPerfQueryIdINTEL(&queryid);
+ queryid != 0;
+ glGetNextPerfQueryIdINTEL(queryid, &queryid)) {
+ ++(*num_queries);
+ }
+
+ *queries = calloc(*num_queries, sizeof(unsigned));
+
+ /* And now collect them */
+ i = 0;
+ for (glGetFirstPerfQueryIdINTEL(&queryid);
+ queryid != 0;
+ glGetNextPerfQueryIdINTEL(queryid, &queryid)) {
+ (*queries)[i++] = queryid;
+ }
+}
+
+/**
+ * Get a list of counter IDs in a given query.
+ */
+static void
+get_counters(unsigned query, unsigned **counters, unsigned *num_counters)
+{
+ unsigned i;
+
+ glGetPerfQueryInfoINTEL(query, 0, NULL, NULL,
+ num_counters, NULL, NULL);
+
+ /* Counters start from 1 and are continuous */
+ *counters = calloc(*num_counters, sizeof(unsigned));
+ for (i = 0; i < *num_counters; ++i) {
+ (*counters)[i] = i + 1;
+ }
+}
+
+/**
+ * Get the size of a counter value of a given datatype enum in bytes.
+ */
+static unsigned
+value_size(GLuint datatype)
+{
+ switch (datatype) {
+ default:
+ /* Return 0 so the caller can report correct data to piglit. */
+ return 0;
+ case GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL:
+ case GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL:
+ case GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL:
+ return sizeof(uint32_t);
+ case GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL:
+ case GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL:
+ return sizeof(uint64_t);
+ }
+}
+
+#define verify(x) \
+ if (!(x)) { \
+ piglit_report_subtest_result(PIGLIT_FAIL, "%s", test_name); \
+ return; \
+ }
+
+/******************************************************************************/
+
+/**
+ * Basic functional test: create a query of the first query (this
+ * terminology is too overloaded) begin monitoring, end monitoring,
+ * make sure results are available, sanity check the result size, and
+ * get the results.
+ */
+static void
+test_basic_measurement(unsigned query)
+{
+ unsigned handle;
+ unsigned *counters;
+ unsigned num_counters;
+ unsigned result_size = 0;
+ GLuint bytes_written = 0;
+ char *data;
+ unsigned i;
+
+ const char *test_name;
+
+ /**
+ * Test #1: Initialization
+ *
+ * Begin monitoring, end monitoring.
+ */
+ test_name = "initialization";
+
+ get_counters(query, &counters, &num_counters);
+ verify(num_counters > 0);
+ verify(piglit_check_gl_error(GL_NO_ERROR));
+
+ glCreatePerfQueryINTEL(query, &handle);
+ verify(piglit_check_gl_error(GL_NO_ERROR));
+
+ /* Start monitoring */
+ glBeginPerfQueryINTEL(handle);
+ verify(piglit_check_gl_error(GL_NO_ERROR));
+
+ /* Drawing...meh */
+ piglit_draw_triangle(0.0, 0.0, 1.0, 1.0, 0.5, 0.5);
+
+ /* End monitoring */
+ glEndPerfQueryINTEL(handle);
+ verify(piglit_check_gl_error(GL_NO_ERROR));
+
+ piglit_report_subtest_result(PIGLIT_PASS, "%s", test_name);
+
+ /**
+ * Test #2: Receiving results
+ *
+ * Grab the data and sanity check its size as much as possible.
+ */
+
+ test_name = "result retrieval";
+
+ /* Get the result size. */
+ glGetPerfQueryInfoINTEL(query, 0, NULL, &result_size, NULL, NULL,
+ NULL);
+ verify(piglit_check_gl_error(GL_NO_ERROR));
+
+ /* Get the results. */
+
+ /* Allocate more than the query info says, in case the
+ * implementation lied about the size.
+ */
+ data = calloc(1, result_size + 32);
+ /* Pass GL_PERFQUERY_WAIT_INTEL which will make the function
+ * return only when results are available.
+ */
+ glGetPerfQueryDataINTEL(handle, GL_PERFQUERY_WAIT_INTEL,
+ result_size + 32, data, &bytes_written);
+ verify(piglit_check_gl_error(GL_NO_ERROR));
+ verify(bytes_written == result_size);
+
+ piglit_report_subtest_result(PIGLIT_PASS, "%s", test_name);
+
+ /**
+ * Test #3: Data
+ *
+ * Check that the data sizes and offsets are correct.
+ */
+ test_name = "data";
+
+ /* Counter values are one of float, double, uint32_t, uint64_t or
+ * bool32_t. Now, the specification implicitly allows counters to
+ * alias and extra data to exist between values (GetPerfCounterInfo
+ * gives counter data offset in bytes) so we don't have many sanity
+ * checks on the result_size the spec would restrict.
+ */
+ verify(result_size >= sizeof(uint32_t));
+ verify(result_size % sizeof(uint32_t) == 0);
+
+ for (i = 0; i < num_counters; ++i) {
+ char name[256];
+ GLuint offset;
+ GLuint size;
+ GLuint datatype;
+ glGetPerfCounterInfoINTEL(query, counters[i],
+ sizeof(name), name,
+ 0, NULL,
+ &offset, &size,
+ NULL, &datatype, NULL);
+ verify(piglit_check_gl_error(GL_NO_ERROR));
+ verify(offset + size <= result_size);
+ /* This tests that the datatype enum is valid */
+ verify(value_size(datatype) != 0);
+ /* In theory, the specification allows counter values to be
+ * _multiple_ values of the reported data type.
+ */
+ verify(size >= value_size(datatype));
+ verify(size % value_size(datatype) == 0);
+
+ /* Print the counter value for manual inspection. */
+ if (!piglit_automatic) {
+ char *p;
+
+ p = data + offset;
+ printf("%u [%s]: ", i, name);
+ switch (datatype) {
+ case GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL:
+ printf("%" PRIu32 "\n", *((uint32_t *) p));
+ break;
+ case GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL:
+ printf("%" PRIu64 "\n", *((uint64_t *) p));
+ break;
+ case GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL:
+ printf("%f\n", *((float *) p));
+ break;
+ case GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL:
+ printf("%f\n", *((double *) p));
+ break;
+ case GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL:
+ printf("%" PRIu32 "\n", *((uint32_t *) p));
+ break;
+ default:
+ verify(!"not reached, should have already checked for validity");
+ break;
+ }
+ }
+ }
+
+ piglit_report_subtest_result(PIGLIT_PASS, "%s", test_name);
+
+ free(data);
+
+ glDeletePerfQueryINTEL(handle);
+}
+
+
+/******************************************************************************/
+
+enum piglit_result
+piglit_display(void)
+{
+ return PIGLIT_FAIL;
+}
+
+/**
+ * The main test program.
+ */
+void
+piglit_init(int argc, char **argv)
+{
+ unsigned *queries;
+ unsigned num_queries;
+
+ piglit_require_extension("GL_INTEL_performance_query");
+
+ get_queries(&queries, &num_queries);
+
+ /* If there are no queries, the rest of the tests can't run. Bail. */
+ if (num_queries == 0)
+ exit(0);
+
+ test_basic_measurement(queries[0]);
+
+ exit(0);
+}
diff --git a/tests/spec/intel_performance_query/minmax.c b/tests/spec/intel_performance_query/minmax.c
new file mode 100644
index 0000000..8258fb6
--- /dev/null
+++ b/tests/spec/intel_performance_query/minmax.c
@@ -0,0 +1,58 @@
+/* Copyright © 2014 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.
+ */
+
+#include "piglit-util-gl-common.h"
+#include "minmax-test.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+ config.supports_gl_compat_version = 30;
+ config.supports_gl_es_version = 20;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+enum piglit_result
+piglit_display(void)
+{
+ return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+ GLboolean extended;
+
+ piglit_require_extension("GL_INTEL_performance_query");
+ piglit_print_minmax_header();
+
+ piglit_test_min_int(GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL, 256);
+ piglit_test_min_int(GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL, 256);
+ piglit_test_min_int(GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL, 1024);
+
+ /* No value tested for this */
+ glGetBooleanv(GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL, &extended);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+
+ piglit_report_result(piglit_minmax_pass ? PIGLIT_PASS : PIGLIT_FAIL);
+}
--
1.9.0
More information about the Piglit
mailing list