[PATCH 01/12] etnaviv: add perfmon query implementation

Christian Gmeiner christian.gmeiner at gmail.com
Sun Mar 25 20:29:56 UTC 2018


Add needed infrastructure to use performance monitor
requests for queries.

Signed-off-by: Christian Gmeiner <christian.gmeiner at gmail.com>
---
 configure.ac                                       |   2 +-
 meson.build                                        |   2 +-
 src/gallium/drivers/etnaviv/Makefile.sources       |   2 +
 src/gallium/drivers/etnaviv/etnaviv_query.c        |  11 +-
 src/gallium/drivers/etnaviv/etnaviv_query.h        |   1 +
 src/gallium/drivers/etnaviv/etnaviv_query_pm.c     | 272 +++++++++++++++++++++
 .../{etnaviv_query.h => etnaviv_query_pm.h}        |  49 ++--
 src/gallium/drivers/etnaviv/etnaviv_screen.c       |   8 +
 src/gallium/drivers/etnaviv/etnaviv_screen.h       |   4 +
 9 files changed, 321 insertions(+), 30 deletions(-)
 create mode 100644 src/gallium/drivers/etnaviv/etnaviv_query_pm.c
 copy src/gallium/drivers/etnaviv/{etnaviv_query.h => etnaviv_query_pm.h} (57%)

diff --git a/configure.ac b/configure.ac
index 99805e0f2b..d9b14c0850 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,7 +79,7 @@ LIBDRM_INTEL_REQUIRED=2.4.75
 LIBDRM_NVVIEUX_REQUIRED=2.4.66
 LIBDRM_NOUVEAU_REQUIRED=2.4.66
 LIBDRM_FREEDRENO_REQUIRED=2.4.91
-LIBDRM_ETNAVIV_REQUIRED=2.4.82
+LIBDRM_ETNAVIV_REQUIRED=2.4.89
 
 dnl Versions for external dependencies
 DRI2PROTO_REQUIRED=2.8
diff --git a/meson.build b/meson.build
index 041d2bfc70..2a9ca3b719 100644
--- a/meson.build
+++ b/meson.build
@@ -1051,7 +1051,7 @@ if with_gallium_nouveau or with_dri_nouveau
   dep_libdrm_nouveau = dependency('libdrm_nouveau', version : '>= 2.4.66')
 endif
 if with_gallium_etnaviv
-  dep_libdrm_etnaviv = dependency('libdrm_etnaviv', version : '>= 2.4.82')
+  dep_libdrm_etnaviv = dependency('libdrm_etnaviv', version : '>= 2.4.89')
 endif
 if with_gallium_freedreno
   dep_libdrm_freedreno = dependency('libdrm_freedreno', version : '>= 2.4.91')
diff --git a/src/gallium/drivers/etnaviv/Makefile.sources b/src/gallium/drivers/etnaviv/Makefile.sources
index 587d369dfb..05df2d9c5f 100644
--- a/src/gallium/drivers/etnaviv/Makefile.sources
+++ b/src/gallium/drivers/etnaviv/Makefile.sources
@@ -35,6 +35,8 @@ C_SOURCES :=  \
 	etnaviv_query_hw.h \
 	etnaviv_query_sw.c \
 	etnaviv_query_sw.h \
+	etnaviv_query_pm.c \
+	etnaviv_query_pm.h \
 	etnaviv_rasterizer.c \
 	etnaviv_rasterizer.h \
 	etnaviv_resource.c \
diff --git a/src/gallium/drivers/etnaviv/etnaviv_query.c b/src/gallium/drivers/etnaviv/etnaviv_query.c
index 2d257a9d34..00f87d22cb 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_query.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_query.c
@@ -32,6 +32,7 @@
 #include "etnaviv_query.h"
 #include "etnaviv_query_hw.h"
 #include "etnaviv_query_sw.h"
