gpu_handle_types/exec_path.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3/// Which path a frame went down. Carried on per-call result types (an
4/// interop layer's import / export results) rather than process-global
5/// cells.
6///
7/// The reason in `CpuBounceFallback` is a `&'static str` **deliberately**
8/// — no allocation, no formatting, and CI can assert specific strings
9/// without string-slicing the whole output.
10#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
11#[non_exhaustive]
12pub enum ExecutionPath {
13 /// No run has completed yet — the initial state of a
14 /// freshly-constructed processor's metrics. Distinct from every
15 /// "work happened" path so a caller can tell "no measurement yet"
16 /// apart from "ran, took the CPU-bounce path". A metrics record's
17 /// default reports this; it never appears after a completed run.
18 NotRun,
19 /// The source resource was aliased into a `wgpu::Texture` / `wgpu::Buffer`
20 /// without any host or device-to-device copy on this frame.
21 ZeroCopy,
22 /// A **host-side** full-buffer copy was elided: the consumer referenced the
23 /// producer's existing CPU allocation (a refcount bump) instead of memcpy-ing
24 /// the payload into its own buffer. No GPU resource was aliased and no device
25 /// was involved at all.
26 ///
27 /// Deliberately NOT [`Self::ZeroCopy`], which asserts a GPU aliasing import —
28 /// conflating the two makes a pure-software path read as GPU zero-copy in
29 /// every matrix report. Deliberately NOT [`Self::CpuBounceFallback`] either:
30 /// no host memcpy ran, so it is not a bounce.
31 ///
32 /// Reported by software-encode input paths that take a new reference to a
33 /// decoded frame's existing CPU planes instead of copying them into the
34 /// encoder's input frame.
35 HostCopyElided,
36 /// Zero-copy modulo a GPU-side staging copy (e.g. the wgpu-GL OES→2D
37 /// blit, or a D3D11→D3D12 row-major stage). `copies` counts how
38 /// many on-device copies happened: `1` for the "single staging
39 /// copy" case; `2+` for forced bounce-and-rewrap. Distinguished
40 /// from `ZeroCopy` so callers gating on "no driver-side copy at
41 /// all" don't conflate them, and from `CpuBounceFallback` because
42 /// the staging cost is GPU-side.
43 ///
44 /// `reason` is an optional `&'static str` tag — same no-alloc,
45 /// CI-assertable rule as `CpuBounceFallback::reason` — naming the
46 /// specific GPU-local route that ran (e.g. which bonded CUDA→GPU
47 /// path), for diagnostics. `None` when the path has no finer label
48 /// worth pinning. It does **not** participate in the "how much work
49 /// happened" signal — `copies` does — but it is part of the variant's
50 /// `Eq`/`Hash`, so two `DeviceLocalCopy`s with the same `copies` but
51 /// different `reason` compare unequal.
52 DeviceLocalCopy { copies: u8, reason: Option<&'static str> },
53 /// Web only. The operation went through a browser API that is a copy
54 /// at the spec surface (`copyExternalImageToTexture`,
55 /// `new VideoFrame(canvas)`) executed **inside the browser** —
56 /// typically GPU-to-GPU, but unobservable and uncountable from wasm.
57 ///
58 /// Distinct from [`Self::DeviceLocalCopy`] (which asserts a counted,
59 /// known copy on a device the caller controls) and from
60 /// [`Self::CpuBounceFallback`] (no CPU memcpy ran on the caller's hot
61 /// path).
62 /// An option that silences cross-backend CPU-bounce warnings should
63 /// never silence this — it is the expected default on the web and
64 /// exists for visibility, not noise.
65 BrowserGpuCopy,
66 /// A prior import (any path) was reused this frame from the import
67 /// cache; no work happened in this call. Distinct from `ZeroCopy`
68 /// because the *original* import may have been a CPU upload — a
69 /// caller gating "is this frame zero-copy aliased?" must not
70 /// conflate the two.
71 CacheHit,
72 /// A CPU host memcpy ran on the per-frame hot path. The `reason`
73 /// disambiguates which call site flipped the path so a once-per-
74 /// reason bounce logger can warn exactly once per cause.
75 CpuBounceFallback { reason: &'static str },
76}