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. 9
      Caddyfile
  2. 24
      client/index.html
  3. 14
      client/index.js
  4. 2
      client/math.js
  5. 72
      client/webgl_draw.js
  6. 48
      client/webgl_geometry.js
  7. 5
      client/webgl_shaders.js

9
Caddyfile

@ -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 /ws /ws/
redir /desk /desk/ redir /desk /desk/
@ -16,7 +21,7 @@ http://192.168.100.2 {
} }
handle_path /desk/* { handle_path /desk/* {
root * /code/desk2/client root * /code/desk2/client
try_files {path} /index.html try_files {path} /index.html
file_server file_server
} }

24
client/index.html

@ -7,20 +7,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <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="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="aux.js?v=45"></script>
<script type="text/javascript" src="math.js?v=42"></script> <script type="text/javascript" src="math.js?v=45"></script>
<script type="text/javascript" src="tools.js?v=42"></script> <script type="text/javascript" src="tools.js?v=45"></script>
<script type="text/javascript" src="webgl_geometry.js?v=42"></script> <script type="text/javascript" src="webgl_geometry.js?v=45"></script>
<script type="text/javascript" src="webgl_shaders.js?v=42"></script> <script type="text/javascript" src="webgl_shaders.js?v=45"></script>
<script type="text/javascript" src="webgl_listeners.js?v=42"></script> <script type="text/javascript" src="webgl_listeners.js?v=45"></script>
<script type="text/javascript" src="webgl_draw.js?v=42"></script> <script type="text/javascript" src="webgl_draw.js?v=45"></script>
<script type="text/javascript" src="index.js?v=42"></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_send.js?v=45"></script>
<script type="text/javascript" src="client_recv.js?v=42"></script> <script type="text/javascript" src="client_recv.js?v=45"></script>
<script type="text/javascript" src="websocket.js?v=42"></script> <script type="text/javascript" src="websocket.js?v=45"></script>
</head> </head>
<body> <body>
<div class="main"> <div class="main">

14
client/index.js

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

2
client/math.js

@ -7,7 +7,7 @@ function screen_to_canvas(state, p) {
} }
function rdp_find_max(state, points, start, end) { 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; // const EPS = 10.0;
let result = -1; let result = -1;

72
client/webgl_draw.js

@ -12,6 +12,9 @@ function draw(state, context) {
const width = window.innerWidth; const width = window.innerWidth;
const height = window.innerHeight; const height = window.innerHeight;
const frame_start = performance.now();
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
let locations; let locations;
let buffers; let buffers;
@ -25,31 +28,68 @@ function draw(state, context) {
gl.useProgram(context.programs['sdf']); 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']);
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.enableVertexAttribArray(locations['a_pos']); if (context.need_static_upload) {
gl.enableVertexAttribArray(locations['a_line']); gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(context.static_serializer.buffer, 0, context.static_serializer.offset), gl.STATIC_DRAW);
gl.enableVertexAttribArray(locations['a_color']); context.need_static_upload = false;
}
gl.vertexAttribPointer(locations['a_pos'], 3, gl.FLOAT, false, config.bytes_per_point, 0); gl.drawArrays(gl.TRIANGLES, 0, static_points);
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);
if (dynamic_points > 0) {
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_packed_dynamic']);
const npoints = context.static_serializer.offset / config.bytes_per_point; gl.enableVertexAttribArray(locations['a_pos']);
gl.enableVertexAttribArray(locations['a_line']);
gl.enableVertexAttribArray(locations['a_color']);
// TODO: if changed 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);
if (npoints > 0) { if (context.need_dynamic_upload) {
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height); gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(context.dynamic_serializer.buffer, 0, context.dynamic_serializer.offset), gl.STATIC_DRAW);
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); context.need_dynamic_upload = false;
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); }
gl.uniform1i(locations['u_debug_mode'], context.debug_mode ? 1 : 0);
gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(context.static_serializer.buffer, 0, context.static_serializer.offset), gl.STATIC_DRAW); gl.drawArrays(gl.TRIANGLES, 0, dynamic_points);
}
gl.drawArrays(gl.TRIANGLES, 0, npoints); 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 // Images
// locations = context.locations['image']; // locations = context.locations['image'];
// buffers = context.buffers['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
push_point(s, p2x, p2y, ax, ay, bx, by, thickness, r, g, b); 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) { // if (stroke.stroke_id !== 1123776468) {
// return; // return;
// } // }
@ -66,7 +66,7 @@ function push_stroke(context, stroke) {
let p4_x = to.x + (-up_x + dir1_x) * radius; let p4_x = to.x + (-up_x + dir1_x) * radius;
let p4_y = to.y + (-up_y + dir1_y) * radius; let p4_y = to.y + (-up_y + dir1_y) * radius;
push_quad(context.static_serializer, push_quad(s,
p1_x, p1_y, p1_x, p1_y,
p2_x, p2_y, p2_x, p2_y,
p3_x, p3_y, p3_x, p3_y,
@ -103,7 +103,9 @@ function geometry_add_stroke(state, context, stroke) {
context.static_serializer = ser_extend(context.static_serializer, extend_to); 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) { 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) { function recompute_dynamic_data(state, context) {
// let bytes_needed = 0; let bytes_needed = 0;
// for (const player_id in state.players) { for (const player_id in state.players) {
// const player = state.players[player_id]; const player = state.players[player_id];
// if (player.points.length > 0) { if (player.points.length > 0) {
// bytes_needed += player.points.length * config.bytes_per_point; bytes_needed += player.points.length * 6 * config.bytes_per_point;
// } }
// } }
// if (bytes_needed > context.dynamic_stroke_serializer.size) { if (bytes_needed > context.dynamic_serializer.size) {
// context.dynamic_stroke_serializer = serializer_create(Math.ceil(bytes_needed * 1.62)); context.dynamic_serializer = serializer_create(Math.ceil(bytes_needed * 1.62));
// } else { } else {
// context.dynamic_stroke_serializer.offset = 0; context.dynamic_serializer.offset = 0;
// } }
// for (const player_id in state.players) { for (const player_id in state.players) {
// // player has the same data as their current stroke: points, color, width // player has the same data as their current stroke: points, color, width
// const player = state.players[player_id]; const player = state.players[player_id];
// if (player.points.length > 0) { if (player.points.length > 0) {
// push_stroke(context.dynamic_stroke_serializer, player); push_stroke(context.dynamic_serializer, player);
// } }
// } }
context.need_dynamic_upload = true;
} }
function geometry_add_point(state, context, player_id, point) { 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
// float alpha = 1.0 - step(0.0, dist); // float alpha = 1.0 - step(0.0, dist);
if (u_debug_mode == 1) { 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 { } else {
FragColor = vec4(v_color * alpha, alpha); FragColor = vec4(v_color * alpha, alpha);
// FragColor = vec4(v_color * alpha, 0.1 + alpha); // FragColor = vec4(v_color * alpha, 0.1 + alpha);
@ -179,7 +179,8 @@ function init_webgl(state, context) {
}; };
context.buffers['sdf'] = { context.buffers['sdf'] = {
'b_packed': context.gl.createBuffer(), 'b_packed_static': context.gl.createBuffer(),
'b_packed_dynamic': context.gl.createBuffer(),
}; };
context.textures['sdf'] = { context.textures['sdf'] = {

Loading…
Cancel
Save