nx_wgsl_cast_lbs_t181.nx
buildroot/runtime/nx_wgsl_cast_lbs_t181.nx
about
nx_wgsl.nx -- THE SHADER BACKENDS: NishiLang in, GLSL and WGSL out.
CONTRACT SYMBOL: wgsl_emit_module (declared _ABSENT_ on the graphics compare board until now).
THE SOURCE IS NISHILANG, NOT GLSL (operator 2026-08-23). This organ is NOT a GLSL->WGSL
transpiler. A shader is authored ONCE against the nx_shader_ir representation; glsl_emit_module
and wgsl_emit_module are two BACKENDS over that one source, exactly as nx_compile_x86 and the
WAT lane are two backends over one NishiLang front-end. Neither dialect is authored, so neither
can drift from the other -- disagreement is impossible BY CONSTRUCTION rather than by discipline.
RUNG 1, SHIPPED HERE: the fullscreen-triangle VERTEX STAGE. It is not a toy -- it is the exact
stage that ships TODAY, hand-written TWICE in nx_game_page_emit:
GLSL VSH : void main(){vec2 v=vec2((gl_VertexID<<1)&2,gl_VertexID&2);gl_Position=vec4(v*2.-1.,0.,1.);}
WGSL vs : @vertex fn vs(@builtin(vertex_index) vi:u32)->@builtin(position) vec4f{...}
Those two hand copies are the duplication this rung deletes: below, ONE NishiLang source
(shsrc_fullscreen_tri) emits both.
WHY THIS STAGE PROVES THE THESIS. The two dialects are not spelling variants of each other:
* GLSL ASSIGNS gl_Position; WGSL RETURNS @builtin(position). Different STRUCTURE.
* GLSL gl_VertexID is i32; WGSL vertex_index is u32 and must be converted before i32 maths.
* WGSL requires a u32 shift amount (1u); GLSL takes a plain int.
* WGSL requires 0.0, never 0. ; GLSL accepts either.
Every one of those is dialect knowledge the BACKEND owns. A translator would have to rediscover
them from GLSL text; a backend simply knows them, once.
COVERED SUBSET (rung 1) -- anything outside REFUSES BY NAME via sir_refuse and returns -1.
A NAMED REFUSAL IS A CONTRACT; A SILENT MISTRANSLATION IN A SHADER BACKEND IS THE WORST
AVAILABLE FAILURE: it compiles, it links, it runs, and it draws the wrong picture forever.
decls : uniform (scalar + array); attribute and varying are GLSL-covered and, since S1
(2026-09-04), WGSL-REFUSED BY NAME (K_ATTRIB anywhere, K_VARY in a fragment stage) until
the entry-parameter derivation that WGSL needs for them lands; a texture-typed uniform
refuses in WGSL too -- it was being emitted INSIDE struct U
S3 (2026-09-04): a TEXTURE is its own kind (K_TEXTURE / sir_texture) in BOTH backends: GLSL
`uniform highp usampler3D`, WGSL a @group/@binding var OUTSIDE struct U with its binding
DERIVED from declaration order; only texture_3d<u32> is covered, other texture types refuse
S4 (2026-09-04): the FRAGMENT entry signature is DERIVED from the declared parameters (no
longer a literal): a sir_param_position parameter is `@builtin(position) name:vec4f` in WGSL and
gl_FragCoord in GLSL; a position READ with no such parameter, and any entry parameter a backend
cannot bind (plain fragment params, any vertex/compute param), refuse by name
stmts : var, assign, return, if/else, discard
dependencies 11 imports · 1 importers
diagram shows first 10 each side; +1 more imports, +0 more importers in the complete lists below.
imports: nx_syscalls.nxnx_shader_ir.nxnx_cast_shader_lbs_candidate_t181.nxnx_world_shader_src.nxnx_types.nxnx_lex_kinds.nxnx_ir.nxnx_tokenizer.nxnx_parse.nxnx_opt.nxnx_import.nx
imported by: nx_cast_lbs_gate_t181.nx
structs
| none |
consts
| 78 | const STAGE_PLAIN: i64 = 0 |
| 79 | const STAGE_VERTEX: i64 = 1 |
| 80 | const STAGE_FRAGMENT: i64 = 2 |
| 82 | const STAGE_COMPUTE: i64 = 3 |
| 87 | const WG_WORKGROUP: i64 = 64 |
| 91 | const WG_TRACE_CAP: i64 = SIR_MAXNODE |
| 95 | const WG_EMIT_CAP: i64 = SIR_MAXNODE * 16 |
| 97 | const WG_C_BANG: i64 = 33 |
| 99 | const WG_NUMBUF: i64 = 32 |
| 107 | const WG_MSGBUF: i64 = 128 |
| 114 | const WG_BIND_GROUP: i64 = 0 |
| 119 | const WG_BIND_UNIFORM: i64 = 0 |
| 120 | const WG_BIND_TEX_FIRST: i64 = WG_BIND_UNIFORM + 1 |
| 264 | const WG_F32ARR_LANES: i64 = 4 |
| 1998 | const WG_UNIFORM_STRIDE_MULTIPLE: i64 = 16 |
| 2132 | const WG_MODE_0644: i64 = 420 |
| 2785 | const SHL_EXPAND_CAP: i64 = 4194304 |
| 2786 | const SHL_LEX_CAP: i64 = 262144 |
functions
| 118 | func wg_group(m: *i64) -> i64 { return WG_BIND_GROUP + m[M_BINDGROUP] } |
| 123 | func gl_ty(t: i64) -> *u8 |
| 142 | func wg_ty(t: i64) -> *u8 |
| 165 | func gl_tyname(m: *i64, t: i64) -> *u8 |
| 170 | func wg_tyname(m: *i64, t: i64) -> *u8 |
| 179 | func wg_is_texty(t: i64) -> i64 |
| 192 | func wg_name_is(m: *i64, id: i64, name: *u8) -> i64 |
| 196 | func wg_fn_param(m: *i64, fn: i64, name: *u8) -> i64 |
| 206 | func wg_fn_position_param(m: *i64, fn: i64) -> i64 |
| 216 | func wg_chain_local(m: *i64, head: i64, name: *u8) -> i64 |
| 231 | func wg_decl_named(m: *i64, kind: i64, name: *u8) -> i64 |
| 241 | func wg_resolves_to_uniform(m: *i64, name: *u8) -> i64 |
| 251 | func wg_resolves_to_varying(m: *i64, name: *u8) -> i64 |
| 265 | func wg_f32arr_vec4n(n: i64) -> i64 { return (n + WG_F32ARR_LANES - 1) / WG_F32ARR_LANES } |
| 267 | func wg_f32arr_len(m: *i64, name: *u8) -> i64 |
| 277 | func wg_decl_kind_first(m: *i64, kind: i64) -> i64 |
| 286 | func wg_decl_kind_count(m: *i64, kind: i64) -> i64 |
| 297 | func wg_fragout(m: *i64) -> i64 { return wg_decl_kind_first(m, K_FRAGOUT) } |
| 302 | func wg_chain_returns_value(m: *i64, head: i64) -> i64 |
| 319 | func wg_chain_assigns(m: *i64, head: i64, name: *u8) -> i64 |
| 337 | func wg_chain_last_is_return(m: *i64, head: i64) -> i64 |
| 347 | func wg_tex_binding(m: *i64, tex: i64) -> i64 |
| 358 | func wg_storage_at(m: *i64, binding: i64) -> i64 |
| 368 | func gl_expr(m: *i64, id: i64, out: *u8, pos: i64, cap: i64, trace: *i64, tcap: i64, tn: *i64) -> i64 |
| 503 | func gl_stmts(m: *i64, head: i64, out: *u8, pos: i64, cap: i64, trace: *i64, tcap: i64, tn: *i64) -> i64 |
| 580 | func glsl_emit_module(m: *i64, stage: i64, out: *u8, cap: i64, trace: *i64, tcap: i64, tn: *i64) -> i64 |
| 770 | func wg_fn_is_plain(m: *i64, f: i64, stage: i64) -> i64 |
| 778 | func wg_rev(out: *u8, a: i64, b: i64) -> i64 |
| 797 | func wg_splat_callee(n: *u8) -> i64 |
| 806 | func wg_vec_arg_ty(m: *i64, id: i64) -> i64 |
| 818 | func wg_expr(m: *i64, id: i64, out: *u8, pos: i64, cap: i64, trace: *i64, tcap: i64, tn: *i64) -> i64 |
| 1032 | func wg_is_position(m: *i64, id: i64) -> i64 |
| 1040 | func wg_stmts(m: *i64, head: i64, out: *u8, pos: i64, cap: i64, trace: *i64, tcap: i64, tn: *i64) -> i64 |
| 1145 | func wgsl_compute_stage(m: *i64, f: i64, out: *u8, pos: i64, cap: i64) -> i64 |
| 1156 | func wgsl_emit_module(m: *i64, stage: i64, out: *u8, cap: i64, trace: *i64, tcap: i64, tn: *i64) -> i64 |
| 1536 | func shsrc_fullscreen_tri(m: *i64) -> i64 |
| 1566 | func shsrc_depth_min(m: *i64) -> i64 |
| 1578 | func wg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 1580 | func wg_streq(a: *u8, b: *u8) -> i64 |
| 1589 | func wg_compute_demo() -> i64 |
| 1641 | func wg_probe(m: *i64, stage: i64, label: *u8, dialect_wgsl: i64, trace: *i64, tn: *i64) -> i64 |
| 1660 | func wg_trace_eq(a: *i64, an: i64, b: *i64, bn: i64) -> i64 |
| 1670 | func shsrc_frag_const(m: *i64) -> i64 |
| 1688 | func shsrc_fullscreen_tri_scaled(m: *i64) -> i64 |
| 1705 | func shsrc_fullscreen_tri_shadowlocal(m: *i64) -> i64 |
| 1723 | func shsrc_plain_shadowparam(m: *i64) -> i64 |
| 1739 | func shsrc_private_demo(m: *i64) -> i64 |
| 1756 | func shsrc_tex2d_sample(m: *i64) -> i64 |
| 1764 | func shsrc_tex_plain(m: *i64) -> i64 |
| 1784 | func shsrc_frag_pos(m: *i64) -> i64 |
| 1800 | func shsrc_frag_pos_undeclared(m: *i64) -> i64 |
| 1815 | func shsrc_frag_plainparam(m: *i64) -> i64 |
| 1833 | func shsrc_frag_discard(m: *i64) -> i64 |
| 1843 | func shsrc_frag_noout(m: *i64) -> i64 |
| 1857 | func shsrc_frag_loc2(m: *i64) -> i64 |
| 1871 | func shsrc_vert_fragout(m: *i64) -> i64 |
| 1878 | func shsrc_frag_twoout(m: *i64) -> i64 |
| 1885 | func shsrc_frag_const_body(m: *i64) -> i64 |
| 1901 | func shsrc_texsample(m: *i64) -> i64 |
| 1912 | func shsrc_select_let(m: *i64) -> i64 |
| 1927 | func shsrc_for_until(m: *i64) -> i64 |
| 1943 | func shsrc_struct(m: *i64) -> i64 |
| 1966 | func shsrc_struct_ret(m: *i64) -> i64 |
| 1999 | func wg_round_up(al: i64, n: i64) -> i64 { return ((n + al - 1) / al) * al } |
| 2000 | func wg_align_of(t: i64) -> i64 |
| 2012 | func wg_size_of(t: i64) -> i64 |
| 2029 | func wg_uniform_layout(m: *i64, out: *u8, pos: i64, cap: i64) -> i64 { return wg_uniform_layout_k(m, out, pos, cap, "struct_u_size=" as *u8) } |
| 2030 | func wg_uniform_layout_k(m: *i64, out: *u8, pos: i64, cap: i64, key: *u8) -> i64 |
| 2083 | func shsrc_world_uniforms(m: *i64) -> i64 |
| 2095 | func shsrc_neg_uninit(m: *i64) -> i64 |
| 2106 | func wg_world_demo() -> i64 |
| 2134 | func wg_glsl_to_path(m: *i64, stage: i64, outp: *u8, label: *u8) -> i64 |
| 2152 | func wg_cast_demo(outp: *u8, outf: *u8) -> i64 |
| 2223 | func wg_layout_demo() -> i64 |
| 2292 | func gl_call_name(name: *u8) -> *u8 |
| 2303 | func wg_decls_demo() -> i64 |
| 2791 | func shl_ty(t: *Type) -> i64 |
| 2801 | func shl_op(op: i64) -> *u8 |
| 2824 | func shl_val(m2: *i64, f: *Function, vid: i64, nb: *u8) -> i64 |
| 2850 | func shl_blk(m2: *i64, f: *Function, fn2: i64, bb: *BasicBlock, nb: *u8, msg: *u8, seen: *i64) -> i64 |
| 2927 | func shl_bid(f: *Function, id: i64) -> *BasicBlock |
| 2940 | func shl_reaches(f: *Function, from: i64, to: i64, mark: *i64, wl: *i64) -> i64 |
| 2970 | func shl_reaches_avoid(f: *Function, from: i64, to: i64, avoid: i64, mark: *i64, wl: *i64) -> i64 |
| 2999 | func shl_dominates(f: *Function, b: i64, p: i64, mark: *i64, wl: *i64) -> i64 |
| 3014 | func shl_is_header(f: *Function, bb: *BasicBlock, mark: *i64, wl: *i64) -> i64 |
| 3043 | func shl_region(m2: *i64, f: *Function, fn2: i64, eid: i64, stop: i64, nb: *u8, msg: *u8, seen: *i64, mark: *i64, wl: *i64, depth: i64) -> i64 |
| 3160 | func shl_lower(m2: *i64, f: *Function, fname: *u8) -> i64 |
| 3226 | func wg_lbs_source_main(argc: i64, argv: *i64) -> i64 |