1use serde::Serialize;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
4pub enum CostMode {
5 Minimal,
6 HostRealistic,
7 FullResearchDebug,
8}
9
10impl CostMode {
11 pub fn as_str(self) -> &'static str {
12 match self {
13 Self::Minimal => "minimal",
14 Self::HostRealistic => "host_realistic",
15 Self::FullResearchDebug => "full_research_debug",
16 }
17 }
18
19 pub fn label(self) -> &'static str {
20 match self {
21 Self::Minimal => "Minimal mode",
22 Self::HostRealistic => "Host-realistic mode",
23 Self::FullResearchDebug => "Full research/debug mode",
24 }
25 }
26}
27
28#[derive(Clone, Debug, Serialize)]
29pub struct BufferCost {
30 pub name: String,
31 pub bytes_per_pixel: usize,
32 pub notes: String,
33}
34
35#[derive(Clone, Debug, Serialize)]
36pub struct StageCost {
37 pub stage: String,
38 pub approximate_ops_per_pixel: usize,
39 pub approximate_reads_per_pixel: usize,
40 pub approximate_writes_per_pixel: usize,
41 pub reduction_note: String,
42}
43
44#[derive(Clone, Debug, Serialize)]
45pub struct ResolutionFootprint {
46 pub width: usize,
47 pub height: usize,
48 pub total_pixels: usize,
49 pub memory_megabytes: f32,
50}
51
52#[derive(Clone, Debug, Serialize)]
53pub struct CostReport {
54 pub mode: CostMode,
55 pub buffers: Vec<BufferCost>,
56 pub stages: Vec<StageCost>,
57 pub footprints: Vec<ResolutionFootprint>,
58 pub estimated_total_ops_per_pixel: usize,
59 pub estimated_total_reads_per_pixel: usize,
60 pub estimated_total_writes_per_pixel: usize,
61 pub notes: Vec<String>,
62}
63
64pub fn build_cost_report(mode: CostMode) -> CostReport {
65 let (buffers, stages, notes) = match mode {
66 CostMode::Minimal => (
67 vec![
68 buffer("residual", 4, "single-channel scalar residual"),
69 buffer("response", 4, "single-channel hazard / trigger"),
70 buffer("alpha", 4, "single-channel alpha modulation"),
71 ],
72 vec![
73 stage("Residual evaluation", 8, 2, 1, "Fuse with resolve when possible"),
74 stage("Response update", 6, 2, 1, "May be reduced-resolution"),
75 stage("Blend modulation", 6, 2, 1, "Can be fused into TAA resolve"),
76 ],
77 vec![
78 "Minimal mode corresponds to fixed heuristic gating without full trust diagnostics."
79 .to_string(),
80 ],
81 ),
82 CostMode::HostRealistic => (
83 vec![
84 buffer("residual", 4, "single-channel scalar residual"),
85 buffer("depth disagreement", 4, "single-channel depth cue"),
86 buffer("normal disagreement", 4, "single-channel normal cue"),
87 buffer("motion disagreement", 4, "single-channel motion cue"),
88 buffer("neighborhood inconsistency", 4, "single-channel neighborhood cue"),
89 buffer("trust", 4, "single-channel supervisory trust"),
90 buffer("alpha", 4, "single-channel alpha modulation"),
91 buffer("intervention", 4, "single-channel hazard / response strength"),
92 ],
93 vec![
94 stage("Residual evaluation", 10, 2, 1, "Local arithmetic only"),
95 stage("Depth/normal disagreement", 12, 4, 2, "Can share reprojection fetches"),
96 stage("Motion / neighborhood proxies", 18, 8, 2, "Tile aggregation is viable"),
97 stage("Trust and alpha update", 14, 6, 3, "Trust may run at half resolution"),
98 stage("Blend modulation", 6, 2, 1, "Fuse with temporal resolve"),
99 ],
100 vec![
101 "Host-realistic mode excludes synthetic visibility hints and uses only signals plausible in an engine temporal pipeline."
102 .to_string(),
103 "The DSFB supervisory layer can be implemented with local operations and limited temporal memory, with expected cost scaling linearly with pixel count and amenable to reduced-resolution evaluation."
104 .to_string(),
105 "The framework is compatible with tiled and asynchronous GPU execution."
106 .to_string(),
107 ],
108 ),
109 CostMode::FullResearchDebug => (
110 vec![
111 buffer("residual", 4, "single-channel scalar residual"),
112 buffer("visibility hint", 4, "synthetic comparison/debug-only visibility cue"),
113 buffer("depth disagreement", 4, "single-channel depth cue"),
114 buffer("normal disagreement", 4, "single-channel normal cue"),
115 buffer("motion disagreement", 4, "single-channel motion cue"),
116 buffer("neighborhood inconsistency", 4, "single-channel neighborhood cue"),
117 buffer("thin proxy", 4, "single-channel thin/local-contrast cue"),
118 buffer("history instability", 4, "single-channel history instability cue"),
119 buffer("trust", 4, "single-channel supervisory trust"),
120 buffer("alpha", 4, "single-channel alpha modulation"),
121 buffer("intervention", 4, "single-channel hazard / response strength"),
122 buffer("state labels", 1, "debug structural-state labels"),
123 ],
124 vec![
125 stage("Residual evaluation", 10, 2, 1, "Local arithmetic only"),
126 stage("All proxy synthesis", 26, 12, 5, "Debug mode keeps all intermediate fields"),
127 stage("Grammar / trust update", 18, 8, 3, "Tile aggregation remains possible"),
128 stage("Alpha / intervention update", 8, 2, 2, "May be fused downstream"),
129 stage("Debug output writes", 4, 0, 5, "Debug-only cost, not required in deployment"),
130 ],
131 vec![
132 "Full research/debug mode keeps all intermediate cues and state exports for ablation and report generation."
133 .to_string(),
134 "Synthetic visibility hints in this mode are intended only for comparison, not as a deployment claim."
135 .to_string(),
136 ],
137 ),
138 };
139
140 let estimated_total_ops_per_pixel = stages
141 .iter()
142 .map(|stage| stage.approximate_ops_per_pixel)
143 .sum();
144 let estimated_total_reads_per_pixel = stages
145 .iter()
146 .map(|stage| stage.approximate_reads_per_pixel)
147 .sum();
148 let estimated_total_writes_per_pixel = stages
149 .iter()
150 .map(|stage| stage.approximate_writes_per_pixel)
151 .sum();
152 let bytes_per_pixel = buffers
153 .iter()
154 .map(|buffer| buffer.bytes_per_pixel)
155 .sum::<usize>();
156 let footprints = [(1280usize, 720usize), (1920, 1080), (3840, 2160)]
157 .into_iter()
158 .map(|(width, height)| ResolutionFootprint {
159 width,
160 height,
161 total_pixels: width * height,
162 memory_megabytes: bytes_per_pixel as f32 * (width * height) as f32 / (1024.0 * 1024.0),
163 })
164 .collect();
165
166 CostReport {
167 mode,
168 buffers,
169 stages,
170 footprints,
171 estimated_total_ops_per_pixel,
172 estimated_total_reads_per_pixel,
173 estimated_total_writes_per_pixel,
174 notes,
175 }
176}
177
178fn buffer(name: &str, bytes_per_pixel: usize, notes: &str) -> BufferCost {
179 BufferCost {
180 name: name.to_string(),
181 bytes_per_pixel,
182 notes: notes.to_string(),
183 }
184}
185
186fn stage(
187 stage: &str,
188 approximate_ops_per_pixel: usize,
189 approximate_reads_per_pixel: usize,
190 approximate_writes_per_pixel: usize,
191 reduction_note: &str,
192) -> StageCost {
193 StageCost {
194 stage: stage.to_string(),
195 approximate_ops_per_pixel,
196 approximate_reads_per_pixel,
197 approximate_writes_per_pixel,
198 reduction_note: reduction_note.to_string(),
199 }
200}