From 8a8534a69855fed209c1842f9e143c785809a7e3 Mon Sep 17 00:00:00 2001 From: Dongwon Kim Date: Tue, 15 Oct 2019 12:43:02 -0700 Subject: [PATCH] iris: INTEL performance query implementation low-level implementation of INTEL-performance-query APIs in Intel iris driver. Most of functions and procedures defined here are adopted from i965 driver (brw_performance_query.c) v2: - replace genX_init_performance_query with iris_init_perfquery_functions which is gen's version agnositic - general code clean-up v3: include gen_perf_gens.h as some of defines were moved to this new header file v4: - checking for kernel 4.13+ won't be needed here as Iris won't be loaded anyway without DRM_SYNCOBJ that is enabled after Kernel 4.13. - checking whether gen < 8 or is_cherryview won't be required as well because those cases are screened in iris_screen_create. v5: remove genX(init_performance_query) v6: - remove oa_metrics_kernel_support as iris works only with kernel 4.18 and newer. - use perf functions defined in separate file, iris_perf.h/c Signed-off-by: Dongwon Kim Reviewed-by: Kenneth Graunke --- src/gallium/drivers/iris/Makefile.sources | 1 + src/gallium/drivers/iris/iris_context.c | 1 + src/gallium/drivers/iris/iris_context.h | 1 + .../drivers/iris/iris_performance_query.c | 236 ++++++++++++++++++ src/gallium/drivers/iris/meson.build | 1 + 5 files changed, 240 insertions(+) create mode 100644 src/gallium/drivers/iris/iris_performance_query.c diff --git a/src/gallium/drivers/iris/Makefile.sources b/src/gallium/drivers/iris/Makefile.sources index c203df18c65..2477d1e1369 100644 --- a/src/gallium/drivers/iris/Makefile.sources +++ b/src/gallium/drivers/iris/Makefile.sources @@ -45,6 +45,7 @@ IRIS_C_SOURCES = \ iris_genx_macros.h \ iris_genx_protos.h \ iris_monitor.c \ + iris_performance_query.c \ iris_perf.c \ iris_pipe.h \ iris_pipe_control.c \ diff --git a/src/gallium/drivers/iris/iris_context.c b/src/gallium/drivers/iris/iris_context.c index ebbb865a150..b95ef707bf5 100644 --- a/src/gallium/drivers/iris/iris_context.c +++ b/src/gallium/drivers/iris/iris_context.c @@ -272,6 +272,7 @@ iris_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags) iris_init_program_functions(ctx); iris_init_resource_functions(ctx); iris_init_flush_functions(ctx); + iris_init_perfquery_functions(ctx); iris_init_program_cache(ice); iris_init_border_color_pool(ice); diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index b81cd30441a..ab09d153661 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -767,6 +767,7 @@ void iris_init_blit_functions(struct pipe_context *ctx); void iris_init_clear_functions(struct pipe_context *ctx); void iris_init_program_functions(struct pipe_context *ctx); void iris_init_resource_functions(struct pipe_context *ctx); +void iris_init_perfquery_functions(struct pipe_context *ctx); void iris_update_compiled_shaders(struct iris_context *ice); void iris_update_compiled_compute_shader(struct iris_context *ice); void iris_fill_cs_push_const_buffer(struct brw_cs_prog_data *cs_prog_data, diff --git a/src/gallium/drivers/iris/iris_performance_query.c b/src/gallium/drivers/iris/iris_performance_query.c new file mode 100644 index 00000000000..2f990762315 --- /dev/null +++ b/src/gallium/drivers/iris/iris_performance_query.c @@ -0,0 +1,236 @@ +/* + * Copyright © 2019 Intel Corporation + * + * 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 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. + */ + +#include + +#include "iris_context.h" +#include "iris_perf.h" + +#include "perf/gen_perf.h" +#include "perf/gen_perf_regs.h" + +struct iris_perf_query { + struct gl_perf_query_object base; + struct gen_perf_query_object *query; +}; + +static unsigned +iris_init_perf_query_info(struct pipe_context *pipe) +{ + struct iris_context *ice = (void *) pipe; + struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen; + struct gen_perf_config *perf_cfg = NULL; + + /* make sure pipe perf counter type/data-type enums are matched with gen_perf's */ + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_EVENT == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_EVENT); + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_NORM == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_DURATION_NORM); + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_RAW == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_DURATION_RAW); + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_THROUGHPUT == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_THROUGHPUT); + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_RAW == (enum pipe_perf_counter_type)GEN_PERF_COUNTER_TYPE_RAW); + + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_BOOL32 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_BOOL32); + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT32 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_UINT32); + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT64 == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_UINT64); + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_FLOAT == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_FLOAT); + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE == (enum pipe_perf_counter_data_type)GEN_PERF_COUNTER_DATA_TYPE_DOUBLE); + + if (!ice->perf_ctx) + ice->perf_ctx = gen_perf_new_context(ice); + + if (unlikely(!ice->perf_ctx)) + return 0; + + perf_cfg = gen_perf_config(ice->perf_ctx); + + if (perf_cfg) + return perf_cfg->n_queries; + + perf_cfg = gen_perf_new(ice->perf_ctx); + + iris_perf_init_vtbl(perf_cfg); + + gen_perf_init_context(ice->perf_ctx, + perf_cfg, + ice, + screen->bufmgr, + &screen->devinfo, + ice->batches[IRIS_BATCH_RENDER].hw_ctx_id, + screen->fd); + + gen_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd); + + return perf_cfg->n_queries; +} + +static struct pipe_query * +iris_new_perf_query_obj(struct pipe_context *pipe, unsigned query_index) +{ + struct iris_context *ice = (void *) pipe; + struct gen_perf_context *perf_ctx = ice->perf_ctx; + struct gen_perf_query_object * obj = gen_perf_new_query(perf_ctx, query_index); + if (unlikely(!obj)) + return NULL; + + struct iris_perf_query *q = calloc(1, sizeof(struct iris_perf_query)); + if (unlikely(!q)) { + gen_perf_delete_query(perf_ctx, obj); + return NULL; + } + + q->query = obj; + return (struct pipe_query *)&q->base; +} + +static void +iris_begin_perf_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct iris_context *ice = (void *) pipe; + struct iris_perf_query *perf_query= (struct iris_perf_query *) q; + struct gen_perf_query_object *obj = perf_query->query; + struct gen_perf_context *perf_ctx = ice->perf_ctx; + + gen_perf_begin_query(perf_ctx, obj); +} + +static void +iris_end_perf_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct iris_context *ice = (void *) pipe; + struct iris_perf_query *perf_query = (struct iris_perf_query *) q; + struct gen_perf_query_object *obj = perf_query->query; + struct gen_perf_context *perf_ctx = ice->perf_ctx; + + gen_perf_end_query(perf_ctx, obj); +} + +static void +iris_delete_perf_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct iris_context *ice = (void *) pipe; + struct iris_perf_query *perf_query = (struct iris_perf_query *) q; + struct gen_perf_query_object *obj = perf_query->query; + struct gen_perf_context *perf_ctx = ice->perf_ctx; + + gen_perf_delete_query(perf_ctx, obj); + free(q); +} + +static void +iris_get_perf_query_info(struct pipe_context *pipe, + unsigned query_index, + const char **name, + uint32_t *data_size, + uint32_t *n_counters, + uint32_t *n_active) +{ + struct iris_context *ice = (void *) pipe; + struct gen_perf_context *perf_ctx = ice->perf_ctx; + struct gen_perf_config *perf_cfg = gen_perf_config(perf_ctx); + const struct gen_perf_query_info *info = &perf_cfg->queries[query_index]; + + *name = info->name; + *data_size = info->data_size; + *n_counters = info->n_counters; + *n_active = gen_perf_active_queries(perf_ctx, info); +} + +static void +iris_get_perf_counter_info(struct pipe_context *pipe, + unsigned query_index, + unsigned counter_index, + const char **name, + const char **desc, + uint32_t *offset, + uint32_t *data_size, + uint32_t *type_enum, + uint32_t *data_type_enum, + uint64_t *raw_max) +{ + struct iris_context *ice = (void *) pipe; + struct gen_perf_context *perf_ctx = ice->perf_ctx; + struct gen_perf_config *perf_cfg = gen_perf_config(perf_ctx); + const struct gen_perf_query_info *info = &perf_cfg->queries[query_index]; + const struct gen_perf_query_counter *counter = &info->counters[counter_index]; + + *name = counter->name; + *desc = counter->desc; + *offset = counter->offset; + *data_size = gen_perf_query_counter_get_size(counter); + *type_enum = counter->type; + *data_type_enum = counter->data_type; + *raw_max = counter->raw_max; +} + +static void +iris_wait_perf_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct iris_context *ice = (void *) pipe; + struct iris_perf_query *perf_query = (struct iris_perf_query *) q; + struct gen_perf_query_object *obj = perf_query->query; + struct gen_perf_context *perf_ctx = ice->perf_ctx; + + gen_perf_wait_query(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER]); +} + +static bool +iris_is_perf_query_ready(struct pipe_context *pipe, struct pipe_query *q) +{ + struct iris_context *ice = (void *) pipe; + struct iris_perf_query *perf_query = (struct iris_perf_query *) q; + struct gen_perf_query_object *obj = perf_query->query; + struct gen_perf_context *perf_ctx = ice->perf_ctx; + + if (perf_query->base.Ready) + return true; + + return gen_perf_is_query_ready(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER]); +} + +static void +iris_get_perf_query_data(struct pipe_context *pipe, + struct pipe_query *q, + size_t data_size, + uint32_t *data, + uint32_t *bytes_written) +{ + struct iris_context *ice = (void *) pipe; + struct iris_perf_query *perf_query = (struct iris_perf_query *) q; + struct gen_perf_query_object *obj = perf_query->query; + struct gen_perf_context *perf_ctx = ice->perf_ctx; + + gen_perf_get_query_data(perf_ctx, obj, data_size, data, bytes_written); +} + +void +iris_init_perfquery_functions(struct pipe_context *ctx) +{ + ctx->init_intel_perf_query_info = iris_init_perf_query_info; + ctx->get_intel_perf_query_info = iris_get_perf_query_info; + ctx->get_intel_perf_query_counter_info = iris_get_perf_counter_info; + ctx->new_intel_perf_query_obj = iris_new_perf_query_obj; + ctx->begin_intel_perf_query = iris_begin_perf_query; + ctx->end_intel_perf_query = iris_end_perf_query; + ctx->delete_intel_perf_query = iris_delete_perf_query; + ctx->wait_intel_perf_query = iris_wait_perf_query; + ctx->is_intel_perf_query_ready = iris_is_perf_query_ready; + ctx->get_intel_perf_query_data = iris_get_perf_query_data; +} diff --git a/src/gallium/drivers/iris/meson.build b/src/gallium/drivers/iris/meson.build index f175b84fc1f..1ed507bc104 100644 --- a/src/gallium/drivers/iris/meson.build +++ b/src/gallium/drivers/iris/meson.build @@ -40,6 +40,7 @@ files_libiris = files( 'iris_perf.h', 'iris_perf.c', 'iris_monitor.c', + 'iris_performance_query.c', 'iris_pipe.h', 'iris_pipe_control.c', 'iris_program.c', -- 2.30.2