wip bytebox integration

This commit is contained in:
Reuben Dunnington 2023-07-31 19:57:16 -07:00
parent a658e714c3
commit 3f2ed41bfc
Signed by: rdunnington
GPG Key ID: 4EC5290E704FD482
10 changed files with 560 additions and 124 deletions

View File

@ -33,30 +33,30 @@ if %target% == orca (
copy milepost\bin\milepost.dll.lib bin
::generate wasm3 api bindings
python3 scripts\bindgen.py core src\core_api.json^
python3 scripts\bindgen_bb.py core src\core_api.json^
--wasm3-bindings src\core_api_bind_gen.c
python3 scripts\bindgen.py gles src\gles_api.json^
python3 scripts\bindgen_bb.py gles src\gles_api.json^
--wasm3-bindings src\gles_api_bind_gen.c
python3 scripts\bindgen.py canvas src\canvas_api.json^
python3 scripts\bindgen_bb.py canvas src\canvas_api.json^
--guest-stubs sdk\orca_surface.c^
--guest-include graphics.h^
--wasm3-bindings src\canvas_api_bind_gen.c
python3 scripts\bindgen.py clock src\clock_api.json^
python3 scripts\bindgen_bb.py clock src\clock_api.json^
--guest-stubs sdk\orca_clock.c^
--guest-include platform_clock.h^
--wasm3-bindings src\clock_api_bind_gen.c
python3 scripts\bindgen.py io^
python3 scripts\bindgen_bb.py io^
src\io_api.json^
--guest-stubs sdk\io_stubs.c^
--wasm3-bindings src\io_api_bind_gen.c
::compile orca
set INCLUDES=/I src /I sdk /I ext\wasm3\source /I milepost\src /I milepost\ext
set LIBS=/LIBPATH:bin milepost.dll.lib wasm3.lib
set INCLUDES=/I src /I sdk /I ext\bytebox\include /I milepost\src /I milepost\ext
set LIBS=/LIBPATH:bin milepost.dll.lib ext\bytebox\lib\bytebox.lib
cl /Zi /Zc:preprocessor /std:c11 /experimental:c11atomics %INCLUDES% src\main.c /link %LIBS% /out:bin\orca.exe
)

View File

