From a5110c3d4448cd983b2db9b0f7201de840ab2d57 Mon Sep 17 00:00:00 2001 From: w Date: Sun, 30 Aug 2026 22:25:48 -0400 Subject: [PATCH 1/2] fix(gpu): refresh browser capabilities after resize --- .../src/pvm-runtime-core.js | 23 ++++++++++++ .../src/pvm-wasm-translated.js | 12 +++++++ .../pvm-runtime-assets/assets/SHA256SUMS | 6 ++-- .../assets/pvm-runtime-core.js | 23 ++++++++++++ .../assets/pvm-wasm-translated.js | 12 +++++++ .../pvm-runtime-assets/assets/pvm-worker.js | 35 +++++++++++++++++++ rust/crates/pvm-runtime-assets/src/lib.rs | 8 ++--- 7 files changed, 112 insertions(+), 7 deletions(-) diff --git a/js/packages/pvm-browser-runtime/src/pvm-runtime-core.js b/js/packages/pvm-browser-runtime/src/pvm-runtime-core.js index 9f8fb8c..3ad416b 100644 --- a/js/packages/pvm-browser-runtime/src/pvm-runtime-core.js +++ b/js/packages/pvm-browser-runtime/src/pvm-runtime-core.js @@ -599,6 +599,21 @@ globalThis.createPvmRuntime = (endpoint) => { ); } + function sendGpuCapabilities(bytes) { + if (!running || bytes.byteLength < 56 || bytes.byteLength > 4096) { + return; + } + if (translated) { + translated.setGpuCapabilities(bytes); + return; + } + stage(bytes); + check( + pvm.pvm_browser_set_gpu_capabilities(), + "update PolkaVM browser GPU capabilities" + ); + } + function sendGpuEvent(bytes) { if (!running || !pvm || !bytes.byteLength) { return; @@ -658,6 +673,14 @@ globalThis.createPvmRuntime = (endpoint) => { postMessage({ type: "error", message: error.message }); postMessage({ type: "terminated" }); } + } else if (message?.type === "gpu-capabilities") { + try { + sendGpuCapabilities(new Uint8Array(message.bytes)); + } catch (error) { + stopRuntime(); + postMessage({ type: "error", message: error.message }); + postMessage({ type: "terminated" }); + } } else if (message?.type === "gpu-event") { try { sendGpuEvent(new Uint8Array(message.bytes)); diff --git a/js/packages/pvm-browser-runtime/src/pvm-wasm-translated.js b/js/packages/pvm-browser-runtime/src/pvm-wasm-translated.js index ac74d7d..006d692 100644 --- a/js/packages/pvm-browser-runtime/src/pvm-wasm-translated.js +++ b/js/packages/pvm-browser-runtime/src/pvm-wasm-translated.js @@ -462,6 +462,18 @@ this.motionSample = bytes.slice(); } + setGpuCapabilities(bytes) { + if ( + this.stopped || + !(bytes instanceof Uint8Array) || + bytes.byteLength < 56 || + bytes.byteLength > 4096 + ) { + throw new Error("invalid translated WebGPU capabilities"); + } + this.gpuCapabilities = bytes.slice(); + } + sendGpuEvent(bytes) { if ( this.stopped || diff --git a/rust/crates/pvm-runtime-assets/assets/SHA256SUMS b/rust/crates/pvm-runtime-assets/assets/SHA256SUMS index 9e5e5dd..2aaba3d 100644 --- a/rust/crates/pvm-runtime-assets/assets/SHA256SUMS +++ b/rust/crates/pvm-runtime-assets/assets/SHA256SUMS @@ -1,6 +1,6 @@ 3b448399a39ee571765f41266032c621ce3668176d7f0d6372c85d6068e7d4a5 pvm-browser-runtime.wasm -de3d1cd9dde09c407cf46ba9c642f3e7923e23bfb30db9eef06bf7c2b949b707 pvm-worker.js +18606f99395a1b1d27ba1341b757b604f0025bfd2daac96b0b50174e562b2b4b pvm-worker.js 33418e2c81c117539569eb4cf91af4d058cdfae7dd4556b13f3687f6d6b3bae4 pvm-gpu-worker.js -488519d9d623e9586cc082d063fdaaec56adf88594a7c164b997ae6b5ef19c95 pvm-wasm-translated.js -0e9e36f1d253fc90d224ea46d02eba120a612cc18abfb11a9733d8dd87be625d pvm-runtime-core.js +a4c2a9ed4274c79b0c11ddbac163f1de200d41005ca1ce54909a5b8116d82c46 pvm-wasm-translated.js +37a3aae65994fb5c7ad660fbfad8fca774ecd165e8cfc2a982279c9571d21fb1 pvm-runtime-core.js 9c929f5d5c64a1b75e7e48485d7c3944ed6838112177ea778827a2c407c2d820 pvm-wasm-worker-entry.js diff --git a/rust/crates/pvm-runtime-assets/assets/pvm-runtime-core.js b/rust/crates/pvm-runtime-assets/assets/pvm-runtime-core.js index 9f8fb8c..3ad416b 100644 --- a/rust/crates/pvm-runtime-assets/assets/pvm-runtime-core.js +++ b/rust/crates/pvm-runtime-assets/assets/pvm-runtime-core.js @@ -599,6 +599,21 @@ globalThis.createPvmRuntime = (endpoint) => { ); } + function sendGpuCapabilities(bytes) { + if (!running || bytes.byteLength < 56 || bytes.byteLength > 4096) { + return; + } + if (translated) { + translated.setGpuCapabilities(bytes); + return; + } + stage(bytes); + check( + pvm.pvm_browser_set_gpu_capabilities(), + "update PolkaVM browser GPU capabilities" + ); + } + function sendGpuEvent(bytes) { if (!running || !pvm || !bytes.byteLength) { return; @@ -658,6 +673,14 @@ globalThis.createPvmRuntime = (endpoint) => { postMessage({ type: "error", message: error.message }); postMessage({ type: "terminated" }); } + } else if (message?.type === "gpu-capabilities") { + try { + sendGpuCapabilities(new Uint8Array(message.bytes)); + } catch (error) { + stopRuntime(); + postMessage({ type: "error", message: error.message }); + postMessage({ type: "terminated" }); + } } else if (message?.type === "gpu-event") { try { sendGpuEvent(new Uint8Array(message.bytes)); diff --git a/rust/crates/pvm-runtime-assets/assets/pvm-wasm-translated.js b/rust/crates/pvm-runtime-assets/assets/pvm-wasm-translated.js index ac74d7d..006d692 100644 --- a/rust/crates/pvm-runtime-assets/assets/pvm-wasm-translated.js +++ b/rust/crates/pvm-runtime-assets/assets/pvm-wasm-translated.js @@ -462,6 +462,18 @@ this.motionSample = bytes.slice(); } + setGpuCapabilities(bytes) { + if ( + this.stopped || + !(bytes instanceof Uint8Array) || + bytes.byteLength < 56 || + bytes.byteLength > 4096 + ) { + throw new Error("invalid translated WebGPU capabilities"); + } + this.gpuCapabilities = bytes.slice(); + } + sendGpuEvent(bytes) { if ( this.stopped || diff --git a/rust/crates/pvm-runtime-assets/assets/pvm-worker.js b/rust/crates/pvm-runtime-assets/assets/pvm-worker.js index 58b35d5..c32947d 100644 --- a/rust/crates/pvm-runtime-assets/assets/pvm-worker.js +++ b/rust/crates/pvm-runtime-assets/assets/pvm-worker.js @@ -462,6 +462,18 @@ this.motionSample = bytes.slice(); } + setGpuCapabilities(bytes) { + if ( + this.stopped || + !(bytes instanceof Uint8Array) || + bytes.byteLength < 56 || + bytes.byteLength > 4096 + ) { + throw new Error("invalid translated WebGPU capabilities"); + } + this.gpuCapabilities = bytes.slice(); + } + sendGpuEvent(bytes) { if ( this.stopped || @@ -2024,6 +2036,21 @@ globalThis.createPvmRuntime = (endpoint) => { ); } + function sendGpuCapabilities(bytes) { + if (!running || bytes.byteLength < 56 || bytes.byteLength > 4096) { + return; + } + if (translated) { + translated.setGpuCapabilities(bytes); + return; + } + stage(bytes); + check( + pvm.pvm_browser_set_gpu_capabilities(), + "update PolkaVM browser GPU capabilities" + ); + } + function sendGpuEvent(bytes) { if (!running || !pvm || !bytes.byteLength) { return; @@ -2083,6 +2110,14 @@ globalThis.createPvmRuntime = (endpoint) => { postMessage({ type: "error", message: error.message }); postMessage({ type: "terminated" }); } + } else if (message?.type === "gpu-capabilities") { + try { + sendGpuCapabilities(new Uint8Array(message.bytes)); + } catch (error) { + stopRuntime(); + postMessage({ type: "error", message: error.message }); + postMessage({ type: "terminated" }); + } } else if (message?.type === "gpu-event") { try { sendGpuEvent(new Uint8Array(message.bytes)); diff --git a/rust/crates/pvm-runtime-assets/src/lib.rs b/rust/crates/pvm-runtime-assets/src/lib.rs index 5c4c273..ae64a79 100644 --- a/rust/crates/pvm-runtime-assets/src/lib.rs +++ b/rust/crates/pvm-runtime-assets/src/lib.rs @@ -32,7 +32,7 @@ const ASSETS: [BrowserAsset; 7] = [ path: "pvm-worker.js", content_type: "text/javascript", bytes: include_bytes!("../assets/pvm-worker.js"), - sha256: "de3d1cd9dde09c407cf46ba9c642f3e7923e23bfb30db9eef06bf7c2b949b707", + sha256: "18606f99395a1b1d27ba1341b757b604f0025bfd2daac96b0b50174e562b2b4b", }, BrowserAsset { path: "pvm-gpu-worker.js", @@ -44,13 +44,13 @@ const ASSETS: [BrowserAsset; 7] = [ path: "pvm-wasm-translated.js", content_type: "text/javascript", bytes: include_bytes!("../assets/pvm-wasm-translated.js"), - sha256: "488519d9d623e9586cc082d063fdaaec56adf88594a7c164b997ae6b5ef19c95", + sha256: "a4c2a9ed4274c79b0c11ddbac163f1de200d41005ca1ce54909a5b8116d82c46", }, BrowserAsset { path: "pvm-runtime-core.js", content_type: "text/javascript", bytes: include_bytes!("../assets/pvm-runtime-core.js"), - sha256: "0e9e36f1d253fc90d224ea46d02eba120a612cc18abfb11a9733d8dd87be625d", + sha256: "37a3aae65994fb5c7ad660fbfad8fca774ecd165e8cfc2a982279c9571d21fb1", }, BrowserAsset { path: "pvm-wasm-worker-entry.js", @@ -62,7 +62,7 @@ const ASSETS: [BrowserAsset; 7] = [ path: "SHA256SUMS", content_type: "text/plain", bytes: include_bytes!("../assets/SHA256SUMS"), - sha256: "ca307d860dd1a7c08e8cbb8d81595f43fdf50e2a964c0cba8c51f60b46b4a469", + sha256: "69926edad64d5f0826cffc5aa85dde9a0133fd4648b3a87e32129744f69b28c6", }, ]; From 2b5d25c8f8d254df87afd1eda681b5bd65793046 Mon Sep 17 00:00:00 2001 From: w Date: Mon, 31 Aug 2026 15:34:39 -0400 Subject: [PATCH 2/2] fix(gpu): preserve resize updates during startup --- .../src/pvm-runtime-core.js | 23 ++++-- .../test/runtime-core.test.mjs | 72 +++++++++++++++++++ .../pvm-runtime-assets/assets/SHA256SUMS | 4 +- .../assets/pvm-runtime-core.js | 23 ++++-- .../pvm-runtime-assets/assets/pvm-worker.js | 23 ++++-- rust/crates/pvm-runtime-assets/src/lib.rs | 6 +- 6 files changed, 125 insertions(+), 26 deletions(-) diff --git a/js/packages/pvm-browser-runtime/src/pvm-runtime-core.js b/js/packages/pvm-browser-runtime/src/pvm-runtime-core.js index 3ad416b..6e62c5e 100644 --- a/js/packages/pvm-browser-runtime/src/pvm-runtime-core.js +++ b/js/packages/pvm-browser-runtime/src/pvm-runtime-core.js @@ -38,6 +38,7 @@ globalThis.createPvmRuntime = (endpoint) => { let disposed = false; let motionAvailability = 0; let pendingMotionSample = null; + let pendingGpuCapabilities = null; let timer; let startedAt = 0; let updateCount = 0; @@ -368,6 +369,10 @@ globalThis.createPvmRuntime = (endpoint) => { } const program = validateStartMessage(message); motionAvailability = message.motionAvailability ?? 0; + pendingGpuCapabilities = + message.gpuCapabilities instanceof ArrayBuffer + ? new Uint8Array(message.gpuCapabilities).slice() + : null; const bootStarted = performance.now(); let translationMs = 0; let compilationMs = 0; @@ -434,15 +439,14 @@ globalThis.createPvmRuntime = (endpoint) => { MAX_TRANSLATED_LOOPS_PER_UPDATE, message.audioEnabled, message.graphicsProfile, - message.gpuCapabilities instanceof ArrayBuffer - ? new Uint8Array(message.gpuCapabilities) - : null, + pendingGpuCapabilities, motionAvailability, ); if (pendingMotionSample !== null) { translated.sendMotionSample(pendingMotionSample); } translated.initialize(); + pendingGpuCapabilities = null; pendingMotionSample = null; backend = "compiler"; } catch (error) { @@ -493,16 +497,17 @@ globalThis.createPvmRuntime = (endpoint) => { pendingMotionSample = null; } if (message.graphicsProfile === "webgpu-raster") { - if (!(message.gpuCapabilities instanceof ArrayBuffer)) { + if (pendingGpuCapabilities === null) { throw new Error( "WebGPU capabilities are required before PVM initialization", ); } - stage(new Uint8Array(message.gpuCapabilities)); + stage(pendingGpuCapabilities); check( pvm.pvm_browser_set_gpu_capabilities(), "set PolkaVM browser GPU capabilities", ); + pendingGpuCapabilities = null; } postMessage({ type: "startup", stage: "interpreter-initializing" }); try { @@ -600,7 +605,11 @@ globalThis.createPvmRuntime = (endpoint) => { } function sendGpuCapabilities(bytes) { - if (!running || bytes.byteLength < 56 || bytes.byteLength > 4096) { + if (bytes.byteLength < 56 || bytes.byteLength > 4096) { + throw new Error("invalid PolkaVM browser GPU capabilities"); + } + if (!running || !pvm) { + pendingGpuCapabilities = bytes.slice(); return; } if (translated) { @@ -610,7 +619,7 @@ globalThis.createPvmRuntime = (endpoint) => { stage(bytes); check( pvm.pvm_browser_set_gpu_capabilities(), - "update PolkaVM browser GPU capabilities" + "update PolkaVM browser GPU capabilities", ); } diff --git a/js/packages/pvm-browser-runtime/test/runtime-core.test.mjs b/js/packages/pvm-browser-runtime/test/runtime-core.test.mjs index cf70791..e25614c 100644 --- a/js/packages/pvm-browser-runtime/test/runtime-core.test.mjs +++ b/js/packages/pvm-browser-runtime/test/runtime-core.test.mjs @@ -117,6 +117,23 @@ function motionResult(bytes) { }; } +function gpuCapabilities(surfaceGeneration) { + const bytes = new Uint8Array(56); + const view = new DataView(bytes.buffer); + bytes.set([0x45, 0x47, 0x43, 0x31]); + view.setUint16(4, 1, true); + view.setUint32(8, bytes.byteLength, true); + view.setUint16(12, 1, true); + view.setUint32(16, 640, true); + view.setUint32(20, 480, true); + view.setUint32(24, 640, true); + view.setUint32(28, 480, true); + view.setFloat32(32, 1, true); + view.setUint32(36, surfaceGeneration, true); + view.setUint32(40, 1, true); + return bytes; +} + test("browser runtime rejects unbounded launch inputs before compilation", async () => { for (const [message, expected] of [ [invalidStart({ program: new Uint8Array() }), /program must contain/], @@ -188,6 +205,61 @@ test("compiler backend enforces the declared graphics profile", async () => { await waitForMessage(messages, "terminated"); }); +test("compiler startup keeps the newest GPU capabilities", async () => { + const runtime = await readFile( + resolve(packageRoot, "dist/pvm-browser-runtime.wasm"), + ); + const program = await readFile( + resolve( + repositoryRoot, + "rust/crates/pvm-runtime/tests/fixtures/framebuffer-test.polkavm", + ), + ); + const Runtime = globalThis.TranslatedPvmRuntime; + let observedCapabilities; + globalThis.TranslatedPvmRuntime = class extends Runtime { + constructor(...args) { + observedCapabilities = new Uint8Array(args[6]); + super(...args); + } + }; + try { + const { messages, receiver } = endpoint(); + receiver.onmessage({ + data: { + type: "start", + runtime: bytesBuffer(runtime), + program: bytesBuffer(program), + assets: [], + graphicsProfile: "webgpu-raster", + gpuCapabilities: gpuCapabilities(1).buffer, + audioEnabled: false, + cacheKey: "gpu-capabilities-startup", + }, + }); + receiver.onmessage({ + data: { + type: "gpu-capabilities", + bytes: gpuCapabilities(2).buffer, + }, + }); + const ready = await waitForMessage(messages, "ready"); + assert.equal(ready.backend, "compiler"); + assert.equal( + new DataView( + observedCapabilities.buffer, + observedCapabilities.byteOffset, + observedCapabilities.byteLength, + ).getUint32(36, true), + 2, + ); + receiver.onmessage({ data: { type: "stop" } }); + await waitForMessage(messages, "terminated"); + } finally { + globalThis.TranslatedPvmRuntime = Runtime; + } +}); + test("native-Wasm and translated backends round-trip opaque TrUAPI frames", async () => { const runtime = await readFile( resolve(packageRoot, "dist/pvm-browser-runtime.wasm"), diff --git a/rust/crates/pvm-runtime-assets/assets/SHA256SUMS b/rust/crates/pvm-runtime-assets/assets/SHA256SUMS index 2aaba3d..cefe514 100644 --- a/rust/crates/pvm-runtime-assets/assets/SHA256SUMS +++ b/rust/crates/pvm-runtime-assets/assets/SHA256SUMS @@ -1,6 +1,6 @@ 3b448399a39ee571765f41266032c621ce3668176d7f0d6372c85d6068e7d4a5 pvm-browser-runtime.wasm -18606f99395a1b1d27ba1341b757b604f0025bfd2daac96b0b50174e562b2b4b pvm-worker.js +55ce96805e22f60ec9a4da072a316c34c1f650d99bdf1421805c1ba35c2d8161 pvm-worker.js 33418e2c81c117539569eb4cf91af4d058cdfae7dd4556b13f3687f6d6b3bae4 pvm-gpu-worker.js a4c2a9ed4274c79b0c11ddbac163f1de200d41005ca1ce54909a5b8116d82c46 pvm-wasm-translated.js -37a3aae65994fb5c7ad660fbfad8fca774ecd165e8cfc2a982279c9571d21fb1 pvm-runtime-core.js +79dce3ab925e78e9ef8e5df6e34fb2823e6f362cbc97d265a9ffdcc22cc24ed4 pvm-runtime-core.js 9c929f5d5c64a1b75e7e48485d7c3944ed6838112177ea778827a2c407c2d820 pvm-wasm-worker-entry.js diff --git a/rust/crates/pvm-runtime-assets/assets/pvm-runtime-core.js b/rust/crates/pvm-runtime-assets/assets/pvm-runtime-core.js index 3ad416b..6e62c5e 100644 --- a/rust/crates/pvm-runtime-assets/assets/pvm-runtime-core.js +++ b/rust/crates/pvm-runtime-assets/assets/pvm-runtime-core.js @@ -38,6 +38,7 @@ globalThis.createPvmRuntime = (endpoint) => { let disposed = false; let motionAvailability = 0; let pendingMotionSample = null; + let pendingGpuCapabilities = null; let timer; let startedAt = 0; let updateCount = 0; @@ -368,6 +369,10 @@ globalThis.createPvmRuntime = (endpoint) => { } const program = validateStartMessage(message); motionAvailability = message.motionAvailability ?? 0; + pendingGpuCapabilities = + message.gpuCapabilities instanceof ArrayBuffer + ? new Uint8Array(message.gpuCapabilities).slice() + : null; const bootStarted = performance.now(); let translationMs = 0; let compilationMs = 0; @@ -434,15 +439,14 @@ globalThis.createPvmRuntime = (endpoint) => { MAX_TRANSLATED_LOOPS_PER_UPDATE, message.audioEnabled, message.graphicsProfile, - message.gpuCapabilities instanceof ArrayBuffer - ? new Uint8Array(message.gpuCapabilities) - : null, + pendingGpuCapabilities, motionAvailability, ); if (pendingMotionSample !== null) { translated.sendMotionSample(pendingMotionSample); } translated.initialize(); + pendingGpuCapabilities = null; pendingMotionSample = null; backend = "compiler"; } catch (error) { @@ -493,16 +497,17 @@ globalThis.createPvmRuntime = (endpoint) => { pendingMotionSample = null; } if (message.graphicsProfile === "webgpu-raster") { - if (!(message.gpuCapabilities instanceof ArrayBuffer)) { + if (pendingGpuCapabilities === null) { throw new Error( "WebGPU capabilities are required before PVM initialization", ); } - stage(new Uint8Array(message.gpuCapabilities)); + stage(pendingGpuCapabilities); check( pvm.pvm_browser_set_gpu_capabilities(), "set PolkaVM browser GPU capabilities", ); + pendingGpuCapabilities = null; } postMessage({ type: "startup", stage: "interpreter-initializing" }); try { @@ -600,7 +605,11 @@ globalThis.createPvmRuntime = (endpoint) => { } function sendGpuCapabilities(bytes) { - if (!running || bytes.byteLength < 56 || bytes.byteLength > 4096) { + if (bytes.byteLength < 56 || bytes.byteLength > 4096) { + throw new Error("invalid PolkaVM browser GPU capabilities"); + } + if (!running || !pvm) { + pendingGpuCapabilities = bytes.slice(); return; } if (translated) { @@ -610,7 +619,7 @@ globalThis.createPvmRuntime = (endpoint) => { stage(bytes); check( pvm.pvm_browser_set_gpu_capabilities(), - "update PolkaVM browser GPU capabilities" + "update PolkaVM browser GPU capabilities", ); } diff --git a/rust/crates/pvm-runtime-assets/assets/pvm-worker.js b/rust/crates/pvm-runtime-assets/assets/pvm-worker.js index c32947d..3bebb86 100644 --- a/rust/crates/pvm-runtime-assets/assets/pvm-worker.js +++ b/rust/crates/pvm-runtime-assets/assets/pvm-worker.js @@ -1475,6 +1475,7 @@ globalThis.createPvmRuntime = (endpoint) => { let disposed = false; let motionAvailability = 0; let pendingMotionSample = null; + let pendingGpuCapabilities = null; let timer; let startedAt = 0; let updateCount = 0; @@ -1805,6 +1806,10 @@ globalThis.createPvmRuntime = (endpoint) => { } const program = validateStartMessage(message); motionAvailability = message.motionAvailability ?? 0; + pendingGpuCapabilities = + message.gpuCapabilities instanceof ArrayBuffer + ? new Uint8Array(message.gpuCapabilities).slice() + : null; const bootStarted = performance.now(); let translationMs = 0; let compilationMs = 0; @@ -1871,15 +1876,14 @@ globalThis.createPvmRuntime = (endpoint) => { MAX_TRANSLATED_LOOPS_PER_UPDATE, message.audioEnabled, message.graphicsProfile, - message.gpuCapabilities instanceof ArrayBuffer - ? new Uint8Array(message.gpuCapabilities) - : null, + pendingGpuCapabilities, motionAvailability, ); if (pendingMotionSample !== null) { translated.sendMotionSample(pendingMotionSample); } translated.initialize(); + pendingGpuCapabilities = null; pendingMotionSample = null; backend = "compiler"; } catch (error) { @@ -1930,16 +1934,17 @@ globalThis.createPvmRuntime = (endpoint) => { pendingMotionSample = null; } if (message.graphicsProfile === "webgpu-raster") { - if (!(message.gpuCapabilities instanceof ArrayBuffer)) { + if (pendingGpuCapabilities === null) { throw new Error( "WebGPU capabilities are required before PVM initialization", ); } - stage(new Uint8Array(message.gpuCapabilities)); + stage(pendingGpuCapabilities); check( pvm.pvm_browser_set_gpu_capabilities(), "set PolkaVM browser GPU capabilities", ); + pendingGpuCapabilities = null; } postMessage({ type: "startup", stage: "interpreter-initializing" }); try { @@ -2037,7 +2042,11 @@ globalThis.createPvmRuntime = (endpoint) => { } function sendGpuCapabilities(bytes) { - if (!running || bytes.byteLength < 56 || bytes.byteLength > 4096) { + if (bytes.byteLength < 56 || bytes.byteLength > 4096) { + throw new Error("invalid PolkaVM browser GPU capabilities"); + } + if (!running || !pvm) { + pendingGpuCapabilities = bytes.slice(); return; } if (translated) { @@ -2047,7 +2056,7 @@ globalThis.createPvmRuntime = (endpoint) => { stage(bytes); check( pvm.pvm_browser_set_gpu_capabilities(), - "update PolkaVM browser GPU capabilities" + "update PolkaVM browser GPU capabilities", ); } diff --git a/rust/crates/pvm-runtime-assets/src/lib.rs b/rust/crates/pvm-runtime-assets/src/lib.rs index ae64a79..de68743 100644 --- a/rust/crates/pvm-runtime-assets/src/lib.rs +++ b/rust/crates/pvm-runtime-assets/src/lib.rs @@ -32,7 +32,7 @@ const ASSETS: [BrowserAsset; 7] = [ path: "pvm-worker.js", content_type: "text/javascript", bytes: include_bytes!("../assets/pvm-worker.js"), - sha256: "18606f99395a1b1d27ba1341b757b604f0025bfd2daac96b0b50174e562b2b4b", + sha256: "55ce96805e22f60ec9a4da072a316c34c1f650d99bdf1421805c1ba35c2d8161", }, BrowserAsset { path: "pvm-gpu-worker.js", @@ -50,7 +50,7 @@ const ASSETS: [BrowserAsset; 7] = [ path: "pvm-runtime-core.js", content_type: "text/javascript", bytes: include_bytes!("../assets/pvm-runtime-core.js"), - sha256: "37a3aae65994fb5c7ad660fbfad8fca774ecd165e8cfc2a982279c9571d21fb1", + sha256: "79dce3ab925e78e9ef8e5df6e34fb2823e6f362cbc97d265a9ffdcc22cc24ed4", }, BrowserAsset { path: "pvm-wasm-worker-entry.js", @@ -62,7 +62,7 @@ const ASSETS: [BrowserAsset; 7] = [ path: "SHA256SUMS", content_type: "text/plain", bytes: include_bytes!("../assets/SHA256SUMS"), - sha256: "69926edad64d5f0826cffc5aa85dde9a0133fd4648b3a87e32129744f69b28c6", + sha256: "8e582ed7a2aca06918f2866e7977af85142333793c15c063d9a2c9b9432f7410", }, ];