-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support WebAssembly Reference Types #10491
Comments
@leroycep @kubkon how you expecting this will be looks like in zig? const Externref = *opaque{}; // like this?
const Externref = anytype; // or this?
// or another syntax? I am tried this and it's not working right now. Even if Here a minimal example that should print //gl.zig
pub const Externref = *opaque{};
pub const GLenum = u32;
pub const WebGLShader = Externref;
pub const DOMString = [*]const u8;
pub const VERTEX_SHADER: GLenum = 0x8B31;
pub extern "gl" fn createShader(t: GLenum) WebGLShader; //console.zig
const gl = @import("gl.zig");
pub extern "console" fn log(_: gl.WebGLShader) void;
pub extern "console" fn logF(_: f32) void;
pub extern "console" fn logI(_: c_int) void; //main.zig
const console = @import("console.zig");
const gl = @import("gl.zig");
export fn main() i32 {
console.logI(123);
console.log(gl.createShader(gl.FRAGMENT_SHADER));
return 0;
} <!--index.html-->
<!DOCTYPE html>
<html>
<head>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<title>Test</title>
</head>
<body>
<canvas id="c"></canvas>
<script type="module" src="main.js"></script>
</body>
</html> //main.js
const canvas = document.getElementById('c');
const gl = canvas.getContext('webgl');
const imports = {
console: {
log(r) { return console.log(r) },
logI(i) { return console.log(i) }
},
gl: { createShader(t) { return gl.createShader(t); }}
}
WebAssembly.instantiateStreaming(fetch('../main.wasm'), imports).then(obj => {
const wasm = obj.instance.exports;
wasm.main();
}) //package.json
{
"scripts": {
"build": "zig build-lib main.zig -target wasm32-freestanding -dynamic -OReleaseSmall",
"start": "npx servez"
},
"devDependencies": {
"servez": "^1.12.1"
}
} |
The plan is to use address spaces (issue #653) for WASM // gl.zig
// `.webref` is just a random name I chose, not likely to be the actual thing
pub extern "gl" fn createShader(t: GLenum) *addrspace(.webref) WebGLShader;
const WebGLShader = opaque{
pub extern "gl" fn shaderSource(this: *addrspace(.webref) WebGLShader, source: [*]const u8, sourceLen: usize) void;
}; // main.zig
const gl = @import("gl.zig");
const SHADER_SOURCE =
\\ very clever fragment shader here
;
export fn main() i32 {
const shader = gl.createShader(gl.FRAGMENT_SHADER);
shader.shaderSource(SHADER_SOURCE.ptr, SHADER_SOURCE.len);
return 0;
} The address space proposal hasn't been finalized, far as I can tell, so it will end up looking a bit different from this. |
This comment was marked as outdated.
This comment was marked as outdated.
Think of what, exactly? I see a lot of noise here, but no concrete idea of how you want to solve this.
For the LLVM backend, we can then emit whatever it wants, and do our own thing in the wasm backend. As long as they generate semantically correct behavior we want. Don't get me wrong. I fully support this use case and would like to see this supported in Zig, but it's not as simple as you seem to portray. I don't think we should rush support for this and should carefully consider all options. Personally, it isn't high on my TODO list right now, as stage2 is far along and I'd like to support Wasm's MVP in the wasm backend before considering the additional proposals and features. Also, note that I'm not part of the core team. While I can and will provide my input to the core team, I'm in no position to make a decision on this. |
Sorry, I am just tried to fix it by myself (was little bit naive here) and also attached an example that somebody can use as a reference test for implementation. Use case: I want to make web engine like three.js, that's why I need to make fully compatibe WebAPI for audio, graphics (including new backends) and mouse events. I will do it with codegenerator that can be reused later for another APIs in another zig projects. Linking with C libraries not in a first priority, because right now ecosystem and tooling is more important. For example we also need manually create a glue for fetch/SetTimeout/reqeustAnimationFrame/performance.now(). So the reasons why I am considering Reference Types in zig:
For those who trying to implement glue in old style it will be a x6 more work and will become legacy later.
@Luukdegram thank you for detailed response, you 100% right I am rushed here. But if someone will create experimental version with memory leak it will be helpful, because building ecosystem it's little bit orthogonal work. |
In the meantime, the workaround is the pass an unsecure i32 pointer which is a lookup key in JS land. |
👍 and while undocumented anywhere as a common practice (AFAICT) this is the way a lot of things do it, regardless of if the host is JS or not. ex say it is a "context" object, there would be a context ID as i32, and the host makes sure this isn't actually mapped to memory, rather a lookup table. That way if some code manipulates it unsafely, they fail to crash anything. It is still insecure in so far as someone can possibly guess another session's ID, if they are in the same module instance, but then again wasm modules are not safe for concurrent use and removing context (clearing the key and the memory) before adding one back to the pool can prevent leaks. Take above as grain of salt because I don't work in wasm security, just things I noticed in how things work outside JS. |
I've got a few questions about this ticket:
(Please don't take this as a commitment to actually implement it. This isn't my day job, and my attention span for hobby work tends to be short.) Footnotes |
Before answering your questions, I'd like to bring to your attention that no decision has been made yet with regard to the syntax or whether it's even possible to integrate the external reference feature into Zig at all. Such a decision isn't very straightforward as there are many cases to consider before this can be accepted. e.g. what should be the behavior when someone tries to
|
Thank you for your response.
Took me an hour or so to realize this... I implemented a naive version of the native changes and was very confused until I noticed one little line where it switched to the LLVM backend. I have some notes I've taken since my last comment that I don't want to go to waste. @Luukdegram, though I suspect I'm just telling you things you already know, I hope someone will find them useful:
(module
(func (export "eq_ref") (param externref externref) (result i32)
local.get 0
local.get 1
eq
)
)
|
An RFC to support Reference Types in Clang was just published. As well as an implementation. |
WebAssembly Reference Types are supported in most WebAssembly runtimes at the moment, and they make it easier to interoperate with the host runtime.
On the Discord: https://discord.com/channels/605571803288698900/
Later in the thread: https://discord.com/channels/605571803288698900/922695973623443466/927281011618873407
As mentioned by Luuk, this feature will need address spaces to be implemented (see #653).
For now we can pass in reference as integer handles to index into an array or a hashmap.
The text was updated successfully, but these errors were encountered: