code wiki / (root) / nx_shader_ir.nx

nx_shader_ir.nx

buildroot/runtime/nx_shader_ir.nx

36219 B608 linesdepth 2pulls 2 transitivereach 180 importersview sourcekind librarytopic shader
docsdependenciesstructsconstsfunctions

about

nx_shader_ir.nx -- THE SHADER IR: ONE source of truth, N dialect backends. WHY THIS EXISTS (measured 2026-08-23). The estate's shaders are hand-written GLSL string literals inside nx_game_page_emit. Drawing characters on the WebGPU tier therefore demanded a SECOND HAND COPY in WGSL -- ~600 lines (dual-quaternion skinning off a joint texture, instance uniform arrays, the voxel occlusion march, the procedural anatomy/eye/hair/skin paint) of the most actively-edited shader in the estate: three separate feature edits landed in it on the day this was written. Two artifacts that must agree, kept in agreement by discipline, is the exact shape the banked law forbids. This module is the construction that makes disagreement IMPOSSIBLE: neither dialect is authored, both are EMITTED from this representation. HOUSE SHAPE. This mirrors the NishiLang compiler itself -- lex_source -> parse_module -> opt_run -> {nx_compile_x86, nx_compile_wat}: one front-end representation, many backends. nx_glsl.nx and nx_wgsl.nx are backends over this IR, not transpilers bolted to a call site. THE SOURCE OF TRUTH IS NISHILANG (operator, 2026-08-23: "we dont want python or glsl or javascript or all that it should be nishi lang and nishi ecosystem from the first byte up each rung gaining all these capabilities"). GLSL IS A TARGET, NOT AN INPUT. This is NOT a GLSL->WGSL transpiler: translating would enshrine GLSL as the canonical language and make a foreign dialect the artifact we maintain. A shader is authored ONCE in NishiLang; GLSL and WGSL are both OUTPUTS, exactly as x86_64 and WAT are outputs of the same NishiLang front-end. The ~600 lines of GLSL in MVS/MFS are therefore a MIGRATION TARGET, not the source: each rung expresses more of them in NishiLang and PROVES the emitted GLSL equivalent to the hand-written GLSL that ships today. LADDER (each rung widens the covered subset; rung 1 is what this lane ships): rung 1 the fullscreen-triangle vertex stage -- authored in NishiLang, emitting BOTH the GLSL VSH and the WGSL vs that are hand-written and SHIPPING today, proven against them. rung 2 lower the real NishiLang AST (nx_tokenizer/nx_parse) into this IR, so a shader is an ordinary NishiLang function rather than builder calls -- the full 'target, not translator' shape, sharing the front-end with nx_compile_x86 and the WAT lane. rung 3 widen the subset to the MFS paint set; rung 4 the MVS skinning set; then the character pass becomes a compile target and the WebGPU abstention flips from owed to shipped. THE SOURCE OF TRUTH IS NISHILANG (operator, 2026-08-23: "we dont want python or glsl or javascript or all that it should be nishi lang and nishi ecosystem from the first byte up each rung gaining all these capabilities"). GLSL IS A TARGET, NOT AN INPUT. This is NOT a GLSL->WGSL transpiler: translating would enshrine GLSL as the canonical language and make a foreign dialect the artifact we maintain. A shader is authored ONCE in NishiLang; GLSL and WGSL are both OUTPUTS, exactly as x86_64 and WAT are outputs of the same NishiLang front-end. The ~600 lines of GLSL in MVS/MFS are therefore a MIGRATION TARGET, not the source: each rung expresses more of them in

dependencies 1 imports · 35 importers

nx_syscalls.nx nx_shader_ir.nx nx_cast_projection_capture_t235.nx nx_cast_projection_gate_t234.nx nx_shader_arg_canonical_gate_t210. nx_tex_sample_mip_alpha_candidate_ nx_tex_sample_mip_candidate_t218.n nx_wgsl.nx nx_wgsl_authored_t55.nx nx_wgsl_before_front_t217.nx nx_wgsl_canonical_skin_t140.nx nx_wgsl_cast_control_t181.nx

diagram shows first 10 each side; +0 more imports, +25 more importers in the complete lists below.

imports: nx_syscalls.nx

