Skip to main content

jxr_core/
report.rs

1//! Observable routing decisions for hybrid decode.
2
3use alloc::vec::Vec;
4
5use crate::{BackendKind, BackendRequest};
6
7/// Ordered decode and reconstruction phases.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum DecodeStage {
10    Parse,
11    EntropyDecode,
12    InverseScan,
13    CoefficientRemap,
14    DcLowPassPrediction,
15    DequantizeAndFirstInverseTransform,
16    FirstOverlap,
17    HighPassPrediction,
18    SecondInverseTransform,
19    SecondOverlap,
20    ChromaReconstruction,
21    ColorAndAlphaConversion,
22    CropClipAndPack,
23    HostReadback,
24}
25
26/// Concrete implementation which owned a stage.
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28pub enum StageExecutor {
29    CpuScalar,
30    CpuSimd,
31    Metal,
32    Cuda,
33}
34
35impl StageExecutor {
36    #[must_use]
37    pub const fn backend(self) -> BackendKind {
38        match self {
39            Self::CpuScalar | Self::CpuSimd => BackendKind::Cpu,
40            Self::Metal => BackendKind::Metal,
41            Self::Cuda => BackendKind::Cuda,
42        }
43    }
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
47pub struct StageReport {
48    pub stage: DecodeStage,
49    pub executor: StageExecutor,
50}
51
52/// Why an automatic request selected CPU before device submission.
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
54pub enum FallbackReason {
55    WorkloadBelowThreshold,
56    BackendNotCompiled,
57    DeviceUnavailable,
58    UnsupportedFormat,
59    PipelineIncomplete,
60    ResourceLimit,
61}
62
63/// Requested route, selected route, and per-stage ownership.
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct DecodeReport {
66    pub requested: BackendRequest,
67    pub selected: BackendKind,
68    pub fallback: Option<FallbackReason>,
69    pub stages: Vec<StageReport>,
70}
71
72impl DecodeReport {
73    #[must_use]
74    pub fn cpu(requested: BackendRequest) -> Self {
75        Self {
76            requested,
77            selected: BackendKind::Cpu,
78            fallback: None,
79            stages: Vec::new(),
80        }
81    }
82
83    #[must_use]
84    pub fn executor_for(&self, stage: DecodeStage) -> Option<StageExecutor> {
85        self.stages
86            .iter()
87            .find(|entry| entry.stage == stage)
88            .map(|entry| entry.executor)
89    }
90}