diff --git a/client/lod_worker.js b/client/lod_worker.js index b666434..c21ee3e 100644 --- a/client/lod_worker.js +++ b/client/lod_worker.js @@ -19,6 +19,7 @@ function work(indices_base, indices_count, zoom, offsets) { exports.do_lod( indices_base, indices_count, zoom, offsets['coords_from'], + offsets['width'], offsets['xs'], offsets['ys'], offsets['pressures'], diff --git a/client/speed.js b/client/speed.js index bcb6f7d..18c3ca4 100644 --- a/client/speed.js +++ b/client/speed.js @@ -80,12 +80,17 @@ async function init_wasm(state) { 'used': 0, 'cap': initial }, + 'width': { + 'used': 0, + 'cap': initial + } }; state.wasm.buffers['xs'].offset = state.wasm.exports.alloc_static(initial); state.wasm.buffers['ys'].offset = state.wasm.exports.alloc_static(initial); state.wasm.buffers['pressures'].offset = state.wasm.exports.alloc_static(initial); state.wasm.buffers['coords_from'].offset = state.wasm.exports.alloc_static(initial); + state.wasm.buffers['width'].offset = state.wasm.exports.alloc_static(initial); const mem = state.wasm.memory.buffer; @@ -97,6 +102,8 @@ async function init_wasm(state) { 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); + state.wasm.buffers['width'].tv = tv_create_on(Uint32Array, initial / 4, + mem, state.wasm.buffers['width'].offset); tv_add(state.wasm.buffers['coords_from'].tv, 0); state.wasm.buffers['coords_from'].used = 4; @@ -108,6 +115,7 @@ function wasm_ensure_by(state, nstrokes, ncoords) { 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_width_offset = buffers['width'].offset; let realloc = false; let coords_bytes = buffers['xs'].cap; @@ -135,23 +143,31 @@ function wasm_ensure_by(state, nstrokes, ncoords) { 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['width'].offset = state.wasm.exports.alloc_static(stroke_bytes); 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, mem, buffers['pressures'].offset); buffers['coords_from'].tv = tv_create_on(Uint32Array, stroke_bytes / 4, mem, buffers['coords_from'].offset); + buffers['width'].tv = tv_create_on(Uint32Array, stroke_bytes / 4, mem, buffers['width'].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['pressures'].tv.size = buffers['pressures'].used; buffers['coords_from'].tv.size = buffers['coords_from'].used / 4; + buffers['width'].tv.size = buffers['width'].used / 4; + + // TODO: this is SUS, should all the caps really be coords_bytes? buffers['xs'].cap = buffers['ys'].cap = buffers['pressures'].cap = coords_bytes; - buffers['coords_from'].cap = stroke_bytes; + buffers['coords_from'].cap = buffers['width'].cap = stroke_bytes; 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_width_offset, buffers['width'].used)); + memv.set(new Uint8Array(tmp.buffer, 0, buffers['width'].used), buffers['width'].offset); + 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); @@ -180,6 +196,7 @@ async function do_lod(state, context) { const indices_per_thread = Math.floor(context.clipped_indices.size / state.wasm.workers.length); const offsets = { 'coords_from': buffers['coords_from'].offset, + 'width': buffers['width'].offset, 'xs': buffers['xs'].offset, 'ys': buffers['ys'].offset, 'pressures': buffers['pressures'].offset, diff --git a/client/wasm/lod.c b/client/wasm/lod.c index f2d7534..c1e21e7 100644 --- a/client/wasm/lod.c +++ b/client/wasm/lod.c @@ -197,6 +197,7 @@ rdp_find_max(float *xs, float *ys, unsigned char *pressures, float zoom, int coo void do_lod(int *clipped_indices, int clipped_count, float zoom, int *stroke_coords_from, + int *width, float *xs, float *ys, unsigned char *pressures, @@ -280,18 +281,20 @@ do_lod(int *clipped_indices, int clipped_count, float zoom, // Write actual coordinates (points) and stroke ids // Do this in one allocation so that they're not interleaved between threads - char *output = alloc_dynamic(segments_head * (3 * 4 + 1)); + char *output = alloc_dynamic(segments_head * (3 * 4 + 1) + clipped_count * 4); float *points = (float *) output; int *ids = (int *) (output + segments_head * 4 * 2); unsigned char *pressures_res = (unsigned char *) (output + segments_head * 4 * 3); + unsigned int *batches = (unsigned int *) (output + segments_head * (4 * 3 + 1)); int phead = 0; int ihead = 0; + float sqrt_zoom = __builtin_sqrtf(zoom); + int last_lod = -1; for (int i = 0; i < clipped_count; ++i) { int stroke_index = clipped_indices[i]; - // TODO: convert to a proper CSR, save half the memory int base_stroke = stroke_coords_from[stroke_index]; int from = segments_from[i]; int to = segments_from[i + 1]; @@ -312,6 +315,20 @@ do_lod(int *clipped_indices, int clipped_count, float zoom, ids[ihead++] = stroke_index | (1 << 31); } } + + // Compute recommended LOD level, add to current batch or start new batch + float sqrt_width = __builtin_sqrtf(width[stroke_index]); // TOOD: pass in stroke width + int lod = __builtin_round(sqrt_zoom * sqrt_width * 0.3333f); + +#if 0 + if (__builtin_abs(lod - last_lod) > 2) { + // Start new batch + } else { + // Add to existing batch + } + + last_lod = lod; +#endif } result_buffer[0] = output; diff --git a/client/wasm/lod.wasm b/client/wasm/lod.wasm index 2682500..23c843d 100755 Binary files a/client/wasm/lod.wasm and b/client/wasm/lod.wasm differ diff --git a/client/webgl_draw.js b/client/webgl_draw.js index b0d05c5..52d35a5 100644 --- a/client/webgl_draw.js +++ b/client/webgl_draw.js @@ -305,7 +305,7 @@ async function draw(state, context, animate, ts) { }); if (i % 2 == 1) { - batches[batches.length - 1].lod = Math.max(0, batches[batches.length - 1].lod - 4); + batches[batches.length - 1].lod = Math.max(0, batches[batches.length - 1].lod); } } batches.push({'index': segment_count, 'lod': -1}); // lod unused