From 33af91dc07efcc2ca52200570a297de33c18a5f7 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 18 Jul 2018 09:40:04 -0400 Subject: [PATCH] freedreno: batch query support (perfcounters) Core infrastructure for performance counters, using gallium's batch query interface (to support AMD_performance_monitor). Signed-off-by: Rob Clark --- .../drivers/freedreno/Makefile.sources | 1 + .../drivers/freedreno/freedreno_perfcntr.h | 72 +++++++++++++++++++ .../drivers/freedreno/freedreno_query.c | 69 +++++++++++++++++- .../drivers/freedreno/freedreno_query.h | 4 ++ .../drivers/freedreno/freedreno_screen.c | 1 + .../drivers/freedreno/freedreno_screen.h | 8 +++ src/gallium/drivers/freedreno/meson.build | 1 + 7 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 src/gallium/drivers/freedreno/freedreno_perfcntr.h diff --git a/src/gallium/drivers/freedreno/Makefile.sources b/src/gallium/drivers/freedreno/Makefile.sources index e0f0586653c..f3b1abd998a 100644 --- a/src/gallium/drivers/freedreno/Makefile.sources +++ b/src/gallium/drivers/freedreno/Makefile.sources @@ -16,6 +16,7 @@ C_SOURCES := \ freedreno_fence.h \ freedreno_gmem.c \ freedreno_gmem.h \ + freedreno_perfcntr.h \ freedreno_program.c \ freedreno_program.h \ freedreno_query.c \ diff --git a/src/gallium/drivers/freedreno/freedreno_perfcntr.h b/src/gallium/drivers/freedreno/freedreno_perfcntr.h new file mode 100644 index 00000000000..79759307a34 --- /dev/null +++ b/src/gallium/drivers/freedreno/freedreno_perfcntr.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 Rob Clark + * + * 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 (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 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. + * + * Authors: + * Rob Clark + */ + +#ifndef FREEDRENO_PERFCNTR_H_ +#define FREEDRENO_PERFCNTR_H_ + +#include "pipe/p_defines.h" + +/* + * Mapping very closely to the AMD_performance_monitor extension, adreno has + * groups of performance counters where each group has N counters, which can + * select from M different countables (things that can be counted), where + * generally M > N. + */ + +/* Describes a single counter: */ +struct fd_perfcntr_counter { + /* offset of the select register to choose what to count: */ + unsigned select_reg; + /* offset of the lo/hi 32b to read current counter value: */ + unsigned counter_reg_lo; + unsigned counter_reg_hi; + /* Optional, most counters don't have enable/clear registers: */ + unsigned enable; + unsigned clear; +}; + +/* Describes a single countable: */ +struct fd_perfcntr_countable { + const char *name; + /* selector register enum value to select this countable: */ + unsigned selector; + + /* description of the countable: */ + enum pipe_driver_query_type query_type; + enum pipe_driver_query_result_type result_type; +}; + +/* Describes an entire counter group: */ +struct fd_perfcntr_group { + const char *name; + unsigned num_counters; + const struct fd_perfcntr_counter *counters; + unsigned num_countables; + const struct fd_perfcntr_countable *countables; +}; + + +#endif /* FREEDRENO_PERFCNTR_H_ */ diff --git a/src/gallium/drivers/freedreno/freedreno_query.c b/src/gallium/drivers/freedreno/freedreno_query.c index 9d4637a03a4..2b100a3d336 100644 --- a/src/gallium/drivers/freedreno/freedreno_query.c +++ b/src/gallium/drivers/freedreno/freedreno_query.c @@ -150,25 +150,88 @@ static int fd_get_driver_query_info(struct pipe_screen *pscreen, unsigned index, struct pipe_driver_query_info *info) { + struct fd_screen *screen = fd_screen(pscreen); + if (!info) - return ARRAY_SIZE(sw_query_list); + return ARRAY_SIZE(sw_query_list) + screen->num_perfcntr_queries; - if (index >= ARRAY_SIZE(sw_query_list)) - return 0; + if (index >= ARRAY_SIZE(sw_query_list)) { + index -= ARRAY_SIZE(sw_query_list); + if (index >= screen->num_perfcntr_queries) + return 0; + *info = screen->perfcntr_queries[index]; + return 1; + } *info = sw_query_list[index]; return 1; } +static int +fd_get_driver_query_group_info(struct pipe_screen *pscreen, unsigned index, + struct pipe_driver_query_group_info *info) +{ + struct fd_screen *screen = fd_screen(pscreen); + + if (!info) + return screen->num_perfcntr_groups; + + if (index >= screen->num_perfcntr_groups) + return 0; + + const struct fd_perfcntr_group *g = &screen->perfcntr_groups[index]; + + info->name = g->name; + info->max_active_queries = g->num_counters; + info->num_queries = g->num_countables; + + return 1; +} + static void fd_set_active_query_state(struct pipe_context *pipe, boolean enable) { } +static void +setup_perfcntr_query_info(struct fd_screen *screen) +{ + unsigned num_queries = 0; + + for (unsigned i = 0; i < screen->num_perfcntr_groups; i++) + num_queries += screen->perfcntr_groups[i].num_countables; + + screen->perfcntr_queries = + calloc(num_queries, sizeof(screen->perfcntr_queries[0])); + screen->num_perfcntr_queries = num_queries; + + unsigned idx = 0; + for (unsigned i = 0; i < screen->num_perfcntr_groups; i++) { + const struct fd_perfcntr_group *g = &screen->perfcntr_groups[i]; + for (unsigned j = 0; j < g->num_countables; j++) { + struct pipe_driver_query_info *info = + &screen->perfcntr_queries[idx]; + const struct fd_perfcntr_countable *c = + &g->countables[j]; + + info->name = c->name; + info->query_type = FD_QUERY_FIRST_PERFCNTR + idx; + info->type = c->query_type; + info->result_type = c->result_type; + info->group_id = i; + info->flags = PIPE_DRIVER_QUERY_FLAG_BATCH; + + idx++; + } + } +} + void fd_query_screen_init(struct pipe_screen *pscreen) { pscreen->get_driver_query_info = fd_get_driver_query_info; + pscreen->get_driver_query_group_info = fd_get_driver_query_group_info; + setup_perfcntr_query_info(fd_screen(pscreen)); } void diff --git a/src/gallium/drivers/freedreno/freedreno_query.h b/src/gallium/drivers/freedreno/freedreno_query.h index 8150d567ff8..22e54ad0974 100644 --- a/src/gallium/drivers/freedreno/freedreno_query.h +++ b/src/gallium/drivers/freedreno/freedreno_query.h @@ -66,6 +66,10 @@ fd_query(struct pipe_query *pq) #define FD_QUERY_SHADOW_UPLOADS (PIPE_QUERY_DRIVER_SPECIFIC + 7) /* texture/buffer uploads that shadowed rsc */ #define FD_QUERY_VS_REGS (PIPE_QUERY_DRIVER_SPECIFIC + 8) /* avg # of VS registers (scaled up by 100x) */ #define FD_QUERY_FS_REGS (PIPE_QUERY_DRIVER_SPECIFIC + 9) /* avg # of VS registers (scaled up by 100x) */ +/* insert any new non-perfcntr queries here, the first perfcntr index + * needs to come last! + */ +#define FD_QUERY_FIRST_PERFCNTR (PIPE_QUERY_DRIVER_SPECIFIC + 10) void fd_query_screen_init(struct pipe_screen *pscreen); void fd_query_context_init(struct pipe_context *pctx); diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index be5b88b0dd6..531644c85e8 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -162,6 +162,7 @@ fd_screen_destroy(struct pipe_screen *pscreen) ralloc_free(screen->compiler); + free(screen->perfcntr_queries); free(screen); } diff --git a/src/gallium/drivers/freedreno/freedreno_screen.h b/src/gallium/drivers/freedreno/freedreno_screen.h index 013dba1a6d3..251a26f1c07 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.h +++ b/src/gallium/drivers/freedreno/freedreno_screen.h @@ -38,6 +38,7 @@ #include "os/os_thread.h" #include "freedreno_batch_cache.h" +#include "freedreno_perfcntr.h" #include "freedreno_util.h" struct fd_bo; @@ -71,6 +72,13 @@ struct fd_screen { uint32_t priority_mask; bool has_timestamp; + unsigned num_perfcntr_groups; + const struct fd_perfcntr_group *perfcntr_groups; + + /* generated at startup from the perfcntr groups: */ + unsigned num_perfcntr_queries; + struct pipe_driver_query_info *perfcntr_queries; + void *compiler; /* currently unused for a2xx */ struct fd_device *dev; diff --git a/src/gallium/drivers/freedreno/meson.build b/src/gallium/drivers/freedreno/meson.build index ba1a21c9e0e..218756f542a 100644 --- a/src/gallium/drivers/freedreno/meson.build +++ b/src/gallium/drivers/freedreno/meson.build @@ -48,6 +48,7 @@ files_libfreedreno = files( 'freedreno_fence.h', 'freedreno_gmem.c', 'freedreno_gmem.h', + 'freedreno_perfcntr.h', 'freedreno_program.c', 'freedreno_program.h', 'freedreno_query.c', -- 2.30.2