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 "iris_monitor.h" 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include <xf86drm.h> 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "iris_screen.h" 28bf215546Sopenharmony_ci#include "iris_context.h" 29bf215546Sopenharmony_ci#include "iris_perf.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_cistruct iris_monitor_object { 32bf215546Sopenharmony_ci int num_active_counters; 33bf215546Sopenharmony_ci int *active_counters; 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci size_t result_size; 36bf215546Sopenharmony_ci unsigned char *result_buffer; 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci struct intel_perf_query_object *query; 39bf215546Sopenharmony_ci}; 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ciint 42bf215546Sopenharmony_ciiris_get_monitor_info(struct pipe_screen *pscreen, unsigned index, 43bf215546Sopenharmony_ci struct pipe_driver_query_info *info) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci struct iris_screen *screen = (struct iris_screen *)pscreen; 46bf215546Sopenharmony_ci struct intel_perf_config *perf_cfg = screen->perf_cfg; 47bf215546Sopenharmony_ci assert(perf_cfg); 48bf215546Sopenharmony_ci if (!perf_cfg) 49bf215546Sopenharmony_ci return 0; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci if (!info) { 52bf215546Sopenharmony_ci /* return the number of metrics */ 53bf215546Sopenharmony_ci return perf_cfg->n_counters; 54bf215546Sopenharmony_ci } 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci struct intel_perf_query_counter_info *counter_info = &perf_cfg->counter_infos[index]; 57bf215546Sopenharmony_ci struct intel_perf_query_info *query_info = 58bf215546Sopenharmony_ci &perf_cfg->queries[intel_perf_query_counter_info_first_query(counter_info)]; 59bf215546Sopenharmony_ci struct intel_perf_query_counter *counter = counter_info->counter; 60bf215546Sopenharmony_ci struct intel_perf_query_result results; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci intel_perf_query_result_clear(&results); 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci info->group_id = counter_info->location.group_idx; 65bf215546Sopenharmony_ci info->name = counter->name; 66bf215546Sopenharmony_ci info->query_type = PIPE_QUERY_DRIVER_SPECIFIC + index; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci if (counter->type == INTEL_PERF_COUNTER_TYPE_THROUGHPUT) 69bf215546Sopenharmony_ci info->result_type = PIPE_DRIVER_QUERY_RESULT_TYPE_AVERAGE; 70bf215546Sopenharmony_ci else 71bf215546Sopenharmony_ci info->result_type = PIPE_DRIVER_QUERY_RESULT_TYPE_CUMULATIVE; 72bf215546Sopenharmony_ci switch (counter->data_type) { 73bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_BOOL32: 74bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_UINT32: { 75bf215546Sopenharmony_ci info->type = PIPE_DRIVER_QUERY_TYPE_UINT; 76bf215546Sopenharmony_ci uint64_t val = 77bf215546Sopenharmony_ci counter->oa_counter_max_uint64 ? 78bf215546Sopenharmony_ci counter->oa_counter_max_uint64(perf_cfg, query_info, &results) : 0; 79bf215546Sopenharmony_ci assert(val <= UINT32_MAX); 80bf215546Sopenharmony_ci info->max_value.u32 = (uint32_t)val; 81bf215546Sopenharmony_ci break; 82bf215546Sopenharmony_ci } 83bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_UINT64: 84bf215546Sopenharmony_ci info->type = PIPE_DRIVER_QUERY_TYPE_UINT64; 85bf215546Sopenharmony_ci info->max_value.u64 = 86bf215546Sopenharmony_ci counter->oa_counter_max_uint64 ? 87bf215546Sopenharmony_ci counter->oa_counter_max_uint64(perf_cfg, query_info, &results) : 0; 88bf215546Sopenharmony_ci break; 89bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_FLOAT: 90bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_DOUBLE: 91bf215546Sopenharmony_ci info->type = PIPE_DRIVER_QUERY_TYPE_FLOAT; 92bf215546Sopenharmony_ci info->max_value.f = 93bf215546Sopenharmony_ci counter->oa_counter_max_float ? 94bf215546Sopenharmony_ci counter->oa_counter_max_float(perf_cfg, query_info, &results) : 0.0f; 95bf215546Sopenharmony_ci break; 96bf215546Sopenharmony_ci default: 97bf215546Sopenharmony_ci assert(false); 98bf215546Sopenharmony_ci break; 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci /* indicates that this is an OA query, not a pipeline statistics query */ 102bf215546Sopenharmony_ci info->flags = PIPE_DRIVER_QUERY_FLAG_BATCH; 103bf215546Sopenharmony_ci return 1; 104bf215546Sopenharmony_ci} 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_cistatic bool 107bf215546Sopenharmony_ciiris_monitor_init_metrics(struct iris_screen *screen) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci struct intel_perf_config *perf_cfg = intel_perf_new(screen); 110bf215546Sopenharmony_ci if (unlikely(!perf_cfg)) 111bf215546Sopenharmony_ci return false; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci screen->perf_cfg = perf_cfg; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci iris_perf_init_vtbl(perf_cfg); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci intel_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd, 118bf215546Sopenharmony_ci true /* pipeline stats*/, 119bf215546Sopenharmony_ci true /* register snapshots */); 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci return perf_cfg->n_counters > 0; 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ciint 125bf215546Sopenharmony_ciiris_get_monitor_group_info(struct pipe_screen *pscreen, 126bf215546Sopenharmony_ci unsigned group_index, 127bf215546Sopenharmony_ci struct pipe_driver_query_group_info *info) 128bf215546Sopenharmony_ci{ 129bf215546Sopenharmony_ci struct iris_screen *screen = (struct iris_screen *)pscreen; 130bf215546Sopenharmony_ci if (!screen->perf_cfg) { 131bf215546Sopenharmony_ci if (!iris_monitor_init_metrics(screen)) 132bf215546Sopenharmony_ci return 0; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci const struct intel_perf_config *perf_cfg = screen->perf_cfg; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci if (!info) { 138bf215546Sopenharmony_ci /* return the count that can be queried */ 139bf215546Sopenharmony_ci return perf_cfg->n_queries; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci if (group_index >= perf_cfg->n_queries) { 143bf215546Sopenharmony_ci /* out of range */ 144bf215546Sopenharmony_ci return 0; 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci struct intel_perf_query_info *query = &perf_cfg->queries[group_index]; 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci info->name = query->name; 150bf215546Sopenharmony_ci info->max_active_queries = query->n_counters; 151bf215546Sopenharmony_ci info->num_queries = query->n_counters; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci return 1; 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic void 157bf215546Sopenharmony_ciiris_init_monitor_ctx(struct iris_context *ice) 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci ice->perf_ctx = intel_perf_new_context(ice); 162bf215546Sopenharmony_ci if (unlikely(!ice->perf_ctx)) 163bf215546Sopenharmony_ci return; 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 166bf215546Sopenharmony_ci struct intel_perf_config *perf_cfg = screen->perf_cfg; 167bf215546Sopenharmony_ci intel_perf_init_context(perf_ctx, 168bf215546Sopenharmony_ci perf_cfg, 169bf215546Sopenharmony_ci ice, 170bf215546Sopenharmony_ci ice, 171bf215546Sopenharmony_ci screen->bufmgr, 172bf215546Sopenharmony_ci &screen->devinfo, 173bf215546Sopenharmony_ci ice->batches[IRIS_BATCH_RENDER].ctx_id, 174bf215546Sopenharmony_ci screen->fd); 175bf215546Sopenharmony_ci} 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci/* entry point for GenPerfMonitorsAMD */ 178bf215546Sopenharmony_cistruct iris_monitor_object * 179bf215546Sopenharmony_ciiris_create_monitor_object(struct iris_context *ice, 180bf215546Sopenharmony_ci unsigned num_queries, 181bf215546Sopenharmony_ci unsigned *query_types) 182bf215546Sopenharmony_ci{ 183bf215546Sopenharmony_ci struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen; 184bf215546Sopenharmony_ci struct intel_perf_config *perf_cfg = screen->perf_cfg; 185bf215546Sopenharmony_ci struct intel_perf_query_object *query_obj = NULL; 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci /* initialize perf context if this has not already been done. This 188bf215546Sopenharmony_ci * function is the first entry point that carries the gl context. 189bf215546Sopenharmony_ci */ 190bf215546Sopenharmony_ci if (ice->perf_ctx == NULL) { 191bf215546Sopenharmony_ci iris_init_monitor_ctx(ice); 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci assert(num_queries > 0); 196bf215546Sopenharmony_ci int query_index = query_types[0] - PIPE_QUERY_DRIVER_SPECIFIC; 197bf215546Sopenharmony_ci assert(query_index <= perf_cfg->n_counters); 198bf215546Sopenharmony_ci const int group = perf_cfg->counter_infos[query_index].location.group_idx; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci struct iris_monitor_object *monitor = 201bf215546Sopenharmony_ci calloc(1, sizeof(struct iris_monitor_object)); 202bf215546Sopenharmony_ci if (unlikely(!monitor)) 203bf215546Sopenharmony_ci goto allocation_failure; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci monitor->num_active_counters = num_queries; 206bf215546Sopenharmony_ci monitor->active_counters = calloc(num_queries, sizeof(int)); 207bf215546Sopenharmony_ci if (unlikely(!monitor->active_counters)) 208bf215546Sopenharmony_ci goto allocation_failure; 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci for (int i = 0; i < num_queries; ++i) { 211bf215546Sopenharmony_ci unsigned current_query = query_types[i]; 212bf215546Sopenharmony_ci unsigned current_query_index = current_query - PIPE_QUERY_DRIVER_SPECIFIC; 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci /* all queries must be in the same group */ 215bf215546Sopenharmony_ci assert(current_query_index <= perf_cfg->n_counters); 216bf215546Sopenharmony_ci assert(perf_cfg->counter_infos[current_query_index].location.group_idx == group); 217bf215546Sopenharmony_ci monitor->active_counters[i] = 218bf215546Sopenharmony_ci perf_cfg->counter_infos[current_query_index].location.counter_idx; 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci /* create the intel_perf_query */ 222bf215546Sopenharmony_ci query_obj = intel_perf_new_query(perf_ctx, group); 223bf215546Sopenharmony_ci if (unlikely(!query_obj)) 224bf215546Sopenharmony_ci goto allocation_failure; 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci monitor->query = query_obj; 227bf215546Sopenharmony_ci monitor->result_size = perf_cfg->queries[group].data_size; 228bf215546Sopenharmony_ci monitor->result_buffer = calloc(1, monitor->result_size); 229bf215546Sopenharmony_ci if (unlikely(!monitor->result_buffer)) 230bf215546Sopenharmony_ci goto allocation_failure; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci return monitor; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ciallocation_failure: 235bf215546Sopenharmony_ci if (monitor) { 236bf215546Sopenharmony_ci free(monitor->active_counters); 237bf215546Sopenharmony_ci free(monitor->result_buffer); 238bf215546Sopenharmony_ci } 239bf215546Sopenharmony_ci free(query_obj); 240bf215546Sopenharmony_ci free(monitor); 241bf215546Sopenharmony_ci return NULL; 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_civoid 245bf215546Sopenharmony_ciiris_destroy_monitor_object(struct pipe_context *ctx, 246bf215546Sopenharmony_ci struct iris_monitor_object *monitor) 247bf215546Sopenharmony_ci{ 248bf215546Sopenharmony_ci struct iris_context *ice = (struct iris_context *)ctx; 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci intel_perf_delete_query(ice->perf_ctx, monitor->query); 251bf215546Sopenharmony_ci free(monitor->result_buffer); 252bf215546Sopenharmony_ci monitor->result_buffer = NULL; 253bf215546Sopenharmony_ci free(monitor->active_counters); 254bf215546Sopenharmony_ci monitor->active_counters = NULL; 255bf215546Sopenharmony_ci free(monitor); 256bf215546Sopenharmony_ci} 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_cibool 259bf215546Sopenharmony_ciiris_begin_monitor(struct pipe_context *ctx, 260bf215546Sopenharmony_ci struct iris_monitor_object *monitor) 261bf215546Sopenharmony_ci{ 262bf215546Sopenharmony_ci struct iris_context *ice = (void *) ctx; 263bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci return intel_perf_begin_query(perf_ctx, monitor->query); 266bf215546Sopenharmony_ci} 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_cibool 269bf215546Sopenharmony_ciiris_end_monitor(struct pipe_context *ctx, 270bf215546Sopenharmony_ci struct iris_monitor_object *monitor) 271bf215546Sopenharmony_ci{ 272bf215546Sopenharmony_ci struct iris_context *ice = (void *) ctx; 273bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci intel_perf_end_query(perf_ctx, monitor->query); 276bf215546Sopenharmony_ci return true; 277bf215546Sopenharmony_ci} 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_cibool 280bf215546Sopenharmony_ciiris_get_monitor_result(struct pipe_context *ctx, 281bf215546Sopenharmony_ci struct iris_monitor_object *monitor, 282bf215546Sopenharmony_ci bool wait, 283bf215546Sopenharmony_ci union pipe_numeric_type_union *result) 284bf215546Sopenharmony_ci{ 285bf215546Sopenharmony_ci struct iris_context *ice = (void *) ctx; 286bf215546Sopenharmony_ci struct intel_perf_context *perf_ctx = ice->perf_ctx; 287bf215546Sopenharmony_ci struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER]; 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci bool monitor_ready = 290bf215546Sopenharmony_ci intel_perf_is_query_ready(perf_ctx, monitor->query, batch); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci if (!monitor_ready) { 293bf215546Sopenharmony_ci if (!wait) 294bf215546Sopenharmony_ci return false; 295bf215546Sopenharmony_ci intel_perf_wait_query(perf_ctx, monitor->query, batch); 296bf215546Sopenharmony_ci } 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci assert(intel_perf_is_query_ready(perf_ctx, monitor->query, batch)); 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci unsigned bytes_written; 301bf215546Sopenharmony_ci intel_perf_get_query_data(perf_ctx, monitor->query, batch, 302bf215546Sopenharmony_ci monitor->result_size, 303bf215546Sopenharmony_ci (unsigned*) monitor->result_buffer, 304bf215546Sopenharmony_ci &bytes_written); 305bf215546Sopenharmony_ci if (bytes_written != monitor->result_size) 306bf215546Sopenharmony_ci return false; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci /* copy metrics into the batch result */ 309bf215546Sopenharmony_ci for (int i = 0; i < monitor->num_active_counters; ++i) { 310bf215546Sopenharmony_ci int current_counter = monitor->active_counters[i]; 311bf215546Sopenharmony_ci const struct intel_perf_query_info *info = 312bf215546Sopenharmony_ci intel_perf_query_info(monitor->query); 313bf215546Sopenharmony_ci const struct intel_perf_query_counter *counter = 314bf215546Sopenharmony_ci &info->counters[current_counter]; 315bf215546Sopenharmony_ci assert(intel_perf_query_counter_get_size(counter)); 316bf215546Sopenharmony_ci switch (counter->data_type) { 317bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_UINT64: 318bf215546Sopenharmony_ci result[i].u64 = *(uint64_t*)(monitor->result_buffer + counter->offset); 319bf215546Sopenharmony_ci break; 320bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_FLOAT: 321bf215546Sopenharmony_ci result[i].f = *(float*)(monitor->result_buffer + counter->offset); 322bf215546Sopenharmony_ci break; 323bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_UINT32: 324bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_BOOL32: 325bf215546Sopenharmony_ci result[i].u64 = *(uint32_t*)(monitor->result_buffer + counter->offset); 326bf215546Sopenharmony_ci break; 327bf215546Sopenharmony_ci case INTEL_PERF_COUNTER_DATA_TYPE_DOUBLE: { 328bf215546Sopenharmony_ci double v = *(double*)(monitor->result_buffer + counter->offset); 329bf215546Sopenharmony_ci result[i].f = v; 330bf215546Sopenharmony_ci break; 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci default: 333bf215546Sopenharmony_ci unreachable("unexpected counter data type"); 334bf215546Sopenharmony_ci } 335bf215546Sopenharmony_ci } 336bf215546Sopenharmony_ci return true; 337bf215546Sopenharmony_ci} 338