You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

219 lines
8.6 KiB

async function init_test() {
const memory = new WebAssembly.Memory({
initial: 32,
maximum: 100,
shared: true,
});
const results = await WebAssembly.instantiateStreaming(fetch('wasm/multi.wasm'), {
env: { 'memory': memory }
});
const nworkers = navigator.hardwareConcurrency;
const heap_base = results.instance.exports.alloc(0);
const buf_offset = results.instance.exports.alloc(1024);
const workers = [];
const sab = new SharedArrayBuffer(nworkers * 4);
const flags = new Int32Array(sab);
let done = 0;
for (let i = 0; i < nworkers; ++i) {
const w = new Worker('wasm_worker.js');
workers.push(w);
}
for (let i = 0; i < nworkers; ++i) {
workers[i].onmessage = () => {
++done;
if (done % nworkers === 0) {
console.log('init done');
for (let j = 0; j < nworkers; ++j) {
workers[j].onmessage = () => {
++done;
if (done % nworkers === 0) {
console.log('work done');
console.log(new Int32Array(memory.buffer, buf_offset, nworkers));
}
}
workers[j].postMessage({
'type': 1,
'num': 10,
});
}
}
}
workers[i].postMessage({
'type': 0,
'thread_id': i,
'memory': memory,
'stack_base': heap_base,
'buffer_offset': buf_offset,
'flags': flags
});
}
// const results = await WebAssembly.instantiateStreaming(fetch('wasm/multi.wasm'));
// state.wasm.exports = results.instance.exports;
// state.wasm.exports.memory.grow(4096);
}
async function init_wasm(state) {
await init_test();
const results = await WebAssembly.instantiateStreaming(fetch('wasm/lod.wasm'));
state.wasm.exports = results.instance.exports;
state.wasm.exports.memory.grow(4096);
state.wasm.stroke_bytes = 4096;
state.wasm.coords_bytes = 4096;
state.wasm.buffers = {
'xs': {
'offset': state.wasm.exports.alloc_static(state.wasm.coords_bytes / 2),
'used': 0
},
'ys': {
'offset': state.wasm.exports.alloc_static(state.wasm.coords_bytes / 2),
'used': 0
},
'coords_from': {
'offset': state.wasm.exports.alloc_static(state.wasm.stroke_bytes),
'used': 0,
},
'line_threshold': {
'offset': state.wasm.exports.alloc_static(state.wasm.stroke_bytes),
'used': 0,
},
'pressures': {
'offset': state.wasm.exports.alloc_static(state.wasm.coords_bytes / 8),
'used': 0
},
};
const mem = state.wasm.exports.memory.buffer;
state.wasm.buffers['xs'].tv = tv_create_on(Float32Array, state.wasm.coords_bytes / 8,
mem, state.wasm.buffers['xs'].offset);
state.wasm.buffers['ys'].tv = tv_create_on(Float32Array, state.wasm.coords_bytes / 8,
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['line_threshold'].tv = tv_create_on(Float32Array, state.wasm.stroke_bytes / 4,
mem, state.wasm.buffers['line_threshold'].offset);
state.wasm.buffers['pressures'].tv = tv_create_on(Uint8Array, state.wasm.coords_bytes / 8,
mem, state.wasm.buffers['pressures'].offset);
tv_add(state.wasm.buffers['coords_from'].tv, 0);
state.wasm.buffers['coords_from'].used = 4;
}
function wasm_ensure_by(state, nstrokes, ncoords) {
const buffers = state.wasm.buffers;
const old_coords_from_offset = buffers['coords_from'].offset;
const old_line_threshold_offset = buffers['line_threshold'].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;
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)
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);
realloc = true;
}
if (realloc) {
// TODO: we do memory.grow() somewhere here if needed
state.wasm.exports.free_static();
const mem = state.wasm.exports.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['line_threshold'].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'].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['line_threshold'].tv = tv_create_on(Float32Array, state.wasm.stroke_bytes / 4, mem, buffers['line_threshold'].offset);
buffers['pressures'].tv = tv_create_on(Uint8Array, state.wasm.coords_bytes / 8, mem, buffers['pressures'].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['line_threshold'].tv.size = buffers['line_threshold'].used / 4;
buffers['pressures'].tv.size = buffers['pressures'].used;
const tmp = new Uint8Array(Math.max(state.wasm.coords_bytes, state.wasm.stroke_bytes)); // TODO: needed?
// Copy from back to front (otherwise we will overwrite)
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_line_threshold_offset, old_size_strokes));
memv.set(new Uint8Array(tmp.buffer, 0, old_size_strokes), buffers['line_threshold'].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);
}
}
function do_lod(state, context) {
state.wasm.exports.free_dynamic();
const clipped_indices = state.wasm.exports.alloc_dynamic(context.clipped_indices.size * 4);
const mem = new Uint8Array(state.wasm.exports.memory.buffer);
// Dynamic input data that should (by design) never be too big
mem.set(tv_bytes(context.clipped_indices), clipped_indices);
const buffers = state.wasm.buffers;
const segment_count = state.wasm.exports.do_lod(
clipped_indices, context.clipped_indices.size, state.canvas.zoom,
buffers['coords_from'].offset,
buffers['line_threshold'].offset,
buffers['xs'].offset,
buffers['ys'].offset,
buffers['pressures'].offset,
buffers['xs'].used / 4,
);
// Use results without copying from WASM memory
const result_offset = clipped_indices + context.clipped_indices.size * 4
+ (context.clipped_indices.size + 1) * 4 + buffers['xs'].used;
const wasm_points = new Float32Array(state.wasm.exports.memory.buffer,
result_offset, segment_count * 2);
const wasm_ids = new Uint32Array(state.wasm.exports.memory.buffer,
result_offset + segment_count * 2 * 4, segment_count);
const wasm_pressures = new Uint8Array(state.wasm.exports.memory.buffer,
result_offset + segment_count * 2 * 4 + segment_count * 4, segment_count);
context.instance_data_points.data = wasm_points;
context.instance_data_points.size = segment_count * 2;
context.instance_data_ids.data = wasm_ids;
context.instance_data_ids.size = segment_count;
context.instance_data_pressures.data = wasm_pressures;
context.instance_data_pressures.size = segment_count;
return segment_count;
}