xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/iris/iris_measure.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2019 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  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 /**
24  * @file iris_measure.c
25  */
26 
27 #include <stdio.h>
28 #include "util/u_debug.h"
29 #include "util/list.h"
30 #include "util/crc32.h"
31 #include "iris_context.h"
32 #include "iris_defines.h"
33 #include "compiler/shader_info.h"
34 
35 /**
36  * This callback is registered with intel_measure.  It will be called when
37  * snapshot data has been fully collected, so iris can release the associated
38  * resources.
39  */
40 static void
measure_batch_free(struct intel_measure_batch * base)41 measure_batch_free(struct intel_measure_batch *base)
42 {
43    struct iris_measure_batch *batch =
44       container_of(base, struct iris_measure_batch, base);
45    iris_destroy_batch_measure(batch);
46 }
47 
48 void
iris_init_screen_measure(struct iris_screen * screen)49 iris_init_screen_measure(struct iris_screen *screen)
50 {
51    struct intel_measure_device *measure_device = &screen->measure;
52 
53    memset(measure_device, 0, sizeof(*measure_device));
54    intel_measure_init(measure_device);
55    measure_device->release_batch = &measure_batch_free;
56    struct intel_measure_config *config = measure_device->config;
57    if (config == NULL)
58       return;
59 
60    /* the final member of intel_measure_ringbuffer is a zero-length array of
61     * intel_measure_buffered_result objects.  Allocate additional space for
62     * the buffered objects based on the run-time configurable buffer_size
63     */
64    const size_t rb_bytes = sizeof(struct intel_measure_ringbuffer) +
65       config->buffer_size * sizeof(struct intel_measure_buffered_result);
66    struct intel_measure_ringbuffer *rb = rzalloc_size(screen, rb_bytes);
67    measure_device->ringbuffer = rb;
68 }
69 
70 static struct intel_measure_config *
config_from_screen(struct iris_screen * screen)71 config_from_screen(struct iris_screen *screen)
72 {
73    return screen->measure.config;
74 }
75 
76 static struct intel_measure_config *
config_from_context(struct iris_context * ice)77 config_from_context(struct iris_context *ice)
78 {
79    return ((struct iris_screen *) ice->ctx.screen)->measure.config;
80 }
81 
82 void
iris_destroy_screen_measure(struct iris_screen * screen)83 iris_destroy_screen_measure(struct iris_screen *screen)
84 {
85    if (!config_from_screen(screen))
86       return;
87 
88    struct intel_measure_device *measure_device = &screen->measure;
89 
90    if (measure_device->config->file &&
91        measure_device->config->file != stderr)
92       fclose(screen->measure.config->file);
93 
94    ralloc_free(measure_device->ringbuffer);
95    measure_device->ringbuffer = NULL;
96 }
97 
98 
99 void
iris_init_batch_measure(struct iris_context * ice,struct iris_batch * batch)100 iris_init_batch_measure(struct iris_context *ice, struct iris_batch *batch)
101 {
102    const struct intel_measure_config *config = config_from_context(ice);
103    struct iris_screen *screen = batch->screen;
104    struct iris_bufmgr *bufmgr = screen->bufmgr;
105 
106    if (!config)
107       return;
108 
109    /* the final member of iris_measure_batch is a zero-length array of
110     * intel_measure_snapshot objects.  Create additional space for the
111     * snapshot objects based on the run-time configurable batch_size
112     */
113    const size_t batch_bytes = sizeof(struct iris_measure_batch) +
114       config->batch_size * sizeof(struct intel_measure_snapshot);
115    assert(batch->measure == NULL);
116    batch->measure = malloc(batch_bytes);
117    memset(batch->measure, 0, batch_bytes);
118    struct iris_measure_batch *measure = batch->measure;
119 
120    measure->bo = iris_bo_alloc(bufmgr, "measure",
121                                config->batch_size * sizeof(uint64_t), 8,
122                                IRIS_MEMZONE_OTHER, BO_ALLOC_ZEROED);
123    measure->base.timestamps = iris_bo_map(NULL, measure->bo, MAP_READ);
124    measure->base.renderpass =
125       (uintptr_t)util_hash_crc32(&ice->state.framebuffer,
126                                  sizeof(ice->state.framebuffer));
127 }
128 
129 void
iris_destroy_batch_measure(struct iris_measure_batch * batch)130 iris_destroy_batch_measure(struct iris_measure_batch *batch)
131 {
132    if (!batch)
133       return;
134    iris_bo_unmap(batch->bo);
135    iris_bo_unreference(batch->bo);
136    batch->bo = NULL;
137    free(batch);
138 }
139 
140 static uint32_t
fetch_hash(const struct iris_uncompiled_shader * uncompiled)141 fetch_hash(const struct iris_uncompiled_shader *uncompiled)
142 {
143    return (uncompiled) ? uncompiled->source_hash : 0;
144 }
145 
146 static void
measure_start_snapshot(struct iris_context * ice,struct iris_batch * batch,enum intel_measure_snapshot_type type,const char * event_name,uint32_t count)147 measure_start_snapshot(struct iris_context *ice,
148                        struct iris_batch *batch,
149                        enum intel_measure_snapshot_type type,
150                        const char *event_name,
151                        uint32_t count)
152 {
153    struct intel_measure_batch *measure_batch = &batch->measure->base;
154    const struct intel_measure_config *config = config_from_context(ice);
155    const struct iris_screen *screen = (void *) ice->ctx.screen;
156    const unsigned screen_frame = screen->measure.frame;
157 
158    /* if the command buffer is not associated with a frame, associate it with
159     * the most recent acquired frame
160     */
161    if (measure_batch->frame == 0)
162       measure_batch->frame = screen_frame;
163 
164    uintptr_t renderpass = measure_batch->renderpass;
165 
166    if (measure_batch->index == config->batch_size) {
167       /* Snapshot buffer is full.  The batch must be flushed before additional
168        * snapshots can be taken.
169        */
170       static bool warned = false;
171       if (unlikely(!warned)) {
172          fprintf(config->file,
173                  "WARNING: batch size exceeds INTEL_MEASURE limit: %d. "
174                  "Data has been dropped. "
175                  "Increase setting with INTEL_MEASURE=batch_size={count}\n",
176                  config->batch_size);
177          warned = true;
178       }
179       return;
180    }
181 
182    unsigned index = measure_batch->index++;
183    assert(index < config->batch_size);
184    if (event_name == NULL)
185       event_name = intel_measure_snapshot_string(type);
186 
187    if(config->cpu_measure) {
188       intel_measure_print_cpu_result(measure_batch->frame,
189                                      measure_batch->batch_count,
190                                      measure_batch->batch_size,
191                                      index/2,
192                                      measure_batch->event_count,
193                                      count,
194                                      event_name);
195       return;
196    }
197 
198    iris_emit_pipe_control_write(batch, "measurement snapshot",
199                                 PIPE_CONTROL_WRITE_TIMESTAMP |
200                                 PIPE_CONTROL_CS_STALL,
201                                 batch->measure->bo, index * sizeof(uint64_t), 0ull);
202 
203    struct intel_measure_snapshot *snapshot = &(measure_batch->snapshots[index]);
204    memset(snapshot, 0, sizeof(*snapshot));
205    snapshot->type = type;
206    snapshot->count = (unsigned) count;
207    snapshot->event_count = measure_batch->event_count;
208    snapshot->event_name = event_name;
209    snapshot->renderpass = renderpass;
210 
211    if (type == INTEL_SNAPSHOT_COMPUTE) {
212       snapshot->cs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_COMPUTE]);
213    } else if (type == INTEL_SNAPSHOT_DRAW) {
214       snapshot->vs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_VERTEX]);
215       snapshot->tcs = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_TESS_CTRL]);
216       snapshot->tes = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]);
217       snapshot->gs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_GEOMETRY]);
218       snapshot->fs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_FRAGMENT]);
219    }
220 }
221 
222 static void
measure_end_snapshot(struct iris_batch * batch,uint32_t event_count)223 measure_end_snapshot(struct iris_batch *batch,
224                      uint32_t event_count)
225 {
226    struct intel_measure_batch *measure_batch = &batch->measure->base;
227    const struct intel_measure_config *config = config_from_context(batch->ice);
228 
229    unsigned index = measure_batch->index++;
230    assert(index % 2 == 1);
231    if(config->cpu_measure)
232       return;
233 
234    iris_emit_pipe_control_write(batch, "measurement snapshot",
235                                 PIPE_CONTROL_WRITE_TIMESTAMP |
236                                 PIPE_CONTROL_CS_STALL,
237                                 batch->measure->bo,
238                                 index * sizeof(uint64_t), 0ull);
239 
240    struct intel_measure_snapshot *snapshot = &(measure_batch->snapshots[index]);
241    memset(snapshot, 0, sizeof(*snapshot));
242    snapshot->type = INTEL_SNAPSHOT_END;
243    snapshot->event_count = event_count;
244 }
245 
246 static bool
state_changed(const struct iris_context * ice,const struct iris_batch * batch,enum intel_measure_snapshot_type type)247 state_changed(const struct iris_context *ice,
248               const struct iris_batch *batch,
249               enum intel_measure_snapshot_type type)
250 {
251    uintptr_t vs=0, tcs=0, tes=0, gs=0, fs=0, cs=0;
252 
253    if (type == INTEL_SNAPSHOT_COMPUTE) {
254       cs = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_COMPUTE]);
255    } else if (type == INTEL_SNAPSHOT_DRAW) {
256       vs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_VERTEX]);
257       tcs = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_TESS_CTRL]);
258       tes = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]);
259       gs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_GEOMETRY]);
260       fs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_FRAGMENT]);
261    }
262    /* else blorp, all programs NULL */
263 
264    return intel_measure_state_changed(&batch->measure->base,
265                                       vs, tcs, tes, gs, fs, cs, 0, 0);
266 }
267 
268 static void
iris_measure_renderpass(struct iris_context * ice)269 iris_measure_renderpass(struct iris_context *ice)
270 {
271    const struct intel_measure_config *config = config_from_context(ice);
272    struct intel_measure_batch *batch =
273       &ice->batches[IRIS_BATCH_RENDER].measure->base;
274 
275    if (!config)
276       return;
277    uint32_t framebuffer_crc = util_hash_crc32(&ice->state.framebuffer,
278                                               sizeof(ice->state.framebuffer));
279    if (framebuffer_crc == batch->renderpass)
280       return;
281    bool filtering = config->flags & INTEL_MEASURE_RENDERPASS;
282    if (filtering && batch->index % 2 == 1) {
283       /* snapshot for previous renderpass was not ended */
284       measure_end_snapshot(&ice->batches[IRIS_BATCH_RENDER],
285                            batch->event_count);
286       batch->event_count = 0;
287    }
288 
289    batch->renderpass = framebuffer_crc;
290 }
291 
292 void
_iris_measure_snapshot(struct iris_context * ice,struct iris_batch * batch,enum intel_measure_snapshot_type type,const struct pipe_draw_info * draw,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * sc)293 _iris_measure_snapshot(struct iris_context *ice,
294                        struct iris_batch *batch,
295                        enum intel_measure_snapshot_type type,
296                        const struct pipe_draw_info *draw,
297                        const struct pipe_draw_indirect_info *indirect,
298                        const struct pipe_draw_start_count_bias *sc)
299 {
300 
301    const struct intel_measure_config *config = config_from_context(ice);
302    struct intel_measure_batch* measure_batch = &batch->measure->base;
303 
304    assert(config);
305    if (!config->enabled)
306       return;
307    if (measure_batch == NULL)
308       return;
309 
310    assert(type != INTEL_SNAPSHOT_END);
311    iris_measure_renderpass(ice);
312 
313    static unsigned batch_count = 0;
314    if (measure_batch->event_count == 0)
315       measure_batch->batch_count = p_atomic_inc_return(&batch_count);
316 
317    if (!state_changed(ice, batch, type)) {
318       /* filter out this event */
319       return;
320    }
321 
322    /* increment event count */
323    ++measure_batch->event_count;
324    if (measure_batch->event_count == 1 ||
325        measure_batch->event_count == config->event_interval + 1) {
326       /* the first event of an interval */
327       if (measure_batch->index % 2) {
328          /* end the previous event */
329          measure_end_snapshot(batch, measure_batch->event_count - 1);
330       }
331       measure_batch->event_count = 1;
332 
333       const char *event_name = NULL;
334       int count = 0;
335       if (sc)
336          count = sc->count;
337 
338       if (draw != NULL) {
339          const struct shader_info *fs_info =
340             iris_get_shader_info(ice, MESA_SHADER_FRAGMENT);
341          if (fs_info && fs_info->name && strncmp(fs_info->name, "st/", 2) == 0) {
342             event_name = fs_info->name;
343          } else if (indirect) {
344             event_name = "DrawIndirect";
345             if (indirect->count_from_stream_output) {
346                event_name = "DrawTransformFeedback";
347             }
348          }
349          else if (draw->index_size)
350             event_name = "DrawElements";
351          else
352             event_name = "DrawArrays";
353          count = count * (draw->instance_count ? draw->instance_count : 1);
354       }
355 
356       measure_start_snapshot(ice, batch, type, event_name, count);
357       return;
358    }
359 }
360 
361 void
iris_destroy_ctx_measure(struct iris_context * ice)362 iris_destroy_ctx_measure(struct iris_context *ice)
363 {
364    /* All outstanding snapshots must be collected before the context is
365     * destroyed.
366     */
367    struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;
368    intel_measure_gather(&screen->measure, screen->devinfo);
369 }
370 
371 void
iris_measure_batch_end(struct iris_context * ice,struct iris_batch * batch)372 iris_measure_batch_end(struct iris_context *ice, struct iris_batch *batch)
373 {
374    const struct intel_measure_config *config = config_from_context(ice);
375    struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;
376    struct iris_measure_batch *iris_measure_batch = batch->measure;
377    struct intel_measure_batch *measure_batch = &iris_measure_batch->base;
378    struct intel_measure_device *measure_device = &screen->measure;
379 
380    if (!config)
381       return;
382    if (!config->enabled)
383       return;
384 
385    assert(measure_batch);
386    assert(measure_device);
387 
388    if (measure_batch->index % 2) {
389       /* We hit the end of the batch, but never terminated our section of
390        * drawing with the same render target or shaders.  End it now.
391        */
392       measure_end_snapshot(batch, measure_batch->event_count);
393    }
394 
395    if (measure_batch->index == 0)
396       return;
397 
398    /* At this point, total_chained_batch_size is not yet updated because the
399     * batch_end measurement is within the batch and the batch is not quite
400     * ended yet (it'll be just after this function call). So combined the
401     * already summed total_chained_batch_size with whatever was written in the
402     * current batch BO.
403     */
404    measure_batch->batch_size = batch->total_chained_batch_size +
405                                iris_batch_bytes_used(batch);
406 
407    /* enqueue snapshot for gathering */
408    pthread_mutex_lock(&measure_device->mutex);
409    list_addtail(&iris_measure_batch->base.link, &measure_device->queued_snapshots);
410    batch->measure = NULL;
411    pthread_mutex_unlock(&measure_device->mutex);
412    /* init new measure_batch */
413    iris_init_batch_measure(ice, batch);
414 
415    static int interval = 0;
416    if (++interval > 10) {
417       intel_measure_gather(measure_device, screen->devinfo);
418       interval = 0;
419    }
420 }
421 
422 void
iris_measure_frame_end(struct iris_context * ice)423 iris_measure_frame_end(struct iris_context *ice)
424 {
425    struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;
426    struct intel_measure_device *measure_device = &screen->measure;
427    const struct intel_measure_config *config = measure_device->config;
428 
429    if (!config)
430       return;
431 
432    /* increment frame counter */
433    intel_measure_frame_transition(p_atomic_inc_return(&measure_device->frame));
434 
435    intel_measure_gather(measure_device, screen->devinfo);
436 }
437