katra_core/payload.rs
1//! Structured event payloads.
2//!
3//! Payloads are plain, `Copy` scalar records so the hot capture path can
4//! store them into preallocated per-thread buffers with **zero heap
5//! allocation per event** (KatraProfiler budget: "avoid heap allocation
6//! unless justified").
7//!
8//! The enum layout is part of the trace format; **append new variants at
9//! the end**.
10
11use serde::{Deserialize, Serialize};
12
13/// Payload for file operations.
14#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
15pub struct FilePayload {
16 /// File identity hash ([`crate::FileKey`]).
17 pub file: u64,
18 /// Byte offset.
19 pub offset: u64,
20 /// Byte length.
21 pub length: u64,
22 /// Flags (open flags, wait flags, ...).
23 pub flags: u32,
24 /// Result (bytes transferred, NTSTATUS/HRESULT, or -1).
25 pub result: i64,
26}
27
28/// Payload for memory operations.
29#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
30pub struct MemPayload {
31 /// Size in bytes.
32 pub size: u64,
33 /// Alignment in bytes.
34 pub align: u32,
35 /// Arena/resource id (0 = process heap).
36 pub arena: u32,
37}
38
39/// Payload for synchronization operations.
40#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
41pub struct SyncPayload {
42 /// Sync kind (0 event, 1 mutex, 2 semaphore, 3 fence, 4 condvar, ...).
43 pub kind: u32,
44 /// Value (fence value, semaphore count, ...).
45 pub value: u64,
46}
47
48/// Payload for thread operations.
49#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
50pub struct ThreadPayload {
51 /// Action (0 create, 1 wakeup, 2 exit, 3 yield, ...).
52 pub action: u32,
53 /// Extra (target thread id, ...).
54 pub extra: u64,
55}
56
57/// Payload for D3D12 calls. The call identity is in [`crate::EventKind`];
58/// `a..d` carry call-specific scalar arguments.
59#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
60pub struct D3d12Payload {
61 /// Call-specific scalar 1.
62 pub a: u64,
63 /// Call-specific scalar 2.
64 pub b: u64,
65 /// Call-specific scalar 3.
66 pub c: u64,
67 /// Call-specific scalar 4.
68 pub d: u64,
69}
70
71/// Payload for Vulkan calls. The call identity is in [`crate::EventKind`].
72#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
73pub struct VulkanPayload {
74 /// Call-specific scalar 1.
75 pub a: u64,
76 /// Call-specific scalar 2.
77 pub b: u64,
78 /// Call-specific scalar 3.
79 pub c: u64,
80 /// Call-specific scalar 4.
81 pub d: u64,
82}
83
84/// Payload for GPU counters/samples.
85#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
86pub struct GpuPayload {
87 /// Counter id (0 timestamp, 1 idle bubble ns, 2 utilization %, ...).
88 pub counter: u32,
89 /// Value.
90 pub value: u64,
91}
92
93/// Payload for I/O events.
94#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
95pub struct IoPayload {
96 /// Queue depth at submission (or 0).
97 pub queue_depth: u32,
98 /// Operation latency in ns (0 if unknown).
99 pub latency_ns: u64,
100 /// Bytes transferred.
101 pub bytes: u64,
102 /// Operation (0 read, 1 submit batch, 2 complete, ...).
103 pub op: u32,
104}
105
106/// Payload for Katra-native events.
107#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
108pub struct KatraPayload {
109 /// Subsystem index (see [`crate::Subsystem`]).
110 pub subsystem: u16,
111 /// Promotion state index (see [`crate::PromotionState`]).
112 pub state: u16,
113 /// Detail (budget bytes, epoch, node id, ...).
114 pub detail: u64,
115}
116
117/// Payload for shader events.
118#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
119pub struct ShaderPayload {
120 /// Shader stage (0 vertex, 1 pixel, 2 compute, ...).
121 pub stage: u32,
122 /// Input identity hash (DXIL).
123 pub input_hash: u64,
124 /// Output identity hash (SPIR-V).
125 pub output_hash: u64,
126}
127
128/// Payload for cache events.
129#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
130pub struct CachePayload {
131 /// Cache layer (1 DXIL, 2 IR, 3 SPIR-V, 4 pipeline).
132 pub layer: u8,
133 /// Whether the lookup hit.
134 pub hit: bool,
135 /// Content key hash.
136 pub key: u64,
137 /// Artifact size in bytes.
138 pub size: u64,
139}
140
141/// Payload for present events.
142#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
143pub struct PresentPayload {
144 /// Frame index.
145 pub frame: u64,
146 /// Present mode (0 vsync, 1 immediate, 2 mailbox, ...).
147 pub present_mode: u32,
148}
149
150/// Payload for decompression events.
151#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
152pub struct DecompressPayload {
153 /// Compressed input bytes.
154 pub input_bytes: u64,
155 /// Decompressed output bytes.
156 pub output_bytes: u64,
157 /// Format (0 gdeflate, 1 gzip, 2 zlib, 3 raw deflate, ...).
158 pub format: u32,
159 /// Decompression latency in ns.
160 pub latency_ns: u64,
161}
162
163/// Payload for future/unknown event kinds (extension escape hatch).
164#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
165pub struct RawPayload {
166 /// Generic scalar 1.
167 pub a: u64,
168 /// Generic scalar 2.
169 pub b: u64,
170 /// Generic scalar 3.
171 pub c: u64,
172 /// Generic scalar 4.
173 pub d: u64,
174}
175
176/// The payload of a [`crate::TraceEvent`]. Plain scalars only; append-only.
177#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
178pub enum Payload {
179 /// No payload.
180 #[default]
181 None,
182 /// File operation.
183 File(FilePayload),
184 /// Memory operation.
185 Mem(MemPayload),
186 /// Synchronization operation.
187 Sync(SyncPayload),
188 /// Thread operation.
189 Thread(ThreadPayload),
190 /// D3D12 call.
191 D3d12(D3d12Payload),
192 /// Vulkan call.
193 Vulkan(VulkanPayload),
194 /// GPU sample.
195 Gpu(GpuPayload),
196 /// I/O operation.
197 Io(IoPayload),
198 /// Katra-native operation.
199 Katra(KatraPayload),
200 /// Shader operation.
201 Shader(ShaderPayload),
202 /// Cache operation.
203 Cache(CachePayload),
204 /// Present operation.
205 Present(PresentPayload),
206 /// Decompression operation.
207 Decompress(DecompressPayload),
208 /// Extension payload.
209 Raw(RawPayload),
210}
211
212impl Payload {
213 /// The payload kind as a stable string (for reports).
214 pub fn as_str(&self) -> &'static str {
215 match self {
216 Payload::None => "none",
217 Payload::File(_) => "file",
218 Payload::Mem(_) => "mem",
219 Payload::Sync(_) => "sync",
220 Payload::Thread(_) => "thread",
221 Payload::D3d12(_) => "d3d12",
222 Payload::Vulkan(_) => "vulkan",
223 Payload::Gpu(_) => "gpu",
224 Payload::Io(_) => "io",
225 Payload::Katra(_) => "katra",
226 Payload::Shader(_) => "shader",
227 Payload::Cache(_) => "cache",
228 Payload::Present(_) => "present",
229 Payload::Decompress(_) => "decompress",
230 Payload::Raw(_) => "raw",
231 }
232 }
233
234 /// Convenience constructor for a D3D12 call payload.
235 pub fn d3d12(a: u64, b: u64, c: u64, d: u64) -> Self {
236 Payload::D3d12(D3d12Payload { a, b, c, d })
237 }
238
239 /// Convenience constructor for a Vulkan call payload.
240 pub fn vulkan(a: u64, b: u64, c: u64, d: u64) -> Self {
241 Payload::Vulkan(VulkanPayload { a, b, c, d })
242 }
243
244 /// Convenience constructor for a raw payload.
245 pub fn raw(a: u64, b: u64, c: u64, d: u64) -> Self {
246 Payload::Raw(RawPayload { a, b, c, d })
247 }
248}