nx_perceptual_render_test.nx
buildroot/runtime/nx_perceptual_render_test.nx
about
nx_perceptual_render_test.nx -- G1+ end-to-end per-perceptual-profile
rendering KAT.
Closes the cardinal structural diff vs DirectX with viewable
artifacts: the SAME triangle, rendered at the SAME coordinates,
produces DIFFERENT PPM byte sequences depending on the declared
nx_perceptual_profile. No other graphics stack on earth does
this; every incumbent bakes in human-trichromat sRGB defaults.
Pipeline per profile:
pack red (255,0,0,255) via nx_fb_pack_for_profile(profile) ->
profile-specific i64 packed cell value ->
nx_raster_triangle paints triangle interior pixels with that cell ->
nx_swap_present serializes fb -> PPM bytes ->
KAT verifies the data area's RGB bytes at a known interior pixel
match the per-profile expectation.
Three profiles exercised end-to-end:
HUMAN_NORMAL : RGBA8888 (R, G, B, A in bytes 0..3)
pack(255,0,0,255) -> 0xFF0000FF -> PPM RGB (255, 0, 0)
DOG_VIZSLA : dichromat Y+B in bytes 0..1
pack(255,0,0,255) -> 0x0000004D -> PPM RGB (77, 0, 0)
Y = (77*255 + 150*0 + 29*0 + 128) / 256 = 77
HONEYBEE : G+B+UV+A in bytes 0..3 (no R sensitivity)
pack(255,0,0,255) -> 0xFF000000 -> PPM RGB (0, 0, 0)
(red invisible to honeybee perceptual profile;
PPM extracts low 3 bytes; UV in byte 3 not visible
in 3-channel PPM -- 4-channel PAM at G2)
AVIAN tetrachromat is intentionally NOT in this demo: its packer
puts R in byte 0, G in byte 1, B in byte 2, UV in byte 3, so the
PPM RGB extraction sees identical bytes to HUMAN_NORMAL. Showing
the AVIAN UV-channel delta needs PAM or a custom UV-PPM extension,
queued for G2. This is honestly noted -- not a hack, just a
3-channel PPM limit.
Composes:
nx_framebuffer.nx (fb alloc + clear + cell layout)
nx_fb_perceptual.nx (per-profile packers; G1 shipped)
nx_raster_sw.nx (Pineda triangle rasterizer; G1 shipped)
dependencies 6 imports · 0 importers
imports: nx_syscalls.nxnx_perceptual_profile.nxnx_framebuffer.nxnx_fb_perceptual.nxnx_raster_sw.nxnx_swapchain.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| none |
functions
| 55 | func _ppr_render_triangle(fb: *i64, cell_color: i64) -> i64 |
| 61 | func _ppr_present(fb: *i64, out: *u8, cap: i64) -> i64 |
| 65 | func main() -> i64 |