nx_pe_dll_d3d11shade.nx source
↩ module page · 238 lines · 12124 B
1// nx_pe_dll_d3d11shade.nx -- PROGRAMMABLE SHADER Draw: a real fxc-compiled DXBC pixel shader, created via the real D3D11
2// API and EXECUTED per-draw by our register machine (sh_execute_scratch, DLL-safe), produces WARP-matching pixels.
3// Superset of d3d11draw: 14 methods incl. CreatePixelShader [dev slot 15] + PSSetShader [ctx slot 9]. CreatePixelShader
4// has 5 args (ppShader on the stack) -> a 5-arg MS-x64->SysV thunk (rbp frame reads [rbp+0x30]). Draw: if a PS is bound,
5// executes its DXBC (sh_execute_scratch over caller-scratch in the object mem) -> o0 color -> UNORM8 -> fills the triangle.
6// Graded vs WARP's shaded triangle (knowledge/warp_shaded.ppm). Method bodies = sovereign nx_cc NishiLang (incl. the fxc-
7// validated DXBC executor); vtables+thunks = sovereign emitter. Input /tmp/nishi_export_lib.s Output knowledge/nishi_d3d11shade.dll
8// license_tier: ORIGINAL expect_exit: 0
9import "nx_syscalls.nx"
10import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
11import "nxasm_x86.nx"
12import "nx_pe_writer.nx"
13
14const N_DEV: i64 = 43
15const N_CTX: i64 = 108
16const N_METH: i64 = 14
17
18func d11_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
19// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
20// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
21// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
22// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
23func d11_putn(v: i64) -> i64 { nxi_out(v); return 0 }
24func d11_wstr(buf: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ buf[off+i]=s[i]; i=i+1 } buf[off+i]=0 as u8; return i+1 }
25
26func d11_assemble(src: *u8, n: i64, out: *u8, out_cap: i64, names: *i64, offs: *i64, cnt: i64) -> i64 {
27 let lab_off: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64
28 let lab_len: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64
29 let lab_addr: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64
30 let lab_sec: *i64 = sys_mmap(ASM_MAX_LABELS * 8) as *i64
31 let op0: *i64 = sys_mmap(72) as *i64 // 9 slots for SIB (matches nxasm_x86)
32 let op1: *i64 = sys_mmap(72) as *i64
33 let op2: *i64 = sys_mmap(72) as *i64 // API DRIFT FIX: axc_pass gained op2
34 let scratch: *u8 = sys_mmap(64)
35 let posbox: *i64 = sys_mmap(16) as *i64
36 let n_lab_box: *i64 = sys_mmap(16) as *i64
37 n_lab_box[0] = 0
38 let lh: *i64 = sys_mmap(ASM_LH_SIZE * 8) as *i64
39 let text_size: i64 = axc_pass(src, n, out, 0, 0, lab_off, lab_len, lab_addr, lab_sec, n_lab_box, lh, op0, op1, op2, scratch, posbox)
40 if text_size < 0 { return text_size }
41 let n_lab: i64 = n_lab_box[0]
42 var k: i64 = 0
43 while k < n_lab {
44 if lab_sec[k] == 1 { lab_addr[k] = lab_addr[k] + text_size }
45 var m: i64 = 0
46 while m < cnt { if axc_tok_is(src, lab_off[k], lab_len[k], names[m] as *u8) == 1 { offs[m] = lab_addr[k] } m = m + 1 }
47 k = k + 1
48 }
49 axc_lh_build(src, lab_off, lab_len, n_lab, lh)
50 let total: i64 = axc_pass(src, n, out, text_size, 1, lab_off, lab_len, lab_addr, lab_sec, n_lab_box, lh, op0, op1, op2, scratch, posbox)
51 if total < 0 { return total }
52 if total > out_cap { return 0 - 200 }
53 return total
54}
55
56func d11_thunk4(buf: *u8, tco: i64, moff: i64) -> i64 {
57 let t: i64 = 0x200 + tco
58 _w8(buf,t+0,0x57); _w8(buf,t+1,0x56)
59 _w8(buf,t+2,0x48); _w8(buf,t+3,0x89); _w8(buf,t+4,0xCF)
60 _w8(buf,t+5,0x48); _w8(buf,t+6,0x89); _w8(buf,t+7,0xD6)
61 _w8(buf,t+8,0x4C); _w8(buf,t+9,0x89); _w8(buf,t+10,0xC2)
62 _w8(buf,t+11,0x4C); _w8(buf,t+12,0x89); _w8(buf,t+13,0xC9)
63 _w8(buf,t+14,0x48); _w8(buf,t+15,0x83); _w8(buf,t+16,0xEC); _w8(buf,t+17,0x08)
64 _w8(buf,t+18,0xE8); _w32(buf, t+19, moff - (tco + 23))
65 _w8(buf,t+23,0x48); _w8(buf,t+24,0x83); _w8(buf,t+25,0xC4); _w8(buf,t+26,0x08)
66 _w8(buf,t+27,0x5E); _w8(buf,t+28,0x5F); _w8(buf,t+29,0xC3)
67 return 0
68}
69// 5-arg thunk (31B): forwards MS arg4 [rbp+0x30] -> SysV R8; rbp frame; saves rdi/rsi.
70func d11_thunk5(buf: *u8, tco: i64, moff: i64) -> i64 {
71 let t: i64 = 0x200 + tco
72 _w8(buf,t+0,0x55)
73 _w8(buf,t+1,0x48); _w8(buf,t+2,0x89); _w8(buf,t+3,0xE5)
74 _w8(buf,t+4,0x57); _w8(buf,t+5,0x56)
75 _w8(buf,t+6,0x48); _w8(buf,t+7,0x89); _w8(buf,t+8,0xCF)
76 _w8(buf,t+9,0x48); _w8(buf,t+10,0x89); _w8(buf,t+11,0xD6)
77 _w8(buf,t+12,0x4C); _w8(buf,t+13,0x89); _w8(buf,t+14,0xC2)
78 _w8(buf,t+15,0x4C); _w8(buf,t+16,0x89); _w8(buf,t+17,0xC9)
79 _w8(buf,t+18,0x4C); _w8(buf,t+19,0x8B); _w8(buf,t+20,0x45); _w8(buf,t+21,0x30)
80 _w8(buf,t+22,0xE8); _w32(buf, t+23, moff - (tco + 27))
81 _w8(buf,t+27,0x5E); _w8(buf,t+28,0x5F); _w8(buf,t+29,0x5D); _w8(buf,t+30,0xC3)
82 return 0
83}
84
85func d11_dev_slot(s: i64) -> i64 {
86 if s == 0 { return 0 }
87 if s == 1 { return 1 }
88 if s == 2 { return 2 }
89 if s == 3 { return 8 } // CreateBuffer
90 if s == 9 { return 6 } // CreateRenderTargetView
91 if s == 15 { return 12 } // CreatePixelShader (5-arg)
92 if s == 37 { return 3 } // GetFeatureLevel
93 if s == 40 { return 5 } // GetImmediateContext
94 return 4
95}
96func d11_ctx_slot(s: i64) -> i64 {
97 if s == 0 { return 0 }
98 if s == 1 { return 1 }
99 if s == 2 { return 2 }
100 if s == 9 { return 13 } // PSSetShader
101 if s == 13 { return 11 } // Draw
102 if s == 18 { return 10 } // IASetVertexBuffers
103 if s == 33 { return 9 } // OMSetRenderTargets
104 if s == 50 { return 7 } // ClearRenderTargetView
105 return 4
106}
107
108func d11_emit(buf: *u8, code: *u8, code_len: i64, offs: *i64) -> i64 {
109 if (buf as i64) == 0 { return 0 - NX_PE_BAD_INPUT }
110 // per-method thunk offsets (create_shader=method 12 uses the 31-byte 5-arg thunk; rest 30-byte 4-arg)
111 let toff: *i64 = sys_mmap(8*N_METH) as *i64
112 var off: i64 = code_len
113 var mi: i64 = 0
114 while mi < N_METH {
115 toff[mi] = off
116 if mi == 12 { off = off + 31 } else { off = off + 30 }
117 mi = mi + 1
118 }
119 let FF: i64 = off
120 let DV: i64 = ((FF + 41 + 7) / 8) * 8
121 let CV: i64 = DV + N_DEV * 8
122 let text_used: i64 = CV + N_CTX * 8
123 let text_pages: i64 = (text_used + 4095) / 4096
124 let text_raw: i64 = text_pages * 4096
125 let edata_rva: i64 = 0x1000 + text_raw
126 let edata_file: i64 = 0x200 + text_raw
127 let size_of_image: i64 = edata_rva + 0x1000
128 let file_size: i64 = edata_file + 0x200
129
130 _w16(buf, 0, 0x5A4D); _w32(buf, 0x3C, 0x80); _w32(buf, 0x80, 0x00004550)
131 _w16(buf, 0x84 + 0, PE_MACHINE_AMD64); _w16(buf, 0x84 + 2, 2); _w16(buf, 0x84 + 16, 0xF0); _w16(buf, 0x84 + 18, 0x2022)
132 let O: i64 = 0x98
133 _w16(buf, O + 0, PE_OH_MAGIC_PEPLUS); _w8(buf, O + 2, 1)
134 _w32(buf, O + 4, text_raw); _w32(buf, O + 8, 0x200)
135 _w32(buf, O + 16, 0); _w32(buf, O + 20, 0x1000)
136 _w64(buf, O + 24, 0x80000000, 0x1)
137 _w32(buf, O + 32, 0x1000); _w32(buf, O + 36, 0x200)
138 _w16(buf, O + 40, 6); _w16(buf, O + 48, 6)
139 _w32(buf, O + 56, size_of_image); _w32(buf, O + 60, 0x200)
140 _w16(buf, O + 68, PE_SUBSYSTEM_CONSOLE)
141 _w64(buf, O + 72, 0x100000, 0); _w64(buf, O + 80, 0x1000, 0); _w64(buf, O + 88, 0x100000, 0); _w64(buf, O + 96, 0x1000, 0)
142 _w32(buf, O + 108, 16)
143 _w32(buf, O + 112 + 0, edata_rva); _w32(buf, O + 112 + 4, 0x56)
144
145 _emit_section_header(buf, FOFF_SECT_TBL, 46, 116, 101, 120, 116, 0, 0, 0, text_used, 0x1000, text_raw, 0x200, PE_SECT_CODE_X_R)
146 _emit_section_header(buf, FOFF_SECT_TBL + 40, 46, 101, 100, 97, 116, 97, 0, 0, 0x56, edata_rva, 0x200, edata_file, PE_SECT_DATA_R)
147
148 var i: i64 = 0
149 while i < code_len { buf[0x200 + i] = code[i]; i = i + 1 }
150
151 var j: i64 = 0
152 while j < N_METH {
153 if j == 12 { d11_thunk5(buf, toff[j], offs[j]) } else { d11_thunk4(buf, toff[j], offs[j]) }
154 j = j + 1
155 }
156
157 let f: i64 = 0x200 + FF
158 _w8(buf,f+0,0x48); _w8(buf,f+1,0x89); _w8(buf,f+2,0xC8)
159 _w8(buf,f+3,0x48); _w8(buf,f+4,0x8D); _w8(buf,f+5,0x15); _w32(buf, f+6, DV - FF - 10)
160 _w8(buf,f+10,0x48); _w8(buf,f+11,0x89); _w8(buf,f+12,0x11)
161 _w8(buf,f+13,0x48); _w8(buf,f+14,0xC7); _w8(buf,f+15,0x41); _w8(buf,f+16,0x08); _w32(buf, f+17, 1)
162 _w8(buf,f+21,0x48); _w8(buf,f+22,0x8D); _w8(buf,f+23,0x15); _w32(buf, f+24, CV - FF - 28)
163 _w8(buf,f+28,0x48); _w8(buf,f+29,0x89); _w8(buf,f+30,0x51); _w8(buf,f+31,0x10)
164 _w8(buf,f+32,0x48); _w8(buf,f+33,0xC7); _w8(buf,f+34,0x41); _w8(buf,f+35,0x18); _w32(buf, f+36, 1)
165 _w8(buf,f+40,0xC3)
166
167 var s: i64 = 0
168 while s < N_DEV { _w64(buf, 0x200 + DV + s*8, 0x80000000 + 0x1000 + toff[d11_dev_slot(s)], 1); s = s + 1 }
169 var c: i64 = 0
170 while c < N_CTX { _w64(buf, 0x200 + CV + c*8, 0x80000000 + 0x1000 + toff[d11_ctx_slot(c)], 1); c = c + 1 }
171
172 let E: i64 = edata_file
173 _w32(buf, E + 12, edata_rva + 0x4A)
174 _w32(buf, E + 16, 1); _w32(buf, E + 20, 1); _w32(buf, E + 24, 1)
175 _w32(buf, E + 28, edata_rva + 0x28); _w32(buf, E + 32, edata_rva + 0x2C); _w32(buf, E + 36, edata_rva + 0x30)
176 _w32(buf, E + 0x28, 0x1000 + FF)
177 _w32(buf, E + 0x2C, edata_rva + 0x32)
178 _w16(buf, E + 0x30, 0)
179 d11_wstr(buf, E + 0x32, "nishi_d3d_create_device\x00" as *u8)
180 d11_wstr(buf, E + 0x4A, "nishicc.dll\x00" as *u8)
181 return file_size
182}
183
184func main() -> i64 {
185 d11_puts("=== nx_pe_dll_d3d11shade -- programmable shader Draw (real fxc DXBC executed through the D3D11 API) ===\n" as *u8)
186 let lenbox: *i64 = sys_mmap(16) as *i64
187 let src: *u8 = sys_read_file("/tmp/nishi_export_lib.s" as *u8, lenbox)
188 if (src as i64) == 0 { d11_puts("FAIL no /tmp/nishi_export_lib.s\n" as *u8); sys_exit(1); return 1 }
189 let n: i64 = lenbox[0]
190 if n <= 0 { d11_puts("FAIL empty .s\n" as *u8); sys_exit(2); return 2 }
191
192 let names: *i64 = sys_mmap(8*N_METH) as *i64
193 names[0] = "nx_dev_qi" as *u8 as i64
194 names[1] = "nx_dev_addref" as *u8 as i64
195 names[2] = "nx_dev_release" as *u8 as i64
196 names[3] = "nx_dev_getfl" as *u8 as i64
197 names[4] = "nx_dev_notimpl" as *u8 as i64
198 names[5] = "nx_dev_getctx" as *u8 as i64
199 names[6] = "nx_dev_create_rtv" as *u8 as i64
200 names[7] = "nx_ctx_clearrtv" as *u8 as i64
201 names[8] = "nx_dev_create_buffer" as *u8 as i64
202 names[9] = "nx_ctx_om_set_rt" as *u8 as i64
203 names[10] = "nx_ctx_ia_set_vb" as *u8 as i64
204 names[11] = "nx_ctx_draw" as *u8 as i64
205 names[12] = "nx_dev_create_shader" as *u8 as i64
206 names[13] = "nx_ctx_pssetshader" as *u8 as i64
207 let offs: *i64 = sys_mmap(8*N_METH) as *i64
208 var z: i64 = 0
209 while z < N_METH { offs[z] = 0 - 1; z = z + 1 }
210
211 let code: *u8 = sys_mmap(4194304)
212 let code_len: i64 = d11_assemble(src, n, code, 4194304, names, offs, N_METH)
213 if code_len < 0 { d11_puts("FAIL assemble rc="); d11_putn(code_len); d11_puts("\n" as *u8); sys_exit(3); return 3 }
214 var miss: i64 = 0
215 var q: i64 = 0
216 while q < N_METH { if offs[q] < 0 { d11_puts(" MISSING method "); d11_putn(q); d11_puts("\n" as *u8); miss = miss + 1 } q = q + 1 }
217 if miss > 0 { d11_puts("FAIL method(s) not found\n" as *u8); sys_exit(4); return 4 }
218 d11_puts(" code_len="); d11_putn(code_len); d11_puts("\n" as *u8)
219
220 let buf: *u8 = sys_mmap(0x80000)
221 let fsz: i64 = d11_emit(buf, code, code_len, offs)
222 if fsz < 0 { d11_puts("FAIL emit rc="); d11_putn(fsz); d11_puts("\n" as *u8); sys_exit(5); return 5 }
223
224 let fd: i64 = sys_openat_wr("knowledge/nishi_d3d11shade.dll\x00" as *u8, 0x1a4)
225 if fd < 0 { d11_puts("FAIL open output\n" as *u8); sys_exit(6); return 6 }
226 let wrote: i64 = sys_write(fd, buf, fsz)
227 sys_close(fd)
228 d11_puts(" wrote "); d11_putn(wrote); d11_puts(" bytes -> knowledge/nishi_d3d11shade.dll (14 methods, shader Draw)\n" as *u8)
229
230 var fails: i64 = 0
231 if (buf[0] as i64) != 0x4D { fails=fails+1 }
232 if (buf[0x84+18] as i64) != 0x22 { fails=fails+1 }
233 if wrote != fsz { fails=fails+1 }
234 if fails == 0 { d11_puts("NX-PE-D3D11SHADE GREEN -- shader-Draw DLL; harness must CreatePixelShader+Draw via real <d3d11.h>\n" as *u8); sys_exit(0); return 0 }
235 d11_puts("NX-PE-D3D11SHADE RED fails="); d11_putn(fails); d11_puts("\n" as *u8)
236 sys_exit(1)
237 return 1
238}