From fd8e31198866a705e908ebc453785a7c24b52b20 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 31 Dec 2021 07:07:48 +1000 Subject: [PATCH] crocus: sync performance monitor code with iris. This provides the same info as iris does now, and exposes INTEL_performance_query Part-of: --- .../drivers/crocus/ci/crocus-hsw-fails.txt | 4 - .../drivers/crocus/ci/crocus-hsw-flakes.txt | 4 + src/gallium/drivers/crocus/crocus_context.c | 1 + src/gallium/drivers/crocus/crocus_context.h | 1 + src/gallium/drivers/crocus/crocus_monitor.c | 223 +++------------ src/gallium/drivers/crocus/crocus_monitor.h | 13 - src/gallium/drivers/crocus/crocus_perf.c | 104 +++++++ src/gallium/drivers/crocus/crocus_perf.h | 31 +++ .../drivers/crocus/crocus_performance_query.c | 263 ++++++++++++++++++ src/gallium/drivers/crocus/crocus_screen.h | 3 +- src/gallium/drivers/crocus/meson.build | 3 + 11 files changed, 446 insertions(+), 204 deletions(-) create mode 100644 src/gallium/drivers/crocus/crocus_perf.c create mode 100644 src/gallium/drivers/crocus/crocus_perf.h create mode 100644 src/gallium/drivers/crocus/crocus_performance_query.c diff --git a/src/gallium/drivers/crocus/ci/crocus-hsw-fails.txt b/src/gallium/drivers/crocus/ci/crocus-hsw-fails.txt index a87d45723d5..e0ef86b69da 100644 --- a/src/gallium/drivers/crocus/ci/crocus-hsw-fails.txt +++ b/src/gallium/drivers/crocus/ci/crocus-hsw-fails.txt @@ -39,8 +39,6 @@ spec@!opengl 3.2@gl-3.2-adj-prims pv-first,Fail spec@arb_direct_state_access@gettextureimage-formats init-by-rendering,Fail -spec@amd_performance_monitor@measure,Crash - spec@arb_gpu_shader_fp64@execution@arb_gpu_shader_fp64-vs-non-uniform-control-flow-ssbo,Fail spec@arb_indirect_parameters@conditional-render,Fail @@ -161,8 +159,6 @@ spec@glsl-1.50@execution@geometry@primitive-types gl_line_loop,Fail spec@glsl-1.50@execution@primitive-id-no-gs-quads,Fail spec@glsl-1.50@execution@primitive-id-no-gs-quad-strip,Fail -spec@intel_performance_query@intel_performance_query-issue_2235,Fail - spec@khr_texture_compression_astc@miptree-gl srgb-fp,Fail spec@khr_texture_compression_astc@miptree-gl srgb-fp@sRGB decode full precision,Fail spec@khr_texture_compression_astc@miptree-gles srgb-fp,Fail diff --git a/src/gallium/drivers/crocus/ci/crocus-hsw-flakes.txt b/src/gallium/drivers/crocus/ci/crocus-hsw-flakes.txt index a0e51bdb911..58ade04935a 100644 --- a/src/gallium/drivers/crocus/ci/crocus-hsw-flakes.txt +++ b/src/gallium/drivers/crocus/ci/crocus-hsw-flakes.txt @@ -1,4 +1,8 @@ KHR-GL46.texture_barrier.overlapping-texels KHR-GL46.texture_barrier_ARB.overlapping-texels KHR-GL46.texture_barrier_ARB.same-texel-rw-multipass +spec@arb_query_buffer_object@qbo spec@arb_shader_storage_buffer_object@execution@ssbo-atomicexchange-int +spec@amd_performance_monitor@measure +spec@amd_performance_monitor@measure@change counters while active +spec@amd_performance_monitor@measure@counters in range diff --git a/src/gallium/drivers/crocus/crocus_context.c b/src/gallium/drivers/crocus/crocus_context.c index 27dc17dd538..903be358524 100644 --- a/src/gallium/drivers/crocus/crocus_context.c +++ b/src/gallium/drivers/crocus/crocus_context.c @@ -277,6 +277,7 @@ crocus_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags) crocus_init_program_functions(ctx); crocus_init_resource_functions(ctx); crocus_init_flush_functions(ctx); + crocus_init_perfquery_functions(ctx); crocus_init_program_cache(ice); diff --git a/src/gallium/drivers/crocus/crocus_context.h b/src/gallium/drivers/crocus/crocus_context.h index 66f7ecc31ea..ddfddd6ac31 100644 --- a/src/gallium/drivers/crocus/crocus_context.h +++ b/src/gallium/drivers/crocus/crocus_context.h @@ -770,6 +770,7 @@ void crocus_init_blit_functions(struct pipe_context *ctx); void crocus_init_clear_functions(struct pipe_context *ctx); void crocus_init_program_functions(struct pipe_context *ctx); void crocus_init_resource_functions(struct pipe_context *ctx); +void crocus_init_perfquery_functions(struct pipe_context *ctx); bool crocus_update_compiled_shaders(struct crocus_context *ice); void crocus_update_compiled_compute_shader(struct crocus_context *ice); void crocus_fill_cs_push_const_buffer(struct brw_cs_prog_data *cs_prog_data, diff --git a/src/gallium/drivers/crocus/crocus_monitor.c b/src/gallium/drivers/crocus/crocus_monitor.c index c0465f22875..e3f668c2cd8 100644 --- a/src/gallium/drivers/crocus/crocus_monitor.c +++ b/src/gallium/drivers/crocus/crocus_monitor.c @@ -26,6 +26,7 @@ #include "crocus_screen.h" #include "crocus_context.h" +#include "crocus_perf.h" #include "perf/intel_perf.h" #include "perf/intel_perf_query.h" @@ -46,24 +47,25 @@ crocus_get_monitor_info(struct pipe_screen *pscreen, unsigned index, struct pipe_driver_query_info *info) { const struct crocus_screen *screen = (struct crocus_screen *)pscreen; - assert(screen->monitor_cfg); - if (!screen->monitor_cfg) + struct intel_perf_config *perf_cfg = screen->perf_cfg; + assert(perf_cfg); + if (!perf_cfg) return 0; - const struct crocus_monitor_config *monitor_cfg = screen->monitor_cfg; - if (!info) { /* return the number of metrics */ - return monitor_cfg->num_counters; + return perf_cfg->n_counters; } - const struct intel_perf_config *perf_cfg = monitor_cfg->perf_cfg; - const int group = monitor_cfg->counters[index].group; - const int counter_index = monitor_cfg->counters[index].counter; - struct intel_perf_query_counter *counter = - &perf_cfg->queries[group].counters[counter_index]; + struct intel_perf_query_counter_info *counter_info = &perf_cfg->counter_infos[index]; + struct intel_perf_query_info *query_info = + &perf_cfg->queries[intel_perf_query_counter_info_first_query(counter_info)]; + struct intel_perf_query_counter *counter = counter_info->counter; + struct intel_perf_query_result results; - info->group_id = group; + intel_perf_query_result_clear(&results); + + info->group_id = counter_info->location.group_idx; info->name = counter->name; info->query_type = PIPE_QUERY_DRIVER_SPECIFIC + index; @@ -75,16 +77,23 @@ crocus_get_monitor_info(struct pipe_screen *pscreen, unsigned index, case INTEL_PERF_COUNTER_DATA_TYPE_BOOL32: case INTEL_PERF_COUNTER_DATA_TYPE_UINT32: info->type = PIPE_DRIVER_QUERY_TYPE_UINT; - info->max_value.u32 = 0; + uint64_t val = + counter->oa_counter_max_uint64 ? + counter->oa_counter_max_uint64(perf_cfg, query_info, &results) : 0; + info->max_value.u32 = (uint32_t)val; break; case INTEL_PERF_COUNTER_DATA_TYPE_UINT64: info->type = PIPE_DRIVER_QUERY_TYPE_UINT64; - info->max_value.u64 = 0; + info->max_value.u64 = + counter->oa_counter_max_uint64 ? + counter->oa_counter_max_uint64(perf_cfg, query_info, &results) : 0; break; case INTEL_PERF_COUNTER_DATA_TYPE_FLOAT: case INTEL_PERF_COUNTER_DATA_TYPE_DOUBLE: info->type = PIPE_DRIVER_QUERY_TYPE_FLOAT; - info->max_value.u64 = -1; + info->max_value.f = + counter->oa_counter_max_float ? + counter->oa_counter_max_float(perf_cfg, query_info, &results) : 0.0f; break; default: assert(false); @@ -96,173 +105,20 @@ crocus_get_monitor_info(struct pipe_screen *pscreen, unsigned index, return 1; } -typedef void (*bo_unreference_t)(void *); -typedef void *(*bo_map_t)(void *, void *, unsigned flags); -typedef void (*bo_unmap_t)(void *); -typedef void (*emit_mi_report_t)(void *, void *, uint32_t, uint32_t); -typedef void (*emit_mi_flush_t)(void *); -typedef void (*capture_frequency_stat_register_t)(void *, void *, - uint32_t ); -typedef void (*store_register_mem64_t)(void *ctx, void *bo, - uint32_t reg, uint32_t offset); -typedef bool (*batch_references_t)(void *batch, void *bo); -typedef void (*bo_wait_rendering_t)(void *bo); -typedef int (*bo_busy_t)(void *bo); - -static void * -crocus_oa_bo_alloc(void *bufmgr, const char *name, uint64_t size) -{ - return crocus_bo_alloc(bufmgr, name, size); -} - -#if 0 -static void -crocus_monitor_emit_mi_flush(struct crocus_context *ice) -{ - const int flags = PIPE_CONTROL_RENDER_TARGET_FLUSH | - PIPE_CONTROL_INSTRUCTION_INVALIDATE | - PIPE_CONTROL_CONST_CACHE_INVALIDATE | - PIPE_CONTROL_DATA_CACHE_FLUSH | - PIPE_CONTROL_DEPTH_CACHE_FLUSH | - PIPE_CONTROL_VF_CACHE_INVALIDATE | - PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | - PIPE_CONTROL_CS_STALL; - crocus_emit_pipe_control_flush(&ice->batches[CROCUS_BATCH_RENDER], - "OA metrics", flags); -} -#endif - -static void -crocus_monitor_emit_mi_report_perf_count(void *c, - void *bo, - uint32_t offset_in_bytes, - uint32_t report_id) -{ - struct crocus_context *ice = c; - struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; - struct crocus_screen *screen = batch->screen; - screen->vtbl.emit_mi_report_perf_count(batch, bo, offset_in_bytes, report_id); -} - -static void -crocus_monitor_batchbuffer_flush(void *c, const char *file, int line) -{ - struct crocus_context *ice = c; - _crocus_batch_flush(&ice->batches[CROCUS_BATCH_RENDER], __FILE__, __LINE__); -} - -#if 0 -static void -crocus_monitor_capture_frequency_stat_register(void *ctx, - void *bo, - uint32_t bo_offset) -{ - struct crocus_context *ice = ctx; - struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; - ice->vtbl.store_register_mem32(batch, GEN9_RPSTAT0, bo, bo_offset, false); -} - -static void -crocus_monitor_store_register_mem64(void *ctx, void *bo, - uint32_t reg, uint32_t offset) -{ - struct crocus_context *ice = ctx; - struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; - ice->vtbl.store_register_mem64(batch, reg, bo, offset, false); -} -#endif - static bool crocus_monitor_init_metrics(struct crocus_screen *screen) { - struct crocus_monitor_config *monitor_cfg = - rzalloc(screen, struct crocus_monitor_config); - struct intel_perf_config *perf_cfg = NULL; - if (unlikely(!monitor_cfg)) - goto allocation_error; - perf_cfg = intel_perf_new(monitor_cfg); + struct intel_perf_config *perf_cfg = intel_perf_new(screen); if (unlikely(!perf_cfg)) - goto allocation_error; + return false; - monitor_cfg->perf_cfg = perf_cfg; + screen->perf_cfg = perf_cfg; - perf_cfg->vtbl.bo_alloc = crocus_oa_bo_alloc; - perf_cfg->vtbl.bo_unreference = (bo_unreference_t)crocus_bo_unreference; - perf_cfg->vtbl.bo_map = (bo_map_t)crocus_bo_map; - perf_cfg->vtbl.bo_unmap = (bo_unmap_t)crocus_bo_unmap; + crocus_perf_init_vtbl(perf_cfg); - perf_cfg->vtbl.emit_mi_report_perf_count = - (emit_mi_report_t)crocus_monitor_emit_mi_report_perf_count; - perf_cfg->vtbl.batchbuffer_flush = crocus_monitor_batchbuffer_flush; - perf_cfg->vtbl.batch_references = (batch_references_t)crocus_batch_references; - perf_cfg->vtbl.bo_wait_rendering = - (bo_wait_rendering_t)crocus_bo_wait_rendering; - perf_cfg->vtbl.bo_busy = (bo_busy_t)crocus_bo_busy; + intel_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd, true, true); - intel_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd, false, false); - screen->monitor_cfg = monitor_cfg; - - /* a gallium "group" is equivalent to a gen "query" - * a gallium "query" is equivalent to a gen "query_counter" - * - * Each gen_query supports a specific number of query_counters. To - * allocate the array of crocus_monitor_counter, we need an upper bound - * (ignoring duplicate query_counters). - */ - int gen_query_counters_count = 0; - for (int gen_query_id = 0; - gen_query_id < perf_cfg->n_queries; - ++gen_query_id) { - gen_query_counters_count += perf_cfg->queries[gen_query_id].n_counters; - } - - monitor_cfg->counters = rzalloc_size(monitor_cfg, - sizeof(struct crocus_monitor_counter) * - gen_query_counters_count); - if (unlikely(!monitor_cfg->counters)) - goto allocation_error; - - int crocus_monitor_id = 0; - for (int group = 0; group < perf_cfg->n_queries; ++group) { - for (int counter = 0; - counter < perf_cfg->queries[group].n_counters; - ++counter) { - /* Check previously identified metrics to filter out duplicates. The - * user is not helped by having the same metric available in several - * groups. (n^2 algorithm). - */ - bool duplicate = false; - for (int existing_group = 0; - existing_group < group && !duplicate; - ++existing_group) { - for (int existing_counter = 0; - existing_counter < perf_cfg->queries[existing_group].n_counters && !duplicate; - ++existing_counter) { - const char *current_name = - perf_cfg->queries[group].counters[counter].name; - const char *existing_name = - perf_cfg->queries[existing_group].counters[existing_counter].name; - if (strcmp(current_name, existing_name) == 0) { - duplicate = true; - } - } - } - if (duplicate) - continue; - monitor_cfg->counters[crocus_monitor_id].group = group; - monitor_cfg->counters[crocus_monitor_id].counter = counter; - ++crocus_monitor_id; - } - } - monitor_cfg->num_counters = crocus_monitor_id; - return monitor_cfg->num_counters; - -allocation_error: - if (monitor_cfg) - free(monitor_cfg->counters); - free(perf_cfg); - free(monitor_cfg); - return false; + return perf_cfg->n_counters > 0; } int @@ -271,13 +127,12 @@ crocus_get_monitor_group_info(struct pipe_screen *pscreen, struct pipe_driver_query_group_info *info) { struct crocus_screen *screen = (struct crocus_screen *)pscreen; - if (!screen->monitor_cfg) { + if (!screen->perf_cfg) { if (!crocus_monitor_init_metrics(screen)) return 0; } - const struct crocus_monitor_config *monitor_cfg = screen->monitor_cfg; - const struct intel_perf_config *perf_cfg = monitor_cfg->perf_cfg; + const struct intel_perf_config *perf_cfg = screen->perf_cfg; if (!info) { /* return the count that can be queried */ @@ -302,14 +157,13 @@ static void crocus_init_monitor_ctx(struct crocus_context *ice) { struct crocus_screen *screen = (struct crocus_screen *) ice->ctx.screen; - struct crocus_monitor_config *monitor_cfg = screen->monitor_cfg; ice->perf_ctx = intel_perf_new_context(ice); if (unlikely(!ice->perf_ctx)) return; struct intel_perf_context *perf_ctx = ice->perf_ctx; - struct intel_perf_config *perf_cfg = monitor_cfg->perf_cfg; + struct intel_perf_config *perf_cfg = screen->perf_cfg; intel_perf_init_context(perf_ctx, perf_cfg, ice, @@ -327,8 +181,7 @@ crocus_create_monitor_object(struct crocus_context *ice, unsigned *query_types) { struct crocus_screen *screen = (struct crocus_screen *) ice->ctx.screen; - struct crocus_monitor_config *monitor_cfg = screen->monitor_cfg; - struct intel_perf_config *perf_cfg = monitor_cfg->perf_cfg; + struct intel_perf_config *perf_cfg = screen->perf_cfg; struct intel_perf_query_object *query_obj = NULL; /* initialize perf context if this has not already been done. This @@ -341,8 +194,8 @@ crocus_create_monitor_object(struct crocus_context *ice, assert(num_queries > 0); int query_index = query_types[0] - PIPE_QUERY_DRIVER_SPECIFIC; - assert(query_index <= monitor_cfg->num_counters); - const int group = monitor_cfg->counters[query_index].group; + assert(query_index <= perf_cfg->n_counters); + const int group = perf_cfg->counter_infos[query_index].location.group_idx; struct crocus_monitor_object *monitor = calloc(1, sizeof(struct crocus_monitor_object)); @@ -359,10 +212,10 @@ crocus_create_monitor_object(struct crocus_context *ice, unsigned current_query_index = current_query - PIPE_QUERY_DRIVER_SPECIFIC; /* all queries must be in the same group */ - assert(current_query_index <= monitor_cfg->num_counters); - assert(monitor_cfg->counters[current_query_index].group == group); + assert(current_query_index <= perf_cfg->n_counters); + assert(perf_cfg->counter_infos[current_query_index].location.group_idx == group); monitor->active_counters[i] = - monitor_cfg->counters[current_query_index].counter; + perf_cfg->counter_infos[current_query_index].location.counter_idx; } /* create the intel_perf_query */ diff --git a/src/gallium/drivers/crocus/crocus_monitor.h b/src/gallium/drivers/crocus/crocus_monitor.h index 3335c8860e2..94a0fc90299 100644 --- a/src/gallium/drivers/crocus/crocus_monitor.h +++ b/src/gallium/drivers/crocus/crocus_monitor.h @@ -25,19 +25,6 @@ #include "pipe/p_screen.h" -struct crocus_monitor_counter { - int group; - int counter; -}; - -struct crocus_monitor_config { - struct intel_perf_config *perf_cfg; - - /* gallium requires an index for each counter */ - int num_counters; - struct crocus_monitor_counter *counters; -}; - int crocus_get_monitor_info(struct pipe_screen *pscreen, unsigned index, struct pipe_driver_query_info *info); int crocus_get_monitor_group_info(struct pipe_screen *pscreen, diff --git a/src/gallium/drivers/crocus/crocus_perf.c b/src/gallium/drivers/crocus/crocus_perf.c new file mode 100644 index 00000000000..cb33db2087d --- /dev/null +++ b/src/gallium/drivers/crocus/crocus_perf.c @@ -0,0 +1,104 @@ +/* + * 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 "crocus_perf.h" +#include "crocus_context.h" + +static void * +crocus_oa_bo_alloc(void *bufmgr, const char *name, uint64_t size) +{ + return crocus_bo_alloc(bufmgr, name, size); +} + +static void +crocus_perf_emit_stall_at_pixel_scoreboard(struct crocus_context *ice) +{ + crocus_emit_end_of_pipe_sync(&ice->batches[CROCUS_BATCH_RENDER], + "OA metrics", + PIPE_CONTROL_STALL_AT_SCOREBOARD); +} + +static void +crocus_perf_emit_mi_report_perf_count(void *c, + void *bo, + uint32_t offset_in_bytes, + uint32_t report_id) +{ + struct crocus_context *ice = c; + struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; + batch->screen->vtbl.emit_mi_report_perf_count(batch, bo, offset_in_bytes, report_id); +} + +static void +crocus_perf_batchbuffer_flush(void *c, const char *file, int line) +{ + struct crocus_context *ice = c; + _crocus_batch_flush(&ice->batches[CROCUS_BATCH_RENDER], __FILE__, __LINE__); +} + +static void +crocus_perf_store_register_mem(void *ctx, void *bo, + uint32_t reg, uint32_t reg_size, + uint32_t offset) +{ + struct crocus_context *ice = ctx; + struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; + if (reg_size == 8) { + batch->screen->vtbl.store_register_mem64(batch, reg, bo, offset, false); + } else { + assert(reg_size == 4); + batch->screen->vtbl.store_register_mem32(batch, reg, bo, offset, false); + } +} + +typedef void (*bo_unreference_t)(void *); +typedef void *(*bo_map_t)(void *, void *, unsigned flags); +typedef void (*bo_unmap_t)(void *); +typedef void (*emit_mi_report_t)(void *, void *, uint32_t, uint32_t); +typedef void (*emit_mi_flush_t)(void *); +typedef void (*store_register_mem_t)(void *ctx, void *bo, + uint32_t reg, uint32_t reg_size, + uint32_t offset); +typedef bool (*batch_references_t)(void *batch, void *bo); +typedef void (*bo_wait_rendering_t)(void *bo); +typedef int (*bo_busy_t)(void *bo); + +void +crocus_perf_init_vtbl(struct intel_perf_config *perf_cfg) +{ + perf_cfg->vtbl.bo_alloc = crocus_oa_bo_alloc; + perf_cfg->vtbl.bo_unreference = (bo_unreference_t)crocus_bo_unreference; + perf_cfg->vtbl.bo_map = (bo_map_t)crocus_bo_map; + perf_cfg->vtbl.bo_unmap = (bo_unmap_t)crocus_bo_unmap; + perf_cfg->vtbl.emit_stall_at_pixel_scoreboard = + (emit_mi_flush_t)crocus_perf_emit_stall_at_pixel_scoreboard; + + perf_cfg->vtbl.emit_mi_report_perf_count = + (emit_mi_report_t)crocus_perf_emit_mi_report_perf_count; + perf_cfg->vtbl.batchbuffer_flush = crocus_perf_batchbuffer_flush; + perf_cfg->vtbl.store_register_mem = + (store_register_mem_t) crocus_perf_store_register_mem; + perf_cfg->vtbl.batch_references = (batch_references_t)crocus_batch_references; + perf_cfg->vtbl.bo_wait_rendering = + (bo_wait_rendering_t)crocus_bo_wait_rendering; + perf_cfg->vtbl.bo_busy = (bo_busy_t)crocus_bo_busy; +} diff --git a/src/gallium/drivers/crocus/crocus_perf.h b/src/gallium/drivers/crocus/crocus_perf.h new file mode 100644 index 00000000000..13d18c89842 --- /dev/null +++ b/src/gallium/drivers/crocus/crocus_perf.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef CROCUS_PERF_H +#define CROCUS_PERF_H + +#include "perf/intel_perf.h" +#include "perf/intel_perf_query.h" + +void crocus_perf_init_vtbl(struct intel_perf_config *cfg); + +#endif /* CROCUS_PERF_H */ diff --git a/src/gallium/drivers/crocus/crocus_performance_query.c b/src/gallium/drivers/crocus/crocus_performance_query.c new file mode 100644 index 00000000000..c33d4fe76cc --- /dev/null +++ b/src/gallium/drivers/crocus/crocus_performance_query.c @@ -0,0 +1,263 @@ +/* + * 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 "crocus_context.h" +#include "crocus_perf.h" + +#include "main/mtypes.h" + +struct crocus_perf_query { + struct gl_perf_query_object base; + struct intel_perf_query_object *query; + bool begin_succeeded; +}; + +static unsigned +crocus_init_perf_query_info(struct pipe_context *pipe) +{ + struct crocus_context *ice = (void *) pipe; + struct crocus_screen *screen = (struct crocus_screen *) ice->ctx.screen; + struct intel_perf_config *perf_cfg = NULL; + + /* make sure pipe perf counter type/data-type enums are matched with intel_perf's */ + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_EVENT == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_EVENT); + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_NORM == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_DURATION_NORM); + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_RAW == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_DURATION_RAW); + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_THROUGHPUT == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_THROUGHPUT); + STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_RAW == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_RAW); + + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_BOOL32 == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_BOOL32); + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT32 == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_UINT32); + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT64 == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_UINT64); + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_FLOAT == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_FLOAT); + STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_DOUBLE); + + if (!ice->perf_ctx) + ice->perf_ctx = intel_perf_new_context(ice); + + if (unlikely(!ice->perf_ctx)) + return 0; + + perf_cfg = intel_perf_config(ice->perf_ctx); + + if (perf_cfg) + return perf_cfg->n_queries; + + perf_cfg = intel_perf_new(ice->perf_ctx); + + crocus_perf_init_vtbl(perf_cfg); + + intel_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd, + true /* pipeline_statistics */, + true /* register snapshots */); + + intel_perf_init_context(ice->perf_ctx, + perf_cfg, + ice, + ice, + screen->bufmgr, + &screen->devinfo, + ice->batches[CROCUS_BATCH_RENDER].hw_ctx_id, + screen->fd); + + return perf_cfg->n_queries; +} + +static struct pipe_query * +crocus_new_perf_query_obj(struct pipe_context *pipe, unsigned query_index) +{ + struct crocus_context *ice = (void *) pipe; + struct intel_perf_context *perf_ctx = ice->perf_ctx; + struct intel_perf_query_object * obj = + intel_perf_new_query(perf_ctx, query_index); + if (unlikely(!obj)) + return NULL; + + struct crocus_perf_query *q = calloc(1, sizeof(struct crocus_perf_query)); + if (unlikely(!q)) { + intel_perf_delete_query(perf_ctx, obj); + return NULL; + } + + q->query = obj; + return (struct pipe_query *)&q->base; +} + +static bool +crocus_begin_perf_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct crocus_context *ice = (void *) pipe; + struct crocus_perf_query *perf_query= (struct crocus_perf_query *) q; + struct intel_perf_query_object *obj = perf_query->query; + struct intel_perf_context *perf_ctx = ice->perf_ctx; + + return (perf_query->begin_succeeded = intel_perf_begin_query(perf_ctx, obj)); +} + +static void +crocus_end_perf_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct crocus_context *ice = (void *) pipe; + struct crocus_perf_query *perf_query = (struct crocus_perf_query *) q; + struct intel_perf_query_object *obj = perf_query->query; + struct intel_perf_context *perf_ctx = ice->perf_ctx; + + if (perf_query->begin_succeeded) + intel_perf_end_query(perf_ctx, obj); +} + +static void +crocus_delete_perf_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct crocus_context *ice = (void *) pipe; + struct crocus_perf_query *perf_query = (struct crocus_perf_query *) q; + struct intel_perf_query_object *obj = perf_query->query; + struct intel_perf_context *perf_ctx = ice->perf_ctx; + + intel_perf_delete_query(perf_ctx, obj); + free(q); +} + +static void +crocus_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 crocus_context *ice = (void *) pipe; + struct intel_perf_context *perf_ctx = ice->perf_ctx; + struct intel_perf_config *perf_cfg = intel_perf_config(perf_ctx); + const struct intel_perf_query_info *info = &perf_cfg->queries[query_index]; + + *name = info->name; + *data_size = info->data_size; + *n_counters = info->n_counters; + *n_active = intel_perf_active_queries(perf_ctx, info); +} + +static void +crocus_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 crocus_context *ice = (void *) pipe; + struct intel_perf_context *perf_ctx = ice->perf_ctx; + struct intel_perf_config *perf_cfg = intel_perf_config(perf_ctx); + const struct intel_perf_query_info *info = &perf_cfg->queries[query_index]; + const struct intel_perf_query_counter *counter = + &info->counters[counter_index]; + struct intel_perf_query_result results; + + intel_perf_query_result_clear(&results); + + *name = counter->name; + *desc = counter->desc; + *offset = counter->offset; + *data_size = intel_perf_query_counter_get_size(counter); + *type_enum = counter->type; + *data_type_enum = counter->data_type; + + if (counter->oa_counter_max_uint64) { + if (counter->data_type == INTEL_PERF_COUNTER_DATA_TYPE_FLOAT || + counter->data_type == INTEL_PERF_COUNTER_DATA_TYPE_DOUBLE) + *raw_max = counter->oa_counter_max_float(perf_cfg, info, &results); + else + *raw_max = counter->oa_counter_max_uint64(perf_cfg, info, &results); + } else { + *raw_max = 0; + } +} + +static void +crocus_wait_perf_query(struct pipe_context *pipe, struct pipe_query *q) +{ + struct crocus_context *ice = (void *) pipe; + struct crocus_perf_query *perf_query = (struct crocus_perf_query *) q; + struct intel_perf_query_object *obj = perf_query->query; + struct intel_perf_context *perf_ctx = ice->perf_ctx; + + if (perf_query->begin_succeeded) + intel_perf_wait_query(perf_ctx, obj, &ice->batches[CROCUS_BATCH_RENDER]); +} + +static bool +crocus_is_perf_query_ready(struct pipe_context *pipe, struct pipe_query *q) +{ + struct crocus_context *ice = (void *) pipe; + struct crocus_perf_query *perf_query = (struct crocus_perf_query *) q; + struct intel_perf_query_object *obj = perf_query->query; + struct intel_perf_context *perf_ctx = ice->perf_ctx; + + if (perf_query->base.Ready) + return true; + if (!perf_query->begin_succeeded) + return true; + + return intel_perf_is_query_ready(perf_ctx, obj, + &ice->batches[CROCUS_BATCH_RENDER]); +} + +static bool +crocus_get_perf_query_data(struct pipe_context *pipe, + struct pipe_query *q, + size_t data_size, + uint32_t *data, + uint32_t *bytes_written) +{ + struct crocus_context *ice = (void *) pipe; + struct crocus_perf_query *perf_query = (struct crocus_perf_query *) q; + struct intel_perf_query_object *obj = perf_query->query; + struct intel_perf_context *perf_ctx = ice->perf_ctx; + + if (perf_query->begin_succeeded) { + intel_perf_get_query_data(perf_ctx, obj, &ice->batches[CROCUS_BATCH_RENDER], + data_size, data, bytes_written); + } + + return perf_query->begin_succeeded; +} + +void +crocus_init_perfquery_functions(struct pipe_context *ctx) +{ + ctx->init_intel_perf_query_info = crocus_init_perf_query_info; + ctx->get_intel_perf_query_info = crocus_get_perf_query_info; + ctx->get_intel_perf_query_counter_info = crocus_get_perf_counter_info; + ctx->new_intel_perf_query_obj = crocus_new_perf_query_obj; + ctx->begin_intel_perf_query = crocus_begin_perf_query; + ctx->end_intel_perf_query = crocus_end_perf_query; + ctx->delete_intel_perf_query = crocus_delete_perf_query; + ctx->wait_intel_perf_query = crocus_wait_perf_query; + ctx->is_intel_perf_query_ready = crocus_is_perf_query_ready; + ctx->get_intel_perf_query_data = crocus_get_perf_query_data; +} diff --git a/src/gallium/drivers/crocus/crocus_screen.h b/src/gallium/drivers/crocus/crocus_screen.h index 31d4fad158c..5544134b503 100644 --- a/src/gallium/drivers/crocus/crocus_screen.h +++ b/src/gallium/drivers/crocus/crocus_screen.h @@ -34,7 +34,6 @@ #include "crocus_bufmgr.h" #include "compiler/shader_enums.h" -struct crocus_monitor_config; struct crocus_resource; struct crocus_context; struct crocus_sampler_state; @@ -209,7 +208,7 @@ struct crocus_screen { struct isl_device isl_dev; struct crocus_bufmgr *bufmgr; struct brw_compiler *compiler; - struct crocus_monitor_config *monitor_cfg; + struct intel_perf_config *perf_cfg; const struct intel_l3_config *l3_config_3d; const struct intel_l3_config *l3_config_cs; diff --git a/src/gallium/drivers/crocus/meson.build b/src/gallium/drivers/crocus/meson.build index 86e713c94f7..e0a270bfb21 100644 --- a/src/gallium/drivers/crocus/meson.build +++ b/src/gallium/drivers/crocus/meson.build @@ -38,6 +38,9 @@ files_libcrocus = files( 'crocus_genx_macros.h', 'crocus_genx_protos.h', 'crocus_monitor.c', + 'crocus_perf.c', + 'crocus_perf.h', + 'crocus_performance_query.c', 'crocus_pipe.h', 'crocus_pipe_control.c', 'crocus_program.c',