Skip to content

Commit c3cc182

Browse files
authored
ui: Add GPU-prefixed names to GPU memory tracks (#5334)
When multiple GPUs are present, prefix GPU memory track names with the GPU display name (e.g., "GPU 0 Memory", "GPU 1 Memory") and nest them under a "GPU Memory" group, matching the GPU Frequency track pattern. ``` Single GPU (unchanged): GPU Gpu 0 Frequency [_____----____--] GPU Memory [=====-----------] Multiple GPUs before: GPU GPU Frequency GPU 0 Frequency [_____----____--] GPU 1 Frequency [__--____----__-] GPU Memory [=====-----------] GPU Memory [===----=========] Multiple GPUs after: GPU GPU Frequency GPU 0 Frequency [_____----____--] GPU 1 Frequency [__--____----__-] GPU Memory GPU 0 Memory [=====-----------] GPU 1 Memory [===----=========] ```
1 parent 38de0bc commit c3cc182

File tree

1 file changed

+74
-10
lines changed

1 file changed

+74
-10
lines changed

ui/src/plugins/dev.perfetto.Gpu/index.ts

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import {createTraceProcessorSliceTrack} from '../dev.perfetto.TraceProcessorTrac
2828
interface GpuCounterSchema {
2929
readonly type: string;
3030
readonly group: string | undefined;
31+
// When set, the track is named "${gpu.displayName} ${gpuTrackName}" instead
32+
// of using the DB track name. This avoids redundant prefixes like
33+
// "GPU 0 GPU Memory" by allowing explicit control (e.g., "GPU 0 Memory").
34+
readonly gpuTrackName: string | undefined;
3135
}
3236

3337
interface GpuSliceSchema {
@@ -36,13 +40,29 @@ interface GpuSliceSchema {
3640
}
3741

3842
const GPU_COUNTER_SCHEMAS: ReadonlyArray<GpuCounterSchema> = [
39-
{type: 'gpu_counter', group: 'Counters'},
40-
{type: 'gpu_memory', group: undefined},
41-
{type: 'virtgpu_latency', group: 'Virtgpu Latency'},
42-
{type: 'virtgpu_num_free', group: 'Virtgpu num_free'},
43-
{type: 'vulkan_device_mem_allocation', group: 'Vulkan Allocations'},
44-
{type: 'vulkan_device_mem_bind', group: 'Vulkan Binds'},
45-
{type: 'vulkan_driver_mem', group: 'Vulkan Driver Memory'},
43+
{type: 'gpu_counter', group: 'Counters', gpuTrackName: undefined},
44+
{type: 'gpu_memory', group: undefined, gpuTrackName: 'Memory'},
45+
{type: 'virtgpu_latency', group: 'Virtgpu Latency', gpuTrackName: undefined},
46+
{
47+
type: 'virtgpu_num_free',
48+
group: 'Virtgpu num_free',
49+
gpuTrackName: undefined,
50+
},
51+
{
52+
type: 'vulkan_device_mem_allocation',
53+
group: 'Vulkan Allocations',
54+
gpuTrackName: undefined,
55+
},
56+
{
57+
type: 'vulkan_device_mem_bind',
58+
group: 'Vulkan Binds',
59+
gpuTrackName: undefined,
60+
},
61+
{
62+
type: 'vulkan_driver_mem',
63+
group: 'Vulkan Driver Memory',
64+
gpuTrackName: undefined,
65+
},
4666
];
4767

4868
const GPU_SLICE_SCHEMAS: ReadonlyArray<GpuSliceSchema> = [
@@ -231,6 +251,13 @@ export default class GpuPlugin implements PerfettoPlugin {
231251
`);
232252

233253
const schemas = new Map(GPU_COUNTER_SCHEMAS.map((x) => [x.type, x]));
254+
const counterTracks: Array<{
255+
schema: GpuCounterSchema;
256+
gpu: Gpu | null;
257+
trackName: string;
258+
baseName: string;
259+
uri: string;
260+
}> = [];
234261
const it = result.iter({
235262
id: NUM,
236263
type: STR,
@@ -262,7 +289,10 @@ export default class GpuPlugin implements PerfettoPlugin {
262289
gpuId !== null
263290
? new Gpu(ugpu ?? trackId, gpuId, machineId, gpuName ?? undefined)
264291
: null;
265-
const trackName = getTrackName({name, kind: COUNTER_TRACK_KIND});
292+
let trackName = getTrackName({name, kind: COUNTER_TRACK_KIND});
293+
if (gpu !== null && schema.gpuTrackName !== undefined) {
294+
trackName = `${gpu.displayName} ${schema.gpuTrackName}${gpu.maybeMachineLabel()}`;
295+
}
266296
const uri = `/counter_${ugpu ?? trackId}_${trackId}`;
267297

268298
ctx.tracks.registerTrack({
@@ -284,10 +314,44 @@ export default class GpuPlugin implements PerfettoPlugin {
284314
trackName,
285315
),
286316
});
317+
318+
counterTracks.push({
319+
schema,
320+
gpu,
321+
trackName,
322+
baseName: getTrackName({name, kind: COUNTER_TRACK_KIND}),
323+
uri,
324+
});
325+
}
326+
327+
// Count ungrouped tracks per type to decide if a sub-group is needed,
328+
// matching the GPU Frequency pattern: only create a sub-group when
329+
// there are multiple tracks of the same type.
330+
const ungroupedCounts = new Map<string, number>();
331+
for (const {schema} of counterTracks) {
332+
if (schema.group === undefined) {
333+
ungroupedCounts.set(
334+
schema.type,
335+
(ungroupedCounts.get(schema.type) ?? 0) + 1,
336+
);
337+
}
338+
}
339+
340+
for (const {schema, gpu, trackName, baseName, uri} of counterTracks) {
341+
let group = schema.group;
342+
let groupGpu = gpu;
343+
if (group === undefined && (ungroupedCounts.get(schema.type) ?? 0) > 1) {
344+
// Multiple tracks of the same ungrouped type: create a sub-group
345+
// using the base track name (e.g., "GPU Memory") and add tracks
346+
// directly under it without per-GPU sub-groups, matching how
347+
// addGpuFreq handles GPU Frequency tracks.
348+
group = baseName;
349+
groupGpu = null;
350+
}
287351
this.addToGpuGroup(
288352
ctx,
289-
schema.group,
290-
gpu,
353+
group,
354+
groupGpu,
291355
new TrackNode({uri, name: trackName, sortOrder: 0}),
292356
);
293357
}

0 commit comments

Comments
 (0)