code wiki / _hdl_build / nx_raster_bench.nx
nx_raster_bench.nx source
↩ module page · 447 lines · 18712 B
1// nx_raster_bench.nx -- ARC-10/S12 PERF RUNG-0: the MEASURED sovereign-rasterizer baseline on the
2// REAL textured-Draw path (txtri_render: 3 edge fns + barycentric UV + 4-tap bilinear nx_txs_sample
3// per fragment -- the realistic pixel workload, NOT a null loop). Hardware clock CLOCK_MONOTONIC,
4// best-of-N reps. NEG-CONTROLS: (a) quarter-pixel scene must take materially less time (the timer
5// tracks the PIXEL workload, kills the synthetic-fps lie); (b) FLAT texture -> uniform fill (the
6// per-fragment sample path is live inside the timed frame). Baseline numbers gate every later
7// rasterizer optimization claim (ratchet). license_tier: ORIGINAL expect_exit: 0
8import "nx_syscalls.nx"
9import "nx_textured_tri.nx"
10import "nx_textured_tri_fast.nx"
11import "nx_pteam.nx" // E1-R3: band-parallel threaded raster
12const RB_MAGIC_1000000000: i64 = 1000000000
13const RB_MAGIC_1400: i64 = 1400
14const RB_MAGIC_10000: i64 = 10000
15const RB_MAGIC_4096: i64 = 4096
16
17const RB_W: i64 = 512
18const RB_H: i64 = 384
19const RB_QW: i64 = 256
20const RB_QH: i64 = 192
21const RB_FRAMES: i64 = 20
22const RB_REPS: i64 = 5
23const RB_TEXW: i64 = 64
24const RB_TEXH: i64 = 64
25const RB_SQ: i64 = 8
26
27func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
28func pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 }
29// print a x100 fixed-point value as d.ff
30func pd2(v100: i64) -> i64 {
31 pn(v100 / 100)
32 hw("." as *u8)
33 let f: i64 = v100 % 100
34 if f < 10 { hw("0" as *u8) }
35 pn(f)
36 return 0
37}
38// append a decimal into a byte buffer at pos, return new pos (for the report file)
39func sput(dst: *u8, pos: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ dst[pos+i]=s[i]; i=i+1 } return pos+i }
40func nput(dst: *u8, pos: i64, v: i64) -> i64 {
41 let b: *u8 = sys_mmap(32) as *u8
42 var x: i64 = v
43 var ng: i64 = 0
44 if x < 0 { ng=1; x=0-x }
45 var i: i64 = 31
46 if x == 0 { b[i]=48 as u8; i=i-1 }
47 while x > 0 { b[i]=(48+x%10) as u8; x=x/10; i=i-1 }
48 if ng == 1 { b[i]=45 as u8; i=i-1 }
49 var p: i64 = pos
50 var k: i64 = i + 1
51 while k < 32 { dst[p]=b[k]; p=p+1; k=k+1 }
52 return p
53}
54
55func rb_now(ts: *i64) -> i64 {
56 sys_clock_gettime_mono(ts)
57 return ts[0] * RB_MAGIC_1000000000 + ts[1]
58}
59
60func rb_clear(fb: *Image) -> i64 {
61 let fp: *u8 = fb.pixels
62 let n: i64 = fb.width * fb.height
63 var i: i64 = 0
64 while i < n { fp[i*3]=10 as u8; fp[i*3+1]=10 as u8; fp[i*3+2]=40 as u8; i=i+1 }
65 return 0
66}
67
68// the fixed scene: a full-frame QUAD (two textured triangles, shared diagonal) -- every framebuffer
69// pixel runs the full per-fragment path (edge tests + UV interp + bilinear sample)
70func rb_quad(fb: *Image, tex: *Image) -> i64 {
71 let w: i64 = fb.width
72 let h: i64 = fb.height
73 txtri_render(fb, tex, 0, 0, 0, 0, w-1, 0, 1023, 0, 0, h-1, 0, 1023)
74 txtri_render(fb, tex, w-1, 0, 1023, 0, w-1, h-1, 1023, 1023, 0, h-1, 0, 1023)
75 return 0
76}
77
78func rb_frame(fb: *Image, tex: *Image) -> i64 {
79 rb_clear(fb)
80 rb_quad(fb, tex)
81 return 0
82}
83
84// E1-R1 fast path (nx_textured_tri_fast): same scene through txtri_render_fast
85func rb_quad_fast(fb: *Image, tex: *Image) -> i64 {
86 let w: i64 = fb.width
87 let h: i64 = fb.height
88 txtri_render_fast(fb, tex, 0, 0, 0, 0, w-1, 0, 1023, 0, 0, h-1, 0, 1023)
89 txtri_render_fast(fb, tex, w-1, 0, 1023, 0, w-1, h-1, 1023, 1023, 0, h-1, 0, 1023)
90 return 0
91}
92func rb_frame_fast(fb: *Image, tex: *Image) -> i64 {
93 rb_clear(fb)
94 rb_quad_fast(fb, tex)
95 return 0
96}
97
98// varied equivalence scene: rotated UV assignments + a partially-offscreen triangle (bbox clamp
99// exercised) + a thin sliver, over a GRADIENT texture. u0a parameterizes the neg-control perturbation.
100func rb_scene_ref(fb: *Image, tex: *Image, u0a: i64) -> i64 {
101 rb_clear(fb)
102 txtri_render(fb, tex, 0-20, 0-10, 0, 0, 60, 8, 1023, 0, 5, 60, 0, 1023)
103 txtri_render(fb, tex, 0, 0, 0, 0, 47, 1, 1023, 0, 2, 3, 0, 1023)
104 // NEGATIVE + OUT-OF-RANGE UVs: forces the fast path's guarded fallback (per-fragment division +
105 // general clamp sampler) so the non-reciprocal lane is equivalence-proven too
106 txtri_render(fb, tex, 30, 26, 0-300, 0, 45, 44, RB_MAGIC_1400, 900, 12, 46, 200, 0-100)
107 // the u0a-perturbable triangle draws LAST so the neg-control perturbation is never overpainted
108 txtri_render(fb, tex, 10, 5, u0a, 0, 46, 20, 0, 1023, 4, 40, 512, 256)
109 return 0
110}
111func rb_scene_fast(fb: *Image, tex: *Image, u0a: i64) -> i64 {
112 rb_clear(fb)
113 txtri_render_fast(fb, tex, 0-20, 0-10, 0, 0, 60, 8, 1023, 0, 5, 60, 0, 1023)
114 txtri_render_fast(fb, tex, 0, 0, 0, 0, 47, 1, 1023, 0, 2, 3, 0, 1023)
115 txtri_render_fast(fb, tex, 30, 26, 0-300, 0, 45, 44, RB_MAGIC_1400, 900, 12, 46, 200, 0-100)
116 txtri_render_fast(fb, tex, 10, 5, u0a, 0, 46, 20, 0, 1023, 4, 40, 512, 256)
117 return 0
118}
119
120func rb_cksum(fb: *Image) -> i64 {
121 let p: *u8 = fb.pixels
122 let n: i64 = fb.width * fb.height * 3
123 var h: i64 = 7
124 var i: i64 = 0
125 while i < n { h = h * 131 + (p[i] as i64); i = i + 1 }
126 return h
127}
128
129// best-of-RB_REPS: each rep renders RB_FRAMES full frames; returns the best rep's ns
130func rb_bench(fb: *Image, tex: *Image, ts: *i64) -> i64 {
131 var best: i64 = 0
132 var r: i64 = 0
133 while r < RB_REPS {
134 let t0: i64 = rb_now(ts)
135 var f: i64 = 0
136 while f < RB_FRAMES { rb_frame(fb, tex); f = f + 1 }
137 let t1: i64 = rb_now(ts)
138 let d: i64 = t1 - t0
139 if best == 0 { best = d }
140 if d < best { best = d }
141 r = r + 1
142 }
143 return best
144}
145func rb_bench_fast(fb: *Image, tex: *Image, ts: *i64) -> i64 {
146 var best: i64 = 0
147 var r: i64 = 0
148 while r < RB_REPS {
149 let t0: i64 = rb_now(ts)
150 var f: i64 = 0
151 while f < RB_FRAMES { rb_frame_fast(fb, tex); f = f + 1 }
152 let t1: i64 = rb_now(ts)
153 let d: i64 = t1 - t0
154 if best == 0 { best = d }
155 if d < best { best = d }
156 r = r + 1
157 }
158 return best
159}
160
161// ---- E1-R3: threaded (band-parallel) raster via nx_pteam. Each band = a DISJOINT scanline strip -> no write
162// conflicts -> BIT-IDENTICAL to the single-thread fast path BY CONSTRUCTION. ctx=[fb, tex, nbands]. ----
163func rb_band_fn(band: i64, ctx: i64) -> i64 {
164 let c: *i64 = ctx as *i64
165 let fb: *Image = c[0] as *Image
166 let tex: *Image = c[1] as *Image
167 let nbands: i64 = c[2]
168 let h: i64 = fb.height
169 let w: i64 = fb.width
170 let bh: i64 = h / nbands
171 let y0: i64 = band * bh
172 var y1: i64 = y0 + bh
173 if band == nbands - 1 { y1 = h }
174 let fp: *u8 = fb.pixels
175 var y: i64 = y0
176 while y < y1 {
177 var x: i64 = 0
178 while x < w { let o: i64 = y * fb.stride + x * 3; fp[o] = 10 as u8; fp[o+1] = 10 as u8; fp[o+2] = 40 as u8; x = x + 1 }
179 y = y + 1
180 }
181 txtri_render_fast_clip(fb, tex, 0, 0, 0, 0, w-1, 0, 1023, 0, 0, h-1, 0, 1023, y0, y1)
182 txtri_render_fast_clip(fb, tex, w-1, 0, 1023, 0, w-1, h-1, 1023, 1023, 0, h-1, 0, 1023, y0, y1)
183 return 0
184}
185func rb_frame_threaded(team: *NxPTeam, fb: *Image, tex: *Image, ctx: *i64, nbands: i64) -> i64 {
186 ctx[0] = fb as i64; ctx[1] = tex as i64; ctx[2] = nbands
187 nx_pteam_run(team, rb_band_fn, ctx as i64)
188 return 0
189}
190func rb_bench_threaded(team: *NxPTeam, fb: *Image, tex: *Image, ctx: *i64, nbands: i64, ts: *i64) -> i64 {
191 var best: i64 = 0
192 var r: i64 = 0
193 while r < RB_REPS {
194 let t0: i64 = rb_now(ts)
195 var f: i64 = 0
196 while f < RB_FRAMES { rb_frame_threaded(team, fb, tex, ctx, nbands); f = f + 1 }
197 let t1: i64 = rb_now(ts)
198 let d: i64 = t1 - t0
199 if best == 0 { best = d }
200 if d < best { best = d }
201 r = r + 1
202 }
203 return best
204}
205
206func main() -> i64 {
207 hw("=== nx_raster_bench -- MEASURED baseline: sovereign textured Draw (bilinear per-fragment) ===\n" as *u8)
208 var fails: i64 = 0
209 let ts: *i64 = sys_mmap(16) as *i64
210
211 // checkerboard texture RB_TEXW x RB_TEXH, RB_SQ-px squares (bright 220 / dark 30)
212 let tex: *Image = nx_image_alloc(RB_TEXW, RB_TEXH, 1)
213 let tp: *u8 = tex.pixels
214 var yy: i64 = 0
215 while yy < RB_TEXH {
216 var xx: i64 = 0
217 while xx < RB_TEXW {
218 var val: i64 = 30
219 if ((xx / RB_SQ) + (yy / RB_SQ)) % 2 == 0 { val = 220 }
220 tp[yy*RB_TEXW + xx] = val as u8
221 xx = xx + 1
222 }
223 yy = yy + 1
224 }
225
226 let fb: *Image = nx_image_alloc(RB_W, RB_H, 3)
227 let fbq: *Image = nx_image_alloc(RB_QW, RB_QH, 3)
228
229 // T1 -- the scene is REAL: full-quad coverage + the checkerboard varies across the surface
230 rb_frame(fb, tex)
231 let fp: *u8 = fb.pixels
232 let npix: i64 = RB_W * RB_H
233 var cov: i64 = 0
234 var bright: i64 = 0
235 var dark: i64 = 0
236 var i: i64 = 0
237 while i < npix {
238 let r: i64 = fp[i*3] as i64
239 let b: i64 = fp[i*3+2] as i64
240 if r == b {
241 cov = cov + 1
242 if r >= 150 { bright = bright + 1 }
243 if r <= 90 { dark = dark + 1 }
244 }
245 i = i + 1
246 }
247 hw(" scene: coverage=" as *u8); pn(cov); hw("/" as *u8); pn(npix)
248 hw(" bright=" as *u8); pn(bright); hw(" dark=" as *u8); pn(dark); hw("\n" as *u8)
249 var t1: i64 = 0
250 if cov * 100 >= npix * 99 { if bright > 0 { if dark > 0 { t1 = 1 } } }
251 if t1 == 1 { hw("T1 PASS full-quad textured coverage, checkerboard sampled across the surface\n" as *u8) } else { fails=fails+1; hw("T1 FAIL scene not real\n" as *u8) }
252
253 // T2 -- deterministic frame (bit-identical re-render)
254 let c1: i64 = rb_cksum(fb)
255 rb_frame(fb, tex)
256 let c2: i64 = rb_cksum(fb)
257 var t2: i64 = 0
258 if c1 == c2 { t2 = 1 }
259 if t2 == 1 { hw("T2 PASS frame bit-deterministic across renders\n" as *u8) } else { fails=fails+1; hw("T2 FAIL nondeterministic frame\n" as *u8) }
260
261 // T3 -- THE MEASUREMENT (full res, best-of-REPS)
262 let best: i64 = rb_bench(fb, tex, ts)
263 let nsf: i64 = best / RB_FRAMES
264 let msf100: i64 = nsf / RB_MAGIC_10000
265 let mpxs: i64 = (npix * RB_FRAMES * 1000) / best
266 let nspx100: i64 = (best * 100) / (RB_FRAMES * npix)
267 hw("T3 MEASURED full 512x384 (" as *u8); pn(RB_REPS); hw(" reps x " as *u8); pn(RB_FRAMES); hw(" frames, best rep):\n" as *u8)
268 hw(" ns/frame=" as *u8); pn(nsf)
269 hw(" ms/frame=" as *u8); pd2(msf100)
270 hw(" Mpx/s=" as *u8); pn(mpxs)
271 hw(" ns/px=" as *u8); pd2(nspx100); hw("\n" as *u8)
272 var t3: i64 = 0
273 if best > 0 { t3 = 1 }
274 if t3 == 1 { hw("T3 PASS hardware-clock measurement captured\n" as *u8) } else { fails=fails+1; hw("T3 FAIL zero/negative timing\n" as *u8) }
275
276 // T4 -- NEG-CONTROL: quarter-pixel scene must be materially cheaper (timer tracks the pixel workload)
277 let bestq: i64 = rb_bench(fbq, tex, ts)
278 let nsfq: i64 = bestq / RB_FRAMES
279 let ratio: i64 = (bestq * 100) / best
280 hw(" quarter 256x192: ns/frame=" as *u8); pn(nsfq); hw(" quarter/full=" as *u8); pn(ratio); hw("%\n" as *u8)
281 var t4: i64 = 0
282 if ratio < 60 { t4 = 1 }
283 if t4 == 1 { hw("T4 PASS quarter-workload time collapses (~25% expected) -> the clock measures the raster work\n" as *u8) } else { fails=fails+1; hw("T4 FAIL timing does not track pixel count\n" as *u8) }
284
285 // T5 -- NEG-CONTROL: FLAT texture -> uniform fill (per-fragment sampling is live in the timed path)
286 let flat: *Image = nx_image_alloc(RB_TEXW, RB_TEXH, 1)
287 let flp: *u8 = flat.pixels
288 i = 0
289 while i < RB_TEXW*RB_TEXH { flp[i] = 128 as u8; i = i + 1 }
290 rb_frame(fbq, flat)
291 let qp: *u8 = fbq.pixels
292 var fbright: i64 = 0
293 var fdark: i64 = 0
294 i = 0
295 while i < RB_QW*RB_QH {
296 let r: i64 = qp[i*3] as i64
297 let b: i64 = qp[i*3+2] as i64
298 if r == b {
299 if r >= 150 { fbright = fbright + 1 }
300 if r <= 90 { fdark = fdark + 1 }
301 }
302 i = i + 1
303 }
304 var t5: i64 = 0
305 if fbright == 0 { if fdark == 0 { t5 = 1 } }
306 if t5 == 1 { hw("T5 PASS flat-texture neg-control uniform -> pattern comes from per-fragment sampling\n" as *u8) } else { fails=fails+1; hw("T5 FAIL flat texture produced checker variation\n" as *u8) }
307
308 // T6 -- E1-R1 FAST-PATH EQUIVALENCE: bit-identical to the reference on the bench quad AND a
309 // varied scene (rotated UVs + offscreen clamp + sliver, gradient texture); NEG-CONTROL: a
310 // perturbed fast scene must NOT match. DIAGNOSING form: per-leg verdicts + first-mismatch probe.
311 rb_frame(fb, tex)
312 let fb3: *Image = nx_image_alloc(RB_W, RB_H, 3)
313 rb_frame_fast(fb3, tex)
314 let rp3: *u8 = fb3.pixels
315 var qdiffs: i64 = 0
316 var qfirst: i64 = 0 - 1
317 i = 0
318 while i < npix*3 {
319 if fp[i] != rp3[i] { qdiffs = qdiffs + 1; if qfirst < 0 { qfirst = i } }
320 i = i + 1
321 }
322 hw(" T6 quad diff bytes=" as *u8); pn(qdiffs)
323 if qfirst >= 0 {
324 let qpx: i64 = (qfirst / 3) % RB_W
325 let qpy: i64 = (qfirst / 3) / RB_W
326 hw(" first@x=" as *u8); pn(qpx); hw(" y=" as *u8); pn(qpy)
327 hw(" ch=" as *u8); pn(qfirst % 3)
328 hw(" ref=" as *u8); pn(fp[qfirst] as i64)
329 hw(" fast=" as *u8); pn(rp3[qfirst] as i64)
330 }
331 hw("\n" as *u8)
332 let fbs2: *Image = nx_image_alloc(48, 48, 3)
333 let fbs3: *Image = nx_image_alloc(48, 48, 3)
334 let gtex: *Image = nx_image_alloc(16, 16, 1)
335 let gp: *u8 = gtex.pixels
336 i = 0
337 while i < 256 { gp[i] = ((i * 7 + (i / 16) * 3) % 256) as u8; i = i + 1 }
338 rb_scene_ref(fbs2, gtex, 1023)
339 rb_scene_fast(fbs3, gtex, 1023)
340 let sp2: *u8 = fbs2.pixels
341 let sp3: *u8 = fbs3.pixels
342 var sdiffs: i64 = 0
343 var sfirst: i64 = 0 - 1
344 i = 0
345 while i < 48*48*3 {
346 if sp2[i] != sp3[i] { sdiffs = sdiffs + 1; if sfirst < 0 { sfirst = i } }
347 i = i + 1
348 }
349 hw(" T6 varied diff bytes=" as *u8); pn(sdiffs)
350 if sfirst >= 0 {
351 let spx: i64 = (sfirst / 3) % 48
352 let spy: i64 = (sfirst / 3) / 48
353 hw(" first@x=" as *u8); pn(spx); hw(" y=" as *u8); pn(spy)
354 hw(" ref=" as *u8); pn(sp2[sfirst] as i64)
355 hw(" fast=" as *u8); pn(sp3[sfirst] as i64)
356 }
357 hw("\n" as *u8)
358 rb_scene_fast(fbs3, gtex, 500)
359 let seq_r: i64 = rb_cksum(fbs2)
360 let seq_n: i64 = rb_cksum(fbs3)
361 var t6: i64 = 0
362 if qdiffs == 0 { if sdiffs == 0 { if seq_n != seq_r { t6 = 1 } } }
363 if t6 == 1 { hw("T6 PASS fast path BIT-IDENTICAL to reference (quad + varied scene); perturbed neg-control detected\n" as *u8) } else { fails=fails+1; hw("T6 FAIL fast path not equivalent (or comparator dead)\n" as *u8) }
364
365 // T7 -- E1-R1 MEASURED (fast path, same protocol; the ratchet must MOVE, never regress)
366 let bestf: i64 = rb_bench_fast(fb, tex, ts)
367 let nsff: i64 = bestf / RB_FRAMES
368 let mpxsf: i64 = (npix * RB_FRAMES * 1000) / bestf
369 let nspxf100: i64 = (bestf * 100) / (RB_FRAMES * npix)
370 let spd100: i64 = (best * 100) / bestf
371 hw("T7 MEASURED fast path:\n" as *u8)
372 hw(" ns/frame=" as *u8); pn(nsff)
373 hw(" Mpx/s=" as *u8); pn(mpxsf)
374 hw(" ns/px=" as *u8); pd2(nspxf100)
375 hw(" speedup=" as *u8); pd2(spd100); hw("x\n" as *u8)
376 var t7: i64 = 0
377 if bestf > 0 { if spd100 >= 100 { t7 = 1 } }
378 if t7 == 1 { hw("T7 PASS fast path measured, no regression vs reference\n" as *u8) } else { fails=fails+1; hw("T7 FAIL fast path slower than reference\n" as *u8) }
379
380 // T8 -- E1-R3 THREADED raster (band-parallel via nx_pteam): BIT-IDENTICAL to the single fast path + measured speedup
381 var nbands: i64 = nx_hw_worker_count()
382 if nbands < 2 { nbands = 2 }
383 if nbands > RB_H { nbands = RB_H }
384 let team: *NxPTeam = nx_pteam_new(nbands)
385 let tctx: *i64 = sys_mmap(32) as *i64
386 rb_frame_fast(fb, tex)
387 let c_single: i64 = rb_cksum(fb)
388 rb_frame_threaded(team, fb, tex, tctx, nbands)
389 let c_thread: i64 = rb_cksum(fb)
390 var bid: i64 = 0
391 if c_single == c_thread { bid = 1 }
392 let bestt: i64 = rb_bench_threaded(team, fb, tex, tctx, nbands, ts)
393 let nsft: i64 = bestt / RB_FRAMES
394 let mpxst: i64 = (npix * RB_FRAMES * 1000) / bestt
395 let spdt: i64 = (bestf * 100) / bestt
396 hw("T8 THREADED raster: nbands=" as *u8); pn(nbands); hw(" ns/frame=" as *u8); pn(nsft); hw(" Mpx/s=" as *u8); pn(mpxst); hw(" speedup_vs_fast=" as *u8); pd2(spdt); hw("x bit-identical=" as *u8); pn(bid); hw("\n" as *u8)
397 var t8: i64 = 0
398 if bid == 1 { if bestt > 0 { t8 = 1 } }
399 if t8 == 1 { hw("T8 PASS threaded raster BIT-IDENTICAL to single fast path + measured (band-parallel via nx_pteam)\n" as *u8) } else { fails=fails+1; hw("T8 FAIL threaded not bit-identical or zero timing\n" as *u8) }
400 nx_pteam_shutdown(team)
401
402 // artifacts: viewable PPM + machine-readable baseline report
403 rb_frame(fb, tex)
404 let hdr: *u8 = "P6\n512 384\n255\n" as *u8
405 var hn: i64 = 0
406 while hdr[hn] != (0 as u8) { hn = hn + 1 }
407 let fd: i64 = sys_openat_wr("knowledge/nx_raster_bench.ppm\x00" as *u8, 0x1a4)
408 sys_write(fd, hdr, hn)
409 sys_write(fd, fp, npix*3)
410 sys_close(fd)
411
412 let rep: *u8 = sys_mmap(RB_MAGIC_4096) as *u8
413 var p: i64 = 0
414 p = sput(rep, p, "RASTER-BENCH rung-0 baseline (sovereign textured Draw, bilinear per-fragment)\n" as *u8)
415 p = sput(rep, p, "scene=fullquad 512x384 tex=64x64 checker reps=" as *u8)
416 p = nput(rep, p, RB_REPS)
417 p = sput(rep, p, " frames=" as *u8)
418 p = nput(rep, p, RB_FRAMES)
419 p = sput(rep, p, "\nns_per_frame=" as *u8)
420 p = nput(rep, p, nsf)
421 p = sput(rep, p, "\nmpx_per_s=" as *u8)
422 p = nput(rep, p, mpxs)
423 p = sput(rep, p, "\nns_per_px_x100=" as *u8)
424 p = nput(rep, p, nspx100)
425 p = sput(rep, p, "\nquarter_ns_per_frame=" as *u8)
426 p = nput(rep, p, nsfq)
427 p = sput(rep, p, "\nquarter_over_full_pct=" as *u8)
428 p = nput(rep, p, ratio)
429 p = sput(rep, p, "\nfast_ns_per_frame=" as *u8)
430 p = nput(rep, p, nsff)
431 p = sput(rep, p, "\nfast_mpx_per_s=" as *u8)
432 p = nput(rep, p, mpxsf)
433 p = sput(rep, p, "\nfast_ns_per_px_x100=" as *u8)
434 p = nput(rep, p, nspxf100)
435 p = sput(rep, p, "\nfast_speedup_x100=" as *u8)
436 p = nput(rep, p, spd100)
437 p = sput(rep, p, "\n" as *u8)
438 let fd2: i64 = sys_openat_wr("knowledge/nx_raster_bench.txt\x00" as *u8, 0x1a4)
439 sys_write(fd2, rep, p)
440 sys_close(fd2)
441 hw("artifacts -> knowledge/nx_raster_bench.ppm + knowledge/nx_raster_bench.txt\n" as *u8)
442
443 if fails == 0 { hw("RASTER-BENCH GREEN -- baseline banked; every later raster optimization must beat these numbers\n" as *u8); sys_exit(0); return 0 }
444 hw("RASTER-BENCH RED fails=" as *u8); pn(fails); hw("\n" as *u8)
445 sys_exit(1)
446 return 1
447}