1// Copyright (C) 2023 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {NUM_NULL, STR_NULL} from '../../trace_processor/query_result'; 16import {Trace} from '../../public/trace'; 17import {Slice} from '../../public/track'; 18import {PerfettoPlugin} from '../../public/plugin'; 19import { 20 NAMED_ROW, 21 NamedRow, 22 NamedSliceTrack, 23} from '../../components/tracks/named_slice_track'; 24import {TrackNode} from '../../public/workspace'; 25class GpuPidTrack extends NamedSliceTrack { 26 constructor( 27 trace: Trace, 28 uri: string, 29 protected readonly upid: number, 30 ) { 31 super(trace, uri); 32 this.upid = upid; 33 } 34 35 protected getRowSpec(): NamedRow { 36 return NAMED_ROW; 37 } 38 39 protected rowToSlice(row: NamedRow): Slice { 40 return this.rowToSliceBase(row); 41 } 42 43 getSqlSource(): string { 44 return ` 45 SELECT * 46 FROM gpu_slice 47 WHERE upid = ${this.upid} 48 `; 49 } 50} 51 52export default class implements PerfettoPlugin { 53 static readonly id = 'dev.perfetto.GpuByProcess'; 54 async onTraceLoad(ctx: Trace): Promise<void> { 55 // Find all unique upid values in gpu_slices and join with process table. 56 const results = await ctx.engine.query(` 57 WITH slice_upids AS ( 58 SELECT DISTINCT upid FROM gpu_slice 59 ) 60 SELECT upid, pid, name FROM slice_upids JOIN process USING (upid) 61 `); 62 63 const it = results.iter({ 64 upid: NUM_NULL, 65 pid: NUM_NULL, 66 name: STR_NULL, 67 }); 68 69 // For each upid, create a GpuPidTrack. 70 for (; it.valid(); it.next()) { 71 if (it.upid == null) { 72 continue; 73 } 74 75 const upid = it.upid; 76 let processName = 'Unknown'; 77 if (it.name != null) { 78 processName = it.name; 79 } else if (it.pid != null) { 80 processName = `${it.pid}`; 81 } 82 83 const uri = `dev.perfetto.GpuByProcess#${upid}`; 84 const title = `GPU ${processName}`; 85 ctx.tracks.registerTrack({ 86 uri, 87 title, 88 track: new GpuPidTrack(ctx, uri, upid), 89 }); 90 const track = new TrackNode({uri, title}); 91 ctx.workspace.addChildInOrder(track); 92 } 93 } 94} 95