set ONYX_MODULE_DIRECTORY=\dev\onyx
copy "%ONYX_MODULE_DIRECTORY%\bin\onyx-loader.js" .\site\js\onyx-loader.js >NUL
+copy "%ONYX_MODULE_DIRECTORY%\bin\onyx-thread.js" .\site\js\onyx-thread.js >NUL
copy "%ONYX_MODULE_DIRECTORY%\modules\webgl2\webgl2.js" .\site\js\webgl2.js >NUL
copy "%ONYX_MODULE_DIRECTORY%\modules\js_events\js_events.js" .\site\js\js_events.js >NUL
-\dev\onyx\onyx --no-colors -r js -V --use-post-mvp-features -I %ONYX_MODULE_DIRECTORY% --doc doc\source_reference -o %TARGET% src\build.onyx
\ No newline at end of file
+\dev\onyx\onyx --no-colors -r js -V --use-post-mvp-features --use-multi-threading -I %ONYX_MODULE_DIRECTORY% --doc doc\source_reference -o %TARGET% src\build.onyx
\ No newline at end of file
# Copy relative javascript modules from Onyx source directory
cp "$ONYX_MODULE_DIRECTORY/bin/onyx-loader.js" ./site/js/onyx-loader.js
+cp "$ONYX_MODULE_DIRECTORY/bin/onyx-thread.js" ./site/js/onyx-thread.js
cp "$ONYX_MODULE_DIRECTORY/modules/webgl2/webgl2.js" ./site/js/webgl2.js
cp "$ONYX_MODULE_DIRECTORY/modules/js_events/js_events.js" ./site/js/js_events.js
onyx --no-colors $FLAGS -r $RUNTIME -V \
--use-post-mvp-features \
+ --use-multi-threading \
-I $ONYX_MODULE_DIRECTORY \
--doc doc/source_reference \
-o $TARGET \
--- /dev/null
+#!/usr/bin/env python
+
+from http import server
+
+class COOPServer(server.SimpleHTTPRequestHandler):
+ def end_headers(self):
+ self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
+ self.send_header("Cross-Origin-Opener-Policy", "same-origin")
+
+ server.SimpleHTTPRequestHandler.end_headers(self)
+
+if __name__ == '__main__':
+ httpd = server.HTTPServer(('', 8000), COOPServer)
+ httpd.serve_forever()
}
</style>
- <script type="application/onyx" src="analyzer.wasm"></script>
+ <script type="application/onyx" multi-threaded="true" data="analyzer.wasm.data" src="analyzer.wasm"></script>
<script type="text/javascript" src="js/webgl2.js"></script>
<script type="text/javascript" src="js/js_events.js"></script>
<script type="text/javascript" src="js/decompiler.js"></script>
<script type="text/javascript" src="js/onyx-loader.js"></script>
+
+ <script>window.ONYX_THREAD_SCRIPT = "js/onyx-thread.js";</script>
</head>
<body>
},
set_cursor: function(curptr, curlen) {
- const decoder = new TextDecoder();
- const data = new Uint8Array(window.ONYX_MEMORY.buffer, curptr, curlen);
- const str = decoder.decode(data);
+ const str = onyx_decode_text(curptr, curlen);
document.getElementById("main_canvas").style.cursor = str;
},
local_storage_store: function(keyptr, keylen, valueptr, valuelen) {
- const decoder = new TextDecoder();
-
- const key = decoder.decode(new Uint8Array(window.ONYX_MEMORY.buffer, keyptr, keylen));
- const value = decoder.decode(new Uint8Array(window.ONYX_MEMORY.buffer, valueptr, valuelen));
+ const key = onyx_decode_text(keyptr, keylen);
+ const value = onyx_decode_text(valueptr, valuelen);
localStorage[key] = value;
},
local_storage_value_length: function(keyptr, keylen) {
- const decoder = new TextDecoder();
const encoder = new TextEncoder();
-
- const key = decoder.decode(new Uint8Array(window.ONYX_MEMORY.buffer, keyptr, keylen));
+ const key = onyx_decode_text(keyptr, keylen);
return encoder.encode(localStorage[key]).length;
},
local_storage_load: function(keyptr, keylen, bufferptr, bufferlen) {
- const decoder = new TextDecoder();
- const encoder = new TextEncoder();
-
- const key = decoder.decode(new Uint8Array(window.ONYX_MEMORY.buffer, keyptr, keylen));
+ const key = onyx_decode_text(keyptr, keylen);
+ const encoder = new TextEncoder();
const value_data = encoder.encode(localStorage[key]);
-
+
let WASM_U8 = new Uint8Array(window.ONYX_MEMORY.buffer);
WASM_U8.set(value_data, bufferptr);
}
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)
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
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);
},
}
}
}
+
+ use package core.intrinsics.atomics
+
+ t, t2: thread.Thread;
+ thread.spawn(^t, (_: ^i32) {
+ printf("Hello from another thread!\n");
+
+ for i: 1000 {
+ __atomic_wait(_, 0, 1000000000);
+ printf("Hello from another thread! {}\n", i);
+ }
+
+ }, null);
+
+ thread.spawn(^t2, (_: ^i32) {
+ i := 1;
+ while true {
+ i *= 2;
+ __atomic_wait(_, 0, 1000000000);
+ debug_log(.Warning, "Debug message: {}\n", i);
+ }
+ }, null);
}
handle_event :: (event: ^events.Event) {