Started work on wasm interface

This commit is contained in:
Maciej Samborski 2024-12-19 19:07:59 +01:00
parent 6d5222949c
commit 3e9bdcc469
18 changed files with 288 additions and 3 deletions

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="description" content="" /> <meta name="description" content="" />
<link rel="stylesheet" href="style.css"></link> <link rel="stylesheet" href="style.css"></link>
<script type="module" src="script.js" defer> var exports = {}; </script> <script type="module" src="src/js/script.js" defer> var exports = {}; </script>
</head> </head>
<body> <body>
<canvas id="game"></canvas> <canvas id="game"></canvas>

View File

@ -1,6 +1,7 @@
import { initializeContext, Vec2 } from "./common.js"; import { initializeContext, Vec2 } from "./common.js";
import { Graphics, fullscreenCanvas } from "./graphics.js"; import { Graphics, fullscreenCanvas } from "./graphics.js";
import * as drawing from "./draw.js"; import * as drawing from "./draw.js";
import * as wasm from "./wasm.js";
const vertexShader = `#version 300 es const vertexShader = `#version 300 es
in vec2 a_position; in vec2 a_position;
@ -48,7 +49,7 @@ function draw(gfx, dt, pos, velocity) {
} }
pos.add(velocity.multNew(dt)); pos.add(velocity.multNew(dt));
} }
(() => { (async () => {
const canvasId = "game"; const canvasId = "game";
const ctx = initializeContext(canvasId); const ctx = initializeContext(canvasId);
if (ctx === null) if (ctx === null)
@ -74,4 +75,5 @@ function draw(gfx, dt, pos, velocity) {
prevTimestamp = timestamp; prevTimestamp = timestamp;
window.requestAnimationFrame(frame); window.requestAnimationFrame(frame);
}); });
let env = await wasm.loadWasmModule("./src/wasm/module.wasm");
})(); })();

View File

@ -1,6 +1,7 @@
import { initializeContext, Vec2 } from "./common.js"; import { initializeContext, Vec2 } from "./common.js";
import { Graphics, fullscreenCanvas } from "./graphics.js"; import { Graphics, fullscreenCanvas } from "./graphics.js";
import * as drawing from "./draw.js"; import * as drawing from "./draw.js";
import * as wasm from "./wasm.js";
const vertexShader = const vertexShader =
`#version 300 es `#version 300 es
@ -61,7 +62,7 @@ function draw(gfx: Graphics, dt: number, pos: Vec2, velocity: Vec2) {
pos.add(velocity.multNew(dt)); pos.add(velocity.multNew(dt));
} }
(() => { (async () => {
const canvasId = "game"; const canvasId = "game";
const ctx = initializeContext(canvasId); const ctx = initializeContext(canvasId);
if (ctx === null) return; if (ctx === null) return;
@ -95,4 +96,6 @@ function draw(gfx: Graphics, dt: number, pos: Vec2, velocity: Vec2) {
prevTimestamp = timestamp; prevTimestamp = timestamp;
window.requestAnimationFrame(frame); window.requestAnimationFrame(frame);
}); });
let env: any = await wasm.loadWasmModule("./src/wasm/module.wasm");
})(); })();

63
src/js/wasm.js Normal file
View File

@ -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 };

97
src/js/wasm.ts Normal file
View File

@ -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<WebAssembly.Exports> {
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 }

10
src/wasm/build.sh Executable file
View File

@ -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

12
src/wasm/index.html Normal file
View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>aaa</title>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="description" content="" />
</head>
<body>
<script src="test.js"></script>
</body>
</html>

19
src/wasm/main.c Normal file
View File

@ -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;
}

BIN
src/wasm/module.wasm Executable file

Binary file not shown.

34
src/wasm/test.js Normal file
View File

@ -0,0 +1,34 @@
(async () => {
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;
}
}

22
src/wasm/wasmgl.c Normal file
View File

@ -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]);
}
}

23
src/wasm/wasmgl.h Normal file
View File

@ -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_