[Mesa-dev] [PATCH 2/4] panfrost: Expose perfcounters through the pipe_query interface
Boris Brezillon
boris.brezillon at collabora.com
Thu Apr 4 15:37:39 UTC 2019
There's existing support for dumping perf counters in a files but
nothing to expose them in a standard way to the gallium pipe infra.
Define new driver hooks and add a common infra to expose perfcounters
in a standard way.
Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
---
src/gallium/drivers/panfrost/meson.build | 3 +-
src/gallium/drivers/panfrost/pan_context.c | 80 ++++++++-
src/gallium/drivers/panfrost/pan_context.h | 9 +-
src/gallium/drivers/panfrost/pan_perfcnt.c | 192 +++++++++++++++++++++
src/gallium/drivers/panfrost/pan_perfcnt.h | 36 ++++
src/gallium/drivers/panfrost/pan_screen.c | 9 +-
src/gallium/drivers/panfrost/pan_screen.h | 41 +++++
7 files changed, 362 insertions(+), 8 deletions(-)
create mode 100644 src/gallium/drivers/panfrost/pan_perfcnt.c
create mode 100644 src/gallium/drivers/panfrost/pan_perfcnt.h
diff --git a/src/gallium/drivers/panfrost/meson.build b/src/gallium/drivers/panfrost/meson.build
index b7e7d0c58082..2dfac261aaa4 100644
--- a/src/gallium/drivers/panfrost/meson.build
+++ b/src/gallium/drivers/panfrost/meson.build
@@ -44,7 +44,8 @@ files_panfrost = files(
'pan_pretty_print.c',
'pan_fragment.c',
'pan_sfbd.c',
- 'pan_mfbd.c'
+ 'pan_mfbd.c',
+ 'pan_perfcnt.c'
)
inc_panfrost = [
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index 9f401b1a7a12..7c80b498e9da 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -2319,17 +2319,76 @@ panfrost_create_query(struct pipe_context *pipe,
return (struct pipe_query *) q;
}
+static struct pipe_query *
+panfrost_create_batch_query(struct pipe_context *pipe, unsigned num_queries,
+ unsigned *query_types)
+{
+ struct panfrost_screen *screen = pan_screen(pipe->screen);
+ struct panfrost_context *ctx = pan_context(pipe);
+ struct panfrost_query *query;
+ unsigned i, nhwqueries = 0;
+
+ if (!screen->driver->create_perfcnt_query)
+ return NULL;
+
+ query = CALLOC_STRUCT(panfrost_query);
+ if (!query)
+ return NULL;
+
+ query->type = PIPE_QUERY_DRIVER_SPECIFIC;
+
+ for (i = 0; i < num_queries; i++) {
+ if (query_types[i] >= PIPE_QUERY_DRIVER_SPECIFIC)
+ nhwqueries++;
+ }
+
+ if (!nhwqueries || nhwqueries != num_queries)
+ goto err_free_query;
+
+ query->perfcnt.ncounters = num_queries;
+ query->perfcnt.counters = CALLOC(num_queries, sizeof(*query->perfcnt.counters));
+ if (!query->perfcnt.counters)
+ goto err_free_query;
+
+ for (i = 0; i < num_queries; i++)
+ query->perfcnt.counters[i] = query_types[i] - PIPE_QUERY_DRIVER_SPECIFIC;
+
+ if (!screen->driver->create_perfcnt_query(ctx, &query->perfcnt))
+ goto err_free_query;
+
+ return (struct pipe_query *)query;
+
+err_free_query:
+ if (query->perfcnt.counters)
+ free(query->perfcnt.counters);
+
+ free(query);
+ return NULL;
+}
+
static void
panfrost_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
{
+ struct panfrost_screen *screen = pan_screen(pipe->screen);
+ struct panfrost_context *ctx = pan_context(pipe);
+ struct panfrost_query *query = (struct panfrost_query *)q;
+
+ if (query->type == PIPE_QUERY_DRIVER_SPECIFIC &&
+ screen->driver->destroy_perfcnt_query)
+ screen->driver->destroy_perfcnt_query(ctx, &query->perfcnt);
+
FREE(q);
}
static boolean
panfrost_begin_query(struct pipe_context *pipe, struct pipe_query *q)
{
- struct panfrost_context *ctx = pan_context(pipe);
- struct panfrost_query *query = (struct panfrost_query *) q;
+ struct panfrost_screen *screen = pan_screen(pipe->screen);
+ struct panfrost_context *ctx = pan_context(pipe);
+ struct panfrost_query *query = (struct panfrost_query *)q;
+
+ if (query->type == PIPE_QUERY_DRIVER_SPECIFIC)
+ return screen->driver->begin_perfcnt_query(ctx, &query->perfcnt);
switch (query->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
@@ -2355,8 +2414,14 @@ panfrost_begin_query(struct pipe_context *pipe, struct pipe_query *q)
static bool
panfrost_end_query(struct pipe_context *pipe, struct pipe_query *q)
{
+ struct panfrost_screen *screen = pan_screen(pipe->screen);
+ struct panfrost_query *query = (struct panfrost_query *)q;
struct panfrost_context *ctx = pan_context(pipe);
- ctx->occlusion_query = NULL;
+
+ if (query->type == PIPE_QUERY_DRIVER_SPECIFIC)
+ return screen->driver->end_perfcnt_query(ctx, &query->perfcnt);
+
+ ctx->occlusion_query = NULL;
return true;
}
@@ -2367,13 +2432,19 @@ panfrost_get_query_result(struct pipe_context *pipe,
union pipe_query_result *vresult)
{
/* STUB */
- struct panfrost_query *query = (struct panfrost_query *) q;
+ struct panfrost_query *query = (struct panfrost_query *)q;
+ struct panfrost_screen *screen = pan_screen(pipe->screen);
+ struct panfrost_context *ctx = pan_context(pipe);
/* We need to flush out the jobs to actually run the counter, TODO
* check wait, TODO wallpaper after if needed */
panfrost_flush(pipe, NULL, PIPE_FLUSH_END_OF_FRAME);
+ if (query->type == PIPE_QUERY_DRIVER_SPECIFIC)
+ return screen->driver->get_perfcnt_results(ctx, &query->perfcnt,
+ wait, vresult);
+
switch (query->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
case PIPE_QUERY_OCCLUSION_PREDICATE:
@@ -2537,6 +2608,7 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
gallium->set_active_query_state = panfrost_set_active_query_state;
gallium->create_query = panfrost_create_query;
+ gallium->create_batch_query = panfrost_create_batch_query;
gallium->destroy_query = panfrost_destroy_query;
gallium->begin_query = panfrost_begin_query;
gallium->end_query = panfrost_end_query;
diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h
index d071da1c62fa..fa3748dd26d9 100644
--- a/src/gallium/drivers/panfrost/pan_context.h
+++ b/src/gallium/drivers/panfrost/pan_context.h
@@ -73,13 +73,20 @@ struct panfrost_constant_buffer {
void *buffer;
};
+struct panfrost_perfcnt_query {
+ unsigned int ncounters;
+ unsigned int *counters;
+ void *driver_data;
+};
+
struct panfrost_query {
/* Passthrough from Gallium */
unsigned type;
unsigned index;
/* Memory for the GPU to writeback the value of the query */
- struct panfrost_transfer transfer;
+ struct panfrost_transfer transfer;
+ struct panfrost_perfcnt_query perfcnt;
};
struct panfrost_fence {
diff --git a/src/gallium/drivers/panfrost/pan_perfcnt.c b/src/gallium/drivers/panfrost/pan_perfcnt.c
new file mode 100644
index 000000000000..3bac92ad359d
--- /dev/null
+++ b/src/gallium/drivers/panfrost/pan_perfcnt.c
@@ -0,0 +1,192 @@
+/**************************************************************************
+ *
+ * Copyright 2019 Collabora Ltd
+ * All Rights Reserved.
+ *
+ * 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 VMWARE AND/OR ITS SUPPLIERS 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 "drm-uapi/panfrost_drm.h"
+
+#include "util/u_memory.h"
+
+#include "pan_context.h"
+#include "pan_perfcnt.h"
+#include "pan_screen.h"
+
+
+#define PANFROST_COUNTER(_id, _name) \
+ { \
+ .id = _id, \
+ .name = _name, \
+ }
+
+#define PANFROST_BLK_COUNTERS(_blk, ...) \
+ .block[PANFROST_##_blk##_BLOCK] = { \
+ .counters = (struct panfrost_counter[]) { __VA_ARGS__ }, \
+ .ncounters = sizeof((struct panfrost_counter[]) { __VA_ARGS__ }) / \
+ sizeof(struct panfrost_counter), \
+ }
+
+struct panfrost_gpu_counters {
+ unsigned int gpu_id;
+ const struct panfrost_counters *counters;
+};
+
+static const struct panfrost_gpu_counters gpus[0];
+
+static const char *block_names[] = {
+ [PANFROST_SHADER_BLOCK] = "SHADER",
+ [PANFROST_TILER_BLOCK] = "TILER",
+ [PANFROST_MMU_L2_BLOCK] = "MMU_L2",
+ [PANFROST_JM_BLOCK] = "JM",
+};
+
+static void panfrost_perfcnt_init_queries(struct panfrost_screen *pscreen)
+{
+ struct panfrost_perfcnt_query_info *qinfo;
+ const struct panfrost_counters *counters;
+ unsigned int i, j, k;
+
+ counters = pscreen->perfcnt_info.counters;
+ for (i = 0; i < PANFROST_NUM_BLOCKS; i++) {
+ for (j = 0; j < 64; j++) {
+ if (!((1ULL << j) & pscreen->perfcnt_info.instances[i]))
+ continue;
+
+ pscreen->perfcnt_info.nqueries += counters->block[i].ncounters;
+ }
+ }
+
+ if (!pscreen->perfcnt_info.nqueries)
+ return;
+
+ pscreen->perfcnt_info.queries = CALLOC(pscreen->perfcnt_info.nqueries,
+ sizeof(*pscreen->perfcnt_info.queries));
+ assert(pscreen->perfcnt_info.queries);
+
+ qinfo = pscreen->perfcnt_info.queries;
+
+ for (i = 0; i < PANFROST_NUM_BLOCKS; i++) {
+ for (j = 0; j < 64; j++) {
+
+ if (!((1ULL << j) & pscreen->perfcnt_info.instances[i]))
+ continue;
+
+ for (k = 0; k < counters->block[i].ncounters; k++) {
+ char *name;
+
+ asprintf(&name, "%s.%s-%d",
+ counters->block[i].counters[k].name,
+ block_names[i], j);
+ assert(name);
+ qinfo->name = name;
+ qinfo->block = i;
+ qinfo->instance = j;
+ qinfo->counter = k;
+ qinfo++;
+ }
+ }
+ }
+}
+
+static void panfrost_perfcnt_cleanup_queries(struct panfrost_screen *pscreen)
+{
+ unsigned int i;
+
+ if (!pscreen->perfcnt_info.nqueries)
+ return;
+
+ for (i = 0; i < pscreen->perfcnt_info.nqueries; i++)
+ FREE((void *)pscreen->perfcnt_info.queries[i].name);
+
+ FREE(pscreen->perfcnt_info.queries);
+}
+
+static int panfrost_get_query_group_info(struct pipe_screen *screen,
+ unsigned index,
+ struct pipe_driver_query_group_info *info)
+{
+ struct panfrost_screen *pscreen = pan_screen(screen);
+
+ if (!info)
+ return 1;
+
+ if (index)
+ return 0;
+
+ info->name = "Panfrost GPU counters";
+ info->num_queries = pscreen->perfcnt_info.nqueries;
+ info->max_active_queries = info->num_queries;
+ return 1;
+}
+
+static int panfrost_get_query_info(struct pipe_screen *screen, unsigned index,
+ struct pipe_driver_query_info *info)
+{
+ struct panfrost_screen *pscreen = pan_screen(screen);
+ struct panfrost_perfcnt_query_info *qinfo;
+
+ if (!info)
+ return pscreen->perfcnt_info.nqueries;
+
+ if (index >= pscreen->perfcnt_info.nqueries)
+ return 0;
+
+ qinfo = &pscreen->perfcnt_info.queries[index];
+ info->group_id = 0;
+ info->flags = PIPE_DRIVER_QUERY_FLAG_BATCH;
+ info->type = PIPE_DRIVER_QUERY_TYPE_UINT64;
+ info->result_type = PIPE_DRIVER_QUERY_RESULT_TYPE_CUMULATIVE;
+ info->query_type = PIPE_QUERY_DRIVER_SPECIFIC + index;
+ info->name = qinfo->name;
+ return 1;
+}
+
+void panfrost_perfcnt_init(struct panfrost_screen *pscreen)
+{
+ unsigned gpu_id, i;
+
+ gpu_id = pscreen->driver->query_gpu_version(pscreen);
+ for (i = 0; i < ARRAY_SIZE(gpus); i++) {
+ if (gpus[i].gpu_id == gpu_id)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(gpus))
+ return;
+
+ pscreen->perfcnt_info.counters = gpus[i].counters;
+
+ if (pscreen->driver->init_perfcnt)
+ pscreen->driver->init_perfcnt(pscreen);
+
+ panfrost_perfcnt_init_queries(pscreen);
+
+ pscreen->base.get_driver_query_group_info = panfrost_get_query_group_info;
+ pscreen->base.get_driver_query_info = panfrost_get_query_info;
+}
+
+void panfrost_perfcnt_cleanup(struct panfrost_screen *pscreen)
+{
+ panfrost_perfcnt_cleanup_queries(pscreen);
+}
diff --git a/src/gallium/drivers/panfrost/pan_perfcnt.h b/src/gallium/drivers/panfrost/pan_perfcnt.h
new file mode 100644
index 000000000000..50100eb451f0
--- /dev/null
+++ b/src/gallium/drivers/panfrost/pan_perfcnt.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * Copyright 2019 Collabora Ltd
+ * All Rights Reserved.
+ *
+ * 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 VMWARE AND/OR ITS SUPPLIERS 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 PAN_PERFCNT_H
+#define PAN_PERFCNT_H
+
+#include "pan_screen.h"
+
+void panfrost_perfcnt_init(struct panfrost_screen *screen);
+void panfrost_perfcnt_cleanup(struct panfrost_screen *screen);
+
+#endif /* PAN_PERFCNT_H */
diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c
index 71c6175d0697..65faed726272 100644
--- a/src/gallium/drivers/panfrost/pan_screen.c
+++ b/src/gallium/drivers/panfrost/pan_screen.c
@@ -46,6 +46,7 @@
#include "pan_screen.h"
#include "pan_resource.h"
+#include "pan_perfcnt.h"
#include "pan_public.h"
#include "pan_util.h"
@@ -499,9 +500,12 @@ panfrost_is_format_supported( struct pipe_screen *screen,
static void
-panfrost_destroy_screen( struct pipe_screen *screen )
+panfrost_destroy_screen(struct pipe_screen *pscreen)
{
- FREE(screen);
+ struct panfrost_screen *screen = pan_screen(pscreen);
+
+ panfrost_perfcnt_cleanup(screen);
+ FREE(screen);
}
static void
@@ -601,6 +605,7 @@ panfrost_create_screen(int fd, struct renderonly *ro)
screen->last_fragment_flushed = true;
panfrost_resource_screen_init(screen);
+ panfrost_perfcnt_init(screen);
return &screen->base;
}
diff --git a/src/gallium/drivers/panfrost/pan_screen.h b/src/gallium/drivers/panfrost/pan_screen.h
index cbadf8136751..93d67ea71c0a 100644
--- a/src/gallium/drivers/panfrost/pan_screen.h
+++ b/src/gallium/drivers/panfrost/pan_screen.h
@@ -40,6 +40,7 @@
struct panfrost_context;
struct panfrost_resource;
struct panfrost_screen;
+struct panfrost_perfcnt_query;
/* Flags for allocated memory */
#define PAN_ALLOCATE_EXECUTE (1 << 0)
@@ -76,6 +77,45 @@ struct panfrost_driver {
struct pipe_context *ctx,
struct pipe_fence_handle *fence,
uint64_t timeout);
+ void (*init_perfcnt) (struct panfrost_screen *screen);
+ boolean (*create_perfcnt_query) (struct panfrost_context *ctx,
+ struct panfrost_perfcnt_query *q);
+ void (*destroy_perfcnt_query) (struct panfrost_context *ctx,
+ struct panfrost_perfcnt_query *q);
+ boolean (*begin_perfcnt_query) (struct panfrost_context *ctx,
+ struct panfrost_perfcnt_query *q);
+ boolean (*end_perfcnt_query) (struct panfrost_context *ctx,
+ struct panfrost_perfcnt_query *q);
+ boolean (*get_perfcnt_results) (struct panfrost_context *ctx,
+ struct panfrost_perfcnt_query *q,
+ boolean wait,
+ union pipe_query_result *vresults);
+};
+
+struct panfrost_counter {
+ unsigned int id;
+ const char *name;
+};
+
+struct panfrost_counters {
+ struct {
+ unsigned int ncounters;
+ struct panfrost_counter *counters;
+ } block[4];
+};
+
+struct panfrost_perfcnt_query_info {
+ const char *name;
+ uint8_t block;
+ uint8_t instance;
+ uint8_t counter;
+};
+
+struct panfrost_perfcnt_info {
+ const struct panfrost_counters *counters;
+ uint64_t instances[4];
+ unsigned int nqueries;
+ struct panfrost_perfcnt_query_info *queries;
};
struct panfrost_screen {
@@ -83,6 +123,7 @@ struct panfrost_screen {
struct renderonly *ro;
struct panfrost_driver *driver;
+ struct panfrost_perfcnt_info perfcnt_info;
struct panfrost_memory perf_counters;
--
2.20.1
More information about the mesa-dev
mailing list