+#include "etnaviv_query_pm.h"
 
 static struct pipe_query *
 etna_create_query(struct pipe_context *pctx, unsigned query_type,
@@ -43,6 +44,8 @@ etna_create_query(struct pipe_context *pctx, unsigned query_type,
    q = etna_sw_create_query(ctx, query_type);
    if (!q)
       q = etna_hw_create_query(ctx, query_type);
+   if (!q)
+      q = etna_pm_create_query(ctx, query_type);
 
    return (struct pipe_query *)q;
 }
@@ -103,11 +106,15 @@ etna_get_driver_query_info(struct pipe_screen *pscreen, unsigned index,
                            struct pipe_driver_query_info *info)
 {
    int nr_sw_queries = etna_sw_get_driver_query_info(pscreen, 0, NULL);
+   int nr_pm_queries = etna_pm_get_driver_query_info(pscreen, 0, NULL);
 
    if (!info)
-      return nr_sw_queries;
+      return nr_sw_queries + nr_pm_queries;
+
+   if (index < nr_sw_queries)
+      return etna_sw_get_driver_query_info(pscreen, index, info);
 
-   return etna_sw_get_driver_query_info(pscreen, index, info);
+   return etna_pm_get_driver_query_info(pscreen, index - nr_sw_queries, info);
 }
 
 static int
diff --git a/src/gallium/drivers/etnaviv/etnaviv_query.h b/src/gallium/drivers/etnaviv/etnaviv_query.h
index 8927266057..d738fb9e81 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_query.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_query.h
@@ -54,6 +54,7 @@ etna_query(struct pipe_query *pq)
 }
 
 #define ETNA_SW_QUERY_BASE       (PIPE_QUERY_DRIVER_SPECIFIC + 0)
+#define ETNA_PM_QUERY_BASE       (PIPE_QUERY_DRIVER_SPECIFIC + 32)
 
 void
 etna_query_screen_init(struct pipe_screen *pscreen);
