From 3e9bdcc46900a2150faaa428be99ee25b0409b80 Mon Sep 17 00:00:00 2001 From: Maciej Samborski Date: Thu, 19 Dec 2024 19:07:59 +0100 Subject: [PATCH] Started work on wasm interface --- index.html | 2 +- common.js => src/js/common.js | 0 common.ts => src/js/common.ts | 0 draw.js => src/js/draw.js | 0 draw.ts => src/js/draw.ts | 0 graphics.js => src/js/graphics.js | 0 graphics.ts => src/js/graphics.ts | 0 script.js => src/js/script.js | 4 +- script.ts => src/js/script.ts | 5 +- src/js/wasm.js | 63 +++++++++++++++++++ src/js/wasm.ts | 97 ++++++++++++++++++++++++++++++ src/wasm/build.sh | 10 +++ src/wasm/index.html | 12 ++++ src/wasm/main.c | 19 ++++++ src/wasm/module.wasm | Bin 0 -> 4195357 bytes src/wasm/test.js | 34 +++++++++++ src/wasm/wasmgl.c | 22 +++++++ src/wasm/wasmgl.h | 23 +++++++ 18 files changed, 288 insertions(+), 3 deletions(-) rename common.js => src/js/common.js (100%) rename common.ts => src/js/common.ts (100%) rename draw.js => src/js/draw.js (100%) rename draw.ts => src/js/draw.ts (100%) rename graphics.js => src/js/graphics.js (100%) rename graphics.ts => src/js/graphics.ts (100%) rename script.js => src/js/script.js (95%) rename script.ts => src/js/script.ts (95%) create mode 100644 src/js/wasm.js create mode 100644 src/js/wasm.ts create mode 100755 src/wasm/build.sh create mode 100644 src/wasm/index.html create mode 100644 src/wasm/main.c create mode 100755 src/wasm/module.wasm create mode 100644 src/wasm/test.js create mode 100644 src/wasm/wasmgl.c create mode 100644 src/wasm/wasmgl.h diff --git a/index.html b/index.html index 70a71c5..63c6b52 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@ - + diff --git a/common.js b/src/js/common.js similarity index 100% rename from common.js rename to src/js/common.js diff --git a/common.ts b/src/js/common.ts similarity index 100% rename from common.ts rename to src/js/common.ts diff --git a/draw.js b/src/js/draw.js similarity index 100% rename from draw.js rename to src/js/draw.js diff --git a/draw.ts b/src/js/draw.ts similarity index 100% rename from draw.ts rename to src/js/draw.ts diff --git a/graphics.js b/src/js/graphics.js similarity index 100% rename from graphics.js rename to src/js/graphics.js diff --git a/graphics.ts b/src/js/graphics.ts similarity index 100% rename from graphics.ts rename to src/js/graphics.ts diff --git a/script.js b/src/js/script.js similarity index 95% rename from script.js rename to src/js/script.js index e33ddf1..c3bb755 100644 --- a/script.js +++ b/src/js/script.js @@ -1,6 +1,7 @@ import { initializeContext, Vec2 } from "./common.js"; import { Graphics, fullscreenCanvas } from "./graphics.js"; import * as drawing from "./draw.js"; +import * as wasm from "./wasm.js"; const vertexShader = `#version 300 es in vec2 a_position; @@ -48,7 +49,7 @@ function draw(gfx, dt, pos, velocity) { } pos.add(velocity.multNew(dt)); } -(() => { +(async () => { const canvasId = "game"; const ctx = initializeContext(canvasId); if (ctx === null) @@ -74,4 +75,5 @@ function draw(gfx, dt, pos, velocity) { prevTimestamp = timestamp; window.requestAnimationFrame(frame); }); + let env = await wasm.loadWasmModule("./src/wasm/module.wasm"); })(); diff --git a/script.ts b/src/js/script.ts similarity index 95% rename from script.ts rename to src/js/script.ts index 7b8251a..9da7de3 100644 --- a/script.ts +++ b/src/js/script.ts @@ -1,6 +1,7 @@ import { initializeContext, Vec2 } from "./common.js"; import { Graphics, fullscreenCanvas } from "./graphics.js"; import * as drawing from "./draw.js"; +import * as wasm from "./wasm.js"; const vertexShader = `#version 300 es @@ -61,7 +62,7 @@ function draw(gfx: Graphics, dt: number, pos: Vec2, velocity: Vec2) { pos.add(velocity.multNew(dt)); } -(() => { +(async () => { const canvasId = "game"; const ctx = initializeContext(canvasId); if (ctx === null) return; @@ -95,4 +96,6 @@ function draw(gfx: Graphics, dt: number, pos: Vec2, velocity: Vec2) { prevTimestamp = timestamp; window.requestAnimationFrame(frame); }); + + let env: any = await wasm.loadWasmModule("./src/wasm/module.wasm"); })(); diff --git a/src/js/wasm.js b/src/js/wasm.js new file mode 100644 index 0000000..7a90e74 --- /dev/null +++ b/src/js/wasm.js @@ -0,0 +1,63 @@ +class WASMGLvalue { + ptr; + size; + constructor(ptr, size) { + this.ptr = ptr; + this.size = size; + } +} +async function loadWasmModule(path) { + let wasm = await WebAssembly.instantiateStreaming(fetch(path)); + const memSize = new Int32Array(wasm.instance.exports.memory.buffer, wasm.instance.exports.WASMGLmemory.value + 4, 1)[0]; + let memInt = new Int32Array(wasm.instance.exports.memory.buffer, wasm.instance.exports.WASMGLmemory.value, memSize); + let memFloat = new Float32Array(wasm.instance.exports.memory.buffer, wasm.instance.exports.WASMGLmemory.value, memSize); + wasm.instance.exports.WASMGLmain(); + const data = [ + 1.5, + 2.5, + 3.5, + 4.5, + 5.5, + 6.5, + 7.5, + 8.5, + ]; + let ptr = sendDataFloat(memFloat, data); + wasm.instance.exports.calc(ptr, data.length); + for (let i = 0; i < data.length; ++i) { + console.log(memFloat[ptr + i]); + } + return wasm.instance.exports; +} +function alloc(mem, size) { + const head = mem[2]; + mem[2] += size; + return head; +} +function allocFloat(mem, size) { + const head = mem[2]; + mem[2] += size; + return head; +} +function setstr(mem, ptr, size, str) { + for (let i = 0; i < size; i++) { + mem[ptr] = str.charCodeAt(i); + ++ptr; + } +} +function sendData(mem, data) { + let ptr = alloc(mem, data.length); + data.forEach((v, i) => { + mem[ptr + i] = v; + }); + return ptr; +} +function sendDataFloat(mem, data) { + let ptr = allocFloat(mem, data.length); + data.forEach((v, i) => { + mem[ptr + i] = v; + console.log(mem[ptr + i]); + }); + return ptr; +} +export { loadWasmModule, alloc, setstr }; diff --git a/src/js/wasm.ts b/src/js/wasm.ts new file mode 100644 index 0000000..f4b2e7a --- /dev/null +++ b/src/js/wasm.ts @@ -0,0 +1,97 @@ +class WASMGLvalue { + ptr: number; + size: number; + + constructor(ptr: number, size: number) { + this.ptr = ptr; + this.size = size; + } +} + +async function loadWasmModule(path: string): Promise { + let wasm: any = await WebAssembly.instantiateStreaming(fetch(path)); + + const memSize = new Int32Array( + wasm.instance.exports.memory.buffer, + wasm.instance.exports.WASMGLmemory.value + 4, + 1 + )[0]; + + let memInt = new Int32Array( + wasm.instance.exports.memory.buffer, + wasm.instance.exports.WASMGLmemory.value, + memSize + ); + + let memFloat = new Float32Array( + wasm.instance.exports.memory.buffer, + wasm.instance.exports.WASMGLmemory.value, + memSize + ); + + wasm.instance.exports.WASMGLmain(); + + const data = [ + 1.5, + 2.5, + 3.5, + 4.5, + 5.5, + 6.5, + 7.5, + 8.5, + ]; + + let ptr = sendDataFloat(memFloat, data); + wasm.instance.exports.calc(ptr, data.length); + + for (let i = 0; i < data.length; ++i) { + console.log(memFloat[ptr + i]); + } + + return wasm.instance.exports; +} + +function alloc(mem: Int32Array, size: number): number { + const head = mem[2]; + mem[2] += size; + + return head; +} + +function allocFloat(mem: Float32Array, size: number): number { + const head = mem[2]; + mem[2] += size; + + return head; +} + +function setstr(mem: Int32Array, ptr: number, size: number, str: string) { + for (let i = 0; i < size; i++) { + mem[ptr] = str.charCodeAt(i); + ++ptr; + } +} + +function sendData(mem: Int32Array, data: number[]): number { + let ptr = alloc(mem, data.length); + + data.forEach((v, i) => { + mem[ptr + i] = v; + }); + + return ptr; +} + +function sendDataFloat(mem: Float32Array, data: number[]): number { + let ptr = allocFloat(mem, data.length); + + data.forEach((v, i) => { + mem[ptr + i] = v; + console.log(mem[ptr + i]); + }); + + return ptr; +} + +export { loadWasmModule, alloc, setstr } diff --git a/src/wasm/build.sh b/src/wasm/build.sh new file mode 100755 index 0000000..e0b7f2e --- /dev/null +++ b/src/wasm/build.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -xe + +CC="clang" + +CLIBS="" +CFLAGS="--target=wasm32 -flto -Wl,--lto-O3 -nostdlib -Wl,--no-entry -Wl,--export-all" + +$CC $CFLAGS -o module.wasm *.c $CLIBS diff --git a/src/wasm/index.html b/src/wasm/index.html new file mode 100644 index 0000000..31716d2 --- /dev/null +++ b/src/wasm/index.html @@ -0,0 +1,12 @@ + + + + + aaa + + + + + + + diff --git a/src/wasm/main.c b/src/wasm/main.c new file mode 100644 index 0000000..94a50d0 --- /dev/null +++ b/src/wasm/main.c @@ -0,0 +1,19 @@ +#include "wasmgl.h" + +int WASMGLmemory[WASMGLmemory_size] = { + [MEM_SIZE] = WASMGLmemory_size, + [MEM_HEAD] = MEM_ELEM_COUNT, + 0, +}; + +void calc(WASMGLvalue(0)) +{ + for (int i = 0; i < size_0; ++i) + WASMGLmemory[ptr_0 + i] = ((float) WASMGLmemory[ptr_0 + i]) * 2.0; +} + +int main(void) +{ + + return 0; +} diff --git a/src/wasm/module.wasm b/src/wasm/module.wasm new file mode 100755 index 0000000000000000000000000000000000000000..a05c526d430717f940e48f6caa712e47c7b0cd3f GIT binary patch literal 4195357 zcmeFwv2Gki7y#he*|mM~o+U@3a6z##6mDoON^eAjkVr*Axjvsyan5HS_zs0gNOwgF zijv8;A>$|5}7eO_;hc6b<{<$GbPPo8{f>7#?@st8}bxI$12b>3Vs$3ZY8LG!*+^w_iQ~{L7ok%i9pg4@qBE z7H`v3wVa0X(XhIjtwZ&&l;YL;F6@lE?sB#4t|qsai&+`>Q#x5sy4mezS=L>*T2H3e z-D3HwtkTXQyL$QJs@yr~x)+P(#bnW4OjfgUH*LO}O}-hjz0{}Aa-UJ!I^1Vie3Uw^ zCl`y^knZpQS?Lx3YGRwRDxQ^RO+1NJ9!6iZ z#kbE6ig*_L$+S1E%-gt5Un4b{pTzL{AD^X9ntx}%9G5>oB!9KjX9uAve|-|hMcw9C ze*Yw-AeZGX?^@0CDbifuyDjGF5aUqSbrsrBKP`&Q{~oySlTMi``tUe3A*DGUr8a#~ z)t|oCq8#pA4tFk_n2XDNo-~Zo&E`3%(uwMyig%UG^>Oua57$(=!-wgS)Q-|4b@(7X z%F}q*RM~Lc8&=7$(b?<6%k$&YHf*}%^S^G}z8+0~t`zh5 z_i@OShttclm{nEEp?40%7qbTprB_c^TExM { + let instance = await WebAssembly.instantiateStreaming(fetch("module.wasm")); + const memSize = new Int32Array( + instance.instance.exports.memory.buffer, + instance.instance.exports.WASMGLmemory.value + 4, + 1 + )[0] + + let mem = new Int32Array( + instance.instance.exports.memory.buffer, + instance.instance.exports.WASMGLmemory.value, + memSize + ); + + let ptr = alloc(mem, 4); + setstr(mem, ptr, 4, "game"); + + console.log(String.fromCharCode(instance.instance.exports.initialize(ptr, 4))); +})(); + +function alloc(mem, size) { + const head = mem[2]; + console.log(head); + mem[2] += size; + + return head; +} + +function setstr(mem, ptr, size, str) { + for (let i = 0; i < size; i++) { + mem[ptr] = str.charCodeAt(i); + ++ptr; + } +} diff --git a/src/wasm/wasmgl.c b/src/wasm/wasmgl.c new file mode 100644 index 0000000..2a383de --- /dev/null +++ b/src/wasm/wasmgl.c @@ -0,0 +1,22 @@ +#include "wasmgl.h" + +WASMGLptr WASMGLmalloc(int * mem, WASMGLsize size) +{ + WASMGLptr ptr = mem[MEM_HEAD]; + mem[MEM_HEAD] += size; + + return ptr; +} + +void WASMGLset(int * mem, WASMGLptr ptr, int value) +{ + mem[ptr] = value; +} + +void WASMGLsetstr(int * mem, WASMGLptr ptr, const char * cstr, WASMGLsize size) +{ + for (int i = 0; i < size; ++i) + { + WASMGLset(mem, ptr + i, cstr[i]); + } +} diff --git a/src/wasm/wasmgl.h b/src/wasm/wasmgl.h new file mode 100644 index 0000000..35f8c66 --- /dev/null +++ b/src/wasm/wasmgl.h @@ -0,0 +1,23 @@ +#ifndef WASMGL_H_ +#define WASMGL_H_ + +#define main WASMGLmain + +#define WASMGLmemory_size (1024 * 1024) + +typedef enum { + MEM_NULL = 0, + MEM_SIZE = 1, + MEM_HEAD, + MEM_ELEM_COUNT, +} WASMGLmemory_layout; + +typedef unsigned int WASMGLptr; +typedef unsigned int WASMGLsize; + +#define WASMGLvalue(n) WASMGLptr ptr_##n, WASMGLsize size_##n + +WASMGLptr WASMGLmalloc(int * mem, WASMGLsize size); +void WASMGLset(int * mem, WASMGLptr ptr, int value); +void WASMGLsetstr(int * mem, WASMGLptr ptr, const char * cstr, WASMGLsize size); +#endif // WASMGL_H_