imported by: nx_cast_projection_capture_t235.nxnx_cast_projection_gate_t234.nxnx_shader_arg_canonical_gate_t210.nxnx_tex_sample_mip_alpha_candidate_t241.nxnx_tex_sample_mip_candidate_t218.nxnx_wgsl.nxnx_wgsl_authored_t55.nxnx_wgsl_before_front_t217.nxnx_wgsl_canonical_skin_t140.nxnx_wgsl_cast_control_t181.nxnx_wgsl_cast_lbs_t181.nxnx_wgsl_cast_material_t181.nxnx_wgsl_cloud_transport_t155.nxnx_wgsl_cumulus_release_t161.nxnx_wgsl_cumulus_t156.nxnx_wgsl_depth_candidate_t192.nxnx_wgsl_eye_t138.nxnx_wgsl_face_mask_t163.nxnx_wgsl_front_candidate_t217.nxnx_wgsl_inspection_t165.nxnx_wgsl_sand_baseline_t137.nxnx_wgsl_sand_private_t137.nxnx_wgsl_scene_light_candidate_t364.nxnx_wgsl_skin_t138.nxnx_wgsl_sky_light_t154.nxnx_wgsl_sky_private_20260910.nxnx_wgsl_sky_review_t154.nxnx_wgsl_static_t335.nxnx_wgsl_world_depth_t195.nxnx_world_shader_cumulus_canonical_t156.nxnx_world_shader_depth_t194.nxnx_world_shader_sand_private_t137.nxnx_world_shader_sky_light_t154.nxnx_world_shader_sky_private_20260910.nxnx_world_shader_src.nx

structs

none

consts

66const SIR_SLOTS: i64 = 8
71const SIR_MAXNODE: i64 = 16384
72const SIR_POOLCAP: i64 = 65536
74const SIR_KIND: i64 = 0
75const SIR_TY: i64 = 1
76const SIR_A: i64 = 2
77const SIR_B: i64 = 3
78const SIR_C: i64 = 4
79const SIR_NAME: i64 = 5
80const SIR_D: i64 = 6
81const SIR_NEXT: i64 = 7
84const M_NODES: i64 = 0
85const M_NCOUNT: i64 = 1
86const M_POOL: i64 = 2
87const M_POOLUSED: i64 = 3
88const M_DECLH: i64 = 4
89const M_DECLT: i64 = 5
90const M_FUNCH: i64 = 6
91const M_FUNCT: i64 = 7
92const M_REFUSE: i64 = 8
93const M_OVER: i64 = 9
98const M_CURFN: i64 = 10
105const M_FRAGOUT: i64 = 11
110const M_VIOMODE: i64 = 12
115const M_USESII: i64 = 13
122const M_WGFRAGOUT: i64 = 14
128const M_BINDGROUP: i64 = 15
131const M_CLIP_DEPTH: i64 = 16
132const SIR_MODULE_WORDS: i64 = 17
133const SIR_CLIP_NATIVE: i64 = 0
134const SIR_CLIP_NEGATIVE_ONE_TO_ONE: i64 = 1
136const SIR_LIT_USUFFIX: i64 = 1
139const K_UNIFORM: i64 = 1
140const K_ATTRIB: i64 = 2
141const K_VARY: i64 = 3
142const K_FUNC: i64 = 4
143const K_PARAM: i64 = 5
151const K_STORAGE: i64 = 6
158const K_TEXTURE: i64 = 7
169const K_FRAGOUT: i64 = 8
177const K_STRUCT: i64 = 9
178const S_RETURN: i64 = 10
179const S_ASSIGN: i64 = 11
180const S_VAR: i64 = 12
181const S_IF: i64 = 13
182const S_DISCARD: i64 = 14
190const S_LOOP: i64 = 15
191const S_BREAK: i64 = 16
195const S_EXPR: i64 = 17
196const E_LIT: i64 = 20
197const E_IDENT: i64 = 21
198const E_BIN: i64 = 22
199const E_CALL: i64 = 23
200const E_SWZ: i64 = 24
201const E_INDEX: i64 = 25
202const E_TEXLOAD: i64 = 26
203const E_TEXSAMPLE: i64 = 27
204const E_CTOR: i64 = 28
208const E_CAST: i64 = 29
209const E_BUILTIN: i64 = 30
214const E_ATOMIC: i64 = 31
220const E_SELECT: i64 = 32
224const E_NEG: i64 = 33
230const K_PRIVATE: i64 = 34
236const E_NOT: i64 = 35
239const T_VOID: i64 = 0
240const T_F32: i64 = 1
241const T_I32: i64 = 2
242const T_U32: i64 = 3
243const T_BOOL: i64 = 4
244const T_V2F: i64 = 5
245const T_V3F: i64 = 6
246const T_V4F: i64 = 7
247const T_V3I: i64 = 8
248const T_TEX3U: i64 = 9
249const T_TEX2F: i64 = 10
251const T_V3U: i64 = 11
254const T_V2I: i64 = 12
258const T_M3F: i64 = 13
260const T_TEX2AF: i64 = 14
261const T_MAX: i64 = 14
262const E_TEXSAMPLE_ARRAY: i64 = 36
413const P_PLAIN: i64 = 0
414const P_BUILTIN_POSITION: i64 = 1
415const P_BUILTIN_FRONT_FACING: i64 = 2
504const SIR_VAR_CONST: i64 = 2
549const SIR_VAR_LET: i64 = 1

