diff --git a/configure.ac b/configure.ac index c0318c1f179..4ff3fceed29 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 7b01d0ab4b7..a4dfa62255c 100644 --- a/meson.build +++ b/meson.build @@ -1037,7 +1037,7 @@ dep_libdrm_intel = null_dep _drm_amdgpu_ver = '2.4.91' _drm_radeon_ver = '2.4.71' _drm_nouveau_ver = '2.4.66' -_drm_etnaviv_ver = '2.4.82' +_drm_etnaviv_ver = '2.4.89' _drm_freedreno_ver = '2.4.91' _drm_intel_ver = '2.4.75' _drm_ver = '2.4.75' diff --git a/src/gallium/drivers/etnaviv/Makefile.sources b/src/gallium/drivers/etnaviv/Makefile.sources index 587d369dfb1..05df2d9c5fb 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 2d257a9d34f..00f87d22cb1 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; - return etna_sw_get_driver_query_info(pscreen, index, info); + if (index < nr_sw_queries) + 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 89272660576..d738fb9e814 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 00000000000..2b09e5dac14 --- /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 + */ + +#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_pm.h b/src/gallium/drivers/etnaviv/etnaviv_query_pm.h new file mode 100644 index 00000000000..3d8cf1419bd --- /dev/null +++ b/src/gallium/drivers/etnaviv/etnaviv_query_pm.h @@ -0,0 +1,61 @@ +/* + * 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: + * Rob Clark + * Christian Gmeiner + */ + +#ifndef H_ETNAVIV_QUERY_PM +#define H_ETNAVIV_QUERY_PM + +#include "etnaviv_query.h" + +struct etna_screen; + +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; +}; + +static inline struct etna_pm_query * +etna_pm_query(struct etna_query *q) +{ + return (struct etna_pm_query *)q; +} + +void +etna_pm_query_setup(struct etna_screen *screen); + +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 fff0a250a28..b0f8b4bebe3 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 dc57a38dbb8..bffd4b6ef94 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;