webgl2 1.1.17 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -19,6 +19,30 @@ export const debug = {
19
19
 
20
20
  export { ERR_OK, ERR_INVALID_HANDLE, GPUBufferUsage, GPUMapMode, GPUTextureUsage, getShaderModule, getShaderWat, getShaderGlsl, decompileWasmToGlsl };
21
21
 
22
+ /**
23
+ * Simple allocator for function table indices.
24
+ * Tracks which slots are in use to enable reuse.
25
+ */
26
+ class TableAllocator {
27
+ constructor() {
28
+ // Rust uses the first ~1900 slots for its indirect function table (dyn calls, etc).
29
+ // We must valid collision by starting allocations after that region.
30
+ this.nextIndex = 2000;
31
+ this.freeList = [];
32
+ }
33
+
34
+ allocate() {
35
+ if (this.freeList.length > 0) {
36
+ return this.freeList.pop();
37
+ }
38
+ return this.nextIndex++;
39
+ }
40
+
41
+ free(index) {
42
+ this.freeList.push(index);
43
+ }
44
+ }
45
+
22
46
  /**
23
47
  * WebGL2 Prototype: Rust-owned Context, JS thin-forwarder
24
48
  * Implements docs/1.1.1-webgl2-prototype.md
@@ -75,7 +99,7 @@ export async function webGL2({ debug = (typeof process !== 'undefined' ? process
75
99
  }
76
100
  });
77
101
  }
78
- const { ex, instance } = await promise;
102
+ const { ex, instance, sharedTable, tableAllocator } = await promise;
79
103
 
80
104
  // Initialize coverage if available
81
105
  if (ex.wasm_init_coverage && ex.COV_MAP_PTR) {
@@ -105,7 +129,15 @@ export async function webGL2({ debug = (typeof process !== 'undefined' ? process
105
129
  }
106
130
 
107
131
  // Wrap and return, pass debug booleans to the JS wrapper
108
- const gl = new WasmWebGL2RenderingContext({ instance, ctxHandle, width, height, debugShaders: !!debugShaders });
132
+ const gl = new WasmWebGL2RenderingContext({
133
+ instance,
134
+ ctxHandle,
135
+ width,
136
+ height,
137
+ debugShaders: !!debugShaders,
138
+ sharedTable,
139
+ tableAllocator
140
+ });
109
141
 
110
142
  if (size && typeof size.width === 'number' && typeof size.height === 'number') {
111
143
  gl.resize(size.width, size.height);
@@ -172,17 +204,27 @@ async function initWASM({ debug } = {}) {
172
204
 
173
205
  // Instantiate WASM (no imports needed, memory is exported)
174
206
  let instance;
207
+
208
+ // Create shared function table for direct shader calls
209
+ const sharedTable = new WebAssembly.Table({
210
+ initial: 4096, // WASM module requires at least 1982
211
+ maximum: 4096, // Prevent unbounded growth
212
+ element: "anyfunc"
213
+ });
214
+ const tableAllocator = new TableAllocator();
215
+
175
216
  const importObject = {
176
217
  env: {
218
+ __indirect_function_table: sharedTable, // Exact name LLVM expects
177
219
  print: (ptr, len) => {
178
220
  const mem = new Uint8Array(instance.exports.memory.buffer);
179
221
  const bytes = mem.subarray(ptr, ptr + len);
180
222
  console.log(new TextDecoder('utf-8').decode(bytes));
181
223
  },
182
- wasm_execute_shader: (ctx, type, attrPtr, uniformPtr, varyingPtr, privatePtr, texturePtr) => {
224
+ wasm_execute_shader: (ctx, type, tableIdx, attrPtr, uniformPtr, varyingPtr, privatePtr, texturePtr) => {
183
225
  const gl = WasmWebGL2RenderingContext._contexts.get(ctx);
184
226
  if (gl) {
185
- gl._executeShader(type, attrPtr, uniformPtr, varyingPtr, privatePtr, texturePtr);
227
+ gl._executeShader(type, tableIdx, attrPtr, uniformPtr, varyingPtr, privatePtr, texturePtr);
186
228
  } else {
187
229
  // console.log(`DEBUG: wasm_execute_shader: ctx ${ctx} not found in _contexts`);
188
230
  }
@@ -192,15 +234,29 @@ async function initWASM({ debug } = {}) {
192
234
  const bytes = mem.subarray(ptr, ptr + len);
193
235
  const msg = new TextDecoder('utf-8').decode(bytes);
194
236
  if (typeof GPU !== 'undefined' && typeof GPU.dispatchUncapturedError === 'function') {
195
- GPU.dispatchUncapturedError(msg);
237
+ GPU.dispatchUncapturedError(msg);
196
238
  } else {
197
- console.error("GPU.dispatchUncapturedError not available", msg);
239
+ console.error("GPU.dispatchUncapturedError not available", msg);
198
240
  }
199
241
  },
200
242
  // Required by egg crate for timing measurements
201
243
  now: () => {
202
244
  return performance.now();
203
245
  }
246
+ },
247
+ math: {
248
+ sin: Math.sin,
249
+ cos: Math.cos,
250
+ tan: Math.tan,
251
+ asin: Math.asin,
252
+ acos: Math.acos,
253
+ atan: Math.atan,
254
+ atan2: Math.atan2,
255
+ exp: Math.exp,
256
+ exp2: (x) => Math.pow(2, x),
257
+ log: Math.log,
258
+ log2: Math.log2,
259
+ pow: Math.pow
204
260
  }
205
261
  };
206
262
  instance = await WebAssembly.instantiate(wasmModule, importObject);
@@ -213,7 +269,7 @@ async function initWASM({ debug } = {}) {
213
269
  if (!(ex.memory instanceof WebAssembly.Memory)) {
214
270
  throw new Error('WASM module missing memory export');
215
271
  }
216
- return { ex, instance, module: wasmModule };
272
+ return { ex, instance, module: wasmModule, sharedTable, tableAllocator };
217
273
  }
218
274
 
219
275
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webgl2",
3
- "version": "1.1.17",
3
+ "version": "1.2.0",
4
4
  "description": "WebGL2 tools to derisk large GPU projects on the web beyond toys and demos.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -24,6 +24,7 @@
24
24
  "homepage": "https://webgl2.was.hm",
25
25
  "files": [
26
26
  "index.js",
27
+ "demo.js",
27
28
  "src/*.js",
28
29
  "webgl2.wasm",
29
30
  "webgl2.debug.wasm",