Skip to main content

zenfg/
report.rs

1use crate::{
2    AccessId, AccessMode, AccessRole, AllocationId, BufferDesc, DebugGroupId, DependencyKind,
3    HazardKind, NodeKind, PassId, ResourceId, ResourceKind, ResourceOrigin, ResourceRange,
4    RootReason, TextureDesc, TextureViewDesc, UndefinedCause, ValueId, ViewId,
5};
6
7/// CPU time spent in each compilation phase, in nanoseconds.
8#[allow(missing_docs)]
9#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct CompilationTimings {
12    pub validation_ns: u64,
13    pub dependency_ns: u64,
14    pub retention_ns: u64,
15    pub planning_ns: u64,
16    pub report_ns: u64,
17    pub total_ns: u64,
18}
19
20/// Counts, memory estimates, and timings available at summary report level.
21#[allow(missing_docs)]
22#[derive(Clone, Debug, Default, PartialEq, Eq)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct CompilationSummary {
25    pub recorded_node_count: usize,
26    pub retained_node_count: usize,
27    pub culled_node_count: usize,
28    pub resource_count: usize,
29    pub view_count: usize,
30    pub access_count: usize,
31    pub value_count: usize,
32    pub dependency_count: usize,
33    pub allocation_count: usize,
34    pub logical_transient_bytes: u64,
35    pub physical_allocation_bytes: u64,
36    pub timings: CompilationTimings,
37}
38
39/// Effective native usage inferred for a retained logical resource.
40#[allow(missing_docs)]
41#[derive(Clone, Copy, Debug, PartialEq, Eq)]
42#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
43pub enum ResourceUsage {
44    Texture(wgpu::TextureUsages),
45    Buffer(wgpu::BufferUsages),
46}
47
48impl ResourceUsage {
49    /// Returns the native wgpu bit representation as a common integer type.
50    pub const fn bits(self) -> u64 {
51        match self {
52            Self::Texture(value) => value.bits() as u64,
53            Self::Buffer(value) => value.bits() as u64,
54        }
55    }
56}
57
58/// Snapshotted logical descriptor of a reported resource.
59#[allow(missing_docs)]
60#[derive(Clone, Debug, PartialEq, Eq)]
61#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
62pub enum ResourceDescriptor {
63    Texture(TextureDesc),
64    Buffer(BufferDesc),
65}
66
67/// One retained node in original recording order.
68#[allow(missing_docs)]
69#[derive(Clone, Debug, PartialEq, Eq)]
70#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
71pub struct NodeReport {
72    pub id: PassId,
73    #[cfg_attr(feature = "serde", serde(skip))]
74    pub recording_order: u32,
75    pub kind: NodeKind,
76    pub label: String,
77    pub side_effect: bool,
78    #[cfg_attr(feature = "serde", serde(skip))]
79    pub debug_group: Option<DebugGroupId>,
80}
81
82/// Why a recorded node was removed from the retained plan.
83#[allow(missing_docs)]
84#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
85#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
86#[non_exhaustive]
87pub enum CulledNodeReason {
88    #[default]
89    NotReachableFromRoot,
90}
91
92/// One removed node in original recording order.
93#[allow(missing_docs)]
94#[derive(Clone, Debug, PartialEq, Eq)]
95#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
96pub struct CulledNodeReport {
97    pub id: PassId,
98    #[cfg_attr(feature = "serde", serde(skip))]
99    pub recording_order: u32,
100    pub kind: NodeKind,
101    pub label: String,
102    pub side_effect: bool,
103    #[cfg_attr(feature = "serde", serde(skip))]
104    pub debug_group: Option<DebugGroupId>,
105    #[cfg_attr(feature = "serde", serde(skip))]
106    pub reason: CulledNodeReason,
107}
108
109/// Descriptor, usage, lifetime, and allocation facts for one logical resource.
110#[allow(missing_docs)]
111#[derive(Clone, Debug, PartialEq, Eq)]
112#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
113pub struct ResourceReport {
114    pub id: ResourceId,
115    pub kind: ResourceKind,
116    pub label: String,
117    pub origin: ResourceOrigin,
118    pub initial_contents: crate::InitialContents,
119    pub descriptor: ResourceDescriptor,
120    pub effective_usage: ResourceUsage,
121    pub estimated_byte_size: u64,
122    pub lifetime: Option<ResourceLifetime>,
123    pub allocation: Option<AllocationId>,
124    #[cfg_attr(feature = "serde", serde(skip))]
125    pub debug_group: Option<DebugGroupId>,
126}
127
128/// One recording-only diagnostic scope in group-open order.
129#[allow(missing_docs)]
130#[derive(Clone, Debug, PartialEq, Eq)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
132pub struct DebugGroupReport {
133    pub id: DebugGroupId,
134    pub parent: Option<DebugGroupId>,
135    pub label: String,
136}
137
138/// One normalized logical texture view.
139#[allow(missing_docs)]
140#[derive(Clone, Debug, PartialEq, Eq)]
141#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
142pub struct ViewReport {
143    pub id: ViewId,
144    pub texture: ResourceId,
145    pub descriptor: TextureViewDesc,
146    pub range: ResourceRange,
147}
148
149/// One declared resource access in recording order.
150#[allow(missing_docs)]
151#[derive(Clone, Debug, PartialEq, Eq)]
152#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
153pub struct AccessReport {
154    pub id: AccessId,
155    pub pass: PassId,
156    pub resource: ResourceId,
157    pub view: Option<ViewId>,
158    pub role: AccessRole,
159    pub mode: AccessMode,
160    pub consumes_previous: bool,
161    pub produces_value: bool,
162    pub range: ResourceRange,
163    pub value: Option<ValueId>,
164}
165
166/// Origin of one logical content value.
167#[allow(missing_docs)]
168#[derive(Clone, Copy, Debug, PartialEq, Eq)]
169#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
170pub enum ValueKind {
171    External,
172    Write,
173}
174
175/// One initial or pass-produced logical content value.
176#[allow(missing_docs)]
177#[derive(Clone, Debug, PartialEq, Eq)]
178#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
179pub struct ValueReport {
180    pub id: ValueId,
181    pub resource: ResourceId,
182    pub producer: Option<PassId>,
183    pub kind: ValueKind,
184    pub range: ResourceRange,
185}
186
187/// One value-carrying or ordering dependency between graph nodes.
188#[allow(missing_docs)]
189#[derive(Clone, Debug, PartialEq, Eq)]
190#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
191pub struct DependencyReport {
192    pub from: PassId,
193    pub to: PassId,
194    pub resource: ResourceId,
195    pub kind: DependencyKind,
196    pub hazard: HazardKind,
197    pub range: ResourceRange,
198    pub value: Option<ValueId>,
199}
200
201/// One observable resource range and the producers that keep it defined.
202#[allow(missing_docs)]
203#[derive(Clone, Debug, PartialEq, Eq)]
204#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
205pub struct RootReport {
206    pub resource: ResourceId,
207    pub reason: RootReason,
208    pub range: ResourceRange,
209    pub resolution: RootResolution,
210}
211
212/// Sources of the final contents in a root's selected range.
213#[allow(missing_docs)]
214#[derive(Clone, Debug, PartialEq, Eq)]
215#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
216pub struct RootResolution {
217    pub producer_node_ids: Vec<PassId>,
218    pub uses_initial_contents: bool,
219}
220
221/// Inclusive retained execution-order interval of one logical resource.
222#[allow(missing_docs)]
223#[derive(Clone, Copy, Debug, PartialEq, Eq)]
224#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
225pub struct ResourceLifetime {
226    pub first_use: usize,
227    pub last_use: usize,
228}
229
230/// One physical transient allocation and all aliased logical resources assigned to it.
231#[allow(missing_docs)]
232#[derive(Clone, Debug, PartialEq, Eq)]
233#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
234pub struct AllocationReport {
235    pub id: AllocationId,
236    pub kind: ResourceKind,
237    pub compatibility_key: String,
238    pub resource_ids: Vec<ResourceId>,
239    pub estimated_byte_size: u64,
240}
241
242/// Kind of encoder/submission segment in the retained execution plan.
243#[allow(missing_docs)]
244#[derive(Clone, Copy, Debug, PartialEq, Eq)]
245#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
246pub enum ExecutionSegmentKind {
247    FrameGraph,
248    ExternalSubmission,
249}
250
251/// Ordered retained nodes belonging to one execution segment.
252#[allow(missing_docs)]
253#[derive(Clone, Debug, PartialEq, Eq)]
254#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
255pub struct ExecutionSegmentReport {
256    pub kind: ExecutionSegmentKind,
257    pub nodes: Vec<PassId>,
258}
259
260/// Severity of a compilation diagnostic.
261#[allow(missing_docs)]
262#[derive(Clone, Copy, Debug, PartialEq, Eq)]
263#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
264pub enum DiagnosticSeverity {
265    Info,
266    Warning,
267    Error,
268}
269
270/// Structured non-fatal diagnostic attached to a compilation report.
271#[allow(missing_docs)]
272#[derive(Clone, Debug, PartialEq, Eq)]
273#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
274pub struct Diagnostic {
275    pub code: String,
276    pub severity: DiagnosticSeverity,
277    pub message: String,
278    pub pass: Option<PassId>,
279    pub resource: Option<ResourceId>,
280    pub undefined_cause: Option<UndefinedCause>,
281}
282
283/// Complete recording, retention, dependency, and allocation tables.
284///
285/// This is present only when compilation uses [`CompileOptions::full_report`](crate::CompileOptions::full_report).
286#[allow(missing_docs)]
287#[derive(Clone, Debug, Default, PartialEq, Eq)]
288#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
289pub struct FullCompilationReport {
290    pub nodes: Vec<NodeReport>,
291    pub culled_nodes: Vec<CulledNodeReport>,
292    pub resources: Vec<ResourceReport>,
293    pub views: Vec<ViewReport>,
294    pub accesses: Vec<AccessReport>,
295    pub values: Vec<ValueReport>,
296    pub dependencies: Vec<DependencyReport>,
297    pub roots: Vec<RootReport>,
298    pub allocations: Vec<AllocationReport>,
299    pub execution_segments: Vec<ExecutionSegmentReport>,
300    pub diagnostics: Vec<Diagnostic>,
301    #[cfg_attr(feature = "serde", serde(skip))]
302    pub debug_groups: Vec<DebugGroupReport>,
303}
304
305/// Optional compilation diagnostics selected by [`ReportLevel`](crate::ReportLevel).
306///
307/// The summary is always present when a report exists. [`Self::full`] is present
308/// only at full report level.
309#[allow(missing_docs)]
310#[derive(Clone, Debug, PartialEq, Eq)]
311#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
312pub struct CompilationReport {
313    pub summary: CompilationSummary,
314    pub full: Option<FullCompilationReport>,
315}