Browse Source

Fix wrong wasm allocation, remove unused js LOD code, take radius of stroke into account when doing LOD, reduce EPS for LOD

ssao
A.Olokhtonov 10 months ago
parent
commit
58f2a60295
  1. 2
      client/client_recv.js
  2. 1
      client/index.html
  3. 5
      client/index.js
  4. 87
      client/speed.js
  5. 10
      client/wasm/lod.c
  6. BIN
      client/wasm/lod.wasm
  7. 6
      client/webgl_listeners.js
  8. 17
      server/milton.js

2
client/client_recv.js

@ -434,7 +434,7 @@ async function handle_message(state, context, d) {
const user_count = des_u32(d); const user_count = des_u32(d);
const total_points = des_u32(d); const total_points = des_u32(d);
wasm_ensure_by(state, event_count, round_to_pow2(total_points * 2)); wasm_ensure_by(state, event_count, round_to_pow2(total_points * 2, 4096));
if (config.debug_print) console.debug(`${event_count} events in init`); if (config.debug_print) console.debug(`${event_count} events in init`);

1
client/index.html

@ -39,7 +39,6 @@
<label><input type="checkbox" id="debug-red">Simple shader</label> <label><input type="checkbox" id="debug-red">Simple shader</label>
<label><input type="checkbox" id="debug-do-prepass">Depth prepass</label> <label><input type="checkbox" id="debug-do-prepass">Depth prepass</label>
<label><input type="checkbox" id="debug-use-wasm">Use WASM</label>
<div class="flexcol"> <div class="flexcol">
<label><input type="checkbox" id="debug-limit-from">Limit events from</label> <label><input type="checkbox" id="debug-limit-from">Limit events from</label>

5
client/index.js

@ -25,8 +25,8 @@ const config = {
stroke_texture_size: 1024, // means no more than 1024^2 = 1M strokes in total (this is a LOT. HMH blackboard has like 80K) stroke_texture_size: 1024, // means no more than 1024^2 = 1M strokes in total (this is a LOT. HMH blackboard has like 80K)
dynamic_stroke_texture_size: 128, // means no more than 128^2 = 16K dynamic strokes at once dynamic_stroke_texture_size: 128, // means no more than 128^2 = 16K dynamic strokes at once
benchmark: { benchmark: {
zoom: 0.03, zoom: 0.00001,
offset: { x: 720, y: 400 }, offset: { x: 425, y: -1195 },
frames: 500, frames: 500,
}, },
}; };
@ -205,7 +205,6 @@ async function main() {
'debug': { 'debug': {
'red': false, 'red': false,
'do_prepass': true, 'do_prepass': true,
'use_wasm': true,
'limit_from': false, 'limit_from': false,
'limit_to': false, 'limit_to': false,
'render_from': 0, 'render_from': 0,

87
client/speed.js

@ -99,7 +99,7 @@ function wasm_ensure_by(state, nstrokes, ncoords) {
} }
} }
function do_lod_wasm(state, context) { function do_lod(state, context) {
state.wasm.exports.free_dynamic(); state.wasm.exports.free_dynamic();
const clipped_indices = state.wasm.exports.alloc_dynamic(context.clipped_indices.size * 4); const clipped_indices = state.wasm.exports.alloc_dynamic(context.clipped_indices.size * 4);
@ -140,88 +140,3 @@ function do_lod_wasm(state, context) {
return segment_count; return segment_count;
} }
function do_lod(state, context) {
if (state.debug.use_wasm) {
return do_lod_wasm(state, context);
}
const zoom = state.canvas.zoom;
const segments_data = state.segments.data;
let segments_head = 0;
for (let i = 0; i < context.clipped_indices.size; ++i) {
const stroke_index = context.clipped_indices.data[i];
const stroke = state.events[stroke_index];
const point_count = (stroke.coords_to - stroke.coords_from) / 2;
const coords_from = stroke.coords_from;
if (point_count > state.rdp_traverse_stack.length) {
//console.size('allocate')
state.rdp_traverse_stack = new Uint32Array(round_to_pow2(point_count, 4096));
}
const stack = state.rdp_traverse_stack;
// Basic CSR crap
state.segments_from.data[i] = segments_head;
if (state.canvas.zoom <= state.line_threshold.data[stroke_index]) {
segments_data[segments_head++] = 0;
segments_data[segments_head++] = point_count - 1;
} else {
let segment_count = 2;
segments_data[segments_head++] = 0;
let head = 0;
// Using stack.push() allocates even if the stack is pre-allocated!
stack[head++] = 0;
stack[head++] = 0;
stack[head++] = point_count - 1;
while (head > 0) {
const end = stack[--head];
const value = start = stack[--head];
const type = stack[--head];
if (type === 1) {
segments_data[segments_head++] = value;
} else {
const max = rdp_find_max(state, zoom, coords_from, start, end);
if (max !== -1) {
segment_count += 1;
stack[head++] = 0;
stack[head++] = max;
stack[head++] = end;
stack[head++] = 1;
stack[head++] = max;
stack[head++] = -1;
stack[head++] = 0;
stack[head++] = start;
stack[head++] = max;
}
}
}
segments_data[segments_head++] = point_count - 1;
if (segment_count === 2 && state.canvas.zoom > state.line_threshold.data[stroke_index]) {
state.line_threshold.data[stroke_index] = state.canvas.zoom;
}
}
}
state.segments_from.data[context.clipped_indices.size] = segments_head;
state.segments_from.size = context.clipped_indices.size + 1;
state.segments.size = segments_head;
write_coordinates(state, context);
return segments_head;
}

10
client/wasm/lod.c

@ -1,3 +1,5 @@
#include <wasm_simd128.h>
extern char __heap_base; extern char __heap_base;
static int allocated_static; static int allocated_static;
@ -35,8 +37,10 @@ static int
rdp_find_max(float *coordinates, unsigned char *pressures, float zoom, int coords_from, rdp_find_max(float *coordinates, unsigned char *pressures, float zoom, int coords_from,
int segment_start, int segment_end) int segment_start, int segment_end)
{ {
float EPS = 1.0 / zoom; float EPS = 0.125 / zoom;
// __i32x4 a = wasm_i32x4_load16x4(coordinates);
int result = -1; int result = -1;
float max_dist = 0.0f; float max_dist = 0.0f;
@ -64,8 +68,8 @@ rdp_find_max(float *coordinates, unsigned char *pressures, float zoom, int coord
float apx = px - ax; float apx = px - ax;
float apy = py - ay; float apy = py - ay;
float dist = __builtin_fabsf(apx * dir_nx + apy * dir_ny); float dist = __builtin_fabsf(apx * dir_nx + apy * dir_ny)
//+ __builtin_abs(pp - ap) / 255.0f + __builtin_abs(pp - bp) / 255.0f; + __builtin_abs(pp - ap) / 255.0f + __builtin_abs(pp - bp) / 255.0f;
if (dist > EPS && dist > max_dist) { if (dist > EPS && dist > max_dist) {
result = i; result = i;

BIN
client/wasm/lod.wasm

Binary file not shown.

6
client/webgl_listeners.js

@ -26,7 +26,6 @@ function debug_panel_init(state, context) {
document.getElementById('debug-do-prepass').checked = state.debug.do_prepass; document.getElementById('debug-do-prepass').checked = state.debug.do_prepass;
document.getElementById('debug-limit-from').checked = state.debug.limit_from; document.getElementById('debug-limit-from').checked = state.debug.limit_from;
document.getElementById('debug-limit-to').checked = state.debug.limit_to; document.getElementById('debug-limit-to').checked = state.debug.limit_to;
document.getElementById('debug-use-wasm').checked = state.debug.use_wasm;
document.getElementById('debug-red').addEventListener('change', (e) => { document.getElementById('debug-red').addEventListener('change', (e) => {
state.debug.red = e.target.checked; state.debug.red = e.target.checked;
@ -38,11 +37,6 @@ function debug_panel_init(state, context) {
schedule_draw(state, context); schedule_draw(state, context);
}); });
document.getElementById('debug-use-wasm').addEventListener('change', (e) => {
state.debug.use_wasm = e.target.checked;
schedule_draw(state, context);
});
document.getElementById('debug-limit-from').addEventListener('change', (e) => { document.getElementById('debug-limit-from').addEventListener('change', (e) => {
state.debug.limit_from = e.target.checked; state.debug.limit_from = e.target.checked;
schedule_draw(state, context); schedule_draw(state, context);

17
server/milton.js

@ -9,22 +9,27 @@ let first_point_y = null;
function parse_and_insert_stroke(desk_id, line) { function parse_and_insert_stroke(desk_id, line) {
const words = line.split(' '); const words = line.split(' ');
const width = parseInt(words.shift()); const width = parseInt(words.shift());
const points = new Float32Array(words.map(i => parseFloat(i))); const data = new Float32Array(words.map(i => parseFloat(i)));
const points = new Float32Array(data.length / 3 * 2);
const pressures = new Uint8Array(data.length / 3);
if (first_point_x === null) { if (first_point_x === null) {
first_point_x = points[0]; first_point_x = points[0];
first_point_y = points[1]; first_point_y = points[1];
} }
for (let i = 0; i < points.length; i += 2) { for (let i = 0; i < data.length; i += 3) {
points[i + 0] -= first_point_x; points[i / 3 * 2 + 0] = data[i + 0];
points[i + 1] -= first_point_y; points[i / 3 * 2 + 1] = data[i + 1];
pressures[i / 3 + 0] = Math.floor(data[i + 2] * 255);
} }
const stroke_res = storage.queries.insert_stroke.get({ const stroke_res = storage.queries.insert_stroke.get({
'$width': width, '$width': width,
'$color': 0, '$color': 0,
'$points': points '$points': points,
'$pressures': pressures,
}); });
storage.queries.insert_event.run({ storage.queries.insert_event.run({
@ -62,4 +67,4 @@ async function import_milton_file_to_sqlite(fullpath) {
console.log(`Finished importing desk ${desk_id}`); console.log(`Finished importing desk ${desk_id}`);
} }
import_milton_file_to_sqlite("/code/desk2/server/points.txt"); import_milton_file_to_sqlite("/home/aolo2/Documents/bin/milton/build/points_pressure.txt");

Loading…
Cancel
Save