• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    measure_device->type = INTEL_MEASURE_DEVICE_OGL;
55    intel_measure_init(measure_device);
56    measure_device->release_batch = &measure_batch_free;
57    struct intel_measure_config *config = measure_device->config;
58    if (config == NULL)
59       return;
60 
61    /* the final member of intel_measure_ringbuffer is a zero-length array of
62     * intel_measure_buffered_result objects.  Allocate additional space for
63     * the buffered objects based on the run-time configurable buffer_size
64     */
65    const size_t rb_bytes = sizeof(struct intel_measure_ringbuffer) +
66       config->buffer_size * sizeof(struct intel_measure_buffered_result);
67    struct intel_measure_ringbuffer *rb = rzalloc_size(screen, rb_bytes);
68    measure_device->ringbuffer = rb;
69 }
70 
71 static struct intel_measure_config *
config_from_screen(struct iris_screen * screen)72 config_from_screen(struct iris_screen *screen)
73 {
74    return screen->measure.config;
75 }
76 
77 static struct intel_measure_config *
config_from_context(struct iris_context * ice)78 config_from_context(struct iris_context *ice)
79 {
80    return ((struct iris_screen *) ice->ctx.screen)->measure.config;
81 }
82 
83 void
iris_destroy_screen_measure(struct iris_screen * screen)84 iris_destroy_screen_measure(struct iris_screen *screen)
85 {
86    if (!config_from_screen(screen))
87       return;
88 
89    struct intel_measure_device *measure_device = &screen->measure;
90 
91    if (measure_device->config->file &&
92        measure_device->config->file != stderr)
93       fclose(screen->measure.config->file);
94 
95    ralloc_free(measure_device->ringbuffer);
96    measure_device->ringbuffer = NULL;
97 }
98 
99 
100 void
iris_init_batch_measure(struct iris_context * ice,struct iris_batch * batch)101 iris_init_batch_measure(struct iris_context *ice, struct iris_batch *batch)
102 {
103    const struct intel_measure_config *config = config_from_context(ice);
104    struct iris_screen *screen = batch->screen;
105    struct iris_bufmgr *bufmgr = screen->bufmgr;
106 
107    if (!config)
108       return;
109 
110    /* the final member of iris_measure_batch is a zero-length array of
111     * intel_measure_snapshot objects.  Create additional space for the
112     * snapshot objects based on the run-time configurable batch_size
113     */
114    const size_t batch_bytes = sizeof(struct iris_measure_batch) +
115       config->batch_size * sizeof(struct intel_measure_snapshot);
116    assert(batch->measure == NULL);
117    batch->measure = malloc(batch_bytes);
118    memset(batch->measure, 0, batch_bytes);
119    struct iris_measure_batch *measure = batch->measure;
120 
121    measure->bo = iris_bo_alloc(bufmgr, "measure",
122                                config->batch_size * sizeof(uint64_t), 8,
123                                IRIS_MEMZONE_OTHER, BO_ALLOC_ZEROED);
124    measure->base.timestamps = iris_bo_map(NULL, measure->bo, MAP_READ);
125    measure->base.renderpass =
126       (uintptr_t)util_hash_crc32(&ice->state.framebuffer,
127                                  sizeof(ice->state.framebuffer));
128 }
129 
130 void
iris_destroy_batch_measure(struct iris_measure_batch * batch)131 iris_destroy_batch_measure(struct iris_measure_batch *batch)
132 {
133    if (!batch)
134       return;
135    iris_bo_unmap(batch->bo);
136    iris_bo_unreference(batch->bo);
137    batch->bo = NULL;
138    free(batch);
139 }
140 
141 static uint32_t
fetch_hash(const struct iris_uncompiled_shader * uncompiled)142 fetch_hash(const struct iris_uncompiled_shader *uncompiled)
143 {
144    return (uncompiled) ? uncompiled->source_hash : 0;
145 }
146 
147 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)148 measure_start_snapshot(struct iris_context *ice,
149                        struct iris_batch *batch,
150                        enum intel_measure_snapshot_type type,
151                        const char *event_name,
152                        uint32_t count)
153 {
154    struct intel_measure_batch *measure_batch = &batch->measure->base;
155    const struct intel_measure_config *config = config_from_context(ice);
156    const struct iris_screen *screen = (void *) ice->ctx.screen;
157    const unsigned screen_frame = screen->measure.frame;
158 
159    /* if the command buffer is not associated with a frame, associate it with
160     * the most recent acquired frame
161     */
162    if (measure_batch->frame == 0)
163       measure_batch->frame = screen_frame;
164 
165    uintptr_t renderpass = measure_batch->renderpass;
166 
167    if (measure_batch->index == config->batch_size) {
168       /* Snapshot buffer is full.  The batch must be flushed before additional
169        * snapshots can be taken.
170        */
171       static bool warned = false;
172       if (unlikely(!warned)) {
173          fprintf(config->file,
174                  "WARNING: batch size exceeds INTEL_MEASURE limit: %d. "
175                  "Data has been dropped. "
176                  "Increase setting with INTEL_MEASURE=batch_size={count}\n",
177                  config->batch_size);
178          warned = true;
179       }
180       return;
181    }
182 
183    unsigned index = measure_batch->index++;
184    assert(index < config->batch_size);
185    if (event_name == NULL)
186       event_name = intel_measure_snapshot_string(type);
187 
188    if(config->cpu_measure) {
189       intel_measure_print_cpu_result(measure_batch->frame,
190                                      measure_batch->batch_count,
191                                      measure_batch->batch_size,
192                                      index/2,
193                                      measure_batch->event_count,
194                                      count,
195                                      event_name);
196       return;
197    }
198 
199    iris_emit_pipe_control_write(batch, "measurement snapshot",
200                                 PIPE_CONTROL_WRITE_TIMESTAMP |
201                                 PIPE_CONTROL_CS_STALL,
202                                 batch->measure->bo, index * sizeof(uint64_t), 0ull);
203 
204    struct intel_measure_snapshot *snapshot = &(measure_batch->snapshots[index]);
205    memset(snapshot, 0, sizeof(*snapshot));
206    snapshot->type = type;
207    snapshot->count = (unsigned) count;
208    snapshot->event_count = measure_batch->event_count;
209    snapshot->event_name = event_name;
210    snapshot->renderpass = renderpass;
211 
212    if (type == INTEL_SNAPSHOT_COMPUTE) {
213       snapshot->cs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_COMPUTE]);
214    } else if (type == INTEL_SNAPSHOT_DRAW) {
215       snapshot->vs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_VERTEX]);
216       snapshot->tcs = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_TESS_CTRL]);
217       snapshot->tes = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]);
218       snapshot->gs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_GEOMETRY]);
219       snapshot->fs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_FRAGMENT]);
220    }
221 }
222 
223 static void
measure_end_snapshot(struct iris_batch * batch,uint32_t event_count)224 measure_end_snapshot(struct iris_batch *batch,
225                      uint32_t event_count)
226 {
227    struct intel_measure_batch *measure_batch = &batch->measure->base;
228    const struct intel_measure_config *config = config_from_context(batch->ice);
229 
230    unsigned index = measure_batch->index++;
231    assert(index % 2 == 1);
232    if(config->cpu_measure)
233       return;
234 
235    iris_emit_pipe_control_write(batch, "measurement snapshot",
236                                 PIPE_CONTROL_WRITE_TIMESTAMP |
237                                 PIPE_CONTROL_CS_STALL,
238                                 batch->measure->bo,
239                                 index * sizeof(uint64_t), 0ull);
240 
241    struct intel_measure_snapshot *snapshot = &(measure_batch->snapshots[index]);
242    memset(snapshot, 0, sizeof(*snapshot));
243    snapshot->type = INTEL_SNAPSHOT_END;
244    snapshot->event_count = event_count;
245 }
246 
247 static bool
state_changed(const struct iris_context * ice,const struct iris_batch * batch,enum intel_measure_snapshot_type type)248 state_changed(const struct iris_context *ice,
249               const struct iris_batch *batch,
250               enum intel_measure_snapshot_type type)
251 {
252    uintptr_t vs=0, tcs=0, tes=0, gs=0, fs=0, cs=0;
253 
254    if (type == INTEL_SNAPSHOT_COMPUTE) {
255       cs = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_COMPUTE]);
256    } else if (type == INTEL_SNAPSHOT_DRAW) {
257       vs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_VERTEX]);
258       tcs = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_TESS_CTRL]);
259       tes = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]);
260       gs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_GEOMETRY]);
261       fs  = fetch_hash(ice->shaders.uncompiled[MESA_SHADER_FRAGMENT]);
262    }
263    /* else blorp, all programs NULL */
264 
265    return intel_measure_state_changed(&batch->measure->base,
266                                       vs, tcs, tes, gs, fs, cs, 0, 0);
267 }
268 
269 static void
iris_measure_renderpass(struct iris_context * ice)270 iris_measure_renderpass(struct iris_context *ice)
271 {
272    const struct intel_measure_config *config = config_from_context(ice);
273    struct intel_measure_batch *batch =
274       &ice->batches[IRIS_BATCH_RENDER].measure->base;
275 
276    if (!config)
277       return;
278    uint32_t framebuffer_crc = util_hash_crc32(&ice->state.framebuffer,
279                                               sizeof(ice->state.framebuffer));
280    if (framebuffer_crc == batch->renderpass)
281       return;
282    bool filtering = config->flags & INTEL_MEASURE_RENDERPASS;
283    if (filtering && batch->index % 2 == 1) {
284       /* snapshot for previous renderpass was not ended */
285       measure_end_snapshot(&ice->batches[IRIS_BATCH_RENDER],
286                            batch->event_count);
287       batch->event_count = 0;
288    }
289 
290    batch->renderpass = framebuffer_crc;
291 }
292 
293 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)294 _iris_measure_snapshot(struct iris_context *ice,
295                        struct iris_batch *batch,
296                        enum intel_measure_snapshot_type type,
297                        const struct pipe_draw_info *draw,
298                        const struct pipe_draw_indirect_info *indirect,
299                        const struct pipe_draw_start_count_bias *sc)
300 {
301 
302    const struct intel_measure_config *config = config_from_context(ice);
303    struct intel_measure_batch* measure_batch = &batch->measure->base;
304 
305    assert(config);
306    if (!config->enabled)
307       return;
308    if (measure_batch == NULL)
309       return;
310 
311    assert(type != INTEL_SNAPSHOT_END);
312    iris_measure_renderpass(ice);
313 
314    static unsigned batch_count = 0;
315    if (measure_batch->event_count == 0)
316       measure_batch->batch_count = p_atomic_inc_return(&batch_count);
317 
318    if (!state_changed(ice, batch, type)) {
319       /* filter out this event */
320       return;
321    }
322 
323    /* increment event count */
324    ++measure_batch->event_count;
325    if (measure_batch->event_count == 1 ||
326        measure_batch->event_count == config->event_interval + 1) {
327       /* the first event of an interval */
328       if (measure_batch->index % 2) {
329          /* end the previous event */
330          measure_end_snapshot(batch, measure_batch->event_count - 1);
331       }
332       measure_batch->event_count = 1;
333 
334       const char *event_name = NULL;
335       int count = 0;
336       if (sc)
337          count = sc->count;
338 
339       if (draw != NULL) {
340          const struct shader_info *fs_info =
341             iris_get_shader_info(ice, MESA_SHADER_FRAGMENT);
342          if (fs_info && fs_info->name && strncmp(fs_info->name, "st/", 2) == 0) {
343             event_name = fs_info->name;
344          } else if (indirect) {
345             event_name = "DrawIndirect";
346             if (indirect->count_from_stream_output) {
347                event_name = "DrawTransformFeedback";
348             }
349          }
350          else if (draw->index_size)
351             event_name = "DrawElements";
352          else
353             event_name = "DrawArrays";
354          count = count * (draw->instance_count ? draw->instance_count : 1);
355       }
356 
357       measure_start_snapshot(ice, batch, type, event_name, count);
358       return;
359    }
360 }
361 
362 void
iris_destroy_ctx_measure(struct iris_context * ice)363 iris_destroy_ctx_measure(struct iris_context *ice)
364 {
365    /* All outstanding snapshots must be collected before the context is
366     * destroyed.
367     */
368    struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;
369    intel_measure_gather(&screen->measure, screen->devinfo);
370 }
371 
372 void
iris_measure_batch_end(struct iris_context * ice,struct iris_batch * batch)373 iris_measure_batch_end(struct iris_context *ice, struct iris_batch *batch)
374 {
375    const struct intel_measure_config *config = config_from_context(ice);
376    struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;
377    struct iris_measure_batch *iris_measure_batch = batch->measure;
378    struct intel_measure_batch *measure_batch = &iris_measure_batch->base;
379    struct intel_measure_device *measure_device = &screen->measure;
380 
381    if (!config)
382       return;
383    if (!config->enabled)
384       return;
385 
386    assert(measure_batch);
387    assert(measure_device);
388 
389    if (measure_batch->index % 2) {
390       /* We hit the end of the batch, but never terminated our section of
391        * drawing with the same render target or shaders.  End it now.
392        */
393       measure_end_snapshot(batch, measure_batch->event_count);
394    }
395 
396    if (measure_batch->index == 0)
397       return;
398 
399    /* At this point, total_chained_batch_size is not yet updated because the
400     * batch_end measurement is within the batch and the batch is not quite
401     * ended yet (it'll be just after this function call). So combined the
402     * already summed total_chained_batch_size with whatever was written in the
403     * current batch BO.
404     */
405    measure_batch->batch_size = batch->total_chained_batch_size +
406                                iris_batch_bytes_used(batch);
407 
408    /* enqueue snapshot for gathering */
409    pthread_mutex_lock(&measure_device->mutex);
410    list_addtail(&iris_measure_batch->base.link, &measure_device->queued_snapshots);
411    batch->measure = NULL;
412    pthread_mutex_unlock(&measure_device->mutex);
413    /* init new measure_batch */
414    iris_init_batch_measure(ice, batch);
415 
416    static int interval = 0;
417    if (++interval > 10) {
418       intel_measure_gather(measure_device, screen->devinfo);
419       interval = 0;
420    }
421 }
422 
423 void
iris_measure_frame_end(struct iris_context * ice)424 iris_measure_frame_end(struct iris_context *ice)
425 {
426    struct iris_screen *screen = (struct iris_screen *) ice->ctx.screen;
427    struct intel_measure_device *measure_device = &screen->measure;
428    const struct intel_measure_config *config = measure_device->config;
429 
430    if (!config)
431       return;
432 
433    /* increment frame counter */
434    intel_measure_frame_transition(p_atomic_inc_return(&measure_device->frame));
435 
436    intel_measure_gather(measure_device, screen->devinfo);
437 }
438