xref: /aosp_15_r20/external/mesa3d/src/intel/common/intel_measure.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2020 Intel Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
12*61046927SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20*61046927SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
21*61046927SAndroid Build Coastguard Worker  */
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker /**
24*61046927SAndroid Build Coastguard Worker  * @file intel_measure.c
25*61046927SAndroid Build Coastguard Worker  */
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #include "intel_measure.h"
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker #include <errno.h>
30*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
31*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
32*61046927SAndroid Build Coastguard Worker #include <string.h>
33*61046927SAndroid Build Coastguard Worker #include <sys/stat.h>
34*61046927SAndroid Build Coastguard Worker #include <sys/types.h>
35*61046927SAndroid Build Coastguard Worker #include <unistd.h>
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker #define __STDC_FORMAT_MACROS 1
38*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker #include "dev/intel_device_info.h"
41*61046927SAndroid Build Coastguard Worker #include "util/os_time.h"
42*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
43*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker static const struct debug_control debug_control[] = {
47*61046927SAndroid Build Coastguard Worker    { "draw",            INTEL_MEASURE_DRAW       },
48*61046927SAndroid Build Coastguard Worker    { "rt",              INTEL_MEASURE_RENDERPASS },
49*61046927SAndroid Build Coastguard Worker    { "shader",          INTEL_MEASURE_SHADER     },
50*61046927SAndroid Build Coastguard Worker    { "batch",           INTEL_MEASURE_BATCH      },
51*61046927SAndroid Build Coastguard Worker    { "frame",           INTEL_MEASURE_FRAME      },
52*61046927SAndroid Build Coastguard Worker    { NULL, 0 }
53*61046927SAndroid Build Coastguard Worker };
54*61046927SAndroid Build Coastguard Worker static struct intel_measure_config config;
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker void
intel_measure_init(struct intel_measure_device * device)57*61046927SAndroid Build Coastguard Worker intel_measure_init(struct intel_measure_device *device)
58*61046927SAndroid Build Coastguard Worker {
59*61046927SAndroid Build Coastguard Worker    static bool once = false;
60*61046927SAndroid Build Coastguard Worker    const char *env = getenv("INTEL_MEASURE");
61*61046927SAndroid Build Coastguard Worker    if (unlikely(!once)) {
62*61046927SAndroid Build Coastguard Worker       once = true;
63*61046927SAndroid Build Coastguard Worker       memset(&config, 0, sizeof(struct intel_measure_config));
64*61046927SAndroid Build Coastguard Worker       if (!env)
65*61046927SAndroid Build Coastguard Worker          return;
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker       char env_copy[1024];
68*61046927SAndroid Build Coastguard Worker       strncpy(env_copy, env, 1024);
69*61046927SAndroid Build Coastguard Worker       env_copy[1023] = '\0';
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker       config.file = stderr;
72*61046927SAndroid Build Coastguard Worker       config.flags = parse_debug_string(env_copy, debug_control);
73*61046927SAndroid Build Coastguard Worker       if (!config.flags)
74*61046927SAndroid Build Coastguard Worker          config.flags = INTEL_MEASURE_DRAW;
75*61046927SAndroid Build Coastguard Worker       config.enabled = true;
76*61046927SAndroid Build Coastguard Worker       config.event_interval = 1;
77*61046927SAndroid Build Coastguard Worker       config.control_fh = -1;
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker       /* Overflows of the following defaults will drop data and generate a
80*61046927SAndroid Build Coastguard Worker        * warning on the output filehandle.
81*61046927SAndroid Build Coastguard Worker        */
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker       /* default batch_size allows for 32k renders in a single batch */
84*61046927SAndroid Build Coastguard Worker       const int MINIMUM_BATCH_SIZE = 1024;
85*61046927SAndroid Build Coastguard Worker       const int DEFAULT_BATCH_SIZE = 64 * 1024;
86*61046927SAndroid Build Coastguard Worker       config.batch_size = DEFAULT_BATCH_SIZE;
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker       /* Default buffer_size allows for 64k batches per line of output in the
89*61046927SAndroid Build Coastguard Worker        * csv.  Overflow may occur for offscreen workloads or large 'interval'
90*61046927SAndroid Build Coastguard Worker        * settings.
91*61046927SAndroid Build Coastguard Worker        */
92*61046927SAndroid Build Coastguard Worker       const int MINIMUM_BUFFER_SIZE = 1024;
93*61046927SAndroid Build Coastguard Worker       const int DEFAULT_BUFFER_SIZE = 64 * 1024;
94*61046927SAndroid Build Coastguard Worker       config.buffer_size = DEFAULT_BUFFER_SIZE;
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker       const char *filename = strstr(env_copy, "file=");
97*61046927SAndroid Build Coastguard Worker       const char *start_frame_s = strstr(env_copy, "start=");
98*61046927SAndroid Build Coastguard Worker       const char *count_frame_s = strstr(env_copy, "count=");
99*61046927SAndroid Build Coastguard Worker       const char *control_path = strstr(env_copy, "control=");
100*61046927SAndroid Build Coastguard Worker       const char *interval_s = strstr(env_copy, "interval=");
101*61046927SAndroid Build Coastguard Worker       const char *batch_size_s = strstr(env_copy, "batch_size=");
102*61046927SAndroid Build Coastguard Worker       const char *buffer_size_s = strstr(env_copy, "buffer_size=");
103*61046927SAndroid Build Coastguard Worker       const char *cpu_s = strstr(env_copy, "cpu");
104*61046927SAndroid Build Coastguard Worker       while (true) {
105*61046927SAndroid Build Coastguard Worker          char *sep = strrchr(env_copy, ',');
106*61046927SAndroid Build Coastguard Worker          if (sep == NULL)
107*61046927SAndroid Build Coastguard Worker             break;
108*61046927SAndroid Build Coastguard Worker          *sep = '\0';
109*61046927SAndroid Build Coastguard Worker       }
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker       if (filename && __normal_user()) {
112*61046927SAndroid Build Coastguard Worker          filename += 5;
113*61046927SAndroid Build Coastguard Worker          config.file = fopen(filename, "w");
114*61046927SAndroid Build Coastguard Worker          if (!config.file) {
115*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE failed to open output file %s: %s\n",
116*61046927SAndroid Build Coastguard Worker                     filename, strerror (errno));
117*61046927SAndroid Build Coastguard Worker             abort();
118*61046927SAndroid Build Coastguard Worker          }
119*61046927SAndroid Build Coastguard Worker       }
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker       if (start_frame_s) {
122*61046927SAndroid Build Coastguard Worker          start_frame_s += 6;
123*61046927SAndroid Build Coastguard Worker          const int start_frame = atoi(start_frame_s);
124*61046927SAndroid Build Coastguard Worker          if (start_frame < 0) {
125*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE start frame may "
126*61046927SAndroid Build Coastguard Worker                     "not be negative: %d\n", start_frame);
127*61046927SAndroid Build Coastguard Worker             abort();
128*61046927SAndroid Build Coastguard Worker          }
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker          config.start_frame = start_frame;
131*61046927SAndroid Build Coastguard Worker          config.enabled = false;
132*61046927SAndroid Build Coastguard Worker       }
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker       if (count_frame_s) {
135*61046927SAndroid Build Coastguard Worker          count_frame_s += 6;
136*61046927SAndroid Build Coastguard Worker          const int count_frame = atoi(count_frame_s);
137*61046927SAndroid Build Coastguard Worker          if (count_frame <= 0) {
138*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE count frame must be positive: %d\n",
139*61046927SAndroid Build Coastguard Worker                     count_frame);
140*61046927SAndroid Build Coastguard Worker             abort();
141*61046927SAndroid Build Coastguard Worker          }
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker          config.end_frame = config.start_frame + count_frame;
144*61046927SAndroid Build Coastguard Worker       }
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker       if (control_path) {
147*61046927SAndroid Build Coastguard Worker          control_path += 8;
148*61046927SAndroid Build Coastguard Worker          if (mkfifoat(AT_FDCWD, control_path, O_CREAT | S_IRUSR | S_IWUSR)) {
149*61046927SAndroid Build Coastguard Worker             if (errno != EEXIST) {
150*61046927SAndroid Build Coastguard Worker                fprintf(stderr, "INTEL_MEASURE failed to create control "
151*61046927SAndroid Build Coastguard Worker                        "fifo %s: %s\n", control_path, strerror (errno));
152*61046927SAndroid Build Coastguard Worker                abort();
153*61046927SAndroid Build Coastguard Worker             }
154*61046927SAndroid Build Coastguard Worker          }
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker          config.control_fh = openat(AT_FDCWD, control_path,
157*61046927SAndroid Build Coastguard Worker                                     O_RDONLY | O_NONBLOCK);
158*61046927SAndroid Build Coastguard Worker          if (config.control_fh == -1) {
159*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE failed to open control fifo "
160*61046927SAndroid Build Coastguard Worker                     "%s: %s\n", control_path, strerror (errno));
161*61046927SAndroid Build Coastguard Worker             abort();
162*61046927SAndroid Build Coastguard Worker          }
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker          /* when using a control fifo, do not start until the user triggers
165*61046927SAndroid Build Coastguard Worker           * capture
166*61046927SAndroid Build Coastguard Worker           */
167*61046927SAndroid Build Coastguard Worker          config.enabled = false;
168*61046927SAndroid Build Coastguard Worker       }
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker       if (interval_s) {
171*61046927SAndroid Build Coastguard Worker          interval_s += 9;
172*61046927SAndroid Build Coastguard Worker          const int event_interval = atoi(interval_s);
173*61046927SAndroid Build Coastguard Worker          if (event_interval < 1) {
174*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE event_interval must be positive: "
175*61046927SAndroid Build Coastguard Worker                     "%d\n", event_interval);
176*61046927SAndroid Build Coastguard Worker             abort();
177*61046927SAndroid Build Coastguard Worker          }
178*61046927SAndroid Build Coastguard Worker          config.event_interval = event_interval;
179*61046927SAndroid Build Coastguard Worker       }
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker       if (batch_size_s) {
182*61046927SAndroid Build Coastguard Worker          batch_size_s += 11;
183*61046927SAndroid Build Coastguard Worker          const int batch_size = atoi(batch_size_s);
184*61046927SAndroid Build Coastguard Worker          if (batch_size < MINIMUM_BATCH_SIZE ) {
185*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE minimum batch_size is 1k: "
186*61046927SAndroid Build Coastguard Worker                     "%d\n", batch_size);
187*61046927SAndroid Build Coastguard Worker             abort();
188*61046927SAndroid Build Coastguard Worker          }
189*61046927SAndroid Build Coastguard Worker          if (batch_size > MINIMUM_BATCH_SIZE * 4 * 1024) {
190*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE batch_size limited to 4M: "
191*61046927SAndroid Build Coastguard Worker                     "%d\n", batch_size);
192*61046927SAndroid Build Coastguard Worker             abort();
193*61046927SAndroid Build Coastguard Worker          }
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker          config.batch_size = batch_size;
196*61046927SAndroid Build Coastguard Worker       }
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker       if (buffer_size_s) {
199*61046927SAndroid Build Coastguard Worker          buffer_size_s += 12;
200*61046927SAndroid Build Coastguard Worker          const int buffer_size = atoi(buffer_size_s);
201*61046927SAndroid Build Coastguard Worker          if (buffer_size < MINIMUM_BUFFER_SIZE) {
202*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE minimum buffer_size is 1k: "
203*61046927SAndroid Build Coastguard Worker                     "%d\n", DEFAULT_BUFFER_SIZE);
204*61046927SAndroid Build Coastguard Worker          }
205*61046927SAndroid Build Coastguard Worker          if (buffer_size > MINIMUM_BUFFER_SIZE * 1024) {
206*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE buffer_size limited to 1M: "
207*61046927SAndroid Build Coastguard Worker                     "%d\n", buffer_size);
208*61046927SAndroid Build Coastguard Worker          }
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker          config.buffer_size = buffer_size;
211*61046927SAndroid Build Coastguard Worker       }
212*61046927SAndroid Build Coastguard Worker 
213*61046927SAndroid Build Coastguard Worker       if (cpu_s) {
214*61046927SAndroid Build Coastguard Worker          config.cpu_measure = true;
215*61046927SAndroid Build Coastguard Worker       }
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker       if (!config.cpu_measure)
218*61046927SAndroid Build Coastguard Worker          fputs("draw_start,draw_end,frame,batch,batch_size,renderpass,"
219*61046927SAndroid Build Coastguard Worker                "event_index,event_count,type,count,vs,tcs,tes,"
220*61046927SAndroid Build Coastguard Worker                "gs,fs,cs,ms,ts,idle_us,time_us\n",
221*61046927SAndroid Build Coastguard Worker                config.file);
222*61046927SAndroid Build Coastguard Worker       else
223*61046927SAndroid Build Coastguard Worker          fputs("draw_start,frame,batch,batch_size,event_index,event_count,"
224*61046927SAndroid Build Coastguard Worker                "type,count\n",
225*61046927SAndroid Build Coastguard Worker                config.file);
226*61046927SAndroid Build Coastguard Worker    }
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    device->config = NULL;
229*61046927SAndroid Build Coastguard Worker    device->frame = 0;
230*61046927SAndroid Build Coastguard Worker    device->render_pass_count = 0;
231*61046927SAndroid Build Coastguard Worker    device->release_batch = NULL;
232*61046927SAndroid Build Coastguard Worker    pthread_mutex_init(&device->mutex, NULL);
233*61046927SAndroid Build Coastguard Worker    list_inithead(&device->queued_snapshots);
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker    if (env)
236*61046927SAndroid Build Coastguard Worker       device->config = &config;
237*61046927SAndroid Build Coastguard Worker }
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker const char *
intel_measure_snapshot_string(enum intel_measure_snapshot_type type)240*61046927SAndroid Build Coastguard Worker intel_measure_snapshot_string(enum intel_measure_snapshot_type type)
241*61046927SAndroid Build Coastguard Worker {
242*61046927SAndroid Build Coastguard Worker    const char *names[] = {
243*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_UNDEFINED]           = "undefined",
244*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_BLIT]                = "blit",
245*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_CCS_AMBIGUATE]       = "ccs ambiguate",
246*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_CCS_COLOR_CLEAR]     = "ccs color clear",
247*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_CCS_PARTIAL_RESOLVE] = "ccs partial resolve",
248*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_CCS_RESOLVE]         = "ccs resolve",
249*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_COMPUTE]             = "compute",
250*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_COPY]                = "copy",
251*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_DRAW]                = "draw",
252*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_HIZ_AMBIGUATE]       = "hiz ambiguate",
253*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_HIZ_CLEAR]           = "hiz clear",
254*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_HIZ_RESOLVE]         = "hiz resolve",
255*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_MCS_AMBIGUATE]       = "mcs ambiguate",
256*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_MCS_COLOR_CLEAR]     = "mcs color clear",
257*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_MCS_PARTIAL_RESOLVE] = "mcs partial resolve",
258*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_SLOW_COLOR_CLEAR]    = "slow color clear",
259*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_SLOW_DEPTH_CLEAR]    = "slow depth clear",
260*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_SECONDARY_BATCH]     = "secondary command buffer",
261*61046927SAndroid Build Coastguard Worker       [INTEL_SNAPSHOT_END]                 = "end",
262*61046927SAndroid Build Coastguard Worker    };
263*61046927SAndroid Build Coastguard Worker    assert(type < ARRAY_SIZE(names));
264*61046927SAndroid Build Coastguard Worker    assert(names[type] != NULL);
265*61046927SAndroid Build Coastguard Worker    assert(type != INTEL_SNAPSHOT_UNDEFINED);
266*61046927SAndroid Build Coastguard Worker    return names[type];
267*61046927SAndroid Build Coastguard Worker }
268*61046927SAndroid Build Coastguard Worker 
269*61046927SAndroid Build Coastguard Worker /**
270*61046927SAndroid Build Coastguard Worker  * Indicate to the caller whether a new snapshot should be started.
271*61046927SAndroid Build Coastguard Worker  *
272*61046927SAndroid Build Coastguard Worker  * Callers provide rendering state to this method to determine whether the
273*61046927SAndroid Build Coastguard Worker  * current start event should be skipped. Depending on the configuration
274*61046927SAndroid Build Coastguard Worker  * flags, a new snapshot may start:
275*61046927SAndroid Build Coastguard Worker  *  - at every event
276*61046927SAndroid Build Coastguard Worker  *  - when the program changes
277*61046927SAndroid Build Coastguard Worker  *  - after a batch is submitted
278*61046927SAndroid Build Coastguard Worker  *  - at frame boundaries
279*61046927SAndroid Build Coastguard Worker  *
280*61046927SAndroid Build Coastguard Worker  * Returns true if a snapshot should be started.
281*61046927SAndroid Build Coastguard Worker  */
282*61046927SAndroid Build Coastguard Worker bool
intel_measure_state_changed(const struct intel_measure_batch * batch,uint32_t vs,uint32_t tcs,uint32_t tes,uint32_t gs,uint32_t fs,uint32_t cs,uint32_t ms,uint32_t ts)283*61046927SAndroid Build Coastguard Worker intel_measure_state_changed(const struct intel_measure_batch *batch,
284*61046927SAndroid Build Coastguard Worker                             uint32_t vs, uint32_t tcs, uint32_t tes,
285*61046927SAndroid Build Coastguard Worker                             uint32_t gs, uint32_t fs, uint32_t cs,
286*61046927SAndroid Build Coastguard Worker                             uint32_t ms, uint32_t ts)
287*61046927SAndroid Build Coastguard Worker {
288*61046927SAndroid Build Coastguard Worker    if (batch->index == 0) {
289*61046927SAndroid Build Coastguard Worker       /* always record the first event */
290*61046927SAndroid Build Coastguard Worker       return true;
291*61046927SAndroid Build Coastguard Worker    }
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker    const struct intel_measure_snapshot *last_snap =
294*61046927SAndroid Build Coastguard Worker       &batch->snapshots[batch->index - 1];
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker    if (config.flags & INTEL_MEASURE_DRAW)
297*61046927SAndroid Build Coastguard Worker       return true;
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker    if (batch->index % 2 == 0) {
300*61046927SAndroid Build Coastguard Worker       /* no snapshot is running, but we have a start event */
301*61046927SAndroid Build Coastguard Worker       return true;
302*61046927SAndroid Build Coastguard Worker    }
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    if (config.flags & (INTEL_MEASURE_FRAME | INTEL_MEASURE_BATCH)) {
305*61046927SAndroid Build Coastguard Worker       /* only start collection when index == 0, at the beginning of a batch */
306*61046927SAndroid Build Coastguard Worker       return false;
307*61046927SAndroid Build Coastguard Worker    }
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker    if (config.flags & INTEL_MEASURE_RENDERPASS) {
310*61046927SAndroid Build Coastguard Worker       bool new_renderpass = !cs && last_snap->renderpass != batch->renderpass;
311*61046927SAndroid Build Coastguard Worker       bool new_compute_block = cs && last_snap->type != INTEL_SNAPSHOT_COMPUTE;
312*61046927SAndroid Build Coastguard Worker       return new_renderpass || new_compute_block;
313*61046927SAndroid Build Coastguard Worker    }
314*61046927SAndroid Build Coastguard Worker 
315*61046927SAndroid Build Coastguard Worker    /* remaining comparisons check the state of the render pipeline for
316*61046927SAndroid Build Coastguard Worker     * INTEL_MEASURE_PROGRAM
317*61046927SAndroid Build Coastguard Worker     */
318*61046927SAndroid Build Coastguard Worker    assert(config.flags & INTEL_MEASURE_SHADER);
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker    if (!vs && !tcs && !tes && !gs && !fs && !cs && !ms && !ts) {
321*61046927SAndroid Build Coastguard Worker       /* blorp always changes program */
322*61046927SAndroid Build Coastguard Worker       return true;
323*61046927SAndroid Build Coastguard Worker    }
324*61046927SAndroid Build Coastguard Worker 
325*61046927SAndroid Build Coastguard Worker    return (last_snap->vs  != vs ||
326*61046927SAndroid Build Coastguard Worker            last_snap->tcs != tcs ||
327*61046927SAndroid Build Coastguard Worker            last_snap->tes != tes ||
328*61046927SAndroid Build Coastguard Worker            last_snap->gs  != gs ||
329*61046927SAndroid Build Coastguard Worker            last_snap->fs  != fs ||
330*61046927SAndroid Build Coastguard Worker            last_snap->cs  != cs ||
331*61046927SAndroid Build Coastguard Worker            last_snap->ms  != ms ||
332*61046927SAndroid Build Coastguard Worker            last_snap->ts  != ts);
333*61046927SAndroid Build Coastguard Worker }
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker /**
336*61046927SAndroid Build Coastguard Worker  * Notify intel_measure that a frame is about to begin.
337*61046927SAndroid Build Coastguard Worker  *
338*61046927SAndroid Build Coastguard Worker  * Configuration values and the control fifo may commence measurement at frame
339*61046927SAndroid Build Coastguard Worker  * boundaries.
340*61046927SAndroid Build Coastguard Worker  */
341*61046927SAndroid Build Coastguard Worker void
intel_measure_frame_transition(unsigned frame)342*61046927SAndroid Build Coastguard Worker intel_measure_frame_transition(unsigned frame)
343*61046927SAndroid Build Coastguard Worker {
344*61046927SAndroid Build Coastguard Worker    if (frame == config.start_frame)
345*61046927SAndroid Build Coastguard Worker       config.enabled = true;
346*61046927SAndroid Build Coastguard Worker    else if (frame == config.end_frame)
347*61046927SAndroid Build Coastguard Worker       config.enabled = false;
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker    /* user commands to the control fifo will override any start/count
350*61046927SAndroid Build Coastguard Worker     * environment settings
351*61046927SAndroid Build Coastguard Worker     */
352*61046927SAndroid Build Coastguard Worker    if (config.control_fh != -1) {
353*61046927SAndroid Build Coastguard Worker       while (true) {
354*61046927SAndroid Build Coastguard Worker          const unsigned BUF_SIZE = 128;
355*61046927SAndroid Build Coastguard Worker          char buf[BUF_SIZE];
356*61046927SAndroid Build Coastguard Worker          ssize_t bytes = read(config.control_fh, buf, BUF_SIZE - 1);
357*61046927SAndroid Build Coastguard Worker          if (bytes == 0)
358*61046927SAndroid Build Coastguard Worker             break;
359*61046927SAndroid Build Coastguard Worker          if (bytes == -1) {
360*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "INTEL_MEASURE failed to read control fifo: %s\n",
361*61046927SAndroid Build Coastguard Worker                     strerror(errno));
362*61046927SAndroid Build Coastguard Worker             abort();
363*61046927SAndroid Build Coastguard Worker          }
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker          buf[bytes] = '\0';
366*61046927SAndroid Build Coastguard Worker          char *nptr = buf, *endptr = buf;
367*61046927SAndroid Build Coastguard Worker          while (*nptr != '\0' && *endptr != '\0') {
368*61046927SAndroid Build Coastguard Worker             long fcount = strtol(nptr, &endptr, 10);
369*61046927SAndroid Build Coastguard Worker             if (nptr == endptr) {
370*61046927SAndroid Build Coastguard Worker                config.enabled = false;
371*61046927SAndroid Build Coastguard Worker                fprintf(stderr, "INTEL_MEASURE invalid frame count on "
372*61046927SAndroid Build Coastguard Worker                        "control fifo.\n");
373*61046927SAndroid Build Coastguard Worker                lseek(config.control_fh, 0, SEEK_END);
374*61046927SAndroid Build Coastguard Worker                break;
375*61046927SAndroid Build Coastguard Worker             } else if (fcount == 0) {
376*61046927SAndroid Build Coastguard Worker                config.enabled = false;
377*61046927SAndroid Build Coastguard Worker             } else {
378*61046927SAndroid Build Coastguard Worker                config.enabled = true;
379*61046927SAndroid Build Coastguard Worker                config.end_frame = frame + fcount;
380*61046927SAndroid Build Coastguard Worker             }
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker             nptr = endptr + 1;
383*61046927SAndroid Build Coastguard Worker          }
384*61046927SAndroid Build Coastguard Worker       }
385*61046927SAndroid Build Coastguard Worker    }
386*61046927SAndroid Build Coastguard Worker }
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker #define TIMESTAMP_BITS 36
389*61046927SAndroid Build Coastguard Worker static uint64_t
raw_timestamp_delta(uint64_t time0,uint64_t time1)390*61046927SAndroid Build Coastguard Worker raw_timestamp_delta(uint64_t time0, uint64_t time1)
391*61046927SAndroid Build Coastguard Worker {
392*61046927SAndroid Build Coastguard Worker    if (time0 > time1) {
393*61046927SAndroid Build Coastguard Worker       return (1ULL << TIMESTAMP_BITS) + time1 - time0;
394*61046927SAndroid Build Coastguard Worker    } else {
395*61046927SAndroid Build Coastguard Worker       return time1 - time0;
396*61046927SAndroid Build Coastguard Worker    }
397*61046927SAndroid Build Coastguard Worker }
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker /**
400*61046927SAndroid Build Coastguard Worker  * Verify that rendering has completed for the batch
401*61046927SAndroid Build Coastguard Worker  *
402*61046927SAndroid Build Coastguard Worker  * Rendering is complete when the last timestamp has been written.
403*61046927SAndroid Build Coastguard Worker */
404*61046927SAndroid Build Coastguard Worker bool
intel_measure_ready(struct intel_measure_batch * batch)405*61046927SAndroid Build Coastguard Worker intel_measure_ready(struct intel_measure_batch *batch)
406*61046927SAndroid Build Coastguard Worker {
407*61046927SAndroid Build Coastguard Worker    assert(batch->timestamps);
408*61046927SAndroid Build Coastguard Worker    assert(batch->index > 1);
409*61046927SAndroid Build Coastguard Worker    return (batch->timestamps[batch->index - 1] != 0);
410*61046927SAndroid Build Coastguard Worker }
411*61046927SAndroid Build Coastguard Worker 
412*61046927SAndroid Build Coastguard Worker /**
413*61046927SAndroid Build Coastguard Worker  * Submit completed snapshots for buffering.
414*61046927SAndroid Build Coastguard Worker  *
415*61046927SAndroid Build Coastguard Worker  * Snapshot data becomes available when asynchronous rendering completes.
416*61046927SAndroid Build Coastguard Worker  * Depending on configuration, snapshot data may need to be collated before
417*61046927SAndroid Build Coastguard Worker  * writing to the output file.
418*61046927SAndroid Build Coastguard Worker  */
419*61046927SAndroid Build Coastguard Worker static void
intel_measure_push_result(struct intel_measure_device * device,struct intel_measure_batch * batch)420*61046927SAndroid Build Coastguard Worker intel_measure_push_result(struct intel_measure_device *device,
421*61046927SAndroid Build Coastguard Worker                           struct intel_measure_batch *batch)
422*61046927SAndroid Build Coastguard Worker {
423*61046927SAndroid Build Coastguard Worker    struct intel_measure_ringbuffer *rb = device->ringbuffer;
424*61046927SAndroid Build Coastguard Worker 
425*61046927SAndroid Build Coastguard Worker    uint64_t *timestamps = batch->timestamps;
426*61046927SAndroid Build Coastguard Worker    assert(timestamps != NULL);
427*61046927SAndroid Build Coastguard Worker    assert(batch->index == 0 || timestamps[0] != 0);
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < batch->index; i += 2) {
430*61046927SAndroid Build Coastguard Worker       const struct intel_measure_snapshot *begin = &batch->snapshots[i];
431*61046927SAndroid Build Coastguard Worker       const struct intel_measure_snapshot *end = &batch->snapshots[i+1];
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker       assert (end->type == INTEL_SNAPSHOT_END);
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker       if (begin->type == INTEL_SNAPSHOT_SECONDARY_BATCH) {
436*61046927SAndroid Build Coastguard Worker          assert(begin->secondary != NULL);
437*61046927SAndroid Build Coastguard Worker          begin->secondary->batch_count = batch->batch_count;
438*61046927SAndroid Build Coastguard Worker          begin->secondary->batch_size = 0;
439*61046927SAndroid Build Coastguard Worker          begin->secondary->primary_renderpass = batch->renderpass;
440*61046927SAndroid Build Coastguard Worker          intel_measure_push_result(device, begin->secondary);
441*61046927SAndroid Build Coastguard Worker          continue;
442*61046927SAndroid Build Coastguard Worker       }
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker       const uint64_t prev_end_ts = rb->results[rb->head].end_ts;
445*61046927SAndroid Build Coastguard Worker 
446*61046927SAndroid Build Coastguard Worker       /* advance ring buffer */
447*61046927SAndroid Build Coastguard Worker       if (++rb->head == config.buffer_size)
448*61046927SAndroid Build Coastguard Worker          rb->head = 0;
449*61046927SAndroid Build Coastguard Worker       if (rb->head == rb->tail) {
450*61046927SAndroid Build Coastguard Worker          static bool warned = false;
451*61046927SAndroid Build Coastguard Worker          if (unlikely(!warned)) {
452*61046927SAndroid Build Coastguard Worker             fprintf(config.file,
453*61046927SAndroid Build Coastguard Worker                     "WARNING: Buffered data exceeds INTEL_MEASURE limit: %d. "
454*61046927SAndroid Build Coastguard Worker                     "Data has been dropped. "
455*61046927SAndroid Build Coastguard Worker                     "Increase setting with INTEL_MEASURE=buffer_size={count}\n",
456*61046927SAndroid Build Coastguard Worker                     config.buffer_size);
457*61046927SAndroid Build Coastguard Worker             warned = true;
458*61046927SAndroid Build Coastguard Worker          }
459*61046927SAndroid Build Coastguard Worker          break;
460*61046927SAndroid Build Coastguard Worker       }
461*61046927SAndroid Build Coastguard Worker 
462*61046927SAndroid Build Coastguard Worker       struct intel_measure_buffered_result *buffered_result =
463*61046927SAndroid Build Coastguard Worker          &rb->results[rb->head];
464*61046927SAndroid Build Coastguard Worker 
465*61046927SAndroid Build Coastguard Worker       memset(buffered_result, 0, sizeof(*buffered_result));
466*61046927SAndroid Build Coastguard Worker       memcpy(&buffered_result->snapshot, begin,
467*61046927SAndroid Build Coastguard Worker              sizeof(struct intel_measure_snapshot));
468*61046927SAndroid Build Coastguard Worker       buffered_result->start_ts = timestamps[i];
469*61046927SAndroid Build Coastguard Worker       buffered_result->end_ts = timestamps[i+1];
470*61046927SAndroid Build Coastguard Worker       buffered_result->idle_duration =
471*61046927SAndroid Build Coastguard Worker          raw_timestamp_delta(prev_end_ts, buffered_result->start_ts);
472*61046927SAndroid Build Coastguard Worker       buffered_result->frame = batch->frame;
473*61046927SAndroid Build Coastguard Worker       buffered_result->batch_count = batch->batch_count;
474*61046927SAndroid Build Coastguard Worker       buffered_result->batch_size = batch->batch_size;
475*61046927SAndroid Build Coastguard Worker       buffered_result->primary_renderpass = batch->primary_renderpass;
476*61046927SAndroid Build Coastguard Worker       buffered_result->event_index = i / 2;
477*61046927SAndroid Build Coastguard Worker       buffered_result->snapshot.event_count = end->event_count;
478*61046927SAndroid Build Coastguard Worker    }
479*61046927SAndroid Build Coastguard Worker }
480*61046927SAndroid Build Coastguard Worker 
481*61046927SAndroid Build Coastguard Worker static unsigned
ringbuffer_size(const struct intel_measure_ringbuffer * rb)482*61046927SAndroid Build Coastguard Worker ringbuffer_size(const struct intel_measure_ringbuffer *rb)
483*61046927SAndroid Build Coastguard Worker {
484*61046927SAndroid Build Coastguard Worker    unsigned head = rb->head;
485*61046927SAndroid Build Coastguard Worker    if (head < rb->tail)
486*61046927SAndroid Build Coastguard Worker       head += config.buffer_size;
487*61046927SAndroid Build Coastguard Worker    return head - rb->tail;
488*61046927SAndroid Build Coastguard Worker }
489*61046927SAndroid Build Coastguard Worker 
490*61046927SAndroid Build Coastguard Worker static const struct intel_measure_buffered_result *
ringbuffer_pop(struct intel_measure_ringbuffer * rb)491*61046927SAndroid Build Coastguard Worker ringbuffer_pop(struct intel_measure_ringbuffer *rb)
492*61046927SAndroid Build Coastguard Worker {
493*61046927SAndroid Build Coastguard Worker    if (rb->tail == rb->head) {
494*61046927SAndroid Build Coastguard Worker       /* encountered ringbuffer overflow while processing events */
495*61046927SAndroid Build Coastguard Worker       return NULL;
496*61046927SAndroid Build Coastguard Worker    }
497*61046927SAndroid Build Coastguard Worker 
498*61046927SAndroid Build Coastguard Worker    if (++rb->tail == config.buffer_size)
499*61046927SAndroid Build Coastguard Worker       rb->tail = 0;
500*61046927SAndroid Build Coastguard Worker    return &rb->results[rb->tail];
501*61046927SAndroid Build Coastguard Worker }
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker static const struct intel_measure_buffered_result *
ringbuffer_peek(const struct intel_measure_ringbuffer * rb,unsigned index)504*61046927SAndroid Build Coastguard Worker ringbuffer_peek(const struct intel_measure_ringbuffer *rb, unsigned index)
505*61046927SAndroid Build Coastguard Worker {
506*61046927SAndroid Build Coastguard Worker    int result_offset = rb->tail + index + 1;
507*61046927SAndroid Build Coastguard Worker    if (result_offset >= config.buffer_size)
508*61046927SAndroid Build Coastguard Worker       result_offset -= config.buffer_size;
509*61046927SAndroid Build Coastguard Worker    return &rb->results[result_offset];
510*61046927SAndroid Build Coastguard Worker }
511*61046927SAndroid Build Coastguard Worker 
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker /**
514*61046927SAndroid Build Coastguard Worker  * Determine the number of buffered events that must be combined for the next
515*61046927SAndroid Build Coastguard Worker  * line of csv output. Returns 0 if more events are needed.
516*61046927SAndroid Build Coastguard Worker  */
517*61046927SAndroid Build Coastguard Worker static unsigned
buffered_event_count(struct intel_measure_device * device)518*61046927SAndroid Build Coastguard Worker buffered_event_count(struct intel_measure_device *device)
519*61046927SAndroid Build Coastguard Worker {
520*61046927SAndroid Build Coastguard Worker    const struct intel_measure_ringbuffer *rb = device->ringbuffer;
521*61046927SAndroid Build Coastguard Worker    const unsigned buffered_event_count = ringbuffer_size(rb);
522*61046927SAndroid Build Coastguard Worker    if (buffered_event_count == 0) {
523*61046927SAndroid Build Coastguard Worker       /* no events to collect */
524*61046927SAndroid Build Coastguard Worker       return 0;
525*61046927SAndroid Build Coastguard Worker    }
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker    /* count the number of buffered events required to meet the configuration */
528*61046927SAndroid Build Coastguard Worker    if (config.flags & (INTEL_MEASURE_DRAW |
529*61046927SAndroid Build Coastguard Worker                        INTEL_MEASURE_RENDERPASS |
530*61046927SAndroid Build Coastguard Worker                        INTEL_MEASURE_SHADER)) {
531*61046927SAndroid Build Coastguard Worker       /* For these flags, every buffered event represents a line in the
532*61046927SAndroid Build Coastguard Worker        * output.  None of these events span batches.  If the event interval
533*61046927SAndroid Build Coastguard Worker        * crosses a batch boundary, then the next interval starts with the new
534*61046927SAndroid Build Coastguard Worker        * batch.
535*61046927SAndroid Build Coastguard Worker        */
536*61046927SAndroid Build Coastguard Worker       return 1;
537*61046927SAndroid Build Coastguard Worker    }
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker    const unsigned start_frame = ringbuffer_peek(rb, 0)->frame;
540*61046927SAndroid Build Coastguard Worker    if (config.flags & INTEL_MEASURE_BATCH) {
541*61046927SAndroid Build Coastguard Worker       /* each buffered event is a command buffer.  The number of events to
542*61046927SAndroid Build Coastguard Worker        * process is the same as the interval, unless the interval crosses a
543*61046927SAndroid Build Coastguard Worker        * frame boundary
544*61046927SAndroid Build Coastguard Worker        */
545*61046927SAndroid Build Coastguard Worker       if (buffered_event_count < config.event_interval) {
546*61046927SAndroid Build Coastguard Worker          /* not enough events */
547*61046927SAndroid Build Coastguard Worker          return 0;
548*61046927SAndroid Build Coastguard Worker       }
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker       /* Imperfect frame tracking requires us to allow for *older* frames */
551*61046927SAndroid Build Coastguard Worker       if (ringbuffer_peek(rb, config.event_interval - 1)->frame <= start_frame) {
552*61046927SAndroid Build Coastguard Worker          /* No frame transition.  The next {interval} events should be combined. */
553*61046927SAndroid Build Coastguard Worker          return config.event_interval;
554*61046927SAndroid Build Coastguard Worker       }
555*61046927SAndroid Build Coastguard Worker 
556*61046927SAndroid Build Coastguard Worker       /* Else a frame transition occurs within the interval.  Find the
557*61046927SAndroid Build Coastguard Worker        * transition, so the following line of output begins with the batch
558*61046927SAndroid Build Coastguard Worker        * that starts the new frame.
559*61046927SAndroid Build Coastguard Worker        */
560*61046927SAndroid Build Coastguard Worker       for (int event_index = 1;
561*61046927SAndroid Build Coastguard Worker            event_index <= config.event_interval;
562*61046927SAndroid Build Coastguard Worker            ++event_index) {
563*61046927SAndroid Build Coastguard Worker          if (ringbuffer_peek(rb, event_index)->frame > start_frame)
564*61046927SAndroid Build Coastguard Worker             return event_index;
565*61046927SAndroid Build Coastguard Worker       }
566*61046927SAndroid Build Coastguard Worker 
567*61046927SAndroid Build Coastguard Worker       assert(false);
568*61046927SAndroid Build Coastguard Worker    }
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker    /* Else we need to search buffered events to find the matching frame
571*61046927SAndroid Build Coastguard Worker     * transition for our interval.
572*61046927SAndroid Build Coastguard Worker     */
573*61046927SAndroid Build Coastguard Worker    assert(config.flags & INTEL_MEASURE_FRAME);
574*61046927SAndroid Build Coastguard Worker    for (int event_index = 1;
575*61046927SAndroid Build Coastguard Worker         event_index < buffered_event_count;
576*61046927SAndroid Build Coastguard Worker         ++event_index) {
577*61046927SAndroid Build Coastguard Worker       const int latest_frame = ringbuffer_peek(rb, event_index)->frame;
578*61046927SAndroid Build Coastguard Worker       if (latest_frame - start_frame >= config.event_interval)
579*61046927SAndroid Build Coastguard Worker          return event_index;
580*61046927SAndroid Build Coastguard Worker    }
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker    return 0;
583*61046927SAndroid Build Coastguard Worker }
584*61046927SAndroid Build Coastguard Worker 
585*61046927SAndroid Build Coastguard Worker /**
586*61046927SAndroid Build Coastguard Worker  * Take result_count events from the ringbuffer and output them as a single
587*61046927SAndroid Build Coastguard Worker  * line.
588*61046927SAndroid Build Coastguard Worker  */
589*61046927SAndroid Build Coastguard Worker static void
print_combined_results(struct intel_measure_device * measure_device,int result_count,const struct intel_device_info * info)590*61046927SAndroid Build Coastguard Worker print_combined_results(struct intel_measure_device *measure_device,
591*61046927SAndroid Build Coastguard Worker                        int result_count,
592*61046927SAndroid Build Coastguard Worker                        const struct intel_device_info *info)
593*61046927SAndroid Build Coastguard Worker {
594*61046927SAndroid Build Coastguard Worker    if (result_count == 0)
595*61046927SAndroid Build Coastguard Worker       return;
596*61046927SAndroid Build Coastguard Worker 
597*61046927SAndroid Build Coastguard Worker    struct intel_measure_ringbuffer *result_rb = measure_device->ringbuffer;
598*61046927SAndroid Build Coastguard Worker    assert(ringbuffer_size(result_rb) >= result_count);
599*61046927SAndroid Build Coastguard Worker    const struct intel_measure_buffered_result* start_result =
600*61046927SAndroid Build Coastguard Worker       ringbuffer_pop(result_rb);
601*61046927SAndroid Build Coastguard Worker    const struct intel_measure_buffered_result* current_result = start_result;
602*61046927SAndroid Build Coastguard Worker 
603*61046927SAndroid Build Coastguard Worker    if (start_result == NULL)
604*61046927SAndroid Build Coastguard Worker       return;
605*61046927SAndroid Build Coastguard Worker    --result_count;
606*61046927SAndroid Build Coastguard Worker 
607*61046927SAndroid Build Coastguard Worker    uint64_t duration_ts = raw_timestamp_delta(start_result->start_ts,
608*61046927SAndroid Build Coastguard Worker                                               current_result->end_ts);
609*61046927SAndroid Build Coastguard Worker    unsigned event_count = start_result->snapshot.event_count;
610*61046927SAndroid Build Coastguard Worker    while (result_count-- > 0) {
611*61046927SAndroid Build Coastguard Worker       assert(ringbuffer_size(result_rb) > 0);
612*61046927SAndroid Build Coastguard Worker       current_result = ringbuffer_pop(result_rb);
613*61046927SAndroid Build Coastguard Worker       if (current_result == NULL)
614*61046927SAndroid Build Coastguard Worker          return;
615*61046927SAndroid Build Coastguard Worker       duration_ts += raw_timestamp_delta(current_result->start_ts,
616*61046927SAndroid Build Coastguard Worker                                          current_result->end_ts);
617*61046927SAndroid Build Coastguard Worker       event_count += current_result->snapshot.event_count;
618*61046927SAndroid Build Coastguard Worker    }
619*61046927SAndroid Build Coastguard Worker 
620*61046927SAndroid Build Coastguard Worker    uint64_t duration_idle_ns =
621*61046927SAndroid Build Coastguard Worker       intel_device_info_timebase_scale(info, start_result->idle_duration);
622*61046927SAndroid Build Coastguard Worker    uint64_t duration_time_ns =
623*61046927SAndroid Build Coastguard Worker       intel_device_info_timebase_scale(info, duration_ts);
624*61046927SAndroid Build Coastguard Worker    const struct intel_measure_snapshot *begin = &start_result->snapshot;
625*61046927SAndroid Build Coastguard Worker    uint32_t renderpass = (start_result->primary_renderpass)
626*61046927SAndroid Build Coastguard Worker       ? start_result->primary_renderpass : begin->renderpass;
627*61046927SAndroid Build Coastguard Worker    fprintf(config.file, "%"PRIu64",%"PRIu64",%u,%u,%"PRIu64",%u,%u,%u,%s,%u,"
628*61046927SAndroid Build Coastguard Worker            "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,%.3lf,%.3lf\n",
629*61046927SAndroid Build Coastguard Worker            start_result->start_ts, current_result->end_ts,
630*61046927SAndroid Build Coastguard Worker            start_result->frame,
631*61046927SAndroid Build Coastguard Worker            start_result->batch_count, start_result->batch_size,
632*61046927SAndroid Build Coastguard Worker            renderpass, start_result->event_index, event_count,
633*61046927SAndroid Build Coastguard Worker            begin->event_name, begin->count,
634*61046927SAndroid Build Coastguard Worker            begin->vs, begin->tcs, begin->tes, begin->gs,
635*61046927SAndroid Build Coastguard Worker            begin->fs, begin->cs, begin->ms, begin->ts,
636*61046927SAndroid Build Coastguard Worker            (double)duration_idle_ns / 1000.0,
637*61046927SAndroid Build Coastguard Worker            (double)duration_time_ns / 1000.0);
638*61046927SAndroid Build Coastguard Worker }
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker /**
641*61046927SAndroid Build Coastguard Worker  * Write data for a cpu event.
642*61046927SAndroid Build Coastguard Worker  */
643*61046927SAndroid Build Coastguard Worker void
intel_measure_print_cpu_result(unsigned int frame,unsigned int batch_count,uint64_t batch_size,unsigned int event_index,unsigned int event_count,unsigned int count,const char * event_name)644*61046927SAndroid Build Coastguard Worker intel_measure_print_cpu_result(unsigned int frame,
645*61046927SAndroid Build Coastguard Worker                                unsigned int batch_count,
646*61046927SAndroid Build Coastguard Worker                                uint64_t batch_size,
647*61046927SAndroid Build Coastguard Worker                                unsigned int event_index,
648*61046927SAndroid Build Coastguard Worker                                unsigned int event_count,
649*61046927SAndroid Build Coastguard Worker                                unsigned int count,
650*61046927SAndroid Build Coastguard Worker                                const char* event_name)
651*61046927SAndroid Build Coastguard Worker {
652*61046927SAndroid Build Coastguard Worker    assert(config.cpu_measure);
653*61046927SAndroid Build Coastguard Worker    uint64_t start_ns = os_time_get_nano();
654*61046927SAndroid Build Coastguard Worker 
655*61046927SAndroid Build Coastguard Worker    fprintf(config.file, "%"PRIu64",%u,%3u,%"PRIu64",%3u,%u,%s,%u\n",
656*61046927SAndroid Build Coastguard Worker            start_ns, frame, batch_count, batch_size,
657*61046927SAndroid Build Coastguard Worker            event_index, event_count, event_name, count);
658*61046927SAndroid Build Coastguard Worker }
659*61046927SAndroid Build Coastguard Worker 
660*61046927SAndroid Build Coastguard Worker /**
661*61046927SAndroid Build Coastguard Worker  * Empty the ringbuffer of events that can be printed.
662*61046927SAndroid Build Coastguard Worker  */
663*61046927SAndroid Build Coastguard Worker static void
intel_measure_print(struct intel_measure_device * device,const struct intel_device_info * info)664*61046927SAndroid Build Coastguard Worker intel_measure_print(struct intel_measure_device *device,
665*61046927SAndroid Build Coastguard Worker                     const struct intel_device_info *info)
666*61046927SAndroid Build Coastguard Worker {
667*61046927SAndroid Build Coastguard Worker    while (true) {
668*61046927SAndroid Build Coastguard Worker       const int events_to_combine = buffered_event_count(device);
669*61046927SAndroid Build Coastguard Worker       if (events_to_combine == 0)
670*61046927SAndroid Build Coastguard Worker          break;
671*61046927SAndroid Build Coastguard Worker       print_combined_results(device, events_to_combine, info);
672*61046927SAndroid Build Coastguard Worker    }
673*61046927SAndroid Build Coastguard Worker }
674*61046927SAndroid Build Coastguard Worker 
675*61046927SAndroid Build Coastguard Worker /**
676*61046927SAndroid Build Coastguard Worker  * Collect snapshots from completed command buffers and submit them to
677*61046927SAndroid Build Coastguard Worker  * intel_measure for printing.
678*61046927SAndroid Build Coastguard Worker  */
679*61046927SAndroid Build Coastguard Worker void
intel_measure_gather(struct intel_measure_device * measure_device,const struct intel_device_info * info)680*61046927SAndroid Build Coastguard Worker intel_measure_gather(struct intel_measure_device *measure_device,
681*61046927SAndroid Build Coastguard Worker                      const struct intel_device_info *info)
682*61046927SAndroid Build Coastguard Worker {
683*61046927SAndroid Build Coastguard Worker    pthread_mutex_lock(&measure_device->mutex);
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker    /* Iterate snapshots and collect if ready.  Each snapshot queue will be
686*61046927SAndroid Build Coastguard Worker     * in-order, but we must determine which queue has the oldest batch.
687*61046927SAndroid Build Coastguard Worker     */
688*61046927SAndroid Build Coastguard Worker    /* iterate snapshots and collect if ready */
689*61046927SAndroid Build Coastguard Worker    while (!list_is_empty(&measure_device->queued_snapshots)) {
690*61046927SAndroid Build Coastguard Worker       struct intel_measure_batch *batch =
691*61046927SAndroid Build Coastguard Worker          list_first_entry(&measure_device->queued_snapshots,
692*61046927SAndroid Build Coastguard Worker                           struct intel_measure_batch, link);
693*61046927SAndroid Build Coastguard Worker 
694*61046927SAndroid Build Coastguard Worker       if (!intel_measure_ready(batch)) {
695*61046927SAndroid Build Coastguard Worker          /* command buffer has begun execution on the gpu, but has not
696*61046927SAndroid Build Coastguard Worker           * completed.
697*61046927SAndroid Build Coastguard Worker           */
698*61046927SAndroid Build Coastguard Worker          break;
699*61046927SAndroid Build Coastguard Worker       }
700*61046927SAndroid Build Coastguard Worker 
701*61046927SAndroid Build Coastguard Worker       list_del(&batch->link);
702*61046927SAndroid Build Coastguard Worker       assert(batch->index % 2 == 0);
703*61046927SAndroid Build Coastguard Worker 
704*61046927SAndroid Build Coastguard Worker       intel_measure_push_result(measure_device, batch);
705*61046927SAndroid Build Coastguard Worker 
706*61046927SAndroid Build Coastguard Worker       batch->index = 0;
707*61046927SAndroid Build Coastguard Worker       batch->frame = 0;
708*61046927SAndroid Build Coastguard Worker       if (measure_device->release_batch)
709*61046927SAndroid Build Coastguard Worker          measure_device->release_batch(batch);
710*61046927SAndroid Build Coastguard Worker    }
711*61046927SAndroid Build Coastguard Worker 
712*61046927SAndroid Build Coastguard Worker    intel_measure_print(measure_device, info);
713*61046927SAndroid Build Coastguard Worker    pthread_mutex_unlock(&measure_device->mutex);
714*61046927SAndroid Build Coastguard Worker }
715