Optimize viewer shaders and camera controls; sample GPU profiles asynchronously

Amp-Thread-ID: https://ampcode.com/threads/T-01a0b382-1e79-712b-abd1-d29201c9bb5e
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-09-18 11:52:09 +00:00
co-authored by heaust
parent bc957cf40d
commit eb8aa0e9dc
21 changed files with 762 additions and 174 deletions
+42
View File
@@ -0,0 +1,42 @@
// Single-writer/single-reader latest-sample mailbox. Header: state, UTF-8 byte length.
// State 0 = empty, 1 = owned by a reader/writer, 2 = complete sample.
// Neither side waits: an unread sample can be replaced, and a busy publication is skipped.
export class SharedProfile {
constructor(buffer = new SharedArrayBuffer(1024 * 1024)) {
this.buffer = buffer;
this.header = new Int32Array(buffer, 0, 2);
this.bytes = new Uint8Array(buffer, 8);
this.encoder = new TextEncoder();
this.decoder = new TextDecoder();
}
write(json) {
const bytes = this.encoder.encode(json);
if (bytes.length > this.bytes.length) return false;
const state = Atomics.load(this.header, 0);
if (
state === 1 ||
Atomics.compareExchange(this.header, 0, state, 1) !== state
)
return false;
this.bytes.set(bytes);
this.header[1] = bytes.length;
Atomics.store(this.header, 0, 2);
return true;
}
read() {
if (Atomics.compareExchange(this.header, 0, 2, 1) !== 2) return;
let bytes;
try {
bytes = this.bytes.slice(0, this.header[1]);
} finally {
Atomics.store(this.header, 0, 0);
}
return JSON.parse(this.decoder.decode(bytes));
}
clear() {
Atomics.compareExchange(this.header, 0, 2, 0);
}
}