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