[Mesa-dev] [PATCH] mesa: Add core support for the GL_INTEL_performance_query extension.

Petri Latvala petri.latvala at intel.com
Thu Apr 3 02:20:48 PDT 2014


Like AMD_performance_monitor, this extension provides an interface for
applications (and OpenGL-based tools) to access GPU performance
counters. Since the exact performance counters available vary between
vendors and hardware generations, the extension provides an API the
application can use to get the names, types, and minimum/maximum
values of all available counters.

Applications create performance queries based on available query
types, and begin/end measurement collection. Multiple queries can be
measuring simultaneously.

v2: Whitespace changes.
v3: src/mapi/glapi/gen/gl_API.xml: Also expose the functions to GLES2.

Signed-off-by: Petri Latvala <petri.latvala at intel.com>
---
 src/mapi/glapi/gen/INTEL_performance_query.xml |  93 ++++++++++++
 src/mapi/glapi/gen/Makefile.am                 |   1 +
 src/mapi/glapi/gen/gl_API.xml                  |   2 +
 src/mesa/main/config.h                         |   8 +
 src/mesa/main/extensions.c                     |   1 +
 src/mesa/main/get.c                            |   1 +
 src/mesa/main/get_hash_params.py               |   6 +
 src/mesa/main/mtypes.h                         |   1 +
 src/mesa/main/performance_monitor.c            | 195 +++++++++++++++++++++++++
 src/mesa/main/performance_monitor.h            |  43 +++++-
 src/mesa/main/tests/dispatch_sanity.cpp        |  12 ++
 11 files changed, 362 insertions(+), 1 deletion(-)
 create mode 100644 src/mapi/glapi/gen/INTEL_performance_query.xml

