xref: /aosp_15_r20/external/mesa3d/src/freedreno/vulkan/tu_perfetto.cc (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2021 Google, Inc.
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include <perfetto.h>
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #include "tu_perfetto.h"
9*61046927SAndroid Build Coastguard Worker #include "tu_buffer.h"
10*61046927SAndroid Build Coastguard Worker #include "tu_device.h"
11*61046927SAndroid Build Coastguard Worker #include "tu_image.h"
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker #include "util/hash_table.h"
14*61046927SAndroid Build Coastguard Worker #include "util/perf/u_perfetto.h"
15*61046927SAndroid Build Coastguard Worker #include "util/perf/u_perfetto_renderpass.h"
16*61046927SAndroid Build Coastguard Worker 
17*61046927SAndroid Build Coastguard Worker #include "tu_tracepoints.h"
18*61046927SAndroid Build Coastguard Worker #include "tu_tracepoints_perfetto.h"
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker /* we can't include tu_knl.h and tu_device.h */
21*61046927SAndroid Build Coastguard Worker 
22*61046927SAndroid Build Coastguard Worker int
23*61046927SAndroid Build Coastguard Worker tu_device_get_gpu_timestamp(struct tu_device *dev,
24*61046927SAndroid Build Coastguard Worker                             uint64_t *ts);
25*61046927SAndroid Build Coastguard Worker int
26*61046927SAndroid Build Coastguard Worker tu_device_get_suspend_count(struct tu_device *dev,
27*61046927SAndroid Build Coastguard Worker                             uint64_t *suspend_count);
28*61046927SAndroid Build Coastguard Worker uint64_t
29*61046927SAndroid Build Coastguard Worker tu_device_ticks_to_ns(struct tu_device *dev, uint64_t ts);
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker struct u_trace_context *
32*61046927SAndroid Build Coastguard Worker tu_device_get_u_trace(struct tu_device *device);
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker /**
35*61046927SAndroid Build Coastguard Worker  * Queue-id's
36*61046927SAndroid Build Coastguard Worker  */
37*61046927SAndroid Build Coastguard Worker enum {
38*61046927SAndroid Build Coastguard Worker    DEFAULT_HW_QUEUE_ID,
39*61046927SAndroid Build Coastguard Worker };
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker /**
42*61046927SAndroid Build Coastguard Worker  * Render-stage id's
43*61046927SAndroid Build Coastguard Worker  */
44*61046927SAndroid Build Coastguard Worker enum tu_stage_id {
45*61046927SAndroid Build Coastguard Worker    CMD_BUFFER_STAGE_ID,
46*61046927SAndroid Build Coastguard Worker    CMD_BUFFER_ANNOTATION_STAGE_ID,
47*61046927SAndroid Build Coastguard Worker    RENDER_PASS_STAGE_ID,
48*61046927SAndroid Build Coastguard Worker    CMD_BUFFER_ANNOTATION_RENDER_PASS_STAGE_ID,
49*61046927SAndroid Build Coastguard Worker    BINNING_STAGE_ID,
50*61046927SAndroid Build Coastguard Worker    GMEM_STAGE_ID,
51*61046927SAndroid Build Coastguard Worker    BYPASS_STAGE_ID,
52*61046927SAndroid Build Coastguard Worker    BLIT_STAGE_ID,
53*61046927SAndroid Build Coastguard Worker    COMPUTE_STAGE_ID,
54*61046927SAndroid Build Coastguard Worker    CLEAR_SYSMEM_STAGE_ID,
55*61046927SAndroid Build Coastguard Worker    CLEAR_GMEM_STAGE_ID,
56*61046927SAndroid Build Coastguard Worker    GENERIC_CLEAR_STAGE_ID,
57*61046927SAndroid Build Coastguard Worker    GMEM_LOAD_STAGE_ID,
58*61046927SAndroid Build Coastguard Worker    GMEM_STORE_STAGE_ID,
59*61046927SAndroid Build Coastguard Worker    SYSMEM_RESOLVE_STAGE_ID,
60*61046927SAndroid Build Coastguard Worker    // TODO add the rest from fd_stage_id
61*61046927SAndroid Build Coastguard Worker };
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker static const struct {
64*61046927SAndroid Build Coastguard Worker    const char *name;
65*61046927SAndroid Build Coastguard Worker    const char *desc;
66*61046927SAndroid Build Coastguard Worker } queues[] = {
67*61046927SAndroid Build Coastguard Worker    [DEFAULT_HW_QUEUE_ID] = {"GPU Queue 0", "Default Adreno Hardware Queue"},
68*61046927SAndroid Build Coastguard Worker };
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker static const struct {
71*61046927SAndroid Build Coastguard Worker    const char *name;
72*61046927SAndroid Build Coastguard Worker    const char *desc;
73*61046927SAndroid Build Coastguard Worker } stages[] = {
74*61046927SAndroid Build Coastguard Worker    [CMD_BUFFER_STAGE_ID]     = { "Command Buffer" },
75*61046927SAndroid Build Coastguard Worker    [CMD_BUFFER_ANNOTATION_STAGE_ID]     = { "Annotation", "Command Buffer Annotation" },
76*61046927SAndroid Build Coastguard Worker    [RENDER_PASS_STAGE_ID]    = { "Render Pass" },
77*61046927SAndroid Build Coastguard Worker    [CMD_BUFFER_ANNOTATION_RENDER_PASS_STAGE_ID]    = { "Annotation", "Render Pass Command Buffer Annotation" },
78*61046927SAndroid Build Coastguard Worker    [BINNING_STAGE_ID]        = { "Binning", "Perform Visibility pass and determine target bins" },
79*61046927SAndroid Build Coastguard Worker    [GMEM_STAGE_ID]           = { "GMEM", "Rendering to GMEM" },
80*61046927SAndroid Build Coastguard Worker    [BYPASS_STAGE_ID]         = { "Bypass", "Rendering to system memory" },
81*61046927SAndroid Build Coastguard Worker    [BLIT_STAGE_ID]           = { "Blit", "Performing a Blit operation" },
82*61046927SAndroid Build Coastguard Worker    [COMPUTE_STAGE_ID]        = { "Compute", "Compute job" },
83*61046927SAndroid Build Coastguard Worker    [CLEAR_SYSMEM_STAGE_ID]   = { "Clear Sysmem", "" },
84*61046927SAndroid Build Coastguard Worker    [CLEAR_GMEM_STAGE_ID]     = { "Clear GMEM", "Per-tile (GMEM) clear" },
85*61046927SAndroid Build Coastguard Worker    [GENERIC_CLEAR_STAGE_ID]  = { "Clear Sysmem/Gmem", ""},
86*61046927SAndroid Build Coastguard Worker    [GMEM_LOAD_STAGE_ID]      = { "GMEM Load", "Per tile system memory to GMEM load" },
87*61046927SAndroid Build Coastguard Worker    [GMEM_STORE_STAGE_ID]     = { "GMEM Store", "Per tile GMEM to system memory store" },
88*61046927SAndroid Build Coastguard Worker    [SYSMEM_RESOLVE_STAGE_ID] = { "SysMem Resolve", "System memory MSAA resolve" },
89*61046927SAndroid Build Coastguard Worker    // TODO add the rest
90*61046927SAndroid Build Coastguard Worker };
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker static uint32_t gpu_clock_id;
93*61046927SAndroid Build Coastguard Worker static uint64_t next_clock_sync_ns; /* cpu time of next clk sync */
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker /**
96*61046927SAndroid Build Coastguard Worker  * The timestamp at the point where we first emitted the clock_sync..
97*61046927SAndroid Build Coastguard Worker  * this  will be a *later* timestamp that the first GPU traces (since
98*61046927SAndroid Build Coastguard Worker  * we capture the first clock_sync from the CPU *after* the first GPU
99*61046927SAndroid Build Coastguard Worker  * tracepoints happen).  To avoid confusing perfetto we need to drop
100*61046927SAndroid Build Coastguard Worker  * the GPU traces with timestamps before this.
101*61046927SAndroid Build Coastguard Worker  */
102*61046927SAndroid Build Coastguard Worker static uint64_t sync_gpu_ts;
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker static uint64_t last_suspend_count;
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker static uint64_t gpu_max_timestamp;
107*61046927SAndroid Build Coastguard Worker static uint64_t gpu_timestamp_offset;
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker struct TuRenderpassIncrementalState {
110*61046927SAndroid Build Coastguard Worker    bool was_cleared = true;
111*61046927SAndroid Build Coastguard Worker };
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker struct TuRenderpassTraits : public perfetto::DefaultDataSourceTraits {
114*61046927SAndroid Build Coastguard Worker    using IncrementalStateType = TuRenderpassIncrementalState;
115*61046927SAndroid Build Coastguard Worker };
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker class TuRenderpassDataSource : public MesaRenderpassDataSource<TuRenderpassDataSource,
118*61046927SAndroid Build Coastguard Worker                                                                TuRenderpassTraits> {
OnStart(const StartArgs & args)119*61046927SAndroid Build Coastguard Worker    void OnStart(const StartArgs &args) override
120*61046927SAndroid Build Coastguard Worker    {
121*61046927SAndroid Build Coastguard Worker       MesaRenderpassDataSource<TuRenderpassDataSource, TuRenderpassTraits>::OnStart(args);
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker       /* Note: clock_id's below 128 are reserved.. for custom clock sources,
124*61046927SAndroid Build Coastguard Worker        * using the hash of a namespaced string is the recommended approach.
125*61046927SAndroid Build Coastguard Worker        * See: https://perfetto.dev/docs/concepts/clock-sync
126*61046927SAndroid Build Coastguard Worker        */
127*61046927SAndroid Build Coastguard Worker       gpu_clock_id =
128*61046927SAndroid Build Coastguard Worker          _mesa_hash_string("org.freedesktop.mesa.freedreno") | 0x80000000;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker       gpu_timestamp_offset = 0;
131*61046927SAndroid Build Coastguard Worker       gpu_max_timestamp = 0;
132*61046927SAndroid Build Coastguard Worker       last_suspend_count = 0;
133*61046927SAndroid Build Coastguard Worker    }
134*61046927SAndroid Build Coastguard Worker };
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(TuRenderpassDataSource);
137*61046927SAndroid Build Coastguard Worker PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(TuRenderpassDataSource);
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker static void
send_descriptors(TuRenderpassDataSource::TraceContext & ctx)140*61046927SAndroid Build Coastguard Worker send_descriptors(TuRenderpassDataSource::TraceContext &ctx)
141*61046927SAndroid Build Coastguard Worker {
142*61046927SAndroid Build Coastguard Worker    PERFETTO_LOG("Sending renderstage descriptors");
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    auto packet = ctx.NewTracePacket();
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker    /* This must be set before interned data is sent. */
147*61046927SAndroid Build Coastguard Worker    packet->set_sequence_flags(perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
148*61046927SAndroid Build Coastguard Worker 
149*61046927SAndroid Build Coastguard Worker    packet->set_timestamp(0);
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    auto event = packet->set_gpu_render_stage_event();
152*61046927SAndroid Build Coastguard Worker    event->set_gpu_id(0);
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker    auto spec = event->set_specifications();
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ARRAY_SIZE(queues); i++) {
157*61046927SAndroid Build Coastguard Worker       auto desc = spec->add_hw_queue();
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker       desc->set_name(queues[i].name);
160*61046927SAndroid Build Coastguard Worker       desc->set_description(queues[i].desc);
161*61046927SAndroid Build Coastguard Worker    }
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ARRAY_SIZE(stages); i++) {
164*61046927SAndroid Build Coastguard Worker       auto desc = spec->add_stage();
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker       desc->set_name(stages[i].name);
167*61046927SAndroid Build Coastguard Worker       if (stages[i].desc)
168*61046927SAndroid Build Coastguard Worker          desc->set_description(stages[i].desc);
169*61046927SAndroid Build Coastguard Worker    }
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker static struct tu_perfetto_stage *
stage_push(struct tu_device * dev)173*61046927SAndroid Build Coastguard Worker stage_push(struct tu_device *dev)
174*61046927SAndroid Build Coastguard Worker {
175*61046927SAndroid Build Coastguard Worker    struct tu_perfetto_state *p = &dev->perfetto;
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker    if (p->stage_depth >= ARRAY_SIZE(p->stages)) {
178*61046927SAndroid Build Coastguard Worker       p->skipped_depth++;
179*61046927SAndroid Build Coastguard Worker       return NULL;
180*61046927SAndroid Build Coastguard Worker    }
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    return &p->stages[p->stage_depth++];
183*61046927SAndroid Build Coastguard Worker }
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker typedef void (*trace_payload_as_extra_func)(perfetto::protos::pbzero::GpuRenderStageEvent *, const void*);
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker static struct tu_perfetto_stage *
stage_pop(struct tu_device * dev)188*61046927SAndroid Build Coastguard Worker stage_pop(struct tu_device *dev)
189*61046927SAndroid Build Coastguard Worker {
190*61046927SAndroid Build Coastguard Worker    struct tu_perfetto_state *p = &dev->perfetto;
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker    if (!p->stage_depth)
193*61046927SAndroid Build Coastguard Worker       return NULL;
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker    if (p->skipped_depth) {
196*61046927SAndroid Build Coastguard Worker       p->skipped_depth--;
197*61046927SAndroid Build Coastguard Worker       return NULL;
198*61046927SAndroid Build Coastguard Worker    }
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker    return &p->stages[--p->stage_depth];
201*61046927SAndroid Build Coastguard Worker }
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker static void
stage_start(struct tu_device * dev,uint64_t ts_ns,enum tu_stage_id stage_id,const char * app_event,const void * payload=nullptr,size_t payload_size=0,trace_payload_as_extra_func payload_as_extra=nullptr)204*61046927SAndroid Build Coastguard Worker stage_start(struct tu_device *dev,
205*61046927SAndroid Build Coastguard Worker             uint64_t ts_ns,
206*61046927SAndroid Build Coastguard Worker             enum tu_stage_id stage_id,
207*61046927SAndroid Build Coastguard Worker             const char *app_event,
208*61046927SAndroid Build Coastguard Worker             const void *payload = nullptr,
209*61046927SAndroid Build Coastguard Worker             size_t payload_size = 0,
210*61046927SAndroid Build Coastguard Worker             trace_payload_as_extra_func payload_as_extra = nullptr)
211*61046927SAndroid Build Coastguard Worker {
212*61046927SAndroid Build Coastguard Worker    struct tu_perfetto_stage *stage = stage_push(dev);
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker    if (!stage) {
215*61046927SAndroid Build Coastguard Worker       PERFETTO_ELOG("stage %d is nested too deep", stage_id);
216*61046927SAndroid Build Coastguard Worker       return;
217*61046927SAndroid Build Coastguard Worker    }
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    if (payload) {
220*61046927SAndroid Build Coastguard Worker       void* new_payload = malloc(payload_size);
221*61046927SAndroid Build Coastguard Worker       if (new_payload)
222*61046927SAndroid Build Coastguard Worker          memcpy(new_payload, payload, payload_size);
223*61046927SAndroid Build Coastguard Worker       else
224*61046927SAndroid Build Coastguard Worker          PERFETTO_ELOG("Failed to allocate payload for stage %d", stage_id);
225*61046927SAndroid Build Coastguard Worker       payload = new_payload;
226*61046927SAndroid Build Coastguard Worker    }
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    *stage = (struct tu_perfetto_stage) {
229*61046927SAndroid Build Coastguard Worker       .stage_id = stage_id,
230*61046927SAndroid Build Coastguard Worker       .stage_iid = 0,
231*61046927SAndroid Build Coastguard Worker       .start_ts = ts_ns,
232*61046927SAndroid Build Coastguard Worker       .payload = payload,
233*61046927SAndroid Build Coastguard Worker       .start_payload_function = (void *) payload_as_extra,
234*61046927SAndroid Build Coastguard Worker    };
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker    if (app_event) {
237*61046927SAndroid Build Coastguard Worker       TuRenderpassDataSource::Trace([=](auto tctx) {
238*61046927SAndroid Build Coastguard Worker          stage->stage_iid =
239*61046927SAndroid Build Coastguard Worker             tctx.GetDataSourceLocked()->debug_marker_stage(tctx, app_event);
240*61046927SAndroid Build Coastguard Worker       });
241*61046927SAndroid Build Coastguard Worker    }
242*61046927SAndroid Build Coastguard Worker }
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker static void
stage_end(struct tu_device * dev,uint64_t ts_ns,enum tu_stage_id stage_id,const void * flush_data,const void * payload=nullptr,trace_payload_as_extra_func payload_as_extra=nullptr)245*61046927SAndroid Build Coastguard Worker stage_end(struct tu_device *dev, uint64_t ts_ns, enum tu_stage_id stage_id,
246*61046927SAndroid Build Coastguard Worker           const void *flush_data,
247*61046927SAndroid Build Coastguard Worker           const void* payload = nullptr,
248*61046927SAndroid Build Coastguard Worker           trace_payload_as_extra_func payload_as_extra = nullptr)
249*61046927SAndroid Build Coastguard Worker {
250*61046927SAndroid Build Coastguard Worker    struct tu_perfetto_stage *stage = stage_pop(dev);
251*61046927SAndroid Build Coastguard Worker    auto trace_flush_data =
252*61046927SAndroid Build Coastguard Worker       (const struct tu_u_trace_submission_data *) flush_data;
253*61046927SAndroid Build Coastguard Worker    uint32_t submission_id = trace_flush_data->submission_id;
254*61046927SAndroid Build Coastguard Worker    uint64_t gpu_ts_offset = trace_flush_data->gpu_ts_offset;
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker    if (!stage)
257*61046927SAndroid Build Coastguard Worker       return;
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker    if (stage->stage_id != stage_id) {
260*61046927SAndroid Build Coastguard Worker       PERFETTO_ELOG("stage %d ended while stage %d is expected",
261*61046927SAndroid Build Coastguard Worker             stage_id, stage->stage_id);
262*61046927SAndroid Build Coastguard Worker       return;
263*61046927SAndroid Build Coastguard Worker    }
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker    /* If we haven't managed to calibrate the alignment between GPU and CPU
266*61046927SAndroid Build Coastguard Worker     * timestamps yet, then skip this trace, otherwise perfetto won't know
267*61046927SAndroid Build Coastguard Worker     * what to do with it.
268*61046927SAndroid Build Coastguard Worker     */
269*61046927SAndroid Build Coastguard Worker    if (!sync_gpu_ts)
270*61046927SAndroid Build Coastguard Worker       return;
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker    TuRenderpassDataSource::Trace([=](TuRenderpassDataSource::TraceContext tctx) {
273*61046927SAndroid Build Coastguard Worker       if (auto state = tctx.GetIncrementalState(); state->was_cleared) {
274*61046927SAndroid Build Coastguard Worker          send_descriptors(tctx);
275*61046927SAndroid Build Coastguard Worker          state->was_cleared = false;
276*61046927SAndroid Build Coastguard Worker       }
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker       auto packet = tctx.NewTracePacket();
279*61046927SAndroid Build Coastguard Worker 
280*61046927SAndroid Build Coastguard Worker       gpu_max_timestamp = MAX2(gpu_max_timestamp, ts_ns + gpu_ts_offset);
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker       packet->set_timestamp(stage->start_ts + gpu_ts_offset);
283*61046927SAndroid Build Coastguard Worker       packet->set_timestamp_clock_id(gpu_clock_id);
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker       auto event = packet->set_gpu_render_stage_event();
286*61046927SAndroid Build Coastguard Worker       event->set_event_id(0); // ???
287*61046927SAndroid Build Coastguard Worker       event->set_hw_queue_id(DEFAULT_HW_QUEUE_ID);
288*61046927SAndroid Build Coastguard Worker       event->set_duration(ts_ns - stage->start_ts);
289*61046927SAndroid Build Coastguard Worker       if (stage->stage_iid)
290*61046927SAndroid Build Coastguard Worker          event->set_stage_iid(stage->stage_iid);
291*61046927SAndroid Build Coastguard Worker       else
292*61046927SAndroid Build Coastguard Worker          event->set_stage_id(stage->stage_id);
293*61046927SAndroid Build Coastguard Worker       event->set_context((uintptr_t) dev);
294*61046927SAndroid Build Coastguard Worker       event->set_submission_id(submission_id);
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker       if (stage->payload) {
297*61046927SAndroid Build Coastguard Worker          if (stage->start_payload_function)
298*61046927SAndroid Build Coastguard Worker             ((trace_payload_as_extra_func) stage->start_payload_function)(
299*61046927SAndroid Build Coastguard Worker                event, stage->payload);
300*61046927SAndroid Build Coastguard Worker          free((void *)stage->payload);
301*61046927SAndroid Build Coastguard Worker       }
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker       if (payload && payload_as_extra)
304*61046927SAndroid Build Coastguard Worker          payload_as_extra(event, payload);
305*61046927SAndroid Build Coastguard Worker    });
306*61046927SAndroid Build Coastguard Worker }
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker class TuMemoryDataSource : public perfetto::DataSource<TuMemoryDataSource> {
309*61046927SAndroid Build Coastguard Worker  public:
OnSetup(const SetupArgs &)310*61046927SAndroid Build Coastguard Worker    void OnSetup(const SetupArgs &) override
311*61046927SAndroid Build Coastguard Worker    {
312*61046927SAndroid Build Coastguard Worker    }
313*61046927SAndroid Build Coastguard Worker 
OnStart(const StartArgs &)314*61046927SAndroid Build Coastguard Worker    void OnStart(const StartArgs &) override
315*61046927SAndroid Build Coastguard Worker    {
316*61046927SAndroid Build Coastguard Worker       PERFETTO_LOG("Memory tracing started");
317*61046927SAndroid Build Coastguard Worker    }
318*61046927SAndroid Build Coastguard Worker 
OnStop(const StopArgs &)319*61046927SAndroid Build Coastguard Worker    void OnStop(const StopArgs &) override
320*61046927SAndroid Build Coastguard Worker    {
321*61046927SAndroid Build Coastguard Worker       PERFETTO_LOG("Memory tracing stopped");
322*61046927SAndroid Build Coastguard Worker    }
323*61046927SAndroid Build Coastguard Worker };
324*61046927SAndroid Build Coastguard Worker 
325*61046927SAndroid Build Coastguard Worker PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(TuMemoryDataSource);
326*61046927SAndroid Build Coastguard Worker PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(TuMemoryDataSource);
327*61046927SAndroid Build Coastguard Worker 
328*61046927SAndroid Build Coastguard Worker 
329*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
330*61046927SAndroid Build Coastguard Worker extern "C" {
331*61046927SAndroid Build Coastguard Worker #endif
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker void
tu_perfetto_init(void)334*61046927SAndroid Build Coastguard Worker tu_perfetto_init(void)
335*61046927SAndroid Build Coastguard Worker {
336*61046927SAndroid Build Coastguard Worker    util_perfetto_init();
337*61046927SAndroid Build Coastguard Worker 
338*61046927SAndroid Build Coastguard Worker    {
339*61046927SAndroid Build Coastguard Worker    perfetto::DataSourceDescriptor dsd;
340*61046927SAndroid Build Coastguard Worker #if DETECT_OS_ANDROID
341*61046927SAndroid Build Coastguard Worker      /* AGI requires this name */
342*61046927SAndroid Build Coastguard Worker      dsd.set_name("gpu.renderstages");
343*61046927SAndroid Build Coastguard Worker #else
344*61046927SAndroid Build Coastguard Worker       dsd.set_name("gpu.renderstages.msm");
345*61046927SAndroid Build Coastguard Worker #endif
346*61046927SAndroid Build Coastguard Worker       TuRenderpassDataSource::Register(dsd);
347*61046927SAndroid Build Coastguard Worker    }
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker    {
350*61046927SAndroid Build Coastguard Worker      perfetto::DataSourceDescriptor dsd;
351*61046927SAndroid Build Coastguard Worker      dsd.set_name("gpu.memory.msm");
352*61046927SAndroid Build Coastguard Worker      TuMemoryDataSource::Register(dsd);
353*61046927SAndroid Build Coastguard Worker    }
354*61046927SAndroid Build Coastguard Worker }
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker static void
emit_sync_timestamp(uint64_t cpu_ts,uint64_t gpu_ts)357*61046927SAndroid Build Coastguard Worker emit_sync_timestamp(uint64_t cpu_ts, uint64_t gpu_ts)
358*61046927SAndroid Build Coastguard Worker {
359*61046927SAndroid Build Coastguard Worker    TuRenderpassDataSource::Trace([=](auto tctx) {
360*61046927SAndroid Build Coastguard Worker       MesaRenderpassDataSource<TuRenderpassDataSource,
361*61046927SAndroid Build Coastguard Worker                                TuRenderpassTraits>::EmitClockSync(tctx, cpu_ts,
362*61046927SAndroid Build Coastguard Worker                                                                   gpu_ts, gpu_clock_id);
363*61046927SAndroid Build Coastguard Worker    });
364*61046927SAndroid Build Coastguard Worker }
365*61046927SAndroid Build Coastguard Worker 
366*61046927SAndroid Build Coastguard Worker static void
emit_submit_id(uint32_t submission_id)367*61046927SAndroid Build Coastguard Worker emit_submit_id(uint32_t submission_id)
368*61046927SAndroid Build Coastguard Worker {
369*61046927SAndroid Build Coastguard Worker    TuRenderpassDataSource::Trace([=](TuRenderpassDataSource::TraceContext tctx) {
370*61046927SAndroid Build Coastguard Worker       auto packet = tctx.NewTracePacket();
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker       packet->set_timestamp(perfetto::base::GetBootTimeNs().count());
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker       auto event = packet->set_vulkan_api_event();
375*61046927SAndroid Build Coastguard Worker       auto submit = event->set_vk_queue_submit();
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker       submit->set_submission_id(submission_id);
378*61046927SAndroid Build Coastguard Worker    });
379*61046927SAndroid Build Coastguard Worker }
380*61046927SAndroid Build Coastguard Worker 
381*61046927SAndroid Build Coastguard Worker struct tu_perfetto_clocks
tu_perfetto_submit(struct tu_device * dev,uint32_t submission_id,struct tu_perfetto_clocks * gpu_clocks)382*61046927SAndroid Build Coastguard Worker tu_perfetto_submit(struct tu_device *dev,
383*61046927SAndroid Build Coastguard Worker                    uint32_t submission_id,
384*61046927SAndroid Build Coastguard Worker                    struct tu_perfetto_clocks *gpu_clocks)
385*61046927SAndroid Build Coastguard Worker {
386*61046927SAndroid Build Coastguard Worker    struct tu_perfetto_clocks clocks {};
387*61046927SAndroid Build Coastguard Worker    if (gpu_clocks) {
388*61046927SAndroid Build Coastguard Worker       clocks = *gpu_clocks;
389*61046927SAndroid Build Coastguard Worker    }
390*61046927SAndroid Build Coastguard Worker 
391*61046927SAndroid Build Coastguard Worker    if (!u_trace_perfetto_active(tu_device_get_u_trace(dev)))
392*61046927SAndroid Build Coastguard Worker       return {};
393*61046927SAndroid Build Coastguard Worker 
394*61046927SAndroid Build Coastguard Worker    clocks.cpu = perfetto::base::GetBootTimeNs().count();
395*61046927SAndroid Build Coastguard Worker 
396*61046927SAndroid Build Coastguard Worker    if (gpu_clocks) {
397*61046927SAndroid Build Coastguard Worker       /* TODO: It would be better to use CPU time that comes
398*61046927SAndroid Build Coastguard Worker        * together with GPU time from the KGSL, but it's not
399*61046927SAndroid Build Coastguard Worker        * equal to GetBootTimeNs.
400*61046927SAndroid Build Coastguard Worker        */
401*61046927SAndroid Build Coastguard Worker 
402*61046927SAndroid Build Coastguard Worker       clocks.gpu_ts_offset = MAX2(gpu_timestamp_offset, clocks.gpu_ts_offset);
403*61046927SAndroid Build Coastguard Worker       gpu_timestamp_offset = clocks.gpu_ts_offset;
404*61046927SAndroid Build Coastguard Worker       sync_gpu_ts = clocks.gpu_ts + clocks.gpu_ts_offset;
405*61046927SAndroid Build Coastguard Worker    } else {
406*61046927SAndroid Build Coastguard Worker       clocks.gpu_ts = 0;
407*61046927SAndroid Build Coastguard Worker       clocks.gpu_ts_offset = gpu_timestamp_offset;
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker       if (clocks.cpu < next_clock_sync_ns)
410*61046927SAndroid Build Coastguard Worker          return clocks;
411*61046927SAndroid Build Coastguard Worker 
412*61046927SAndroid Build Coastguard Worker       if (tu_device_get_gpu_timestamp(dev, &clocks.gpu_ts)) {
413*61046927SAndroid Build Coastguard Worker          PERFETTO_ELOG("Could not sync CPU and GPU clocks");
414*61046927SAndroid Build Coastguard Worker          return {};
415*61046927SAndroid Build Coastguard Worker       }
416*61046927SAndroid Build Coastguard Worker 
417*61046927SAndroid Build Coastguard Worker       clocks.gpu_ts = tu_device_ticks_to_ns(dev, clocks.gpu_ts);
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker       /* get cpu timestamp again because tu_device_get_gpu_timestamp can take
420*61046927SAndroid Build Coastguard Worker        * >100us
421*61046927SAndroid Build Coastguard Worker        */
422*61046927SAndroid Build Coastguard Worker       clocks.cpu = perfetto::base::GetBootTimeNs().count();
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker       uint64_t current_suspend_count = 0;
425*61046927SAndroid Build Coastguard Worker       /* If we fail to get it we will use a fallback */
426*61046927SAndroid Build Coastguard Worker       tu_device_get_suspend_count(dev, &current_suspend_count);
427*61046927SAndroid Build Coastguard Worker 
428*61046927SAndroid Build Coastguard Worker       /* GPU timestamp is being reset after suspend-resume cycle.
429*61046927SAndroid Build Coastguard Worker        * Perfetto requires clock snapshots to be monotonic,
430*61046927SAndroid Build Coastguard Worker        * so we have to fix-up the time.
431*61046927SAndroid Build Coastguard Worker        */
432*61046927SAndroid Build Coastguard Worker       if (current_suspend_count != last_suspend_count) {
433*61046927SAndroid Build Coastguard Worker          gpu_timestamp_offset = gpu_max_timestamp;
434*61046927SAndroid Build Coastguard Worker          last_suspend_count = current_suspend_count;
435*61046927SAndroid Build Coastguard Worker       }
436*61046927SAndroid Build Coastguard Worker       clocks.gpu_ts_offset = gpu_timestamp_offset;
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker       uint64_t gpu_absolute_ts = clocks.gpu_ts + clocks.gpu_ts_offset;
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker       /* Fallback check, detect non-monotonic cases which would happen
441*61046927SAndroid Build Coastguard Worker        * if we cannot retrieve suspend count.
442*61046927SAndroid Build Coastguard Worker        */
443*61046927SAndroid Build Coastguard Worker       if (sync_gpu_ts > gpu_absolute_ts) {
444*61046927SAndroid Build Coastguard Worker          gpu_absolute_ts += (gpu_max_timestamp - gpu_timestamp_offset);
445*61046927SAndroid Build Coastguard Worker          gpu_timestamp_offset = gpu_max_timestamp;
446*61046927SAndroid Build Coastguard Worker          clocks.gpu_ts = gpu_absolute_ts - gpu_timestamp_offset;
447*61046927SAndroid Build Coastguard Worker       }
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker       if (sync_gpu_ts > gpu_absolute_ts) {
450*61046927SAndroid Build Coastguard Worker          PERFETTO_ELOG("Non-monotonic gpu timestamp detected, bailing out");
451*61046927SAndroid Build Coastguard Worker          return {};
452*61046927SAndroid Build Coastguard Worker       }
453*61046927SAndroid Build Coastguard Worker 
454*61046927SAndroid Build Coastguard Worker       gpu_max_timestamp = clocks.gpu_ts;
455*61046927SAndroid Build Coastguard Worker       sync_gpu_ts = clocks.gpu_ts;
456*61046927SAndroid Build Coastguard Worker       next_clock_sync_ns = clocks.cpu + 30000000;
457*61046927SAndroid Build Coastguard Worker    }
458*61046927SAndroid Build Coastguard Worker 
459*61046927SAndroid Build Coastguard Worker    emit_sync_timestamp(clocks.cpu, clocks.gpu_ts + clocks.gpu_ts_offset);
460*61046927SAndroid Build Coastguard Worker    emit_submit_id(submission_id);
461*61046927SAndroid Build Coastguard Worker    return clocks;
462*61046927SAndroid Build Coastguard Worker }
463*61046927SAndroid Build Coastguard Worker 
464*61046927SAndroid Build Coastguard Worker /*
465*61046927SAndroid Build Coastguard Worker  * Trace callbacks, called from u_trace once the timestamps from GPU have been
466*61046927SAndroid Build Coastguard Worker  * collected.
467*61046927SAndroid Build Coastguard Worker  *
468*61046927SAndroid Build Coastguard Worker  * The default "extra" funcs are code-generated into tu_tracepoints_perfetto.h
469*61046927SAndroid Build Coastguard Worker  * and just take the tracepoint's args and add them as name/value pairs in the
470*61046927SAndroid Build Coastguard Worker  * perfetto events.  This file can usually just map a tu_perfetto_* to
471*61046927SAndroid Build Coastguard Worker  * stage_start/end with a call to that codegenned "extra" func.  But you can
472*61046927SAndroid Build Coastguard Worker  * also provide your own entrypoint and extra funcs if you want to change that
473*61046927SAndroid Build Coastguard Worker  * mapping.
474*61046927SAndroid Build Coastguard Worker  */
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker #define CREATE_EVENT_CALLBACK(event_name, stage_id)                                 \
477*61046927SAndroid Build Coastguard Worker    void tu_perfetto_start_##event_name(                                             \
478*61046927SAndroid Build Coastguard Worker       struct tu_device *dev, uint64_t ts_ns, uint16_t tp_idx,                       \
479*61046927SAndroid Build Coastguard Worker       const void *flush_data, const struct trace_start_##event_name *payload,       \
480*61046927SAndroid Build Coastguard Worker       const void *indirect_data)                                                    \
481*61046927SAndroid Build Coastguard Worker    {                                                                                \
482*61046927SAndroid Build Coastguard Worker       stage_start(                                                                  \
483*61046927SAndroid Build Coastguard Worker          dev, ts_ns, stage_id, NULL, payload, sizeof(*payload),                     \
484*61046927SAndroid Build Coastguard Worker          (trace_payload_as_extra_func) &trace_payload_as_extra_start_##event_name); \
485*61046927SAndroid Build Coastguard Worker    }                                                                                \
486*61046927SAndroid Build Coastguard Worker                                                                                     \
487*61046927SAndroid Build Coastguard Worker    void tu_perfetto_end_##event_name(                                               \
488*61046927SAndroid Build Coastguard Worker       struct tu_device *dev, uint64_t ts_ns, uint16_t tp_idx,                       \
489*61046927SAndroid Build Coastguard Worker       const void *flush_data, const struct trace_end_##event_name *payload,         \
490*61046927SAndroid Build Coastguard Worker       const void *indirect_data)                                                    \
491*61046927SAndroid Build Coastguard Worker    {                                                                                \
492*61046927SAndroid Build Coastguard Worker       stage_end(                                                                    \
493*61046927SAndroid Build Coastguard Worker          dev, ts_ns, stage_id, flush_data, payload,                                 \
494*61046927SAndroid Build Coastguard Worker          (trace_payload_as_extra_func) &trace_payload_as_extra_end_##event_name);   \
495*61046927SAndroid Build Coastguard Worker    }
496*61046927SAndroid Build Coastguard Worker 
CREATE_EVENT_CALLBACK(cmd_buffer,CMD_BUFFER_STAGE_ID)497*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(cmd_buffer, CMD_BUFFER_STAGE_ID)
498*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(render_pass, RENDER_PASS_STAGE_ID)
499*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(binning_ib, BINNING_STAGE_ID)
500*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(draw_ib_gmem, GMEM_STAGE_ID)
501*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(draw_ib_sysmem, BYPASS_STAGE_ID)
502*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(blit, BLIT_STAGE_ID)
503*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(compute, COMPUTE_STAGE_ID)
504*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(compute_indirect, COMPUTE_STAGE_ID)
505*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(generic_clear, GENERIC_CLEAR_STAGE_ID)
506*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(gmem_clear, CLEAR_GMEM_STAGE_ID)
507*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(sysmem_clear, CLEAR_SYSMEM_STAGE_ID)
508*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(sysmem_clear_all, CLEAR_SYSMEM_STAGE_ID)
509*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(gmem_load, GMEM_LOAD_STAGE_ID)
510*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(gmem_store, GMEM_STORE_STAGE_ID)
511*61046927SAndroid Build Coastguard Worker CREATE_EVENT_CALLBACK(sysmem_resolve, SYSMEM_RESOLVE_STAGE_ID)
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker void
514*61046927SAndroid Build Coastguard Worker tu_perfetto_start_cmd_buffer_annotation(
515*61046927SAndroid Build Coastguard Worker    struct tu_device *dev,
516*61046927SAndroid Build Coastguard Worker    uint64_t ts_ns,
517*61046927SAndroid Build Coastguard Worker    uint16_t tp_idx,
518*61046927SAndroid Build Coastguard Worker    const void *flush_data,
519*61046927SAndroid Build Coastguard Worker    const struct trace_start_cmd_buffer_annotation *payload,
520*61046927SAndroid Build Coastguard Worker    const void *indirect_data)
521*61046927SAndroid Build Coastguard Worker {
522*61046927SAndroid Build Coastguard Worker    /* No extra func necessary, the only arg is in the end payload.*/
523*61046927SAndroid Build Coastguard Worker    stage_start(dev, ts_ns, CMD_BUFFER_ANNOTATION_STAGE_ID, payload->str, payload,
524*61046927SAndroid Build Coastguard Worker                sizeof(*payload), NULL);
525*61046927SAndroid Build Coastguard Worker }
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker void
tu_perfetto_end_cmd_buffer_annotation(struct tu_device * dev,uint64_t ts_ns,uint16_t tp_idx,const void * flush_data,const struct trace_end_cmd_buffer_annotation * payload,const void * indirect_data)528*61046927SAndroid Build Coastguard Worker tu_perfetto_end_cmd_buffer_annotation(
529*61046927SAndroid Build Coastguard Worker    struct tu_device *dev,
530*61046927SAndroid Build Coastguard Worker    uint64_t ts_ns,
531*61046927SAndroid Build Coastguard Worker    uint16_t tp_idx,
532*61046927SAndroid Build Coastguard Worker    const void *flush_data,
533*61046927SAndroid Build Coastguard Worker    const struct trace_end_cmd_buffer_annotation *payload,
534*61046927SAndroid Build Coastguard Worker    const void *indirect_data)
535*61046927SAndroid Build Coastguard Worker {
536*61046927SAndroid Build Coastguard Worker    /* Pass the payload string as the app_event, which will appear right on the
537*61046927SAndroid Build Coastguard Worker     * event block, rather than as metadata inside.
538*61046927SAndroid Build Coastguard Worker     */
539*61046927SAndroid Build Coastguard Worker    stage_end(dev, ts_ns, CMD_BUFFER_ANNOTATION_STAGE_ID, flush_data,
540*61046927SAndroid Build Coastguard Worker              payload, NULL);
541*61046927SAndroid Build Coastguard Worker }
542*61046927SAndroid Build Coastguard Worker 
543*61046927SAndroid Build Coastguard Worker void
tu_perfetto_start_cmd_buffer_annotation_rp(struct tu_device * dev,uint64_t ts_ns,uint16_t tp_idx,const void * flush_data,const struct trace_start_cmd_buffer_annotation_rp * payload,const void * indirect_data)544*61046927SAndroid Build Coastguard Worker tu_perfetto_start_cmd_buffer_annotation_rp(
545*61046927SAndroid Build Coastguard Worker    struct tu_device *dev,
546*61046927SAndroid Build Coastguard Worker    uint64_t ts_ns,
547*61046927SAndroid Build Coastguard Worker    uint16_t tp_idx,
548*61046927SAndroid Build Coastguard Worker    const void *flush_data,
549*61046927SAndroid Build Coastguard Worker    const struct trace_start_cmd_buffer_annotation_rp *payload,
550*61046927SAndroid Build Coastguard Worker    const void *indirect_data)
551*61046927SAndroid Build Coastguard Worker {
552*61046927SAndroid Build Coastguard Worker    /* No extra func necessary, the only arg is in the end payload.*/
553*61046927SAndroid Build Coastguard Worker    stage_start(dev, ts_ns, CMD_BUFFER_ANNOTATION_RENDER_PASS_STAGE_ID,
554*61046927SAndroid Build Coastguard Worker                payload->str, payload, sizeof(*payload), NULL);
555*61046927SAndroid Build Coastguard Worker }
556*61046927SAndroid Build Coastguard Worker 
557*61046927SAndroid Build Coastguard Worker void
tu_perfetto_end_cmd_buffer_annotation_rp(struct tu_device * dev,uint64_t ts_ns,uint16_t tp_idx,const void * flush_data,const struct trace_end_cmd_buffer_annotation_rp * payload,const void * indirect_data)558*61046927SAndroid Build Coastguard Worker tu_perfetto_end_cmd_buffer_annotation_rp(
559*61046927SAndroid Build Coastguard Worker    struct tu_device *dev,
560*61046927SAndroid Build Coastguard Worker    uint64_t ts_ns,
561*61046927SAndroid Build Coastguard Worker    uint16_t tp_idx,
562*61046927SAndroid Build Coastguard Worker    const void *flush_data,
563*61046927SAndroid Build Coastguard Worker    const struct trace_end_cmd_buffer_annotation_rp *payload,
564*61046927SAndroid Build Coastguard Worker    const void *indirect_data)
565*61046927SAndroid Build Coastguard Worker {
566*61046927SAndroid Build Coastguard Worker    /* Pass the payload string as the app_event, which will appear right on the
567*61046927SAndroid Build Coastguard Worker     * event block, rather than as metadata inside.
568*61046927SAndroid Build Coastguard Worker     */
569*61046927SAndroid Build Coastguard Worker    stage_end(dev, ts_ns, CMD_BUFFER_ANNOTATION_RENDER_PASS_STAGE_ID,
570*61046927SAndroid Build Coastguard Worker              flush_data, payload, NULL);
571*61046927SAndroid Build Coastguard Worker }
572*61046927SAndroid Build Coastguard Worker 
573*61046927SAndroid Build Coastguard Worker 
574*61046927SAndroid Build Coastguard Worker static void
log_mem(struct tu_device * dev,struct tu_buffer * buffer,struct tu_image * image,perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::Operation op)575*61046927SAndroid Build Coastguard Worker log_mem(struct tu_device *dev, struct tu_buffer *buffer, struct tu_image *image,
576*61046927SAndroid Build Coastguard Worker         perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::Operation op)
577*61046927SAndroid Build Coastguard Worker {
578*61046927SAndroid Build Coastguard Worker    TuMemoryDataSource::Trace([=](TuMemoryDataSource::TraceContext tctx) {
579*61046927SAndroid Build Coastguard Worker       auto packet = tctx.NewTracePacket();
580*61046927SAndroid Build Coastguard Worker 
581*61046927SAndroid Build Coastguard Worker       packet->set_timestamp(perfetto::base::GetBootTimeNs().count());
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker       auto event = packet->set_vulkan_memory_event();
584*61046927SAndroid Build Coastguard Worker 
585*61046927SAndroid Build Coastguard Worker       event->set_timestamp(perfetto::base::GetBootTimeNs().count());
586*61046927SAndroid Build Coastguard Worker       event->set_operation(op);
587*61046927SAndroid Build Coastguard Worker       event->set_pid(getpid());
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker       if (buffer) {
590*61046927SAndroid Build Coastguard Worker          event->set_source(perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::SOURCE_BUFFER);
591*61046927SAndroid Build Coastguard Worker          event->set_memory_size(buffer->vk.size);
592*61046927SAndroid Build Coastguard Worker          if (buffer->bo)
593*61046927SAndroid Build Coastguard Worker             event->set_memory_address(buffer->iova);
594*61046927SAndroid Build Coastguard Worker       } else {
595*61046927SAndroid Build Coastguard Worker          assert(image);
596*61046927SAndroid Build Coastguard Worker          event->set_source(perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::SOURCE_IMAGE);
597*61046927SAndroid Build Coastguard Worker          event->set_memory_size(image->layout[0].size);
598*61046927SAndroid Build Coastguard Worker          if (image->bo)
599*61046927SAndroid Build Coastguard Worker             event->set_memory_address(image->iova);
600*61046927SAndroid Build Coastguard Worker       }
601*61046927SAndroid Build Coastguard Worker 
602*61046927SAndroid Build Coastguard Worker    });
603*61046927SAndroid Build Coastguard Worker }
604*61046927SAndroid Build Coastguard Worker 
605*61046927SAndroid Build Coastguard Worker void
tu_perfetto_log_create_buffer(struct tu_device * dev,struct tu_buffer * buffer)606*61046927SAndroid Build Coastguard Worker tu_perfetto_log_create_buffer(struct tu_device *dev, struct tu_buffer *buffer)
607*61046927SAndroid Build Coastguard Worker {
608*61046927SAndroid Build Coastguard Worker    log_mem(dev, buffer, NULL, perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::OP_CREATE);
609*61046927SAndroid Build Coastguard Worker }
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker void
tu_perfetto_log_bind_buffer(struct tu_device * dev,struct tu_buffer * buffer)612*61046927SAndroid Build Coastguard Worker tu_perfetto_log_bind_buffer(struct tu_device *dev, struct tu_buffer *buffer)
613*61046927SAndroid Build Coastguard Worker {
614*61046927SAndroid Build Coastguard Worker    log_mem(dev, buffer, NULL, perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::OP_BIND);
615*61046927SAndroid Build Coastguard Worker }
616*61046927SAndroid Build Coastguard Worker 
617*61046927SAndroid Build Coastguard Worker void
tu_perfetto_log_destroy_buffer(struct tu_device * dev,struct tu_buffer * buffer)618*61046927SAndroid Build Coastguard Worker tu_perfetto_log_destroy_buffer(struct tu_device *dev, struct tu_buffer *buffer)
619*61046927SAndroid Build Coastguard Worker {
620*61046927SAndroid Build Coastguard Worker    log_mem(dev, buffer, NULL, buffer->bo ?
621*61046927SAndroid Build Coastguard Worker       perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::OP_DESTROY_BOUND :
622*61046927SAndroid Build Coastguard Worker       perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::OP_DESTROY);
623*61046927SAndroid Build Coastguard Worker }
624*61046927SAndroid Build Coastguard Worker 
625*61046927SAndroid Build Coastguard Worker void
tu_perfetto_log_create_image(struct tu_device * dev,struct tu_image * image)626*61046927SAndroid Build Coastguard Worker tu_perfetto_log_create_image(struct tu_device *dev, struct tu_image *image)
627*61046927SAndroid Build Coastguard Worker {
628*61046927SAndroid Build Coastguard Worker    log_mem(dev, NULL, image, perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::OP_CREATE);
629*61046927SAndroid Build Coastguard Worker }
630*61046927SAndroid Build Coastguard Worker 
631*61046927SAndroid Build Coastguard Worker void
tu_perfetto_log_bind_image(struct tu_device * dev,struct tu_image * image)632*61046927SAndroid Build Coastguard Worker tu_perfetto_log_bind_image(struct tu_device *dev, struct tu_image *image)
633*61046927SAndroid Build Coastguard Worker {
634*61046927SAndroid Build Coastguard Worker    log_mem(dev, NULL, image, perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::OP_BIND);
635*61046927SAndroid Build Coastguard Worker }
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker void
tu_perfetto_log_destroy_image(struct tu_device * dev,struct tu_image * image)638*61046927SAndroid Build Coastguard Worker tu_perfetto_log_destroy_image(struct tu_device *dev, struct tu_image *image)
639*61046927SAndroid Build Coastguard Worker {
640*61046927SAndroid Build Coastguard Worker    log_mem(dev, NULL, image, image->bo ?
641*61046927SAndroid Build Coastguard Worker       perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::OP_DESTROY_BOUND :
642*61046927SAndroid Build Coastguard Worker       perfetto::protos::pbzero::perfetto_pbzero_enum_VulkanMemoryEvent::OP_DESTROY);
643*61046927SAndroid Build Coastguard Worker }
644*61046927SAndroid Build Coastguard Worker 
645*61046927SAndroid Build Coastguard Worker 
646*61046927SAndroid Build Coastguard Worker 
647*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
648*61046927SAndroid Build Coastguard Worker }
649*61046927SAndroid Build Coastguard Worker #endif
650