xref: /aosp_15_r20/external/mesa3d/src/intel/vulkan_hasvk/anv_measure.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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