diff --git a/src/mapi/glapi/gen/INTEL_performance_query.xml b/src/mapi/glapi/gen/INTEL_performance_query.xml
new file mode 100644
index 0000000..0f4d687
--- /dev/null
+++ b/src/mapi/glapi/gen/INTEL_performance_query.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_INTEL_performance_query" number="443">
+
+  <function name="GetFirstPerfQueryIdINTEL" offset="assign" es2="2.0">
+    <param name="queryId" type="GLuint *"/>
+  </function>
+
+  <function name="GetNextPerfQueryIdINTEL" offset="assign" es2="2.0">
+    <param name="queryId" type="GLuint"/>
+    <param name="nextQueryId" type="GLuint *"/>
+  </function>
+
+  <function name="GetPerfQueryIdByNameINTEL" offset="assign" es2="2.0">
+    <param name="queryName" type="GLchar *"/>
+    <param name="queryId" type="GLuint *"/>
+  </function>
+
+  <function name="GetPerfQueryInfoINTEL" offset="assign" es2="2.0">
+    <param name="queryId" type="GLuint"/>
+    <param name="queryNameLength" type="GLuint"/>
+    <param name="queryName" type="GLchar *"/>
+    <param name="dataSize" type="GLuint *"/>
+    <param name="noCounters" type="GLuint *"/>
+    <param name="noInstances" type="GLuint *"/>
+    <param name="capsMask" type="GLuint *"/>
+  </function>
+
+  <function name="GetPerfCounterInfoINTEL" offset="assign" es2="2.0">
+    <param name="queryId" type="GLuint"/>
+    <param name="counterId" type="GLuint"/>
+    <param name="counterNameLength" type="GLuint"/>
+    <param name="counterName" type="GLchar *"/>
+    <param name="counterDescLength" type="GLuint"/>
+    <param name="counterDesc" type="GLchar *"/>
+    <param name="counterOffset" type="GLuint *"/>
+    <param name="counterDataSize" type="GLuint *"/>
+    <param name="counterTypeEnum" type="GLuint *"/>
+    <param name="counterDataTypeEnum" type="GLuint *"/>
+    <param name="rawCounterMaxValue" type="GLuint64 *"/>
+  </function>
+
+  <function name="CreatePerfQueryINTEL" offset="assign" es2="2.0">
+    <param name="queryId" type="GLuint"/>
+    <param name="queryHandle" type="GLuint *"/>
+  </function>
+
+  <function name="DeletePerfQueryINTEL" offset="assign" es2="2.0">
+    <param name="queryHandle" type="GLuint"/>
+  </function>
+
+  <function name="BeginPerfQueryINTEL" offset="assign" es2="2.0">
+    <param name="queryHandle" type="GLuint"/>
+  </function>
+
+  <function name="EndPerfQueryINTEL" offset="assign" es2="2.0">
+    <param name="queryHandle" type="GLuint"/>
+  </function>
+
+  <function name="GetPerfQueryDataINTEL" offset="assign" es2="2.0">
+    <param name="queryHandle" type="GLuint"/>
+    <param name="flags" type="GLuint"/>
+    <param name="dataSize" type="GLsizei"/>
+    <param name="data" type="GLvoid *"/>
+    <param name="bytesWritten" type="GLuint *"/>
+  </function>
+
+  <enum name="PERFQUERY_SINGLE_CONTEXT_INTEL" value="0x0000"/>
+  <enum name="PERFQUERY_GLOBAL_CONTEXT_INTEL" value="0x0001"/>
+  <enum name="PERFQUERY_WAIT_INTEL" value="0x83FB"/>
+  <enum name="PERFQUERY_FLUSH_INTEL" value="0x83FA"/>
+  <enum name="PERFQUERY_DONOT_FLUSH_INTEL" value="0x83F9"/>
+  <enum name="PERFQUERY_COUNTER_EVENT_INTEL" value="0x94F0"/>
+  <enum name="PERFQUERY_COUNTER_DURATION_NORM_INTEL" value="0x94F1"/>
+  <enum name="PERFQUERY_COUNTER_DURATION_RAW_INTEL" value="0x94F2"/>
+  <enum name="PERFQUERY_COUNTER_THROUGHPUT_INTEL" value="0x94F3"/>
+  <enum name="PERFQUERY_COUNTER_RAW_INTEL" value="0x94F4"/>
+  <enum name="PERFQUERY_COUNTER_TIMESTAMP_INTEL" value="0x94F5"/>
+  <enum name="PERFQUERY_COUNTER_DATA_UINT32_INTEL" value="0x94F8"/>
+  <enum name="PERFQUERY_COUNTER_DATA_UINT64_INTEL" value="0x94F9"/>
+  <enum name="PERFQUERY_COUNTER_DATA_FLOAT_INTEL" value="0x94FA"/>
+  <enum name="PERFQUERY_COUNTER_DATA_DOUBLE_INTEL" value="0x94FB"/>
+  <enum name="PERFQUERY_COUNTER_DATA_BOOL32_INTEL" value="0x94FC"/>
+  <enum name="PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL" value="0x94FD"/>
+  <enum name="PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL" value="0x94FE"/>
+  <enum name="PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL" value="0x94FF"/>
+  <enum name="PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL" value="0x9500"/>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/Makefile.am b/src/mapi/glapi/gen/Makefile.am
index 7b3c118..1c5b61c 100644
--- a/src/mapi/glapi/gen/Makefile.am
+++ b/src/mapi/glapi/gen/Makefile.am
@@ -147,6 +147,7 @@ API_XML = \
 	EXT_texture_array.xml \
 	EXT_texture_integer.xml \
 	EXT_transform_feedback.xml \
+	INTEL_performance_query.xml \
 	NV_conditional_render.xml \
 	NV_primitive_restart.xml \
 	NV_texture_barrier.xml \
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 9129d57..8fbf700 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -12840,6 +12840,8 @@
     <enum name="SKIP_DECODE_EXT"                      value="0x8A4A"/>
 </category>
 
+<xi:include href="INTEL_performance_query.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
 <!-- Unnumbered extensions sorted by name. -->
 
 <category name="GL_ATI_blend_equation_separate">
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index 30da5d4..c96502a 100644
--- a/src/mesa/main/config.h
+++ b/src/mesa/main/config.h
@@ -281,6 +281,14 @@
 #define MAX_VERTEX_STREAMS                  4
 /*@}*/
 
