Browse Source

Do not upload buffers each frame (DUH!), re-introduce dynamic data, set headers in caddy to enable precise timings

ssao
A.Olokhtonov 1 year ago
parent
commit
eefbb8ef75
  1. 7
      Caddyfile
  2. 24
      client/index.html
  3. 14
      client/index.js
  4. 2
      client/math.js
  5. 60
      client/webgl_draw.js
  6. 48
      client/webgl_geometry.js
  7. 5
      client/webgl_shaders.js

7
Caddyfile

@ -1,4 +1,9 @@ @@ -1,4 +1,9 @@
http://192.168.100.2 {
desk.local {
header {
Cross-Origin-Opener-Policy same-origin
Cross-Origin-Embedder-Policy require-corp
}
redir /ws /ws/
redir /desk /desk/

24
client/index.html

@ -7,20 +7,20 @@ @@ -7,20 +7,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="shortcut icon" href="icons/favicon.svg" id="favicon">
<link rel="stylesheet" type="text/css" href="default.css?v=42">
<link rel="stylesheet" type="text/css" href="default.css?v=45">
<script type="text/javascript" src="aux.js?v=42"></script>
<script type="text/javascript" src="math.js?v=42"></script>
<script type="text/javascript" src="tools.js?v=42"></script>
<script type="text/javascript" src="webgl_geometry.js?v=42"></script>
<script type="text/javascript" src="webgl_shaders.js?v=42"></script>
<script type="text/javascript" src="webgl_listeners.js?v=42"></script>
<script type="text/javascript" src="webgl_draw.js?v=42"></script>
<script type="text/javascript" src="index.js?v=42"></script>
<script type="text/javascript" src="aux.js?v=45"></script>
<script type="text/javascript" src="math.js?v=45"></script>
<script type="text/javascript" src="tools.js?v=45"></script>
<script type="text/javascript" src="webgl_geometry.js?v=45"></script>
<script type="text/javascript" src="webgl_shaders.js?v=45"></script>
<script type="text/javascript" src="webgl_listeners.js?v=45"></script>
<script type="text/javascript" src="webgl_draw.js?v=45"></script>
<script type="text/javascript" src="index.js?v=45"></script>
<script type="text/javascript" src="client_send.js?v=42"></script>
<script type="text/javascript" src="client_recv.js?v=42"></script>
<script type="text/javascript" src="websocket.js?v=42"></script>
<script type="text/javascript" src="client_send.js?v=45"></script>
<script type="text/javascript" src="client_recv.js?v=45"></script>
<script type="text/javascript" src="websocket.js?v=45"></script>
</head>
<body>
<div class="main">

14
client/index.js

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
document.addEventListener('DOMContentLoaded', main);
const config = {
ws_url: 'ws://192.168.100.2/ws/',
ping_url: 'http://192.168.100.2/api/ping',
image_url: 'http://192.168.100.2/images/',
ws_url: 'wss://desk.local/ws/',
ping_url: 'https://desk.local/api/ping',
image_url: 'https://desk.local/images/',
sync_timeout: 1000,
ws_reconnect_timeout: 2000,
brush_preview_timeout: 1000,
@ -17,6 +17,8 @@ const config = { @@ -17,6 +17,8 @@ const config = {
default_width: 8,
bytes_per_point: 8 * 4,
initial_static_bytes: 4096 * 16,
initial_dynamic_bytes: 4096,
frametime_window_size: 100,
};
const EVENT = Object.freeze({
@ -109,6 +111,11 @@ function main() { @@ -109,6 +111,11 @@ function main() {
'canvas': null,
'gl': null,
'debug_mode': false,
'frametime_window': [],
'frametime_window_head': 0,
'need_static_upload': true,
'need_dynamic_upload': false,
'programs': {},
'buffers': {},
@ -116,6 +123,7 @@ function main() { @@ -116,6 +123,7 @@ function main() {
'textures': {},
'static_serializer': serializer_create(config.initial_static_bytes),
'dynamic_serializer': serializer_create(config.initial_dynamic_bytes),
'bgcolor': {'r': 1.0, 'g': 1.0, 'b': 1.0},

2
client/math.js

@ -7,7 +7,7 @@ function screen_to_canvas(state, p) { @@ -7,7 +7,7 @@ function screen_to_canvas(state, p) {
}
function rdp_find_max(state, points, start, end) {
const EPS = 0.5 / Math.pow(state.canvas.zoom, 0.5);
const EPS = 0.5 / Math.pow(state.canvas.zoom, 0.25);
// const EPS = 10.0;
let result = -1;

60
client/webgl_draw.js

@ -12,6 +12,9 @@ function draw(state, context) { @@ -12,6 +12,9 @@ function draw(state, context) {
const width = window.innerWidth;
const height = window.innerHeight;
const frame_start = performance.now();
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
let locations;
let buffers;
@ -25,7 +28,16 @@ function draw(state, context) { @@ -25,7 +28,16 @@ function draw(state, context) {
gl.useProgram(context.programs['sdf']);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_packed']);
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height);
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom);
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y);
gl.uniform1i(locations['u_debug_mode'], context.debug_mode ? 1 : 0);
const static_points = context.static_serializer.offset / config.bytes_per_point;
const dynamic_points = context.dynamic_serializer.offset / config.bytes_per_point;
if (static_points > 0) {
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_packed_static']);
gl.enableVertexAttribArray(locations['a_pos']);
gl.enableVertexAttribArray(locations['a_line']);
@ -35,21 +47,49 @@ function draw(state, context) { @@ -35,21 +47,49 @@ function draw(state, context) {
gl.vertexAttribPointer(locations['a_line'], 4, gl.FLOAT, false, config.bytes_per_point, 4 * 3);
gl.vertexAttribPointer(locations['a_color'], 3, gl.UNSIGNED_BYTE, true, config.bytes_per_point, 4 * 3 + 4 * 4);
const npoints = context.static_serializer.offset / config.bytes_per_point;
if (context.need_static_upload) {
gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(context.static_serializer.buffer, 0, context.static_serializer.offset), gl.STATIC_DRAW);
context.need_static_upload = false;
}
// TODO: if changed
gl.drawArrays(gl.TRIANGLES, 0, static_points);
}
if (npoints > 0) {
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height);
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom);
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y);
gl.uniform1i(locations['u_debug_mode'], context.debug_mode ? 1 : 0);
if (dynamic_points > 0) {
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_packed_dynamic']);
gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(context.static_serializer.buffer, 0, context.static_serializer.offset), gl.STATIC_DRAW);
gl.enableVertexAttribArray(locations['a_pos']);
gl.enableVertexAttribArray(locations['a_line']);
gl.enableVertexAttribArray(locations['a_color']);
gl.vertexAttribPointer(locations['a_pos'], 3, gl.FLOAT, false, config.bytes_per_point, 0);
gl.vertexAttribPointer(locations['a_line'], 4, gl.FLOAT, false, config.bytes_per_point, 4 * 3);
gl.vertexAttribPointer(locations['a_color'], 3, gl.UNSIGNED_BYTE, true, config.bytes_per_point, 4 * 3 + 4 * 4);
gl.drawArrays(gl.TRIANGLES, 0, npoints);
if (context.need_dynamic_upload) {
gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(context.dynamic_serializer.buffer, 0, context.dynamic_serializer.offset), gl.STATIC_DRAW);
context.need_dynamic_upload = false;
}
gl.drawArrays(gl.TRIANGLES, 0, dynamic_points);
}
const next_tick = () => {
const wait_status = gl.clientWaitSync(sync, 0, 0);
const frame_end = performance.now();
if (wait_status === gl.ALREADY_SIGNALED || wait_status === gl.CONDITION_SATISFIED) {
const frametime_ms = frame_end - frame_start;
gl.deleteSync(sync);
console.debug(frametime_ms);
} else {
setTimeout(next_tick, 0);
}
}
setTimeout(next_tick, 0);
// Images
// locations = context.locations['image'];
// buffers = context.buffers['image'];

48
client/webgl_geometry.js

@ -22,7 +22,7 @@ function push_quad(s, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y, ax, ay, bx, by, th @@ -22,7 +22,7 @@ function push_quad(s, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y, ax, ay, bx, by, th
push_point(s, p2x, p2y, ax, ay, bx, by, thickness, r, g, b);
}
function push_stroke(context, stroke) {
function push_stroke(s, stroke) {
// if (stroke.stroke_id !== 1123776468) {
// return;
// }
@ -66,7 +66,7 @@ function push_stroke(context, stroke) { @@ -66,7 +66,7 @@ function push_stroke(context, stroke) {
let p4_x = to.x + (-up_x + dir1_x) * radius;
let p4_y = to.y + (-up_y + dir1_y) * radius;
push_quad(context.static_serializer,
push_quad(s,
p1_x, p1_y,
p2_x, p2_y,
p3_x, p3_y,
@ -103,7 +103,9 @@ function geometry_add_stroke(state, context, stroke) { @@ -103,7 +103,9 @@ function geometry_add_stroke(state, context, stroke) {
context.static_serializer = ser_extend(context.static_serializer, extend_to);
}
push_stroke(context, stroke);
push_stroke(context.static_serializer, stroke);
context.need_static_upload = true;
}
function geometry_delete_stroke(state, context, stroke_index) {
@ -127,28 +129,30 @@ function geometry_delete_stroke(state, context, stroke_index) { @@ -127,28 +129,30 @@ function geometry_delete_stroke(state, context, stroke_index) {
}
function recompute_dynamic_data(state, context) {
// let bytes_needed = 0;
let bytes_needed = 0;
// for (const player_id in state.players) {
// const player = state.players[player_id];
// if (player.points.length > 0) {
// bytes_needed += player.points.length * config.bytes_per_point;
// }
// }
for (const player_id in state.players) {
const player = state.players[player_id];
if (player.points.length > 0) {
bytes_needed += player.points.length * 6 * config.bytes_per_point;
}
}
// if (bytes_needed > context.dynamic_stroke_serializer.size) {
// context.dynamic_stroke_serializer = serializer_create(Math.ceil(bytes_needed * 1.62));
// } else {
// context.dynamic_stroke_serializer.offset = 0;
// }
if (bytes_needed > context.dynamic_serializer.size) {
context.dynamic_serializer = serializer_create(Math.ceil(bytes_needed * 1.62));
} else {
context.dynamic_serializer.offset = 0;
}
// for (const player_id in state.players) {
// // player has the same data as their current stroke: points, color, width
// const player = state.players[player_id];
// if (player.points.length > 0) {
// push_stroke(context.dynamic_stroke_serializer, player);
// }
// }
for (const player_id in state.players) {
// player has the same data as their current stroke: points, color, width
const player = state.players[player_id];
if (player.points.length > 0) {
push_stroke(context.dynamic_serializer, player);
}
}
context.need_dynamic_upload = true;
}
function geometry_add_point(state, context, player_id, point) {

5
client/webgl_shaders.js

@ -80,7 +80,7 @@ const sdf_fs_src = `#version 300 es @@ -80,7 +80,7 @@ const sdf_fs_src = `#version 300 es
// float alpha = 1.0 - step(0.0, dist);
if (u_debug_mode == 1) {
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
FragColor = vec4(1.0, 0.0, 0.0, 0.5);
} else {
FragColor = vec4(v_color * alpha, alpha);
// FragColor = vec4(v_color * alpha, 0.1 + alpha);
@ -179,7 +179,8 @@ function init_webgl(state, context) { @@ -179,7 +179,8 @@ function init_webgl(state, context) {
};
context.buffers['sdf'] = {
'b_packed': context.gl.createBuffer(),
'b_packed_static': context.gl.createBuffer(),
'b_packed_dynamic': context.gl.createBuffer(),
};
context.textures['sdf'] = {

Loading…
Cancel
Save