diff --git a/src/gallium/drivers/etnaviv/etnaviv_query_pm.c b/src/gallium/drivers/etnaviv/etnaviv_query_pm.c
new file mode 100644
index 0000000000..2b09e5dac1
--- /dev/null
+++ b/src/gallium/drivers/etnaviv/etnaviv_query_pm.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2017 Etnaviv Project
+ * Copyright (C) 2017 Zodiac Inflight Innovations
+ *
+ * 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, sub license,
+ * 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 NON-INFRINGEMENT. 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.
+ *
+ * Authors:
+ *    Christian Gmeiner <christian.gmeiner at gmail.com>
+ */
+
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+
+#include "etnaviv_context.h"
+#include "etnaviv_query_pm.h"
+#include "etnaviv_screen.h"
+
+struct etna_perfmon_source
+{
+   const char *domain;
+   const char *signal;
+};
+
+struct etna_perfmon_config
+{
+   const char *name;
+   unsigned type;
+   const struct etna_perfmon_source *source;
+};
+
+static const struct etna_perfmon_config query_config[] = {
+};
+
+static const struct etna_perfmon_config *
+etna_pm_query_config(unsigned type)
+{
+   for (unsigned i = 0; i < ARRAY_SIZE(query_config); i++)
+      if (query_config[i].type == type)
+         return &query_config[i];
+
+   return NULL;
+}
+
+static struct etna_perfmon_signal *
+etna_pm_query_signal(struct etna_perfmon *perfmon,
+                     const struct etna_perfmon_source *source)
+{
+   struct etna_perfmon_domain *domain;
+
+   domain = etna_perfmon_get_dom_by_name(perfmon, source->domain);
+   if (!domain)
+      return NULL;
+
+   return etna_perfmon_get_sig_by_name(domain, source->signal);
+}
+
+static inline bool
+etna_pm_cfg_supported(struct etna_perfmon *perfmon,
+                      const struct etna_perfmon_config *cfg)
+{
+   struct etna_perfmon_signal *signal = etna_pm_query_signal(perfmon, cfg->source);
+
+   return !!signal;
+}
+
+static inline void
+etna_pm_add_signal(struct etna_pm_query *pq, struct etna_perfmon *perfmon,
+                   const struct etna_perfmon_config *cfg)
+{
+   struct etna_perfmon_signal *signal = etna_pm_query_signal(perfmon, cfg->source);
+
+   pq->signal = signal;
+}
+
+static bool
+realloc_query_bo(struct etna_context *ctx, struct etna_pm_query *pq)
+{
+   if (pq->bo)
+      etna_bo_del(pq->bo);
+
+   pq->bo = etna_bo_new(ctx->screen->dev, 64, DRM_ETNA_GEM_CACHE_WC);
+   if (unlikely(!pq->bo))
+      return false;
+
+   pq->data = etna_bo_map(pq->bo);
+
+   return true;
+}
+
+static void
+etna_pm_query_get(struct etna_cmd_stream *stream, struct etna_query *q,
+                  unsigned flags)
+{
+   struct etna_pm_query *pq = etna_pm_query(q);
+   unsigned offset;
+   assert(flags);
+
+   if (flags == ETNA_PM_PROCESS_PRE)
+      offset = 2;
+   else
+      offset = 3;
+
+   struct etna_perf p = {
+      .flags = flags,
+      .sequence = pq->sequence,
+      .bo = pq->bo,
+      .signal = pq->signal,
+      .offset = offset
+   };
+
+   etna_cmd_stream_perf(stream, &p);
+}
+
+static inline void
+etna_pm_query_update(struct etna_query *q)
+{
+   struct etna_pm_query *pq = etna_pm_query(q);
+
+   if (pq->data[0] == pq->sequence)
+      pq->ready = true;
+}
+
+static void
+etna_pm_destroy_query(struct etna_context *ctx, struct etna_query *q)
+{
+   struct etna_pm_query *pq = etna_pm_query(q);
+
+   etna_bo_del(pq->bo);
+   FREE(pq);
+}
+
+static boolean
+etna_pm_begin_query(struct etna_context *ctx, struct etna_query *q)
+{
+   struct etna_pm_query *pq = etna_pm_query(q);
+
+   pq->ready = false;
+   pq->sequence++;
+
+   etna_pm_query_get(ctx->stream, q, ETNA_PM_PROCESS_PRE);
+
+   return true;
+}
+
+static void
+etna_pm_end_query(struct etna_context *ctx, struct etna_query *q)
+{
+   etna_pm_query_get(ctx->stream, q, ETNA_PM_PROCESS_POST);
+}
+
+static boolean
+etna_pm_get_query_result(struct etna_context *ctx, struct etna_query *q,
+                         boolean wait, union pipe_query_result *result)
+{
+   struct etna_pm_query *pq = etna_pm_query(q);
+
+   etna_pm_query_update(q);
+
+   if (!pq->ready) {
+      if (!wait)
+         return false;
+
+      if (!etna_bo_cpu_prep(pq->bo, DRM_ETNA_PREP_READ))
+         return false;
+
+      pq->ready = true;
+      etna_bo_cpu_fini(pq->bo);
+   }
+
+   result->u32 = pq->data[2] - pq->data[1];
+
+   return true;
+}
+
+static const struct etna_query_funcs hw_query_funcs = {
+   .destroy_query = etna_pm_destroy_query,
+   .begin_query = etna_pm_begin_query,
+   .end_query = etna_pm_end_query,
+   .get_query_result = etna_pm_get_query_result,
+};
+
+struct etna_query *
+etna_pm_create_query(struct etna_context *ctx, unsigned query_type)
+{
+   struct etna_perfmon *perfmon = ctx->screen->perfmon;
+   const struct etna_perfmon_config *cfg;
+   struct etna_pm_query *pq;
+   struct etna_query *q;
+
+   cfg = etna_pm_query_config(query_type);
+   if (!cfg)
+      return NULL;
+
+   if (!etna_pm_cfg_supported(perfmon, cfg))
+      return NULL;
+
+   pq = CALLOC_STRUCT(etna_pm_query);
+   if (!pq)
+      return NULL;
+
+   if (!realloc_query_bo(ctx, pq)) {
+      FREE(pq);
+      return NULL;
+   }
+
+   q = &pq->base;
+   q->funcs = &hw_query_funcs;
+   q->type = query_type;
+
+   etna_pm_add_signal(pq, perfmon, cfg);
+
+   return q;
+}
+
+void
+etna_pm_query_setup(struct etna_screen *screen)
+{
+   screen->perfmon = etna_perfmon_create(screen->pipe);
+
+   if (!screen->perfmon)
+      return;
+
+   for (unsigned i = 0; i < ARRAY_SIZE(query_config); i++) {
+      const struct etna_perfmon_config *cfg = &query_config[i];
+
+      if (!etna_pm_cfg_supported(screen->perfmon, cfg))
+         continue;
+
+      util_dynarray_append(&screen->supported_pm_queries, unsigned, i);
+   }
+}
+
+int
+etna_pm_get_driver_query_info(struct pipe_screen *pscreen, unsigned index,
+                              struct pipe_driver_query_info *info)
+{
+   const struct etna_screen *screen = etna_screen(pscreen);
+   const unsigned num = screen->supported_pm_queries.size / sizeof(unsigned);
+   unsigned i;
+
+   if (!info)
+      return num;
+
+   if (index >= num)
+      return 0;
+
+   i = *util_dynarray_element(&screen->supported_pm_queries, unsigned, index);
+   assert(i < ARRAY_SIZE(query_config));
+
+   info->name = query_config[i].name;
+   info->query_type = query_config[i].type;
+   info->group_id = 0;
+
+   return 1;
+}
diff --git a/src/gallium/drivers/etnaviv/etnaviv_query.h b/src/gallium/drivers/etnaviv/etnaviv_query_pm.h
similarity index 57%
copy from src/gallium/drivers/etnaviv/etnaviv_query.h
copy to src/gallium/drivers/etnaviv/etnaviv_query_pm.h
index 8927266057..3d8cf1419b 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_query.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_query_pm.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2016 Etnaviv Project
+ * Copyright (c) 2017 Etnaviv Project
+ * Copyright (C) 2017 Zodiac Inflight Innovations
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -25,40 +26,36 @@
  *    Christian Gmeiner <christian.gmeiner at gmail.com>
  */
 