+/** For GL_INTEL_performance_query */
+/*@{*/
+#define MAX_PERFQUERY_QUERY_NAME_LENGTH     256
+#define MAX_PERFQUERY_COUNTER_NAME_LENGTH   256
+#define MAX_PERFQUERY_COUNTER_DESC_LENGTH   1024
+#define PERFQUERY_HAVE_GPA_EXTENDED_COUNTERS 0
+/*@}*/
+
 /*
  * Color channel component order
  * 
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index a72284c..e8f125d 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -330,6 +330,7 @@ static const struct extension extension_table[] = {
    { "GL_IBM_rasterpos_clip",                      o(dummy_true),                              GLL,            1996 },
    { "GL_IBM_texture_mirrored_repeat",             o(dummy_true),                              GLL,            1998 },
    { "GL_INGR_blend_func_separate",                o(EXT_blend_func_separate),                 GLL,            1999 },
+   { "GL_INTEL_performance_query",                 o(INTEL_performance_query),                 GL | ES2,       2013 },
    { "GL_MESA_pack_invert",                        o(MESA_pack_invert),                        GL,             2002 },
    { "GL_MESA_texture_signed_rgba",                o(EXT_texture_snorm),                       GL,             2009 },
    { "GL_MESA_window_pos",                         o(dummy_true),                              GLL,            2000 },
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 88cf202..8c4ac08 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -394,6 +394,7 @@ EXTRA_EXT(ARB_viewport_array);
 EXTRA_EXT(ARB_compute_shader);
 EXTRA_EXT(ARB_gpu_shader5);
 EXTRA_EXT2(ARB_transform_feedback3, ARB_gpu_shader5);
+EXTRA_EXT(INTEL_performance_query);
 
 static const int
 extra_ARB_color_buffer_float_or_glcore[] = {
diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py
index 674d003..4c0838e 100644
--- a/src/mesa/main/get_hash_params.py
+++ b/src/mesa/main/get_hash_params.py
@@ -311,6 +311,12 @@ descriptor=[
 # GL_ARB_get_program_binary / GL_OES_get_program_binary
   [ "NUM_PROGRAM_BINARY_FORMATS", "CONST(0), NO_EXTRA" ],
   [ "PROGRAM_BINARY_FORMATS", "LOC_CUSTOM, TYPE_INVALID, 0, NO_EXTRA" ],
+
+# GL_INTEL_performance_query
+  [ "PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL", "CONST(MAX_PERFQUERY_QUERY_NAME_LENGTH), extra_INTEL_performance_query" ],
+  [ "PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL", "CONST(MAX_PERFQUERY_COUNTER_NAME_LENGTH), extra_INTEL_performance_query" ],
+  [ "PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL", "CONST(MAX_PERFQUERY_COUNTER_DESC_LENGTH), extra_INTEL_performance_query" ],
+  [ "PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL", "CONST(PERFQUERY_HAVE_GPA_EXTENDED_COUNTERS), extra_INTEL_performance_query" ],
 ]},
 
 # GLES3 is not a typo.
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index c6d90c5..aa39f79 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -3598,6 +3598,7 @@ struct gl_extensions
    GLboolean ATI_texture_env_combine3;
    GLboolean ATI_fragment_shader;
    GLboolean ATI_separate_stencil;
+   GLboolean INTEL_performance_query;
    GLboolean MESA_pack_invert;
    GLboolean MESA_ycbcr_texture;
    GLboolean NV_conditional_render;
diff --git a/src/mesa/main/performance_monitor.c b/src/mesa/main/performance_monitor.c
index e62f770..dd22fef 100644
--- a/src/mesa/main/performance_monitor.c
+++ b/src/mesa/main/performance_monitor.c
@@ -639,3 +639,198 @@ _mesa_perf_monitor_counter_size(const struct gl_perf_monitor_counter *c)
       return 0;
    }
 }
+
+extern void GLAPIENTRY
+_mesa_GetFirstPerfQueryIdINTEL(GLuint *queryId)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If queryId pointer is equal to 0, INVALID_VALUE error is generated."
+    */
+   if (!queryId) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glGetFirstPerfQueryIdINTEL(queryId == NULL)");
+      return;
+   }
+
+   /* "If the given hardware platform doesn't support any performance queries,
+    * then the value of 0 is returned and INVALID_OPERATION error is raised."
+    */
+
+   *queryId = 0;
+   _mesa_error(ctx, GL_INVALID_OPERATION,
+               "glGetFirstPerfQueryIdINTEL(no queries supported)");
+}
+
+extern void GLAPIENTRY
+_mesa_GetNextPerfQueryIdINTEL(GLuint queryId, GLuint *nextQueryId)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If nextQueryId pointer is equal to 0, an INVALID_VALUE error is
+    * generated."
+    */
+   if (!nextQueryId) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glGetNextPerfQueryIdINTEL(nextQueryId == NULL)");
+      return;
+   }
+
+   /* "If the specified performance
+    * query identifier is invalid then INVALID_VALUE error is generated."
+    *
+    * No queries are supported, so all queries are invalid.
+    *
+    * "Whenever error is generated, the value of 0 is returned."
+    */
+   *nextQueryId = 0;
+   _mesa_error(ctx, GL_INVALID_VALUE,
+               "glGetNextPerfQueryIdINTEL(invalid query)");
+}
+
+extern void GLAPIENTRY
+_mesa_GetPerfQueryIdByNameINTEL(char *queryName, GLuint *queryId)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If queryName does not reference a valid query name, an INVALID_VALUE
+    * error is generated."
+    *
+    * No queries are supported, so all query names are invalid.
+    */
+
+   _mesa_error(ctx, GL_INVALID_VALUE,
+               "glGetPerfQueryIdByNameINTEL(invalid query name)");
+}
+
+extern void GLAPIENTRY
+_mesa_GetPerfQueryInfoINTEL(GLuint queryId,
+                            GLuint queryNameLength, char *queryName,
+                            GLuint *dataSize, GLuint *noCounters,
+                            GLuint *noActiveInstances,
+                            GLuint *capsMask)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If queryId does not reference a valid query type, an INVALID_VALUE
+    * error is generated."
+    *
+    * No queries are supported, so all queries are invalid.
+    */
+
+   _mesa_error(ctx, GL_INVALID_VALUE,
+               "glGetPerfQueryInfoINTEL(invalid query)");
+}
+
+extern void GLAPIENTRY
+_mesa_GetPerfCounterInfoINTEL(GLuint queryId, GLuint counterId,
+                              GLuint counterNameLength, char *counterName,
+                              GLuint counterDescLength, char *counterDesc,
+                              GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum,
+                              GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If the pair of queryId and counterId does not reference a valid counter,
+    * an INVALID_VALUE error is generated."
+    *
+    * No queries are supported, so all queries are invalid.
+    */
+
+   _mesa_error(ctx, GL_INVALID_VALUE,
+               "glGetPerfCounterInfoINTEL(invalid counterId)");
+}
+
+extern void GLAPIENTRY
+_mesa_CreatePerfQueryINTEL(GLuint queryId, GLuint *queryHandle)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If queryId does not reference a valid query type,
+    * an INVALID_VALUE error is generated."
+    *
+    * No queries are supported, so all queries are invalid.
+    */
+
+   _mesa_error(ctx, GL_INVALID_VALUE,
+               "glCreatePerfQueryINTEL(invalid queryId)");
+}
+
+extern void GLAPIENTRY
+_mesa_DeletePerfQueryINTEL(GLuint queryHandle)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If a query handle doesn't reference a previously created performance
+    * query instance, an INVALID_VALUE error is generated."
+    *
+    * No queries are supported, so all queries are invalid.
+    */
+
+   _mesa_error(ctx, GL_INVALID_VALUE,
+               "glDeletePerfQueryINTEL(invalid queryHandle)");
+}
+
+extern void GLAPIENTRY
+_mesa_BeginPerfQueryINTEL(GLuint queryHandle)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If a query handle doesn't reference a previously created performance
+    * query instance, an INVALID_VALUE error is generated."
+    *
+    * No queries are supported, so all queries are invalid.
+    */
+
+   _mesa_error(ctx, GL_INVALID_VALUE,
+               "glBeginPerfQueryINTEL(invalid queryHandle)");
+}
+
+extern void GLAPIENTRY
+_mesa_EndPerfQueryINTEL(GLuint queryHandle)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If a performance query is not currently started, an INVALID_OPERATION
+    * error will be generated."
+    *
+    * The specification doesn't state that an invalid handle would be an
+    * INVALID_VALUE error. Regardless, query for such a handle will not be
+    * started, so we generate an INVALID_OPERATION in that case.
+    *
+    * No queries are supported, so all handles are invalid.
+    */
+
+   _mesa_error(ctx, GL_INVALID_OPERATION,
+               "glEndPerfQueryINTEL(query not started)");
+}
+
+extern void GLAPIENTRY
+_mesa_GetPerfQueryDataINTEL(GLuint queryHandle, GLuint flags,
+                            GLsizei dataSize, void *data, GLuint *bytesWritten)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* "If bytesWritten or data pointers are NULL then an INVALID_VALUE error
+    * is generated."
+    */
+   if (!bytesWritten || !data) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glGetPerfQueryDataINTEL(bytesWritten or data is NULL)");
+      return;
+   }
+
+   /* The specification doesn't state that an invalid handle generates an
+    * error. We could interpret that to mean the case should be handled as
+    * "measurement not ready for this query", but what should be done if
+    * `flags' equals PERFQUERY_WAIT_INTEL?
+    *
+    * To resolve this, we just generate an INVALID_VALUE from an invalid query
+    * handle.
+    *
+    * No queries are supported, so all handles are invalid.
+    */
+
+   _mesa_error(ctx, GL_INVALID_VALUE,
+               "glGetPerfQueryDataINTEL(invalid queryHandle)");
+}
diff --git a/src/mesa/main/performance_monitor.h b/src/mesa/main/performance_monitor.h
index 76234e5..7b311e4 100644
--- a/src/mesa/main/performance_monitor.h
+++ b/src/mesa/main/performance_monitor.h
@@ -23,7 +23,8 @@
 
 /**
  * \file performance_monitor.h
- * Core Mesa support for the AMD_performance_monitor extension.
+ * Core Mesa support for the AMD_performance_monitor extension and the
+ * INTEL_performance_query extension.
  */
 
 #pragma once