@ -0,0 +1,147 @@
// C interface for bytebox wasm runtime.
#include <stdint.h>
#include <stdbool.h>
struct bb_slice
{
char* data;
size_t length;
};
typedef struct bb_slice bb_slice;
enum bb_error
{
BB_ERROR_OK,
BB_ERROR_FAILED,
BB_ERROR_OUTOFMEMORY,
BB_ERROR_INVALIDPARAM,
BB_ERROR_UNKNOWNEXPORT,
};
typedef enum bb_error bb_error;
enum bb_valtype
{
BB_VALTYPE_I32,
BB_VALTYPE_I64,
BB_VALTYPE_F32,
BB_VALTYPE_F64,
};
typedef enum bb_valtype bb_valtype;
typedef float bb_v128[4];
union bb_val
{
int32_t i32_val;
int64_t i64_val;
float f32_val;
double f64_val;
bb_v128 v128_val;
uint32_t externref_val;
};
typedef union bb_val bb_val;
struct bb_module_definition_init_opts
{
const char* debug_name;
};
typedef struct bb_module_definition_init_opts bb_module_definition_init_opts;
struct bb_module_definition
{
void* module;
};
typedef struct bb_module_definition bb_module_definition;
// struct bb_import_function
// {
// const char* name;
// bb_host_function* func;
// bb_valtype* params;
// size_t num_params;
// bb_valtype* returns;
// size_t num_returns;
// void* userdata;
// };
// typedef struct bb_import_function bb_import_function;
struct bb_import_package
{
void* package;
};
typedef struct bb_import_package bb_import_package;
struct bb_module_instance_instantiate_opts
{
bb_import_package* packages;
size_t num_packages;
bool enable_debug;
};
typedef struct bb_module_instance_instantiate_opts bb_module_instance_instantiate_opts;
struct bb_module_instance
{
void* module;
};
typedef struct bb_module_instance bb_module_instance;
struct bb_module_instance_invoke_opts
{
bool trap_on_start;
};
typedef struct bb_module_instance_invoke_opts bb_module_instance_invoke_opts;
struct bb_func_handle
{
uint32_t index;
uint32_t type;
};
typedef struct bb_func_handle bb_func_handle;
struct bb_func_info
{
bb_valtype* params;
size_t num_params;
bb_valtype* returns;
size_t num_returns;
};
typedef struct bb_func_info bb_func_info;
enum bb_debug_trap_mode
{
BB_DEBUG_TRAP_MODE_DISABLED,
BB_DEBUG_TRAP_MODE_ENABLED,
};
typedef enum bb_debug_trap_mode bb_debug_trap_mode;
typedef void bb_host_function(void* userdata, bb_module_instance* module, const bb_val* params, bb_val* returns);
// typedef void* bb_malloc_func(size_t size, void* userdata);
// typedef void* bb_realloc_func(void* mem, size_t size, void* userdata);
// typedef void bb_free_func(void* mem, void* userdata);
// void bb_set_memory_hooks(bb_alloc_func* alloc_func, bb_realloc_func* realloc_func, bb_free_func);
const char* bb_error_str(bb_error err);
bb_module_definition bb_module_definition_init(bb_module_definition_init_opts opts);
void bb_module_definition_deinit(bb_module_definition* definition);
bb_error bb_module_definition_decode(bb_module_definition* definition, const char* data, size_t length);
bb_slice bb_module_definition_get_custom_section(const bb_module_definition* definition, const char* name);
bb_import_package bb_import_package_init(const char* name);
void bb_import_package_deinit(bb_import_package* package); // only deinit when all module_instances using the package have been deinited
void* bb_import_package_userdata(const bb_import_package* package);
bb_error bb_import_package_add_function(bb_import_package* package, bb_host_function* func, const char* export_name, bb_valtype* params, size_t num_params, bb_valtype* returns, size_t num_returns, void* userdata);
bb_module_instance bb_module_instance_init(bb_module_definition* definition);
void bb_module_instance_deinit(bb_module_instance* instance);
bb_error bb_module_instance_instantiate(bb_module_instance* instance, bb_module_instance_instantiate_opts opts);
bb_func_handle bb_module_instance_find_func(bb_module_instance* instance, const char* func_name);
bb_func_info bb_module_instance_func_info(bb_module_instance* instance, bb_func_handle handle);
bb_error bb_module_instance_invoke(bb_module_instance* instance, bb_func_handle, const bb_val* params, size_t num_params, bb_val* returns, size_t num_returns, bb_module_instance_invoke_opts opts);
bb_error bb_module_instance_resume(bb_module_instance* instance, bb_val* returns, size_t num_returns);
bb_error bb_module_instance_step(bb_module_instance* instance, bb_val* returns, size_t num_returns);
bb_error bb_module_instance_debug_set_trap(bb_module_instance* instance, uint32_t address, bb_debug_trap_mode trap_mode);
void* bb_module_instance_mem(bb_module_instance* instance, size_t offset, size_t length);
bb_slice bb_module_instance_mem_all(bb_module_instance* instance);

4
ext/bytebox/update.cmd Normal file
View File

@ -0,0 +1,4 @@
@mkdir include 2> nul
@mkdir lib 2> nul
cp E:\Dev\zig_projects\bytebox\zig-out\include\bytebox.h include\bytebox.h
cp E:\Dev\zig_projects\bytebox\zig-out\lib\bytebox.lib lib\bytebox.lib

231
scripts/bindgen_bb.py Normal file
View File

