wasm_instance = res.instance;
const lib = res.instance.exports;
- lib._thread_start(funcidx, dataptr);
+ lib._thread_start(thread_id, funcidx, dataptr);
lib._thread_exit(thread_id);
});
}
window.ONYX_MODULES = window.ONYX_MODULES || [];
window.ONYX_MEMORY = null;
window.ONYX_INSTANCE = null;
+window.ONYX_BYTES = null;
+window.ONYX_THREAD_SCRIPT = "onyx-thread.js";
window.ONYX_MODULES.push({
module_name: "host",
print_str: function(ptr, len) {
- var buffer = new Uint8Array(ONYX_MEMORY.buffer, ptr, len);
- var string = new TextDecoder().decode(buffer);
- console.log(string);
+ console.log(onyx_decode_text(ptr, len));
},
- exit: function() { debugger; }
+ exit: function() { debugger; },
+
+ spawn_thread: function(id, funcidx, dataptr) {
+ try {
+ let needed_imports = {};
+
+ for (let i = 0; i < window.ONYX_MODULES.length; i++) {
+ needed_imports[window.ONYX_MODULES[i].module_name] = [];
+
+ for (let k of Object.keys(window.ONYX_MODULES[i])) {
+ if (k == "module_name") continue;
+
+ needed_imports[window.ONYX_MODULES[i].module_name].push(k);
+ }
+ }
+
+ const worker = new Worker(window.ONYX_THREAD_SCRIPT);
+ worker.postMessage({
+ thread_id : id,
+ memory : window.ONYX_MEMORY,
+ wasm_bytes : window.ONYX_BYTES,
+ funcidx : funcidx,
+ dataptr : dataptr,
+ imports : needed_imports,
+ });
+
+ return 1;
+
+ } catch (e) {
+ console.error(e);
+ return 0;
+ }
+ },
});
+function onyx_decode_text(ptr, len) {
+ let v = new DataView(window.ONYX_MEMORY.buffer);
+
+ let s = "";
+ for (let i = 0; i < len; i++) {
+ s += String.fromCharCode(v.getUint8(ptr + i));
+ }
+
+ return s;
+}
+
function launch_onyx_program(script_path, call_start) {
fetch(script_path)
.then(function(res) { return res.arrayBuffer(); })
});
}
+function launch_multi_threaded_onyx_program(script_path, data_path, call_start) {
+ Promise.all([fetch(script_path), fetch(data_path)])
+ .then(function(xs) { return Promise.all([xs[0].arrayBuffer(), xs[1].arrayBuffer()]); })
+ .then(function(data) {
+ var import_object = {};
+
+ for (var i = 0; i < window.ONYX_MODULES.length; i++) {
+ import_object[window.ONYX_MODULES[i].module_name] = window.ONYX_MODULES[i];
+ }
+
+ import_object["onyx"] = { memory: new WebAssembly.Memory({ initial: 1024, maximum: 65536, shared: true }) };
+ window.ONYX_MEMORY = import_object["onyx"]["memory"];
+ window.ONYX_BYTES = data[0];
+
+ WebAssembly.instantiate(data[1], import_object)
+ .then(function (data_module) {
+ WebAssembly.instantiate(data[0], import_object)
+ .then(function (code_module) {
+ window.ONYX_INSTANCE = code_module.instance;
+ code_module.instance.exports._start();
+ });
+ });
+ });
+}
+
window.onload = function() {
var script_tags = document.getElementsByTagName("script");
for (var i = 0; i < script_tags.length; i++) {
if (script_tags[i].getAttribute("type") == "application/onyx") {
- // @ROBUSTNESS: It should be configurable which function is called on start up of a Onyx WASM module.
- launch_onyx_program(script_tags[i].getAttribute("src"), true);
+ if (script_tags[i].getAttribute("multi-threaded")) {
+ launch_multi_threaded_onyx_program(script_tags[i].getAttribute("src"), script_tags[i].getAttribute("data"), true);
+ } else {
+ launch_onyx_program(script_tags[i].getAttribute("src"), true);
+ }
}
}
};
--- /dev/null
+
+function onyx_decode_text(ptr, len) {
+ let v = new DataView(self.ONYX_MEMORY.buffer);
+
+ let s = "";
+ for (let i = 0; i < len; i++) {
+ s += String.fromCharCode(v.getUint8(ptr + i));
+ }
+
+ return s;
+}
+
+
+self.onmessage = function (msg) {
+ const data = msg.data;
+
+ let import_object = {};
+ for (let k of Object.keys(data.imports)) {
+ import_object[k] = {};
+ for (let v of data.imports[k]) {
+ import_object[k][v] = function(a, b, c, d, e, f, g, h, i, j) {
+ console.error("ATTEMPT TO CALL MAIN THREAD FUNCTION FROM WORKER THREAD! " + v + "." + k);
+ }
+ }
+ }
+
+ import_object.host.print_str = function(ptr, len) { console.log(onyx_decode_text(ptr, len)); };
+ import_object.host.exit = function() { debugger; };
+ import_object.onyx = { memory: data.memory };
+
+ WebAssembly.instantiate(new Uint8Array(data.wasm_bytes), import_object)
+ .then(function(res) {
+ self.ONYX_MEMORY = data.memory;
+
+ res.instance.exports._thread_start(data.thread_id, data.funcidx, data.dataptr);
+ res.instance.exports._thread_exit(data.thread_id);
+ });
+}
\ No newline at end of file
logger : Logger = .{ default_logger, null };
assert_handler : (msg: str, site: CallSite) -> void;
+
+ thread_id : i32;
}
#if runtime.Runtime != runtime.Runtime_Custom {
use package core
-__output_string :: (s: str) -> u32 #foreign "host" "print_str" ---
+__output_string :: (s: str) -> u32 #foreign "host" "print_str" ---
__exit :: (status: i32) -> void #foreign "host" "exit" ---
// The builtin _start proc.
// Sets up everything needed for execution.
#export "_start" () {
__runtime_initialize();
+ context.thread_id = 0;
args: [] cstr = .{ null, 0 };
(package main).main(args);
#if Multi_Threading_Enabled {
__spawn_thread :: (id: i32, func: (data: rawptr) -> void, data: rawptr) -> bool #foreign "host" "spawn_thread" ---
- #export "_thread_start" (func: (data: rawptr) -> void, data: rawptr) {
+ #export "_thread_start" (id: i32, func: (data: rawptr) -> void, data: rawptr) {
__stack_top = raw_alloc(alloc.heap_allocator, 1 << 20);
__thread_initialize();
+ context.thread_id = id;
+
func(data);
__flush_stdio();
// Sets up everything needed for execution.
#export "_start" () {
__runtime_initialize();
+ context.thread_id = 0;
args : [] cstr;
argv_buf_size : Size;
if (ev.altKey) modifiers |= 0x02;
if (ev.metaKey) modifiers |= 0x04;
if (ev.shiftKey) modifiers |= 0x08;
-
+
push_event_to_buffer(esp, event_size, 0x05, [ ev.keyCode, modifiers ]);
var keyname = ev.code;
request_file(esp, event_size, filename_ptr, filename_len, fileid) {
esp /= 4;
- var path_memory = new Uint8Array(ONYX_MEMORY.buffer, filename_ptr, filename_len);
- var path = new TextDecoder("utf-8").decode(path_memory);
+ var data_view = new DataView(ONYX_MEMORY.buffer);
+ var path = "";
+ for (var i = 0; i < filename_len; i++) path += String.fromCharCode(data_view.getUint8(filename_ptr + i));
console.log(`Requesting file '${path}'`);
fetch(path)
module_name: "gl",
init(name, namelen) {
- const decoder = new TextDecoder();
- const str = new Uint8Array(window.ONYX_MEMORY.buffer, name, namelen);
- const canvasname = decoder.decode(str);
+ const canvasname = onyx_decode_text(name, namelen);
canvas = document.getElementById(canvasname);
if (canvas == null) return 0;
},
// getAttachedShaders() { console.log("NOT IMPLEMENTED!"); },
getAttribLocation(program, name, namelen) {
- const decoder = new TextDecoder();
- const str = new Uint8Array(window.ONYX_MEMORY.buffer, name, namelen);
- const attribname = decoder.decode(str);
+ const attribname = onyx_decode_text(name, namelen);
return gl.getAttribLocation(programs[program], attribname);
},
getShaderParameter(shader, param) { return gl.getShaderParameter(shaders[shader], param); },
getProgramParameter(program, param) { return gl.getProgramParameter(programs[program], param); },
getUniformLocation(program, name, namelen) {
- const decoder = new TextDecoder();
- const str = new Int8Array(window.ONYX_MEMORY.buffer, name, namelen);
- const uniname = decoder.decode(str);
+ const uniname = onyx_decode_text(name, namelen);
uniformlocs.push(gl.getUniformLocation(programs[program], uniname));
return uniformlocs.length - 1;
scissor(x, y, width, height) { gl.scissor(x, y, width, height); },
setSize(width, height) { canvas.width = width; canvas.height = height; },
shaderSource(shader, source, sourcelen) {
- const decoder = new TextDecoder();
- const str = new Int8Array(window.ONYX_MEMORY.buffer, source, sourcelen);
- const sourcedata = decoder.decode(str);
+ const sourcedata = onyx_decode_text(source, sourcelen);
gl.shaderSource(shaders[shader], sourcedata);
},
EMIT_FUNC_NO_ARGS(intrinsic_atomic_notify) {
bh_arr(WasmInstruction) code = *pcode;
- WI(WI_ATOMIC_NOTIFY);
+ WID(WI_ATOMIC_NOTIFY, ((WasmInstructionData) { 2, 0 }));
*pcode = code;
}