-#ifndef H_ETNAVIV_QUERY
-#define H_ETNAVIV_QUERY
+#ifndef H_ETNAVIV_QUERY_PM
+#define H_ETNAVIV_QUERY_PM
 
-#include "pipe/p_context.h"
+#include "etnaviv_query.h"
 
-struct etna_context;
-struct etna_query;
+struct etna_screen;
 
-struct etna_query_funcs {
-   void (*destroy_query)(struct etna_context *ctx, struct etna_query *q);
-   boolean (*begin_query)(struct etna_context *ctx, struct etna_query *q);
-   void (*end_query)(struct etna_context *ctx, struct etna_query *q);
-   boolean (*get_query_result)(struct etna_context *ctx, struct etna_query *q,
-                               boolean wait, union pipe_query_result *result);
+struct etna_pm_query {
+   struct etna_query base;
+   struct etna_perfmon_signal *signal;
+   struct etna_bo *bo;
+   uint32_t *data;
+   uint32_t sequence;
+   bool ready;
 };
 
-struct etna_query {
-   const struct etna_query_funcs *funcs;
-   bool active;
-   unsigned type;
-};
-
-static inline struct etna_query *
-etna_query(struct pipe_query *pq)
+static inline struct etna_pm_query *
+etna_pm_query(struct etna_query *q)
 {
-   return (struct etna_query *)pq;
+   return (struct etna_pm_query *)q;
 }
 
-#define ETNA_SW_QUERY_BASE       (PIPE_QUERY_DRIVER_SPECIFIC + 0)
-
 void
-etna_query_screen_init(struct pipe_screen *pscreen);
+etna_pm_query_setup(struct etna_screen *screen);
 
-void
-etna_query_context_init(struct pipe_context *pctx);
+struct etna_query *
+etna_pm_create_query(struct etna_context *ctx, unsigned query_type);
+
+int
+etna_pm_get_driver_query_info(struct pipe_screen *pscreen, unsigned index,
+                              struct pipe_driver_query_info *info);
 
 #endif
diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c
index 2ae4e86c63..eb52416e84 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_screen.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c
@@ -49,6 +49,7 @@
 
 #define ETNA_DRM_VERSION(major, minor) ((major) << 16 | (minor))
 #define ETNA_DRM_VERSION_FENCE_FD      ETNA_DRM_VERSION(1, 1)
+#define ETNA_DRM_VERSION_PERFMON       ETNA_DRM_VERSION(1, 2)
 
 static const struct debug_named_value debug_options[] = {
    {"dbg_msgs",       ETNA_DBG_MSGS, "Print debug messages"},
@@ -80,6 +81,9 @@ etna_screen_destroy(struct pipe_screen *pscreen)
 {
    struct etna_screen *screen = etna_screen(pscreen);
 
+   if (screen->perfmon)
+      etna_perfmon_del(screen->perfmon);
+
    if (screen->pipe)
       etna_pipe_del(screen->pipe);
 
@@ -986,8 +990,12 @@ etna_screen_create(struct etna_device *dev, struct etna_gpu *gpu,
    etna_query_screen_init(pscreen);
    etna_resource_screen_init(pscreen);
 
+   util_dynarray_init(&screen->supported_pm_queries, NULL);
    slab_create_parent(&screen->transfer_pool, sizeof(struct etna_transfer), 16);
 
+   if (screen->drm_version >= ETNA_DRM_VERSION_PERFMON)
+      etna_pm_query_setup(screen);
+
    return pscreen;
 
 fail:
diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.h b/src/gallium/drivers/etnaviv/etnaviv_screen.h
index dc57a38dbb..bffd4b6ef9 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_screen.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_screen.h
@@ -29,11 +29,13 @@
 #define H_ETNAVIV_SCREEN
 
 #include "etnaviv_internal.h"
+#include "etnaviv_query_pm.h"
 
 #include "os/os_thread.h"
 #include "pipe/p_screen.h"
 #include "renderonly/renderonly.h"
 #include "util/slab.h"
+#include "util/u_dynarray.h"
 
 struct etna_bo;
 
@@ -65,8 +67,10 @@ struct etna_screen {
    struct etna_device *dev;
    struct etna_gpu *gpu;
    struct etna_pipe *pipe;
+   struct etna_perfmon *perfmon;
    struct renderonly *ro;
 
+   struct util_dynarray supported_pm_queries;
    struct slab_parent_pool transfer_pool;
 
    uint32_t model;
-- 
2.14.3



More information about the etnaviv mailing list