functions

264func sir_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
called by 2: sir_streb_put
266func sir_new() -> *i64
283func sir_get(m: *i64, id: i64, k: i64) -> i64
288func sir_set(m: *i64, id: i64, k: i64, v: i64) -> i64
296func sir_str(m: *i64, s: *u8) -> i64
310func sir_cstr(m: *i64, off: i64) -> *u8
314func sir_node(m: *i64, kind: i64, ty: i64, a: i64, b: i64, c: i64, nameoff: i64) -> i64
330func sir_chain(m: *i64, hw: i64, tw: i64, id: i64) -> i64
340func sir_uniform(m: *i64, name: *u8, ty: i64, arraylen: i64) -> i64
346func sir_private(m: *i64, name: *u8, ty: i64, arraylen: i64) -> i64
351func sir_attrib(m: *i64, name: *u8, ty: i64, location: i64) -> i64
356func sir_vary(m: *i64, name: *u8, ty: i64, location: i64, flat: i64) -> i64
363func sir_storage(m: *i64, name: *u8, elemty: i64, binding: i64, readwrite: i64, atomic: i64) -> i64
369func sir_texture(m: *i64, name: *u8, ty: i64) -> i64
376func sir_fragout(m: *i64, name: *u8, ty: i64, location: i64) -> i64
386func sir_struct(m: *i64, name: *u8) -> i64
390func sir_member(m: *i64, st: i64, name: *u8, ty: i64) -> i64 { return sir_param(m, st, name, ty) }
calls 1: sir_param
391func sir_struct_ty(st: i64) -> i64 { return SIR_MAXNODE + st }
393func sir_struct_of(m: *i64, ty: i64) -> i64
calls 1: sir_get
400func sir_member_of(m: *i64, base: i64, name: *u8, ty: i64) -> i64 { return sir_swz(m, base, name, ty) }
calls 1: sir_swz
403func sir_func(m: *i64, name: *u8, rettype: i64) -> i64
418func sir_param_front_facing(m:*i64,fn:i64,name:*u8)->i64
424func sir_param(m: *i64, fn: i64, name: *u8, ty: i64) -> i64
433func sir_param_position(m: *i64, fn: i64, name: *u8) -> i64
440func sir_stmt(m: *i64, fn: i64, st: i64) -> i64
449func sir_return(m: *i64, e: i64) -> i64 { return sir_node(m, S_RETURN, T_VOID, e, 0, 0, 0) }
calls 1: sir_node
452func sir_return_depth(m: *i64, color: i64, depth: i64) -> i64
calls 1: sir_node
456func sir_assign(m: *i64, lhs: i64, rhs: i64) -> i64 { return sir_node(m, S_ASSIGN, T_VOID, lhs, rhs, 0, 0) }
457func sir_var(m: *i64, name: *u8, ty: i64, init: i64) -> i64 { return sir_node(m, S_VAR, ty, init, 0, 0, sir_str(m, name)) }
458func sir_if(m: *i64, cond: i64, thenh: i64, elseh: i64) -> i64 { return sir_node(m, S_IF, T_VOID, cond, thenh, elseh, 0) }
459func sir_discard(m: *i64) -> i64 { return sir_node(m, S_DISCARD, T_VOID, 0, 0, 0, 0) }
calls 1: sir_node
463func sir_loop(m: *i64, body: i64) -> i64 { return sir_node(m, S_LOOP, T_VOID, body, 0, 0, 0) }
464func sir_break(m: *i64) -> i64 { return sir_node(m, S_BREAK, T_VOID, 0, 0, 0, 0) }
466func sir_expr(m: *i64, e: i64) -> i64 { return sir_node(m, S_EXPR, T_VOID, e, 0, 0, 0) }
calls 1: sir_node
475func sir_for_until(m: *i64, fn: i64, init: i64, until: i64, step: i64, body: i64) -> i64
484func sir_seq(m: *i64, a: i64, b: i64) -> i64
493func sir_lit(m: *i64, text: *u8, ty: i64) -> i64 { return sir_node(m, E_LIT, ty, 0, 0, 0, sir_str(m, text)) }
497func sir_lit_u(m: *i64, text: *u8) -> i64
called by 1: main calls 2: sir_litsir_set
505func sir_const(m: *i64, name: *u8, ty: i64, init: i64) -> i64
calls 2: sir_varsir_set
510func sir_ident(m: *i64, name: *u8, ty: i64) -> i64 { return sir_node(m, E_IDENT, ty, 0, 0, 0, sir_str(m, name)) }
511func sir_bin(m: *i64, op: *u8, l: i64, r: i64, ty: i64) -> i64 { return sir_node(m, E_BIN, ty, l, r, 0, sir_str(m, op)) }
512func sir_swz(m: *i64, base: i64, sel: *u8, ty: i64) -> i64 { return sir_node(m, E_SWZ, ty, base, 0, 0, sir_str(m, sel)) }
513func sir_index(m: *i64, base: i64, idx: i64, ty: i64) -> i64 { return sir_node(m, E_INDEX, ty, base, idx, 0, 0) }
calls 1: sir_node
517func sir_texload(m: *i64, tex: i64, coord: i64, lod: i64) -> i64
522func sir_texsample(m: *i64, tex: i64, coord: i64) -> i64 { return sir_node(m, E_TEXSAMPLE, T_V4F, tex, coord, 0, 0) }
calls 1: sir_node
524func sir_texsample_array(m:*i64,tex:i64,coord:i64,layer:i64)->i64
531func sir_call(m: *i64, name: *u8, ty: i64) -> i64 { return sir_node(m, E_CALL, ty, 0, 0, 0, sir_str(m, name)) }
532func sir_ctor(m: *i64, ty: i64) -> i64 { return sir_node(m, E_CTOR, ty, 0, 0, 0, 0) }
533func sir_cast(m: *i64, e: i64, ty: i64) -> i64 { return sir_node(m, E_CAST, ty, e, 0, 0, 0) }
534func sir_builtin(m: *i64, which: *u8, ty: i64) -> i64
calls 2: sir_nodesir_str
540func sir_atomic(m: *i64, op: *u8, target: i64, val: i64, ty: i64) -> i64 { return sir_node(m, E_ATOMIC, ty, target, val, 0, sir_str(m, op)) }
calls 2: sir_nodesir_str
542func sir_select(m: *i64, cond: i64, tval: i64, fval: i64, ty: i64) -> i64 { return sir_node(m, E_SELECT, ty, cond, tval, fval, 0) }
calls 1: sir_node
544func sir_neg(m: *i64, e: i64, ty: i64) -> i64 { return sir_node(m, E_NEG, ty, e, 0, 0, 0) }
calls 1: sir_node
546func sir_not(m: *i64, e: i64) -> i64 { return sir_node(m, E_NOT, T_BOOL, e, 0, 0, 0) }
calls 1: sir_node
550func sir_let(m: *i64, name: *u8, ty: i64, init: i64) -> i64
556func sir_arg(m: *i64, callid: i64, e: i64) -> i64
573func sir_refuse(m: *i64, what: *u8) -> i64
called by 1: sir_texsample_array calls 1: sir_str
577func sir_refused(m: *i64) -> i64 { return m[M_REFUSE] }
580func eb_put(out: *u8, pos: i64, cap: i64, s: *u8) -> i64
called by 1: eb_num calls 1: sir_slen
588func eb_num(out: *u8, pos: i64, cap: i64, v: i64) -> i64
calls 2: eb_putsys_mmap
605func tr_add(trace: *i64, tcap: i64, tn: *i64, id: i64) -> i64