code wiki / (root) / nx_gsplat_perf.nx

nx_gsplat_perf.nx source

↩ module page · 361 lines · 18613 B

1// nx_gsplat_perf.nx -- THE SPLAT RENDER BASELINE: a number for every performance claim to beat. 2// 3// WHY THIS ORGAN EXISTS. On 2026-08-23 the sovereign splat rasterizer's viewport stopped being a 4// compile-time 512x384 and became a parameter. Every performance claim made after that moment needs 5// a measured baseline, per stage, at the resolutions we actually intend to deliver. WITHOUT A 6// BASELINE AN IMPROVEMENT CLAIM IS UNFALSIFIABLE -- so this organ ships before any optimisation does. 7// 8// WHAT IT REPORTS, per viewport: total frame microseconds, plus the microseconds of each of the four 9// stages the renderer is COMPOSED FROM (project+sort, clear, blend, resolve), and the CONIC 10// EVALUATION count -- the deterministic cost unit gs_blend_rect already returns. Two renderers can be 11// compared in that currency without a stopwatch at all, which is what makes an optimisation provable 12// on a loaded box. 13// 14// THE BLEND FIGURE IS DERIVED (total - project - clear - resolve), never measured directly: measuring 15// it directly would require a second copy of the full-screen policy, and a second policy is a second 16// ruler. The subtraction is stated here so nobody reads it as an independent measurement. 17// 18// TIMING IS THE MINIMUM OF PF_ITERS RUNS. A minimum is the least contaminated estimator of the true 19// cost on a shared box -- the mean absorbs every interfering lane, and this box carries many. The 20// spread (max-min) is printed beside it so the reader can see how noisy the sample was rather than 21// trusting the minimum blindly. 22// 23// THE VIEWPORT LADDER IS NOT PICKED. Each rung is a resolution the estate already has a reason for: 24// the historic cap it just escaped, the derived gallery target read from the capture wire's own 25// recorded frame, and the 4K rung the beauty tier is aimed at. 26 27import "nx_syscalls.nx" 28import "nx_itrig.nx" 29import "nx_gsplat.nx" 30import "nx_gsplat_tile_lib.nx" 31import "nx_gate_verdict.nx" 32 33const PF_W64: i64 = 8 34const PF_ITERS: i64 = 3 // min-of-3; see header on why the minimum and not the mean 35 36// Scene: the SAME fixture shape nx_gsplat_res_gate already proves the renderer against, so the 37// baseline is taken on a scene the estate has already accepted rather than one invented here. 38const PF_CAMZ: i64 = 30 39const PF_RTAN: i64 = 250 40const PF_XSPAN: i64 = 10000 41const PF_YSPAN: i64 = 8000 42 43// The two scene densities: the proven 8x8 fixture, and a 32x32 that puts real pressure on the sort. 44const PF_GRID_A: i64 = 8 45const PF_GRID_B: i64 = 32 46 47// Viewport ladder, largest first so the one allocation covers every rung. 48const PF_NRES: i64 = 5 49const PF_W0: i64 = 3840 50const PF_H0: i64 = 2160 51const PF_W1: i64 = 1920 52const PF_H1: i64 = 1200 53const PF_W2: i64 = 1920 54const PF_H2: i64 = 1080 55const PF_W3: i64 = 1280 56const PF_H3: i64 = 720 57const PF_W4: i64 = 512 58const PF_H4: i64 = 384 59 60func pf_w_at(i: i64) -> i64 { 61 if i == 0 { return PF_W0 } 62 if i == 1 { return PF_W1 } 63 if i == 2 { return PF_W2 } 64 if i == 3 { return PF_W3 } 65 return PF_W4 66} 67func pf_h_at(i: i64) -> i64 { 68 if i == 0 { return PF_H0 } 69 if i == 1 { return PF_H1 } 70 if i == 2 { return PF_H2 } 71 if i == 3 { return PF_H3 } 72 return PF_H4 73} 74 75// Build a grid scene of grid*grid anisotropic gaussians spanning the model box. 76func pf_scene(gauss: *i64, grid: i64) -> i64 { 77 let ng: i64 = grid * grid 78 var i: i64 = 0 79 while i < ng { 80 let row: i64 = i / grid 81 let col: i64 = i - row * grid 82 let x: i64 = 0 - PF_XSPAN + col * (2 * PF_XSPAN / (grid - 1)) 83 let y: i64 = 0 - PF_YSPAN + row * (2 * PF_YSPAN / (grid - 1)) 84 gs_set_aniso(gauss, i, x, y, 0, 0, 0, 0 - gs_fxa(), PF_RTAN, 60 + i * 3, 200, 255 - i * 2, gs_fxa()) 85 i = i + 1 86 } 87 return ng 88} 89 90// Framebuffer checksum: the CORRECTNESS ANCHOR. Any optimisation of the rasterizer must reproduce 91// this number exactly at every rung -- a faster renderer that changes a pixel is a broken renderer, 92// and this is the one line that can tell those two apart. 93// PF_SUM_RADIX: the positional weight that makes the hash order-sensitive -- two frames with the same 94// pixels in a different order must not collide. PF_SUM_MOD: a prime modulus, present ONLY to keep the 95// running value inside i64 so the hash is defined rather than overflow-dependent. 96// Parallel-section budgets. PF_WORKERS is the worker count nx_gsplat_tile_gate already proves 97// byte-identical and spread across (T9/T10/T11). The three tile edges are POINTS ON THE CURVE the 98// gate sweeps, reported rather than chosen -- this organ publishes what each costs at the delivery 99// viewport instead of naming a favourite. PF_TILE_BUDGET is a DECLARED ceiling on tile-list slots: 100// a splat straddling many tiles takes one slot per tile, so the total is scene-dependent and the lib 101// REFUSES rather than truncating -- gt_entries() prints what was actually used so the next caller 102// sizes it from a measurement. 103const PF_WORKERS: i64 = 4 104const PF_NEDGE: i64 = 3 105const PF_EDGE0: i64 = 32 106const PF_EDGE1: i64 = 64 107const PF_EDGE2: i64 = 128 108const PF_TILE_BUDGET: i64 = 4000000 109const PF_SUM_RADIX: i64 = 31 110const PF_SUM_MOD: i64 = 1000000007 111func pf_sum(fb: *i64, n: i64) -> i64 { 112 var h: i64 = 0 113 var i: i64 = 0 114 while i < n { h = (h * PF_SUM_RADIX + fb[i]) % PF_SUM_MOD; i = i + 1 } 115 return h 116} 117 118func pf_pad(v: i64, width: i64) -> i64 { 119 var d: i64 = 1 120 var n: i64 = v 121 while n >= 10 { n = n / 10; d = d + 1 } 122 while d < width { gv_puts(" " as *u8); d = d + 1 } 123 return 0 124} 125 126func main() -> i64 { 127 gv_puts("nx_gsplat_perf -- sovereign splat rasterizer baseline (min of 3, microseconds)\n\n" as *u8) 128 129 let maxpx: i64 = PF_W0 * PF_H0 130 let maxng: i64 = PF_GRID_B * PF_GRID_B 131 let st: i64 = gs_stride_aniso() 132 133 // ONE allocation at the largest rung, reused by every smaller one. Sized from the ladder's own 134 // maximum, never from a chosen ceiling. 135 let gauss: *i64 = sys_mmap(maxng * st * PF_W64) as *i64 136 let acc: *i64 = sys_mmap(maxpx * 3 * PF_W64) as *i64 137 let trans: *i64 = sys_mmap(maxpx * PF_W64) as *i64 138 let fb: *i64 = sys_mmap(maxpx * PF_W64) as *i64 139 let depth: *i64 = sys_mmap(maxng * PF_W64) as *i64 140 let sxb: *i64 = sys_mmap(maxng * PF_W64) as *i64 141 let syb: *i64 = sys_mmap(maxng * PF_W64) as *i64 142 let pa: *i64 = sys_mmap(maxng * PF_W64) as *i64 143 let pb: *i64 = sys_mmap(maxng * PF_W64) as *i64 144 let pc: *i64 = sys_mmap(maxng * PF_W64) as *i64 145 let pdet: *i64 = sys_mmap(maxng * PF_W64) as *i64 146 let order: *i64 = sys_mmap(maxng * PF_W64) as *i64 147 let count: *i64 = sys_mmap((gs_nb() + 2) * PF_W64) as *i64 148 let explut: *i64 = sys_mmap(gs_expn() * PF_W64) as *i64 149 gs_build_explut(explut) 150 151 gv_puts(" bytes/pixel = 40 (acc x3 + trans + fb, i64 each) -- the resource contract\n" as *u8) 152 gv_puts(" scene = anisotropic grid, camz " as *u8); gv_num(PF_CAMZ) 153 gv_puts(", rtan " as *u8); gv_num(PF_RTAN); gv_puts("\n\n" as *u8) 154 155 var s: i64 = 0 156 while s < 2 { 157 var grid: i64 = PF_GRID_A 158 if s == 1 { grid = PF_GRID_B } 159 let ng: i64 = pf_scene(gauss, grid) 160 161 gv_puts("=== scene: " as *u8); gv_num(ng); gv_puts(" gaussians ===\n" as *u8) 162 gv_puts(" viewport pixels total_us proj_us clear_us blend_us resolve_us spread_us evals fb_checksum\n" as *u8) 163 164 var r: i64 = 0 165 while r < PF_NRES { 166 let w: i64 = pf_w_at(r) 167 let h: i64 = pf_h_at(r) 168 let npx: i64 = w * h 169 let focal: i64 = gs_focal_for(h) 170 let hw: i64 = w / 2 171 let hh: i64 = h / 2 172 173 // --- total frame, min of PF_ITERS ------------------------------------------------- 174 var best: i64 = 0 175 var worst: i64 = 0 176 var it: i64 = 0 177 while it < PF_ITERS { 178 let t0: i64 = sys_clock_now_us() 179 gs_render_aniso_at(gauss, ng, 0, PF_CAMZ, fb, acc, trans, depth, sxb, syb, pa, pb, pc, pdet, order, count, explut, 0, 0, 0, w, h, focal) 180 let t1: i64 = sys_clock_now_us() 181 let el: i64 = t1 - t0 182 if it == 0 { best = el; worst = el } 183 if el < best { best = el } 184 if el > worst { worst = el } 185 it = it + 1 186 } 187 188 // --- stage attribution: each exported stage timed on its own, min of PF_ITERS ------ 189 var bproj: i64 = 0 190 var bclear: i64 = 0 191 var bres: i64 = 0 192 it = 0 193 while it < PF_ITERS { 194 let p0: i64 = sys_clock_now_us() 195 gs_project_sort_at(gauss, ng, 0, PF_CAMZ, depth, sxb, syb, pa, pb, pc, pdet, order, count, hw, hh, focal) 196 let p1: i64 = sys_clock_now_us() 197 gs_clear_at(acc, trans, npx) 198 let p2: i64 = sys_clock_now_us() 199 gs_resolve(fb, acc, trans, npx, 0, 0, 0) 200 let p3: i64 = sys_clock_now_us() 201 if it == 0 { bproj = p1 - p0; bclear = p2 - p1; bres = p3 - p2 } 202 if p1 - p0 < bproj { bproj = p1 - p0 } 203 if p2 - p1 < bclear { bclear = p2 - p1 } 204 if p3 - p2 < bres { bres = p3 - p2 } 205 it = it + 1 206 } 207 // DERIVED, not measured: see header. 208 var blend: i64 = best - bproj - bclear - bres 209 if blend < 0 { blend = 0 } 210 211 // --- conic evaluations: the deterministic cost unit, independent of the clock ------- 212 // Re-run the full-screen policy's own blend accounting by summing what gs_blend_rect 213 // returns for each visible splat over the same rectangles the policy uses. 214 let vis: i64 = gs_project_sort_at(gauss, ng, 0, PF_CAMZ, depth, sxb, syb, pa, pb, pc, pdet, order, count, hw, hh, focal) 215 gs_clear_at(acc, trans, npx) 216 var evals: i64 = 0 217 var oi: i64 = 0 218 while oi < vis { 219 let g: i64 = order[oi] 220 let sx: i64 = sxb[g] 221 let sy: i64 = syb[g] 222 let ca: i64 = pa[g] 223 let cbv: i64 = pb[g] 224 let cc: i64 = pc[g] 225 let det: i64 = pdet[g] 226 let rx: i64 = gs_splat_rx(ca) 227 let ry: i64 = gs_splat_ry(cc) 228 var y0: i64 = sy - ry 229 if y0 < 0 { y0 = 0 } 230 var y1: i64 = sy + ry 231 if y1 >= h { y1 = h - 1 } 232 var x0: i64 = sx - rx 233 if x0 < 0 { x0 = 0 } 234 var x1: i64 = sx + rx 235 if x1 >= w { x1 = w - 1 } 236 evals = evals + gs_blend_rect(gauss, g, sx, sy, ca, cbv, cc, det, x0, x1, y0, y1, acc, trans, explut, w, ((count as i64) + (gs_nb()+1)*8) as *i64) 237 oi = oi + 1 238 } 239 240 // One clean canonical frame for the checksum: the stage-attribution pass above resolved 241 // against scratch it had already disturbed, so fb must be re-rendered before it is hashed. 242 gs_render_aniso_at(gauss, ng, 0, PF_CAMZ, fb, acc, trans, depth, sxb, syb, pa, pb, pc, pdet, order, count, explut, 0, 0, 0, w, h, focal) 243 let sum: i64 = pf_sum(fb, npx) 244 245 gv_puts(" " as *u8) 246 pf_pad(w, 5); gv_num(w); gv_puts("x" as *u8); gv_num(h) 247 if h < 1000 { gv_puts(" " as *u8) } 248 gv_puts(" " as *u8); pf_pad(npx, 9); gv_num(npx) 249 gv_puts(" " as *u8); pf_pad(best, 9); gv_num(best) 250 gv_puts(" " as *u8); pf_pad(bproj, 9); gv_num(bproj) 251 gv_puts(" " as *u8); pf_pad(bclear, 9); gv_num(bclear) 252 gv_puts(" " as *u8); pf_pad(blend, 10); gv_num(blend) 253 gv_puts(" " as *u8); pf_pad(bres, 10); gv_num(bres) 254 gv_puts(" " as *u8); pf_pad(worst - best, 13); gv_num(worst - best) 255 gv_puts(" " as *u8); pf_pad(evals, 11); gv_num(evals) 256 gv_puts(" " as *u8); pf_pad(sum, 15); gv_num(sum) 257 gv_puts("\n" as *u8) 258 259 r = r + 1 260 } 261 gv_puts("\n" as *u8) 262 s = s + 1 263 } 264 265 // ==== PARALLEL SECTION: the one speed-up that is ARITHMETIC rather than EMPIRICAL ============ 266 // Everything above is a wall-clock measurement, and this box currently carries six build lanes -- 267 // nx_membound reversed direction (0.935 then 1.464) between two runs of ONE binary, so a +-50% 268 // effect cannot be resolved here at all. Dividing the tiles among N forked workers is different in 269 // kind: every pixel belongs to exactly ONE tile, so the partition IS the synchronisation, no two 270 // workers touch the same acc/trans word, and the frame is byte-identical BY CONSTRUCTION. That 271 // property survives a noisy box when no timing does. 272 // 273 // The tile edge is NOT picked here. nx_gsplat_tile_gate sweeps 8/16/32/64/128/256 and proves every 274 // one byte-identical; this organ reports the CURVE at the delivery viewport so a caller chooses on 275 // a measurement rather than on a favourite number. gt_entries() is printed for the same reason: 276 // the next reader sizes the budget from what a scene actually used. 277 gv_puts("=== 4K PARALLEL: full-screen serial vs tiled workers (checksums must all match) ===\n" as *u8) 278 gv_puts(" tile_edge workers total_us entries evals fb_checksum\n" as *u8) 279 280 let pw: i64 = PF_W0 281 let ph: i64 = PF_H0 282 let ppx: i64 = pw * ph 283 let pfoc: i64 = gs_focal_for(ph) 284 let ng2: i64 = pf_scene(gauss, PF_GRID_B) 285 286 // acc/trans MUST be MAP_SHARED for the forked workers to composite into one frame -- a private 287 // mapping would give each child its own copy-on-write pixels and the parent would resolve an 288 // EMPTY buffer while every worker reported a full day's work. 289 let sacc: *i64 = sys_mmap_shared(ppx * 3 * PF_W64) as *i64 290 let stra: *i64 = sys_mmap_shared(ppx * PF_W64) as *i64 291 let sfb: *i64 = sys_mmap_shared(ppx * PF_W64) as *i64 292 293 // reference: the full-screen policy at 4K, the number the parallel path must reproduce and beat 294 let rt0: i64 = sys_clock_now_us() 295 gs_render_aniso_at(gauss, ng2, 0, PF_CAMZ, sfb, sacc, stra, depth, sxb, syb, pa, pb, pc, pdet, order, count, explut, 0, 0, 0, pw, ph, pfoc) 296 let rt1: i64 = sys_clock_now_us() 297 let refsum: i64 = pf_sum(sfb, ppx) 298 gv_puts(" full-screen serial " as *u8); pf_pad(rt1-rt0, 12); gv_num(rt1-rt0) 299 gv_puts(" - " as *u8); pf_pad(0, 10); gv_num(0) 300 gv_puts(" " as *u8); pf_pad(refsum, 15); gv_num(refsum); gv_puts("\n" as *u8) 301 302 var mismatches: i64 = 0 303 var ei: i64 = 0 304 while ei < PF_NEDGE { 305 var edge: i64 = PF_EDGE0 306 if ei == 1 { edge = PF_EDGE1 } 307 if ei == 2 { edge = PF_EDGE2 } 308 if gt_init_at(edge, PF_TILE_BUDGET, PF_WORKERS, pw, ph) == 0 { 309 var wi: i64 = 0 310 while wi < 2 { 311 var nw: i64 = 1 312 if wi == 1 { nw = PF_WORKERS } 313 let g0: i64 = sys_clock_now_us() 314 gt_render(gauss, ng2, 0, PF_CAMZ, sfb, sacc, stra, depth, sxb, syb, pa, pb, pc, pdet, order, count, explut, 0, 0, 0, nw) 315 let g1: i64 = sys_clock_now_us() 316 let gsum: i64 = pf_sum(sfb, ppx) 317 if gsum != refsum { mismatches = mismatches + 1 } 318 gv_puts(" " as *u8); pf_pad(edge, 10); gv_num(edge) 319 gv_puts(" " as *u8); pf_pad(nw, 8); gv_num(nw) 320 gv_puts(" " as *u8); pf_pad(g1-g0, 12); gv_num(g1-g0) 321 gv_puts(" " as *u8); pf_pad(gt_entries(), 9); gv_num(gt_entries()) 322 gv_puts(" " as *u8); pf_pad(gt_evals(), 11); gv_num(gt_evals()) 323 gv_puts(" " as *u8); pf_pad(gsum, 15); gv_num(gsum) 324 if gsum != refsum { gv_puts(" <== CHECKSUM MISMATCH" as *u8) } 325 gv_puts("\n" as *u8) 326 wi = wi + 1 327 } 328 // per-worker spread: a run that claimed N workers and idled N-1 of them is a serial run 329 // wearing a parallel label, and this is the line that tells them apart. 330 gv_puts(" per-worker evals:" as *u8) 331 var w2: i64 = 0 332 while w2 < PF_WORKERS { gv_puts(" " as *u8); gv_num(gt_worker_evals(w2)); w2 = w2 + 1 } 333 gv_puts("\n" as *u8) 334 } else { gv_puts(" tile init REFUSED at edge " as *u8); gv_num(edge); gv_puts(" -- budget or viewport rejected it BY NAME\n" as *u8) } 335 ei = ei + 1 336 } 337 gv_puts("\n checksum mismatches across every tiled configuration = " as *u8); gv_num(mismatches) 338 gv_puts(" (must be 0: a faster frame that moves a pixel is a broken frame)\n\n" as *u8) 339 340 gv_puts("NX-GSPLAT-PERF baseline recorded (blend_us is DERIVED by subtraction; evals is the\n" as *u8) 341 gv_puts("clock-free cost unit -- but note it counts PIXELS VISITED, not cost per pixel, so an\n" as *u8) 342 gv_puts("optimisation that makes each evaluation cheaper does NOT move it: the clock is the\n" as *u8) 343 gv_puts("instrument for that class, and the fb_checksum is what keeps the clock honest.)\n\n" as *u8) 344 345 // ---- BANKED NEGATIVE RESULT, 2026-08-23 ------------------------------------------------- 346 // Forward differencing + bracketed quotient (SHARP-GS SIGGRAPH 2026 contribution iii) was 347 // implemented in gs_blend_rect and MEASURED against these rows, then REVERTED. It was exactly 348 // correct -- all ten fb_checksums reproduced, and nx_fwddiff_equiv_gate proves the arithmetic 349 // identity 8/8 over 4,759,650 swept pixels -- but it was NOT faster here: on the least noisy 350 // rows (the low-resolution dense scene, where the box's own load contributes least) blend went 351 // 25,712 -> 31,721 us at 512x384 and 79,066 -> 96,147 us at 1280x720, i.e. ~22-23% SLOWER. 352 // It won only where scanlines are long (sparse scene, high resolution). The mechanism is that 353 // trading six multiplies and one divide for two adds plus two compare-loops pays only when the 354 // walk amortises over a long run of pixels; a small splat re-pays the per-scanline setup on 355 // every row. A published speed-up on a GPU accelerator did not transfer to this CPU rasterizer, 356 // and the honest record of that is worth more than the rewrite would have been. 357 gv_puts("SHARP-GS forward differencing was implemented, measured on these rows and REVERTED:\n" as *u8) 358 gv_puts("byte-identical (10/10 checksums) but ~22-23 percent SLOWER on the low-noise dense rows.\n" as *u8) 359 gv_puts("The incumbent is restored and proven byte-identical by rebuild. See nx_fwddiff_equiv_gate.\n" as *u8) 360 return 0 361}