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