base: wasm fixes

This commit is contained in:
luboslenco
2026-10-01 15:59:44 +02:00
parent d730b2f09d
commit 70f2cac3a9
5 changed files with 107 additions and 37 deletions
+17 -9
View File
@@ -180,17 +180,22 @@ function id_to_filter_mode(id) {
return "linear";
}
async function init() {
let wasm_bytes = null;
await fetch("./start.wasm").then(res => res.arrayBuffer()).then(buffer => wasm_bytes = new Uint8Array(buffer));
memory = new WebAssembly.Memory({initial : 10240, maximum : 10240, shared : true}); // * 65536 = 671088640 (amake --initial-memory)
function update_heap_views() {
heapu8 = new Uint8Array(memory.buffer);
heapu16 = new Uint16Array(memory.buffer);
heapu32 = new Uint32Array(memory.buffer);
heapi32 = new Int32Array(memory.buffer);
heapf32 = new Float32Array(memory.buffer);
heapf64 = new Float64Array(memory.buffer);
}
async function init() {
let wasm_bytes = null;
await fetch("./start.wasm").then(res => res.arrayBuffer()).then(buffer => wasm_bytes = new Uint8Array(buffer));
// * 65536 = amake --initial-memory=268435456, --max-memory=4294967296, malloc grows it
memory = new WebAssembly.Memory({initial : 4096, maximum : 65536, shared : true});
update_heap_views();
if (!navigator.gpu) {
throw new Error('WebGPU not supported');
@@ -716,6 +721,9 @@ async function init() {
surface.configure(config);
},
js_memory_grow : function() {
update_heap_views();
},
js_printf : function(format) {
console.log(read_string(format));
},
@@ -775,8 +783,8 @@ async function init() {
js_time : function() {
return window.performance.now();
},
js_pow : function(x) {
return Math.pow(x);
js_pow : function(base, exponent) {
return Math.pow(base, exponent);
},
js_sin : function(x) {
return Math.sin(x);
@@ -787,8 +795,8 @@ async function init() {
js_tan : function(x) {
return Math.tan(x);
},
js_log : function(base, exponent) {
return Math.log(base, exponent);
js_log : function(x) {
return Math.log(x);
},
js_exp : function(x) {
return Math.exp(x);
+15 -10
View File
@@ -355,6 +355,11 @@ iron_a1_sound_t *iron_a1_sound_create_from_bytes(uint8_t *filedata, int filedata
if (strncmp(format, ".ogg", 4) == 0) {
int channels, sample_rate;
int samples = stb_vorbis_decode_memory(filedata, (int)filedata_size, &channels, &sample_rate, (short **)&data);
if (samples <= 0) {
free(data);
sound->in_use = false;
return NULL;
}
sound->channel_count = (uint8_t)channels;
sound->samples_per_second = (uint32_t)sample_rate;
sound->size = samples * 2 * sound->channel_count;
@@ -571,48 +576,48 @@ float *iron_a1_sound_stream_next_frame(iron_a1_sound_stream_t *stream) {
return stream->samples;
}
static iron_mutex_t mutex;
static iron_mutex_t a2_mutex;
static void (*a2_callback)(iron_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL;
static void *a2_userdata = NULL;
void iron_a2_set_callback(void (*iron_a2_audio_callback)(iron_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) {
iron_mutex_lock(&mutex);
iron_mutex_lock(&a2_mutex);
a2_callback = iron_a2_audio_callback;
a2_userdata = userdata;
iron_mutex_unlock(&mutex);
iron_mutex_unlock(&a2_mutex);
}
static void (*a2_sample_rate_callback)(void *userdata) = NULL;
static void *a2_sample_rate_userdata = NULL;
void iron_a2_set_sample_rate_callback(void (*iron_a2_sample_rate_callback)(void *userdata), void *userdata) {
iron_mutex_lock(&mutex);
iron_mutex_lock(&a2_mutex);
a2_sample_rate_callback = iron_a2_sample_rate_callback;
a2_sample_rate_userdata = userdata;
iron_mutex_unlock(&mutex);
iron_mutex_unlock(&a2_mutex);
}
void iron_a2_internal_init(void) {
iron_mutex_init(&mutex);
iron_mutex_init(&a2_mutex);
}
bool iron_a2_internal_callback(iron_a2_buffer_t *buffer, int samples) {
iron_mutex_lock(&mutex);
iron_mutex_lock(&a2_mutex);
bool has_callback = a2_callback != NULL;
if (has_callback) {
a2_callback(buffer, samples, a2_userdata);
}
iron_mutex_unlock(&mutex);
iron_mutex_unlock(&a2_mutex);
return has_callback;
}
void iron_a2_internal_sample_rate_callback(void) {
iron_mutex_lock(&mutex);
iron_mutex_lock(&a2_mutex);
if (a2_sample_rate_callback != NULL) {
a2_sample_rate_callback(a2_sample_rate_userdata);
}
iron_mutex_unlock(&mutex);
iron_mutex_unlock(&a2_mutex);
}
#endif
+40 -14
View File
@@ -1,17 +1,17 @@
#include "math.h"
#ifdef IRON_WASM
__attribute__((import_module("imports"), import_name("js_pow"))) float js_pow(float base, float exponent);
__attribute__((import_module("imports"), import_name("js_sin"))) float js_sin(float x);
__attribute__((import_module("imports"), import_name("js_cos"))) float js_cos(float x);
__attribute__((import_module("imports"), import_name("js_tan"))) float js_tan(float x);
__attribute__((import_module("imports"), import_name("js_log"))) float js_log(float x);
__attribute__((import_module("imports"), import_name("js_exp"))) float js_exp(float x);
__attribute__((import_module("imports"), import_name("js_sqrt"))) float js_sqrt(float x);
__attribute__((import_module("imports"), import_name("js_acos"))) float js_acos(float x);
__attribute__((import_module("imports"), import_name("js_asin"))) float js_asin(float x);
__attribute__((import_module("imports"), import_name("js_atan"))) float js_atan(float x);
__attribute__((import_module("imports"), import_name("js_atan2"))) float js_atan2(float x, float y);
__attribute__((import_module("imports"), import_name("js_pow"))) double js_pow(double base, double exponent);
__attribute__((import_module("imports"), import_name("js_sin"))) double js_sin(double x);
__attribute__((import_module("imports"), import_name("js_cos"))) double js_cos(double x);
__attribute__((import_module("imports"), import_name("js_tan"))) double js_tan(double x);
__attribute__((import_module("imports"), import_name("js_log"))) double js_log(double x);
__attribute__((import_module("imports"), import_name("js_exp"))) double js_exp(double x);
__attribute__((import_module("imports"), import_name("js_sqrt"))) double js_sqrt(double x);
__attribute__((import_module("imports"), import_name("js_acos"))) double js_acos(double x);
__attribute__((import_module("imports"), import_name("js_asin"))) double js_asin(double x);
__attribute__((import_module("imports"), import_name("js_atan"))) double js_atan(double x);
__attribute__((import_module("imports"), import_name("js_atan2"))) double js_atan2(double x, double y);
#endif
double fabs(double n) {
@@ -38,8 +38,25 @@ float fminf(float x, float y) {
return x < y ? x : y;
}
static double exp2_int(int exp) {
union {
double d;
unsigned long long u;
} v;
v.u = (unsigned long long)(exp + 1023) << 52;
return v.d;
}
double ldexp(double x, int exp) {
return x * pow(2.0, exp);
while (exp > 1023) {
x *= exp2_int(1023);
exp -= 1023;
}
while (exp < -1022) {
x *= exp2_int(-1022);
exp += 1022;
}
return x * exp2_int(exp);
}
double pow(double base, double exponent) {
@@ -224,7 +241,14 @@ float expf(float x) {
}
double exp2(double x) {
return pow(2.0, x);
#ifdef IRON_WASM
return js_pow(2.0, x);
#endif
double r = 1.0;
int n = (int)x;
for (int i = 0; i < n; i++)
r *= 2.0;
return r;
}
float exp2f(float x) {
@@ -236,6 +260,8 @@ double frexp(double x, int *exp) {
*exp = 0;
return 0.0;
}
double sign = x < 0.0 ? -1.0 : 1.0;
x *= sign;
*exp = 0;
while (x >= 1.0) {
x /= 2.0;
@@ -245,7 +271,7 @@ double frexp(double x, int *exp) {
x *= 2.0;
(*exp)--;
}
return x;
return x * sign;
}
float frexpf(float x, int *exp) {
+34 -3
View File
@@ -1,5 +1,6 @@
#include "stdlib.h"
#include "ctype.h"
#include "stdbool.h"
#include "stddef.h"
#include "stdio.h"
#include "string.h"
@@ -7,9 +8,36 @@
#define ALIGNMENT 8
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
#ifdef IRON_WASM
__attribute__((import_module("imports"), import_name("js_memory_grow"))) void js_memory_grow(void);
extern unsigned char __heap_base;
#define heap (&__heap_base)
#define WASM_PAGE_SIZE 65536ULL
#define HEAP_GROW_PAGES 1024 // 64MB steps
static bool heap_reserve(unsigned long long end) {
unsigned long long size = __builtin_wasm_memory_size(0) * WASM_PAGE_SIZE - (size_t)heap;
if (end <= size) {
return true;
}
size_t pages = (size_t)((end - size + WASM_PAGE_SIZE - 1) / WASM_PAGE_SIZE);
if (__builtin_wasm_memory_grow(0, pages < HEAP_GROW_PAGES ? HEAP_GROW_PAGES : pages) == (size_t)-1 &&
__builtin_wasm_memory_grow(0, pages) == (size_t)-1) {
return false;
}
js_memory_grow();
return true;
}
#else
#define HEAP_SIZE 1024 * 1024 * 512
static unsigned char heap[HEAP_SIZE] __attribute__((aligned(ALIGNMENT)));
static size_t heap_top = ALIGNMENT;
static bool heap_reserve(unsigned long long end) {
return end <= HEAP_SIZE;
}
#endif
static size_t heap_top = ALIGNMENT;
typedef struct block {
size_t size;
@@ -21,6 +49,9 @@ static block_t *free_list = NULL;
__attribute__((export_name("wasm_malloc")))
#endif
void *malloc(size_t size) {
if (size > (size_t)-1 - ALIGNMENT) {
return NULL;
}
size = ALIGN(size);
block_t **link = &free_list;
block_t *curr = free_list;
@@ -41,8 +72,8 @@ void *malloc(size_t size) {
link = &curr->next;
curr = curr->next;
}
if (heap_top + sizeof(block_t) + size > HEAP_SIZE) {
printf("malloc: out of memory");
if (!heap_reserve((unsigned long long)heap_top + sizeof(block_t) + size)) {
printf("malloc: out of memory (%u bytes requested)\n", (unsigned)size);
return NULL;
}
block_t *ptr = (block_t *)&heap[heap_top];
+1 -1
View File
@@ -1548,7 +1548,7 @@ void export_solution(project_t *project) {
char *compiler = "clang --target=wasm32 -nostdlib -matomics -mbulk-memory";
char *linker =
"--target=wasm32 -nostdlib -matomics -mbulk-memory "
"\"-Wl,--import-memory,--shared-memory,--allow-undefined,--no-entry,--initial-memory=671088640,--max-memory=671088640,-z,stack-size=256000\"";
"\"-Wl,--import-memory,--shared-memory,--allow-undefined,--no-entry,--initial-memory=268435456,--max-memory=4294967296,-z,stack-size=256000\"";
if (!goptions.debug) {
linker = string("%s -Wl,--strip-all", linker);
}