Home | History | Annotate | Line # | Download | only in vulkan
      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
     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*
     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
     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->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
    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->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, measure->bo, index * sizeof(uint64_t));
    162 
    163    if (event_name == NULL)
    164       event_name = intel_measure_snapshot_string(type);
    165 
    166    struct intel_measure_snapshot *snapshot = &(measure->base.snapshots[index]);
    167    memset(snapshot, 0, sizeof(*snapshot));
    168    snapshot->type = type;
    169    snapshot->count = (unsigned) count;
    170    snapshot->event_count = measure->base.event_count;
    171    snapshot->event_name = event_name;
    172    snapshot->framebuffer = framebuffer;
    173 
    174    if (type == INTEL_SNAPSHOT_COMPUTE && cmd_buffer->state.compute.pipeline) {
    175       snapshot->cs = (uintptr_t) cmd_buffer->state.compute.pipeline->cs;
    176    } else if (cmd_buffer->state.gfx.pipeline) {
    177       const struct anv_graphics_pipeline *pipeline =
    178          cmd_buffer->state.gfx.pipeline;
    179       snapshot->vs = (uintptr_t) pipeline->shaders[MESA_SHADER_VERTEX];
    180       snapshot->tcs = (uintptr_t) pipeline->shaders[MESA_SHADER_TESS_CTRL];
    181       snapshot->tes = (uintptr_t) pipeline->shaders[MESA_SHADER_TESS_EVAL];
    182       snapshot->gs = (uintptr_t) pipeline->shaders[MESA_SHADER_GEOMETRY];
    183       snapshot->fs = (uintptr_t) pipeline->shaders[MESA_SHADER_FRAGMENT];
    184    }
    185 }
    186 
    187 static void
    188 anv_measure_end_snapshot(struct anv_cmd_buffer *cmd_buffer,
    189                          uint32_t event_count)
    190 {
    191    struct anv_batch *batch = &cmd_buffer->batch;
    192    struct anv_measure_batch *measure = cmd_buffer->measure;
    193    struct anv_physical_device *device = cmd_buffer->device->physical;
    194 
    195    unsigned index = measure->base.index++;
    196    assert(index % 2 == 1);
    197 
    198    (*device->cmd_emit_timestamp)(batch, measure->bo, index * sizeof(uint64_t));
    199 
    200    struct intel_measure_snapshot *snapshot = &(measure->base.snapshots[index]);
    201    memset(snapshot, 0, sizeof(*snapshot));
    202    snapshot->type = INTEL_SNAPSHOT_END;
    203    snapshot->event_count = event_count;
    204 }
    205 
    206 static bool
    207 state_changed(struct anv_cmd_buffer *cmd_buffer,
    208               enum intel_measure_snapshot_type type)
    209 {
    210    uintptr_t vs=0, tcs=0, tes=0, gs=0, fs=0, cs=0;
    211 
    212    if (cmd_buffer->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)
    213       /* can't record timestamps in this mode */
    214       return false;
    215 
    216    if (type == INTEL_SNAPSHOT_COMPUTE) {
    217       const struct anv_compute_pipeline *cs_pipe =
    218          cmd_buffer->state.compute.pipeline;
    219       assert(cs_pipe);
    220       cs = (uintptr_t)cs_pipe->cs;
    221    } else if (type == INTEL_SNAPSHOT_DRAW) {
    222       const struct anv_graphics_pipeline *gfx = cmd_buffer->state.gfx.pipeline;
    223       assert(gfx);
    224       vs = (uintptr_t) gfx->shaders[MESA_SHADER_VERTEX];
    225       tcs = (uintptr_t) gfx->shaders[MESA_SHADER_TESS_CTRL];
    226       tes = (uintptr_t) gfx->shaders[MESA_SHADER_TESS_EVAL];
    227       gs = (uintptr_t) gfx->shaders[MESA_SHADER_GEOMETRY];
    228       fs = (uintptr_t) gfx->shaders[MESA_SHADER_FRAGMENT];
    229    }
    230    /* else blorp, all programs NULL */
    231 
    232    return intel_measure_state_changed(&cmd_buffer->measure->base,
    233                                       vs, tcs, tes, gs, fs, cs);
    234 }
    235 
    236 void
    237 _anv_measure_snapshot(struct anv_cmd_buffer *cmd_buffer,
    238                      enum intel_measure_snapshot_type type,
    239                      const char *event_name,
    240                      uint32_t count)
    241 {
    242    struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
    243    struct anv_measure_batch *measure = cmd_buffer->measure;
    244 
    245    assert(config);
    246    if (measure == NULL)
    247       return;
    248 
    249    assert(type != INTEL_SNAPSHOT_END);
    250    if (!state_changed(cmd_buffer, type)) {
    251       /* filter out this event */
    252       return;
    253    }
    254 
    255    /* increment event count */
    256    ++measure->base.event_count;
    257    if (measure->base.event_count == 1 ||
    258        measure->base.event_count == config->event_interval + 1) {
    259       /* the first event of an interval */
    260 
    261       if (measure->base.index % 2) {
    262          /* end the previous event */
    263          anv_measure_end_snapshot(cmd_buffer, measure->base.event_count - 1);
    264       }
    265       measure->base.event_count = 1;
    266 
    267       if (measure->base.index == config->batch_size) {
    268          /* Snapshot buffer is full.  The batch must be flushed before
    269           * additional snapshots can be taken.
    270           */
    271          static bool warned = false;
    272          if (unlikely(!warned)) {
    273             fprintf(config->file,
    274                     "WARNING: batch size exceeds INTEL_MEASURE limit: %d. "
    275                     "Data has been dropped. "
    276                     "Increase setting with INTEL_MEASURE=batch_size={count}\n",
    277                     config->batch_size);
    278          }
    279 
    280          warned = true;
    281          return;
    282       }
    283 
    284       anv_measure_start_snapshot(cmd_buffer, type, event_name, count);
    285    }
    286 }
    287 
    288 /**
    289  * Called when a command buffer is reset.  Re-initializes existing anv_measure
    290  * data structures.
    291  */
    292 void
    293 anv_measure_reset(struct anv_cmd_buffer *cmd_buffer)
    294 {
    295    struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
    296    struct anv_device *device = cmd_buffer->device;
    297    struct anv_measure_batch *measure = cmd_buffer->measure;
    298 
    299    if (!config)
    300       return;
    301 
    302    if (!config->enabled) {
    303       cmd_buffer->measure = NULL;
    304       return;
    305    }
    306 
    307    if (!measure) {
    308       /* Capture has recently been enabled. Instead of resetting, a new data
    309        * structure must be allocated and initialized.
    310        */
    311       return anv_measure_init(cmd_buffer);
    312    }
    313 
    314    /* it is possible that the command buffer contains snapshots that have not
    315     * yet been processed
    316     */
    317    intel_measure_gather(&device->physical->measure_device,
    318                         &device->info);
    319 
    320    assert(cmd_buffer->device != NULL);
    321 
    322    measure->base.index = 0;
    323    measure->base.framebuffer = 0;
    324    measure->base.frame = 0;
    325    measure->base.event_count = 0;
    326    list_inithead(&measure->base.link);
    327 
    328    anv_device_release_bo(device, measure->bo);
    329    ASSERTED VkResult result =
    330       anv_device_alloc_bo(device, "measure data",
    331                           config->batch_size * sizeof(uint64_t),
    332                           ANV_BO_ALLOC_MAPPED,
    333                           0,
    334                           (struct anv_bo**)&measure->bo);
    335    measure->base.timestamps = measure->bo->map;
    336    assert(result == VK_SUCCESS);
    337 }
    338 
    339 void
    340 anv_measure_destroy(struct anv_cmd_buffer *cmd_buffer)
    341 {
    342    struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
    343    struct anv_measure_batch *measure = cmd_buffer->measure;
    344    struct anv_device *device = cmd_buffer->device;
    345    struct anv_physical_device *physical = device->physical;
    346 
    347    if (!config)
    348       return;
    349    if (measure == NULL)
    350       return;
    351 
    352    /* it is possible that the command buffer contains snapshots that have not
    353     * yet been processed
    354     */
    355    intel_measure_gather(&physical->measure_device, &physical->info);
    356 
    357    anv_device_release_bo(device, measure->bo);
    358    vk_free(&cmd_buffer->pool->alloc, measure);
    359    cmd_buffer->measure = NULL;
    360 }
    361 
    362 static struct intel_measure_config*
    363 config_from_device(struct anv_device *device)
    364 {
    365    return device->physical->measure_device.config;
    366 }
    367 
    368 void
    369 anv_measure_device_destroy(struct anv_physical_device *device)
    370 {
    371    struct intel_measure_device *measure_device = &device->measure_device;
    372    struct intel_measure_config *config = measure_device->config;
    373 
    374    if (!config)
    375       return;
    376 
    377    if (measure_device->ringbuffer != NULL) {
    378       vk_free(&device->instance->vk.alloc, measure_device->ringbuffer);
    379       measure_device->ringbuffer = NULL;
    380    }
    381 }
    382 
    383 /**
    384  *  Hook for command buffer submission.
    385  */
    386 void
    387 _anv_measure_submit(struct anv_cmd_buffer *cmd_buffer)
    388 {
    389    struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
    390    struct anv_measure_batch *measure = cmd_buffer->measure;
    391    struct intel_measure_device *measure_device = &cmd_buffer->device->physical->measure_device;
    392 
    393    if (!config)
    394       return;
    395    if (measure == NULL)
    396       return;
    397 
    398    if (measure->base.index == 0)
    399       /* no snapshots were started */
    400       return;
    401 
    402    /* finalize snapshots and enqueue them */
    403    static unsigned cmd_buffer_count = 0;
    404    measure->base.batch_count = p_atomic_inc_return(&cmd_buffer_count);
    405 
    406    if (measure->base.index %2 == 1) {
    407       anv_measure_end_snapshot(cmd_buffer, measure->base.event_count);
    408       measure->base.event_count = 0;
    409    }
    410 
    411    /* add to the list of submitted snapshots */
    412    pthread_mutex_lock(&measure_device->mutex);
    413    list_addtail(&measure->base.link, &measure_device->queued_snapshots);
    414    pthread_mutex_unlock(&measure_device->mutex);
    415 }
    416 
    417 /**
    418  *  Hook for the start of a frame.
    419  */
    420 void
    421 anv_measure_acquire(struct anv_device *device)
    422 {
    423    struct intel_measure_config *config = config_from_device(device);
    424    struct intel_measure_device *measure_device = &device->physical->measure_device;
    425 
    426    if (!config)
    427       return;
    428    if (measure_device == NULL)
    429       return;
    430 
    431    intel_measure_frame_transition(p_atomic_inc_return(&measure_device->frame));
    432 
    433    /* iterate the queued snapshots and publish those that finished */
    434    intel_measure_gather(measure_device, &device->physical->info);
    435 }
    436 
    437 void
    438 _anv_measure_endcommandbuffer(struct anv_cmd_buffer *cmd_buffer)
    439 {
    440    struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
    441    struct anv_measure_batch *measure = cmd_buffer->measure;
    442 
    443    if (!config)
    444       return;
    445    if (measure == NULL)
    446       return;
    447    if (measure->base.index % 2 == 0)
    448       return;
    449 
    450    anv_measure_end_snapshot(cmd_buffer, measure->base.event_count);
    451    measure->base.event_count = 0;
    452 }
    453 
    454 void
    455 _anv_measure_beginrenderpass(struct anv_cmd_buffer *cmd_buffer)
    456 {
    457    struct intel_measure_config *config = config_from_command_buffer(cmd_buffer);
    458    struct anv_measure_batch *measure = cmd_buffer->measure;
    459 
    460    if (!config)
    461       return;
    462    if (measure == NULL)
    463       return;
    464 
    465    if (measure->base.framebuffer == (uintptr_t) cmd_buffer->state.framebuffer)
    466       /* no change */
    467       return;
    468 
    469    bool filtering = (config->flags & (INTEL_MEASURE_RENDERPASS |
    470                                       INTEL_MEASURE_SHADER));
    471    if (filtering && measure->base.index % 2 == 1) {
    472       /* snapshot for previous renderpass was not ended */
    473       anv_measure_end_snapshot(cmd_buffer,
    474                                measure->base.event_count);
    475       measure->base.event_count = 0;
    476    }
    477 
    478    measure->base.framebuffer = (uintptr_t) cmd_buffer->state.framebuffer;
    479 }
    480 
    481 void
    482 _anv_measure_add_secondary(struct anv_cmd_buffer *primary,
    483                            struct anv_cmd_buffer *secondary)
    484 {
    485    struct intel_measure_config *config = config_from_command_buffer(primary);
    486    struct anv_measure_batch *measure = primary->measure;
    487    if (!config)
    488       return;
    489    if (measure == NULL)
    490       return;
    491    if (config->flags & (INTEL_MEASURE_BATCH | INTEL_MEASURE_FRAME))
    492       /* secondary timing will be contained within the primary */
    493       return;
    494    if (secondary->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
    495          static bool warned = false;
    496          if (unlikely(!warned)) {
    497             fprintf(config->file,
    498                     "WARNING: INTEL_MEASURE cannot capture timings of commands "
    499                     "in secondary command buffers with "
    500                     "VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set.\n");
    501          }
    502       return;
    503    }
    504 
    505    if (measure->base.index % 2 == 1)
    506       anv_measure_end_snapshot(primary, measure->base.event_count);
    507 
    508    struct intel_measure_snapshot *snapshot = &(measure->base.snapshots[measure->base.index]);
    509    _anv_measure_snapshot(primary, INTEL_SNAPSHOT_SECONDARY_BATCH, NULL, 0);
    510 
    511    snapshot->secondary = &secondary->measure->base;
    512 }
    513