Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ members = [
]

[workspace.package]
version = "0.1.1"
version = "0.1.2"
edition = "2021"
license = "MPL-2.0"
repository = "https://github.com/paritytech/pvm-host-runtime"
Expand Down
2 changes: 1 addition & 1 deletion js/packages/pvm-browser-runtime/SOURCE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PolkaVM App v2 browser runtime
Source repository: https://github.com/paritytech/pvm-host-runtime
Release tag: v0.1.1
Release tag: v0.1.2
Rust crate: rust/crates/pvm-runtime
GPU wire crate: rust/crates/pvm-gpu-wire
PolkaVM native revision: e06cce9da5c6d3f72458168876ea304e27992094
Expand Down
2 changes: 1 addition & 1 deletion js/packages/pvm-browser-runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@parity/pvm-browser-runtime",
"version": "0.1.1",
"version": "0.1.2",
"description": "Host-neutral PolkaVM App v2 browser runtime artifacts",
"license": "MPL-2.0",
"type": "module",
Expand Down
37 changes: 37 additions & 0 deletions js/packages/pvm-browser-runtime/src/pvm-runtime-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,18 @@ globalThis.createPvmRuntime = endpoint => {
}
}

function drainTruapiRequests() {
while (pvm.pvm_browser_take_truapi_request?.()) {
const length = pvm.pvm_browser_truapi_request_length();
const bytes = new Uint8Array(
pvm.memory.buffer,
pvm.pvm_browser_truapi_request_pointer(),
length
).slice();
postMessage({ type: "truapi-request", bytes }, [bytes.buffer]);
}
}

