iris: INTEL performance query implementation
authorDongwon Kim <dongwon.kim@intel.com>
Tue, 15 Oct 2019 19:43:02 +0000 (12:43 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 11 Dec 2019 01:02:58 +0000 (17:02 -0800)
low-level implementation of INTEL-performance-query APIs in
Intel iris driver. Most of functions and procedures defined here
are adopted from i965 driver (brw_performance_query.c)

v2: - replace genX_init_performance_query with
      iris_init_perfquery_functions which is gen's version agnositic
    - general code clean-up

v3: include gen_perf_gens.h as some of defines were moved to this new
    header file

v4: - checking for kernel 4.13+ won't be needed here as Iris won't be
      loaded anyway without DRM_SYNCOBJ that is enabled after Kernel
      4.13.

    - checking whether gen < 8 or is_cherryview won't be required as
      well because those cases are screened in iris_screen_create.

v5: remove genX(init_performance_query)

v6: - remove oa_metrics_kernel_support as iris works only with kernel
    4.18 and newer.

    - use perf functions defined in separate file, iris_perf.h/c

Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/gallium/drivers/iris/Makefile.sources
src/gallium/drivers/iris/iris_context.c
src/gallium/drivers/iris/iris_context.h
src/gallium/drivers/iris/iris_performance_query.c [new file with mode: 0644]
src/gallium/drivers/iris/meson.build

index c203df18c65793cb854289cc0aeb581673443746..2477d1e1369d699d7e3544c9f198105dbee9a864 100644 (file)
@@ -45,6 +45,7 @@ IRIS_C_SOURCES = \
        iris_genx_macros.h \
        iris_genx_protos.h \
        iris_monitor.c \
+       iris_performance_query.c \
        iris_perf.c \
        iris_pipe.h \
        iris_pipe_control.c \
index ebbb865a1508ab94d6a0431236e2a3311b470b4e..b95ef707bf5fcba3b9efb9a3027e9672c79a1df2 100644 (file)
@@ -272,6 +272,7 @@ iris_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags)
    iris_init_program_functions(ctx);
    iris_init_resource_functions(ctx);
    iris_init_flush_functions(ctx);
+   iris_init_perfquery_functions(ctx);
 
    iris_init_program_cache(ice);
    iris_init_border_color_pool(ice);
index b81cd30441a33d0fd2a6c181c34b2742b8564f76..ab09d1536615b1a430fd0a849adec7dc2d2ebe5a 100644 (file)
@@ -767,6 +767,7 @@ void iris_init_blit_functions(struct pipe_context *ctx);
 void iris_init_clear_functions(struct pipe_context *ctx);
 void iris_init_program_functions(struct pipe_context *ctx);
 void iris_init_resource_functions(struct pipe_context *ctx);
