Skip to content

Commit 613790b

Browse files
authored
rust-sdk: Add perfetto-protos-gpu crate (#3487)
This crate provides extra protobuf bindings for GPU events. Fixes: #3486
1 parent 96736c4 commit 613790b

35 files changed

+1043
-52
lines changed

contrib/rust-sdk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[workspace]
22
resolver = "2"
3-
members = ["perfetto", "perfetto-derive", "perfetto-sys"]
3+
members = ["perfetto", "perfetto-derive", "perfetto-protos-gpu", "perfetto-sys"]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
edition = "2024"
3+
name = "perfetto-protos-gpu"
4+
version = "0.1.0"
5+
authors = ["David Reveman <[email protected]>"]
6+
description = "Extra protobuf bindings for GPU events"
7+
readme = "README.md"
8+
keywords = [
9+
"tracing",
10+
"perfetto",
11+
]
12+
categories = ["profiling"]
13+
license = "Apache-2.0"
14+
repository = "https://github.com/google/perfetto"
15+
16+
[dependencies]
17+
perfetto = { path = "../perfetto", version = "0.1.0", default-features = false }
18+
paste = "1"
19+
20+
[[example]]
21+
name = "gpu_counters"
22+
path = "examples/gpu_counters.rs"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../perfetto/README.md
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright (C) 2025 Rivos Inc.
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+
15+
use perfetto::{
16+
data_source::*, pb_decoder::*, producer::*, protos::trace::trace_packet::TracePacket,
17+
};
18+
19+
use perfetto_protos_gpu::protos::{
20+
common::gpu_counter_descriptor::*, config::data_source_config::*,
21+
config::gpu::gpu_counter_config::*, trace::gpu::gpu_counter_event::*,
22+
trace::trace_packet::prelude::*,
23+
};
24+
25+
use std::{
26+
error::Error,
27+
sync::{Arc, Mutex},
28+
time::{Duration, Instant},
29+
};
30+
31+
#[derive(Debug, Default)]
32+
struct GpuCounterConfig {
33+
counter_period_ns: Option<u64>,
34+
counter_ids: Vec<u32>,
35+
instrumented_sampling: Option<bool>,
36+
fix_gpu_clock: Option<bool>,
37+
}
38+
39+
impl GpuCounterConfig {
40+
fn decode(&mut self, data: &[u8]) -> &mut Self {
41+
use PbDecoderField::*;
42+
const COUNTER_PERIOD_NS_ID: u32 = GpuCounterConfigFieldNumber::CounterPeriodNs as u32;
43+
const COUNTER_IDS_ID: u32 = GpuCounterConfigFieldNumber::CounterIds as u32;
44+
const INSTRUMENTED_SAMPLING_ID: u32 =
45+
GpuCounterConfigFieldNumber::InstrumentedSampling as u32;
46+
const FIX_GPU_CLOCK_ID: u32 = GpuCounterConfigFieldNumber::FixGpuClock as u32;
47+
for item in PbDecoder::new(data) {
48+
match item.as_ref().unwrap_or_else(|e| panic!("Error: {}", e)) {
49+
(COUNTER_PERIOD_NS_ID, Varint(v)) => self.counter_period_ns = Some(*v),
50+
(COUNTER_IDS_ID, Varint(v)) => self.counter_ids.push(*v as u32),
51+
(INSTRUMENTED_SAMPLING_ID, Varint(v)) => self.instrumented_sampling = Some(*v != 0),
52+
(FIX_GPU_CLOCK_ID, Varint(v)) => self.fix_gpu_clock = Some(*v != 0),
53+
_ => println!("WARNING: unknown GpuCounterConfig field: {:?}", item),
54+
}
55+
}
56+
self
57+
}
58+
}
59+
60+
fn main() -> Result<(), Box<dyn Error>> {
61+
const GPU_COUNTER_CONFIG_ID: u32 = DataSourceConfigExtFieldNumber::GpuCounterConfig as u32;
62+
let producer_args = ProducerInitArgsBuilder::new().backends(Backends::SYSTEM);
63+
Producer::init(producer_args.build());
64+
let mut data_source = DataSource::new();
65+
let gpu_counter_config = Arc::new(Mutex::new(GpuCounterConfig::default()));
66+
let gpu_counter_config_for_setup = Arc::clone(&gpu_counter_config);
67+
let data_source_args = DataSourceArgsBuilder::new().on_setup(move |inst_id, config| {
68+
let mut gpu_counter_config = gpu_counter_config_for_setup.lock().unwrap();
69+
for item in PbDecoder::new(config) {
70+
if let (GPU_COUNTER_CONFIG_ID, PbDecoderField::Delimited(value)) =
71+
item.unwrap_or_else(|e| panic!("Error: {}", e))
72+
{
73+
gpu_counter_config.decode(value);
74+
}
75+
}
76+
println!(
77+
"OnSetup id: {} gpu_conter_config: {:?}",
78+
inst_id, gpu_counter_config
79+
);
80+
});
81+
let start_time = Instant::now();
82+
data_source.register("gpu.counters.rig", data_source_args.build())?;
83+
loop {
84+
data_source.trace(|ctx: &mut TraceContext| {
85+
// Fixed set of counters: sin, cos, tan.
86+
const COUNTER_IDS: [u32; 3] = [1, 2, 3];
87+
let elapsed_secs = start_time.elapsed().as_secs_f64();
88+
ctx.with_incremental_state(|ctx: &mut TraceContext, state| {
89+
let was_cleared = std::mem::replace(&mut state.was_cleared, false);
90+
ctx.add_packet(|packet: &mut TracePacket| {
91+
packet.set_gpu_counter_event(|event: &mut GpuCounterEvent| {
92+
for i in COUNTER_IDS.iter() {
93+
event.set_counters(|counter: &mut GpuCounter| {
94+
counter.set_counter_id(*i);
95+
match i {
96+
1 => counter.set_double_value(elapsed_secs.sin()),
97+
2 => counter.set_double_value(elapsed_secs.cos()),
98+
_ => counter.set_double_value(elapsed_secs.tan()),
99+
};
100+
});
101+
}
102+
if was_cleared {
103+
event.set_counter_descriptor(|desc: &mut GpuCounterDescriptor| {
104+
for i in COUNTER_IDS.iter() {
105+
desc.set_specs(|desc: &mut GpuCounterSpec| {
106+
desc.set_counter_id(*i);
107+
match i {
108+
1 => desc.set_name("sin"),
109+
2 => desc.set_name("cos"),
110+
_ => desc.set_name("tan"),
111+
};
112+
});
113+
}
114+
});
115+
}
116+
});
117+
});
118+
});
119+
});
120+
let counter_period = gpu_counter_config
121+
.lock()
122+
.unwrap()
123+
.counter_period_ns
124+
.map(|ns| Duration::from_nanos(ns))
125+
.unwrap_or(Duration::from_secs(1));
126+
std::thread::sleep(counter_period);
127+
}
128+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (C) 2025 Rivos Inc.
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+
15+
/// Re-export pb_msg macro from this crate.
16+
pub use perfetto::pb_msg;
17+
18+
/// Re-export pb_msg_ext macro from this crate.
19+
pub use perfetto::pb_msg_ext;
20+
21+
/// Re-export pb_enum macro from this crate.
22+
pub use perfetto::pb_enum;
23+
24+
/// Protobuf bindings module.
25+
pub mod protos;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (C) 2025 Rivos Inc.
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+
15+
// Manually generated with bindings for an extra set of
16+
// DataSourceDescriptor fields.
17+
18+
use crate::pb_msg;
19+
use crate::pb_msg_ext;
20+
use crate::protos::common::gpu_counter_descriptor::*;
21+
22+
use perfetto::protos::common::data_source_descriptor::DataSourceDescriptor;
23+
24+
pb_msg_ext!(DataSourceDescriptor {
25+
gpu_counter_descriptor: GpuCounterDescriptor, msg, 5,
26+
});
27+
28+
/// Import this to use the extra `DataSourceDescriptor` fields.
29+
pub mod prelude {
30+
pub use super::DataSourceDescriptorExt;
31+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (C) 2025 Rivos Inc.
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+
15+
// Autogenerated by the gen_rust_protos script.
16+
// DO NOT EDIT.
17+
18+
/// `data_source_descriptor` protos.
19+
#[path = "data_source_descriptor.pz.rs"]
20+
pub mod data_source_descriptor;
21+
22+
/// `gpu_counter_descriptor` protos.
23+
#[path = "gpu_counter_descriptor.pz.rs"]
24+
pub mod gpu_counter_descriptor;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (C) 2025 Rivos Inc.
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+
15+
// Manually generated with bindings for an extra set of DataSourceConfig
16+
// fields.
17+
18+
use crate::pb_msg;
19+
use crate::pb_msg_ext;
20+
use crate::protos::config::gpu::gpu_counter_config::*;
21+
use crate::protos::config::gpu::gpu_renderstages_config::*;
22+
use crate::protos::config::gpu::vulkan_memory_config::*;
23+
24+
use perfetto::protos::config::data_source_config::DataSourceConfig;
25+
26+
pb_msg_ext!(DataSourceConfig {
27+
gpu_counter_config: GpuCounterConfig, msg, 108,
28+
vulkan_memory_config: VulkanMemoryConfig, msg, 112,
29+
gpu_renderstages_config: GpuRenderStagesConfig, msg, 133,
30+
});
31+
32+
/// Import this to use the extra `DataSourceConfig` fields.
33+
pub mod prelude {
34+
pub use super::DataSourceConfigExt;
35+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (C) 2025 Rivos Inc.
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+
15+
// Autogenerated by the ProtoZero Rust compiler plugin.
16+
// Invoked by contrib/rust-sdk/tools/gen_rust_protos
17+
// DO NOT EDIT.
18+
19+
use crate::pb_msg;
20+
21+
pb_msg!(GpuCounterConfig {
22+
counter_period_ns: u64, primitive, 1,
23+
counter_ids: u32, primitive, 2,
24+
instrumented_sampling: bool, primitive, 3,
25+
fix_gpu_clock: bool, primitive, 4,
26+
});

0 commit comments

Comments
 (0)