1/* 2 * Copyright © 2019 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 */ 22 23#include <xf86drm.h> 24 25#include "iris_context.h" 26#include "iris_perf.h" 27 28struct iris_perf_query { 29 struct gl_perf_query_object base; 30 struct intel_perf_query_object *query; 31 bool begin_succeeded; 32}; 33 34static unsigned 35iris_init_perf_query_info(struct pipe_context *pipe) 36{ 37 struct iris_context *ice = (void *) pipe; 38 struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen; 39 struct intel_perf_config *perf_cfg = NULL; 40 41 /* make sure pipe perf counter type/data-type enums are matched with intel_perf's */ 42 STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_EVENT == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_EVENT); 43 STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_NORM == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_DURATION_NORM); 44 STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_DURATION_RAW == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_DURATION_RAW); 45 STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_THROUGHPUT == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_THROUGHPUT); 46 STATIC_ASSERT(PIPE_PERF_COUNTER_TYPE_RAW == (enum pipe_perf_counter_type)INTEL_PERF_COUNTER_TYPE_RAW); 47 48 STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_BOOL32 == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_BOOL32); 49 STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT32 == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_UINT32); 50 STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_UINT64 == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_UINT64); 51 STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_FLOAT == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_FLOAT); 52 STATIC_ASSERT(PIPE_PERF_COUNTER_DATA_TYPE_DOUBLE == (enum pipe_perf_counter_data_type)INTEL_PERF_COUNTER_DATA_TYPE_DOUBLE); 53 54 if (!ice->perf_ctx) 55 ice->perf_ctx = intel_perf_new_context(ice); 56 57 if (unlikely(!ice->perf_ctx)) 58 return 0; 59 60 perf_cfg = intel_perf_config(ice->perf_ctx); 61 62 if (perf_cfg) 63 return perf_cfg->n_queries; 64 65 perf_cfg = intel_perf_new(ice->perf_ctx); 66 67 iris_perf_init_vtbl(perf_cfg); 68 69 intel_perf_init_metrics(perf_cfg, &screen->devinfo, screen->fd, 70 true /* pipeline_statistics */, 71 true /* register snapshots */); 72 73 intel_perf_init_context(ice->perf_ctx, 74 perf_cfg, 75 ice, 76 ice, 77 screen->bufmgr, 78 &screen->devinfo, 79 ice->batches[IRIS_BATCH_RENDER].hw_ctx_id, 80 screen->fd); 81 82 return perf_cfg->n_queries; 83} 84 85static struct pipe_query * 86iris_new_perf_query_obj(struct pipe_context *pipe, unsigned query_index) 87{ 88 struct iris_context *ice = (void *) pipe; 89 struct intel_perf_context *perf_ctx = ice->perf_ctx; 90 struct intel_perf_query_object * obj = 91 intel_perf_new_query(perf_ctx, query_index); 92 if (unlikely(!obj)) 93 return NULL; 94 95 struct iris_perf_query *q = calloc(1, sizeof(struct iris_perf_query)); 96 if (unlikely(!q)) { 97 intel_perf_delete_query(perf_ctx, obj); 98 return NULL; 99 } 100 101 q->query = obj; 102 return (struct pipe_query *)&q->base; 103} 104 105static bool 106iris_begin_perf_query(struct pipe_context *pipe, struct pipe_query *q) 107{ 108 struct iris_context *ice = (void *) pipe; 109 struct iris_perf_query *perf_query= (struct iris_perf_query *) q; 110 struct intel_perf_query_object *obj = perf_query->query; 111 struct intel_perf_context *perf_ctx = ice->perf_ctx; 112 113 return (perf_query->begin_succeeded = intel_perf_begin_query(perf_ctx, obj)); 114} 115 116static void 117iris_end_perf_query(struct pipe_context *pipe, struct pipe_query *q) 118{ 119 struct iris_context *ice = (void *) pipe; 120 struct iris_perf_query *perf_query = (struct iris_perf_query *) q; 121 struct intel_perf_query_object *obj = perf_query->query; 122 struct intel_perf_context *perf_ctx = ice->perf_ctx; 123 124 if (perf_query->begin_succeeded) 125 intel_perf_end_query(perf_ctx, obj); 126} 127 128static void 129iris_delete_perf_query(struct pipe_context *pipe, struct pipe_query *q) 130{ 131 struct iris_context *ice = (void *) pipe; 132 struct iris_perf_query *perf_query = (struct iris_perf_query *) q; 133 struct intel_perf_query_object *obj = perf_query->query; 134 struct intel_perf_context *perf_ctx = ice->perf_ctx; 135 136 intel_perf_delete_query(perf_ctx, obj); 137 free(q); 138} 139 140static void 141iris_get_perf_query_info(struct pipe_context *pipe, 142 unsigned query_index, 143 const char **name, 144 uint32_t *data_size, 145 uint32_t *n_counters, 146 uint32_t *n_active) 147{ 148 struct iris_context *ice = (void *) pipe; 149 struct intel_perf_context *perf_ctx = ice->perf_ctx; 150 struct intel_perf_config *perf_cfg = intel_perf_config(perf_ctx); 151 const struct intel_perf_query_info *info = &perf_cfg->queries[query_index]; 152 153 *name = info->name; 154 *data_size = info->data_size; 155 *n_counters = info->n_counters; 156 *n_active = intel_perf_active_queries(perf_ctx, info); 157} 158 159static void 160iris_get_perf_counter_info(struct pipe_context *pipe, 161 unsigned query_index, 162 unsigned counter_index, 163 const char **name, 164 const char **desc, 165 uint32_t *offset, 166 uint32_t *data_size, 167 uint32_t *type_enum, 168 uint32_t *data_type_enum, 169 uint64_t *raw_max) 170{ 171 struct iris_context *ice = (void *) pipe; 172 struct intel_perf_context *perf_ctx = ice->perf_ctx; 173 struct intel_perf_config *perf_cfg = intel_perf_config(perf_ctx); 174 const struct intel_perf_query_info *info = &perf_cfg->queries[query_index]; 175 const struct intel_perf_query_counter *counter = 176 &info->counters[counter_index]; 177 178 *name = counter->name; 179 *desc = counter->desc; 180 *offset = counter->offset; 181 *data_size = intel_perf_query_counter_get_size(counter); 182 *type_enum = counter->type; 183 *data_type_enum = counter->data_type; 184 *raw_max = counter->raw_max; 185} 186 187static void 188iris_wait_perf_query(struct pipe_context *pipe, struct pipe_query *q) 189{ 190 struct iris_context *ice = (void *) pipe; 191 struct iris_perf_query *perf_query = (struct iris_perf_query *) q; 192 struct intel_perf_query_object *obj = perf_query->query; 193 struct intel_perf_context *perf_ctx = ice->perf_ctx; 194 195 if (perf_query->begin_succeeded) 196 intel_perf_wait_query(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER]); 197} 198 199static bool 200iris_is_perf_query_ready(struct pipe_context *pipe, struct pipe_query *q) 201{ 202 struct iris_context *ice = (void *) pipe; 203 struct iris_perf_query *perf_query = (struct iris_perf_query *) q; 204 struct intel_perf_query_object *obj = perf_query->query; 205 struct intel_perf_context *perf_ctx = ice->perf_ctx; 206 207 if (perf_query->base.Ready) 208 return true; 209 if (!perf_query->begin_succeeded) 210 return true; 211 212 return intel_perf_is_query_ready(perf_ctx, obj, 213 &ice->batches[IRIS_BATCH_RENDER]); 214} 215 216static bool 217iris_get_perf_query_data(struct pipe_context *pipe, 218 struct pipe_query *q, 219 size_t data_size, 220 uint32_t *data, 221 uint32_t *bytes_written) 222{ 223 struct iris_context *ice = (void *) pipe; 224 struct iris_perf_query *perf_query = (struct iris_perf_query *) q; 225 struct intel_perf_query_object *obj = perf_query->query; 226 struct intel_perf_context *perf_ctx = ice->perf_ctx; 227 228 if (perf_query->begin_succeeded) { 229 intel_perf_get_query_data(perf_ctx, obj, &ice->batches[IRIS_BATCH_RENDER], 230 data_size, data, bytes_written); 231 } 232 233 return perf_query->begin_succeeded; 234} 235 236void 237iris_init_perfquery_functions(struct pipe_context *ctx) 238{ 239 ctx->init_intel_perf_query_info = iris_init_perf_query_info; 240 ctx->get_intel_perf_query_info = iris_get_perf_query_info; 241 ctx->get_intel_perf_query_counter_info = iris_get_perf_counter_info; 242 ctx->new_intel_perf_query_obj = iris_new_perf_query_obj; 243 ctx->begin_intel_perf_query = iris_begin_perf_query; 244 ctx->end_intel_perf_query = iris_end_perf_query; 245 ctx->delete_intel_perf_query = iris_delete_perf_query; 246 ctx->wait_intel_perf_query = iris_wait_perf_query; 247 ctx->is_intel_perf_query_ready = iris_is_perf_query_ready; 248 ctx->get_intel_perf_query_data = iris_get_perf_query_data; 249} 250