1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2019 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 12bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include "crocus_monitor.h" 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include <xf86drm.h> 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "crocus_screen.h" 28bf215546Sopenharmony_ci#include "crocus_context.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "perf/intel_perf.h" 31bf215546Sopenharmony_ci#include "perf/intel_perf_query.h" 32bf215546Sopenharmony_ci#include "perf/intel_perf_regs.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_cistruct crocus_monitor_object { 35bf215546Sopenharmony_ci int num_active_counters; 36bf215546Sopenharmony_ci int *active_counters; 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci size_t result_size; 39bf215546Sopenharmony_ci unsigned char *result_buffer; 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci struct intel_perf_query_object *query; 42bf215546Sopenharmony_ci}; 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ciint 45bf215546Sopenharmony_cicrocus_get_monitor_info(struct pipe_screen *pscreen, unsigned index, 46bf215546Sopenharmony_ci struct pipe_driver_query_info *info) 47bf215546Sopenharmony_ci{ 48bf215546Sopenharmony_ci const struct crocus_screen *screen = (struct crocus_screen *)pscreen; 49bf215546Sopenharmony_ci assert(screen->monitor_cfg); 50bf215546Sopenharmony_ci if (!screen->monitor_cfg) 51bf215546Sopenharmony_ci return 0; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci const struct crocus_monitor_config *monitor_cfg = screen->monitor_cfg; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci if (!info) { 56bf215546Sopenharmony_ci /* return the number of metrics */ 57bf215546Sopenharmony_ci return monitor_cfg->num_counters; 58bf215546Sopenharmony_ci } 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci const struct intel_perf_config *perf_cfg = monitor_cfg->perf_cfg; 61bf215546Sopenharmony_ci const int group = monitor_cfg->counters[index].group; 62bf215546Sopenharmony_ci const int counter_index = monitor_cfg->counters[index].counter; 63bf215546Sopenharmony_ci struct intel_perf_query_counter *counter = 64bf215546Sopenharmony_ci &perf_cfg->queries[group].counters[counter_index]; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci info->group_id = group; 67bf215546Sopenharmony_ci info->name = counter->name; 68bf215546Sopenharmony_ci info->query_type = PIPE_QUERY_DRIVER_SPECIFIC + index; 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci if (counter->type == INTEL_PERF_COUNTER_TYPE_THROUGHPUT) 71bf215546Sopenharmony_ci info->result_type = PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE; 72bf215546Sopenharmony_ci else 73bf215546Sopenharmony_ci info->result_type = PIPE_DRIVER_QUERY_RESULT_TYPE_CUMULATIVE; 74bf215546Sopenharmony_ci switch (counter->data_type) { 75bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_BOOL32: 76bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_UINT32: 77bf215546Sopenharmony_ci info->type = PIPE_DRIVER_QUERY_TYPE_UINT; 78bf215546Sopenharmony_ci info->max_value.u32 = 0; 79bf215546Sopenharmony_ci break; 80bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_UINT64: 81bf215546Sopenharmony_ci info->type = PIPE_DRIVER_QUERY_TYPE_UINT64; 82bf215546Sopenharmony_ci info->max_value.u64 = 0; 83bf215546Sopenharmony_ci break; 84bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_FLOAT: 85bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_DOUBLE: 86bf215546Sopenharmony_ci info->type = PIPE_DRIVER_QUERY_TYPE_FLOAT; 87bf215546Sopenharmony_ci info->max_value.u64 = -1; 88bf215546Sopenharmony_ci break; 89bf215546Sopenharmony_ci default: 90bf215546Sopenharmony_ci assert(false); 91bf215546Sopenharmony_ci break; 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci /* indicates that this is an OA query, not a pipeline statistics query */ 95bf215546Sopenharmony_ci info->flags = PIPE_DRIVER_QUERY_FLAG_BATCH; 96bf215546Sopenharmony_ci return 1; 97bf215546Sopenharmony_ci} 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_citypedef void (*bo_unreference_t)(void *); 100bf215546Sopenharmony_citypedef void *(*bo_map_t)(void *, void *, unsigned flags); 101bf215546Sopenharmony_citypedef void (*bo_unmap_t)(void *); 102bf215546Sopenharmony_citypedef void (*emit_mi_report_t)(void *, void *, uint32_t, uint32_t); 103bf215546Sopenharmony_citypedef void (*emit_mi_flush_t)(void *); 104bf215546Sopenharmony_citypedef void (*capture_frequency_stat_register_t)(void *, void *, 105bf215546Sopenharmony_ci uint32_t ); 106bf215546Sopenharmony_citypedef void (*store_register_mem64_t)(void *ctx, void *bo, 107bf215546Sopenharmony_ci uint32_t reg, uint32_t offset); 108bf215546Sopenharmony_citypedef bool (*batch_references_t)(void *batch, void *bo); 109bf215546Sopenharmony_citypedef void (*bo_wait_rendering_t)(void *bo); 110bf215546Sopenharmony_citypedef int (*bo_busy_t)(void *bo); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_cistatic void * 113bf215546Sopenharmony_cicrocus_oa_bo_alloc(void *bufmgr, const char *name, uint64_t size) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci return crocus_bo_alloc(bufmgr, name, size); 116bf215546Sopenharmony_ci} 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci#if 0 119bf215546Sopenharmony_cistatic void 120bf215546Sopenharmony_cicrocus_monitor_emit_mi_flush(struct crocus_context *ice) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci const int flags = PIPE_CONTROL_RENDER_TARGET_FLUSH | 123bf215546Sopenharmony_ci PIPE_CONTROL_INSTRUCTION_INVALIDATE | 124bf215546Sopenharmony_ci PIPE_CONTROL_CONST_CACHE_INVALIDATE | 125bf215546Sopenharmony_ci PIPE_CONTROL_DATA_CACHE_FLUSH | 126bf215546Sopenharmony_ci PIPE_CONTROL_DEPTH_CACHE_FLUSH | 127bf215546Sopenharmony_ci PIPE_CONTROL_VF_CACHE_INVALIDATE | 128bf215546Sopenharmony_ci PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | 129bf215546Sopenharmony_ci PIPE_CONTROL_CS_STALL; 130bf215546Sopenharmony_ci crocus_emit_pipe_control_flush(&ice->batches[CROCUS_BATCH_RENDER], 131bf215546Sopenharmony_ci "OA metrics", flags); 132bf215546Sopenharmony_ci} 133bf215546Sopenharmony_ci#endif 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_cistatic void 136bf215546Sopenharmony_cicrocus_monitor_emit_mi_report_perf_count(void *c, 137bf215546Sopenharmony_ci void *bo, 138bf215546Sopenharmony_ci uint32_t offset_in_bytes, 139bf215546Sopenharmony_ci uint32_t report_id) 140bf215546Sopenharmony_ci{ 141bf215546Sopenharmony_ci struct crocus_context *ice = c; 142bf215546Sopenharmony_ci struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 143bf215546Sopenharmony_ci struct crocus_screen *screen = batch->screen; 144bf215546Sopenharmony_ci screen->vtbl.emit_mi_report_perf_count(batch, bo, offset_in_bytes, report_id); 145bf215546Sopenharmony_ci} 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_cistatic void 148bf215546Sopenharmony_cicrocus_monitor_batchbuffer_flush(void *c, const char *file, int line) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci struct crocus_context *ice = c; 151bf215546Sopenharmony_ci _crocus_batch_flush(&ice->batches[CROCUS_BATCH_RENDER], __FILE__, __LINE__); 152bf215546Sopenharmony_ci} 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci#if 0 155bf215546Sopenharmony_cistatic void 156bf215546Sopenharmony_cicrocus_monitor_capture_frequency_stat_register(void *ctx, 157bf215546Sopenharmony_ci void *bo, 158bf215546Sopenharmony_ci uint32_t bo_offset) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci struct crocus_context *ice = ctx; 161bf215546Sopenharmony_ci struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 162bf215546Sopenharmony_ci ice->vtbl.store_register_mem32(batch, GEN9_RPSTAT0, bo, bo_offset, false); 163bf215546Sopenharmony_ci} 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_cistatic void 166bf215546Sopenharmony_cicrocus_monitor_store_register_mem64(void *ctx, void *bo, 167bf215546Sopenharmony_ci uint32_t reg, uint32_t offset) 168bf215546Sopenharmony_ci{ 169bf215546Sopenharmony_ci struct crocus_context *ice = ctx; 170bf215546Sopenharmony_ci struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 171bf215546Sopenharmony_ci ice->vtbl.store_register_mem64(batch, reg, bo, offset, false); 172bf215546Sopenharmony_ci} 173bf215546Sopenharmony_ci#endif 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_cistatic bool 176bf215546Sopenharmony_cicrocus_monitor_init_metrics(struct crocus_screen *screen) 177bf215546Sopenharmony_ci{ 178bf215546Sopenharmony_ci struct crocus_monitor_config *monitor_cfg = 179bf215546Sopenharmony_ci rzalloc(screen, struct crocus_monitor_config); 180bf215546Sopenharmony_ci struct intel_perf_config *perf_cfg = NULL; 181bf215546Sopenharmony_ci if (unlikely(!monitor_cfg)) 182bf215546Sopenharmony_ci goto allocation_error; 183bf215546Sopenharmony_ci perf_cfg = intel_perf_new(monitor_cfg); 184bf215546Sopenharmony_ci if (unlikely(!perf_cfg)) 185bf215546Sopenharmony_ci goto allocation_error; 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci monitor_cfg->perf_cfg = perf_cfg; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci perf_cfg->vtbl.bo_alloc = crocus_oa_bo_alloc; 190bf215546Sopenharmony_ci perf_cfg->vtbl.bo_unreference = (bo_unreference_t)crocus_bo_unreference; 191bf215546Sopenharmony_ci perf_cfg->vtbl.bo_map = (bo_map_t)crocus_bo_map; 192bf215546Sopenharmony_ci perf_cfg->vtbl.bo_unmap = (bo_unmap_t)crocus_bo_unmap; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci perf_cfg->vtbl.emit_mi_report_perf_count = 195bf215546Sopenharmony_ci (emit_mi_report_t)crocus_monitor_emit_mi_report_perf_count; 196bf215546Sopenharmony_ci perf_cfg->vtbl.batchbuffer_flush = crocus_monitor_batchbuffer_flush; 197bf215546Sopenharmony_ci perf_cfg->vtbl.batch_references = (batch_references_t)crocus_batch_references; 198bf215546Sopenharmony_ci perf_cfg->vtbl.bo_wait_rendering = 199bf215546Sopenharmony_ci (bo_wait_rendering_t)crocus_bo_wait_rendering; 200bf215546Sopenharmony_ci perf_cfg->vtbl.bo_busy = (bo_busy_t)crocus_bo_busy; 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci intel_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd, false, false); 203bf215546Sopenharmony_ci screen->monitor_cfg = monitor_cfg; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci /* a gallium "group" is equivalent to a gen "query" 206bf215546Sopenharmony_ci * a gallium "query" is equivalent to a gen "query_counter" 207bf215546Sopenharmony_ci * 208bf215546Sopenharmony_ci * Each gen_query supports a specific number of query_counters. To 209bf215546Sopenharmony_ci * allocate the array of crocus_monitor_counter, we need an upper bound 210bf215546Sopenharmony_ci * (ignoring duplicate query_counters). 211bf215546Sopenharmony_ci */ 212bf215546Sopenharmony_ci int gen_query_counters_count = 0; 213bf215546Sopenharmony_ci for (int gen_query_id = 0; 214bf215546Sopenharmony_ci gen_query_id < perf_cfg->n_queries; 215bf215546Sopenharmony_ci ++gen_query_id) { 216bf215546Sopenharmony_ci gen_query_counters_count += perf_cfg->queries[gen_query_id].n_counters; 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci monitor_cfg->counters = rzalloc_size(monitor_cfg, 220bf215546Sopenharmony_ci sizeof(struct crocus_monitor_counter) * 221bf215546Sopenharmony_ci gen_query_counters_count); 222bf215546Sopenharmony_ci if (unlikely(!monitor_cfg->counters)) 223bf215546Sopenharmony_ci goto allocation_error; 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci int crocus_monitor_id = 0; 226bf215546Sopenharmony_ci for (int group = 0; group < perf_cfg->n_queries; ++group) { 227bf215546Sopenharmony_ci for (int counter = 0; 228bf215546Sopenharmony_ci counter < perf_cfg->queries[group].n_counters; 229bf215546Sopenharmony_ci ++counter) { 230bf215546Sopenharmony_ci /* Check previously identified metrics to filter out duplicates. The 231bf215546Sopenharmony_ci * user is not helped by having the same metric available in several 232bf215546Sopenharmony_ci * groups. (n^2 algorithm). 233bf215546Sopenharmony_ci */ 234bf215546Sopenharmony_ci bool duplicate = false; 235bf215546Sopenharmony_ci for (int existing_group = 0; 236bf215546Sopenharmony_ci existing_group < group && !duplicate; 237bf215546Sopenharmony_ci ++existing_group) { 238bf215546Sopenharmony_ci for (int existing_counter = 0; 239bf215546Sopenharmony_ci existing_counter < perf_cfg->queries[existing_group].n_counters && !duplicate; 240bf215546Sopenharmony_ci ++existing_counter) { 241bf215546Sopenharmony_ci const char *current_name = 242bf215546Sopenharmony_ci perf_cfg->queries[group].counters[counter].name; 243bf215546Sopenharmony_ci const char *existing_name = 244bf215546Sopenharmony_ci perf_cfg->queries[existing_group].counters[existing_counter].name; 245bf215546Sopenharmony_ci if (strcmp(current_name, existing_name) == 0) { 246bf215546Sopenharmony_ci duplicate = true; 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci } 250bf215546Sopenharmony_ci if (duplicate) 251bf215546Sopenharmony_ci continue; 252bf215546Sopenharmony_ci monitor_cfg->counters[crocus_monitor_id].group = group; 253bf215546Sopenharmony_ci monitor_cfg->counters[crocus_monitor_id].counter = counter; 254bf215546Sopenharmony_ci ++crocus_monitor_id; 255bf215546Sopenharmony_ci } 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci monitor_cfg->num_counters = crocus_monitor_id; 258bf215546Sopenharmony_ci return monitor_cfg->num_counters; 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ciallocation_error: 261bf215546Sopenharmony_ci if (monitor_cfg) 262bf215546Sopenharmony_ci free(monitor_cfg->counters); 263bf215546Sopenharmony_ci free(perf_cfg); 264bf215546Sopenharmony_ci free(monitor_cfg); 265bf215546Sopenharmony_ci return false; 266bf215546Sopenharmony_ci} 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ciint 269bf215546Sopenharmony_cicrocus_get_monitor_group_info(struct pipe_screen *pscreen, 270bf215546Sopenharmony_ci unsigned group_index, 271bf215546Sopenharmony_ci struct pipe_driver_query_group_info *info) 272bf215546Sopenharmony_ci{ 273bf215546Sopenharmony_ci struct crocus_screen *screen = (struct crocus_screen *)pscreen; 274bf215546Sopenharmony_ci if (!screen->monitor_cfg) { 275bf215546Sopenharmony_ci if (!crocus_monitor_init_metrics(screen)) 276bf215546Sopenharmony_ci return 0; 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci const struct crocus_monitor_config *monitor_cfg = screen->monitor_cfg; 280bf215546Sopenharmony_ci const struct intel_perf_config *perf_cfg = monitor_cfg->perf_cfg; 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci if (!info) { 283bf215546Sopenharmony_ci /* return the count that can be queried */ 284bf215546Sopenharmony_ci return perf_cfg->n_queries; 285bf215546Sopenharmony_ci } 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci if (group_index >= perf_cfg->n_queries) { 288bf215546Sopenharmony_ci /* out of range */ 289bf215546Sopenharmony_ci return 0; 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci struct intel_perf_query_info *query = &perf_cfg->queries[group_index]; 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci info->name = query->name; 295bf215546Sopenharmony_ci info->max_active_queries = query->n_counters; 296bf215546Sopenharmony_ci info->num_queries = query->n_counters; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci return 1; 299bf215546Sopenharmony_ci} 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_cistatic void 302bf215546Sopenharmony_cicrocus_init_monitor_ctx(struct crocus_context *ice) 303bf215546Sopenharmony_ci{ 304bf215546Sopenharmony_ci struct crocus_screen *screen = (struct crocus_screen *) ice->ctx.screen; 305bf215546Sopenharmony_ci struct crocus_monitor_config *monitor_cfg = screen->monitor_cfg; 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci ice->perf_ctx = intel_perf_new_context(ice); 308bf215546Sopenharmony_ci if (unlikely(!ice->perf_ctx)) 309bf215546Sopenharmony_ci return; 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 312bf215546Sopenharmony_ci struct intel_perf_config *perf_cfg = monitor_cfg->perf_cfg; 313bf215546Sopenharmony_ci intel_perf_init_context(perf_ctx, 314bf215546Sopenharmony_ci perf_cfg, 315bf215546Sopenharmony_ci ice, 316bf215546Sopenharmony_ci ice, 317bf215546Sopenharmony_ci screen->bufmgr, 318bf215546Sopenharmony_ci &screen->devinfo, 319bf215546Sopenharmony_ci ice->batches[CROCUS_BATCH_RENDER].hw_ctx_id, 320bf215546Sopenharmony_ci screen->fd); 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci/* entry point for GenPerfMonitorsAMD */ 324bf215546Sopenharmony_cistruct crocus_monitor_object * 325bf215546Sopenharmony_cicrocus_create_monitor_object(struct crocus_context *ice, 326bf215546Sopenharmony_ci unsigned num_queries, 327bf215546Sopenharmony_ci unsigned *query_types) 328bf215546Sopenharmony_ci{ 329bf215546Sopenharmony_ci struct crocus_screen *screen = (struct crocus_screen *) ice->ctx.screen; 330bf215546Sopenharmony_ci struct crocus_monitor_config *monitor_cfg = screen->monitor_cfg; 331bf215546Sopenharmony_ci struct intel_perf_config *perf_cfg = monitor_cfg->perf_cfg; 332bf215546Sopenharmony_ci struct intel_perf_query_object *query_obj = NULL; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci /* initialize perf context if this has not already been done. This 335bf215546Sopenharmony_ci * function is the first entry point that carries the gl context. 336bf215546Sopenharmony_ci */ 337bf215546Sopenharmony_ci if (ice->perf_ctx == NULL) { 338bf215546Sopenharmony_ci crocus_init_monitor_ctx(ice); 339bf215546Sopenharmony_ci } 340bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci assert(num_queries > 0); 343bf215546Sopenharmony_ci int query_index = query_types[0] - PIPE_QUERY_DRIVER_SPECIFIC; 344bf215546Sopenharmony_ci assert(query_index <= monitor_cfg->num_counters); 345bf215546Sopenharmony_ci const int group = monitor_cfg->counters[query_index].group; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci struct crocus_monitor_object *monitor = 348bf215546Sopenharmony_ci calloc(1, sizeof(struct crocus_monitor_object)); 349bf215546Sopenharmony_ci if (unlikely(!monitor)) 350bf215546Sopenharmony_ci goto allocation_failure; 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci monitor->num_active_counters = num_queries; 353bf215546Sopenharmony_ci monitor->active_counters = calloc(num_queries, sizeof(int)); 354bf215546Sopenharmony_ci if (unlikely(!monitor->active_counters)) 355bf215546Sopenharmony_ci goto allocation_failure; 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci for (int i = 0; i < num_queries; ++i) { 358bf215546Sopenharmony_ci unsigned current_query = query_types[i]; 359bf215546Sopenharmony_ci unsigned current_query_index = current_query - PIPE_QUERY_DRIVER_SPECIFIC; 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci /* all queries must be in the same group */ 362bf215546Sopenharmony_ci assert(current_query_index <= monitor_cfg->num_counters); 363bf215546Sopenharmony_ci assert(monitor_cfg->counters[current_query_index].group == group); 364bf215546Sopenharmony_ci monitor->active_counters[i] = 365bf215546Sopenharmony_ci monitor_cfg->counters[current_query_index].counter; 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci /* create the intel_perf_query */ 369bf215546Sopenharmony_ci query_obj = intel_perf_new_query(perf_ctx, group); 370bf215546Sopenharmony_ci if (unlikely(!query_obj)) 371bf215546Sopenharmony_ci goto allocation_failure; 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci monitor->query = query_obj; 374bf215546Sopenharmony_ci monitor->result_size = perf_cfg->queries[group].data_size; 375bf215546Sopenharmony_ci monitor->result_buffer = calloc(1, monitor->result_size); 376bf215546Sopenharmony_ci if (unlikely(!monitor->result_buffer)) 377bf215546Sopenharmony_ci goto allocation_failure; 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci return monitor; 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ciallocation_failure: 382bf215546Sopenharmony_ci if (monitor) { 383bf215546Sopenharmony_ci free(monitor->active_counters); 384bf215546Sopenharmony_ci free(monitor->result_buffer); 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci free(query_obj); 387bf215546Sopenharmony_ci free(monitor); 388bf215546Sopenharmony_ci return NULL; 389bf215546Sopenharmony_ci} 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_civoid 392bf215546Sopenharmony_cicrocus_destroy_monitor_object(struct pipe_context *ctx, 393bf215546Sopenharmony_ci struct crocus_monitor_object *monitor) 394bf215546Sopenharmony_ci{ 395bf215546Sopenharmony_ci struct crocus_context *ice = (struct crocus_context *)ctx; 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci intel_perf_delete_query(ice->perf_ctx, monitor->query); 398bf215546Sopenharmony_ci free(monitor->result_buffer); 399bf215546Sopenharmony_ci monitor->result_buffer = NULL; 400bf215546Sopenharmony_ci free(monitor->active_counters); 401bf215546Sopenharmony_ci monitor->active_counters = NULL; 402bf215546Sopenharmony_ci free(monitor); 403bf215546Sopenharmony_ci} 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_cibool 406bf215546Sopenharmony_cicrocus_begin_monitor(struct pipe_context *ctx, 407bf215546Sopenharmony_ci struct crocus_monitor_object *monitor) 408bf215546Sopenharmony_ci{ 409bf215546Sopenharmony_ci struct crocus_context *ice = (void *) ctx; 410bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci return intel_perf_begin_query(perf_ctx, monitor->query); 413bf215546Sopenharmony_ci} 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_cibool 416bf215546Sopenharmony_cicrocus_end_monitor(struct pipe_context *ctx, 417bf215546Sopenharmony_ci struct crocus_monitor_object *monitor) 418bf215546Sopenharmony_ci{ 419bf215546Sopenharmony_ci struct crocus_context *ice = (void *) ctx; 420bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci intel_perf_end_query(perf_ctx, monitor->query); 423bf215546Sopenharmony_ci return true; 424bf215546Sopenharmony_ci} 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_cibool 427bf215546Sopenharmony_cicrocus_get_monitor_result(struct pipe_context *ctx, 428bf215546Sopenharmony_ci struct crocus_monitor_object *monitor, 429bf215546Sopenharmony_ci bool wait, 430bf215546Sopenharmony_ci union pipe_numeric_type_union *result) 431bf215546Sopenharmony_ci{ 432bf215546Sopenharmony_ci struct crocus_context *ice = (void *) ctx; 433bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 434bf215546Sopenharmony_ci struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci bool monitor_ready = 437bf215546Sopenharmony_ci intel_perf_is_query_ready(perf_ctx, monitor->query, batch); 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci if (!monitor_ready) { 440bf215546Sopenharmony_ci if (!wait) 441bf215546Sopenharmony_ci return false; 442bf215546Sopenharmony_ci intel_perf_wait_query(perf_ctx, monitor->query, batch); 443bf215546Sopenharmony_ci } 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci assert(intel_perf_is_query_ready(perf_ctx, monitor->query, batch)); 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci unsigned bytes_written; 448bf215546Sopenharmony_ci intel_perf_get_query_data(perf_ctx, monitor->query, batch, 449bf215546Sopenharmony_ci monitor->result_size, 450bf215546Sopenharmony_ci (unsigned*) monitor->result_buffer, 451bf215546Sopenharmony_ci &bytes_written); 452bf215546Sopenharmony_ci if (bytes_written != monitor->result_size) 453bf215546Sopenharmony_ci return false; 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci /* copy metrics into the batch result */ 456bf215546Sopenharmony_ci for (int i = 0; i < monitor->num_active_counters; ++i) { 457bf215546Sopenharmony_ci int current_counter = monitor->active_counters[i]; 458bf215546Sopenharmony_ci const struct intel_perf_query_info *info = 459bf215546Sopenharmony_ci intel_perf_query_info(monitor->query); 460bf215546Sopenharmony_ci const struct intel_perf_query_counter *counter = 461bf215546Sopenharmony_ci &info->counters[current_counter]; 462bf215546Sopenharmony_ci assert(intel_perf_query_counter_get_size(counter)); 463bf215546Sopenharmony_ci switch (counter->data_type) { 464bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_UINT64: 465bf215546Sopenharmony_ci result[i].u64 = *(uint64_t*)(monitor->result_buffer + counter->offset); 466bf215546Sopenharmony_ci break; 467bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_FLOAT: 468bf215546Sopenharmony_ci result[i].f = *(float*)(monitor->result_buffer + counter->offset); 469bf215546Sopenharmony_ci break; 470bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_UINT32: 471bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_BOOL32: 472bf215546Sopenharmony_ci result[i].u64 = *(uint32_t*)(monitor->result_buffer + counter->offset); 473bf215546Sopenharmony_ci break; 474bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_DOUBLE: { 475bf215546Sopenharmony_ci double v = *(double*)(monitor->result_buffer + counter->offset); 476bf215546Sopenharmony_ci result[i].f = v; 477bf215546Sopenharmony_ci break; 478bf215546Sopenharmony_ci } 479bf215546Sopenharmony_ci default: 480bf215546Sopenharmony_ci unreachable("unexpected counter data type"); 481bf215546Sopenharmony_ci } 482bf215546Sopenharmony_ci } 483bf215546Sopenharmony_ci return true; 484bf215546Sopenharmony_ci} 485