code wiki / _hdl_build / nx_ng_radiance.nx
nx_ng_radiance.nx source
↩ module page · 212 lines · 12042 B
1// nx_ng_radiance.nx -- CAP-RADIANCE-FIELD, generation 8: a tiny NeRF. The defining recipe of NeRF/instant-ngp:
2// a COORDINATE NETWORK (MLP queried at sample positions) whose outputs are VOLUME-RENDERED into observations,
3// trained by INVERSE-RENDERING loss to recover the field from rendered measurements. Composes the two rungs
4// just built -- the autograd gradient engine (nx_nofloat_autograd) and the volume compositor (nx_ng_volrender)
5// -- on ONE Q16 integer tape: the composite C = sum_i w_i*f(x_i) is nfa_cmul (scale by the fixed transmittance
6// weight) + nfa_vadd, so the WHOLE chain (coord-MLP -> volume render -> loss) backprops end-to-end. No float.
7//
8// Honest gated proof (HARD evidence): a shared MLP f(x)=W2*relu(W1*x+b1)+b2 is applied at N sample coords ->
9// colors c_i; R observations C_r = sum_i w[r][i]*c_i (volume composite, weights = a fixed invertible
10// transmittance matrix) are matched to targets generated from a TRUE field. Gate:
11// T1 LEARNS -- inverse-rendering SSE loss collapses (the gradient flows MLP<-render<-loss),
12// T2 FIELD RECOVERED -- the trained net reproduces the true field at the samples (|f(x_i)-c*_i| small):
13// teeth = it learned the RIGHT field through the renderer, not just any loss drop,
14// T3 BIT-EXACT -- train twice from the same init -> identical integer weights (structural determinism),
15// T4 UNTRAINED -- the initial loss is genuinely large (not vacuous).
16// Sovereign: imports nx_nofloat_autograd + nx_syscalls (no float). license_tier: ORIGINAL expect_exit: 0
17import "nx_nofloat_autograd.nx"
18import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
19import "nx_syscalls.nx"
20const K_MAGIC_6553: i64 = 6553
21const K_MAGIC_1311: i64 = 1311
22const K_MAGIC_2048: i64 = 2048
23const K_MAGIC_9830: i64 = 9830
24const K_MAGIC_2000: i64 = 2000
25const K_MAGIC_8192: i64 = 8192
26const K_MAGIC_13107: i64 = 13107
27const K_MAGIC_26214: i64 = 26214
28const K_MAGIC_39321: i64 = 39321
29const K_MAGIC_52429: i64 = 52429
30const K_MAGIC_32768: i64 = 32768
31const K_MAGIC_16384: i64 = 16384
32const K_MAGIC_4096: i64 = 4096
33
34const RLOG: *u8 = "knowledge/status/ng_radiance.log"
35const Q16: i64 = 65536
36const NC: i64 = 4 // sample coords along the field
37const NH: i64 = 8 // hidden units
38const NR: i64 = 4 // volume-rendered observations (invertible weight matrix -> field recoverable)
39const EPOCHS: i64 = 6000
40const LRQ: i64 = 2048 // 1/32
41
42func rp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
43// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
44// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
45// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
46// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
47func rpn(v: i64) -> i64 { nxi_out(v); return 0 }
48func r_abs(v: i64) -> i64 { if v<0 { return 0-v } return v }
49func rl_ws(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
50// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
51// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
52// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
53// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
54func rl_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
55
56// build the full coord-MLP -> volume-render -> SSE graph. stores the 4 weight-leaf node ids in wn[0..3]
57// (W1,b1,W2,b2) and the N color-output node ids in cn[0..NC-1]. returns the SSE root node.
58func rad_build(tape: *i64, vals: *i64, st: *i64, W1p: *i64, b1p: *i64, W2p: *i64, b2p: *i64,
59 coords: *i64, wmat: *i64, targ: *i64, wn: *i64, cn: *i64) -> i64 {
60 st[0]=0; st[1]=0
61 let nW1: i64 = nfa_leaf(tape,vals,st, NH, 1, W1p, 0) // H x 1
62 let nb1: i64 = nfa_leaf(tape,vals,st, NH, 1, b1p, 0) // H x 1
63 let nW2: i64 = nfa_leaf(tape,vals,st, 1, NH, W2p, 0) // 1 x H
64 let nb2: i64 = nfa_leaf(tape,vals,st, 1, 1, b2p, 0) // 1 x 1
65 wn[0]=nW1; wn[1]=nb1; wn[2]=nW2; wn[3]=nb2
66 var i: i64 = 0
67 while i < NC {
68 let nxi: i64 = nfa_leaf(tape,vals,st, 1, 1, coords, i)
69 let nh: i64 = nfa_matvec(tape,vals,st, nW1, nxi) // H x 1
70 let nh1: i64 = nfa_vadd(tape,vals,st, nh, nb1)
71 let nr: i64 = nfa_relu(tape,vals,st, nh1)
72 let ncm: i64 = nfa_matvec(tape,vals,st, nW2, nr) // 1 x 1
73 let nci: i64 = nfa_vadd(tape,vals,st, ncm, nb2)
74 cn[i] = nci
75 i = i + 1
76 }
77 var root: i64 = 0 - 1
78 var r: i64 = 0
79 while r < NR {
80 var acc: i64 = 0 - 1
81 var j: i64 = 0
82 while j < NC {
83 let cm: i64 = nfa_cmul(tape,vals,st, cn[j], wmat[r*NC+j]) // w_rj * c_j (volume composite term)
84 if acc < 0 { acc = cm } else { acc = nfa_vadd(tape,vals,st, acc, cm) }
85 j = j + 1
86 }
87 let ntr: i64 = nfa_leaf(tape,vals,st, 1, 1, targ, r)
88 let nmr: i64 = nfa_mse(tape,vals,st, acc, ntr)
89 if root < 0 { root = nmr } else { root = nfa_vadd(tape,vals,st, root, nmr) }
90 r = r + 1
91 }
92 return root
93}
94
95func rad_init(W1p: *i64, b1p: *i64, W2p: *i64, b2p: *i64) -> i64 {
96 var k: i64 = 0
97 while k < NH {
98 W1p[k] = K_MAGIC_6553 + k * K_MAGIC_1311 // varied positive -> break unit symmetry
99 b1p[k] = 0 - (k * K_MAGIC_2048) // varied biases -> relu kinks at different x
100 W2p[k] = K_MAGIC_9830 - k * K_MAGIC_1311 // varied (some negative for k>=8 -- none here, all distinct)
101 k = k + 1
102 }
103 b2p[0] = 0
104 return 0
105}
106
107// train; fills Wf (4*NH cap, packed W1|b1|W2|b2), loss first/last, and cf[NC] = recovered field f(x_i).
108func rad_train(tape: *i64, vals: *i64, grads: *i64, st: *i64, coords: *i64, wmat: *i64, targ: *i64,
109 W1p: *i64, b1p: *i64, W2p: *i64, b2p: *i64, lf: *i64, ll: *i64, cf: *i64, trace: i64) -> i64 {
110 rad_init(W1p, b1p, W2p, b2p)
111 let wn: *i64 = sys_mmap(4*8) as *i64
112 let cn: *i64 = sys_mmap(NC*8) as *i64
113 let gW1: *i64 = sys_mmap(NH*8) as *i64
114 let gb1: *i64 = sys_mmap(NH*8) as *i64
115 let gW2: *i64 = sys_mmap(NH*8) as *i64
116 let gb2: *i64 = sys_mmap(8) as *i64
117 var ep: i64 = 0
118 while ep < EPOCHS {
119 let root: i64 = rad_build(tape,vals,st, W1p,b1p,W2p,b2p, coords,wmat,targ, wn,cn)
120 nfa_backward(tape,vals,grads, st[0], root)
121 if ep == 0 { *lf = nfa_val(tape,vals,root,0) }
122 *ll = nfa_val(tape,vals,root,0)
123 if trace == 1 { if ep % K_MAGIC_2000 == 0 { rp(" ep " as *u8); rpn(ep); rp(" loss=" as *u8); rpn(nfa_val(tape,vals,root,0)); rp("\n" as *u8) } }
124 var k: i64 = 0
125 while k < NH { gW1[k]=nfa_grad(tape,grads,wn[0],k); gb1[k]=nfa_grad(tape,grads,wn[1],k); gW2[k]=nfa_grad(tape,grads,wn[2],k); k=k+1 }
126 gb2[0] = nfa_grad(tape,grads,wn[3],0)
127 nfa_sgd(W1p, gW1, NH, LRQ); nfa_sgd(b1p, gb1, NH, LRQ); nfa_sgd(W2p, gW2, NH, LRQ); nfa_sgd(b2p, gb2, 1, LRQ)
128 ep = ep + 1
129 }
130 // recovered field: one more forward, read the color nodes
131 let root2: i64 = rad_build(tape,vals,st, W1p,b1p,W2p,b2p, coords,wmat,targ, wn,cn)
132 nfa_backward(tape,vals,grads, st[0], root2) // (harmless; keeps vals populated)
133 var i: i64 = 0
134 while i < NC { cf[i] = nfa_val(tape,vals, cn[i], 0); i = i + 1 }
135 return 0
136}
137
138func main() -> i64 {
139 rp("nx_ng_radiance: CAP-RADIANCE-FIELD -- a tiny NeRF (coord-MLP through volume render, Q16 no float)\n" as *u8)
140 let tape: *i64 = sys_mmap(512*7*8) as *i64
141 let vals: *i64 = sys_mmap(K_MAGIC_8192*8) as *i64
142 let grads: *i64 = sys_mmap(K_MAGIC_8192*8) as *i64
143 let st: *i64 = sys_mmap(2*8) as *i64
144
145 // sample coords + TRUE field c*(x) = x (linear field; nonlinear fields + positional encoding = follow-on)
146 let coords: *i64 = sys_mmap(NC*8) as *i64
147 coords[0]=K_MAGIC_13107; coords[1]=K_MAGIC_26214; coords[2]=K_MAGIC_39321; coords[3]=K_MAGIC_52429 // 0.2 0.4 0.6 0.8
148 let cstar: *i64 = sys_mmap(NC*8) as *i64
149 cstar[0]=K_MAGIC_13107; cstar[1]=K_MAGIC_26214; cstar[2]=K_MAGIC_39321; cstar[3]=K_MAGIC_52429 // c*(x)=x
150 // R volume-render weight vectors (diagonally-dominant transmittance -> invertible -> field recoverable)
151 let wmat: *i64 = sys_mmap(NR*NC*8) as *i64
152 wmat[0]=K_MAGIC_32768; wmat[1]=K_MAGIC_16384; wmat[2]=K_MAGIC_8192; wmat[3]=K_MAGIC_4096
153 wmat[4]=K_MAGIC_16384; wmat[5]=K_MAGIC_32768; wmat[6]=K_MAGIC_8192; wmat[7]=K_MAGIC_4096
154 wmat[8]=K_MAGIC_8192; wmat[9]=K_MAGIC_16384; wmat[10]=K_MAGIC_32768; wmat[11]=K_MAGIC_4096
155 wmat[12]=K_MAGIC_4096; wmat[13]=K_MAGIC_8192; wmat[14]=K_MAGIC_16384; wmat[15]=K_MAGIC_32768
156 // targets = volume-render the TRUE field (same accumulate-shift as nfa_cmul: (c*w)>>16)
157 let targ: *i64 = sys_mmap(NR*8) as *i64
158 var r: i64 = 0
159 while r < NR { var s: i64=0; var j: i64=0; while j<NC { s = s + ((cstar[j]*wmat[r*NC+j])>>16); j=j+1 } targ[r]=s; r=r+1 }
160
161 let W1p: *i64 = sys_mmap(NH*8) as *i64; let b1p: *i64 = sys_mmap(NH*8) as *i64
162 let W2p: *i64 = sys_mmap(NH*8) as *i64; let b2p: *i64 = sys_mmap(8) as *i64
163 let lf: *i64 = sys_mmap(8) as *i64; let ll: *i64 = sys_mmap(8) as *i64
164 let cf: *i64 = sys_mmap(NC*8) as *i64
165 rad_train(tape,vals,grads,st, coords,wmat,targ, W1p,b1p,W2p,b2p, lf,ll,cf, 1)
166
167 rp(" [measure] inverse-render SSE loss: start=" as *u8); rpn(*lf); rp(" after " as *u8); rpn(EPOCHS); rp(" steps=" as *u8); rpn(*ll); rp("\n" as *u8)
168 rp(" [measure] recovered field f(x_i) vs true c*(x_i):\n" as *u8)
169 var i: i64 = 0
170 while i < NC { rp(" x=" as *u8); rpn(coords[i]); rp(" f=" as *u8); rpn(cf[i]); rp(" c*=" as *u8); rpn(cstar[i]); rp(" |err|=" as *u8); rpn(r_abs(cf[i]-cstar[i])); rp("\n" as *u8); i=i+1 }
171
172 // T1 LEARNS: SSE collapses >= 80%
173 var t1: i64 = 0
174 if (*ll) * 5 < (*lf) { t1 = 1 }
175 // T2 FIELD RECOVERED: every |f(x_i)-c*_i| < Q16/8 (0.125)
176 var t2: i64 = 1
177 i = 0
178 while i < NC { if r_abs(cf[i]-cstar[i]) >= K_MAGIC_8192 { t2 = 0 } i = i + 1 }
179 // T4 UNTRAINED: started genuinely untrained
180 var t4: i64 = 0
181 if (*lf) > 0 { t4 = 1 }
182 // T3 BIT-EXACT: retrain from same init -> identical weights
183 let W1b: *i64 = sys_mmap(NH*8) as *i64; let b1b: *i64 = sys_mmap(NH*8) as *i64
184 let W2b: *i64 = sys_mmap(NH*8) as *i64; let b2b: *i64 = sys_mmap(8) as *i64
185 let lf2: *i64 = sys_mmap(8) as *i64; let ll2: *i64 = sys_mmap(8) as *i64; let cf2: *i64 = sys_mmap(NC*8) as *i64
186 rad_train(tape,vals,grads,st, coords,wmat,targ, W1b,b1b,W2b,b2b, lf2,ll2,cf2, 0)
187 var t3: i64 = 1
188 i = 0
189 while i < NH { if W1b[i]!=W1p[i] { t3=0 } if b1b[i]!=b1p[i] { t3=0 } if W2b[i]!=W2p[i] { t3=0 } i=i+1 }
190 if b2b[0]!=b2p[0] { t3=0 }
191
192 rp(" T1 learns(SSE>=80% down)=" as *u8); rpn(t1); rp(" T2 field-recovered=" as *u8); rpn(t2); rp(" T3 bit-exact=" as *u8); rpn(t3); rp(" T4 untrained-start=" as *u8); rpn(t4); rp("\n" as *u8)
193
194 var ok: i64 = 1
195 if t1 != 1 { ok = 0 }
196 if t2 != 1 { ok = 0 }
197 if t3 != 1 { ok = 0 }
198 if t4 != 1 { ok = 0 }
199
200 let logf: i64 = sys_openat_append(RLOG, 420)
201 if logf >= 0 {
202 rl_ws(logf, "NGRADIANCE authored=organ engine=Q16-coord-MLP-through-volrender loss_first=" as *u8); rl_wn(logf, *lf)
203 rl_ws(logf, " loss_last=" as *u8); rl_wn(logf, *ll); rl_ws(logf, " t1=" as *u8); rl_wn(logf, t1)
204 rl_ws(logf, " t2=" as *u8); rl_wn(logf, t2); rl_ws(logf, " t3=" as *u8); rl_wn(logf, t3); rl_ws(logf, " t4=" as *u8); rl_wn(logf, t4)
205 if ok==1 { rl_ws(logf, " verdict=GREEN\n" as *u8) } else { rl_ws(logf, " verdict=RED\n" as *u8) }
206 sys_close(logf)
207 }
208 rp(" verdict=" as *u8)
209 if ok == 1 { rp("GREEN (coord-network trained THROUGH the volume renderer recovers the field = a tiny NeRF)\n" as *u8); sys_exit(0); return 0 }
210 rp("RED\n" as *u8)
211 sys_exit(1); return 1
212}