1 /*
2 * Copyright © 2020 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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "anv_measure.h"
25
26 #include <fcntl.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29
30 #include "common/intel_measure.h"
31 #include "util/u_debug.h"
32
33 struct anv_measure_batch {
34 struct anv_bo *bo;
35 struct intel_measure_batch base;
36 };
37
38 void
anv_measure_device_init(struct anv_physical_device * device)39 anv_measure_device_init(struct anv_physical_device *device)
40 {
41 /* initialise list of measure structures that await rendering */
42 struct intel_measure_device *measure_device = &device->measure_device;
43 intel_measure_init(measure_device);
44 struct intel_measure_config *config = measure_device->config;
45 if (config == NULL)
46 return;
47
48 /* the final member of intel_measure_ringbuffer is a zero-length array of
49 * intel_measure_buffered_result objects. Allocate additional space for
50 * the buffered objects based on the run-time configurable buffer_size
51 */
52 const size_t rb_bytes = sizeof(struct intel_measure_ringbuffer) +
53 config->buffer_size * sizeof(struct intel_measure_buffered_result);
54 struct intel_measure_ringbuffer * rb =
55 vk_zalloc(&device->instance->vk.alloc,
56 rb_bytes, 8,
57 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
58 measure_device->ringbuffer = rb;
59 }
60
61 static struct intel_measure_config*
config_from_command_buffer(struct anv_cmd_buffer * cmd_buffer)62 config_from_command_buffer(struct anv_cmd_buffer *cmd_buffer)
63 {
64 return cmd_buffer->device->physical->measure_device.config;
65 }
66
67 void
anv_measure_init(struct anv_cmd_buffer * cmd_buffer)68 anv_measure_init(struct anv_cmd_buffer *cmd_buffer)
69 {
70 struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
71 struct anv_device *device = cmd_buffer->device;
72
73 if (!config || !config->enabled) {
74 cmd_buffer->measure = NULL;
75 return;
76 }
77
78 /* the final member of anv_measure is a zero-length array of
79 * intel_measure_snapshot objects. Create additional space for the
80 * snapshot objects based on the run-time configurable batch_size
81 */
82 const size_t batch_bytes = sizeof(struct anv_measure_batch) +
83 config->batch_size * sizeof(struct intel_measure_snapshot);
84 struct anv_measure_batch * measure =
85 vk_alloc(&cmd_buffer->vk.pool->alloc,
86 batch_bytes, 8,
87 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
88
89 memset(measure, 0, batch_bytes);
90 ASSERTED VkResult result =
91 anv_device_alloc_bo(device, "measure data",
92 config->batch_size * sizeof(uint64_t),
93 ANV_BO_ALLOC_MAPPED,
94 0,
95 (struct anv_bo**)&measure->bo);
96 measure->base.timestamps = measure->bo->map;
97 assert(result == VK_SUCCESS);
98
99 cmd_buffer->measure = measure;
100 }
101
102 static void
anv_measure_start_snapshot(struct anv_cmd_buffer * cmd_buffer,enum intel_measure_snapshot_type type,const char * event_name,uint32_t count)103 anv_measure_start_snapshot(struct anv_cmd_buffer *cmd_buffer,
104 enum intel_measure_snapshot_type type,
105 const char *event_name,
106 uint32_t count)
107 {
108 struct anv_batch *batch = &cmd_buffer->batch;
109 struct anv_measure_batch *measure = cmd_buffer->measure;
110 struct anv_physical_device *device = cmd_buffer->device->physical;
111 struct intel_measure_device *measure_device = &device->measure_device;
112
113 const unsigned device_frame = measure_device->frame;
114
115 /* if the command buffer is not associated with a frame, associate it with
116 * the most recent acquired frame
117 */
118 if (measure->base.frame == 0)
119 measure->base.frame = device_frame;
120
121 // uintptr_t framebuffer = (uintptr_t)cmd_buffer->state.framebuffer;
122 //
123 // if (!measure->base.framebuffer &&
124 // cmd_buffer->vk.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)
125 // /* secondary command buffer inherited the framebuffer from the primary */
126 // measure->base.framebuffer = framebuffer;
127 //
128 // /* verify framebuffer has been properly tracked */
129 // assert(type == INTEL_SNAPSHOT_END ||
130 // framebuffer == measure->base.framebuffer ||
131 // framebuffer == 0 ); /* compute has no framebuffer */
132
133 unsigned index = measure->base.index++;
134
135 (*device->cmd_emit_timestamp)(batch, cmd_buffer->device,
136 (struct anv_address) {
137 .bo = measure->bo,
138 .offset = index * sizeof(uint64_t) },
139 ANV_TIMESTAMP_CAPTURE_AT_CS_STALL);
140
141 if (event_name == NULL)
142 event_name = intel_measure_snapshot_string(type);
143
144 struct intel_measure_snapshot *snapshot = &(measure->base.snapshots[index]);
145 memset(snapshot, 0, sizeof(*snapshot));
146 snapshot->type = type;
147 snapshot->count = (unsigned) count;
148 snapshot->event_count = measure->base.event_count;
149 snapshot->event_name = event_name;
150 // snapshot->framebuffer = framebuffer;
151
152 if (type == INTEL_SNAPSHOT_COMPUTE && cmd_buffer->state.compute.pipeline) {
153 snapshot->cs = (uintptr_t) cmd_buffer->state.compute.pipeline->cs;
154 } else if (cmd_buffer->state.gfx.pipeline) {
155 const struct anv_graphics_pipeline *pipeline =
156 cmd_buffer->state.gfx.pipeline;
157 snapshot->vs = (uintptr_t) pipeline->shaders[MESA_SHADER_VERTEX];
158 snapshot->tcs = (uintptr_t) pipeline->shaders[MESA_SHADER_TESS_CTRL];
159 snapshot->tes = (uintptr_t) pipeline->shaders[MESA_SHADER_TESS_EVAL];
160 snapshot->gs = (uintptr_t) pipeline->shaders[MESA_SHADER_GEOMETRY];
161 snapshot->fs = (uintptr_t) pipeline->shaders[MESA_SHADER_FRAGMENT];
162 }
163 }
164
165 static void
anv_measure_end_snapshot(struct anv_cmd_buffer * cmd_buffer,uint32_t event_count)166 anv_measure_end_snapshot(struct anv_cmd_buffer *cmd_buffer,
167 uint32_t event_count)
168 {
169 struct anv_batch *batch = &cmd_buffer->batch;
170 struct anv_measure_batch *measure = cmd_buffer->measure;
171 struct anv_physical_device *device = cmd_buffer->device->physical;
172
173 unsigned index = measure->base.index++;
174 assert(index % 2 == 1);
175
176 (*device->cmd_emit_timestamp)(batch, cmd_buffer->device,
177 (struct anv_address) {
178 .bo = measure->bo,
179 .offset = index * sizeof(uint64_t) },
180 ANV_TIMESTAMP_CAPTURE_AT_CS_STALL);
181
182 struct intel_measure_snapshot *snapshot = &(measure->base.snapshots[index]);
183 memset(snapshot, 0, sizeof(*snapshot));
184 snapshot->type = INTEL_SNAPSHOT_END;
185 snapshot->event_count = event_count;
186 }
187
188 static bool
state_changed(struct anv_cmd_buffer * cmd_buffer,enum intel_measure_snapshot_type type)189 state_changed(struct anv_cmd_buffer *cmd_buffer,
190 enum intel_measure_snapshot_type type)
191 {
192 uintptr_t vs=0, tcs=0, tes=0, gs=0, fs=0, cs=0;
193
194 if (cmd_buffer->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)
195 /* can't record timestamps in this mode */
196 return false;
197
198 if (type == INTEL_SNAPSHOT_COMPUTE) {
199 const struct anv_compute_pipeline *cs_pipe =
200 cmd_buffer->state.compute.pipeline;
201 assert(cs_pipe);
202 cs = (uintptr_t)cs_pipe->cs;
203 } else if (type == INTEL_SNAPSHOT_DRAW) {
204 const struct anv_graphics_pipeline *gfx = cmd_buffer->state.gfx.pipeline;
205 assert(gfx);
206 vs = (uintptr_t) gfx->shaders[MESA_SHADER_VERTEX];
207 tcs = (uintptr_t) gfx->shaders[MESA_SHADER_TESS_CTRL];
208 tes = (uintptr_t) gfx->shaders[MESA_SHADER_TESS_EVAL];
209 gs = (uintptr_t) gfx->shaders[MESA_SHADER_GEOMETRY];
210 fs = (uintptr_t) gfx->shaders[MESA_SHADER_FRAGMENT];
211 }
212 /* else blorp, all programs NULL */
213
214 return intel_measure_state_changed(&cmd_buffer->measure->base,
215 vs, tcs, tes, gs, fs, cs, 0, 0);
216 }
217
218 void
_anv_measure_snapshot(struct anv_cmd_buffer * cmd_buffer,enum intel_measure_snapshot_type type,const char * event_name,uint32_t count)219 _anv_measure_snapshot(struct anv_cmd_buffer *cmd_buffer,
220 enum intel_measure_snapshot_type type,
221 const char *event_name,
222 uint32_t count)
223 {
224 struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
225 struct anv_measure_batch *measure = cmd_buffer->measure;
226
227 assert(config);
228 if (measure == NULL)
229 return;
230
231 assert(type != INTEL_SNAPSHOT_END);
232 if (!state_changed(cmd_buffer, type)) {
233 /* filter out this event */
234 return;
235 }
236
237 /* increment event count */
238 ++measure->base.event_count;
239 if (measure->base.event_count == 1 ||
240 measure->base.event_count == config->event_interval + 1) {
241 /* the first event of an interval */
242
243 if (measure->base.index % 2) {
244 /* end the previous event */
245 anv_measure_end_snapshot(cmd_buffer, measure->base.event_count - 1);
246 }
247 measure->base.event_count = 1;
248
249 if (measure->base.index == config->batch_size) {
250 /* Snapshot buffer is full. The batch must be flushed before
251 * additional snapshots can be taken.
252 */
253 static bool warned = false;
254 if (unlikely(!warned)) {
255 fprintf(config->file,
256 "WARNING: batch size exceeds INTEL_MEASURE limit: %d. "
257 "Data has been dropped. "
258 "Increase setting with INTEL_MEASURE=batch_size={count}\n",
259 config->batch_size);
260 }
261
262 warned = true;
263 return;
264 }
265
266 anv_measure_start_snapshot(cmd_buffer, type, event_name, count);
267 }
268 }
269
270 /**
271 * Called when a command buffer is reset. Re-initializes existing anv_measure
272 * data structures.
273 */
274 void
anv_measure_reset(struct anv_cmd_buffer * cmd_buffer)275 anv_measure_reset(struct anv_cmd_buffer *cmd_buffer)
276 {
277 struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
278 struct anv_device *device = cmd_buffer->device;
279 struct anv_measure_batch *measure = cmd_buffer->measure;
280
281 if (!config)
282 return;
283
284 if (!config->enabled) {
285 cmd_buffer->measure = NULL;
286 return;
287 }
288
289 if (!measure) {
290 /* Capture has recently been enabled. Instead of resetting, a new data
291 * structure must be allocated and initialized.
292 */
293 return anv_measure_init(cmd_buffer);
294 }
295
296 /* it is possible that the command buffer contains snapshots that have not
297 * yet been processed
298 */
299 intel_measure_gather(&device->physical->measure_device,
300 device->info);
301
302 assert(cmd_buffer->device != NULL);
303
304 measure->base.index = 0;
305 // measure->base.framebuffer = 0;
306 measure->base.frame = 0;
307 measure->base.event_count = 0;
308 list_inithead(&measure->base.link);
309 }
310
311 void
anv_measure_destroy(struct anv_cmd_buffer * cmd_buffer)312 anv_measure_destroy(struct anv_cmd_buffer *cmd_buffer)
313 {
314 struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
315 struct anv_measure_batch *measure = cmd_buffer->measure;
316 struct anv_device *device = cmd_buffer->device;
317 struct anv_physical_device *physical = device->physical;
318
319 if (!config)
320 return;
321 if (measure == NULL)
322 return;
323
324 /* it is possible that the command buffer contains snapshots that have not
325 * yet been processed
326 */
327 intel_measure_gather(&physical->measure_device, &physical->info);
328
329 anv_device_release_bo(device, measure->bo);
330 vk_free(&cmd_buffer->vk.pool->alloc, measure);
331 cmd_buffer->measure = NULL;
332 }
333
334 static struct intel_measure_config*
config_from_device(struct anv_device * device)335 config_from_device(struct anv_device *device)
336 {
337 return device->physical->measure_device.config;
338 }
339
340 void
anv_measure_device_destroy(struct anv_physical_device * device)341 anv_measure_device_destroy(struct anv_physical_device *device)
342 {
343 struct intel_measure_device *measure_device = &device->measure_device;
344 struct intel_measure_config *config = measure_device->config;
345
346 if (!config)
347 return;
348
349 if (measure_device->ringbuffer != NULL) {
350 vk_free(&device->instance->vk.alloc, measure_device->ringbuffer);
351 measure_device->ringbuffer = NULL;
352 }
353 }
354
355 /**
356 * Hook for command buffer submission.
357 */
358 void
_anv_measure_submit(struct anv_cmd_buffer * cmd_buffer)359 _anv_measure_submit(struct anv_cmd_buffer *cmd_buffer)
360 {
361 struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
362 struct anv_measure_batch *measure = cmd_buffer->measure;
363 struct intel_measure_device *measure_device = &cmd_buffer->device->physical->measure_device;
364
365 if (!config)
366 return;
367 if (measure == NULL)
368 return;
369
370 struct intel_measure_batch *base = &measure->base;
371 if (base->index == 0)
372 /* no snapshots were started */
373 return;
374
375 /* finalize snapshots and enqueue them */
376 static unsigned cmd_buffer_count = 0;
377 base->batch_count = p_atomic_inc_return(&cmd_buffer_count);
378
379 if (base->index %2 == 1) {
380 anv_measure_end_snapshot(cmd_buffer, base->event_count);
381 base->event_count = 0;
382 }
383
384 /* Mark the final timestamp as 'not completed'. This marker will be used
385 * to verify that rendering is complete.
386 */
387 base->timestamps[base->index - 1] = 0;
388
389 /* add to the list of submitted snapshots */
390 pthread_mutex_lock(&measure_device->mutex);
391 list_addtail(&measure->base.link, &measure_device->queued_snapshots);
392 pthread_mutex_unlock(&measure_device->mutex);
393 }
394
395 /**
396 * Hook for the start of a frame.
397 */
398 void
_anv_measure_acquire(struct anv_device * device)399 _anv_measure_acquire(struct anv_device *device)
400 {
401 struct intel_measure_config *config = config_from_device(device);
402 struct intel_measure_device *measure_device = &device->physical->measure_device;
403
404 if (!config)
405 return;
406 if (measure_device == NULL)
407 return;
408
409 intel_measure_frame_transition(p_atomic_inc_return(&measure_device->frame));
410
411 /* iterate the queued snapshots and publish those that finished */
412 intel_measure_gather(measure_device, &device->physical->info);
413 }
414
415 void
_anv_measure_endcommandbuffer(struct anv_cmd_buffer * cmd_buffer)416 _anv_measure_endcommandbuffer(struct anv_cmd_buffer *cmd_buffer)
417 {
418 struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
419 struct anv_measure_batch *measure = cmd_buffer->measure;
420
421 if (!config)
422 return;
423 if (measure == NULL)
424 return;
425 if (measure->base.index % 2 == 0)
426 return;
427
428 anv_measure_end_snapshot(cmd_buffer, measure->base.event_count);
429 measure->base.event_count = 0;
430 }
431
432 void
_anv_measure_beginrenderpass(struct anv_cmd_buffer * cmd_buffer)433 _anv_measure_beginrenderpass(struct anv_cmd_buffer *cmd_buffer)
434 {
435 struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
436 struct anv_measure_batch *measure = cmd_buffer->measure;
437
438 if (!config)
439 return;
440 if (measure == NULL)
441 return;
442
443 // if (measure->base.framebuffer == (uintptr_t) cmd_buffer->state.framebuffer)
444 // /* no change */
445 // return;
446
447 bool filtering = (config->flags & (INTEL_MEASURE_RENDERPASS |
448 INTEL_MEASURE_SHADER));
449 if (filtering && measure->base.index % 2 == 1) {
450 /* snapshot for previous renderpass was not ended */
451 anv_measure_end_snapshot(cmd_buffer,
452 measure->base.event_count);
453 measure->base.event_count = 0;
454 }
455
456 // measure->base.framebuffer = (uintptr_t) cmd_buffer->state.framebuffer;
457 }
458
459 void
_anv_measure_add_secondary(struct anv_cmd_buffer * primary,struct anv_cmd_buffer * secondary)460 _anv_measure_add_secondary(struct anv_cmd_buffer *primary,
461 struct anv_cmd_buffer *secondary)
462 {
463 struct intel_measure_config *config = config_from_command_buffer(primary);
464 struct anv_measure_batch *measure = primary->measure;
465 if (!config)
466 return;
467 if (measure == NULL)
468 return;
469 if (config->flags & (INTEL_MEASURE_BATCH | INTEL_MEASURE_FRAME))
470 /* secondary timing will be contained within the primary */
471 return;
472 if (secondary->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
473 static bool warned = false;
474 if (unlikely(!warned)) {
475 fprintf(config->file,
476 "WARNING: INTEL_MEASURE cannot capture timings of commands "
477 "in secondary command buffers with "
478 "VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set.\n");
479 }
480 return;
481 }
482
483 if (measure->base.index % 2 == 1)
484 anv_measure_end_snapshot(primary, measure->base.event_count);
485
486 struct intel_measure_snapshot *snapshot = &(measure->base.snapshots[measure->base.index]);
487 _anv_measure_snapshot(primary, INTEL_SNAPSHOT_SECONDARY_BATCH, NULL, 0);
488
489 snapshot->secondary = &secondary->measure->base;
490 }
491