gallium: enable INTEL_PERFORMANCE_QUERY
authorDongwon Kim <dongwon.kim@intel.com>
Tue, 15 Oct 2019 19:43:04 +0000 (12:43 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 11 Dec 2019 01:02:58 +0000 (17:02 -0800)
new state tracker APIs added for INTEL_performance_query
This extension is enabled if all vendor specific functions for it
exist.

v2: add st_cb_perfquery.* to the list of sources in Makefile
v3: minor code clean-up
v4: - add driver hooks for intel-performance-query apis
    - add PIPE level performance counter and type enums that
      match to OpenGL enums
    - do conversion of pipe_perf_counter_type and
      pipe_perf_counter_data_type enums to GL defines in state_tracker

Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/gallium/include/pipe/p_context.h
src/gallium/include/pipe/p_defines.h
src/mesa/Makefile.sources
src/mesa/meson.build
src/mesa/state_tracker/st_cb_perfquery.c [new file with mode: 0644]
src/mesa/state_tracker/st_cb_perfquery.h [new file with mode: 0644]
src/mesa/state_tracker/st_context.c

index b2a6622210f5a131277902425c33a731f4d53fe8..b8051df57fe860aa1860b010cef4032fb3080134 100644 (file)
@@ -191,6 +191,50 @@ struct pipe_context {
     */
    void (*set_active_query_state)(struct pipe_context *pipe, bool enable);
 
+   /**
+    * INTEL Performance Query
+    */
+   /*@{*/
+
+   unsigned (*init_intel_perf_query_info)(struct pipe_context *pipe);
+
+   void (*get_intel_perf_query_info)(struct pipe_context *pipe,
+                                     unsigned query_index,
+                                     const char **name,
+                                     uint32_t *data_size,
+                                     uint32_t *n_counters,
+                                     uint32_t *n_active);
+
+   void (*get_intel_perf_query_counter_info)(struct pipe_context *pipe,
+                                             unsigned query_index,
+                                             unsigned counter_index,
+                                             const char **name,
+                                             const char **desc,
+                                             uint32_t *offset,
+                                             uint32_t *data_size,
+                                             uint32_t *type_enum,
+                                             uint32_t *data_type_enum,
+                                             uint64_t *raw_max);
+
+   struct pipe_query *(*new_intel_perf_query_obj)(struct pipe_context *pipe,
+                                                 unsigned query_index);
+
+   void (*begin_intel_perf_query)(struct pipe_context *pipe, struct pipe_query *q);
+
+   void (*end_intel_perf_query)(struct pipe_context *pipe, struct pipe_query *q);
+
+   void (*delete_intel_perf_query)(struct pipe_context *pipe, struct pipe_query *q);
+
+   void (*wait_intel_perf_query)(struct pipe_context *pipe, struct pipe_query *q);
+
+   bool (*is_intel_perf_query_ready)(struct pipe_context *pipe, struct pipe_query *q);
+
+   void (*get_intel_perf_query_data)(struct pipe_context *pipe,
+                                     struct pipe_query *q,
+                                     size_t data_size,
+                                     uint32_t *data,
+                                     uint32_t *bytes_written);
+
    /*@}*/
 
    /**
index ca98ee55e9780031bc7614d223dbcf44c874f610..0f6229a57fb51ce1f7baeb842c2190ff1ca23a6e 100644 (file)
@@ -1246,6 +1246,29 @@ enum pipe_debug_type
    PIPE_DEBUG_TYPE_CONFORMANCE,
 };
 
+/**
+ * counter type and counter data type enums used by INTEL_performance_query
+ * APIs in gallium drivers.
+ */
+enum pipe_perf_counter_type
+{
+   PIPE_PERF_COUNTER_TYPE_EVENT,
+   PIPE_PERF_COUNTER_TYPE_DURATION_NORM,
+   PIPE_PERF_COUNTER_TYPE_DURATION_RAW,
+   PIPE_PERF_COUNTER_TYPE_THROUGHPUT,
+   PIPE_PERF_COUNTER_TYPE_RAW,
+   PIPE_PERF_COUNTER_TYPE_TIMESTAMP,
+};
+
+enum pipe_perf_counter_data_type
+{
+   PIPE_PERF_COUNTER_DATA_TYPE_BOOL32,
+   PIPE_PERF_COUNTER_DATA_TYPE_UINT32,
+   PIPE_PERF_COUNTER_DATA_TYPE_UINT64,
+   PIPE_PERF_COUNTER_DATA_TYPE_FLOAT,
+   PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE,
+};
+
 #define PIPE_UUID_SIZE 16
 
 #ifdef __cplusplus
index dfdff434c4dde2cd2e35ef936471195513d13b68..e4252ce80067c2b74a36462b70adbb02ff394e0c 100644 (file)
@@ -483,6 +483,8 @@ STATETRACKER_FILES = \
        state_tracker/st_cb_msaa.h \
        state_tracker/st_cb_perfmon.c \
        state_tracker/st_cb_perfmon.h \
+       state_tracker/st_cb_perfquery.c \
+       state_tracker/st_cb_perfquery.h \
        state_tracker/st_cb_program.c \
        state_tracker/st_cb_program.h \
        state_tracker/st_cb_queryobj.c \
index 1254ccc619ea2449e21914545d1f9b64f091b823..4651ef88d6a18887a510d5e5a90f94f6af68c2eb 100644 (file)
@@ -527,6 +527,8 @@ files_libmesa_gallium = files(
   'state_tracker/st_cb_msaa.h',
   'state_tracker/st_cb_perfmon.c',
   'state_tracker/st_cb_perfmon.h',
+  'state_tracker/st_cb_perfquery.c',
+  'state_tracker/st_cb_perfquery.h',
   'state_tracker/st_cb_program.c',
   'state_tracker/st_cb_program.h',
   'state_tracker/st_cb_queryobj.c',
diff --git a/src/mesa/state_tracker/st_cb_perfquery.c b/src/mesa/state_tracker/st_cb_perfquery.c
new file mode 100644 (file)
index 0000000..b405703
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright © 2019 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 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.
+ */
+
+/**
+ * Intel Performance query interface to gallium.
+ */
+
+#include "st_debug.h"
+#include "st_context.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_perfquery.h"
+#include "st_util.h"
+
+#include "util/bitset.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "util/u_memory.h"
+
+bool
+st_have_perfquery(struct st_context *st)
+{
+   struct pipe_context *pipe = st->pipe;
+
+   return pipe->init_intel_perf_query_info && pipe->get_intel_perf_query_info &&
+          pipe->get_intel_perf_query_counter_info &&
+          pipe->new_intel_perf_query_obj && pipe->begin_intel_perf_query &&
+          pipe->end_intel_perf_query && pipe->delete_intel_perf_query &&
+          pipe->wait_intel_perf_query && pipe->is_intel_perf_query_ready &&
+          pipe->get_intel_perf_query_data;
+}
+
+static unsigned
+st_InitPerfQueryInfo(struct gl_context *ctx)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   return pipe->init_intel_perf_query_info(pipe);
+}
+
+static void
+st_GetPerfQueryInfo(struct gl_context *ctx,
+                    unsigned query_index,
+                    const char **name,
+                    GLuint *data_size,
+                    GLuint *n_counters,
+                    GLuint *n_active)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   pipe->get_intel_perf_query_info(pipe, query_index, name, data_size,
+                                   n_counters, n_active);
+}
+
+static uint32_t
+pipe_counter_type_enum_to_gl_type(enum pipe_perf_counter_type type)
+{
+   switch (type) {
+   case PIPE_PERF_COUNTER_TYPE_EVENT: return GL_PERFQUERY_COUNTER_EVENT_INTEL;
+   case PIPE_PERF_COUNTER_TYPE_DURATION_NORM: return GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL;
+   case PIPE_PERF_COUNTER_TYPE_DURATION_RAW: return GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL;
+   case PIPE_PERF_COUNTER_TYPE_THROUGHPUT: return GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL;
+   case PIPE_PERF_COUNTER_TYPE_RAW: return GL_PERFQUERY_COUNTER_RAW_INTEL;
+   case PIPE_PERF_COUNTER_TYPE_TIMESTAMP: return GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL;
+   default:
+      unreachable("Unknown counter type");
+   }
+}
+
+static uint32_t
+pipe_counter_data_type_to_gl_type(enum pipe_perf_counter_data_type type)
+{
+   switch (type) {
+   case PIPE_PERF_COUNTER_DATA_TYPE_BOOL32: return GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL;
+   case PIPE_PERF_COUNTER_DATA_TYPE_UINT32: return GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL;
+   case PIPE_PERF_COUNTER_DATA_TYPE_UINT64: return GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL;
+   case PIPE_PERF_COUNTER_DATA_TYPE_FLOAT: return GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL;
+   case PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE: return GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL;
+   default:
+      unreachable("Unknown counter data type");
+   }
+}
+
+static void
+st_GetPerfCounterInfo(struct gl_context *ctx,
+                      unsigned query_index,
+                      unsigned counter_index,
+                      const char **name,
+                      const char **desc,
+                      GLuint *offset,
+                      GLuint *data_size,
+                      GLuint *type_enum,
+                      GLuint *data_type_enum,
+                      GLuint64 *raw_max)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+   uint32_t pipe_type_enum;
+   uint32_t pipe_data_type_enum;
+
+   pipe->get_intel_perf_query_counter_info(pipe, query_index, counter_index,
+                                           name, desc, offset, data_size,
+                                           &pipe_type_enum, &pipe_data_type_enum, raw_max);
+   *type_enum = pipe_counter_type_enum_to_gl_type(pipe_type_enum);
+   *data_type_enum = pipe_counter_data_type_to_gl_type(pipe_data_type_enum);
+}
+
+static void
+st_DeletePerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   /* We can assume that the frontend waits for a query to complete
+    * before ever calling into here, so we don't have to worry about
+    * deleting an in-flight query object.
+    */
+   assert(!o->Active);
+   assert(!o->Used || o->Ready);
+
+   pipe->delete_intel_perf_query(pipe, (struct pipe_query *)o);
+}
+
+static bool
+st_BeginPerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   /* We can assume the frontend hides mistaken attempts to Begin a
+    * query object multiple times before its End. Similarly if an
+    * application reuses a query object before results have arrived
+    * the frontend will wait for prior results so we don't need
+    * to support abandoning in-flight results.
+    */
+   assert(!o->Active);
+   assert(!o->Used || o->Ready); /* no in-flight query to worry about */
+
+   pipe->begin_intel_perf_query(pipe, (struct pipe_query *)o);
+
+   return true;
+}
+
+static void
+st_EndPerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   pipe->end_intel_perf_query(pipe, (struct pipe_query *)o);
+}
+
+static void
+st_WaitPerfQuery(struct gl_context *ctx, struct gl_perf_query_object *o)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   assert(!o->Ready);
+
+   pipe->wait_intel_perf_query(pipe, (struct pipe_query *)o);
+}
+
+static bool
+st_IsPerfQueryReady(struct gl_context *ctx, struct gl_perf_query_object *o)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   if (o->Ready)
+      return true;
+
+   return pipe->is_intel_perf_query_ready(pipe, (struct pipe_query *)o);
+}
+
+static void
+st_GetPerfQueryData(struct gl_context *ctx,
+                    struct gl_perf_query_object *o,
+                    GLsizei data_size,
+                    GLuint *data,
+                    GLuint *bytes_written)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   assert(st_IsPerfQueryReady(ctx, o));
+
+   /* We expect that the frontend only calls this hook when it knows
+    * that results are available.
+    */
+   assert(o->Ready);
+
+   pipe->get_intel_perf_query_data(pipe, (struct pipe_query *)o, data_size, data,
+                                   bytes_written);
+}
+
+static struct gl_perf_query_object *
+st_NewPerfQueryObject(struct gl_context *ctx, unsigned query_index)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+   struct pipe_query *q;
+
+   q = pipe->new_intel_perf_query_obj(pipe, query_index);
+
+   return (struct gl_perf_query_object *)q;
+}
+
+void st_init_perfquery_functions(struct dd_function_table *functions)
+{
+   functions->InitPerfQueryInfo = st_InitPerfQueryInfo;
+   functions->GetPerfQueryInfo = st_GetPerfQueryInfo;
+   functions->GetPerfCounterInfo = st_GetPerfCounterInfo;
+   functions->NewPerfQueryObject = st_NewPerfQueryObject;
+   functions->DeletePerfQuery = st_DeletePerfQuery;
+   functions->BeginPerfQuery = st_BeginPerfQuery;
+   functions->EndPerfQuery = st_EndPerfQuery;
+   functions->WaitPerfQuery = st_WaitPerfQuery;
+   functions->IsPerfQueryReady = st_IsPerfQueryReady;
+   functions->GetPerfQueryData = st_GetPerfQueryData;
+}
diff --git a/src/mesa/state_tracker/st_cb_perfquery.h b/src/mesa/state_tracker/st_cb_perfquery.h
new file mode 100644 (file)
index 0000000..1fbcd74
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2019 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 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.
+ */
+
+#ifndef ST_CB_PERFQUERY_H
+#define ST_CB_PERFQUERY_H
+
+bool
+st_have_perfquery(struct st_context *st);
+
+extern void
+st_init_perfquery_functions(struct dd_function_table *functions);
+
+#endif
index e13bc71d1858b991f48fae2f64378a4f06a836a8..c45c7f7e5fbb7d95f34060e81efce5ea0e685a6e 100644 (file)
@@ -57,6 +57,7 @@
 #include "st_cb_memoryobjects.h"
 #include "st_cb_msaa.h"
 #include "st_cb_perfmon.h"
+#include "st_cb_perfquery.h"
 #include "st_cb_program.h"
 #include "st_cb_queryobj.h"
 #include "st_cb_readpixels.h"
@@ -720,6 +721,10 @@ st_create_context_priv(struct gl_context *ctx, struct pipe_context *pipe,
       ctx->Extensions.AMD_performance_monitor = GL_TRUE;
    }
 
+   if (st_have_perfquery(st)) {
+      ctx->Extensions.INTEL_performance_query = GL_TRUE;
+   }
+
    /* Enable shader-based fallbacks for ARB_color_buffer_float if needed. */
    if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) {
       if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) {
@@ -886,6 +891,7 @@ st_init_driver_functions(struct pipe_screen *screen,
    st_init_memoryobject_functions(functions);
    st_init_msaa_functions(functions);
    st_init_perfmon_functions(functions);
+   st_init_perfquery_functions(functions);
    st_init_program_functions(functions);
    st_init_query_functions(functions);
    st_init_cond_render_functions(functions);