|
|
|
@ -33,7 +33,7 @@ function workers_thread_message(workers, message, thread_field=null) {
@@ -33,7 +33,7 @@ function workers_thread_message(workers, message, thread_field=null) {
|
|
|
|
|
|
|
|
|
|
async function init_wasm(state) { |
|
|
|
|
const memory = new WebAssembly.Memory({ |
|
|
|
|
initial: 32, // 2MiB, 1MiB of which is stack
|
|
|
|
|
initial: 16384, // F U
|
|
|
|
|
maximum: 16384, // 1GiB
|
|
|
|
|
shared: true, |
|
|
|
|
}); |
|
|
|
@ -61,37 +61,41 @@ async function init_wasm(state) {
@@ -61,37 +61,41 @@ async function init_wasm(state) {
|
|
|
|
|
'memory': memory, |
|
|
|
|
}, 'thread_id'); |
|
|
|
|
|
|
|
|
|
state.wasm.stroke_bytes = 4096; |
|
|
|
|
state.wasm.coords_bytes = 4096; |
|
|
|
|
const initial = config.initial_wasm_bytes; |
|
|
|
|
|
|
|
|
|
state.wasm.buffers = { |
|
|
|
|
'xs': { |
|
|
|
|
'offset': state.wasm.exports.alloc_static(state.wasm.coords_bytes / 2), |
|
|
|
|
'used': 0 |
|
|
|
|
'offset': state.wasm.exports.alloc_static(initial), |
|
|
|
|
'used': 0, |
|
|
|
|
'cap': initial |
|
|
|
|
}, |
|
|
|
|
'ys': { |
|
|
|
|
'offset': state.wasm.exports.alloc_static(state.wasm.coords_bytes / 2), |
|
|
|
|
'used': 0 |
|
|
|
|
'offset': state.wasm.exports.alloc_static(initial), |
|
|
|
|
'used': 0, |
|
|
|
|
'cap': initial |
|
|
|
|
}, |
|
|
|
|
'coords_from': { |
|
|
|
|
'offset': state.wasm.exports.alloc_static(state.wasm.stroke_bytes), |
|
|
|
|
'offset': state.wasm.exports.alloc_static(initial), |
|
|
|
|
'used': 0, |
|
|
|
|
'cap': initial |
|
|
|
|
}, |
|
|
|
|
'pressures': { |
|
|
|
|
'offset': state.wasm.exports.alloc_static(state.wasm.coords_bytes / 8), |
|
|
|
|
'used': 0 |
|
|
|
|
'offset': state.wasm.exports.alloc_static(initial), |
|
|
|
|
'used': 0, |
|
|
|
|
'cap': initial |
|
|
|
|
}, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const mem = state.wasm.memory.buffer; |
|
|
|
|
|
|
|
|
|
state.wasm.buffers['xs'].tv = tv_create_on(Float32Array, state.wasm.coords_bytes / 8, |
|
|
|
|
state.wasm.buffers['xs'].tv = tv_create_on(Float32Array, initial / 4, |
|
|
|
|
mem, state.wasm.buffers['xs'].offset); |
|
|
|
|
state.wasm.buffers['ys'].tv = tv_create_on(Float32Array, state.wasm.coords_bytes / 8, |
|
|
|
|
state.wasm.buffers['ys'].tv = tv_create_on(Float32Array, initial / 4, |
|
|
|
|
mem, state.wasm.buffers['ys'].offset); |
|
|
|
|
state.wasm.buffers['coords_from'].tv = tv_create_on(Uint32Array, state.wasm.stroke_bytes / 4, |
|
|
|
|
mem, state.wasm.buffers['coords_from'].offset); |
|
|
|
|
state.wasm.buffers['pressures'].tv = tv_create_on(Uint8Array, state.wasm.coords_bytes / 8, |
|
|
|
|
state.wasm.buffers['pressures'].tv = tv_create_on(Uint8Array, initial, |
|
|
|
|
mem, state.wasm.buffers['pressures'].offset); |
|
|
|
|
state.wasm.buffers['coords_from'].tv = tv_create_on(Uint32Array, initial / 4, |
|
|
|
|
mem, state.wasm.buffers['coords_from'].offset); |
|
|
|
|
|
|
|
|
|
tv_add(state.wasm.buffers['coords_from'].tv, 0); |
|
|
|
|
state.wasm.buffers['coords_from'].used = 4; |
|
|
|
@ -100,60 +104,61 @@ async function init_wasm(state) {
@@ -100,60 +104,61 @@ async function init_wasm(state) {
|
|
|
|
|
function wasm_ensure_by(state, nstrokes, ncoords) { |
|
|
|
|
const buffers = state.wasm.buffers; |
|
|
|
|
|
|
|
|
|
const old_ys_offset = buffers['ys'].offset; |
|
|
|
|
const old_coords_from_offset = buffers['coords_from'].offset; |
|
|
|
|
const old_pressures_offset = buffers['pressures'].offset; |
|
|
|
|
|
|
|
|
|
const old_size_coords = state.wasm.coords_bytes; |
|
|
|
|
const old_size_strokes = state.wasm.stroke_bytes; |
|
|
|
|
|
|
|
|
|
let realloc = false; |
|
|
|
|
let coords_bytes = buffers['xs'].cap; |
|
|
|
|
let stroke_bytes = buffers['coords_from'].cap; |
|
|
|
|
|
|
|
|
|
if (buffers['xs'].used + ncoords * 4 > state.wasm.coords_bytes / 2) { |
|
|
|
|
state.wasm.coords_bytes += round_to_pow2(ncoords * 4, 4096 * 16); // 1 wasm page (although it doesn't matter here)
|
|
|
|
|
if (buffers['xs'].used + ncoords * 4 > buffers['xs'].cap) { |
|
|
|
|
coords_bytes = round_to_pow2(buffers['xs'].cap + ncoords * 4, 4096 * 16); // 1 wasm page (although it doesn't matter here)
|
|
|
|
|
realloc = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (buffers['coords_from'].used + nstrokes * 4 > state.wasm.stroke_bytes / 2) { |
|
|
|
|
state.wasm.stroke_bytes += round_to_pow2(nstrokes * 4, 4096 * 16); |
|
|
|
|
if (buffers['coords_from'].used + nstrokes * 4 > buffers['coords_from'].cap) { |
|
|
|
|
stroke_bytes = round_to_pow2(buffers['coords_from'].cap + nstrokes * 4, 4096 * 16); |
|
|
|
|
realloc = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (realloc) { |
|
|
|
|
const current_pages = Math.ceil(state.wasm.memory.buffer.byteLength / (4096 * 16)); |
|
|
|
|
const need_pages = 2 * Math.ceil((state.wasm.coords_bytes * 3 + state.wasm.stroke_bytes * 2) / (4096 * 16)); // TODO: figure out actual memory requirements
|
|
|
|
|
const grow_by = Math.max(1, need_pages - current_pages); |
|
|
|
|
// const grow_by = 16;
|
|
|
|
|
if (config.debug_print) console.debug('WASM static data re-layout'); |
|
|
|
|
|
|
|
|
|
state.wasm.memory.grow(grow_by); |
|
|
|
|
state.wasm.exports.free_static(); |
|
|
|
|
|
|
|
|
|
const mem = state.wasm.memory.buffer; |
|
|
|
|
const memv = new Uint8Array(mem); |
|
|
|
|
|
|
|
|
|
buffers['xs'].offset = state.wasm.exports.alloc_static(state.wasm.coords_bytes / 2); |
|
|
|
|
buffers['ys'].offset = state.wasm.exports.alloc_static(state.wasm.coords_bytes / 2); |
|
|
|
|
buffers['coords_from'].offset = state.wasm.exports.alloc_static(state.wasm.stroke_bytes); |
|
|
|
|
buffers['pressures'].offset = state.wasm.exports.alloc_static(state.wasm.coords_bytes / 8); |
|
|
|
|
buffers['xs'].offset = state.wasm.exports.alloc_static(coords_bytes); |
|
|
|
|
buffers['ys'].offset = state.wasm.exports.alloc_static(coords_bytes); |
|
|
|
|
buffers['pressures'].offset = state.wasm.exports.alloc_static(coords_bytes); |
|
|
|
|
buffers['coords_from'].offset = state.wasm.exports.alloc_static(stroke_bytes); |
|
|
|
|
|
|
|
|
|
buffers['xs'].tv = tv_create_on(Float32Array, state.wasm.coords_bytes / 8, mem, buffers['xs'].offset); |
|
|
|
|
buffers['ys'].tv = tv_create_on(Float32Array, state.wasm.coords_bytes / 8, mem, buffers['ys'].offset); |
|
|
|
|
buffers['coords_from'].tv = tv_create_on(Uint32Array, state.wasm.stroke_bytes / 4, mem, buffers['coords_from'].offset); |
|
|
|
|
buffers['pressures'].tv = tv_create_on(Uint8Array, state.wasm.coords_bytes / 8, mem, buffers['pressures'].offset); |
|
|
|
|
buffers['xs'].tv = tv_create_on(Float32Array, coords_bytes / 4, mem, buffers['xs'].offset); |
|
|
|
|
buffers['ys'].tv = tv_create_on(Float32Array, coords_bytes / 4, mem, buffers['ys'].offset); |
|
|
|
|
buffers['pressures'].tv = tv_create_on(Uint8Array, coords_bytes / 8, mem, buffers['pressures'].offset); |
|
|
|
|
buffers['coords_from'].tv = tv_create_on(Uint32Array, stroke_bytes / 4, mem, buffers['coords_from'].offset); |
|
|
|
|
|
|
|
|
|
// TODO: this should have been automatic maybe?
|
|
|
|
|
buffers['xs'].tv.size = buffers['xs'].used / 4; |
|
|
|
|
buffers['ys'].tv.size = buffers['ys'].used / 4; |
|
|
|
|
buffers['coords_from'].tv.size = buffers['coords_from'].used / 4; |
|
|
|
|
buffers['pressures'].tv.size = buffers['pressures'].used; |
|
|
|
|
buffers['coords_from'].tv.size = buffers['coords_from'].used / 4; |
|
|
|
|
buffers['xs'].cap = buffers['ys'].cap = buffers['pressures'].cap = coords_bytes; |
|
|
|
|
buffers['coords_from'].cap = stroke_bytes; |
|
|
|
|
|
|
|
|
|
const tmp = new Uint8Array(Math.max(state.wasm.coords_bytes, state.wasm.stroke_bytes)); // TODO: needed?
|
|
|
|
|
const tmp = new Uint8Array(Math.max(coords_bytes, stroke_bytes)); |
|
|
|
|
|
|
|
|
|
// Copy from back to front (otherwise we will overwrite)
|
|
|
|
|
tmp.set(new Uint8Array(mem, old_coords_from_offset, buffers['coords_from'].used)); |
|
|
|
|
memv.set(new Uint8Array(tmp.buffer, 0, buffers['coords_from'].used), buffers['coords_from'].offset); |
|
|
|
|
|
|
|
|
|
tmp.set(new Uint8Array(mem, old_pressures_offset, buffers['pressures'].used)); |
|
|
|
|
memv.set(new Uint8Array(tmp.buffer, 0, buffers['pressures'].used), buffers['pressures'].offset); |
|
|
|
|
|
|
|
|
|
tmp.set(new Uint8Array(mem, old_coords_from_offset, old_size_strokes)); |
|
|
|
|
memv.set(new Uint8Array(tmp.buffer, 0, old_size_strokes), buffers['coords_from'].offset); |
|
|
|
|
tmp.set(new Uint8Array(mem, old_ys_offset, buffers['ys'].used)); |
|
|
|
|
memv.set(new Uint8Array(tmp.buffer, 0, buffers['ys'].used), buffers['ys'].offset); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|