| -- Copyright 2024 The Chromium Authors |
| -- Use of this source code is governed by a BSD-style license that can be |
| -- found in the LICENSE file. |
| |
| INCLUDE PERFETTO MODULE slices.with_context; |
| |
| -- `Graphics.Pipeline` steps corresponding to work done by a Viz client to |
| -- produce a frame (i.e. before surface aggregation). Covers steps: |
| -- * STEP_ISSUE_BEGIN_FRAME |
| -- * STEP_RECEIVE_BEGIN_FRAME |
| -- * STEP_GENERATE_RENDER_PASS |
| -- * STEP_GENERATE_COMPOSITOR_FRAME |
| -- * STEP_SUBMIT_COMPOSITOR_FRAME |
| -- * STEP_RECEIVE_COMPOSITOR_FRAME |
| -- * STEP_RECEIVE_BEGIN_FRAME_DISCARD |
| -- * STEP_DID_NOT_PRODUCE_FRAME |
| -- * STEP_DID_NOT_PRODUCE_COMPOSITOR_FRAME |
| CREATE PERFETTO TABLE chrome_graphics_pipeline_surface_frame_steps ( |
| -- Slice Id of the `Graphics.Pipeline` slice. |
| id LONG, |
| -- The start timestamp of the slice/step. |
| ts TIMESTAMP, |
| -- The duration of the slice/step. |
| dur DURATION, |
| -- Step name of the `Graphics.Pipeline` slice. |
| step STRING, |
| -- Id of the graphics pipeline, pre-surface aggregation. |
| surface_frame_trace_id LONG, |
| -- Utid of the thread where this slice exists. |
| utid LONG, |
| -- Start time of the parent Chrome scheduler task (if any) of this step. |
| task_start_time_ts TIMESTAMP |
| ) AS |
| WITH |
| -- Same places in Chromium (e.g. WebView) emit -1 as the `surface_frame_trace_id`, |
| -- which blows up the joins on that value. Replace them with NULLs to avoid that. |
| raw_data AS ( |
| SELECT |
| id, |
| ts, |
| dur, |
| extract_arg(arg_set_id, 'chrome_graphics_pipeline.step') AS step, |
| extract_arg(arg_set_id, 'chrome_graphics_pipeline.surface_frame_trace_id') AS surface_frame_trace_raw_id, |
| utid, |
| ts - ( |
| extract_arg(thread_slice.arg_set_id, 'current_task.event_offset_from_task_start_time_us') * 1000 |
| ) AS task_start_time_ts |
| FROM thread_slice |
| WHERE |
| name = 'Graphics.Pipeline' AND surface_frame_trace_raw_id IS NOT NULL |
| ) |
| SELECT |
| id, |
| ts, |
| dur, |
| step, |
| nullif(surface_frame_trace_raw_id, -1) AS surface_frame_trace_id, |
| utid, |
| task_start_time_ts |
| FROM raw_data; |
| |
| -- `Graphics.Pipeline` steps corresponding to work done on creating and |
| -- presenting one frame during/after surface aggregation. Covers steps: |
| -- * STEP_DRAW_AND_SWAP |
| -- * STEP_SURFACE_AGGREGATION |
| -- * STEP_SEND_BUFFER_SWAP |
| -- * STEP_BUFFER_SWAP_POST_SUBMIT |
| -- * STEP_FINISH_BUFFER_SWAP |
| -- * STEP_SWAP_BUFFERS_ACK |
| CREATE PERFETTO TABLE chrome_graphics_pipeline_display_frame_steps ( |
| -- Slice Id of the `Graphics.Pipeline` slice. |
| id LONG, |
| -- The start timestamp of the slice/step. |
| ts TIMESTAMP, |
| -- The duration of the slice/step. |
| dur DURATION, |
| -- Step name of the `Graphics.Pipeline` slice. |
| step STRING, |
| -- Id of the graphics pipeline, post-surface aggregation. |
| display_trace_id LONG, |
| -- Utid of the thread where this slice exists. |
| utid LONG, |
| -- Start time of the parent Chrome scheduler task (if any) of this step. |
| task_start_time_ts TIMESTAMP |
| ) AS |
| WITH |
| steps_with_potential_duplicates AS ( |
| SELECT |
| id, |
| ts, |
| dur, |
| extract_arg(arg_set_id, 'chrome_graphics_pipeline.step') AS step, |
| extract_arg(arg_set_id, 'chrome_graphics_pipeline.display_trace_id') AS display_trace_id, |
| utid, |
| ts - ( |
| extract_arg(thread_slice.arg_set_id, 'current_task.event_offset_from_task_start_time_us') * 1000 |
| ) AS task_start_time_ts |
| FROM thread_slice |
| WHERE |
| name = 'Graphics.Pipeline' AND display_trace_id IS NOT NULL |
| ), |
| steps_with_ordering AS ( |
| SELECT |
| *, |
| -- Partition the steps so that, if the same step (for the same graphics |
| -- pipeline) was emitted more than once (e.g. due to b:390610512), the |
| -- step ends up in the same partition as all its duplicates. This will |
| -- enable us to deduplicate the steps later. |
| -- If there are multiple STEP_DRAW_AND_SWAP or multiple |
| -- STEP_SURFACE_AGGREGATION steps, we assume that all duplicates except |
| -- the last one were cancelled, so we only care about the last |
| -- STEP_DRAW_AND_SWAP/STEP_SURFACE_AGGREGATION step. We don't have any |
| -- preference for other steps but, for the sake of determinism and |
| -- consistency, let's always pick the last step. |
| row_number() OVER (PARTITION BY display_trace_id, step, utid ORDER BY ts DESC) AS ordering_within_partition |
| FROM steps_with_potential_duplicates |
| ) |
| SELECT |
| id, |
| ts, |
| dur, |
| step, |
| display_trace_id, |
| utid, |
| task_start_time_ts |
| FROM steps_with_ordering |
| -- This is where we actually remove duplicate steps. |
| WHERE |
| ordering_within_partition = 1; |
| |
| -- Links surface frames (`chrome_graphics_pipeline_surface_frame_steps`) to the |
| -- the first display frame (`chrome_graphics_pipeline_display_frame_steps`) into |
| -- which it was included. As an display frame usually aggregates frames from |
| -- multiple surfaces, multiple `surface_frame_trace_id`s will correspond to one |
| -- `display_trace_id`. |
| CREATE PERFETTO TABLE chrome_surface_frame_id_to_first_display_id ( |
| -- Id of the graphics pipeline, pre-surface aggregation. |
| surface_frame_trace_id LONG, |
| -- Id of the graphics pipeline, post-surface aggregation. |
| display_trace_id LONG |
| ) AS |
| WITH |
| aggregations AS ( |
| SELECT |
| args.int_value AS surface_frame_trace_id, |
| display_trace_id, |
| slice.ts |
| FROM chrome_graphics_pipeline_display_frame_steps AS step |
| JOIN slice |
| USING (id) |
| JOIN args |
| USING (arg_set_id) |
| WHERE |
| step.step = 'STEP_SURFACE_AGGREGATION' |
| AND args.flat_key = 'chrome_graphics_pipeline.aggregated_surface_frame_trace_ids' |
| ) |
| SELECT |
| surface_frame_trace_id, |
| first_value(display_trace_id) OVER (PARTITION BY surface_frame_trace_id ORDER BY ts) AS display_trace_id |
| FROM aggregations |
| GROUP BY |
| surface_frame_trace_id; |
| |
| -- Links inputs (`chrome_input_pipeline_steps.latency_id`) to the surface frame |
| -- (`chrome_graphics_pipeline_surface_frame_steps`) to which they correspond. |
| -- In other words, in general, multiple `latency_id`s will correspond to one |
| -- `surface_frame_trace_id`. |
| CREATE PERFETTO TABLE chrome_graphics_pipeline_inputs_to_surface_frames ( |
| -- Id corresponding to the input pipeline. |
| latency_id LONG, |
| -- Id of the graphics pipeline, post-surface aggregation. |
| surface_frame_trace_id LONG |
| ) AS |
| SELECT |
| args.int_value AS latency_id, |
| surface_frame_trace_id |
| FROM chrome_graphics_pipeline_surface_frame_steps AS step |
| JOIN slice |
| USING (id) |
| JOIN args |
| USING (arg_set_id) |
| WHERE |
| step.step = 'STEP_SUBMIT_COMPOSITOR_FRAME' |
| AND args.flat_key = 'chrome_graphics_pipeline.latency_ids'; |