Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Emscripten support: wasm & webgpu in browser#309

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
Deins wants to merge14 commits intozig-gamedev:main
base:main
Choose a base branch
Loading
fromDeins:emscripten

Conversation

Deins
Copy link

@DeinsDeins commentedMay 31, 2023
edited
Loading

Feel free to reject this if you think this is out of scope or if some of the required workarounds are too ugly etc. But I thought to share this in case this interesting/useful and hear what you think.

This adds support and a sample for web compilation withemscripten toolchain. In general it just adds additional linking step with emsdk on top of regularwasm32-freestanding build which generates all the nececary js browser binding glue code. But also needs some platform specific modifications.
Main notes with required changes are intriangle_wgpu_emscripten sample readme.
Live demo (needs nightly browser with webgpu support):https://deins.lv/triangle_wgpu_emscripten/.

Its quite raw and its possible that some of the emscripten specific stuff could be better abstracted and included in zgpu for example. But currently I tried to avoid modifying api in any way requiring user/sample_code to do it instead.

Known issues

  • doesn't display any user friendly message if browser doesn't support webgpu
  • [fixed]not all keyboard input works correctly in imgui, such as arrow keys / backspace. Might be glfw version incompatibility, has to be debugged.
  • mapAsync is much slower and there is larger chance of running out of uniform buffers. Blocking is not viable and requires addedcanRender fn to be called before each frame to prevent crashes in such scenarios. Or in most extreme situations skipping frame. Also requires emscripten from upstream as I had to make pull request in regards to mapAsync alignment.

Nirlah reacted with thumbs up emojiwyattades reacted with eyes emoji
@michal-z
Copy link
Collaborator

Thanks for the PR and nice work!

I will be looking at this in coming days but please note that I have zero experience with the web stuff. That said, I would like to have this functionality in the project.

@hazeycode Can you please help with the review?

Also, how does this compare to#224?

@hazeycode
Copy link
Member

hazeycode commentedJun 1, 2023
edited
Loading

Very nice work@Deins !

@michal-z This is focused on linking glfw-webgpu using emscipten where in#224 I tried linking sdl-webgl. Also the way the program entry point is resolved is different. I need to revisit some of the details. But I will try to review before the end of the week.

Interesting that Firefox is not playing along. I think that's what I was testing with last time I looked at this - I'll use Chromium as a default from now on, it seems to generally work more often than Firefox.

michal-z reacted with thumbs up emoji

@Deins
Copy link
Author

Deins commentedJun 1, 2023
edited
Loading

Sorry, missed#224. It is similar, but yes main difference is glfw vs sdl and webgl vs webgpu.

I don't see a reason why they both could not work. As in this project user can choose which libs to use and which backend. Main requirement would be to create a nice way from build system to be able to choose correct emscripten link flags, etc.

Another difference is that this useswasm32-freestanding target instead ofwasm32-emscripten. Reason is: I ran into issues with zigstd that had almost no support for emscripten os tag even for most basic things. And it might be that it is the reason why the c entry point was needed for#224. Overall there is no need to usewasm32-emscripten its only needed for C/C++ libraries that use emscripten macro magic to inline JS in C source files. Otherwisefreestanding for zig code is much nicer and I don't know any downsides other than not being able to use builtinos.tag for platform specific checks. So most ergonomic build flow from my experience is to:

  • usefreestanding for zig code
  • usefreestanding for C libraries that have no emscripten specific macros
  • useemscripten target tag for C libraries that use emscripten specific macros

In regards to firefox, I got webgpu running on different pc. But it still didn't run: webgpu functiononSubmittedWorkDone, is not implemented in it. I am not sure how critical it is in zgpu, probably can be worked around. But it might get implemented in future so might not need to worry too much about it until any browser actually enables webgpu by default in stable releases and doesn't have it (as from my understanding it is in webgpu spec).

@hazeycode
Copy link
Member

I don't see a reason why they both could not work. As in this project user can choose which libs to use and which backend. Main requirement would be to create a nice way from build system to be able to choose correct emscripten link flags, etc.

Agreed

