code wiki / (root) / nx_wgsl_gate.nx

nx_wgsl_gate.nx source

↩ module page · 752 lines · 77340 B

1// nx_wgsl_gate.nx -- IS THE SHADER BACKEND REAL, OR A RUBBER STAMP? 2// 3// SUBJECT: ./nx_wgsl.elf by default, or ./nx_wgsl.sov.elf.new with `staged`. 4// Both modes execute the actual binary; e2e fork, never an in-process re-derive -- an 5// in-process gate would prove the SOURCE compiles, not that the SHIPPED artifact behaves). 6// 7// THE PRE-DECLARED ACCEPT RULE (written before the backend was built): the SAME NishiLang source 8// compiled to BOTH dialects must produce the SAME RESULT. On this box that cannot be proven at the 9// pixel level -- headless WebGPU wedges inside requestAdapter/createShaderModule (measured; it is 10// why nx_game_page_emit carries a GPU_BOOT_MS race at all) -- so equivalence is asserted at the 11// EMITTED-IR level and the pixel gap is DECLARED, never papered over: 12// * TRACE IDENTITY: each backend records the node ids it emits, in order. Two backends that 13// consumed the same source completely produce identical traces. 14// * NON-VACUITY: a module with one statement removed must NOT trace the same. Without this leg 15// trace identity would be satisfied by two backends that both emit nothing. 16// * REFUSAL: a construct outside the covered subset must refuse BY NAME. A silent 17// mistranslation in a shader backend compiles, links, runs, and draws the wrong picture. 18// * DIALECT SEPARATION: the GLSL output must carry GLSL's own spelling and the WGSL output 19// WGSL's -- proving each backend emitted its dialect rather than copying the other. 20// * SHIPPING EQUIVALENCE: the emitted GLSL must carry the same operators and operands as the 21// hand-written VSH that ships in nx_game_page_emit today, which is the migration reference. 22// * DECLARATION REFUSALS (S1, 2026-09-04): a texture-typed uniform, a K_ATTRIB and a fragment K_VARY 23// each REFUSE BY NAME in WGSL (they used to be emitted wrong with no refusal), and a scalar uniform 24// is still ADMITTED by the same pass -- the positive control a deny-guard must carry. 25// * UNIFORM QUALIFICATION (S2, 2026-09-04): WGSL reads a uniform as `u.<name>` (it lives in struct U), 26// GLSL reads it bare; a parameter or local of the same name shadows the uniform and stays bare in 27// both. Trace identity must survive a uniform being in play. 28// * TEXTURES ARE THEIR OWN KIND (S3, 2026-09-04): K_TEXTURE emits a @group/@binding var OUTSIDE struct U 29// in WGSL and a sampler uniform in GLSL, read bare in both; the deprecated texture-typed K_UNIFORM 30// refuses in BOTH dialects naming K_TEXTURE; texture_2d<f32> and a binding collision refuse by name. 31// * DERIVED FRAGMENT SIGNATURE (S4, 2026-09-04): a sir_param_position parameter yields 32// `@fragment fn main(@builtin(position) pos:vec4f)->@location(0) vec4f{` and GLSL reads it as gl_FragCoord; 33// zero parameters derive to the old literal exactly; a position READ with no declared parameter and a 34// plain (unbound) fragment parameter refuse by name -- an undeclared input is never a placeholder. 35// 36// WHAT THIS GATE DOES NOT MEASURE, STATED SO IT CANNOT BE MISREAD: no tooth renders a frame. 37// GREEN here means the two dialects are emitted from one source and agree structurally. It does 38// NOT mean a GPU drew the same pixels from both. That is nx_wgsl_pixel_gate, and it is OWED. 39 40import "nx_syscalls.nx" 41import "nx_gate_verdict.nx" 42import "nx_gatekit_lib.nx" 43 44const WGG_ELF: *u8 = "./nx_wgsl.elf" 45// Capture ceiling: the subject prints two shader texts plus a summary line. 64 KiB is two orders 46// of magnitude above the measured 310-byte emission and is a REFUSAL bound, not a silent cap -- 47// gk_run_capture reports the byte count and the teeth below bind to it. 48// S12c-6 (2026-09-05): the `cast` verb now prints TWO modules (vertex + fragment) in TWO dialects; each module's emission is 49// bounded by the subject's own WG_EMIT_CAP (SIR_MAXNODE*16 = 262,144), so four times that is a ceiling the subject cannot 50// exceed -- still a REFUSAL bound (gk_run_capture reports the count), never a silent cap. 65,536 would have truncated the full 51// fragment (34 KB of hand GLSL x 2 dialects + the vertex pair) and reported the prefix as the whole. 52const WGG_CAP: i64 = 1048576 53// R-F KAT (2026-09-04): THE SHIPPING PAGE PACKER'S OWN NUMBERS, read off nx_game_page_emit's gpe_emit_webgpu -- 54// it packs 96 floats into struct U, writes pal from float index 28 and palf from float index 76. The derived 55// layout must reproduce them as byte offsets (index times 4); they are known answers from the artifact the 56// layout serves, not thresholds chosen here. 57const WGG_PACKER_FLOATS: i64 = 96 58const WGG_PACKER_PAL_F: i64 = 28 59const WGG_PACKER_PALF_F: i64 = 76 60const WGG_FLOAT_BYTES: i64 = 4 61// THE REFUSAL TEXTS THE S1 TEETH ASSERT, exactly as `nx_wgsl decls` prints them (`<label>_named=<refusal>`). 62// Keyed on the probe LABEL so the tooth reads the refusal of ITS probe, and on the rule's own opening 63// words so a refusal that fired for the WRONG reason cannot score it. 64const WGG_R_TEXUNIFORM: *u8 = "texuniform_named=wgsl: texture-typed uniform" 65// S6 2026-09-05: fixture attribute renamed apos->aP (the real cast name; apos:vec3f contained the 66// substring pos:vec3f and inflated the member-balance neg-control). Closure bump: a prior build served a 67// stale cached artifact (staged apos, not aP) despite a changed src -- this comment forces a real compile. 68const WGG_R_ATTRIB: *u8 = "attrib_named=wgsl: vertex attribute declaration (K_ATTRIB)" 69const WGG_R_FRAGVARY: *u8 = "fragvary_named=wgsl: varying declaration (K_VARY) reached in a fragment stage" 70// S3: the texture contract bytes and refusals, exactly as `nx_wgsl decls` prints them for shsrc_tex_plain 71// (uniform scale, texture vox, fn vox_at). WGG_TEX_LAYOUT is ONE contiguous string -- struct U holding only 72// the scalar, its binding line, then the texture var -- so "outside struct U" and "struct U does not contain 73// it" are proven by adjacency, not by two independent contains-checks a reordering could wave through. 74const WGG_TEX_LAYOUT: *u8 = "struct U{\nscale:f32,\n}\n@group(0)@binding(0)var<uniform> u:U;\n@group(0)@binding(1)var vox:texture_3d<u32>;\n" 75const WGG_TEX_WGSL_DECL: *u8 = "@group(0)@binding(1)var vox:texture_3d<u32>;\n" 76const WGG_TEX_GLSL_DECL: *u8 = "uniform highp usampler3D vox;\n" 77const WGG_TEX_WGSL_READ: *u8 = "return textureLoad(vox,vec3i(x,y,z),0).x;\n" 78const WGG_TEX_GLSL_READ: *u8 = "return texelFetch(vox,ivec3(x,y,z),0).x;\n" 79const WGG_R_TEXUNIFORM_GL: *u8 = "texuniform_glsl_named=glsl: texture-typed uniform" 80const WGG_R_TEX2D_WG: *u8 = "tex2d_wgsl_named=wgsl: texture type outside the covered subset" 81const WGG_R_TEX2D_GL: *u8 = "tex2d_glsl_named=glsl: texture type outside the covered subset" 82const WGG_R_TEXCOLLIDE: *u8 = "texcollide_named=wgsl: derived texture binding collides" 83// S4: the derived fragment signature and its reads, exactly as `nx_wgsl decls` prints them for shsrc_frag_pos, 84// the zero-parameter control, and the refusals for an undeclared / unbound input. 85const WGG_FRAGPOS_SIG: *u8 = "@fragment fn main(@builtin(position) pos:vec4f)->@location(0) vec4f{\n" 86const WGG_FRAGPOS_WGSL_BODY: *u8 = "return vec4f(pos.x,pos.y,0.0,1.0);\n" 87const WGG_FRAGPOS_GLSL_BODY: *u8 = "vec4(gl_FragCoord.x,gl_FragCoord.y,0.0,1.0)" 88const WGG_FRAGCONST_SIG: *u8 = "@fragment fn main()->@location(0) vec4f{\n" 89const WGG_R_FRAGUNDECL: *u8 = "fragundecl_named=wgsl: @builtin(position) read without a declared entry parameter" 90const WGG_R_FRAGPLAIN_WG: *u8 = "fragplain_wgsl_named=wgsl: fragment entry parameter that is not the @builtin(position) input" 91const WGG_R_FRAGPLAIN_GL: *u8 = "fragplain_glsl_named=glsl: entry-point parameter that is not the @builtin(position) input" 92// S5 (2026-09-04): THE FRAGMENT OUTPUT. Each of these is ONE CONTIGUOUS RUN, so adjacency proves the shape 93// -- a declaration that drifted away from its main(), or a return that survived beside the assignment, 94// cannot score them the way two independent contains-checks could. 95// The GLSL run is the whole program: header, the declared output, and an entry that ASSIGNS rather than 96// returns. Before S5 the middle line did not exist and the last was `return vec4(1.0,0.0,0.0,1.0);` -- 97// a value returned from a void function, against no declaration: invalid GLSL ES 3.00 on both counts. 98const WGG_FRAGOUT_GLSL: *u8 = "out vec4 fc;\nvoid main(){\nfc=vec4(1.0,0.0,0.0,1.0);\n}\n" 99const WGG_FRAGOUT_GLSL_DECL: *u8 = "out vec4 fc;\n" 100// The WGSL run at location 0 must reproduce the literal this line used to carry, BYTE FOR BYTE. 101const WGG_FRAGOUT_WGSL: *u8 = "@fragment fn main()->@location(0) vec4f{\nreturn vec4f(1.0,0.0,0.0,1.0);\n}\n" 102// A NON-ZERO location proves the number is DATA and not the constant 0 it was spelled as. 103const WGG_FRAGLOC2_GLSL: *u8 = "layout(location=2) out vec4 fc;\n" 104const WGG_FRAGLOC2_WGSL: *u8 = "@fragment fn main()->@location(2) vec4f{\n" 105// The discard-only positive control: no output declared, and BOTH backends admit it. 106const WGG_FRAGDISCARD_WGSL: *u8 = "@fragment fn main(){\ndiscard;\n}\n" 107const WGG_FRAGDISCARD_GLSL: *u8 = "void main(){\ndiscard;\n}\n" 108const WGG_R_FRAGNOOUT_GL: *u8 = "fragnoout_glsl_named=glsl: fragment entry returns a value with no declared fragment output" 109const WGG_R_FRAGNOOUT_WG: *u8 = "fragnoout_wgsl_named=wgsl: fragment entry returns a value with no declared fragment output" 110const WGG_R_VERTFRAGOUT_GL: *u8 = "vertfragout_glsl_named=glsl: fragment output declaration (K_FRAGOUT) outside a fragment stage" 111const WGG_R_VERTFRAGOUT_WG: *u8 = "vertfragout_wgsl_named=wgsl: fragment output declaration (K_FRAGOUT) outside a fragment stage" 112const WGG_R_TWOOUT_GL: *u8 = "fragtwoout_glsl_named=glsl: more than one fragment output declared" 113const WGG_R_TWOOUT_WG: *u8 = "fragtwoout_wgsl_named=wgsl: more than one fragment output declared" 114// S5 residual (b): the sampled read. WGSL refuses (no sampler binding); GLSL EMITS, because its texture() 115// needs no separate sampler object -- the mirror image of K_STORAGE, which GLSL refuses and WGSL emits. 116const WGG_R_TEXSAMPLE_WG: *u8 = "texsample_wgsl_named=wgsl: sampled texture read (E_TEXSAMPLE)" 117const WGG_TEXSAMPLE_GLSL: *u8 = "return texture(vox,uv);\n" 118 119func wgg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 120 121func wgg_has(buf: *u8, n: i64, ned: *u8) -> i64 { 122 let m: i64 = wgg_slen(ned) 123 if m == 0 { return 0 } 124 var i: i64 = 0 125 while i + m <= n { 126 var j: i64 = 0 127 var ok: i64 = 1 128 while j < m { 129 if buf[i+j] != ned[j] { ok = 0; j = m } else { j = j + 1 } 130 } 131 if ok == 1 { return 1 } 132 i = i + 1 133 } 134 return 0 135} 136 137// how many times ned occurs in buf[0..n) -- the S2 teeth need "exactly once" (the qualifier appears in the 138// WGSL text and never leaks into the GLSL text printed beside it), which a presence check cannot say. 139func wgg_count(buf: *u8, n: i64, ned: *u8) -> i64 { 140 let m: i64 = wgg_slen(ned) 141 if m == 0 { return 0 } 142 var c: i64 = 0 143 var i: i64 = 0 144 while i + m <= n { 145 var j: i64 = 0 146 var ok: i64 = 1 147 while j < m { 148 if buf[i+j] != ned[j] { ok = 0; j = m } else { j = j + 1 } 149 } 150 if ok == 1 { c = c + 1 } 151 i = i + 1 152 } 153 return c 154} 155 156// first integer following the LAST occurrence of key -- anchored on the key, never on position, 157// so a value appearing in the prose above cannot be read as the answer. 158func wgg_num_after(buf: *u8, n: i64, key: *u8) -> i64 { 159 let m: i64 = wgg_slen(key) 160 var at: i64 = 0 - 1 161 var i: i64 = 0 162 while i + m <= n { 163 // S5 (2026-09-04): THE KEY MUST START A LINE. This search was an UNANCHORED substring match that 164 // kept the LAST hit, so any probe label that is a SUFFIX of another label silently read the WRONG 165 // probe's number -- "fragout_glsl_rc=" matches inside "vertfragout_glsl_rc=-1", and the tooth asking 166 // "did the fragout probe emit?" was answered -1 by the vertex-stage REFUSAL probe. MEASURED the 167 // moment both labels existed: 100/102, two teeth failing against a subject that was in fact correct 168 // (the emission was 113 bytes). The failure direction is the dangerous one too -- a suffix label 169 // whose sibling REFUSES reads as a refusal, so a working feature reports as broken and a broken one 170 // could report as working. `nx_wgsl decls` prints every "<label>_rc=" and "<label>_trace_equal=" at 171 // a line start, so this anchor is exact and no pre-existing tooth's reading moves. The colliding 172 // pair is kept in the probe set ON PURPOSE and asserted below: it is the live neg-control for this. 173 var anch: i64 = 0 174 if i == 0 { anch = 1 } else { if buf[i-1] == (10 as u8) { anch = 1 } } 175 if anch == 1 { 176 var j: i64 = 0 177 var ok: i64 = 1 178 while j < m { 179 if buf[i+j] != key[j] { ok = 0; j = m } else { j = j + 1 } 180 } 181 if ok == 1 { at = i + m } 182 } 183 i = i + 1 184 } 185 if at < 0 { return 0 - 1 } 186 var v: i64 = 0 187 var seen: i64 = 0 188 var neg: i64 = 0 189 if at < n { if buf[at] == (45 as u8) { neg = 1; at = at + 1 } } 190 while at < n { 191 let c: i64 = buf[at] as i64 192 if c >= 48 { if c <= 57 { v = v*10 + (c - 48); seen = 1; at = at + 1 } else { at = n } } else { at = n } 193 } 194 if seen == 0 { return 0 - 1 } 195 if neg == 1 { return 0 - v } 196 return v 197} 198 199// S12c-4: a needle that must carry a bang -- nx_cc refuses '!' inside a literal, so the fixture is written with '~' (126) 200// and every tilde becomes '!' (33) at run time, the byte the emitted shader actually carries. 201const WGG_C_TILDE: i64 = 126 202const WGG_C_BANG: i64 = 33 203func wgg_bang(s: *u8) -> *u8 { 204 var n: i64 = 0 205 while s[n] != (0 as u8) { n = n + 1 } 206 let o: *u8 = sys_mmap(n + 1) 207 var i: i64 = 0 208 while i < n { 209 var c: i64 = s[i] as i64 210 if c == WGG_C_TILDE { c = WGG_C_BANG } 211 o[i] = c as u8 212 i = i + 1 213 } 214 o[n] = 0 as u8 215 return o 216} 217 218func main(argc: i64, argv: *i64) -> i64 { 219 var subject: *u8 = WGG_ELF 220 if argc > 1 { 221 let mode: *u8 = argv[1] as *u8 222 if argc != 2 || wgg_slen(mode) != wgg_slen("staged" as *u8) || wgg_has(mode, wgg_slen(mode), "staged" as *u8) == 0 { 223 gv_puts("usage: nx_wgsl_gate [staged]; invalid selection, no subject executed\n" as *u8) 224 return 2 225 } 226 subject = "./nx_wgsl.sov.elf.new" as *u8 227 } 228 gv_puts("shader subject=" as *u8); gv_puts(subject); gv_puts("\n" as *u8) 229 let ctr: *i64 = gv_ctr() 230 gv_puts("nx_wgsl_gate -- ONE NishiLang source, TWO dialects, and the equivalence is measured\n\n" as *u8) 231 232 let buf: *u8 = sys_mmap(WGG_CAP) 233 let bl: *i64 = sys_mmap(16) as *i64 234 bl[0] = 0 235 // COMPOSE the proven subprocess primitive. A hand-rolled pipe/fork/wait DEADLOCKED a sibling 236 // gate in production this same day (pid 2240, 50+ min in pipe_wait); the banked law is that 237 // fixtures and subprocess come from nx_gatekit_lib. Never re-roll this. 238 let rc: i64 = gk_run_capture(subject, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, buf, WGG_CAP, bl) 239 let n: i64 = bl[0] 240 gv_puts(" subject rc=" as *u8); gv_num(rc); gv_puts(" bytes=" as *u8); gv_num(n); gv_puts("\n" as *u8) 241 gv_check("subject-ran-and-produced-output (127 = elf absent, the stale-offc tell)" as *u8, rc == 0, ctr) 242 var got: i64 = 0 243 if n > 0 { got = 1 } 244 gv_check("subject-emitted-bytes (a silent subject proves nothing)" as *u8, got, ctr) 245 if got == 0 { return gv_verdict("NX-WGSL" as *u8, ctr, "the backend produced no output at all" as *u8) } 246 247 // ---- the GLSL dialect is really GLSL -------------------------------------------------- 248 gv_check("glsl-carries-its-version-pragma" as *u8, wgg_has(buf, n, "#version 300 es" as *u8), ctr) 249 gv_check("glsl-uses-gl_VertexID (GLSL's own vertex-index spelling)" as *u8, wgg_has(buf, n, "gl_VertexID" as *u8), ctr) 250 gv_check("glsl-ASSIGNS-gl_Position" as *u8, wgg_has(buf, n, "gl_Position=" as *u8), ctr) 251 252 // ---- the WGSL dialect is really WGSL, and STRUCTURALLY different ----------------------- 253 gv_check("wgsl-declares-a-vertex-entry-point" as *u8, wgg_has(buf, n, "@vertex fn" as *u8), ctr) 254 gv_check("wgsl-RETURNS-builtin-position (not an assignment -- a real structural difference)" as *u8, wgg_has(buf, n, "->@builtin(position)" as *u8), ctr) 255 gv_check("wgsl-uses-its-own-type-spelling (vec4f, never vec4)" as *u8, wgg_has(buf, n, "vec4f(" as *u8), ctr) 256 gv_check("wgsl-suffixes-its-unsigned-shift-amount (1u -- GLSL must not)" as *u8, wgg_has(buf, n, "<<1u" as *u8), ctr) 257 258 // ---- SHIPPING EQUIVALENCE: same operators and operands as the hand-written VSH --------- 259 // The GLSL that ships today is: 260 // void main(){vec2 v=vec2((gl_VertexID<<1)&2,gl_VertexID&2);gl_Position=vec4(v*2.-1.,0.,1.);} 261 // The emitted form is explicit where the hand form leaned on constructor conversion, so this 262 // is SEMANTIC equivalence over the same operator set -- stated exactly, not overclaimed. 263 gv_check("emitted-glsl-keeps-the-shipped-shift (<<1)" as *u8, wgg_has(buf, n, "<<1)" as *u8), ctr) 264 gv_check("emitted-glsl-keeps-the-shipped-mask (&2)" as *u8, wgg_has(buf, n, "&2)" as *u8), ctr) 265 gv_check("emitted-glsl-keeps-the-shipped-vec2-local" as *u8, wgg_has(buf, n, "vec2 v=vec2(" as *u8), ctr) 266 gv_check("emitted-glsl-keeps-the-shipped-clip-transform (*2.0)-1.0" as *u8, wgg_has(buf, n, "(v*2.0)-1.0" as *u8), ctr) 267 268 // ---- THE ACCEPT RULE: trace identity, and its non-vacuity ------------------------------ 269 let gnodes: i64 = wgg_num_after(buf, n, "glsl_nodes=" as *u8) 270 let wnodes: i64 = wgg_num_after(buf, n, "wgsl_nodes=" as *u8) 271 let teq: i64 = wgg_num_after(buf, n, "trace_equal=" as *u8) 272 let cnodes: i64 = wgg_num_after(buf, n, "corrupt_nodes=" as *u8) 273 gv_puts(" glsl_nodes=" as *u8); gv_num(gnodes) 274 gv_puts(" wgsl_nodes=" as *u8); gv_num(wnodes) 275 gv_puts(" trace_equal=" as *u8); gv_num(teq) 276 gv_puts(" corrupt_nodes=" as *u8); gv_num(cnodes); gv_puts("\n" as *u8) 277 // BOUND IN THE CONDITION, so an empty emit cannot pass: the node count must be positive AND 278 // equal across backends. A gate that only asked 'are they equal?' would pass on 0 == 0. 279 var same: i64 = 0 280 if gnodes > 0 { if gnodes == wnodes { same = 1 } } 281 gv_check("both-backends-consumed-the-same-source (node counts equal AND positive)" as *u8, same, ctr) 282 gv_check("trace-identity-element-wise (same node ids, same order)" as *u8, teq == 1, ctr) 283 // NON-VACUITY: drop one statement and the trace MUST change. This is what makes the tooth 284 // above load-bearing rather than decorative. 285 var nonvac: i64 = 0 286 if cnodes > 0 { if cnodes != gnodes { nonvac = 1 } } 287 gv_check("neg-control-a-statement-dropped-CHANGES-the-trace (equality is not vacuous)" as *u8, nonvac, ctr) 288 289 // ---- REFUSAL: outside the covered subset, refuse BY NAME ------------------------------- 290 let urc: i64 = wgg_num_after(buf, n, "uncovered_rc=" as *u8) 291 gv_puts(" uncovered_rc=" as *u8); gv_num(urc); gv_puts("\n" as *u8) 292 gv_check("neg-control-uncovered-construct-REFUSES (rc=-1, never a guess)" as *u8, urc == (0 - 1), ctr) 293 gv_check("the-refusal-NAMES-the-construct (a named refusal is a contract)" as *u8, wgg_has(buf, n, "outside the covered subset" as *u8), ctr) 294 gv_check("neg-control-did-not-fire-on-the-GOOD-module (no REFUSED on the real shader)" as *u8, wgg_has(buf, n, "REFUSED: " as *u8) == 0, ctr) 295 296 // ---- S1 (2026-09-04): DECLARATION MISTRANSLATIONS ARE NAMED REFUSALS, AND THE GUARD STILL ADMITS ---- 297 // Three outputs used to be confidently wrong with NO refusal: a texture-typed uniform emitted INSIDE 298 // struct U, a K_ATTRIB dropped to zero bytes, a fragment K_VARY emitted as a comment. `nx_wgsl decls` 299 // runs each and prints the refusal VERBATIM; each tooth asserts rc == -1 AND which rule fired. A 300 // deny-guard that has only ever refused is unverified, so the same run carries a POSITIVE control -- 301 // a scalar uniform that MUST be admitted: a guard that refuses everything passes every negative test. 302 let db: *u8 = sys_mmap(WGG_CAP) 303 bl[0] = 0 304 let drc: i64 = gk_run_capture(subject, "decls" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, db, WGG_CAP, bl) 305 let dn: i64 = bl[0] 306 gv_puts(" decls rc=" as *u8); gv_num(drc); gv_puts(" bytes=" as *u8); gv_num(dn); gv_puts("\n" as *u8) 307 gv_check("decls-verb-ran (rc=0)" as *u8, drc == 0, ctr) 308 gv_check("decls-verb-emitted-bytes" as *u8, dn > 0, ctr) 309 // S3 (2026-09-04) REWROTE THE S1 TEXTURE TOOTH INTO COVERAGE. A texture is now its own kind (K_TEXTURE, 310 // sir_texture). The deprecated form -- a texture-typed K_UNIFORM -- still refuses, in BOTH dialects, naming 311 // K_TEXTURE as the remedy; the covered form is emitted OUTSIDE struct U in WGSL (proven by ADJACENCY: 312 // struct U, its binding, then the texture var, one contiguous string) and as a sampler uniform in GLSL, 313 // is read bare in both, keeps trace identity, and every other texture type refuses by name. 314 gv_check_eq("neg-control-texture-typed-K_UNIFORM-still-REFUSES-in-wgsl (rc=-1; the remedy is K_TEXTURE)" as *u8, wgg_num_after(db, dn, "texuniform_rc=" as *u8), 0 - 1, ctr) 315 gv_check("neg-control-texture-typed-K_UNIFORM-wgsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TEXUNIFORM), ctr) 316 gv_check_eq("neg-control-texture-typed-K_UNIFORM-REFUSES-in-glsl-too (rc=-1; both backends cover the same source)" as *u8, wgg_num_after(db, dn, "texuniform_glsl_rc=" as *u8), 0 - 1, ctr) 317 gv_check("neg-control-texture-typed-K_UNIFORM-glsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TEXUNIFORM_GL), ctr) 318 gv_check("K_TEXTURE-wgsl-probe-emitted (tex_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "tex_wgsl_rc=" as *u8) > 0, ctr) 319 gv_check("K_TEXTURE-glsl-probe-emitted (tex_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "tex_glsl_rc=" as *u8) > 0, ctr) 320 gv_check("K_TEXTURE-wgsl-emits-a-binding-var (group 0, derived binding 1)" as *u8, wgg_has(db, dn, WGG_TEX_WGSL_DECL), ctr) 321 gv_check("K_TEXTURE-is-OUTSIDE-struct-U-and-struct-U-holds-only-the-scalar (contiguous layout KAT)" as *u8, wgg_has(db, dn, WGG_TEX_LAYOUT), ctr) 322 gv_check_eq("neg-control-struct-U-member-spelling-of-the-texture-is-ABSENT (count 0)" as *u8, wgg_count(db, dn, "vox:texture_3d<u32>," as *u8), 0, ctr) 323 gv_check("K_TEXTURE-glsl-emits-the-sampler-uniform" as *u8, wgg_has(db, dn, WGG_TEX_GLSL_DECL), ctr) 324 gv_check("K_TEXTURE-wgsl-reads-it-with-textureLoad-and-the-ident-BARE" as *u8, wgg_has(db, dn, WGG_TEX_WGSL_READ), ctr) 325 gv_check("K_TEXTURE-glsl-reads-it-with-texelFetch" as *u8, wgg_has(db, dn, WGG_TEX_GLSL_READ), ctr) 326 gv_check_eq("neg-control-the-texture-ident-is-NEVER-u.-qualified (count of u.vox is 0)" as *u8, wgg_count(db, dn, "u.vox" as *u8), 0, ctr) 327 gv_check_eq("K_TEXTURE-trace-identity-holds-across-dialects (tex_trace_equal)" as *u8, wgg_num_after(db, dn, "tex_trace_equal=" as *u8), 1, ctr) 328 // GE54 (2026-09-05): the four `texture_2d REFUSES` neg-controls were RETIRED here -- texture_2d<f32> is now a 329 // SUPPORTED sampled texture (GLSL sampler2D, WGSL texture + companion sampler), proven by the tex2d teeth above, 330 // so asserting it refuses is asserting the old world. The refusal contract now fires only for texture types 331 // outside {T_TEX3U, T_TEX2F}; WGG_R_TEX2D_WG/GL are kept for the record. The storage/texture collision below 332 // still refuses and its neg-control stands. 333 gv_check_eq("neg-control-derived-texture-binding-on-a-storage-binding-REFUSES (rc=-1)" as *u8, wgg_num_after(db, dn, "texcollide_rc=" as *u8), 0 - 1, ctr) 334 gv_check("neg-control-collision-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TEXCOLLIDE), ctr) 335 336 // ---- S4 (2026-09-04): THE FRAGMENT ENTRY SIGNATURE IS DERIVED FROM THE DECLARED PARAMETERS ---- 337 // It was the literal "()->@location(0) vec4f{" whatever the function declared, and a position READ 338 // emitted the placeholder identifier POSITION. Now the single covered input, @builtin(position), is 339 // derived from a sir_param_position parameter in both dialects; the zero-parameter case derives to the 340 // old literal exactly (control); an undeclared read and an unbound parameter refuse by name. 341 gv_check("fragpos-wgsl-probe-emitted (fragpos_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "fragpos_wgsl_rc=" as *u8) > 0, ctr) 342 gv_check("fragpos-glsl-probe-emitted (fragpos_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "fragpos_glsl_rc=" as *u8) > 0, ctr) 343 gv_check("fragment-entry-signature-is-DERIVED-from-the-position-param (KAT)" as *u8, wgg_has(db, dn, WGG_FRAGPOS_SIG), ctr) 344 gv_check("fragment-body-reads-the-position-param-BARE (pos.x, pos.y)" as *u8, wgg_has(db, dn, WGG_FRAGPOS_WGSL_BODY), ctr) 345 gv_check("glsl-reads-the-declared-position-input-as-gl_FragCoord" as *u8, wgg_has(db, dn, WGG_FRAGPOS_GLSL_BODY), ctr) 346 gv_check_eq("fragpos-trace-identity-holds-across-dialects (fragpos_trace_equal)" as *u8, wgg_num_after(db, dn, "fragpos_trace_equal=" as *u8), 1, ctr) 347 gv_check("control-zero-parameter-fragment-derives-to-the-old-literal-EXACTLY" as *u8, wgg_has(db, dn, WGG_FRAGCONST_SIG), ctr) 348 gv_check_eq("neg-control-position-READ-without-a-declared-param-REFUSES (rc=-1)" as *u8, wgg_num_after(db, dn, "fragundecl_rc=" as *u8), 0 - 1, ctr) 349 gv_check("neg-control-undeclared-input-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGUNDECL), ctr) 350 gv_check_eq("neg-control-the-placeholder-identifier-POSITION-is-emitted-NOWHERE (count 0)" as *u8, wgg_count(db, dn, "POSITION" as *u8), 0, ctr) 351 gv_check_eq("neg-control-plain-fragment-param-REFUSES-in-wgsl (rc=-1)" as *u8, wgg_num_after(db, dn, "fragplain_wgsl_rc=" as *u8), 0 - 1, ctr) 352 gv_check("neg-control-plain-fragment-param-wgsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGPLAIN_WG), ctr) 353 gv_check_eq("neg-control-plain-fragment-param-REFUSES-in-glsl (rc=-1)" as *u8, wgg_num_after(db, dn, "fragplain_glsl_rc=" as *u8), 0 - 1, ctr) 354 gv_check("neg-control-plain-fragment-param-glsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGPLAIN_GL), ctr) 355 gv_check("S6-K_ATTRIB-is-ADMITTED-in-wgsl (attrib_rc>0: a vertex attribute no longer refuses)" as *u8, wgg_num_after(db, dn, "attrib_rc=" as *u8) > 0, ctr) 356 gv_check("S6-vertex-attribute-emits-as-a-@location-entry-parameter (,@location(0) aP:vec3f)" as *u8, wgg_has(db, dn, ",@location(0) aP:vec3f" as *u8), ctr) 357 gv_check("S6-glsl-emits-the-attribute-module-scope (layout(location=0) in vec3 aP;)" as *u8, wgg_has(db, dn, "layout(location=0) in vec3 aP;" as *u8), ctr) 358 gv_check_eq("S6-attribute-trace-identity-holds-across-dialects (attrib_trace_equal)" as *u8, wgg_num_after(db, dn, "attrib_trace_equal=" as *u8), 1, ctr) 359 gv_check_eq("neg-control-K_ATTRIB-in-a-FRAGMENT-stage-REFUSES (attribfrag_rc=-1)" as *u8, wgg_num_after(db, dn, "attribfrag_rc=" as *u8), 0 - 1, ctr) 360 gv_check("neg-control-fragment-attribute-refusal-NAMES-ITS-RULE (outside a vertex stage)" as *u8, wgg_has(db, dn, "outside a vertex stage" as *u8), ctr) 361 gv_check("S7-fragment-K_VARY-is-ADMITTED (fragvary_rc>0: declared-but-unread still carries the struct parameter)" as *u8, wgg_num_after(db, dn, "fragvary_rc=" as *u8) > 0, ctr) 362 gv_check("S7-interstage-struct-emitted-with-the-reserved-position-member (struct VIO{@builtin(position) bpos:vec4f,@location(0) vcol:vec4f,)" as *u8, wgg_has(db, dn, "struct VIO{@builtin(position) bpos:vec4f,@location(0) vcol:vec4f," as *u8), ctr) 363 gv_check("S7-flat-int-varying-carries-@interpolate(flat) (@location(1) @interpolate(flat) vii:i32,})" as *u8, wgg_has(db, dn, "@location(1) @interpolate(flat) vii:i32,}" as *u8), ctr) 364 gv_check("S7-vertex-entry-RETURNS-the-struct-and-opens-var-vo (->VIO{ var vo:VIO;)" as *u8, wgg_has(db, dn, ")->VIO{\nvar vo:VIO;" as *u8), ctr) 365 gv_check("S7-varying-write-qualifies-vo. (vo.vii=7;)" as *u8, wgg_has(db, dn, "vo.vii=7;" as *u8), ctr) 366 gv_check("S7-position-assignment-lands-in-the-struct (vo.bpos=vec4f()" as *u8, wgg_has(db, dn, "vo.bpos=vec4f(" as *u8), ctr) 367 gv_check("S7-vertex-entry-closes-with-return-vo" as *u8, wgg_has(db, dn, "return vo;\n}" as *u8), ctr) 368 gv_check("S7-fragment-entry-TAKES-the-struct ((vin:VIO)->@location(0) vec4f{)" as *u8, wgg_has(db, dn, "(vin:VIO)->@location(0) vec4f{" as *u8), ctr) 369 gv_check("S7-varying-read-qualifies-vin. ((vin.vcol*f32(vin.vii)))" as *u8, wgg_has(db, dn, "(vin.vcol*f32(vin.vii))" as *u8), ctr) 370 gv_check("S7-glsl-keeps-module-scope-out-with-flat (flat out int vii;)" as *u8, wgg_has(db, dn, "flat out int vii;" as *u8), ctr) 371 gv_check("S7-glsl-fragment-input-spelled-in (in vec4 vcol;)" as *u8, wgg_has(db, dn, "in vec4 vcol;" as *u8), ctr) 372 gv_check_eq("S7-vertex-varying-trace-identity-holds-across-dialects (varyvs_trace_equal)" as *u8, wgg_num_after(db, dn, "varyvs_trace_equal=" as *u8), 1, ctr) 373 gv_check_eq("S7-fragment-varying-trace-identity-holds-across-dialects (varyfs_trace_equal)" as *u8, wgg_num_after(db, dn, "varyfs_trace_equal=" as *u8), 1, ctr) 374 gv_check_eq("neg-control-a-varying-named-bpos-REFUSES (varybpos_rc=-1; the reserved position member)" as *u8, wgg_num_after(db, dn, "varybpos_rc=" as *u8), 0 - 1, ctr) 375 gv_check("neg-control-bpos-refusal-NAMES-ITS-RULE (reserved @builtin(position) member)" as *u8, wgg_has(db, dn, "reserved @builtin(position) member" as *u8), ctr) 376 // ---- S8 (2026-09-05): THE NAMED CAST SAMPLER SET uAtl uNrm uJT uGD ---- 377 gv_check("S8-cast-vertex-probe-emitted (cast8vs_rc>0)" as *u8, wgg_num_after(db, dn, "cast8vs_rc=" as *u8) > 0, ctr) 378 gv_check("S8-cast-fragment-probe-emitted (cast8fs_rc>0)" as *u8, wgg_num_after(db, dn, "cast8fs_rc=" as *u8) > 0, ctr) 379 gv_check("S8-joint-table-read-by-INTEGER-coordinate-in-the-vertex-entry (vo.vcol=textureLoad(uJT,vec2i(i32(aJ.x),0),0);)" as *u8, wgg_has(db, dn, "vo.vcol=textureLoad(uJT,vec2i(i32(aJ.x),0),0);" as *u8), ctr) 380 gv_check("S8-glsl-texelFetch-twin-over-ivec2 (vcol=texelFetch(uJT,ivec2(int(aJ.x),0),0);)" as *u8, wgg_has(db, dn, "vcol=texelFetch(uJT,ivec2(int(aJ.x),0),0);" as *u8), ctr) 381 gv_check("S8-2D-float-load-returns-a-vec4f-usable-as-position (vo.bpos=textureLoad(uGD,vec2i(0,0),0);)" as *u8, wgg_has(db, dn, "vo.bpos=textureLoad(uGD,vec2i(0,0),0);" as *u8), ctr) 382 gv_check("S8-glsl-position-from-the-garment-table (gl_Position=texelFetch(uGD,ivec2(0,0),0);)" as *u8, wgg_has(db, dn, "gl_Position=texelFetch(uGD,ivec2(0,0),0);" as *u8), ctr) 383 gv_check("S8-the-fourth-2D-texture-lands-at-DERIVED-binding-7 (two slots each: 1,3,5,7) (@binding(7)var uGD:texture_2d<f32>;)" as *u8, wgg_has(db, dn, "@binding(7)var uGD:texture_2d<f32>;" as *u8), ctr) 384 gv_check("S8-its-companion-sampler-follows-at-8 (uGD_s:sampler)" as *u8, wgg_has(db, dn, "@binding(8)var uGD_s:sampler;" as *u8), ctr) 385 gv_check("S8-atlas-and-normal-map-SAMPLED-in-the-fragment-through-companion-samplers ((textureSample(uAtl,uAtl_s,vin.vcol.xy)*textureSample(uNrm,uNrm_s,vin.vcol.xy)))" as *u8, wgg_has(db, dn, "(textureSample(uAtl,uAtl_s,vin.vcol.xy)*textureSample(uNrm,uNrm_s,vin.vcol.xy))" as *u8), ctr) 386 gv_check("S8-glsl-sampled-twin ((texture(uAtl,vcol.xy)*texture(uNrm,vcol.xy)))" as *u8, wgg_has(db, dn, "(texture(uAtl,vcol.xy)*texture(uNrm,vcol.xy))" as *u8), ctr) 387 gv_check_eq("S8-cast-vertex-trace-identity-holds-across-dialects (cast8vs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast8vs_trace_equal=" as *u8), 1, ctr) 388 gv_check_eq("S8-cast-fragment-trace-identity-holds-across-dialects (cast8fs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast8fs_trace_equal=" as *u8), 1, ctr) 389 // S9 (2026-09-05): mat3 + derivatives + inverseSqrt. cast9vs = mat3x3f(aA,aB,aC) then M*aP into position; cast9fs = 390 // vec4(dpdx, dpdy, fwidth, inverseSqrt) over the varying. The IR names are the WGSL spellings; the GLSL arm re-spells 391 // dFdx/dFdy/inversesqrt through ONE map (gl_call_name), and the two leak controls prove the map is one-directional. 392 gv_check("S9-mat3-vertex-emits (cast9vs_rc>0)" as *u8, (wgg_num_after(db, dn, "cast9vs_rc=" as *u8) > 0) as i64, ctr) 393 gv_check("S9-wgsl-mat3x3f-ctor-from-three-columns" as *u8, wgg_has(db, dn, "mat3x3f(aA,aB,aC)" as *u8), ctr) 394 gv_check("S9-glsl-mat3-ctor-from-three-columns" as *u8, wgg_has(db, dn, "mat3(aA,aB,aC)" as *u8), ctr) 395 gv_check("S9-mat-times-vec-is-plain-star-in-both-dialects" as *u8, (wgg_count(db, dn, "(M*aP)" as *u8) >= 2) as i64, ctr) 396 gv_check_eq("S9-mat3-vertex-trace-identity-holds-across-dialects (cast9vs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast9vs_trace_equal=" as *u8), 1, ctr) 397 gv_check("S9-derivative-fragment-emits (cast9fs_rc>0)" as *u8, (wgg_num_after(db, dn, "cast9fs_rc=" as *u8) > 0) as i64, ctr) 398 gv_check("S9-wgsl-spells-dpdx-dpdy-fwidth-inverseSqrt" as *u8, wgg_has(db, dn, "vec4f(dpdx(vin.vcol.x),dpdy(vin.vcol.y),fwidth(vin.vcol.z),inverseSqrt(vin.vcol.w))" as *u8), ctr) 399 gv_check("S9-glsl-spells-dFdx-dFdy-fwidth-inversesqrt" as *u8, wgg_has(db, dn, "vec4(dFdx(vcol.x),dFdy(vcol.y),fwidth(vcol.z),inversesqrt(vcol.w))" as *u8), ctr) 400 gv_check("neg-control-S9-glsl-spelling-never-leaks-into-wgsl" as *u8, (wgg_count(db, dn, "dFdx(vin." as *u8) == 0) as i64, ctr) 401 gv_check("neg-control-S9-wgsl-spelling-never-leaks-into-glsl" as *u8, (wgg_count(db, dn, "inverseSqrt(vcol." as *u8) == 0) as i64, ctr) 402 gv_check_eq("S9-derivative-fragment-trace-identity-holds-across-dialects (cast9fs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast9fs_trace_equal=" as *u8), 1, ctr) 403 // S12a (2026-09-05): the instance index. cast10vs = position = vec4(f32(instance_index), aP.y, 0, 1). WGSL binds 404 // @builtin(instance_index) ii:u32 ONLY in the module that reads it (M_USESII); every other decls module keeps its 405 // signature, which the count neg-control proves across the whole decls output. GLSL reads gl_InstanceID undeclared. 406 gv_check("S12a-instance-vertex-emits (cast10vs_rc>0)" as *u8, (wgg_num_after(db, dn, "cast10vs_rc=" as *u8) > 0) as i64, ctr) 407 gv_check("S12a-wgsl-binds-instance_index-beside-vertex_index" as *u8, wgg_has(db, dn, "vi:u32,@builtin(instance_index) iidx:u32" as *u8), ctr) 408 gv_check("S12a-wgsl-reads-the-instance-as-i32(iidx) (S12c-2b: the builtin parameter is iidx so a module-level local ii cannot collide)" as *u8, wgg_has(db, dn, "f32(i32(iidx))" as *u8), ctr) 409 gv_check("S12a-glsl-reads-gl_InstanceID-undeclared" as *u8, wgg_has(db, dn, "float(gl_InstanceID)" as *u8), ctr) 410 gv_check_eq("neg-control-S12a-instance-binding-appears-in-exactly-one-decls-module" as *u8, wgg_count(db, dn, "@builtin(instance_index)" as *u8), 1, ctr) 411 gv_check_eq("S12a-instance-vertex-trace-identity-holds-across-dialects (cast10vs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast10vs_trace_equal=" as *u8), 1, ctr) 412 // S12c-1 (2026-09-05): a VOID return inside the interstage-struct vertex entry. cast11vs writes vo.vcol then returns early 413 // under an if; WGSL must hand back the struct (`return vo;`), GLSL says `return;`, and nothing anywhere may emit `return ;`. 414 gv_check("S12c1-void-return-vertex-emits (cast11vs_rc>0)" as *u8, (wgg_num_after(db, dn, "cast11vs_rc=" as *u8) > 0) as i64, ctr) 415 gv_check("S12c1-wgsl-void-return-inside-VIO-entry-returns-the-struct" as *u8, wgg_has(db, dn, "vo.vcol=vec4f(0.0);\nreturn vo;\n}" as *u8), ctr) 416 gv_check("S12c1-glsl-void-return-is-bare" as *u8, wgg_has(db, dn, "vcol=vec4(0.0);\nreturn;\n}" as *u8), ctr) 417 gv_check_eq("neg-control-S12c1-no-dialect-emits-return-space-semicolon" as *u8, wgg_count(db, dn, "return ;" as *u8), 0, ctr) 418 gv_check_eq("S12c1-void-return-trace-identity-holds-across-dialects (cast11vs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast11vs_trace_equal=" as *u8), 1, ctr) 419 gv_check("control-the-3D-u32-load-path-is-UNCHANGED-by-the-typed-result (textureLoad(vox,vec3i(x,y,z),0).x still emitted)" as *u8, wgg_has(db, dn, "textureLoad(vox,vec3i(x,y,z),0).x" as *u8), ctr) 420 let prc: i64 = wgg_num_after(db, dn, "posctl_wgsl_rc=" as *u8) 421 gv_puts(" posctl_wgsl_rc=" as *u8); gv_num(prc); gv_puts("\n" as *u8) 422 gv_check("positive-control-a-SCALAR-uniform-is-ADMITTED (wgsl rc>0: the guard does not refuse everything)" as *u8, prc > 0, ctr) 423 gv_check("positive-control-no-refusal-fired-on-it" as *u8, wgg_has(db, dn, "posctl_wgsl_named=NONE" as *u8), ctr) 424 gv_check("positive-control-struct-U-carries-the-scalar (scale:f32)" as *u8, wgg_has(db, dn, "scale:f32," as *u8), ctr) 425 426 // ---- S2 (2026-09-04): A UNIFORM READ IS `u.<name>` IN WGSL AND BARE IN GLSL; SHADOWING WINS ---- 427 // Measured on the S1 positive control before S2: WGSL printed `v=(v*scale);` under `struct U{scale:f32,}` 428 // -- an undeclared identifier, no refusal. The same probe now carries both dialects' spelling, and two 429 // neg-controls prove the resolver reads SCOPE, not just the name: a local and a parameter named like a 430 // uniform must stay bare. 431 gv_check("wgsl-QUALIFIES-the-uniform-read (v=(v*u.scale);)" as *u8, wgg_has(db, dn, "v=(v*u.scale);" as *u8), ctr) 432 gv_check("glsl-keeps-the-BARE-uniform-read (v=(v*scale);)" as *u8, wgg_has(db, dn, "v=(v*scale);" as *u8), ctr) 433 gv_check_eq("the-qualifier-appears-EXACTLY-ONCE (WGSL only -- it never leaks into the GLSL printed beside it)" as *u8, wgg_count(db, dn, "u.scale" as *u8), 1, ctr) 434 gv_check_eq("trace-identity-STILL-holds-with-a-uniform-in-play (posctl_trace_equal)" as *u8, wgg_num_after(db, dn, "posctl_trace_equal=" as *u8), 1, ctr) 435 gv_check("shadow-local-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "shadowlocal_rc=" as *u8) > 0, ctr) 436 gv_check("neg-control-a-LOCAL-named-like-a-uniform-is-NOT-qualified (v=(v*k);)" as *u8, wgg_has(db, dn, "v=(v*k);" as *u8), ctr) 437 gv_check("shadow-param-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "shadowparam_rc=" as *u8) > 0, ctr) 438 gv_check("neg-control-a-PARAM-named-like-a-uniform-is-NOT-qualified (return (k*2.0);)" as *u8, wgg_has(db, dn, "return (k*2.0);" as *u8), ctr) 439 gv_check_eq("neg-control-the-shadowed-uniform-is-NEVER-qualified (count of u.k is 0)" as *u8, wgg_count(db, dn, "u.k" as *u8), 0, ctr) 440 441 // ---- S5 (2026-09-04): THE FRAGMENT OUTPUT IS A DECLARATION, AND BOTH HALVES OF THE SIGNATURE ARE DATA ---- 442 // TWO defects, one shape. (a) The GLSL fragment stage had NO output declaration and lowered S_RETURN to 443 // `return <e>;` inside `void main()` -- invalid GLSL ES 3.00 twice over, emitted with no refusal, and 444 // invisible because nothing in this gate pinned the GLSL fragment bytes. It does now, and that absence 445 // was the whole reason the defect survived S1-S4. (b) The WGSL side spelled its signature tail as the 446 // literal ")->@location(0) vec4f{", so the location and the type were unreadable constants -- the same 447 // defect S4 had just removed from the PARAMETER half of that identical line. Both halves are derived now. 448 gv_check("fragout-glsl-probe-emitted (fragout_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "fragout_glsl_rc=" as *u8) > 0, ctr) 449 gv_check("fragout-wgsl-probe-emitted (fragout_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "fragout_wgsl_rc=" as *u8) > 0, ctr) 450 gv_check("glsl-DECLARES-the-fragment-output-and-ASSIGNS-it (one contiguous KAT)" as *u8, wgg_has(db, dn, WGG_FRAGOUT_GLSL), ctr) 451 gv_check_eq("neg-control-the-glsl-fragment-entry-RETURNS-NOTHING (count of 'return vec4(1.0,0.0,0.0,1.0)' is 0)" as *u8, wgg_count(db, dn, "return vec4(1.0,0.0,0.0,1.0)" as *u8), 0, ctr) 452 gv_check("wgsl-DERIVES-the-return-half-to-the-old-literal-EXACTLY (KAT)" as *u8, wgg_has(db, dn, WGG_FRAGOUT_WGSL), ctr) 453 gv_check_eq("neg-control-wgsl-declares-NO-out-variable-for-it (count of 'out vec4f' is 0)" as *u8, wgg_count(db, dn, "out vec4f" as *u8), 0, ctr) 454 gv_check_eq("fragout-trace-identity-holds-across-dialects (fragout_trace_equal)" as *u8, wgg_num_after(db, dn, "fragout_trace_equal=" as *u8), 1, ctr) 455 // THE LOCATION IS DATA. A tooth that only ever saw location 0 could not tell a derived number from the 456 // constant it replaced -- this is the tooth the trivial wrong implementation (keep printing 0) fails. 457 gv_check("anti-vacuity-a-NON-ZERO-location-reaches-the-glsl-layout-qualifier" as *u8, wgg_has(db, dn, WGG_FRAGLOC2_GLSL), ctr) 458 gv_check("anti-vacuity-a-NON-ZERO-location-reaches-the-wgsl-@location" as *u8, wgg_has(db, dn, WGG_FRAGLOC2_WGSL), ctr) 459 gv_check_eq("location-0-FRAGOUT-emits-NO-layout-qualifier (a loc-0 out is bare; S6 attributes carry layout(location=0) in, so this counts the loc-0 out form specifically, not the shared prefix)" as *u8, wgg_count(db, dn, "layout(location=0) out" as *u8), 0, ctr) 460 // POSITIVE CONTROL for the PRECISION of the rule: the requirement binds to a body that RETURNS A VALUE, 461 // never to the stage. A discard-only fragment is a legal program with no colour output, and a guard that 462 // refused it would be a false-positive generator -- the failure mode a deny-guard is most prone to. 463 gv_check("positive-control-a-DISCARD-only-fragment-needs-no-output-glsl (rc>0)" as *u8, wgg_num_after(db, dn, "fragdiscard_glsl_rc=" as *u8) > 0, ctr) 464 gv_check("positive-control-a-DISCARD-only-fragment-needs-no-output-wgsl (rc>0)" as *u8, wgg_num_after(db, dn, "fragdiscard_wgsl_rc=" as *u8) > 0, ctr) 465 gv_check("positive-control-discard-only-glsl-body-is-EXACTLY-void-main-discard" as *u8, wgg_has(db, dn, WGG_FRAGDISCARD_GLSL), ctr) 466 gv_check("positive-control-discard-only-wgsl-entry-carries-NO-return-type" as *u8, wgg_has(db, dn, WGG_FRAGDISCARD_WGSL), ctr) 467 // NEG-CONTROLS. Each asserts WHICH rule fired, never merely that something was refused. 468 gv_check_eq("neg-control-value-returned-with-NO-declared-output-REFUSES-in-glsl (rc=-1)" as *u8, wgg_num_after(db, dn, "fragnoout_glsl_rc=" as *u8), 0 - 1, ctr) 469 gv_check("neg-control-glsl-no-output-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGNOOUT_GL), ctr) 470 gv_check_eq("neg-control-value-returned-with-NO-declared-output-REFUSES-in-wgsl (rc=-1)" as *u8, wgg_num_after(db, dn, "fragnoout_wgsl_rc=" as *u8), 0 - 1, ctr) 471 gv_check("neg-control-wgsl-no-output-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGNOOUT_WG), ctr) 472 gv_check_eq("neg-control-a-fragment-output-on-a-VERTEX-stage-REFUSES-in-glsl (rc=-1)" as *u8, wgg_num_after(db, dn, "vertfragout_glsl_rc=" as *u8), 0 - 1, ctr) 473 gv_check("neg-control-vertex-fragout-glsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_VERTFRAGOUT_GL), ctr) 474 gv_check_eq("neg-control-a-fragment-output-on-a-VERTEX-stage-REFUSES-in-wgsl (rc=-1)" as *u8, wgg_num_after(db, dn, "vertfragout_wgsl_rc=" as *u8), 0 - 1, ctr) 475 gv_check("neg-control-vertex-fragout-wgsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_VERTFRAGOUT_WG), ctr) 476 gv_check_eq("neg-control-TWO-declared-outputs-REFUSE-in-glsl (rc=-1; MRT is its own rung)" as *u8, wgg_num_after(db, dn, "fragtwoout_glsl_rc=" as *u8), 0 - 1, ctr) 477 gv_check("neg-control-two-output-glsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TWOOUT_GL), ctr) 478 gv_check_eq("neg-control-TWO-declared-outputs-REFUSE-in-wgsl (rc=-1; MRT is its own rung)" as *u8, wgg_num_after(db, dn, "fragtwoout_wgsl_rc=" as *u8), 0 - 1, ctr) 479 gv_check("neg-control-two-output-wgsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TWOOUT_WG), ctr) 480 481 // ---- S5 residual (b): A SAMPLED READ REFUSES IN WGSL AND EMITS IN GLSL ---- 482 // wg_expr emitted `textureSample(t,samp,c)` against an UNDECLARED `samp` -- WGSL that does not compile, 483 // produced with no refusal, while wgsl_emit_module's declaration pass ALREADY refused a texture_2d<f32> 484 // for exactly that missing binding. The declaration side refused and the expression side guessed. 485 // Measured over the shipping world shader before choosing a remedy: texelFetch 1 / textureLoad 1 / 486 // texture( 0 / textureSample 0 -- ZERO sampled reads, so a sampler declaration kind would have been 487 // built for no caller. The GLSL half is asserted too: a refusal with no ADMITTING twin would not prove 488 // the rule is about the sampler rather than about the operation. 489 // GE54 (2026-09-05): the two `SAMPLED read REFUSES in wgsl` neg-controls were RETIRED -- E_TEXSAMPLE now emits 490 // textureSample(<tex>,<tex>_s,<coord>) against the DERIVED companion sampler (proven by the tex2d teeth), so 491 // asserting it refuses asserts the old world. The two controls below still stand: the OLD undeclared placeholder 492 // `,samp,` must appear NOWHERE, and the GLSL sampled read still emits -- the rule was the sampler, not the op. 493 gv_check_eq("neg-control-the-undeclared-sampler-`samp`-is-emitted-NOWHERE (count of ',samp,' is 0)" as *u8, wgg_count(db, dn, ",samp," as *u8), 0, ctr) 494 gv_check("positive-control-the-SAME-sampled-read-still-EMITS-in-glsl (rc>0: the rule is the sampler, not the operation)" as *u8, wgg_num_after(db, dn, "texsample_glsl_rc=" as *u8) > 0, ctr) 495 gv_check("positive-control-glsl-emits-texture(vox,uv)" as *u8, wgg_has(db, dn, WGG_TEXSAMPLE_GLSL), ctr) 496 497 // ---- S5: THE GATE'S OWN NUMBER PARSER IS ANCHORED (a defect this run FOUND, in the gate itself) ---- 498 // wgg_num_after was an unanchored substring search keeping the LAST hit. "fragout_glsl_rc=" is a strict 499 // SUFFIX of "vertfragout_glsl_rc=", so the fragout teeth were reading the vertex-stage refusal's -1. 500 // The colliding label pair is DELIBERATELY retained so this control cannot go vacuous: it is measuring 501 // a collision that genuinely exists in the subject's output, not a planted one. 502 gv_check("neg-control-the-number-parser-ANCHORS-AT-A-LINE-START (fragout_glsl_rc= is a SUFFIX of vertfragout_glsl_rc=)" as *u8, wgg_num_after(db, dn, "fragout_glsl_rc=" as *u8) != wgg_num_after(db, dn, "vertfragout_glsl_rc=" as *u8), ctr) 503 gv_check_eq("positive-control-the-SUFFIX-label-still-reads-ITS-OWN-number (vertfragout_glsl_rc=-1)" as *u8, wgg_num_after(db, dn, "vertfragout_glsl_rc=" as *u8), 0 - 1, ctr) 504 gv_check("anti-vacuity-the-collision-is-REAL-in-the-subject-output (both labels present)" as *u8, wgg_has(db, dn, "\nfragout_glsl_rc=" as *u8) + wgg_has(db, dn, "\nvertfragout_glsl_rc=" as *u8) == 2, ctr) 505 506 // ---- R-A / R-C (2026-09-04): select() AND let -- the first two IR kinds the world shader needs (GE44) ---- 507 // The whole-population diff of the two hand world shaders named five missing IR kinds (B1-B5). E_SELECT and 508 // the let flag are the two that need no new declaration machinery, so they land first. Each spelling is 509 // asserted EXACTLY in its own dialect and asserted ABSENT from the other; trace identity holds. 510 gv_check("selectlet-glsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "selectlet_glsl_rc=" as *u8) > 0, ctr) 511 gv_check("selectlet-wgsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "selectlet_wgsl_rc=" as *u8) > 0, ctr) 512 gv_check("glsl-lowers-E_SELECT-to-the-ternary-and-let-to-a-plain-local (float t=((c>0)?a:b);)" as *u8, wgg_has(db, dn, "float t=((c>0)?a:b);" as *u8), ctr) 513 gv_check("wgsl-lowers-E_SELECT-to-select(f,t,cond)-and-let-to-let (let t:f32=select(b,a,(c>0));)" as *u8, wgg_has(db, dn, "let t:f32=select(b,a,(c>0));" as *u8), ctr) 514 gv_check_eq("neg-control-the-ternary-appears-ONCE (GLSL only; it never leaks into WGSL)" as *u8, wgg_count(db, dn, "?a:b)" as *u8), 1, ctr) 515 gv_check_eq("neg-control-select(b,a-appears-ONCE (WGSL only; it never leaks into GLSL)" as *u8, wgg_count(db, dn, "=select(b,a," as *u8), 1, ctr) 516 gv_check_eq("neg-control-the-let-local-is-never-spelled-var-in-wgsl (count of 'var t:f32' is 0)" as *u8, wgg_count(db, dn, "var t:f32" as *u8), 0, ctr) 517 gv_check_eq("selectlet-trace-identity-holds-across-dialects (selectlet_trace_equal)" as *u8, wgg_num_after(db, dn, "selectlet_trace_equal=" as *u8), 1, ctr) 518 519 // ---- R-B: the counted loop (GE44, B3 of the hand-shader diff) is BUILDER SUGAR over S_LOOP/S_BREAK ---- 520 // sir_for_until appends init; loop { if until { break } body; step } -- so both dialects lower it through arms 521 // they already share and the only per-dialect bytes are the loop keyword and the declaration spelling. Each 522 // shape is asserted EXACTLY with the exit test FIRST and the step LAST, the sugar never spells `for(` in either 523 // dialect, and the trace is identical by construction. 524 gv_check("foruntil-glsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "foruntil_glsl_rc=" as *u8) > 0, ctr) 525 gv_check("foruntil-wgsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "foruntil_wgsl_rc=" as *u8) > 0, ctr) 526 gv_check("glsl-lowers-the-counted-loop-to-while(true)-exit-test-first-step-last (int i=0; while(true){ if((i>=n)){ break; } s=(s+i); i=(i+1); })" as *u8, wgg_has(db, dn, "int i=0;\nwhile(true){\nif((i>=n)){\nbreak;\n}\ns=(s+i);\ni=(i+1);\n}" as *u8), ctr) 527 gv_check("wgsl-lowers-the-counted-loop-to-loop-exit-test-first-step-last (var i:i32=0; loop{ if((i>=n)){ break; } s=(s+i); i=(i+1); })" as *u8, wgg_has(db, dn, "var i:i32=0;\nloop{\nif((i>=n)){\nbreak;\n}\ns=(s+i);\ni=(i+1);\n}" as *u8), ctr) 528 gv_check_eq("neg-control-while(true)-appears-ONCE (GLSL only; it never leaks into WGSL)" as *u8, wgg_count(db, dn, "while(true){" as *u8), 1, ctr) 529 gv_check_eq("neg-control-loop{-appears-ONCE (WGSL only; it never leaks into GLSL)" as *u8, wgg_count(db, dn, "loop{" as *u8), 1, ctr) 530 gv_check_eq("neg-control-the-sugar-never-spells-for( in either dialect (count 0)" as *u8, wgg_count(db, dn, "for(" as *u8), 0, ctr) 531 gv_check_eq("the-step-is-the-last-statement-of-the-body-in-BOTH-dialects (i=(i+1); then the closing brace then return s; twice)" as *u8, wgg_count(db, dn, "i=(i+1);\n}\nreturn s;" as *u8), 2, ctr) 532 gv_check_eq("foruntil-trace-identity-holds-across-dialects (foruntil_trace_equal)" as *u8, wgg_num_after(db, dn, "foruntil_trace_equal=" as *u8), 1, ctr) 533 534 // ---- R-D: K_STRUCT declaration + member access (GE44, B1 of the hand-shader diff) ---- 535 // One declaration kind, members as K_PARAM nodes, a struct type named by its declaration; construction is an 536 // E_CALL named after the struct and member access is the E_SWZ spelling both dialects already share. Each 537 // dialect's declaration bytes are asserted EXACTLY and asserted ABSENT from the other; the local, the member 538 // write and the nested member read are asserted per dialect; trace identity holds. 539 gv_check("struct-glsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "struct_glsl_rc=" as *u8) > 0, ctr) 540 gv_check("struct-wgsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "struct_wgsl_rc=" as *u8) > 0, ctr) 541 gv_check("glsl-declares-the-struct-with-semicolon-members-and-a-terminating-semicolon (struct Hit{vec3 pos;float d;};)" as *u8, wgg_has(db, dn, "struct Hit{vec3 pos;float d;};\n" as *u8), ctr) 542 gv_check("wgsl-declares-the-struct-with-comma-members-and-no-terminator (struct Hit{pos:vec3f,d:f32,})" as *u8, wgg_has(db, dn, "struct Hit{pos:vec3f,d:f32,}\n" as *u8), ctr) 543 gv_check("glsl-struct-typed-local-built-by-the-struct-constructor (Hit h=Hit(p,k);)" as *u8, wgg_has(db, dn, "Hit h=Hit(p,k);\n" as *u8), ctr) 544 gv_check("wgsl-struct-typed-local-built-by-the-struct-constructor (var h:Hit=Hit(p,k);)" as *u8, wgg_has(db, dn, "var h:Hit=Hit(p,k);\n" as *u8), ctr) 545 gv_check_eq("member-write-then-nested-member-read-spelled-IDENTICALLY-in-BOTH-dialects (h.d=(h.d*2.0); return (h.d+h.pos.x); twice)" as *u8, wgg_count(db, dn, "h.d=(h.d*2.0);\nreturn (h.d+h.pos.x);\n" as *u8), 2, ctr) 546 // R-E CORRECTION (same day): these three were hand-counted ONCE / TWICE and the R-E fixture's second Hit 547 // declaration turned the LIVE gate RED an hour after they shipped -- a count pinned to the fixture population 548 // is a magic number wearing a tooth. DERIVED now: the GLSL spelling and the WGSL spelling must occur EQUALLY 549 // often (every fixture declares once per dialect) and more than never; a leak of either spelling into the 550 // other dialect breaks the balance, which is exactly what the neg-controls existed to catch. 551 gv_check("glsl-member-spelling-present (vec3 pos;)" as *u8, wgg_count(db, dn, "vec3 pos;" as *u8) > 0, ctr) 552 gv_check_eq("neg-control-member-spellings-BALANCE-across-dialects (count of vec3 pos; equals count of pos:vec3f -- a leak breaks it)" as *u8, wgg_count(db, dn, "vec3 pos;" as *u8), wgg_count(db, dn, "pos:vec3f" as *u8), ctr) 553 gv_check_eq("the-struct-declaration-BALANCES-across-dialects (count of struct Hit{vec3 equals count of struct Hit{pos:)" as *u8, wgg_count(db, dn, "struct Hit{vec3 " as *u8), wgg_count(db, dn, "struct Hit{pos:" as *u8), ctr) 554 gv_check_eq("struct-trace-identity-holds-across-dialects (struct_trace_equal)" as *u8, wgg_num_after(db, dn, "struct_trace_equal=" as *u8), 1, ctr) 555 556 // ---- R-E: struct RETURN and struct PARAMETER, one canonical shape (GE44, B2 of the hand-shader diff) ---- 557 // The two hand shaders spell march two ways (GLSL out-params, WGSL struct return). GLSL ES 3.00 returns 558 // structs, so the IR carries ONE shape and both signature emitters spell the struct by its declaration; no 559 // out-parameter twin exists to disagree with. Asserted exactly per dialect, the member read straight off the 560 // call result identical in both, the struct-return signature once per dialect, trace identity. 561 gv_check("structret-glsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "structret_glsl_rc=" as *u8) > 0, ctr) 562 gv_check("structret-wgsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "structret_wgsl_rc=" as *u8) > 0, ctr) 563 gv_check("glsl-returns-a-struct-from-a-plain-function (Hit mk(vec3 p,float k){ Hit h=Hit(p,k); h.d=(k*2.0); return h; })" as *u8, wgg_has(db, dn, "Hit mk(vec3 p,float k){\nHit h=Hit(p,k);\nh.d=(k*2.0);\nreturn h;\n}\n" as *u8), ctr) 564 gv_check("wgsl-returns-a-struct-from-a-plain-function (fn mk(p:vec3f,k:f32)->Hit{ var h:Hit=Hit(p,k); h.d=(k*2.0); return h; })" as *u8, wgg_has(db, dn, "fn mk(p:vec3f,k:f32)->Hit{\nvar h:Hit=Hit(p,k);\nh.d=(k*2.0);\nreturn h;\n}\n" as *u8), ctr) 565 gv_check("glsl-takes-a-struct-parameter (float useh(Hit h,float k){)" as *u8, wgg_has(db, dn, "float useh(Hit h,float k){\n" as *u8), ctr) 566 gv_check("wgsl-takes-a-struct-parameter (fn useh(h:Hit,k:f32)->f32{)" as *u8, wgg_has(db, dn, "fn useh(h:Hit,k:f32)->f32{\n" as *u8), ctr) 567 gv_check_eq("member-read-straight-off-the-call-result-spelled-IDENTICALLY-in-BOTH-dialects (return (mk(h.pos,k).d+h.d); twice)" as *u8, wgg_count(db, dn, "return (mk(h.pos,k).d+h.d);\n" as *u8), 2, ctr) 568 gv_check("glsl-struct-return-signature-present (Hit mk( -- no out-parameter twin)" as *u8, wgg_count(db, dn, "Hit mk(" as *u8) > 0, ctr) 569 gv_check_eq("neg-control-struct-return-signatures-BALANCE-across-dialects (count of Hit mk( equals count of ->Hit{ -- derived, not pinned to the fixture population)" as *u8, wgg_count(db, dn, "Hit mk(" as *u8), wgg_count(db, dn, "->Hit{" as *u8), ctr) 570 gv_check_eq("structret-trace-identity-holds-across-dialects (structret_trace_equal)" as *u8, wgg_num_after(db, dn, "structret_trace_equal=" as *u8), 1, ctr) 571 572 // ---- R-F: the uniform LAYOUT is derived from the IR by the WGSL rules and published as data (GE44) ---- 573 // A SECOND capture: `nx_wgsl layout` prints the world uniform block through both backends, one row per uniform 574 // (offset/size/align/stride/count) and the struct size. The KAT is the shipping page packer's own numbers 575 // (WGG_PACKER_*), so 112, 304 and 384 are read off the artifact the layout must serve, never off this gate; 576 // the spec's uniform stride rule is bite-proven by the array<f32,8> neg-control refusing BY NAME. 577 let lb: *u8 = sys_mmap(WGG_CAP) 578 bl[0] = 0 579 let lrc: i64 = gk_run_capture(subject, "layout" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, lb, WGG_CAP, bl) 580 let ln: i64 = bl[0] 581 gv_puts(" layout rc=" as *u8); gv_num(lrc); gv_puts(" bytes=" as *u8); gv_num(ln); gv_puts("\n" as *u8) 582 gv_check("layout-verb-ran (rc=0)" as *u8, lrc == 0, ctr) 583 gv_check("layout-verb-emitted-bytes" as *u8, ln > 0, ctr) 584 gv_check_eq("struct-U-size-equals-the-packer's-96-floats-times-4 (struct_u_size)" as *u8, wgg_num_after(lb, ln, "struct_u_size=" as *u8), WGG_PACKER_FLOATS * WGG_FLOAT_BYTES, ctr) 585 gv_check_eq("pal-offset-equals-the-packer's-float-index-28-times-4 (uniform|pal|offset=)" as *u8, wgg_num_after(lb, ln, "uniform|pal|offset=" as *u8), WGG_PACKER_PAL_F * WGG_FLOAT_BYTES, ctr) 586 gv_check_eq("palf-offset-equals-the-packer's-float-index-76-times-4 (uniform|palf|offset=)" as *u8, wgg_num_after(lb, ln, "uniform|palf|offset=" as *u8), WGG_PACKER_PALF_F * WGG_FLOAT_BYTES, ctr) 587 gv_check("vec3f-member-aligns-to-16-sizes-12-and-the-next-f32-packs-into-its-tail (cam at 0 size 12, t at 12)" as *u8, wgg_has(lb, ln, "uniform|cam|offset=0|size=12|align=16|stride=0|count=0\nuniform|t|offset=12|size=4|align=4|stride=0|count=0\n" as *u8), ctr) 588 gv_check("vec2f-member-aligns-to-8 (res at 80 size 8 align 8)" as *u8, wgg_has(lb, ln, "uniform|res|offset=80|size=8|align=8|stride=0|count=0\n" as *u8), ctr) 589 gv_check("vec4f-array-stride-is-16-and-size-is-stride-times-count (pal 192 over 12, palf 80 over 5)" as *u8, wgg_has(lb, ln, "uniform|pal|offset=112|size=192|align=16|stride=16|count=12\nuniform|palf|offset=304|size=80|align=16|stride=16|count=5\n" as *u8), ctr) 590 gv_check("the-emitted-struct-U-carries-the-hand-shader's-array-spellings (pal:array<vec4f,12>, palf:array<vec4f,5>,)" as *u8, wgg_has(lb, ln, "pal:array<vec4f,12>,\npalf:array<vec4f,5>,\n" as *u8), ctr) 591 gv_check("the-uniform-read-is-qualified-in-wgsl (return (u.t*k);)" as *u8, wgg_has(lb, ln, "return (u.t*k);" as *u8), ctr) 592 gv_check("the-uniform-read-is-bare-in-glsl (return (t*k);)" as *u8, wgg_has(lb, ln, "return (t*k);" as *u8), ctr) 593 gv_check("layout-positive-control-admitted (layout_rc=384 layout_named=NONE)" as *u8, wgg_has(lb, ln, "layout_rc=384 layout_named=NONE" as *u8), ctr) 594 // S12c-2b: the neg-control's subject moved from array<f32,8> (now LOWERED, below) to array<vec2f,8> -- stride 8 is genuinely 595 // invalid in the uniform address space and has no lowering, so the refusal still fires BY NAME on a real offender. 596 gv_check("neg-control-uniform-array<vec2f,8>-refuses-BY-NAME (stride not a multiple of 16)" as *u8, wgg_has(lb, ln, "layoutbad_rc=-1 layoutbad_named=wgsl: uniform array element stride is not a multiple of 16" as *u8), ctr) 597 gv_check("S12c2b-uniform-array<f32,8>-is-LOWERED-to-two-vec4-lanes (offset=0 size=32 align=16 stride=16 count=2 f32n=8)" as *u8, wgg_has(lb, ln, "uniform|w|offset=0|size=32|align=16|stride=16|count=2|f32n=8" as *u8), ctr) 598 gv_check("S12c2b-lowered-f32-array-struct-size-is-32 (layoutf32_rc=32)" as *u8, wgg_has(lb, ln, "layoutf32_rc=32" as *u8), ctr) 599 600 // ---- R-G teeth: the WORLD shader (the full ray-marcher) emits through BOTH dialects, once (GE44) ---- 601 // A THIRD capture. `nx_wgsl world` builds the world fragment + vertex pass ONCE (nx_world_shader_src) and 602 // emits it to GLSL and WGSL. This is the pixel-parity claim's TEXT-LEVEL control and it survives the 603 // retirement of the page's hand WGSL literal, because it RE-DERIVES the emitted shader on every gate run 604 // rather than trusting a stored copy. rc is read off the report line, never pinned to the byte count (a real 605 // shader edit changes the count and must not read as a leak); named=NONE proves neither dialect refused; the 606 // trace identity proves ONE IR walk; dialect-specific spellings prove both fragments are genuinely present 607 // (one program emitted twice, never one dialect twice). The GLSL/WGSL march signatures must BALANCE. 608 let wb: *u8 = sys_mmap(WGG_CAP) 609 bl[0] = 0 610 let wrc: i64 = gk_run_capture(subject, "world" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, wb, WGG_CAP, bl) 611 let wn: i64 = bl[0] 612 gv_puts(" world rc=" as *u8); gv_num(wrc); gv_puts(" bytes=" as *u8); gv_num(wn); gv_puts("\n" as *u8) 613 gv_check("world-verb-ran (rc=0)" as *u8, wrc == 0, ctr) 614 gv_check("world-verb-emitted-bytes" as *u8, wn > 0, ctr) 615 gv_check("world-glsl-fragment-emitted (world_glsl_rc>0)" as *u8, wgg_num_after(wb, wn, "world_glsl_rc=" as *u8) > 0, ctr) 616 gv_check("world-glsl-fragment-not-refused (world_glsl_named=NONE)" as *u8, wgg_has(wb, wn, "world_glsl_named=NONE" as *u8), ctr) 617 gv_check("world-wgsl-fragment-emitted (world_wgsl_rc>0)" as *u8, wgg_num_after(wb, wn, "world_wgsl_rc=" as *u8) > 0, ctr) 618 gv_check("world-wgsl-fragment-not-refused (world_wgsl_named=NONE)" as *u8, wgg_has(wb, wn, "world_wgsl_named=NONE" as *u8), ctr) 619 gv_check_eq("world-fragment-trace-identity-holds-across-dialects (world_trace_equal)" as *u8, wgg_num_after(wb, wn, "world_trace_equal=" as *u8), 1, ctr) 620 gv_check("world-glsl-vertex-emitted (worldvs_glsl_rc>0)" as *u8, wgg_num_after(wb, wn, "worldvs_glsl_rc=" as *u8) > 0, ctr) 621 gv_check("world-wgsl-vertex-emitted (worldvs_wgsl_rc>0)" as *u8, wgg_num_after(wb, wn, "worldvs_wgsl_rc=" as *u8) > 0, ctr) 622 gv_check("world-glsl-dialect-spelling-uint-vx-present" as *u8, wgg_has(wb, wn, "uint vx(" as *u8), ctr) 623 gv_check("world-glsl-dialect-spelling-out-vec4-present" as *u8, wgg_has(wb, wn, "out vec4" as *u8), ctr) 624 gv_check("world-wgsl-dialect-spelling-fn-vx-present" as *u8, wgg_has(wb, wn, "fn vx(" as *u8), ctr) 625 gv_check("world-wgsl-dialect-spelling-Hit-return-arrow-present" as *u8, wgg_has(wb, wn, ")->Hit{" as *u8), ctr) 626 gv_check_eq("neg-control-march-signatures-BALANCE-across-dialects (count of Hit march( equals count of fn march()" as *u8, wgg_count(wb, wn, "Hit march(" as *u8), wgg_count(wb, wn, "fn march(" as *u8), ctr) 627 gv_kv("world_glsl_rc" as *u8, wgg_num_after(wb, wn, "world_glsl_rc=" as *u8)) 628 gv_kv("world_wgsl_rc" as *u8, wgg_num_after(wb, wn, "world_wgsl_rc=" as *u8)) 629 gv_kv("worldvs_glsl_rc" as *u8, wgg_num_after(wb, wn, "worldvs_glsl_rc=" as *u8)) 630 gv_kv("worldvs_wgsl_rc" as *u8, wgg_num_after(wb, wn, "worldvs_wgsl_rc=" as *u8)) 631 632 // ---- GE55 K_PRIVATE: module-scope private state, ONE declaration kind, both dialects (the decls capture) ---- 633 // The kind exists so the world shader can derive every float from RAW uniform words in one function while every 634 // other body stays byte-identical. Proven: declared per dialect (scalar and array spellings), written bare beside 635 // a QUALIFIED uniform read, an array element assigned in both dialects, never spelled u.<name>, trace-identical, 636 // and a texture-typed private refuses BY NAME in each dialect. The layout capture proves it is invisible there. 637 gv_check("priv-glsl-probe-emitted (priv_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "priv_glsl_rc=" as *u8) > 0, ctr) 638 gv_check("priv-wgsl-probe-emitted (priv_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "priv_wgsl_rc=" as *u8) > 0, ctr) 639 gv_check("wgsl-private-scalar-declared (var<private> gk:f32;)" as *u8, wgg_has(db, dn, "var<private> gk:f32;\n" as *u8), ctr) 640 gv_check("wgsl-private-array-declared (var<private> pv:array<vec4f,2>;)" as *u8, wgg_has(db, dn, "var<private> pv:array<vec4f,2>;\n" as *u8), ctr) 641 gv_check("glsl-private-scalar-declared (float gk;)" as *u8, wgg_has(db, dn, "float gk;\n" as *u8), ctr) 642 gv_check("glsl-private-array-declared (vec4 pv[2];)" as *u8, wgg_has(db, dn, "vec4 pv[2];\n" as *u8), ctr) 643 gv_check("wgsl-private-written-bare-beside-a-QUALIFIED-uniform-read (gk=(u.q*2.0);)" as *u8, wgg_has(db, dn, "gk=(u.q*2.0);\n" as *u8), ctr) 644 gv_check("glsl-private-written-bare-beside-a-bare-uniform-read (gk=(q*2.0);)" as *u8, wgg_has(db, dn, "gk=(q*2.0);\n" as *u8), ctr) 645 gv_check_eq("neg-control-private-never-qualified-as-a-uniform (count of u.gk)" as *u8, wgg_count(db, dn, "u.gk" as *u8), 0, ctr) 646 gv_check_eq("private-array-element-assigned-in-BOTH-dialects (pv[0]= twice)" as *u8, wgg_count(db, dn, "pv[0]=" as *u8), 2, ctr) 647 gv_check_eq("priv-trace-identity-holds-across-dialects (priv_trace_equal)" as *u8, wgg_num_after(db, dn, "priv_trace_equal=" as *u8), 1, ctr) 648 gv_check("neg-control-texture-typed-private-refuses-BY-NAME-in-glsl" as *u8, wgg_has(db, dn, "privtex_glsl_rc=-1 privtex_glsl_named=glsl: texture-typed private variable" as *u8), ctr) 649 gv_check("neg-control-texture-typed-private-refuses-BY-NAME-in-wgsl" as *u8, wgg_has(db, dn, "privtex_wgsl_rc=-1 privtex_wgsl_named=wgsl: texture-typed private variable" as *u8), ctr) 650 gv_check("layout-lists-the-uniform-beside-the-private (uniform|q|offset=0|size=4)" as *u8, wgg_has(lb, ln, "uniform|q|offset=0|size=4|align=4|stride=0|count=0\n" as *u8), ctr) 651 gv_check_eq("neg-control-layout-never-lists-a-private (count of uniform|gk|)" as *u8, wgg_count(lb, ln, "uniform|gk|" as *u8), 0, ctr) 652 gv_check("layout-struct-size-is-the-uniform-alone (layoutpriv_rc=4)" as *u8, wgg_has(lb, ln, "layoutpriv_rc=4 rows:" as *u8), ctr) 653 gv_kv("priv_glsl_rc" as *u8, wgg_num_after(db, dn, "priv_glsl_rc=" as *u8)) 654 gv_kv("priv_wgsl_rc" as *u8, wgg_num_after(db, dn, "priv_wgsl_rc=" as *u8)) 655 656 // ---- GE55 step B: the world module takes the sim's RAW words and derives every float on the GPU ---- 657 // The layout capture pins the raw struct to the sim's UR_* table (one ruler, two consumers): camx at word 0, 658 // pal0 at 80, palf0 at 128, resw at 148, yflip at 156, struct 160 == URAW_BYTES. The world capture proves the 659 // emitted shaders now declare the raw words as the uniform block, hold the derived names as private state, carry 660 // upk(), and never read the old f32 uniforms through u. (a leak of `u.cam` would mean the flip did not happen). 661 gv_check("layoutraw-struct-is-164-bytes (layoutraw_rc=164: 41 raw words with r_surf at 160; AlignOf(U) is 4 for a scalar-only struct so SizeOf is offset+size of the last member and is NOT rounded to 16 -- the 176 this tooth once pinned was a prediction the backend never made; the sim block stays 176 = 44 words vec4-padded and the page copies the 164 the layout names -- GE53)" as *u8, wgg_has(lb, ln, "layoutraw_rc=164 rows:" as *u8), ctr) 662 gv_check("layoutraw-surf-at-byte-160 (UR_SURF=40, GE53: the ground-is-the-field word)" as *u8, wgg_has(lb, ln, "uniform|r_surf|offset=160|size=4|align=4|stride=0|count=0\n" as *u8), ctr) 663 gv_check("layoutraw-camx-at-word-0 (uniform|r_camx|offset=0|size=4)" as *u8, wgg_has(lb, ln, "uniform|r_camx|offset=0|size=4|align=4|stride=0|count=0\n" as *u8), ctr) 664 gv_check("layoutraw-pal0-at-byte-80 (UR_PAL=20)" as *u8, wgg_has(lb, ln, "uniform|r_pal0|offset=80|size=4|align=4|stride=0|count=0\n" as *u8), ctr) 665 gv_check("layoutraw-palf0-at-byte-128 (UR_PALF=32)" as *u8, wgg_has(lb, ln, "uniform|r_palf0|offset=128|size=4|align=4|stride=0|count=0\n" as *u8), ctr) 666 gv_check("layoutraw-resw-at-byte-148 (UR_RESW=37)" as *u8, wgg_has(lb, ln, "uniform|r_resw|offset=148|size=4|align=4|stride=0|count=0\n" as *u8), ctr) 667 gv_check("layoutraw-yflip-at-byte-156 (UR_YFLIP=39)" as *u8, wgg_has(lb, ln, "uniform|r_yflip|offset=156|size=4|align=4|stride=0|count=0\n" as *u8), ctr) 668 gv_check("world-wgsl-uniform-block-is-the-raw-words (struct U{ r_camx:i32,)" as *u8, wgg_has(wb, wn, "struct U{\nr_camx:i32,\n" as *u8), ctr) 669 gv_check("world-glsl-uniform-block-is-the-raw-words (uniform int r_camx;)" as *u8, wgg_has(wb, wn, "uniform int r_camx;\n" as *u8), ctr) 670 gv_check("world-wgsl-derived-palette-is-private-state (var<private> pal:array<vec4f,12>;)" as *u8, wgg_has(wb, wn, "var<private> pal:array<vec4f,12>;\n" as *u8), ctr) 671 gv_check("world-glsl-derived-palette-is-a-bare-global (vec4 pal[12];)" as *u8, wgg_has(wb, wn, "vec4 pal[12];\n" as *u8), ctr) 672 gv_check("world-wgsl-carries-upk (fn upk(){)" as *u8, wgg_has(wb, wn, "fn upk(){" as *u8), ctr) 673 gv_check("world-glsl-carries-upk (void upk(){)" as *u8, wgg_has(wb, wn, "void upk(){" as *u8), ctr) 674 gv_check("world-entry-calls-upk-first-in-both-dialects (upk(); twice)" as *u8, wgg_count(wb, wn, "upk();\n" as *u8) == 2, ctr) 675 gv_check_eq("neg-control-no-function-reads-the-old-f32-uniforms (count of u.cam)" as *u8, wgg_count(wb, wn, "u.cam" as *u8), 0, ctr) 676 gv_check("world-wgsl-reads-a-raw-word-qualified (f32(u.r_camx))" as *u8, wgg_has(wb, wn, "f32(u.r_camx)" as *u8), ctr) 677 gv_check("world-glsl-reads-a-raw-word-bare (float(r_camx))" as *u8, wgg_has(wb, wn, "float(r_camx)" as *u8), ctr) 678 gv_kv("layoutraw_rc" as *u8, wgg_num_after(lb, ln, "layoutraw_rc=" as *u8)) 679 680 // ---- GE55: a void function has no return arrow in WGSL (the backend once spelled fn upk()->void{) ---- 681 gv_check_eq("neg-control-wgsl-never-spells-a-void-return-arrow-in-the-world (count of ->void)" as *u8, wgg_count(wb, wn, "->void" as *u8), 0, ctr) 682 gv_check_eq("neg-control-wgsl-never-spells-a-void-return-arrow-in-decls (count of ->void)" as *u8, wgg_count(db, dn, "->void" as *u8), 0, ctr) 683 gv_check("wgsl-void-function-signature-has-no-arrow-in-the-private-fixture (fn upk(){)" as *u8, wgg_has(db, dn, "fn upk(){" as *u8), ctr) 684 685 // ---- GE54: sampled texture_2d<f32> lowers in both dialects (the cast fragment needs it; the world used only 686 // textureLoad, which takes no sampler). GLSL is one combined sampler2D; WGSL is a texture binding + a DERIVED 687 // companion sampler `<name>_s`, and the E_TEXSAMPLE arm uses exactly that name so they agree by construction. ---- 688 gv_check("tex2d-glsl-emitted (tex2dsmp_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "tex2dsmp_glsl_rc=" as *u8) > 0, ctr) 689 gv_check("tex2d-wgsl-emitted (tex2dsmp_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "tex2dsmp_wgsl_rc=" as *u8) > 0, ctr) 690 gv_check("glsl-declares-a-combined-sampler2D (uniform sampler2D atlas;)" as *u8, wgg_has(db, dn, "uniform sampler2D atlas;\n" as *u8), ctr) 691 gv_check("wgsl-declares-the-texture-binding (atlas:texture_2d<f32>;)" as *u8, wgg_has(db, dn, "atlas:texture_2d<f32>;\n" as *u8), ctr) 692 gv_check("wgsl-derives-a-companion-sampler (atlas_s:sampler;)" as *u8, wgg_has(db, dn, "atlas_s:sampler;\n" as *u8), ctr) 693 gv_check("glsl-samples-with-texture (texture(atlas,uv))" as *u8, wgg_has(db, dn, "texture(atlas,uv)" as *u8), ctr) 694 gv_check("wgsl-samples-with-textureSample-and-the-companion (textureSample(atlas,atlas_s,uv))" as *u8, wgg_has(db, dn, "textureSample(atlas,atlas_s,uv)" as *u8), ctr) 695 gv_check_eq("tex2d-trace-identity-holds-across-dialects (tex2dsmp_trace_equal)" as *u8, wgg_num_after(db, dn, "tex2dsmp_trace_equal=" as *u8), 1, ctr) 696 gv_check_eq("neg-control-glsl-has-NO-separate-wgsl-sampler-decl (count of atlas_s:sampler is a WGSL-only construct)" as *u8, wgg_count(db, dn, "sampler2D atlas;" as *u8), 1, ctr) 697 698 // S5 VALUES (gv_kv): an arithmetic that cannot see a number can never contradict one. 699 gv_kv("fragout_glsl_rc" as *u8, wgg_num_after(db, dn, "fragout_glsl_rc=" as *u8)) 700 gv_kv("fragout_wgsl_rc" as *u8, wgg_num_after(db, dn, "fragout_wgsl_rc=" as *u8)) 701 gv_kv("fragloc2_glsl_rc" as *u8, wgg_num_after(db, dn, "fragloc2_glsl_rc=" as *u8)) 702 gv_kv("fragdiscard_glsl_rc" as *u8, wgg_num_after(db, dn, "fragdiscard_glsl_rc=" as *u8)) 703 gv_kv("texsample_glsl_rc" as *u8, wgg_num_after(db, dn, "texsample_glsl_rc=" as *u8)) 704 gv_kv("layout_location_sites" as *u8, wgg_count(db, dn, "layout(location=" as *u8)) 705 gv_kv("undeclared_samp_sites" as *u8, wgg_count(db, dn, ",samp," as *u8)) 706 707 // ---- S12c-5 teeth (2026-09-05): the three spellings the cast FRAGMENT needs, on the decls capture's fragassign fixture ---- 708 // The hand fragment ASSIGNS its declared output and exits early with a void `return;` -- valid GLSL as-is, while WGSL must 709 // carry the output as a local (`var fc:vec4f;`), return it at every void return and once after the body. It also carries a 710 // `const float` local and a u-suffixed unsigned literal. The value-returning fragout fixture beside it (m8f) must be 711 // UNTOUCHED: exactly one `var fc:vec4f;` in the whole decls capture proves the lowering fires only where assignment happens. 712 gv_check("S12c5-fragassign-glsl-emitted-with-no-refusal" as *u8, wgg_has(db, dn, "fragassign_glsl_named=NONE" as *u8), ctr) 713 gv_check("S12c5-fragassign-wgsl-emitted-with-no-refusal" as *u8, wgg_has(db, dn, "fragassign_wgsl_named=NONE" as *u8), ctr) 714 gv_check("S12c5-glsl-assigns-the-out-variable-void-returns-const-local-and-0u-literal (fc=vec4(1.0); return; const float K=1.2; uint z=0u; fc=vec4(K);)" as *u8, wgg_has(db, dn, "fc=vec4(1.0);\nreturn;\n}\nconst float K=1.2;\nuint z=0u;\nfc=vec4(K);\n}" as *u8), ctr) 715 gv_check("S12c5-wgsl-carries-the-output-as-a-local-and-returns-it-at-every-exit (var fc:vec4f; ... return fc; ... return fc;)" as *u8, wgg_has(db, dn, "var fc:vec4f;\nif((u.a<0.5)){\nfc=vec4f(1.0);\nreturn fc;\n}\nconst K:f32=1.2;\nvar z:u32=0u;\nfc=vec4f(K);\nreturn fc;\n}" as *u8), ctr) 716 gv_check("neg-control-the-output-local-appears-ONLY-in-the-assigning-fixture (count of var fc:vec4f; is 1; the value-returning fixture stays untouched)" as *u8, wgg_count(db, dn, "var fc:vec4f;" as *u8) == 1, ctr) 717 gv_check("S12c5-fragassign-trace-identity-holds-across-dialects (fragassign_trace_equal=1)" as *u8, wgg_has(db, dn, "fragassign_trace_equal=1" as *u8), ctr) 718 gv_check("neg-control-glsl-never-spells-the-wgsl-local-form (count of var fc:vec4f in GLSL is impossible; uint z=0u; appears once)" as *u8, wgg_count(db, dn, "uint z=0u;" as *u8) == 1, ctr) 719 720 // ---- S12c teeth (2026-09-05): THE CAST vertex stage (nx_cast_shader_src) through both backends, `nx_wgsl cast` ---- 721 // The GLSL side's proof is the canonical token ruler against the hand MVS (nx_glsl_tokdiff, journaled on gameengine.plan); 722 // these teeth pin what the WGSL side must carry to be VALID WGSL under S12c-2b: the float[N] uniforms lowered to vec4 lanes 723 // and read as [i/4][i%4], no array<f32 member anywhere, the instance builtin bound as iidx so the cast's own local ii 724 // cannot collide, and logical not spelled in both dialects. Refusal-free emission in both dialects is asserted by name. 725 let cb: *u8 = sys_mmap(WGG_CAP) 726 bl[0] = 0 727 let crc: i64 = gk_run_capture(subject, "cast" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, cb, WGG_CAP, bl) 728 let cn: i64 = bl[0] 729 gv_puts(" cast rc=" as *u8); gv_num(crc); gv_puts(" bytes=" as *u8); gv_num(cn); gv_puts("\n" as *u8) 730 gv_check("S12c-cast-verb-ran (rc=0)" as *u8, crc == 0, ctr) 731 gv_check("S12c-cast-verb-emits-GLSL-with-no-refusal" as *u8, wgg_has(cb, cn, "cast_glsl_named=NONE" as *u8), ctr) 732 gv_check("S12c-cast-verb-emits-WGSL-with-no-refusal" as *u8, wgg_has(cb, cn, "cast_wgsl_named=NONE" as *u8), ctr) 733 gv_check("S12c-glsl-keeps-the-hand-float-array (uniform float uGN[12];)" as *u8, wgg_has(cb, cn, "uniform float uGN[12];" as *u8), ctr) 734 gv_check("S12c-glsl-reads-the-float-array-bare (uGN[ii])" as *u8, wgg_has(cb, cn, "float gs9=uGN[ii];" as *u8), ctr) 735 gv_check("S12c2b-wgsl-lowers-float-array-to-vec4-lanes (uGN:array<vec4f,3>)" as *u8, wgg_has(cb, cn, "uGN:array<vec4f,3>," as *u8), ctr) 736 gv_check("S12c2b-wgsl-lowers-the-72-vec3-array-untouched (uSB:array<vec3f,72>)" as *u8, wgg_has(cb, cn, "uSB:array<vec3f,72>," as *u8), ctr) 737 gv_check("S12c2b-wgsl-reads-the-lowered-lane (u.uGN[(ii)/4][(ii)%4])" as *u8, wgg_has(cb, cn, "u.uGN[(ii)/4][(ii)%4]" as *u8), ctr) 738 gv_check("neg-control-wgsl-never-declares-array<f32 (0 sites)" as *u8, wgg_count(cb, cn, "array<f32," as *u8) == 0, ctr) 739 gv_check("S12c2b-wgsl-instance-builtin-is-iidx-so-the-cast-local-ii-cannot-collide" as *u8, wgg_has(cb, cn, "@builtin(instance_index) iidx:u32" as *u8), ctr) 740 gv_check("S12c2b-wgsl-cast-local-ii-is-derived-from-iidx (var ii:i32=i32(iidx);)" as *u8, wgg_has(cb, cn, "var ii:i32=i32(iidx);" as *u8), ctr) 741 gv_check("S12c4-both-dialects-spell-logical-not-on-wr9 (2 sites)" as *u8, wgg_count(cb, cn, wgg_bang("(~wr9)" as *u8)) == 2, ctr) 742 gv_check("S12c4-both-dialects-spell-logical-not-on-the-skirt-gate (2 sites)" as *u8, wgg_count(cb, cn, wgg_bang("(~((((gbm==4)||(gbm==5))||(gbm==8))||(gbm==9)))" as *u8)) == 2, ctr) 743 gv_check("S12c-cast-emits-the-clip-transform-in-both-dialects (2 sites)" as *u8, wgg_count(cb, cn, "(300.08/299.92)" as *u8) == 2, ctr) 744 // S12c-6: WGSL has no scalar-bound overload of clamp/min/max, so the skin tail's clamp((vec3(ndl)+w3)/(1.+w3),0.,1.) must 745 // read vec3f bounds in WGSL and scalar bounds in GLSL; an all-scalar clamp and an all-vector min must pass through untouched 746 gv_check("S12c6-wgsl-splats-scalar-bounds-on-the-vector-clamp (dif3: ,vec3f(0.0),vec3f(1.0)) once)" as *u8, wgg_count(cb, cn, ",vec3f(0.0),vec3f(1.0))" as *u8) == 1, ctr) 747 gv_check("neg-control-S12c6-glsl-keeps-the-scalar-bounds-and-only-glsl-does ((1.0+w3)),0.0,1.0) exactly once)" as *u8, wgg_count(cb, cn, "(1.0+w3)),0.0,1.0)" as *u8) == 1, ctr) 748 gv_check("neg-control-S12c6-all-scalar-clamp-untouched-in-both-dialects (clamp(fl9,0.0,0.3) twice)" as *u8, wgg_count(cb, cn, "clamp(fl9,0.0,0.3)" as *u8) == 2, ctr) 749 gv_check("neg-control-S12c6-all-vector-min-untouched (min(spec8,vec3f(6.0)) once)" as *u8, wgg_count(cb, cn, "min(spec8,vec3f(6.0))" as *u8) == 1, ctr) 750 751 return gv_verdict("NX-WGSL" as *u8, ctr, "one NishiLang source emits both dialects; equivalence is measured at the IR level and the pixel level is declared unproven" as *u8) 752}