nx_nxa_gpu_gate.nx source
↩ module page · 243 lines · 13141 B
1// Qualify native GPU geometry packing with IEEE-754 witnesses and real NXA assets.
2import "nx_syscalls.nx"
3import "nx_gate_verdict.nx"
4import "nx_nxa_gpu_lib.nx"
5const GG_WORD: i64=8
6const GG_TOC: i64=4
7const GG_SECTIONS: i64=2
8const GG_VERT: i64=GG_TOC+GG_SECTIONS*GG_TOC
9const GG_TRIS: i64=GG_VERT+1+NGP_COMPONENTS
10const GG_WORDS: i64=GG_TRIS+1+NGP_COMPONENTS
11const GG_ONE_F32: i64=1065353216 // IEEE-754 +1
12const GG_NEG_TWO_F32: i64=3221225472 // IEEE-754 -2
13const GG_ROUND_INPUT: i64=16777217 // 2^24+1: midpoint, rounds to even.
14const GG_ROUND_F32: i64=1266679808 // IEEE-754 2^24
15const GG_SENTINEL: i64=165
16
17func gg_seal(h: *i64) -> i64 {
18 h[7]=nxa_check2(1,((h as i64)+GG_VERT*GG_WORD) as *i64,1+NGP_COMPONENTS)
19 h[11]=nxa_check2(1,((h as i64)+GG_TRIS*GG_WORD) as *i64,1+NGP_COMPONENTS)
20 h[3]=nxa_check2(1,((h as i64)+GG_TOC*GG_WORD) as *i64,GG_SECTIONS*GG_TOC)
21 return 0
22}
23
24const GG_SKIN_SECTIONS: i64=3
25const GG_SKIN_VERT: i64=GG_TOC+GG_SKIN_SECTIONS*GG_TOC
26const GG_SKIN_SKEL: i64=GG_SKIN_VERT+1+NGP_COMPONENTS
27const GG_SKIN_DATA: i64=GG_SKIN_SKEL+1+NGP_SKEL_WORDS
28const GG_SKIN_TOTAL: i64=GG_SKIN_DATA+1+NGP_SKIN_WORDS
29const GG_HALF_F32: i64=1056964608 // IEEE-754 1/2
30const GG_QUARTER_F32: i64=1048576000 // IEEE-754 1/4
31const GG_UV_MAX_F32: i64=1065352960 // IEEE-754 largest unsigned Q16 fractional coordinate.
32const GG_EIGHTH_F32: i64=1040187392 // IEEE-754 1/8
33func gg_skin_seal(h: *i64) -> i64 {
34 var s: i64=0
35 while s<GG_SKIN_SECTIONS {
36 let e: i64=GG_TOC+s*GG_TOC
37 h[e+3]=nxa_check2(1,((h as i64)+h[e+1]) as *i64,h[e+2])
38 s=s+1
39 }
40 h[3]=nxa_check2(1,((h as i64)+GG_TOC*GG_WORD) as *i64,GG_SKIN_SECTIONS*GG_TOC)
41 return 0
42}
43func gg_skin(c: *i64) -> i64 {
44 let h: *i64=sys_mmap(GG_SKIN_TOTAL*GG_WORD) as *i64
45 let b: *u8=h as *u8
46 let n: i64=GG_SKIN_TOTAL*GG_WORD
47 h[0]=nxa_magic();h[1]=NXA_VER;h[2]=GG_SKIN_SECTIONS
48 h[4]=nxa_tag4("VERT" as *u8);h[5]=GG_SKIN_VERT*GG_WORD;h[6]=1+NGP_COMPONENTS
49 h[8]=nxa_tag4("SKEL" as *u8);h[9]=GG_SKIN_SKEL*GG_WORD;h[10]=1+NGP_SKEL_WORDS
50 h[12]=nxa_tag4("SKIN" as *u8);h[13]=GG_SKIN_DATA*GG_WORD;h[14]=1+NGP_SKIN_WORDS
51 h[GG_SKIN_VERT]=1;h[GG_SKIN_SKEL]=1;h[GG_SKIN_DATA]=1
52 let w: i64=GG_SKIN_DATA+1+NGP_SKIN_INFLUENCES
53 h[w]=NGP_WEIGHT_ONE/2;h[w+1]=NGP_WEIGHT_ONE/4
54 h[w+2]=NGP_WEIGHT_ONE/8;h[w+3]=NGP_WEIGHT_ONE/8;gg_skin_seal(h)
55 let need: i64=NGP_SKIN_WORDS*NGP_GPU_WORD
56 let out: *u8=sys_mmap(need+1)
57 let bits: *u32=out as *u32
58 out[need]=GG_SENTINEL as u8
59 gv_check_eq("skin byte requirement",ngp_skin_bytes(b,n),need,c)
60 gv_check_eq("skin packed",ngp_skin(b,n,out,need),need,c)
61 gv_check_eq("skin joint zero exact",bits[0] as i64,0,c)
62 gv_check_eq("skin half weight exact",bits[NGP_SKIN_INFLUENCES] as i64,GG_HALF_F32,c)
63 gv_check_eq("skin quarter weight exact",bits[NGP_SKIN_INFLUENCES+1] as i64,GG_QUARTER_F32,c)
64 gv_check_eq("skin eighth weight exact",bits[NGP_SKIN_INFLUENCES+2] as i64,GG_EIGHTH_F32,c)
65 gv_check_eq("skin trailing guard",out[need] as i64,GG_SENTINEL,c)
66 gv_check_eq("skin short destination",ngp_skin(b,n,out,need-1),NGP_E_OUTPUT,c)
67 gv_check_eq("skin overlapping destination",ngp_skin(b,n,b,need),NGP_E_OVERLAP,c)
68 out[0]=GG_SENTINEL as u8
69 h[GG_SKIN_DATA+NGP_SKIN_INFLUENCES]=1;gg_skin_seal(h)
70 gv_check_eq("skin late invalid joint",ngp_skin(b,n,out,need),NGP_E_SKIN_JOINT,c)
71 gv_check_eq("skin refusal preserves output",out[0] as i64,GG_SENTINEL,c)
72 h[GG_SKIN_DATA+NGP_SKIN_INFLUENCES]=0;h[w+3]=0-1;gg_skin_seal(h)
73 gv_check_eq("skin negative weight",ngp_skin(b,n,out,need),NGP_E_SKIN_WEIGHT,c)
74 h[w+3]=NGP_WEIGHT_ONE+1;gg_skin_seal(h)
75 gv_check_eq("skin excessive weight",ngp_skin(b,n,out,need),NGP_E_SKIN_WEIGHT,c)
76 h[w+3]=0;gg_skin_seal(h)
77 gv_check_eq("skin nonunit weight sum",ngp_skin(b,n,out,need),NGP_E_SKIN_WEIGHT,c)
78 h[w+3]=NGP_WEIGHT_ONE/8;h[GG_SKIN_VERT]=0;h[6]=1;gg_skin_seal(h)
79 gv_check_eq("skin vertex count mismatch",ngp_skin(b,n,out,need),NGP_E_SKIN_COUNT,c)
80 sys_munmap(out,need+1);sys_munmap(b,n)
81 return 0
82}
83
84func gg_texcoords(c: *i64) -> i64 {
85 let n: i64=GG_SKIN_TOTAL*GG_WORD
86 let h: *i64=sys_mmap(n) as *i64
87 let b: *u8=h as *u8
88 h[0]=nxa_magic();h[1]=NXA_VER;h[2]=GG_SKIN_SECTIONS
89 h[4]=nxa_tag4("VERT" as *u8);h[5]=GG_SKIN_VERT*GG_WORD;h[6]=1+NGP_COMPONENTS
90 h[8]=nxa_tag4("SKEL" as *u8);h[9]=GG_SKIN_SKEL*GG_WORD;h[10]=1+NGP_SKEL_WORDS
91 h[12]=nxa_tag4("TEXC" as *u8);h[13]=GG_SKIN_DATA*GG_WORD;h[14]=NGP_TEXC_HEADER+NGP_TEXC_STRIDE
92 h[GG_SKIN_VERT]=1;h[GG_SKIN_SKEL]=1;h[GG_SKIN_DATA]=1
93 h[GG_SKIN_DATA+1]=NGP_TEXC_STRIDE;h[GG_SKIN_DATA+2]=1
94 let uv: i64=GG_SKIN_DATA+NGP_TEXC_HEADER
95 h[uv]=NGP_TEXC_ONE/2;h[uv+1]=NGP_TEXC_ONE/4
96 gg_skin_seal(h)
97 let need: i64=NGP_TEXC_UV*NGP_GPU_WORD
98 let out: *u8=sys_mmap(need+1)
99 let bits: *u32=out as *u32
100 out[need]=GG_SENTINEL as u8
101 gv_check_eq("UV byte requirement",ngp_texcoord_bytes(b,n),need,c)
102 gv_check_eq("UV packed",ngp_texcoords(b,n,out,need),need,c)
103 gv_check_eq("UV half exact",bits[0] as i64,GG_HALF_F32,c)
104 gv_check_eq("UV quarter exact",bits[1] as i64,GG_QUARTER_F32,c)
105 gv_check_eq("UV trailing guard",out[need] as i64,GG_SENTINEL,c)
106 gv_check_eq("UV short destination",ngp_texcoords(b,n,out,need-1),NGP_E_OUTPUT,c)
107 gv_check_eq("UV overlap refusal",ngp_texcoords(b,n,b,need),NGP_E_OVERLAP,c)
108 out[0]=GG_SENTINEL as u8;h[uv+1]=NGP_TEXC_ONE;gg_skin_seal(h)
109 gv_check_eq("UV late excessive value refused",ngp_texcoords(b,n,out,need),NGP_E_TEXC_VALUE,c)
110 gv_check_eq("UV rejection preserves output",out[0] as i64,GG_SENTINEL,c)
111 h[uv+1]=0-1;gg_skin_seal(h)
112 gv_check_eq("UV negative value refused",ngp_texcoords(b,n,out,need),NGP_E_TEXC_VALUE,c)
113 h[uv+1]=0;h[uv+2]=1;gg_skin_seal(h)
114 gv_check_eq("UV owning joint outside skeleton refused",ngp_texcoords(b,n,out,need),NGP_E_TEXC_VALUE,c)
115 h[uv+2]=0;h[GG_SKIN_DATA+1]=NGP_TEXC_STRIDE-1;gg_skin_seal(h)
116 gv_check_eq("UV stride mismatch refused",ngp_texcoords(b,n,out,need),NGP_E_TEXC_SHAPE,c)
117 h[GG_SKIN_DATA+1]=NGP_TEXC_STRIDE;h[GG_SKIN_DATA]=0;gg_skin_seal(h)
118 gv_check_eq("UV vertex count mismatch refused",ngp_texcoords(b,n,out,need),NGP_E_TEXC_SHAPE,c)
119 h[GG_SKIN_DATA]=1;h[14]=NGP_TEXC_HEADER+NGP_TEXC_STRIDE-1;gg_skin_seal(h)
120 gv_check_eq("UV short payload refused",ngp_texcoords(b,n,out,need),NGP_E_TEXC_SHAPE,c)
121 h[14]=NGP_TEXC_HEADER+NGP_TEXC_STRIDE;h[uv]=0;h[uv+1]=NGP_TEXC_ONE-1;gg_skin_seal(h)
122 gv_check_eq("UV boundary values packed",ngp_texcoords(b,n,out,need),need,c)
123 gv_check_eq("UV zero exact",bits[0] as i64,0,c)
124 gv_check_eq("UV largest Q16 coordinate exact",bits[1] as i64,GG_UV_MAX_F32,c)
125 h[uv]=1
126 gv_check_eq("UV corrupt checksum refused",ngp_texcoords(b,n,out,need),0-3,c)
127 sys_munmap(out,need+1);sys_munmap(b,n)
128 return 0
129}
130func gg_normals(c: *i64) -> i64 {
131 let vertices: i64=NGP_COMPONENTS
132 let ta: i64=GG_VERT+1+vertices*NGP_COMPONENTS
133 let n: i64=(ta+1+NGP_COMPONENTS)*GG_WORD
134 let h: *i64=sys_mmap(n) as *i64
135 let b: *u8=h as *u8
136 h[0]=nxa_magic();h[1]=NXA_VER;h[2]=GG_SECTIONS
137 h[4]=nxa_tag4("VERT" as *u8);h[5]=GG_VERT*GG_WORD;h[6]=1+vertices*NGP_COMPONENTS
138 h[8]=nxa_tag4("TRIS" as *u8);h[9]=ta*GG_WORD;h[10]=1+NGP_COMPONENTS
139 h[GG_VERT]=vertices;h[GG_VERT+1+NGP_COMPONENTS]=2;h[GG_VERT+2+NGP_COMPONENTS*2]=2
140 h[ta]=1;h[ta+1]=0;h[ta+2]=1;h[ta+3]=2
141 h[7]=nxa_check2(1,((h as i64)+h[5]) as *i64,h[6])
142 h[11]=nxa_check2(1,((h as i64)+h[9]) as *i64,h[10])
143 h[3]=nxa_check2(1,((h as i64)+GG_TOC*GG_WORD) as *i64,GG_SECTIONS*GG_TOC)
144 let need: i64=vertices*NGP_COMPONENTS*NGP_GPU_WORD
145 let out: *u8=sys_mmap(need+1);let bits: *u32=out as *u32
146 out[need]=GG_SENTINEL as u8
147 gv_check_eq("normals packed",ngp_normals(b,n,out,need),need,c)
148 gv_check_eq("normal perpendicular x",bits[0] as i64,0,c)
149 gv_check_eq("normal perpendicular y",bits[1] as i64,0,c)
150 gv_check_eq("normal unit z",bits[2] as i64,GG_ONE_F32,c)
151 gv_check_eq("last vertex normal unit z",bits[vertices*NGP_COMPONENTS-1] as i64,GG_ONE_F32,c)
152 gv_check_eq("normal output guard",out[need] as i64,GG_SENTINEL,c)
153 gv_check_eq("normal short output",ngp_normals(b,n,out,need-1),NGP_E_OUTPUT,c)
154 gv_check_eq("normal overlapping source",ngp_normals(b,n,b,need),NGP_E_OVERLAP,c)
155 h[ta+3]=vertices
156 h[11]=nxa_check2(1,((h as i64)+h[9]) as *i64,h[10])
157 h[3]=nxa_check2(1,((h as i64)+GG_TOC*GG_WORD) as *i64,GG_SECTIONS*GG_TOC)
158 out[0]=GG_SENTINEL as u8
159 gv_check_eq("normal late bad index",ngp_normals(b,n,out,need),NGP_E_INDEX,c)
160 gv_check_eq("normal refusal preserves output",out[0] as i64,GG_SENTINEL,c)
161 sys_munmap(out,need+1);sys_munmap(b,n)
162 return 0
163}
164func main(argc: i64,argv: *i64) -> i64 {
165 let c: *i64=gv_ctr()
166 gg_skin(c)
167 gg_texcoords(c)
168 gg_normals(c)
169 let h: *i64=sys_mmap(GG_WORDS*GG_WORD) as *i64
170 h[0]=nxa_magic();h[1]=NXA_VER;h[2]=GG_SECTIONS
171 h[4]=nxa_tag4("VERT" as *u8);h[5]=GG_VERT*GG_WORD;h[6]=1+NGP_COMPONENTS
172 h[8]=nxa_tag4("TRIS" as *u8);h[9]=GG_TRIS*GG_WORD;h[10]=1+NGP_COMPONENTS
173 h[GG_VERT]=1;h[GG_VERT+1]=1;h[GG_VERT+2]=0-2;h[GG_VERT+3]=GG_ROUND_INPUT
174 h[GG_TRIS]=1;h[GG_TRIS+1]=0;h[GG_TRIS+2]=0;h[GG_TRIS+3]=0;gg_seal(h)
175 let b: *u8=h as *u8
176 let n: i64=GG_WORDS*GG_WORD
177 let need: i64=NGP_COMPONENTS*NGP_GPU_WORD
178 let out: *u8=sys_mmap(need+1)
179 let words: *u32=out as *u32
180 out[need]=GG_SENTINEL as u8
181 gv_check_eq("size derived from source geometry",ngp_bytes(b,n,"VERT" as *u8),need,c)
182 gv_check_eq("vertices packed",ngp_vertices(b,n,out,need),need,c)
183 gv_check_eq("positive IEEE float32",words[0] as i64,GG_ONE_F32,c)
184 gv_check_eq("negative IEEE float32",words[1] as i64,GG_NEG_TWO_F32,c)
185 gv_check_eq("float32 midpoint rounds to even",words[2] as i64,GG_ROUND_F32,c)
186 gv_check_eq("output trailing guard preserved",out[need] as i64,GG_SENTINEL,c)
187 gv_check_eq("short destination refused",ngp_vertices(b,n,out,need-1),NGP_E_OUTPUT,c)
188 gv_check_eq("null destination refused",ngp_vertices(b,n,0 as *u8,need),NGP_E_OUTPUT,c)
189 gv_check_eq("source overlap refused",ngp_vertices(b,n,b,need),NGP_E_OVERLAP,c)
190 gv_check_eq("short destination unchanged",words[0] as i64,GG_ONE_F32,c)
191 gv_check_eq("indices packed",ngp_indices(b,n,out,need),need,c)
192 gv_check_eq("uint32 index exact",words[2] as i64,0,c)
193 h[GG_TRIS+3]=1;gg_seal(h);out[0]=GG_SENTINEL as u8
194 gv_check_eq("late out of range index refused",ngp_indices(b,n,out,need),NGP_E_INDEX,c)
195 gv_check_eq("index failure does not partially write",out[0] as i64,GG_SENTINEL,c)
196 h[GG_TRIS+3]=0-1;gg_seal(h)
197 gv_check_eq("negative index refused",ngp_indices(b,n,out,need),NGP_E_INDEX,c)
198 h[GG_TRIS+3]=0;gg_seal(h);h[GG_VERT+1]=h[GG_VERT+1]+1
199 gv_check_eq("unsealed source refused",ngp_vertices(b,n,out,need),0-3,c)
200 sys_munmap(out,need+1);sys_munmap(b,n)
201 if argc>1 {
202 let sizes: *i64=sys_mmap(2*GG_WORD) as *i64
203 let data: *u8=sys_map_file(argv[1] as *u8,sizes)
204 let vb: i64=ngp_bytes(data,sizes[0],"VERT" as *u8)
205 let ib: i64=ngp_bytes(data,sizes[0],"TRIS" as *u8)
206 gv_check("real source vertex extent", (vb>0) as i64,c)
207 gv_check("real source index extent", (ib>0) as i64,c)
208 if vb>0 { if ib>0 {
209 let vp: *u8=sys_mmap(vb+1)
210 let ip: *u8=sys_mmap(ib+1)
211 vp[vb]=GG_SENTINEL as u8;ip[ib]=GG_SENTINEL as u8
212 gv_check_eq("real vertices packed",ngp_vertices(data,sizes[0],vp,vb),vb,c)
213 gv_check_eq("real indices packed",ngp_indices(data,sizes[0],ip,ib),ib,c)
214 gv_check_eq("real vertex guard",vp[vb] as i64,GG_SENTINEL,c)
215 gv_check_eq("real index guard",ip[ib] as i64,GG_SENTINEL,c)
216 gv_check_eq("real normal vectors packed",ngp_normals(data,sizes[0],vp,vb),vb,c)
217 gv_check_eq("real normal guard",vp[vb] as i64,GG_SENTINEL,c)
218 sys_munmap(vp,vb+1);sys_munmap(ip,ib+1)
219 } }
220 let sb: i64=ngp_skin_bytes(data,sizes[0])
221 gv_check("real skin binding validates",(sb>0) as i64,c)
222 if sb>0 {
223 let sp: *u8=sys_mmap(sb+1)
224 sp[sb]=GG_SENTINEL as u8
225 gv_check_eq("real skin packed",ngp_skin(data,sizes[0],sp,sb),sb,c)
226 gv_check_eq("real skin guard",sp[sb] as i64,GG_SENTINEL,c)
227 sys_munmap(sp,sb+1)
228 }
229 let tb: i64=ngp_texcoord_bytes(data,sizes[0])
230 gv_check("real texture coordinates validate",(tb>0) as i64,c)
231 if tb>0 {
232 let tp: *u8=sys_mmap(tb+1)
233 tp[tb]=GG_SENTINEL as u8
234 gv_check_eq("real texture coordinates packed",ngp_texcoords(data,sizes[0],tp,tb),tb,c)
235 gv_check_eq("real texture coordinate guard",tp[tb] as i64,GG_SENTINEL,c)
236 gv_kv("real_texcoord_bytes",tb)
237 sys_munmap(tp,tb+1)
238 }
239 if sizes[0]>0 { sys_munmap(data,sizes[0]) }
240 sys_munmap(sizes as *u8,2*GG_WORD)
241 }
242 return gv_verdict("NXA-GPU-PACK",c,"native geometry conversion; IEEE known answers; source/destination extent and index checks before writes")
243}