+void iris_init_perfquery_functions(struct pipe_context *ctx);
 void iris_update_compiled_shaders(struct iris_context *ice);
 void iris_update_compiled_compute_shader(struct iris_context *ice);
 void iris_fill_cs_push_const_buffer(struct brw_cs_prog_data *cs_prog_data,
diff --git a/src/gallium/drivers/iris/iris_performance_query.c b/src/gallium/drivers/iris/iris_performance_query.c
new file mode 100644 (file)
index 0000000..2f99076
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * 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.
+ */
+
+#include <xf86drm.h>
+
+#include "iris_context.h"
+#include "iris_perf.h"
+
+#include "perf/gen_perf.h"
+#include "perf/gen_perf_regs.h"
+
+struct iris_perf_query {
+   struct gl_perf_query_object base;
+   struct gen_perf_query_object *query;
+};
+
+static unsigned
+iris_init_perf_query_info(struct pipe_context *pipe)
+{
+   struct iris_context *ice = (void *) pipe;
+   struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;
+   struct gen_perf_config *perf_cfg = NULL;
+
+   /* make sure pipe perf counter type/data-type enums are matched with gen_perf's */
+   STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_EVENT == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_EVENT);
+   STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_NORM == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_DURATION_NORM);
+   STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_RAW == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_DURATION_RAW);
+   STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_THROUGHPUT == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_THROUGHPUT);
+   STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_RAW == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_RAW);
+
+   STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_BOOL32 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_BOOL32);
+   STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT32 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_UINT32);
+   STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT64 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_UINT64);
+   STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_FLOAT == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_FLOAT);
+   STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_DOUBLE);
+
+   if (!ice->perf_ctx)
+      ice->perf_ctx = gen_perf_new_context(ice);
+
+   if (unlikely(!ice->perf_ctx))
+      return 0;
+
+   perf_cfg = gen_perf_config(ice->perf_ctx);
+
+   if (perf_cfg)
+      return perf_cfg->n_queries;
+
+   perf_cfg = gen_perf_new(ice->perf_ctx);
+
+   iris_perf_init_vtbl(perf_cfg);
+
+   gen_perf_init_context(ice->perf_ctx,
+                         perf_cfg,
+                         ice,
+                         screen->bufmgr,
+                         &screen->devinfo,
+                         ice->batches[IRIS_BATCH_RENDER].hw_ctx_id,
+                         screen->fd);
+
+   gen_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd);
+
+   return perf_cfg->n_queries;
+}
+
+static struct pipe_query *
+iris_new_perf_query_obj(struct pipe_context *pipe, unsigned query_index)
+{
+   struct iris_context *ice = (void *) pipe;
+   struct gen_perf_context *perf_ctx = ice->perf_ctx;
+   struct gen_perf_query_object * obj = gen_perf_new_query(perf_ctx, query_index);
+   if (unlikely(!obj))
+      return NULL;
+
+   struct iris_perf_query *q = calloc(1, sizeof(struct iris_perf_query));
+   if (unlikely(!q)) {
+      gen_perf_delete_query(perf_ctx, obj);
+      return NULL;
+   }
+
+   q->query = obj;
+   return (struct pipe_query *)&q->base;
+}
+
+static void
+iris_begin_perf_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+   struct iris_context *ice = (void *) pipe;
+   struct iris_perf_query *perf_query= (struct iris_perf_query *) q;
+   struct gen_perf_query_object *obj = perf_query->query;
+   struct gen_perf_context *perf_ctx = ice->perf_ctx;
+
+   gen_perf_begin_query(perf_ctx, obj);
+}
+
+static void
+iris_end_perf_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+   struct iris_context *ice = (void *) pipe;
+   struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
+   struct gen_perf_query_object *obj = perf_query->query;
+   struct gen_perf_context *perf_ctx = ice->perf_ctx;
+
+   gen_perf_end_query(perf_ctx, obj);
+}
+
+static void
+iris_delete_perf_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+   struct iris_context *ice = (void *) pipe;
+   struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
+   struct gen_perf_query_object *obj = perf_query->query;
+   struct gen_perf_context *perf_ctx = ice->perf_ctx;
+
+   gen_perf_delete_query(perf_ctx, obj);
+   free(q);
+}
+
+static void
+iris_get_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)
+{
+   struct iris_context *ice = (void *) pipe;
+   struct gen_perf_context *perf_ctx = ice->perf_ctx;
+   struct gen_perf_config *perf_cfg = gen_perf_config(perf_ctx);
+   const struct gen_perf_query_info *info = &perf_cfg->queries[query_index];
+
+   *name = info->name;
+   *data_size = info->data_size;
+   *n_counters = info->n_counters;
+   *n_active = gen_perf_active_queries(perf_ctx, info);
+}
+
+static void
+iris_get_perf_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 iris_context *ice = (void *) pipe;
+   struct gen_perf_context *perf_ctx = ice->perf_ctx;
+   struct gen_perf_config *perf_cfg = gen_perf_config(perf_ctx);
+   const struct gen_perf_query_info *info = &perf_cfg->queries[query_index];
+   const struct gen_perf_query_counter *counter = &info->counters[counter_index];
+
+   *name = counter->name;
+   *desc = counter->desc;
+   *offset = counter->offset;
+   *data_size = gen_perf_query_counter_get_size(counter);
+   *type_enum = counter->type;
+   *data_type_enum = counter->data_type;
+   *raw_max = counter->raw_max;
+}
+
+static void
+iris_wait_perf_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+   struct iris_context *ice = (void *) pipe;
+   struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
+   struct gen_perf_query_object *obj = perf_query->query;
+   struct gen_perf_context *perf_ctx = ice->perf_ctx;
+
+   gen_perf_wait_query(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER]);
+}
+
+static bool
+iris_is_perf_query_ready(struct pipe_context *pipe, struct pipe_query *q)
+{
+   struct iris_context *ice = (void *) pipe;
+   struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
+   struct gen_perf_query_object *obj = perf_query->query;
+   struct gen_perf_context *perf_ctx = ice->perf_ctx;
+
+   if (perf_query->base.Ready)
+      return true;
+
+   return gen_perf_is_query_ready(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER]);
+}
+
+static void
+iris_get_perf_query_data(struct pipe_context *pipe,
+                         struct pipe_query *q,
+                         size_t data_size,
+                         uint32_t *data,
+                         uint32_t *bytes_written)
+{
+   struct iris_context *ice = (void *) pipe;
+   struct iris_perf_query *perf_query = (struct iris_perf_query *) q;
+   struct gen_perf_query_object *obj = perf_query->query;
+   struct gen_perf_context *perf_ctx = ice->perf_ctx;
+
+   gen_perf_get_query_data(perf_ctx, obj, data_size, data, bytes_written);
+}
+
+void
+iris_init_perfquery_functions(struct pipe_context *ctx)
+{
+   ctx->init_intel_perf_query_info = iris_init_perf_query_info;
+   ctx->get_intel_perf_query_info = iris_get_perf_query_info;
+   ctx->get_intel_perf_query_counter_info = iris_get_perf_counter_info;
+   ctx->new_intel_perf_query_obj = iris_new_perf_query_obj;
+   ctx->begin_intel_perf_query = iris_begin_perf_query;
+   ctx->end_intel_perf_query = iris_end_perf_query;
+   ctx->delete_intel_perf_query = iris_delete_perf_query;
+   ctx->wait_intel_perf_query = iris_wait_perf_query;
+   ctx->is_intel_perf_query_ready = iris_is_perf_query_ready;
+   ctx->get_intel_perf_query_data = iris_get_perf_query_data;
+}
index f175b84fc1ff4576f19592ca3b71745fc538708d..1ed507bc10446e27dc2ecaa5fc70834fbe769dc5 100644 (file)
@@ -40,6 +40,7 @@ files_libiris = files(
   'iris_perf.h',
   'iris_perf.c',
   'iris_monitor.c',
+  'iris_performance_query.c',
   'iris_pipe.h',
   'iris_pipe_control.c',
   'iris_program.c',