From ce824a8e31b679a51b35a776d50a03512cba08c9 Mon Sep 17 00:00:00 2001 From: "A.Olokhtonov" Date: Mon, 18 Nov 2024 00:24:17 +0300 Subject: [PATCH] Pass stroke widths to wasm (not actually writing any values right now, just some busywork to allocate memory and pass pointers) --- client/lod_worker.js | 1 + client/speed.js | 19 ++++++++++++++++++- client/wasm/lod.c | 21 +++++++++++++++++++-- client/wasm/lod.wasm | Bin 2784 -> 2793 bytes client/webgl_draw.js | 2 +- 5 files changed, 39 insertions(+), 4 deletions(-) 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 268250085ae243ef6d21b3814b4a8134b7b65954..23c843d3b9700370db94a9041b19610f22b995c9 100755 GIT binary patch delta 1641 zcmYLJ$!;V?5Y4QrZntZ3@9m`*N2ZtYf(+Ez|>K+rYTn2n3_* z0|yWsMpOO(!~rx%|u9k%wOLsyiPyNF4*pBESI$%^e_| zP%Q+SGtnt6S>yhnEsLWoaD}HFj%V)Jss(CO$L49&5>=*&t5&rU3}q`1CAacavsn@< zQ5(79a3(`#2=rl4lUsz?+ZamW13TS0hw7UP{_=5t?t34m+h7# zl!KI2s|k&yB4xHiY$9@ah~T3c>e(G3ZVC|3>jrfw;F^&P?GJ&iWMg0pnBf4#NyeP> z4Y=4NK|9p|x~{y?2}Je-M%2JiGRZJpUBhmGMCCOeP&X~+WYRo1!WJVqbNQCI?qZ-i zNQy^R$IAy!2~aCm5p`kA!YYjbJ*!sOW1KTEY+ThsL*^J{4U?9xL(OPUosXNUi);c1LDDNe{R#wNwVzg*P@8rnMi--#^*rskYLBV_hOTSgGS(3* zE20%{eU%oNF@5bSt*ZkhT}Zwy?#CYaF9Lg+_S3+7IFXn=gV|&v4d{D8;86}Vo?UBG zL7fh(ripkgW^23;v_JeWSrM09MJ5JzhqhkV&Gs}1mY6#@=0n}+u}{^PBN=0aNVv-F zgmy1!haz4)m0Ujh3O>p(d$cjsO=_Cu3*8)1b9nU#r>+gPhwj4WjmU#dZ_?IXB-(uQ zewLUv|IIr6+(fLqOobL-9adaiKsjZD!Y%pPZ469&96?36L79y?L7cm{VcbLkf%5pf zg+Taj1pxqHze{W6G41P9DblLdkUpC@ckT>uCvN?Xr+huLS1i4hi6t6W@FTGa~O z0zFSbissXe^f#IQF6lXnvh`uUPJfl@6NwHj*z^q{(l2HDSSCM~4jX}i-ucF1;941J zQkq@c&ee%K!8Z&_Z}8=@&?z^9e>9t+52$?g+H6V6y`=B2_x!yZyL-FO(#HO#c(*+6 zpT9F0zjbfWA77jgMl;EG{>|=o`FwD1a6Wkd?ZM9YlMe@@ZU5}zbo|~&{nLxVKjJSc Aga7~l delta 1649 zcmYjROK%)S5bmDYUGKd1y?(79)$K?8Aa-J49dbbKM6pmnxp4x5eK4S&L@4$~LV{@a zzyS#kk;mM*apC|uN8*nl`4Eu!0i2?NeATlcW;I*g)sOn>`>N*8{$+nb9G^XuLI_FK zBO#7t#;?qdf-HOT^Wtw(zQ|w7A3uAZ_>|S2L|?85^TSxCy0t321Co^k5-KEV1iyC& zTB*oCpa_1S!VOOtZ)9~~Di&jkEd{WtiYbH(2O}d>6~(gZF7QTq?9XMhn8Y~v_mcN@ zUC*0w9f$P5JpJZZVXc~>3LjpeDx1aIK>s#*-@|6NFZ5Q?Rj&g=m((Fp%mNo6P;&?@ zLQUi9rb!+c-{TId3IRBncWHq_&Joc-e*;P(k9eXakir>2Ug#Q9$JDLr zFlei$p)yGo#9k!a4=|AhqY0P}Mhu=RHp7I8Vbey?*-|~4fh^c#1P5>368k<3h13SO zNNecT0T$vc17W+oRuRrGTBUi#cn|fQRV&7Kx-}Vhg9X&6io4*5xz($bwYXyIsa|6Q z31UneKP_d`>x@)#WzCdyQ{uQ#&Df7P`xF~=hmylYf^^4kuLJ|e;Yk3I=OHVgw{z`% zM;>_>5FlU|RXqyx-P-Q^2>|M-Xru5vTP#ReAJ&7d!20Ss`1Mn;O}u5KW3H!|G|N$= z4$WCsPG5P3mKeg5z?1(}+sguq-a`g0+AE^U)3LG?@yxp->wrZ`aDEg={^p zpdRi_m~2z|Tu14DA**O?6&utoGTHh-_Xd+oFvZxzu?UsTl}Md?2?`ucQOL<|=d^P{ zS1IPnYx%|bw^&B)vhgo8Kts#S2+n$|7cg{{Mip6laBlfu^|fvH5h1h_Hz!)8%WY>--(}Z|i0Urih+5C? v1a&F*@_XU>a&&#Tb8Tlx8+-ek;@#%x`1I40(Z`>h9FHEKo}5+l^YG>?>y0F* 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