Path: blob/21.2-virgl/src/gallium/drivers/iris/iris_measure.c
4565 views
/*1* Copyright © 2019 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included11* in all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS14* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING18* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER19* DEALINGS IN THE SOFTWARE.20*/2122/**23* @file iris_measure.c24*/2526#include <stdio.h>27#include "util/debug.h"28#include "util/list.h"29#include "util/crc32.h"30#include "iris_context.h"31#include "iris_defines.h"3233void34iris_init_screen_measure(struct iris_screen *screen)35{36struct intel_measure_device *measure_device = &screen->measure;3738memset(measure_device, 0, sizeof(*measure_device));39intel_measure_init(measure_device);40struct intel_measure_config *config = measure_device->config;41if (config == NULL)42return;4344/* the final member of intel_measure_ringbuffer is a zero-length array of45* intel_measure_buffered_result objects. Allocate additional space for46* the buffered objects based on the run-time configurable buffer_size47*/48const size_t rb_bytes = sizeof(struct intel_measure_ringbuffer) +49config->buffer_size * sizeof(struct intel_measure_buffered_result);50struct intel_measure_ringbuffer *rb = rzalloc_size(screen, rb_bytes);51measure_device->ringbuffer = rb;52}5354static struct intel_measure_config *55config_from_screen(struct iris_screen *screen)56{57return screen->measure.config;58}5960static struct intel_measure_config *61config_from_context(struct iris_context *ice)62{63return ((struct iris_screen *) ice->ctx.screen)->measure.config;64}6566void67iris_destroy_screen_measure(struct iris_screen *screen)68{69if (!config_from_screen(screen))70return;7172struct intel_measure_device *measure_device = &screen->measure;7374if (measure_device->config->file &&75measure_device->config->file != stderr)76fclose(screen->measure.config->file);7778ralloc_free(measure_device->ringbuffer);79measure_device->ringbuffer = NULL;80}818283void84iris_init_batch_measure(struct iris_context *ice, struct iris_batch *batch)85{86const struct intel_measure_config *config = config_from_context(ice);87struct iris_screen *screen = batch->screen;88struct iris_bufmgr *bufmgr = screen->bufmgr;8990if (!config)91return;9293/* the final member of iris_measure_batch is a zero-length array of94* intel_measure_snapshot objects. Create additional space for the95* snapshot objects based on the run-time configurable batch_size96*/97const size_t batch_bytes = sizeof(struct iris_measure_batch) +98config->batch_size * sizeof(struct intel_measure_snapshot);99assert(batch->measure == NULL);100batch->measure = malloc(batch_bytes);101memset(batch->measure, 0, batch_bytes);102struct iris_measure_batch *measure = batch->measure;103104measure->bo = iris_bo_alloc(bufmgr, "measure",105config->batch_size * sizeof(uint64_t), 1,106IRIS_MEMZONE_OTHER, BO_ALLOC_ZEROED);107measure->base.timestamps = iris_bo_map(NULL, measure->bo, MAP_READ);108measure->base.framebuffer =109(uintptr_t)util_hash_crc32(&ice->state.framebuffer,110sizeof(ice->state.framebuffer));111}112113void114iris_destroy_batch_measure(struct iris_measure_batch *batch)115{116if (!batch)117return;118iris_bo_unmap(batch->bo);119iris_bo_unreference(batch->bo);120batch->bo = NULL;121free(batch);122}123124static void125measure_start_snapshot(struct iris_context *ice,126struct iris_batch *batch,127enum intel_measure_snapshot_type type,128const char *event_name,129uint32_t count)130{131struct intel_measure_batch *measure_batch = &batch->measure->base;132const struct intel_measure_config *config = config_from_context(ice);133const struct iris_screen *screen = (void *) ice->ctx.screen;134const unsigned screen_frame = screen->measure.frame;135136/* if the command buffer is not associated with a frame, associate it with137* the most recent acquired frame138*/139if (measure_batch->frame == 0)140measure_batch->frame = screen_frame;141142uintptr_t framebuffer = measure_batch->framebuffer;143144if (measure_batch->index == config->batch_size) {145/* Snapshot buffer is full. The batch must be flushed before additional146* snapshots can be taken.147*/148static bool warned = false;149if (unlikely(!warned)) {150fprintf(config->file,151"WARNING: batch size exceeds INTEL_MEASURE limit: %d. "152"Data has been dropped. "153"Increase setting with INTEL_MEASURE=batch_size={count}\n",154config->batch_size);155warned = true;156}157return;158}159160unsigned index = measure_batch->index++;161assert(index < config->batch_size);162iris_emit_pipe_control_write(batch, "measurement snapshot",163PIPE_CONTROL_WRITE_TIMESTAMP |164PIPE_CONTROL_CS_STALL,165batch->measure->bo, index * sizeof(uint64_t), 0ull);166if (event_name == NULL)167event_name = intel_measure_snapshot_string(type);168169struct intel_measure_snapshot *snapshot = &(measure_batch->snapshots[index]);170memset(snapshot, 0, sizeof(*snapshot));171snapshot->type = type;172snapshot->count = (unsigned) count;173snapshot->event_count = measure_batch->event_count;174snapshot->event_name = event_name;175snapshot->framebuffer = framebuffer;176177if (type == INTEL_SNAPSHOT_COMPUTE) {178snapshot->cs = (uintptr_t) ice->shaders.prog[MESA_SHADER_COMPUTE];179} else {180snapshot->vs = (uintptr_t) ice->shaders.prog[MESA_SHADER_VERTEX];181snapshot->tcs = (uintptr_t) ice->shaders.prog[MESA_SHADER_TESS_CTRL];182snapshot->tes = (uintptr_t) ice->shaders.prog[MESA_SHADER_TESS_EVAL];183snapshot->gs = (uintptr_t) ice->shaders.prog[MESA_SHADER_GEOMETRY];184snapshot->fs = (uintptr_t) ice->shaders.prog[MESA_SHADER_FRAGMENT];185}186}187188static void189measure_end_snapshot(struct iris_batch *batch,190uint32_t event_count)191{192struct intel_measure_batch *measure_batch = &batch->measure->base;193194unsigned index = measure_batch->index++;195assert(index % 2 == 1);196197iris_emit_pipe_control_write(batch, "measurement snapshot",198PIPE_CONTROL_WRITE_TIMESTAMP |199PIPE_CONTROL_CS_STALL,200batch->measure->bo,201index * sizeof(uint64_t), 0ull);202203struct intel_measure_snapshot *snapshot = &(measure_batch->snapshots[index]);204memset(snapshot, 0, sizeof(*snapshot));205snapshot->type = INTEL_SNAPSHOT_END;206snapshot->event_count = event_count;207}208209static bool210state_changed(const struct iris_context *ice,211const struct iris_batch *batch,212enum intel_measure_snapshot_type type)213{214uintptr_t vs=0, tcs=0, tes=0, gs=0, fs=0, cs=0;215216if (type == INTEL_SNAPSHOT_COMPUTE) {217cs = (uintptr_t) ice->shaders.prog[MESA_SHADER_COMPUTE];218} else if (type == INTEL_SNAPSHOT_DRAW) {219vs = (uintptr_t) ice->shaders.prog[MESA_SHADER_VERTEX];220tcs = (uintptr_t) ice->shaders.prog[MESA_SHADER_TESS_CTRL];221tes = (uintptr_t) ice->shaders.prog[MESA_SHADER_TESS_EVAL];222gs = (uintptr_t) ice->shaders.prog[MESA_SHADER_GEOMETRY];223fs = (uintptr_t) ice->shaders.prog[MESA_SHADER_FRAGMENT];224}225/* else blorp, all programs NULL */226227return intel_measure_state_changed(&batch->measure->base,228vs, tcs, tes, gs, fs, cs);229}230231static void232iris_measure_renderpass(struct iris_context *ice)233{234const struct intel_measure_config *config = config_from_context(ice);235struct intel_measure_batch *batch =236&ice->batches[IRIS_BATCH_RENDER].measure->base;237238if (!config)239return;240uint32_t framebuffer_crc = util_hash_crc32(&ice->state.framebuffer,241sizeof(ice->state.framebuffer));242if (framebuffer_crc == batch->framebuffer)243return;244bool filtering = config->flags & INTEL_MEASURE_RENDERPASS;245if (filtering && batch->index % 2 == 1) {246/* snapshot for previous renderpass was not ended */247measure_end_snapshot(&ice->batches[IRIS_BATCH_RENDER],248batch->event_count);249batch->event_count = 0;250}251252batch->framebuffer = framebuffer_crc;253}254255void256_iris_measure_snapshot(struct iris_context *ice,257struct iris_batch *batch,258enum intel_measure_snapshot_type type,259const struct pipe_draw_info *draw,260const struct pipe_draw_indirect_info *indirect,261const struct pipe_draw_start_count_bias *sc)262{263264const struct intel_measure_config *config = config_from_context(ice);265struct intel_measure_batch* measure_batch = &batch->measure->base;266267assert(config);268if (!config->enabled)269return;270if (measure_batch == NULL)271return;272273assert(type != INTEL_SNAPSHOT_END);274iris_measure_renderpass(ice);275276if (!state_changed(ice, batch, type)) {277/* filter out this event */278return;279}280281/* increment event count */282++measure_batch->event_count;283if (measure_batch->event_count == 1 ||284measure_batch->event_count == config->event_interval + 1) {285/* the first event of an interval */286if (measure_batch->index % 2) {287/* end the previous event */288measure_end_snapshot(batch, measure_batch->event_count - 1);289}290measure_batch->event_count = 1;291292const char *event_name = NULL;293int count = 0;294if (sc)295count = sc->count;296297if (draw != NULL) {298const struct shader_info *fs_info =299iris_get_shader_info(ice, MESA_SHADER_FRAGMENT);300if (fs_info && fs_info->name && strncmp(fs_info->name, "st/", 2) == 0) {301event_name = fs_info->name;302} else if (indirect) {303event_name = "DrawIndirect";304if (indirect->count_from_stream_output) {305event_name = "DrawTransformFeedback";306}307}308else if (draw->index_size)309event_name = "DrawElements";310else311event_name = "DrawArrays";312count = count * (draw->instance_count ? draw->instance_count : 1);313}314315measure_start_snapshot(ice, batch, type, event_name, count);316return;317}318}319320void321iris_destroy_ctx_measure(struct iris_context *ice)322{323/* All outstanding snapshots must be collected before the context is324* destroyed.325*/326struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;327intel_measure_gather(&screen->measure, &screen->devinfo);328}329330void331iris_measure_batch_end(struct iris_context *ice, struct iris_batch *batch)332{333const struct intel_measure_config *config = config_from_context(ice);334struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;335struct iris_measure_batch *iris_measure_batch = batch->measure;336struct intel_measure_batch *measure_batch = &iris_measure_batch->base;337struct intel_measure_device *measure_device = &screen->measure;338339if (!config)340return;341if (!config->enabled)342return;343344assert(measure_batch);345assert(measure_device);346347static unsigned batch_count = 0;348measure_batch->batch_count = p_atomic_inc_return(&batch_count);349350if (measure_batch->index % 2) {351/* We hit the end of the batch, but never terminated our section of352* drawing with the same render target or shaders. End it now.353*/354measure_end_snapshot(batch, measure_batch->event_count);355}356357if (measure_batch->index == 0)358return;359360/* enqueue snapshot for gathering */361pthread_mutex_lock(&measure_device->mutex);362list_addtail(&iris_measure_batch->base.link, &measure_device->queued_snapshots);363batch->measure = NULL;364pthread_mutex_unlock(&measure_device->mutex);365/* init new measure_batch */366iris_init_batch_measure(ice, batch);367368static int interval = 0;369if (++interval > 10) {370intel_measure_gather(measure_device, &screen->devinfo);371interval = 0;372}373}374375void376iris_measure_frame_end(struct iris_context *ice)377{378struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;379struct intel_measure_device *measure_device = &screen->measure;380const struct intel_measure_config *config = measure_device->config;381382if (!config)383return;384385/* increment frame counter */386intel_measure_frame_transition(p_atomic_inc_return(&measure_device->frame));387388intel_measure_gather(measure_device, &screen->devinfo);389}390391392