@@ -85,4 +86,44 @@ _mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname,
 unsigned
 _mesa_perf_monitor_counter_size(const struct gl_perf_monitor_counter *);
 
+
+extern void GLAPIENTRY
+_mesa_GetFirstPerfQueryIdINTEL(GLuint *queryId);
+
+extern void GLAPIENTRY
+_mesa_GetNextPerfQueryIdINTEL(GLuint queryId, GLuint *nextQueryId);
+
+extern void GLAPIENTRY
+_mesa_GetPerfQueryIdByNameINTEL(char *queryName, GLuint *queryId);
+
+extern void GLAPIENTRY
+_mesa_GetPerfQueryInfoINTEL(GLuint queryId,
+                            GLuint queryNameLength, char *queryName,
+                            GLuint *dataSize, GLuint *noCounters,
+                            GLuint *noActiveInstances,
+                            GLuint *capsMask);
+
+extern void GLAPIENTRY
+_mesa_GetPerfCounterInfoINTEL(GLuint queryId, GLuint counterId,
+                              GLuint counterNameLength, char *counterName,
+                              GLuint counterDescLength, char *counterDesc,
+                              GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum,
+                              GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+
+extern void GLAPIENTRY
+_mesa_CreatePerfQueryINTEL(GLuint queryId, GLuint *queryHandle);
+
+extern void GLAPIENTRY
+_mesa_DeletePerfQueryINTEL(GLuint queryHandle);
+
+extern void GLAPIENTRY
+_mesa_BeginPerfQueryINTEL(GLuint queryHandle);
+
+extern void GLAPIENTRY
+_mesa_EndPerfQueryINTEL(GLuint queryHandle);
+
+extern void GLAPIENTRY
+_mesa_GetPerfQueryDataINTEL(GLuint queryHandle, GLuint flags,
+                            GLsizei dataSize, void *data, GLuint *bytesWritten);
+
 #endif
diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
index 8ff975f..672302f 100644
--- a/src/mesa/main/tests/dispatch_sanity.cpp
+++ b/src/mesa/main/tests/dispatch_sanity.cpp
@@ -912,6 +912,18 @@ const struct function gl_core_functions_possible[] = {
    { "glEndPerfMonitorAMD", 11, -1 },
    { "glGetPerfMonitorCounterDataAMD", 11, -1 },
 
+   /* GL_INTEL_performance_query */
+   { "glGetFirstPerfQueryIdINTEL", 30, -1 },
+   { "glGetNextPerfQueryIdINTEL", 30, -1 },
+   { "glGetPerfQueryIdByNameINTEL", 30, -1 },
+   { "glGetPerfQueryInfoINTEL", 30, -1 },
+   { "glGetPerfCounterInfoINTEL", 30, -1 },
+   { "glCreatePerfQueryINTEL", 30, -1 },
+   { "glDeletePerfQueryINTEL", 30, -1 },
+   { "glBeginPerfQueryINTEL", 30, -1 },
+   { "glEndPerfQueryINTEL", 30, -1 },
+   { "glGetPerfQueryDataINTEL", 30, -1 },
+
    /* GL_NV_vdpau_interop */
    { "glVDPAUInitNV", 11, -1 },
    { "glVDPAUFiniNV", 11, -1 },
-- 
1.9.0



More information about the mesa-dev mailing list