function drainAudio() {
while (pvm.pvm_browser_take_audio()) {
const sampleRate = pvm.pvm_browser_audio_sample_rate();
Expand Down Expand Up @@ -199,6 +211,7 @@ globalThis.createPvmRuntime = endpoint => {
drainFrame();
drainTri2d();
drainGpuBatches();
drainTruapiRequests();
drainAudio();
drainSave();
drainLogs();
Expand Down Expand Up @@ -472,6 +485,7 @@ globalThis.createPvmRuntime = endpoint => {
postMessage({ type: "startup", stage: "interpreter-initialized" });
drainTri2d();
drainGpuBatches();
drainTruapiRequests();
drainLogs();
}
startedAt = performance.now();
Expand Down Expand Up @@ -523,6 +537,21 @@ globalThis.createPvmRuntime = endpoint => {
check(pvm.pvm_browser_send_gpu_event(), "send PolkaVM browser GPU event");
}

function sendTruapiResponse(bytes) {
if (!running || !pvm || !bytes.byteLength) {
return;
}
if (translated) {
translated.sendTruapiResponse(bytes);
return;
}
stage(bytes);
check(
pvm.pvm_browser_send_truapi_response(),
"send PolkaVM browser TrUAPI response"
);
}

endpoint.onmessage = event => {
const message = event.data;
if (message?.type === "start") {
Expand All @@ -547,6 +576,14 @@ globalThis.createPvmRuntime = endpoint => {
postMessage({ type: "error", message: error.message });
postMessage({ type: "terminated" });
}
} else if (message?.type === "truapi-response") {
try {
sendTruapiResponse(new Uint8Array(message.bytes));
} catch (error) {
stopRuntime();
postMessage({ type: "error", message: error.message });
postMessage({ type: "terminated" });
}
} else if (message?.type === "stop") {
stopRuntime();
postMessage({ type: "terminated" });
Expand Down
72 changes: 72 additions & 0 deletions js/packages/pvm-browser-runtime/src/pvm-wasm-translated.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
const MAX_GPU_EVENT_BYTES = 64 * 1024;
const MAX_GPU_EVENTS = 256;
const MAX_GPU_SUBMITS_PER_UPDATE = 8;
const MAX_TRUAPI_FRAME_BYTES = 1024 * 1024;
const MAX_TRUAPI_FRAMES = 32;
const MAX_TRUAPI_QUEUE_BYTES = 4 * 1024 * 1024;
const MAX_GPU_COMMANDS = 16_384;
const GPU_ERROR_MALFORMED_BATCH = -2;
const GPU_ERROR_QUOTA_EXCEEDED = -3;
Expand Down Expand Up @@ -258,6 +261,10 @@
this.gpuEvents = [];
this.gpuSubmits = 0;
this.gpuLastSequence = 0n;
this.truapiRequests = 0;
this.truapiRequestBytes = 0;
this.truapiResponses = [];
this.truapiResponseBytes = 0;
this.tri2dSubmitted = false;
this.maxGas = BigInt(maxGas);
this.input = [];
Expand Down Expand Up @@ -310,6 +317,8 @@
}
this.timeMs = timeMs;
this.gpuSubmits = 0;
this.truapiRequests = 0;
this.truapiRequestBytes = 0;
this.#resetBudget(
this.coreVm && !this.coreVmStarted
? MAX_HOSTCALLS_PER_INIT
Expand Down Expand Up @@ -400,11 +409,34 @@
this.gpuEvents.push(bytes.slice());
}

sendTruapiResponse(bytes) {
if (
this.stopped ||
!(bytes instanceof Uint8Array) ||
!bytes.byteLength ||
bytes.byteLength > MAX_TRUAPI_FRAME_BYTES
) {
throw new Error("invalid translated TrUAPI response");
}
if (
this.truapiResponses.length === MAX_TRUAPI_FRAMES ||
this.truapiResponseBytes + bytes.byteLength > MAX_TRUAPI_QUEUE_BYTES
) {
throw new Error("translated TrUAPI response queue overflow");
}
this.truapiResponses.push(bytes.slice());
this.truapiResponseBytes += bytes.byteLength;
}

stop() {
this.stopped = true;
this.input.length = 0;
this.coreInput.length = 0;
this.truapiRequests = 0;
this.truapiRequestBytes = 0;
this.gpuEvents.length = 0;
this.truapiResponses.length = 0;
this.truapiResponseBytes = 0;
}

#resetBudget(hostcalls) {
Expand Down Expand Up @@ -764,6 +796,43 @@
this.#setReg(7, 0n);
return false;
}
case "host_truapi_send": {
const length = this.#u32(a1);
if (!length || length > MAX_TRUAPI_FRAME_BYTES) {
this.#setReg(7, 1n);
return false;
}
if (
this.truapiRequests === MAX_TRUAPI_FRAMES ||
this.truapiRequestBytes + length > MAX_TRUAPI_QUEUE_BYTES
) {
this.#setReg(7, 2n);
return false;
}
const bytes = this.#read(this.#u32(a0), length);
this.emit({ type: "truapi-request", bytes }, [bytes.buffer]);
this.truapiRequests++;
this.truapiRequestBytes += length;
this.#setReg(7, 0n);
return false;
}
case "host_truapi_poll": {
const response = this.truapiResponses[0];
if (response === undefined) {
this.#setReg(7, 0n);
return false;
}
const capacity = this.#u32(a1);
if (capacity < response.byteLength) {
this.#setReg(7, BigInt(-response.byteLength));
return false;
}
this.#write(this.#u32(a0), response);
this.truapiResponses.shift();
this.truapiResponseBytes -= response.byteLength;
this.#setReg(7, BigInt(response.byteLength));
return false;
}
case "host_asset_read": {
const nameLength = this.#u32(a1);
const offset = this.#u32(a2);
Expand Down Expand Up @@ -918,6 +987,9 @@
// eslint-disable-next-line complexity -- Flat hostcall dispatch mirrors the guest ABI.
#handleCoreVmCall(name) {
switch (name) {
case "host_truapi_send":
case "host_truapi_poll":
return this.#handleCooperativeCall(name);
case "pvm_set_palette": {
const palette = this.#read(this.#u32(this.#reg(7)), 256 * 3);
for (let index = 0; index < 256; index++) {
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "pvm-host-runtime-workspace",
"private": true,
"version": "0.1.1",
"version": "0.1.2",
"description": "Host-neutral PolkaVM application runtime workspace",
"license": "MPL-2.0",
"type": "module",
Expand Down
4 changes: 2 additions & 2 deletions rust/crates/pvm-assets-export/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
name = "pvm-assets-export"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
description = "Exports host-neutral PolkaVM browser runtime assets"
license = "MPL-2.0"
repository = "https://github.com/paritytech/pvm-host-runtime"
publish = false

[dependencies]
pvm-runtime-assets = { version = "0.1.1", path = "../pvm-runtime-assets" }
pvm-runtime-assets = { version = "0.1.2", path = "../pvm-runtime-assets" }
2 changes: 1 addition & 1 deletion rust/crates/pvm-gpu-wire/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pvm-gpu-wire"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
description = "Bounded host-neutral WebGPU Raster wire protocol for PolkaVM applications"
license = "MPL-2.0"
Expand Down
2 changes: 1 addition & 1 deletion rust/crates/pvm-runtime-assets/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pvm-runtime-assets"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
description = "Source-built browser assets for the host-neutral PolkaVM runtime"
license = "MPL-2.0"
Expand Down
8 changes: 4 additions & 4 deletions rust/crates/pvm-runtime-assets/assets/SHA256SUMS
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
182c471bd62e3279abe996f33d8e9ccfded4de7e6b4a18470cad1e67f1e074f3 pvm-browser-runtime.wasm
c25dbaef94f91dcdfe33185fc58485fdc128c5f9edde11daa23f94fdb6464d18 pvm-worker.js
df0d64ed4a028693c680380990c6f2b84dae096373d15f716d7c6ad96fe45041 pvm-browser-runtime.wasm
921d6c3b06be34ad39a57ae9ae612e37840338e58b7e83a2f81bbea9a12c6ff1 pvm-worker.js
33418e2c81c117539569eb4cf91af4d058cdfae7dd4556b13f3687f6d6b3bae4 pvm-gpu-worker.js
865bfe48c8e01c18a93d40f868afd8b21e2be2ec84e0c993faa54470480abd3c pvm-wasm-translated.js
51891fa4bd0a513dd7ad14b82c4a9f6cbb880755f93612fa4d4ebecd1bcc8dcb pvm-runtime-core.js
17e52fff13b7f5e6732c6290c11e133869cda46b64d4fd09c6089972b9f36904 pvm-wasm-translated.js
f527c1f530ce326e4d40840a5c0456dc9dad5798818038c8f0fe865040742c50 pvm-runtime-core.js
9c929f5d5c64a1b75e7e48485d7c3944ed6838112177ea778827a2c407c2d820 pvm-wasm-worker-entry.js
Binary file modified rust/crates/pvm-runtime-assets/assets/pvm-browser-runtime.wasm
Binary file not shown.
37 changes: 37 additions & 0 deletions rust/crates/pvm-runtime-assets/assets/pvm-runtime-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,18 @@ globalThis.createPvmRuntime = endpoint => {
}
}

function drainTruapiRequests() {
while (pvm.pvm_browser_take_truapi_request?.()) {
const length = pvm.pvm_browser_truapi_request_length();
const bytes = new Uint8Array(
pvm.memory.buffer,
pvm.pvm_browser_truapi_request_pointer(),
length
).slice();
postMessage({ type: "truapi-request", bytes }, [bytes.buffer]);
}
}

function drainAudio() {
while (pvm.pvm_browser_take_audio()) {
const sampleRate = pvm.pvm_browser_audio_sample_rate();
Expand Down Expand Up @@ -199,6 +211,7 @@ globalThis.createPvmRuntime = endpoint => {
drainFrame();
drainTri2d();
drainGpuBatches();
drainTruapiRequests();
drainAudio();
drainSave();
drainLogs();
Expand Down Expand Up @@ -472,6 +485,7 @@ globalThis.createPvmRuntime = endpoint => {
postMessage({ type: "startup", stage: "interpreter-initialized" });
drainTri2d();
drainGpuBatches();
drainTruapiRequests();
drainLogs();
}
startedAt = performance.now();
Expand Down Expand Up @@ -523,6 +537,21 @@ globalThis.createPvmRuntime = endpoint => {
check(pvm.pvm_browser_send_gpu_event(), "send PolkaVM browser GPU event");
}

function sendTruapiResponse(bytes) {
if (!running || !pvm || !bytes.byteLength) {
return;
}
if (translated) {
translated.sendTruapiResponse(bytes);
return;
}
stage(bytes);
check(
pvm.pvm_browser_send_truapi_response(),
"send PolkaVM browser TrUAPI response"
);
}

endpoint.onmessage = event => {
const message = event.data;
if (message?.type === "start") {
Expand All @@ -547,6 +576,14 @@ globalThis.createPvmRuntime = endpoint => {
postMessage({ type: "error", message: error.message });
postMessage({ type: "terminated" });
}
} else if (message?.type === "truapi-response") {
try {
sendTruapiResponse(new Uint8Array(message.bytes));
} catch (error) {
stopRuntime();
postMessage({ type: "error", message: error.message });
postMessage({ type: "terminated" });
}
} else if (message?.type === "stop") {
stopRuntime();
postMessage({ type: "terminated" });
Expand Down
Loading
Loading