gpu_validate/
gpu_validate.rs1fn main() {
7 println!("== GPU Preview Pipeline Validation ==");
9 println!();
10
11 println!("[1/4] Initializing wgpu device...");
12 let context = match mcraw_tui::preview::pipeline::device::PreviewGpuContext::new() {
13 Ok(ctx) => {
14 println!(" ✓ Device created");
15 println!(" ✓ Queue acquired");
16 ctx
17 }
18 Err(e) => {
19 println!(" ✗ FAILED: {}", e);
20 std::process::exit(1);
21 }
22 };
23
24 println!();
25 println!("[2/4] Creating compute pipeline + compiling WGSL shader...");
26 let ctx_arc = std::sync::Arc::new(context);
27 let mut pipeline = match mcraw_tui::preview::pipeline::GpuPreviewPipeline::new().init(ctx_arc.clone()) {
28 Ok(p) => {
29 println!(" ✓ SHADER COMPILED — all 15 OETFs loaded");
30 println!(" ✓ Pipeline cache pre-warmed with default combo");
31 p
32 }
33 Err(e) => {
34 println!(" ✗ FAILED: {}", e);
35 std::process::exit(1);
36 }
37 };
38
39 println!();
40 println!("[3/4] Processing synthetic 256x128 Bayer frame...");
41
42 const W: u32 = 256;
44 const H: u32 = 128;
45 let mut bayer: Vec<u16> = Vec::with_capacity((W * H) as usize);
46 for y in 0..H {
47 for x in 0..W {
48 let phase = (y & 1) * 2 + (x & 1); let val = match phase {
50 0 | 3 => { let r = ((x as f32 / W as f32) * 0.8 + 0.1) * 65535.0;
52 r as u16
53 }
54 1 | 2 => { let g = 0.5 * 65535.0 + ((y as f32 / H as f32) * 0.3 - 0.15) * 65535.0;
56 g as u16
57 }
58 _ => unreachable!(),
59 };
60 bayer.push(val);
61 }
62 }
63 println!(" ✓ Synthetic Bayer frame: {}x{}", W, H);
64
65 use mcraw_tui::preview::pipeline::params::PreviewParams;
67 let params = PreviewParams {
68 width: W,
69 height: H,
70 bayer_width: W,
71 bayer_height: H,
72 black_level: 64.0,
73 white_level: 4095.0,
74 exposure: 1.0,
75 wb_r: 1.0, wb_g: 1.0, wb_b: 1.0,
76 contrast: 1.0,
77 saturation: 1.0,
78 shadows: 0.0,
79 highlights: 0.0,
80 _align0: 0.0, _align1: 0.0,
81 ccm_row0: [1.0, 0.0, 0.0, 0.0],
82 ccm_row1: [0.0, 1.0, 0.0, 0.0],
83 ccm_row2: [0.0, 0.0, 1.0, 0.0],
84 color_space: 0,
85 transfer: 1, adjust_enabled: 0,
87 bayer_phase: 0,
88 compute_histogram: 0,
89 _pad0: 0, _pad1: 0, _pad2: 0, _pad3: 0, _pad4: 0, _pad5: 0, _pad6: 0,
90 };
91
92 let start = std::time::Instant::now();
93 match pipeline.process_and_readback(&bayer, ¶ms) {
94 Ok((rgba, out_w, out_h)) => {
95 let elapsed = start.elapsed();
96 println!(" ✓ GPU process + readback: {}x{} → {} bytes in {:?} ({:.0} fps)",
97 out_w, out_h, rgba.len(), elapsed, 1.0 / elapsed.as_secs_f64());
98 let expected_pixels = (out_w * out_h) as usize;
100 if rgba.len() == expected_pixels * 4 {
101 println!(" ✓ Output buffer size correct: {} RGBA pixels", expected_pixels);
102 } else {
103 println!(" ✗ Size mismatch: got {} bytes, expected {}", rgba.len(), expected_pixels * 4);
104 std::process::exit(1);
105 }
106 let non_zero = rgba.iter().filter(|&&b| b != 0).count();
108 if non_zero > 0 {
109 println!(" ✓ Output has {} non-zero bytes (image content verified)", non_zero);
110 } else {
111 println!(" ✗ All output bytes are zero — pipeline produced black frame");
112 std::process::exit(1);
113 }
114 }
115 Err(e) => {
116 println!(" ✗ FAILED: {}", e);
117 std::process::exit(1);
118 }
119 }
120
121 println!();
122 println!("[4/4] Testing all 15 transfer function combinations...");
123
124 use mcraw_tui::preview::pipeline::params::transfer_to_u32;
125 use mcraw_tui::color::TransferFunction;
126
127 let mut passed = 0u32;
128 let mut failed = 0u32;
129 for tf in TransferFunction::all() {
130 let mut params = params.clone();
131 params.transfer = transfer_to_u32(tf);
132 let start = std::time::Instant::now();
133 match pipeline.process_and_readback(&bayer, ¶ms) {
134 Ok((_, _, _)) => {
135 let elapsed = start.elapsed();
136 if elapsed.as_millis() < 5000 {
137 println!(" ✓ {:<20} {:>6?}", tf.name(), elapsed);
138 passed += 1;
139 } else {
140 println!(" ✗ {:<20} timed out", tf.name());
141 failed += 1;
142 }
143 }
144 Err(e) => {
145 println!(" ✗ {:<20} {}", tf.name(), e);
146 failed += 1;
147 }
148 }
149 }
150
151 println!();
152 println!("== RESULTS ==");
153 println!(" ✓ GPU device init: PASS");
154 println!(" ✓ WGSL compilation: PASS");
155 println!(" ✓ Synthetic frame: PASS");
156 println!(" ✓ OETF variants: {}/15 passed, {}/15 failed", passed, failed);
157
158 if failed == 0 {
159 println!();
160 println!(" 🎉 All checks passed — pipeline is fully functional on this GPU!");
161 0
162 } else {
163 println!();
164 println!(" ⚠ {} OETF variants failed — see above for details", failed);
165 1
166 };
167}