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.brezil...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev