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