17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2021 Google, Inc.
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
217ec681f3Smrg * SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include <perfetto.h>
257ec681f3Smrg
267ec681f3Smrg#include "util/u_perfetto.h"
277ec681f3Smrg
287ec681f3Smrg#include "freedreno_tracepoints.h"
297ec681f3Smrg
307ec681f3Smrgstatic uint32_t gpu_clock_id;
317ec681f3Smrgstatic uint64_t next_clock_sync_ns; /* cpu time of next clk sync */
327ec681f3Smrg
337ec681f3Smrg/**
347ec681f3Smrg * The timestamp at the point where we first emitted the clock_sync..
357ec681f3Smrg * this  will be a *later* timestamp that the first GPU traces (since
367ec681f3Smrg * we capture the first clock_sync from the CPU *after* the first GPU
377ec681f3Smrg * tracepoints happen).  To avoid confusing perfetto we need to drop
387ec681f3Smrg * the GPU traces with timestamps before this.
397ec681f3Smrg */
407ec681f3Smrgstatic uint64_t sync_gpu_ts;
417ec681f3Smrg
427ec681f3Smrgstruct FdRenderpassIncrementalState {
437ec681f3Smrg   bool was_cleared = true;
447ec681f3Smrg};
457ec681f3Smrg
467ec681f3Smrgstruct FdRenderpassTraits : public perfetto::DefaultDataSourceTraits {
477ec681f3Smrg   using IncrementalStateType = FdRenderpassIncrementalState;
487ec681f3Smrg};
497ec681f3Smrg
507ec681f3Smrgclass FdRenderpassDataSource : public perfetto::DataSource<FdRenderpassDataSource, FdRenderpassTraits> {
517ec681f3Smrgpublic:
527ec681f3Smrg   void OnSetup(const SetupArgs &) override
537ec681f3Smrg   {
547ec681f3Smrg      // Use this callback to apply any custom configuration to your data source
557ec681f3Smrg      // based on the TraceConfig in SetupArgs.
567ec681f3Smrg   }
577ec681f3Smrg
587ec681f3Smrg   void OnStart(const StartArgs &) override
597ec681f3Smrg   {
607ec681f3Smrg      // This notification can be used to initialize the GPU driver, enable
617ec681f3Smrg      // counters, etc. StartArgs will contains the DataSourceDescriptor,
627ec681f3Smrg      // which can be extended.
637ec681f3Smrg      u_trace_perfetto_start();
647ec681f3Smrg      PERFETTO_LOG("Tracing started");
657ec681f3Smrg
667ec681f3Smrg      /* Note: clock_id's below 128 are reserved.. for custom clock sources,
677ec681f3Smrg       * using the hash of a namespaced string is the recommended approach.
687ec681f3Smrg       * See: https://perfetto.dev/docs/concepts/clock-sync
697ec681f3Smrg       */
707ec681f3Smrg      gpu_clock_id =
717ec681f3Smrg         _mesa_hash_string("org.freedesktop.mesa.freedreno") | 0x80000000;
727ec681f3Smrg   }
737ec681f3Smrg
747ec681f3Smrg   void OnStop(const StopArgs &) override
757ec681f3Smrg   {
767ec681f3Smrg      PERFETTO_LOG("Tracing stopped");
777ec681f3Smrg
787ec681f3Smrg      // Undo any initialization done in OnStart.
797ec681f3Smrg      u_trace_perfetto_stop();
807ec681f3Smrg      // TODO we should perhaps block until queued traces are flushed?
817ec681f3Smrg
827ec681f3Smrg      Trace([](FdRenderpassDataSource::TraceContext ctx) {
837ec681f3Smrg         auto packet = ctx.NewTracePacket();
847ec681f3Smrg         packet->Finalize();
857ec681f3Smrg         ctx.Flush();
867ec681f3Smrg      });
877ec681f3Smrg   }
887ec681f3Smrg};
897ec681f3Smrg
907ec681f3SmrgPERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(FdRenderpassDataSource);
917ec681f3SmrgPERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(FdRenderpassDataSource);
927ec681f3Smrg
937ec681f3Smrgstatic void
947ec681f3Smrgsend_descriptors(FdRenderpassDataSource::TraceContext &ctx, uint64_t ts_ns)
957ec681f3Smrg{
967ec681f3Smrg   PERFETTO_LOG("Sending renderstage descriptors");
977ec681f3Smrg
987ec681f3Smrg   auto packet = ctx.NewTracePacket();
997ec681f3Smrg
1007ec681f3Smrg   packet->set_timestamp(0);
1017ec681f3Smrg//   packet->set_timestamp(ts_ns);
1027ec681f3Smrg//   packet->set_timestamp_clock_id(gpu_clock_id);
1037ec681f3Smrg
1047ec681f3Smrg   auto event = packet->set_gpu_render_stage_event();
1057ec681f3Smrg   event->set_gpu_id(0);
1067ec681f3Smrg
1077ec681f3Smrg   auto spec = event->set_specifications();
1087ec681f3Smrg
1097ec681f3Smrg   for (unsigned i = 0; i < ARRAY_SIZE(queues); i++) {
1107ec681f3Smrg      auto desc = spec->add_hw_queue();
1117ec681f3Smrg
1127ec681f3Smrg      desc->set_name(queues[i].name);
1137ec681f3Smrg      desc->set_description(queues[i].desc);
1147ec681f3Smrg   }
1157ec681f3Smrg
1167ec681f3Smrg   for (unsigned i = 0; i < ARRAY_SIZE(stages); i++) {
1177ec681f3Smrg      auto desc = spec->add_stage();
1187ec681f3Smrg
1197ec681f3Smrg      desc->set_name(stages[i].name);
1207ec681f3Smrg      if (stages[i].desc)
1217ec681f3Smrg         desc->set_description(stages[i].desc);
1227ec681f3Smrg   }
1237ec681f3Smrg}
1247ec681f3Smrg
1257ec681f3Smrgstatic void
1267ec681f3Smrgstage_start(struct pipe_context *pctx, uint64_t ts_ns, enum fd_stage_id stage)
1277ec681f3Smrg{
1287ec681f3Smrg   struct fd_context *ctx = fd_context(pctx);
1297ec681f3Smrg   struct fd_perfetto_state *p = &ctx->perfetto;
1307ec681f3Smrg
1317ec681f3Smrg   p->start_ts[stage] = ts_ns;
1327ec681f3Smrg}
1337ec681f3Smrg
1347ec681f3Smrgstatic void
1357ec681f3Smrgstage_end(struct pipe_context *pctx, uint64_t ts_ns, enum fd_stage_id stage)
1367ec681f3Smrg{
1377ec681f3Smrg   struct fd_context *ctx = fd_context(pctx);
1387ec681f3Smrg   struct fd_perfetto_state *p = &ctx->perfetto;
1397ec681f3Smrg
1407ec681f3Smrg   /* If we haven't managed to calibrate the alignment between GPU and CPU
1417ec681f3Smrg    * timestamps yet, then skip this trace, otherwise perfetto won't know
1427ec681f3Smrg    * what to do with it.
1437ec681f3Smrg    */
1447ec681f3Smrg   if (!sync_gpu_ts)
1457ec681f3Smrg      return;
1467ec681f3Smrg
1477ec681f3Smrg   FdRenderpassDataSource::Trace([=](FdRenderpassDataSource::TraceContext tctx) {
1487ec681f3Smrg      if (auto state = tctx.GetIncrementalState(); state->was_cleared) {
1497ec681f3Smrg         send_descriptors(tctx, p->start_ts[stage]);
1507ec681f3Smrg         state->was_cleared = false;
1517ec681f3Smrg      }
1527ec681f3Smrg
1537ec681f3Smrg      auto packet = tctx.NewTracePacket();
1547ec681f3Smrg
1557ec681f3Smrg      packet->set_timestamp(p->start_ts[stage]);
1567ec681f3Smrg      packet->set_timestamp_clock_id(gpu_clock_id);
1577ec681f3Smrg
1587ec681f3Smrg      auto event = packet->set_gpu_render_stage_event();
1597ec681f3Smrg      event->set_event_id(0); // ???
1607ec681f3Smrg      event->set_hw_queue_id(DEFAULT_HW_QUEUE_ID);
1617ec681f3Smrg      event->set_duration(ts_ns - p->start_ts[stage]);
1627ec681f3Smrg      event->set_stage_id(stage);
1637ec681f3Smrg      event->set_context((uintptr_t)pctx);
1647ec681f3Smrg
1657ec681f3Smrg      /* The "surface" meta-stage has extra info about render target: */
1667ec681f3Smrg      if (stage == SURFACE_STAGE_ID) {
1677ec681f3Smrg
1687ec681f3Smrg         event->set_submission_id(p->submit_id);
1697ec681f3Smrg
1707ec681f3Smrg         if (p->cbuf0_format) {
1717ec681f3Smrg            auto data = event->add_extra_data();
1727ec681f3Smrg
1737ec681f3Smrg            data->set_name("color0 format");
1747ec681f3Smrg            data->set_value(util_format_short_name(p->cbuf0_format));
1757ec681f3Smrg         }
1767ec681f3Smrg
1777ec681f3Smrg         if (p->zs_format) {
1787ec681f3Smrg            auto data = event->add_extra_data();
1797ec681f3Smrg
1807ec681f3Smrg            data->set_name("zs format");
1817ec681f3Smrg            data->set_value(util_format_short_name(p->zs_format));
1827ec681f3Smrg         }
1837ec681f3Smrg
1847ec681f3Smrg         {
1857ec681f3Smrg            auto data = event->add_extra_data();
1867ec681f3Smrg
1877ec681f3Smrg            data->set_name("width");
1887ec681f3Smrg            data->set_value(std::to_string(p->width));
1897ec681f3Smrg         }
1907ec681f3Smrg
1917ec681f3Smrg         {
1927ec681f3Smrg            auto data = event->add_extra_data();
1937ec681f3Smrg
1947ec681f3Smrg            data->set_name("height");
1957ec681f3Smrg            data->set_value(std::to_string(p->height));
1967ec681f3Smrg         }
1977ec681f3Smrg
1987ec681f3Smrg         {
1997ec681f3Smrg            auto data = event->add_extra_data();
2007ec681f3Smrg
2017ec681f3Smrg            data->set_name("MSAA");
2027ec681f3Smrg            data->set_value(std::to_string(p->samples));
2037ec681f3Smrg         }
2047ec681f3Smrg
2057ec681f3Smrg         {
2067ec681f3Smrg            auto data = event->add_extra_data();
2077ec681f3Smrg
2087ec681f3Smrg            data->set_name("MRTs");
2097ec681f3Smrg            data->set_value(std::to_string(p->mrts));
2107ec681f3Smrg         }
2117ec681f3Smrg
2127ec681f3Smrg         // "renderMode"
2137ec681f3Smrg         // "surfaceID"
2147ec681f3Smrg
2157ec681f3Smrg         if (p->nbins) {
2167ec681f3Smrg            auto data = event->add_extra_data();
2177ec681f3Smrg
2187ec681f3Smrg            data->set_name("numberOfBins");
2197ec681f3Smrg            data->set_value(std::to_string(p->nbins));
2207ec681f3Smrg         }
2217ec681f3Smrg
2227ec681f3Smrg         if (p->binw) {
2237ec681f3Smrg            auto data = event->add_extra_data();
2247ec681f3Smrg
2257ec681f3Smrg            data->set_name("binWidth");
2267ec681f3Smrg            data->set_value(std::to_string(p->binw));
2277ec681f3Smrg         }
2287ec681f3Smrg
2297ec681f3Smrg         if (p->binh) {
2307ec681f3Smrg            auto data = event->add_extra_data();
2317ec681f3Smrg
2327ec681f3Smrg            data->set_name("binHeight");
2337ec681f3Smrg            data->set_value(std::to_string(p->binh));
2347ec681f3Smrg         }
2357ec681f3Smrg      }
2367ec681f3Smrg   });
2377ec681f3Smrg}
2387ec681f3Smrg
2397ec681f3Smrg#ifdef __cplusplus
2407ec681f3Smrgextern "C" {
2417ec681f3Smrg#endif
2427ec681f3Smrg
2437ec681f3Smrgvoid
2447ec681f3Smrgfd_perfetto_init(void)
2457ec681f3Smrg{
2467ec681f3Smrg   util_perfetto_init();
2477ec681f3Smrg
2487ec681f3Smrg   perfetto::DataSourceDescriptor dsd;
2497ec681f3Smrg   dsd.set_name("gpu.renderstages.msm");
2507ec681f3Smrg   FdRenderpassDataSource::Register(dsd);
2517ec681f3Smrg}
2527ec681f3Smrg
2537ec681f3Smrgstatic void
2547ec681f3Smrgsync_timestamp(struct fd_context *ctx)
2557ec681f3Smrg{
2567ec681f3Smrg   uint64_t cpu_ts = perfetto::base::GetBootTimeNs().count();
2577ec681f3Smrg   uint64_t gpu_ts;
2587ec681f3Smrg
2597ec681f3Smrg   if (cpu_ts < next_clock_sync_ns)
2607ec681f3Smrg      return;
2617ec681f3Smrg
2627ec681f3Smrg   if (fd_pipe_get_param(ctx->pipe, FD_TIMESTAMP, &gpu_ts)) {
2637ec681f3Smrg      PERFETTO_ELOG("Could not sync CPU and GPU clocks");
2647ec681f3Smrg      return;
2657ec681f3Smrg   }
2667ec681f3Smrg
2677ec681f3Smrg   /* convert GPU ts into ns: */
2687ec681f3Smrg   gpu_ts = ctx->ts_to_ns(gpu_ts);
2697ec681f3Smrg
2707ec681f3Smrg   FdRenderpassDataSource::Trace([=](FdRenderpassDataSource::TraceContext tctx) {
2717ec681f3Smrg      auto packet = tctx.NewTracePacket();
2727ec681f3Smrg
2737ec681f3Smrg      packet->set_timestamp(cpu_ts);
2747ec681f3Smrg
2757ec681f3Smrg      auto event = packet->set_clock_snapshot();
2767ec681f3Smrg
2777ec681f3Smrg      {
2787ec681f3Smrg         auto clock = event->add_clocks();
2797ec681f3Smrg
2807ec681f3Smrg         clock->set_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
2817ec681f3Smrg         clock->set_timestamp(cpu_ts);
2827ec681f3Smrg      }
2837ec681f3Smrg
2847ec681f3Smrg      {
2857ec681f3Smrg         auto clock = event->add_clocks();
2867ec681f3Smrg
2877ec681f3Smrg         clock->set_clock_id(gpu_clock_id);
2887ec681f3Smrg         clock->set_timestamp(gpu_ts);
2897ec681f3Smrg      }
2907ec681f3Smrg
2917ec681f3Smrg      sync_gpu_ts = gpu_ts;
2927ec681f3Smrg      next_clock_sync_ns = cpu_ts + 30000000;
2937ec681f3Smrg   });
2947ec681f3Smrg}
2957ec681f3Smrg
2967ec681f3Smrgstatic void
2977ec681f3Smrgemit_submit_id(struct fd_context *ctx)
2987ec681f3Smrg{
2997ec681f3Smrg   FdRenderpassDataSource::Trace([=](FdRenderpassDataSource::TraceContext tctx) {
3007ec681f3Smrg      auto packet = tctx.NewTracePacket();
3017ec681f3Smrg
3027ec681f3Smrg      packet->set_timestamp(perfetto::base::GetBootTimeNs().count());
3037ec681f3Smrg
3047ec681f3Smrg      auto event = packet->set_vulkan_api_event();
3057ec681f3Smrg      auto submit = event->set_vk_queue_submit();
3067ec681f3Smrg
3077ec681f3Smrg      submit->set_submission_id(ctx->submit_count);
3087ec681f3Smrg   });
3097ec681f3Smrg}
3107ec681f3Smrg
3117ec681f3Smrgvoid
3127ec681f3Smrgfd_perfetto_submit(struct fd_context *ctx)
3137ec681f3Smrg{
3147ec681f3Smrg   sync_timestamp(ctx);
3157ec681f3Smrg   emit_submit_id(ctx);
3167ec681f3Smrg}
3177ec681f3Smrg
3187ec681f3Smrg/*
3197ec681f3Smrg * Trace callbacks, called from u_trace once the timestamps from GPU have been
3207ec681f3Smrg * collected.
3217ec681f3Smrg */
3227ec681f3Smrg
3237ec681f3Smrgvoid
3247ec681f3Smrgfd_start_render_pass(struct pipe_context *pctx, uint64_t ts_ns,
3257ec681f3Smrg                     const void *flush_data,
3267ec681f3Smrg                     const struct trace_start_render_pass *payload)
3277ec681f3Smrg{
3287ec681f3Smrg   stage_start(pctx, ts_ns, SURFACE_STAGE_ID);
3297ec681f3Smrg
3307ec681f3Smrg   struct fd_perfetto_state *p = &fd_context(pctx)->perfetto;
3317ec681f3Smrg
3327ec681f3Smrg   p->submit_id = payload->submit_id;
3337ec681f3Smrg   p->cbuf0_format = payload->cbuf0_format;
3347ec681f3Smrg   p->zs_format = payload->zs_format;
3357ec681f3Smrg   p->width = payload->width;
3367ec681f3Smrg   p->height = payload->height;
3377ec681f3Smrg   p->mrts = payload->mrts;
3387ec681f3Smrg   p->samples = payload->samples;
3397ec681f3Smrg   p->nbins = payload->nbins;
3407ec681f3Smrg   p->binw = payload->binw;
3417ec681f3Smrg   p->binh = payload->binh;
3427ec681f3Smrg}
3437ec681f3Smrg
3447ec681f3Smrgvoid
3457ec681f3Smrgfd_end_render_pass(struct pipe_context *pctx, uint64_t ts_ns,
3467ec681f3Smrg                   const void *flush_data,
3477ec681f3Smrg                   const struct trace_end_render_pass *payload)
3487ec681f3Smrg{
3497ec681f3Smrg   stage_end(pctx, ts_ns, SURFACE_STAGE_ID);
3507ec681f3Smrg}
3517ec681f3Smrg
3527ec681f3Smrgvoid
3537ec681f3Smrgfd_start_binning_ib(struct pipe_context *pctx, uint64_t ts_ns,
3547ec681f3Smrg                    const void *flush_data,
3557ec681f3Smrg                    const struct trace_start_binning_ib *payload)
3567ec681f3Smrg{
3577ec681f3Smrg   stage_start(pctx, ts_ns, BINNING_STAGE_ID);
3587ec681f3Smrg}
3597ec681f3Smrg
3607ec681f3Smrgvoid
3617ec681f3Smrgfd_end_binning_ib(struct pipe_context *pctx, uint64_t ts_ns,
3627ec681f3Smrg                  const void *flush_data,
3637ec681f3Smrg                  const struct trace_end_binning_ib *payload)
3647ec681f3Smrg{
3657ec681f3Smrg   stage_end(pctx, ts_ns, BINNING_STAGE_ID);
3667ec681f3Smrg}
3677ec681f3Smrg
3687ec681f3Smrgvoid
3697ec681f3Smrgfd_start_draw_ib(struct pipe_context *pctx, uint64_t ts_ns,
3707ec681f3Smrg                 const void *flush_data,
3717ec681f3Smrg                 const struct trace_start_draw_ib *payload)
3727ec681f3Smrg{
3737ec681f3Smrg   stage_start(
3747ec681f3Smrg      pctx, ts_ns,
3757ec681f3Smrg      fd_context(pctx)->perfetto.nbins ? GMEM_STAGE_ID : BYPASS_STAGE_ID);
3767ec681f3Smrg}
3777ec681f3Smrg
3787ec681f3Smrgvoid
3797ec681f3Smrgfd_end_draw_ib(struct pipe_context *pctx, uint64_t ts_ns,
3807ec681f3Smrg               const void *flush_data,
3817ec681f3Smrg               const struct trace_end_draw_ib *payload)
3827ec681f3Smrg{
3837ec681f3Smrg   stage_end(
3847ec681f3Smrg      pctx, ts_ns,
3857ec681f3Smrg      fd_context(pctx)->perfetto.nbins ? GMEM_STAGE_ID : BYPASS_STAGE_ID);
3867ec681f3Smrg}
3877ec681f3Smrg
3887ec681f3Smrgvoid
3897ec681f3Smrgfd_start_blit(struct pipe_context *pctx, uint64_t ts_ns,
3907ec681f3Smrg              const void *flush_data,
3917ec681f3Smrg              const struct trace_start_blit *payload)
3927ec681f3Smrg{
3937ec681f3Smrg   stage_start(pctx, ts_ns, BLIT_STAGE_ID);
3947ec681f3Smrg}
3957ec681f3Smrg
3967ec681f3Smrgvoid
3977ec681f3Smrgfd_end_blit(struct pipe_context *pctx, uint64_t ts_ns,
3987ec681f3Smrg            const void *flush_data,
3997ec681f3Smrg            const struct trace_end_blit *payload)
4007ec681f3Smrg{
4017ec681f3Smrg   stage_end(pctx, ts_ns, BLIT_STAGE_ID);
4027ec681f3Smrg}
4037ec681f3Smrg
4047ec681f3Smrgvoid
4057ec681f3Smrgfd_start_compute(struct pipe_context *pctx, uint64_t ts_ns,
4067ec681f3Smrg                 const void *flush_data,
4077ec681f3Smrg                 const struct trace_start_compute *payload)
4087ec681f3Smrg{
4097ec681f3Smrg   stage_start(pctx, ts_ns, COMPUTE_STAGE_ID);
4107ec681f3Smrg}
4117ec681f3Smrg
4127ec681f3Smrgvoid
4137ec681f3Smrgfd_end_compute(struct pipe_context *pctx, uint64_t ts_ns,
4147ec681f3Smrg               const void *flush_data,
4157ec681f3Smrg               const struct trace_end_compute *payload)
4167ec681f3Smrg{
4177ec681f3Smrg   stage_end(pctx, ts_ns, COMPUTE_STAGE_ID);
4187ec681f3Smrg}
4197ec681f3Smrg
4207ec681f3Smrgvoid
4217ec681f3Smrgfd_start_clear_restore(struct pipe_context *pctx, uint64_t ts_ns,
4227ec681f3Smrg                       const void *flush_data,
4237ec681f3Smrg                       const struct trace_start_clear_restore *payload)
4247ec681f3Smrg{
4257ec681f3Smrg   stage_start(pctx, ts_ns, CLEAR_RESTORE_STAGE_ID);
4267ec681f3Smrg}
4277ec681f3Smrg
4287ec681f3Smrgvoid
4297ec681f3Smrgfd_end_clear_restore(struct pipe_context *pctx, uint64_t ts_ns,
4307ec681f3Smrg                     const void *flush_data,
4317ec681f3Smrg                     const struct trace_end_clear_restore *payload)
4327ec681f3Smrg{
4337ec681f3Smrg   stage_end(pctx, ts_ns, CLEAR_RESTORE_STAGE_ID);
4347ec681f3Smrg}
4357ec681f3Smrg
4367ec681f3Smrgvoid
4377ec681f3Smrgfd_start_resolve(struct pipe_context *pctx, uint64_t ts_ns,
4387ec681f3Smrg                 const void *flush_data,
4397ec681f3Smrg                 const struct trace_start_resolve *payload)
4407ec681f3Smrg{
4417ec681f3Smrg   stage_start(pctx, ts_ns, RESOLVE_STAGE_ID);
4427ec681f3Smrg}
4437ec681f3Smrg
4447ec681f3Smrgvoid
4457ec681f3Smrgfd_end_resolve(struct pipe_context *pctx, uint64_t ts_ns,
4467ec681f3Smrg               const void *flush_data,
4477ec681f3Smrg               const struct trace_end_resolve *payload)
4487ec681f3Smrg{
4497ec681f3Smrg   stage_end(pctx, ts_ns, RESOLVE_STAGE_ID);
4507ec681f3Smrg}
4517ec681f3Smrg
4527ec681f3Smrg#ifdef __cplusplus
4537ec681f3Smrg}
4547ec681f3Smrg#endif
455