Overall there is no need to use wasm32-emscripten its only needed for C/C++ libraries that use emscripten macro magic to inline JS in C source files. Otherwise freestanding for zig code is much nicer and I don't know any downsides other than not being able to use builtin os.tag for platform specific checks. So most ergonomic build flow from my experience is to:
use freestanding for zig code
use freestanding for C libraries that have no emscripten specific macros
use emscripten target tag for C libraries that use emscripten specific macros

Also agreed. IIRC SDL makes use of these macros and there is some complication with how the main shim works. New SDL 3 simplifies this FWIW. Regardless, we can focus on GLFW+WebGPU here.

build.zig Outdated
@@ -22,8 +22,9 @@ pub fn build(b: *std.Build) void {
"Enable DirectX 12 GPU-Based Validation (GBV)",
) orelse false,
.zpix_enable = b.option(bool, "zpix-enable", "Enable PIX for Windows profiler") orelse false,
.emscripten = b.option(bool, "emscripten", "Build for linking with emscripten toolchain") orelse false,
Copy link
Member

@hazeycodehazeycodeJun 8, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Instead of adding another option, I think we should drive emsc builds using Zig's built-in emscripten os target, the same way as when x-compiling other targets. it can be "overridden" to freestanding wherever appropriate.

Deins reacted with thumbs up emoji
build.zig Outdated
@@ -168,6 +171,7 @@ fn packagesWindows(b: *std.Build, options: Options) void {
fn samplesCrossPlatform(b: *std.Build, options: Options) void {
const minimal_gl = @import("samples/minimal_gl/build.zig");
const triangle_wgpu = @import("samples/triangle_wgpu/build.zig");
const triangle_wgpu_emscripten = @import("samples/triangle_wgpu_emscripten/build.zig");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is a good way to develop initially but I think we should make the existing cross-platform samples emscripten compatible instead of adding new sample variants. Any samples that have not yet been made compatible can be individually skipped.

Deins reacted with thumbs up emoji
build.zig Outdated
run_cmd.step.dependOn(install_step);
run_step.dependOn(&run_cmd.step);
} else {
const link_step = linkEmscripten(b, install_options.?, exe) catch unreachable;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Linking should not happen insideinstall

build.zig Outdated
Comment on lines 531 to 532
emlink.addArg("-sUSE_GLFW=3");
emlink.addArg("-sUSE_WEBGPU=1");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Library/sample specific flags could be added separately i.e.linkEmscripten only has the common stuff

Deins reacted with thumbs up emoji
Comment on lines 13 to 17
if (pkg.options.emscripten) return;

switch (host.os.tag) {
.windows => {},
.macos => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

We can just leverage the Zigs builtin emscripten target here and treat it like the others.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Just commited this. Not sure if its better. Its still tricky because zig modules reuse target from target its linked with (as I understand), now zglfw and zgpu etc. has to assume both .emscripten and .freestanding target means emscripten. It works as long as we don't need any other .freestanding target. But still we have to supportwasm32-freestanding andemscripten os, or beter workaround has to be found to be able to use.emscripten target everywhere.

Copy link
Member

@hazeycodehazeycodeJun 11, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

now zglfw and zgpu etc. has to assume both .emscripten and .freestanding target means emscripten

Why? I don't understand. Do you mean that if we compile our game as freestanding we are unable to link zglfw if has been built with emscripten os tag? I thought that it would link because they are both wasm32.

Copy link
Author

@DeinsDeinsJun 12, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Basically issue is that I had to usewasm32-freestanding instead of emscripten for main user/sample code, otherwise I think I got issues with entry point or or_start , don't rememember, but it didn't work for me.

In regards to zglfw & libs issue is not withc but zig modules that don't support specifying different target for them:build.createModule - can't specify target.addModule() just uses target from exe its added to.
So zig bindings code such aszglfw.zig in end has to assume thatbuiltin.target freestanding is emscripten.
Hope I explained it better this time.

Copy link
Member

@hazeycodehazeycodeJun 12, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yes, i follow now. Thanks for clarifying. I'm not sure whether it's better to deal with the entry point or not in the long run; but let's just go with this for now.

unreachable;
}
// more checks? iterate struct fields?
// emscripten in .Debug mode asserts at runtime if required field is missing etc. but something always slips through
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I don't understand what is meant by something slips through

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

core issue is why I added these tests is thatwebgpu.zig basically rewrites c headerwebgpu.h. By default it matches dawnwebgpu.h but emscripten ships with its own that can have version mismatch. If zig structs doesn't match with ones in actual header problems start. For emscripten that means it will try read some struct field but might get value from different field etc. Size checks help to quickly at comptime show these. But if u32 field was removed to struct and other added at end, it will slip through leading to unknown behavior and most likely crash at runtime or worse. But its not straight forward to test at comptime whole struct due to camel-case/snake-case naming changes.

hazeycode reacted with thumbs up emoji
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@michal-z do you have any thoughts regarding how struct layouts can be validated?

@@ -345,6 +368,11 @@ pub const GraphicsContext = struct {
}

if (gctx.uniforms.stage.num >= uniforms_staging_pipeline_len) {
if (emscripten) {
// we can't block in requestAnimationFrame
slog.debug("uniformsNextStagingBuffer: Out of buffers! canRender() must be checked next frame, otherwise we will crash!", .{});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This should beslog.warning

Deins reacted with thumbs up emoji
Comment on lines +350 to +355
// Change current working directory to where the executable is located.
if (!emscripten) {
var buffer: [1024]u8 = undefined;
const path = std.fs.selfExeDirPath(buffer[0..]) catch ".";
std.os.chdir(path) catch {};
}
Copy link
Member

@hazeycodehazeycodeJun 8, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Ideally we need to come up with a better file abstraction We can just do the hacky thing for now (assuming a single emscripten sample).

if (emscripten) {
// by default emscripten initializes on window creation WebGL context
// this flag skips context creation. otherwise we later can't create webgpu surface
zglfw.WindowHint.set(.client_api, @enumToInt(zglfw.ClientApi.no_api));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Should this just be set anyway?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

not sure, if someone wants to use webgl +glfw, different flags might be needed, but I haven't tested

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

this is a wgpu sample so I think it's ok

Comment on lines 434 to 550
};
buf[slice.len] = 0;
switch (level) {
.err => emscripten_console_error(@ptrCast([*:0]u8, slice.ptr)),
.warn => emscripten_console_warn(@ptrCast([*:0]u8, slice.ptr)),
else => emscripten_console_log(@ptrCast([*:0]u8, slice.ptr)),
}
}

pub const EmBool = enum(u32) {
true = 1,
false = 0,
};
// https://emscripten.org/docs/api_reference/html5.h.html#c.emscripten_request_animation_frame_loop
pub const AnimationFrameCallback = *const fn (time: f64, user_data: ?*anyopaque) callconv(.C) EmBool;
extern fn emscripten_request_animation_frame(cb: AnimationFrameCallback, user_data: ?*anyopaque) c_long;
extern fn emscripten_cancel_animation_frame(requestAnimationFrameId: c_long) void;
extern fn emscripten_request_animation_frame_loop(cb: AnimationFrameCallback, user_data: ?*anyopaque) void;
extern fn emscripten_console_log(utf8_string: [*:0]const u8) void;
extern fn emscripten_console_warn(utf8_string: [*:0]const u8) void;
extern fn emscripten_console_error(utf8_string: [*:0]const u8) void;
extern fn emscripten_sleep(ms: u32) void;

/// EmmalocAllocator allocator
/// use with linker flag -sMALLOC=emmalloc
/// for details see docs: https://github.com/emscripten-core/emscripten/blob/main/system/lib/emmalloc.c
extern fn emmalloc_memalign(alignment: usize, size: usize) ?[*]u8;
extern fn emmalloc_realloc_try(ptr: ?[*]u8, size: usize) ?[*]u8;
extern fn emmalloc_free(ptr: ?[*]u8) void;
pub const EmmalocAllocator = struct {
const Self = @This();
dummy: u32 = undefined,

pub fn allocator(self: *Self) std.mem.Allocator {
return .{
.ptr = self,
.vtable = &.{
.alloc = &alloc,
.resize = &resize,
.free = &free,
},
};
}

fn alloc(
ctx: *anyopaque,
len: usize,
ptr_align_log2: u8,
return_address: usize,
) ?[*]u8 {
_ = ctx;
_ = return_address;
const ptr_align: u32 = @intCast(u32, 1) << @intCast(u5, ptr_align_log2);
if (!std.math.isPowerOfTwo(ptr_align)) unreachable;
const ptr = emmalloc_memalign(ptr_align, len) orelse return null;
return @ptrCast([*]u8, ptr);
}

fn resize(
ctx: *anyopaque,
buf: []u8,
buf_align_log2: u8,
new_len: usize,
return_address: usize,
) bool {
_ = ctx;
_ = return_address;
_ = buf_align_log2;
return emmalloc_realloc_try(buf.ptr, new_len) != null;
}

fn free(
ctx: *anyopaque,
buf: []u8,
buf_align_log2: u8,
return_address: usize,
) void {
_ = ctx;
_ = buf_align_log2;
_ = return_address;
return emmalloc_free(buf.ptr);
}
};

usingnamespace if (@import("builtin").cpu.arch == .wasm32) struct {
// GLFW - emscripten uses older version that doesn't have these functions - implement dummies
/// use glfwSetCallback instead
pub export fn glfwGetError() i32 {
return 0; // no error
}

pub export fn glfwGetGamepadState(_: i32, _: ?*anyopaque) i32 {
return 0; // false - failure
}

pub export fn wgpuDeviceTick() void {
std.log.warn("use of device.tick() should be avoided! It can break if used with callbacks such as requestAnimationFrame etc.", .{});
emscripten_sleep(1); // requires -sASYNCIFY
}
} else struct {};
Copy link
Member

@hazeycodehazeycodeJun 8, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Can we move this intozglfw? Or perhaps a new glue library? So that the users don't need to put this stuff in their code

Deins reacted with thumbs up emoji
@Deins
Copy link
Author

Deins commentedJun 11, 2023
edited
Loading

Fixed some of the requested changes, still might need some cleanup.

  • removed/ switched to targetwasm32-emscripten.
  • separated / moved emscripten build and utility stuff in separate libzems. I tried to avoid adding it as dependency to zglfw, zgpu etc. So that mostly stays the same.
  • ported existinggui_test_wgpu to see how easy it is to port existing sample with refactored build stuffdemo. Includes usage ofemscripten asset file preloading that worked well. But file ops are mostly called from c, haven't tested how / if std.fs would work from zig code. Most likely would require some hacks to make std.fs to use posix filesystem calls in either .emscripten or .freestanding target (has to be investigated).
  • portedinstanced_pills_wgpu for quick benchmarks. (mostly probably stresses browser wgpu overhead than cpu/wasm). But gives some feeling of overhead: 1M pills with 7 segments - browser 15FPS vs 20FPS native.
hazeycode reacted with thumbs up emoji

ztracy_pkg = ztracy.package(b, target, optimize, .{
.options = .{
.enable_ztracy = !target.isDarwin(), // TODO: ztracy fails to compile on macOS.
.enable_fibers = !target.isDarwin(),
.enable_ztracy = !target.isDarwin() and options.target.getOsTag() != .emscripten, // TODO: ztracy fails to compile on macOS.
Copy link
Member

@hazeycodehazeycodeJun 11, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@michal-z is this TODO comment still valid? I think we fixed it here:#262?

Comment on lines 18 to 36
pub const AnimationFrameCallback = *const fn (time: f64, user_data: ?*anyopaque) callconv(.C) EmBool;

pub inline fn requestAnimationFrame(cb: AnimationFrameCallback, user_data: ?*anyopaque) c_long {
const cb_ptr = @ptrCast(*const fn (time: f64, user_data: ?*anyopaque) callconv(.C) c_int, cb); // return enum doesn't pass typesafety
return c.emscripten_request_animation_frame(cb_ptr, user_data);
}

pub inline fn requestAnimationFrameLoop(cb: AnimationFrameCallback, user_data: ?*anyopaque) void {
const cb_ptr = @ptrCast(*const fn (time: f64, user_data: ?*anyopaque) callconv(.C) c_int, cb); // return enum doesn't pass typesafety
return c.emscripten_request_animation_frame_loop(cb_ptr, user_data);
}

pub inline fn cancelAnimationFrame(request_animation_frame_id: c_long) void {
c.emscripten_cancel_animation_frame(request_animation_frame_id);
}

pub inline fn sleep(ms: u32) void {
c.emscripten_sleep(ms);
}
Copy link
Member

@hazeycodehazeycodeJun 11, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think we should just declare extern C fns instead of wrapping them. Like you had originally?

Comment on lines 620 to 649
if (zems.is_emscripten) {
// requestAnimationFrame usage is needed to avoid flickering, otherwise could work in loop as well
zems.requestAnimationFrameLoop(&tickEmcripten, demo);
// TODO: ideally we would store all state in globals and return, but for now I don't want to refactor it, so lets spin forever
while (true) zems.sleep(1000);
} else while (!window.shouldClose() and window.getKey(.escape) != .press) {
try tick(demo);
}
}

pub fn tick(demo: *DemoState) !void {
zglfw.pollEvents();
try update(demo);
draw(demo);
}

usingnamespace if (zems.is_emscripten) struct {
pub export fn tickEmcripten(time: f64, user_data: ?*anyopaque) callconv(.C) zems.EmBool {
_ = time;
const demo = @ptrCast(*DemoState, @alignCast(@alignOf(DemoState), user_data.?));
if (demo.gctx.canRender()) tick(demo) catch |err| {
std.log.err("animation frame canceled! tick failed with: {}", .{err});
return .false;
} else {
std.log.warn("canRender(): Frame skipped!", .{});
}
return .true;
}
} else struct {};
extern fn tickEmcripten(time: f64, user_data: ?*anyopaque) callconv(.C) zems.EmBool;
Copy link
Member

@hazeycodehazeycodeJun 11, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Maybe we should look into abstracting this away in zglfw? I'm not sure exactly what it would look like.... something like zglfw init sets up a js animation callback which sets some redraw bool that we can check in our application loop?

This would not be the ideal way of handling display sync but I think it's "good enough". It would of course mean than zems becomes an optional dependency of zglfw, which I think is fine.

For proper display sync, GLFW sucks, you need a better platform abstraction and I'm not sure it's the job of these samples to do that. It gets complicated. On browsers you basicallyhave to use the animation callback but on other platforms you get to pick a scheme. Should we also, for example, set up a CVDisplayLink on macOS in these samples? Or do the crazy stuff on windows? Probably not.

Perhaps I was wrong to suggest merging emscripten support into existing samples.... Maybe there should just be one emscripten sample that does a bunch of stuff. Should that sample use GLFW or SDL or something else? or should there be a sample for each? I don't know. But I wouldn't want to maintain it all.

If it was up to me, I would just delete GLFW, LOL! That is to say, that my opinion doesn't count for much here.

So what do you guys think?@Deins@michal-z

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think its not glfws fault. (at least for web)
Sdl2 had the same issue a while back, it required user to use emscripten specific callbacks for web (at least in older versions that I remember). Random example from web:https://github.com/erik-larsen/emscripten-sdl2-ogles2/blob/master/src/hello_triangle.cpp#L144

Core issue is that on web nothing can block main thread. (andWebWorker threads can't access any web api, so its not even worth mentioning). Emscripten providesasyncify magic that will try to detect functions that can block and do some crazy stuff to unwind stack etc. to allow blocking code to actually not block. But it has its limitations.
In general to smoothly render there is no alternative as far as I know than using requestAnimationFrame.

I think unless API is ground up built, not to ever block, it doesn't matter, it will require getting rid of main loop and using web specific callback interface. Nice example of how such api might look like is C librarysokol which just tries to provide cross platform window, input etc.
But I think its out of scope ofzig-gamedev which mostly just provides zig bindings and libraries which you match together as you wish.

So yeah, currently maybe is good idea just to have one example that show how to compile for web with emscripten.

Copy link
Member

@hazeycodehazeycodeJun 12, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yeah you're right, the problem is trying to fudge a desktop platform abstraction to work with browsers and they we're never designed to do so.

In my own projects I use a custom platform abstraction with completely separate desktop and web backends. It's totally different architecturally (maybe when it is more mature I will look at contributing the web portion as a lib). The use-case here I think is being to quickly be able to take something written on-top of glfw and get it going in a browser. Which wouldn't the path I would recommend for any serious project. But it's a usecase thatcan be supported nonetheless.

So yeah, currently maybe is good idea just to have one example that show how to compile for web with emscripten.

Yeah I think this is the way to go, for now it can just be glfw+webgpu. But in the future we could potentially reusezems to show how to get sdl+opengl in the browser too. Sorry for the distraction by suggesting that we should try to get existing samples to work.

Let's see if@michal-z agrees

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yes, I agree. One sample compiled for the web is enough for this PR. It will provide nice example and give us experience/knowledge about what exactly is needed - we can think about better/different abstraction in the future.

hazeycode reacted with thumbs up emoji
#### Wasm for web
#### Install emscripten sdk
* [Follow these instructions](https://emscripten.org/docs/getting_started/downloads.html#installation-instructions-using-the-emsdk-recommended)
* emscripten needs this [patch](https://github.com/emscripten-core/emscripten/pull/19477/commits/f4bb4f578131578cd13abbbf78d7f4273788d76f) currently for this sample to run until it gets merged/released.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This has now been merged 🍾


#### Compile
```bash
zig build triangle_wgpu_emscripten -Dtarget=wasm32-emscripten
Copy link
Member

@hazeycodehazeycodeJul 19, 2023
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is currently failing for me:

zig build-lib zgui Debug wasm32-emscripten: error: error(compilation): clang failed with stderr: /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/backends/imgui_impl_wgpu.cpp:337:15: error: no member named 'source' in 'WGPUShaderModuleWGSLDescriptor'/home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/backends/imgui_impl_wgpu.cpp:606:37: error: assigning to 'WGPUMipmapFilterMode' from incompatible type 'const WGPUFilterMode'zig build-lib zgui Debug wasm32-emscripten: error: the following command failed with 1 compilation errors:/home/hazeycode/zig/0.11.0-dev.3971+6bc9c4f71/files/zig build-lib -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/src/zgui.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/imgui.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/imgui_widgets.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/imgui_tables.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/imgui_draw.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/imgui_demo.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/implot_demo.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/implot.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/implot_items.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/backends/imgui_impl_glfw.cpp -cflags -fno-sanitize=undefined -- /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/backends/imgui_impl_wgpu.cpp --cache-dir /home/hazeycode/Desktop/zig-gamedev/zig-cache --global-cache-dir /home/hazeycode/.cache/zig --name zgui -static -fno-stack-check -fno-stack-protector -target wasm32-emscripten -mcpu generic -I /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs -I /home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui -isystem /home/hazeycode/Desktop/emsdk/upstream/emscripten/cache/sysroot/include -D __EMSCRIPTEN__ -D __EMSCRIPTEN_major__=3 -D __EMSCRIPTEN_minor__=1 --listen=- Build Summary: 3/7 steps succeeded; 1 failed (disable with --summary none)triangle_wgpu_emscripten transitive failure└─ run emcc transitive failure   ├─ zig build-lib triangle_wgpu_emscripten Debug wasm32-freestanding transitive failure   │  └─ zig build-lib zgui Debug wasm32-emscripten 1 errors   ├─ zig build-lib zgui Debug wasm32-emscripten (reused)   └─ zig build-lib triangle_wgpu_emscripten Debug wasm32-freestanding (+6 more reused dependencies)/home/hazeycode/Desktop/zig-gamedev/libs/zgui/libs/imgui/backends/imgui_impl_wgpu.cpp:1:1: error: unable to build C object: clang exited with code 1

Note I am able to compile for native host target. This is only a problem when compiling forwasm32-emscripten

Zig 0.11.0-dev.3971+6bc9c4f71
emsdk 3.1.43

@hazeycode
Copy link
Member

Needs a rebase

@ckrowland
Copy link
Contributor

Hello everyone.

I'm not sure exactly how to do this, but I rebased deins:emscripten onto michal-z:main on my branch ckrowland:em. Hopefully it can save someone some time.
If my attempt is acceptable, Should I create a PR on deins:emscripten branch or create a new pull request here on michal-z:main?

I got all the emscripten examples running on the web with
chrome, zig 0.11.0-dev.4403+e84cda0eb, macos 12.6.7 and the current zig-gamedev main.

Firefox nightly is throwing a
queue.onSubmittedWorkDone is not a function error

What else needs to be done? I'm still getting up to speed on emscripten/wasm.

Screen Shot 2023-08-04 at 5 54 08 PM
michal-z and hazeycode reacted with heart emoji

@michal-z
Copy link
Collaborator

@Deins Could you please rebase this? We can take it from there if you don't have time to work on it anymore. I think we are very close to finally merge it. Thanks for your work!

@Deins
Copy link
Author

sorry, have been too busy to work much on this.
Overall I think its in ok state. Since wgpu.zig was updated to newer version, as wellwgpuCreateInstance implementation in emscripten, some of the ugly hacks are gone now.
Just have to be careful with emscripten versions as wgpu still slightly changes.
Tested now with zig 11 and emscripten sdk from latest master commitef2a8e929d5337755e9b1d1e1d4ad859dc694eee seems to be working.

The last thing that still might be nice to get rid of is zgpucanRender check that I added to safeguard against running out of buffers.
Otherwise just testing it in more complex use cases. I think there might be more of minor usize/u64 mistakes in some wgpu functions but those should be easy to identify and fix.

hazeycode, ckrowland, and Nazariglez reacted with heart emoji

@hazeycode
Copy link
Member

Some useful developments/info here:ziglang/zig#10836 (comment)

@hazeycode
Copy link
Member

hazeycode commentedJan 11, 2024
edited
Loading

Zig now has emscripten support properziglang/zig#10836

Also this is pretty cool, emsdk can be consumed via package manager:floooh/sokol-zig#50 (comment)

ckrowland reacted with rocket emoji

@ckrowland
Copy link
Contributor

I was able to get mydemo running live on chromium browsers with this. So much thanks Deins!

Only a few minor things I found:

  • Needed to pass -sUSE_OFFSET_CONVERTER to emsdk
  • Needed to copy shell.html file emscripten relies on into zems
    • Maybe we should include a basic template to start?
hazeycode reacted with heart emoji

@hazeycodehazeycode marked this pull request as draftFebruary 7, 2024 23:49
@hazeycode
Copy link
Member

Having another go at emscripten support here ->#480, based largely on this PR

Deins reacted with heart emoji

@hazeycode
Copy link
Member

Note that we haveone demo building for web. I'm leaving this open to remind me to get the other demos, including wgpu ones in a browser too.

@ckrowland
Copy link
Contributor

This is a bit all over the place, but hopefully this can help.

I've been working on this a bit, using the latest emscripten, a couple webgpu structs have been updated slightly from what the native dawn implements. I just switch on emscripten targets, but there is adawn emscripten fork, which emscripten reflects, and perhaps we could build from for native as well.

Also, there is a problem with the way the emscripten webgpu library treats bool onmakeGetBool. It should only look at a u8 instead of u32. When a bool is at the end of a struct, emscripten reads beyond the bool. I'll create a pull request eventually.

hazeycode reacted with heart emoji

@taylorh140
Copy link

Note that we haveone demo building for web. I'm leaving this open to remind me to get the other demos, including wgpu ones in a browser too.

I was curious to try this. (probably the wrong place to ask the question) but what are the build options activate this?

@ckrowland
Copy link
Contributor

Hey@taylorh140, emscripten is still a work in progress. I was able to get my own project working with all the pull requests I referenced. Once we get those merged you'll have better luck.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@michal-zmichal-zmichal-z left review comments

@hazeycodehazeycodehazeycode requested changes

Assignees
No one assigned
Labels
None yet
Projects
None yet
Milestone
0.7.0
Development

Successfully merging this pull request may close these issues.

5 participants
@Deins@michal-z@hazeycode@ckrowland@taylorh140

[8]ページ先頭

©2009-2025 Movatter.jp