@ -0,0 +1,231 @@
#!/usr/bin/env python3
from argparse import ArgumentParser
import json
parser = ArgumentParser(prog='bindgen.py')
parser.add_argument('api')
parser.add_argument('spec')
parser.add_argument('-g', '--guest-stubs')
parser.add_argument('--guest-include')
parser.add_argument('--wasm3-bindings')
args = parser.parse_args()
apiName = args.api
spec = args.spec
guest_stubs_path = args.guest_stubs
if guest_stubs_path == None:
guest_stubs_path = 'bindgen_' + apiName + '_guest_stubs.c'
wasm3_bindings_path = args.wasm3_bindings
if wasm3_bindings_path == None:
wasm3_bindings_path = 'bindgen_' + apiName + '_wasm3_bindings.c'
host_bindings = open(wasm3_bindings_path, 'w')
guest_bindings = None
specFile = open(spec, 'r')
data = json.load(specFile)
def needs_arg_ptr_stub(decl):
res = (decl['ret']['tag'] == 'S')
for arg in decl['args']:
if arg['type']['tag'] == 'S':
res = True
return(res)
for decl in data:
if needs_arg_ptr_stub(decl):
guest_bindings = open(guest_stubs_path, 'w')
if args.guest_include != None:
s = '#include"' + args.guest_include + '"\n\n'
print(s, file=guest_bindings)
break
for decl in data:
name = decl['name']
cname = decl.get('cname', name)
if needs_arg_ptr_stub(decl):
argPtrStubName = name + '_argptr_stub'
# pointer arg stub declaration
s = ''
if decl['ret']['tag'] == 'S':
s += 'void'
else:
s += decl['ret']['name']
s += ' ORCA_IMPORT(' + argPtrStubName + ') ('
if decl['ret']['tag'] == 'S':
s += decl['ret']['name'] + '* __retArg'
if len(decl['args']) > 0:
s += ', '
for i, arg in enumerate(decl['args']):
s += arg['type']['name']
if arg['type']['tag'] == 'S':
s += '*'
s += ' ' + arg['name']
if i+1 < len(decl['args']):
s += ', '
s += ');\n\n'
# forward function to pointer arg stub declaration
s += decl['ret']['name'] + ' ' + name + '('
for i, arg in enumerate(decl['args']):
s += arg['type']['name'] + ' ' + arg['name']
if i+1 < len(decl['args']):
s += ', '
s += ')\n'
s += '{\n'
s += '\t'
if decl['ret']['tag'] == 'S':
s += decl['ret']['name'] + ' __ret;\n\t'
elif decl['ret']['tag'] != 'v':
s += decl['ret']['name']
s += ' __ret = '
s += argPtrStubName + '('
if decl['ret']['tag'] == 'S':
s += '&__ret'
if len(decl['args']) > 0:
s += ', '
for i, arg in enumerate(decl['args']):
if arg['type']['tag'] == 'S':
s += '&'
s += arg['name']
if i+1 < len(decl['args']):
s += ', '
s += ');\n'
if decl['ret']['tag'] != 'v':
s += '\treturn(__ret);\n'
s += '}\n\n'
print(s, file=guest_bindings)
# host-side stub
s = 'void ' + cname + '_stub(void* userdata, bb_module_instance* module, const bb_val* params, bb_val* returns)'
gen_stub = decl.get('gen_stub', True)
if gen_stub == False:
s += ';\n\n'
else:
s += '\n{\n\t'
retTag = decl['ret']['tag']
if retTag == 'i':
s += 'returns[0].i32_val = '
elif retTag == 'I':
s += 'returns[0].i64_val = '
elif retTag == 'f':
s += 'returns[0].f32_val = '
elif retTag == 'F':
s += 'returns[0].f64_val = '
elif retTag == 'S':
retTypeName = decl['ret']['name']
retTypeCName = decl['ret'].get('cname', retTypeName)
s += '*(' + retTypeCName + '*)(bb_module_instance_mem(module, returns[0].i32_val, sizeof(' + retTypeCName + '))) = '
s += cname + '('
firstArgIndex = 0
for i, arg in enumerate(decl['args']):
typeName = arg['type']['name']
typeCName = arg['type'].get('cname', typeName)
argTag = arg['type']['tag']
if argTag == 'i':
s += 'params[' + str(firstArgIndex + i) + '].i32_val'
elif argTag == 'I':
s += 'params[' + str(firstArgIndex + i) + '].i64_val'
elif argTag == 'f':
s += 'params[' + str(firstArgIndex + i) + '].f32_val'
elif argTag == 'F':
s += 'params[' + str(firstArgIndex + i) + '].f64_val'
elif argTag == 'p':
s += 'bb_module_instance_mem(module, params[' + str(firstArgIndex + i) + '].i32_val, sizeof(1))'
elif argTag == 'S':
s += '*(' + typeCName + '*)bb_module_instance_mem(module, params[' + str(firstArgIndex + i) + '].i32_val, sizeof(' + typeCName + '))'
else:
print('unrecognized type ' + typeCName + ' in procedure signature\n')
break
if i+1 < len(decl['args']):
s += ', '
s += ');\n}\n'
print(s, file=host_bindings)
# link function
s = 'int bindgen_link_' + apiName + '_api(bb_import_package* package)\n{\n'
def translateTag(tag):
if tag == 'i' or tag == 'p':
return 'BB_VALTYPE_I32'
elif tag == 'I':
return 'BB_VALTYPE_I64'
elif tag == 'f':
return 'BB_VALTYPE_F32'
elif tag == 'F':
return 'BB_VALTYPE_F64'
elif tag == 'v':
return ''
print('translateTag: unhandled tag "' + tag + '" with type ')
print(type(tag))
print('\n')
return ''
for decl in data:
name = decl['name']
cname = decl.get('cname', name)
if needs_arg_ptr_stub(decl):
name = name + '_argptr_stub'
retTag = decl['ret']['tag']
retType = ''
numReturns = 0
paramTypes = []
numParams = 0
if retTag == 'S':
retType = 'BB_VALTYPE_I32' # unused, but we need something to put in the the returns array since 0-size arrays are illegal in C
paramTypes.append('BB_VALTYPE_I32')
elif retTag == 'v': #no returns
retType = 'BB_VALTYPE_I32' #unused but we need a dummy value
numReturns = 0
else:
retType = translateTag(retTag)
numReturns = 1
for arg in decl['args']:
tag = arg['type']['tag']
if tag == 'p' or tag == 'S':
tag = 'i'
paramTypes.append(translateTag(tag))
numParams += 1
if numParams == 0:
paramTypes.append('BB_VALTYPE_I32') # unused but need a dummy value to avoid 0-length array
s += '\t{\n'
s += '\t\tbb_valtype params[] = {' + ', '.join(paramTypes) + '};\n'
s += '\t\tsize_t num_params = ' + str(len(paramTypes)) + ';\n'
s += '\t\tbb_valtype returns[] = {' + retType + '};\n'
s += '\t\tsize_t num_returns = ' + str(numReturns) + ';\n'
s += '\t\tbb_error err = bb_import_package_add_function(package, ' + cname + '_stub, "' + name + '", params, num_params, returns, num_returns, NULL);\n'
s += '\t\tif(err != BB_ERROR_OK) { log_error("error: %s\\n", bb_error_str(err)); return(-1); }\n'
s += '\t}\n'
s += '\treturn(0);\n}\n'
print(s, file=host_bindings)

View File

@ -6,16 +6,16 @@ typedef struct wasm_str8
i32 offset;
} wasm_str8;
const void* mg_text_outlines_stub(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t* _sp, void* _mem)
const void* mg_text_outlines_stub(void* userdata, bb_module_instance* module, const bb_val* params, bb_val* returns)
{
wasm_str8 wasmStr = *(wasm_str8*)((char*)_mem + *(i32*)&_sp[0]);
wasm_str8 wasmStr = *(wasm_str8*)bb_module_instance_mem(module, params[0].i32_val, sizeof(wasm_str8));
/////////////////////////////////////////////////////////////////////
//TODO: bound checks
str8 str = {.len = wasmStr.len,
.ptr = (char*)_mem + wasmStr.offset};
/////////////////////////////////////////////////////////////////////
.ptr = (char*)bb_module_instance_mem(module, wasmStr.offset, wasmStr.len)};
mg_text_outlines(str);
if(str.ptr)
{
mg_text_outlines(str);
}
return(0);
}

View File

@ -18,16 +18,17 @@ io_cmp orca_io_wait_single_req(io_req* wasmReq)
//NOTE: convert the req->buffer wasm pointer to a native pointer
// for some reason, wasm3 memory doesn't start at the beginning of the block we give it.
u64 bufferIndex = (u64)req.buffer & 0xffffffff;
u32 memSize = 0;
char* memory = (char*)m3_GetMemory(orca->runtime.m3Runtime, &memSize, 0);
// u32 memSize = 0;
// char* memory = (char*)m3_GetMemory(orca->runtime.m3Runtime, &memSize, 0);
bb_slice memory = bb_module_instance_mem_all(orca->runtime.bbModuleInst);
if(bufferIndex + req.size > memSize)
if(bufferIndex + req.size > memory.length)
{
cmp.error = IO_ERR_ARG;
}
else
{
req.buffer = memory + bufferIndex;
req.buffer = memory.data + bufferIndex;
if(req.op == IO_OP_OPEN_AT)
{

View File

@ -267,26 +267,26 @@ void log_entry_ui(orca_debug_overlay* overlay, log_entry* entry)
}
char m3_type_to_tag(M3ValueType type)
{
switch(type)
{
case c_m3Type_none:
return('v');
case c_m3Type_i32:
return('i');
case c_m3Type_i64:
return('I');
case c_m3Type_f32:
return('f');
case c_m3Type_f64:
return('d');
// char m3_type_to_tag(M3ValueType type)
// {
// switch(type)
// {
// case c_m3Type_none:
// return('v');
// case c_m3Type_i32:
// return('i');
// case c_m3Type_i64:
// return('I');
// case c_m3Type_f32:
// return('f');
// case c_m3Type_f64:
// return('d');
case c_m3Type_unknown:
default:
return('!');
}
}
// case c_m3Type_unknown:
// default:
// return('!');
// }
// }
void orca_runtime_init(orca_runtime* runtime)
{
@ -305,6 +305,21 @@ void orca_runtime_init(orca_runtime* runtime)
#include"gles_api_bind_gen.c"
#include"manual_gles_api.c"
void* quit_on_wasm_init_failure(const char* stage, bb_error err)
{
const char* errStr = bb_error_str(err);
log_error("wasm error at init stage '%s': %s\n", errStr);
const char* options[] = {"OK"};
mp_alert_popup("Error",
"The application couldn't load: encountered fatal error at stage '%s': %s",
stage,
errStr);
mp_request_quit();
return((void*)-1);
}
i32 orca_runloop(void* user)
{
orca_app* app = &__orcaApp;
@ -339,53 +354,81 @@ i32 orca_runloop(void* user)
fread(app->runtime.wasmBytecode.ptr, 1, app->runtime.wasmBytecode.len, file);
fclose(file);
u32 stackSize = 65536;
app->runtime.m3Env = m3_NewEnvironment();
bb_error wasm_init_err;
bb_module_definition_init_opts module_def_init_opts = { .debug_name = bundleNameCString };
app->runtime.bbModuleDef = bb_module_definition_init(module_def_init_opts);
wasm_init_err = bb_module_definition_decode(&app->runtime.bbModuleDef, app->runtime.wasmBytecode.ptr, app->runtime.wasmBytecode.len);
if (wasm_init_err != BB_ERROR_OK)
{
return quit_on_wasm_init_failure("wasm decode", wasm_init_err);
}
app->runtime.m3Runtime = m3_NewRuntime(app->runtime.m3Env, stackSize, NULL);
m3_RuntimeSetMemoryCallbacks(app->runtime.m3Runtime, wasm_memory_resize_callback, wasm_memory_free_callback, &app->runtime.wasmMemory);
// TODO [ReubenD] - allow specifying stack size
// TODO [ReubenD] - allow overriding wasm memory alloc/resize/free
// u32 stackSize = 65536;
// app->runtime.m3Env = m3_NewEnvironment();
// app->runtime.m3Runtime = m3_NewRuntime(app->runtime.m3Env, stackSize, NULL);
// m3_RuntimeSetMemoryCallbacks(app->runtime.m3Runtime, wasm_memory_resize_callback, wasm_memory_free_callback, &app->runtime.wasmMemory);
//NOTE: host memory will be freed when runtime is freed.
//TODO check errors
m3_ParseModule(app->runtime.m3Env, &app->runtime.m3Module, (u8*)app->runtime.wasmBytecode.ptr, app->runtime.wasmBytecode.len);
m3_LoadModule(app->runtime.m3Runtime, app->runtime.m3Module);
m3_SetModuleName(app->runtime.m3Module, bundleNameCString);
// m3_ParseModule(app->runtime.m3Env, &app->runtime.m3Module, (u8*)app->runtime.wasmBytecode.ptr, app->runtime.wasmBytecode.len);
// m3_LoadModule(app->runtime.m3Runtime, app->runtime.m3Module);
// m3_SetModuleName(app->runtime.m3Module, bundleNameCString);
mem_arena_clear(mem_scratch());
//NOTE: bind orca APIs
bindgen_link_core_api(app->runtime.m3Module);
bindgen_link_canvas_api(app->runtime.m3Module);
bindgen_link_clock_api(app->runtime.m3Module);
bindgen_link_io_api(app->runtime.m3Module);
bindgen_link_gles_api(app->runtime.m3Module);
manual_link_gles_api(app->runtime.m3Module);
bb_import_package module_imports = bb_import_package_init("*");
bindgen_link_core_api(&module_imports);
bindgen_link_canvas_api(&module_imports);
bindgen_link_clock_api(&module_imports);
bindgen_link_io_api(&module_imports);
bindgen_link_gles_api(&module_imports);
manual_link_gles_api(&module_imports);
//NOTE: compile
M3Result res = m3_CompileModule(app->runtime.m3Module);
if(res)
// M3Result res = m3_CompileModule(app->runtime.m3Module);
// if(res)
// {
// M3ErrorInfo errInfo = {0};
// m3_GetErrorInfo(app->runtime.m3Runtime, &errInfo);
// log_error("wasm error: %s\n", errInfo.message);
// const char* options[] = {"OK"};
// mp_alert_popup("Error",
// "The application couldn't load: can't compile web assembly module",
// 1,
// options);
// mp_request_quit();
// return(-1);
// }
app->runtime.bbModuleInst = bb_module_instance_init(&app->runtime.bbModuleDef);
bb_module_instance_instantiate_opts module_inst_instantiate_opts = { .packages = &module_imports, .num_packages = 1, .enable_debug = false, };
wasm_init_err = bb_module_instance_instantiate(&app->runtime.bbModuleInst, bb_module_instance_instantiate_opts opts);
if (wasm_init_err != BB_ERROR_OK)
{
M3ErrorInfo errInfo = {0};
m3_GetErrorInfo(app->runtime.m3Runtime, &errInfo);
log_error("wasm error: %s\n", errInfo.message);
const char* options[] = {"OK"};
mp_alert_popup("Error",
"The application couldn't load: can't compile web assembly module",
1,
options);
mp_request_quit();
return(-1);
return quit_on_wasm_init_failure("wasm instantiate", wasm_init_err);
}
bb_import_package_deinit(&module_imports); // safe to deinit this now that the module has been instantiated
// TODO up next: expose a cached handle to functions to invoke instead of a string search
//NOTE: Find and type check event handlers.
for(int i=0; i<G_EXPORT_COUNT; i++)
{
const g_export_desc* desc = &G_EXPORT_DESC[i];
IM3Function handler = 0;
m3_FindFunction(&handler, app->runtime.m3Runtime, desc->name.ptr);
bb_func_handle handler;
bb_module_instance_find_func(&app->runtime.bbModuleInst, desc->name.ptr);
// IM3Function handler = 0;
// m3_FindFunction(&handler, app->runtime.m3Runtime, desc->name.ptr);
if(handler)
{

View File

@ -1,29 +1,28 @@
const void* glShaderSource_stub(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem)
void glShaderSource_stub(void* userdata, bb_module_instance* module, const bb_val* params, bb_val* returns)
{
i32 shader = *(i32*)&_sp[0];
i32 count = *(i32*)&_sp[1];
i32 stringArrayOffset = *(i32*)&_sp[2];
i32 lengthArrayOffset = *(i32*)&_sp[3];
i32 shader = params[0].i32_val;
i32 count = params[1].i32_val;
i32 stringArrayOffset = params[2].i32_val;
i32 lengthArrayOffset = params[3].i32_val;
int* stringOffsetArray = (int*)((char*)_mem + stringArrayOffset);
const int* lengthArray = lengthArrayOffset ? (int*)(bb_module_instance_mem(module, lengthArrayOffset, count * sizeof(int))) : 0;
const int* stringOffsetArray = (int*)(bb_module_instance_mem(module, stringArrayOffset, count * sizeof(int)));
const char** stringArray = (const char**)mem_arena_alloc_array(mem_scratch(), char*, count);
for(int i=0; i<count; i++)
{
stringArray[i] = (char*)_mem + stringOffsetArray[i];
stringArray[i] = (char*)bb_module_instance_mem(module, stringOffsetArray[i], lengthArray ? lengthArray[i] : (size_t)-1);
}
int* lengthArray = lengthArrayOffset ? (int*)((char*)_mem + lengthArrayOffset) : 0;
glShaderSource(shader, count, stringArray, lengthArray);
return(0);
}
int manual_link_gles_api(IM3Module module)
int manual_link_gles_api(bb_import_package* package)
{
M3Result res;
res = m3_LinkRawFunction(module, "*", "glShaderSource", "v(iiii)", glShaderSource_stub);
if(res) { log_error("error: %s\n", res); return(-1); }
bb_valtype params[] = {BB_VALTYPE_I32, BB_VALTYPE_I32, BB_VALTYPE_I32, BB_VALTYPE_I32};
size_t num_params = 4;
bb_error err = bb_import_package_add_function(package, glShaderSource_stub, "glShaderSource", params, num_params, NULL, 0, NULL);
if(err != BB_ERROR_OK) { log_error("error: %s\n", bb_error_str(err)); return(-1); }
return(0);
}

View File

@ -10,57 +10,62 @@
void* wasm_memory_resize_callback(void* p, unsigned long size, void* userData)
{
wasm_memory* memory = (wasm_memory*)userData;
// wasm_memory* memory = (wasm_memory*)userData;
if(memory->committed >= size)
{
return(memory->ptr);
}
else if(memory->committed < memory->reserved)
{
u32 commitSize = size - memory->committed;
// if(memory->committed >= size)
// {
// return(memory->ptr);
// }
// else if(memory->committed < memory->reserved)
// {
// u32 commitSize = size - memory->committed;
mem_base_allocator* allocator = mem_base_allocator_default();
mem_base_commit(allocator, memory->ptr + memory->committed, commitSize);
memory->committed += commitSize;
return(memory->ptr);
}
else
{
DEBUG_ASSERT(0, "Out of memory");
return(0);
}
// mem_base_allocator* allocator = mem_base_allocator_default();
// mem_base_commit(allocator, memory->ptr + memory->committed, commitSize);
// memory->committed += commitSize;
// return(memory->ptr);
// }
// else
// {
// DEBUG_ASSERT(0, "Out of memory");
// return(0);
// }
return NULL;
}
void wasm_memory_free_callback(void* p, void* userData)
{
wasm_memory* memory = (wasm_memory*)userData;
// wasm_memory* memory = (wasm_memory*)userData;
mem_base_allocator* allocator = mem_base_allocator_default();
mem_base_release(allocator, memory->ptr, memory->reserved);
memset(memory, 0, sizeof(wasm_memory));
// mem_base_allocator* allocator = mem_base_allocator_default();
// mem_base_release(allocator, memory->ptr, memory->reserved);
// memset(memory, 0, sizeof(wasm_memory));
}
extern u32 orca_mem_grow(u64 size)
{
orca_runtime* runtime = orca_runtime_get();
wasm_memory* memory = &runtime->wasmMemory;
return 0;
// const size_t PAGE_SIZE = 65536;
size = AlignUpOnPow2(size, d_m3MemPageSize);
u64 totalSize = size + m3_GetMemorySize(runtime->m3Runtime);
// orca_runtime* runtime = orca_runtime_get();
// wasm_memory* memory = &runtime->wasmMemory;
u32 addr = memory->committed;
// size = AlignUpOnPow2(size, PAGE_SIZE);
// u64 totalSize = size + m3_GetMemorySize(runtime->m3Runtime);
//NOTE: call resize memory, which will call our custom resize callback... this is a bit involved because
// wasm3 doesn't allow resizing the memory directly
M3Result res = ResizeMemory(runtime->m3Runtime, totalSize/d_m3MemPageSize);
// u32 addr = memory->committed;
return(addr);
// //NOTE: call resize memory, which will call our custom resize callback... this is a bit involved because
// // wasm3 doesn't allow resizing the memory directly
// M3Result res = ResizeMemory(runtime->m3Runtime, totalSize/PAGE_SIZE);
// return(addr);
}
void* wasm_memory_offset_to_ptr(wasm_memory* memory, u32 offset)
{
M3MemoryHeader* header = (M3MemoryHeader*)(memory->ptr);
DEBUG_ASSERT(offset < header->length, "Wasm offset exceeds memory length")
return memory->ptr + sizeof(M3MemoryHeader) + offset;
}
// M3MemoryHeader* header = (M3MemoryHeader*)(memory->ptr);
// DEBUG_ASSERT(offset < header->length, "Wasm offset exceeds memory length")
// return memory->ptr + sizeof(M3MemoryHeader) + offset;
return NULL;
}

View File

@ -10,9 +10,11 @@
#include"platform/platform_io_internal.h"
#include"wasm3.h"
#include"m3_env.h"
#include"m3_compile.h"
#include "bytebox.h"
// #include"wasm3.h"
// #include"m3_env.h"
// #include"m3_compile.h"
#define G_EXPORTS(X) \
X(G_EXPORT_ON_INIT, "OnInit", "", "") \
@ -65,12 +67,16 @@ typedef struct orca_runtime
str8 wasmBytecode;
wasm_memory wasmMemory;
// bytebox data
bb_module_definition bbModuleDef;
bb_module_instance bbModuleInst;
// wasm3 data
IM3Environment m3Env;
IM3Runtime m3Runtime;
IM3Module m3Module;
IM3Function exports[G_EXPORT_COUNT];
u32 rawEventOffset;
// IM3Environment m3Env;
// IM3Runtime m3Runtime;
// IM3Module m3Module;
// IM3Function exports[G_EXPORT_COUNT];
// u32 rawEventOffset;
} orca_runtime;