Skip to content

Conversation

@BrutPitt
Copy link
Contributor

@BrutPitt BrutPitt commented Feb 7, 2025

As already anticipated here, I send you the PR with the example GLFW in which the Swap-Chain was removed in favor of SurfaceConfigure.

But given the little troubles with GLFW (Validation Layer messages), I wanted to check with SDL2 if everything worked well.
So I created a function to acquire the surface in a native way on SDL.
It works and has been tested (with ImGui SDL2 WebGPU example) in Windows, Linux (X11) and Emscripten
There is also the possibility with Linux (Wayland) , but I haven't tried it yet.

The ImGui SDL2 WebGPU example works well: the web version is live here (obviously a browser with webGPU capabilities is required)

In SDL2 everything works perfectly and there are no warnings from the Validation Layer: it was tested in Linux, Windows and EMSCRIPTEN*

@ocornut
Copy link
Owner

ocornut commented Feb 10, 2025

Hello,
Could you ensure the new symbols use matching code style?

  • surfaceConfiguration -> wgpu_surface_configuration

  • surfaceResize() -> ResizeSurface()

  • wgpuSurfaceConfigure( wgpu_surface, (WGPUSurfaceConfiguration *) &surfaceConfiguration ); -> wgpuSurfaceConfigure(wgpu_surface, (WGPUSurfaceConfiguration*)&surfaceConfiguration);

  • etc.

  • brace on new line

  • Can you clarify why the RequestAdapter() stuff needs to be changed? Is e.g. std::move() an absolute requirement (spoiler: I don't know what it does) ?

  • Could the new callback have declared signatures instead of using lambdas?

Thank you!

@ocornut
Copy link
Owner

ocornut commented Feb 10, 2025

In addition, if I try to compile example_glfw_wgpu/ BEFORE your change using Dawn, I get many other errors (which are not the one you are aiming to fix).

imgui_impl_wgpu.cpp(66,41): error C2187: syntax error: 'WGPUComputeState' was unexpected here [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(273,5): error C2065: 'WGPUShaderSourceWGSL': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(273,26): error C2146: syntax error: missing ';' before identifier 'wgsl_desc' [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(273,26): error C2065: 'wgsl_desc': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(273,36): error C3079: an initializer list cannot be used as the right operand of this assignment operator [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(274,5): error C2065: 'wgsl_desc': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(274,29): error C2065: 'WGPUSType_ShaderSourceWGSL': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(275,5): error C2065: 'wgsl_desc': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(275,37): error C2065: 'WGPU_STRLEN': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(283,62): error C2065: 'wgsl_desc': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(288,39): error C2065: 'WGPU_STRLEN': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(288,29): error C2440: '=': cannot convert from 'initializer list' to 'const char *' [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
      imgui_impl_wgpu.cpp(288,29):
      The initializer contains too many elements
imgui_impl_wgpu.cpp(405,13): error C2065: 'WGPU_STRLEN': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(432,13): error C2065: 'WGPU_STRLEN': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(545,55): error C2065: 'WGPU_STRLEN': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(545,26): error C2440: '=': cannot convert from 'initializer list' to 'const char *' [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
      imgui_impl_wgpu.cpp(545,26):
      The initializer contains too many elements

imgui_impl_wgpu.cpp(612,9): error C2065: 'WGPU_STRLEN': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
imgui_impl_wgpu.cpp(720,45): error C2065: 'WGPUOptionalBool_False': undeclared identifier [C:\Omar\Work\imgui\examples\example_glfw_wgpu\build\example_glfw_wgpu.vcxproj]
  imgui_widgets.cpp
  Generating Code...

Yet my copy of Dawn appears to be up to date, so I am quite confused about the build process it seems.

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Feb 10, 2025

Hi Omar, let me start with your last message.

I tried to compile the GLFW example under Windows, again, and continue to get NO errors.
I tried also to:

  • delete DAWN and re-clone it entirely
  • delete all sources and re-clone they entirely
  • delete all CMake cache and previous generated files
  • in the end have compiled with: VS2022 (from CMakeFile), with CLion (from CMakeFile) and also directly from command line, and to do this I followed the directives contained in the CMakeFile.txt (file not touched by me) step by step, and which I report below:
# Building for desktop (WebGPU-native) with Dawn:
#  1. git clone https://github.com/google/dawn dawn
#  2. cmake -B build -DIMGUI_DAWN_DIR=dawn
#  3. cmake --build build

and always I get NO errors.

I add, for full completeness, after cloning DAWN I run python tools/fetch_dawn_dependencies.py --use-test-deps command (before to compile), as reported here (googlesource site)

I also noticed that in your report appears example_glfw_wgpu.vcxproj that I don't find from me, nor before, nor after.
I also opened imgui_examples.sln, but it does not contain example_glfw_wgpu.
So I also generated, from CMake, an imgui_example_glfw_wgpu.sln (and obviously also relative .vcxproj), and again get NO errors to compile it

Screenshot 2025-02-10 220006

 

  • For this I ask you which procedure did you follow to compile the example?

 

Moreover, I checked the state of the "undeclared identifier" that you report, and they exist (in my copy of dawn):
e.g. WGPUOptionalBool_False in webgpu.h

Screenshot at 2025-02-10 22-19-02

And, searching the net, I found that WGPUOptionalBool_False was declared lately, in DAWN, but already (at least) from September:
#7969

This seemed to me the most important thing to clarify as soon possible, later I reply to your questions

P.S.
In this reply I focused only on Windows, because of the .vcxproj extension, but obviously it compile with success also in Linux and emscripten

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Feb 11, 2025

About your questions:

About code style

No problem to use your code style.

About changes in RequestAdapter/Device

RequestAdapter was changed because wgpuInstanceRequestAdapter has been changed from Google Dawn:

Currently this is the wgpuInstanceRequestAdapter prototype, it accepts THREE parameters:

WGPUFuture wgpuInstanceRequestAdapter(WGPUInstance instance, WGPU_NULLABLE WGPURequestAdapterOptions const * options, WGPURequestAdapterCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE;

In the previous code wgpuInstanceRequestAdapter used FOUR parameters :

 WGPUAdapter adapter;
    wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter);
    return adapter;                                                            ^^^^^^^^^

The 4th parameter was removed from google DAWN

Same for wgpuInstanceRequestDevice

WGPU_EXPORT WGPUFuture wgpuAdapterRequestDevice(WGPUAdapter adapter, WGPU_NULLABLE WGPUDeviceDescriptor const * options, WGPURequestDeviceCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE;

About std::move

I make just a little example:

    std::string str1 {"AAAAAA"};
    std::string str2 {"BBBBBB"};

    std::string str1_out = str1;
    std::string str2_out = std::move(str2);

The first assignment call the copy constructor/operator: it copy the full string "AAAAAA" into str1_out.
The second move the reference of str2 into str2_out and simply set str2 in a valid but unspecified state
Both str1_out and str2_out will have what is expected, but str2_out with less work for the CPU.
So std::move, move the reference of an object into another, and this is very useful when a local object must to be moved/assigned to a global variable, when it's near to end its scope and then it will not be needed anymore (frequently used in lambda).

(I'm sorry for the short and simplistic explanation: std::move is a "bit" more complex)

  • I'm sorry, this had escaped me, so I add:

Absolute requirement, no.
I went to see the class constructor and the assignment operator and, using std::move, the "release" functions (e.g. WGPURelease) are avoided on an object which will soon be destroyed.

And again:
I tried with the simple assignment and all works (obviously), but I receive this warning from Clang-Tidy:
"Parameter 'adapter' is passed by value and only copied once; consider moving it to avoid unnecessary copies"

About callback

In principle, no problem, but (to understand well) you want that I remove all lambdas, not only the validation layers callbacks, right?

@PathogenDavid
Copy link
Contributor

PathogenDavid commented Feb 11, 2025

Just to give an extra data point, I was able to successfully build and run example_glfw_wgpu on Windows using @BrutPitt's instructions and google/dawn@2a84206.

I've never worked with WebGPU on this machine so the Dawn clone was as fresh as can be. I don't have depot_tools or any other Chromium-specific stuff installed.

This is with Windows 10 22H2, CMake 3.30.2, Python 3.12.5, Visual Studio 2022 17.12.4 (latest). I also have Visual Studio 2022 17.13.0p2.1 and Ninja 1.12.1 on this machine, but I don't think either were used while building the example.

I add, for full completeness, after cloning DAWN I run python tools/fetch_dawn_dependencies.py --use-test-deps command (before to compile), as reported here (googlesource site)

I also ran this as per your mention, although judging by our CMakeLists it shouldn't actually be necessary.

(Also for @ocornut's sake: If you're like me and habitually add --recursive to your git clone commands. Definitely don't do that with Dawn unless you hate bandwidth, time, and storage space. It also might not actually work since their tooling probably doesn't expect you to do it.)

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Feb 11, 2025

@ocornut

About SDL2 WebGPU example attached.

As mentioned it uses a "made by me" module sdl2wgpu.cpp with SDL native calls to get SDL_SysWMinfo data to pass wgpuInstanceCreateSurface call.
And despite being a widely mentioned and used method to acquire the info from/of WM to create Surface, I know is not an official DAWN wgpu procedure.
*and currently I tested it only on Windows, Linux (X11) and emscripten, and the macOS procedure has yet to be written

But I made and attached it exclusively to "present" an example without messages from the Validation Layer and consider/test the correct procedure also/already used in GLFW.

So, give the premises, if you prefer, I take it off from the PR.
Possibly, after, I add it as "un-official" SDL2 imgui WGPU example on my account

@PathogenDavid

This is with Windows 10 22H2, CMake 3.30.2, Python 3.12.5, Visual Studio 2022 17.12.4 (latest). I also have Visual Studio 2022 17.13.0p2.1 and Ninja 1.12.1 on this machine, but I don't think either were used while building the example.

You did well to specify the developer tools releases and OS
Personally tested on/with:

  • Windows 11 24H2
  • CMake > 3.30: bundled compiler versions (CLion/VS) and also last official 3.31.5 release (for command line build and to generate .sln)
  • VS v17.12.3
  • Builder: bundled Ninja on CLion 2024.3.2, otherwise MSbuild

I add, for full completeness, after cloning DAWN I run python tools/fetch_dawn_dependencies.py --use-test-deps command (before to compile), as reported here (googlesource site)

I also ran this as per your mention, although judging by our CMakeLists it shouldn't actually be necessary.

Confirm that this is not necessary (on Linux I don't used it), and therefore is not necessary to insert this step in the CMake procedure, but given the doubts I wanted to follow all the "official" steps

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Feb 12, 2025

Last commit changes:

If you prefer RequestAdaper and RequestDevice declared as functions would have this code, in a #ifndef __EMSCRIPTEN__ block:

#ifndef __EMSCRIPTEN__
static wgpu::Adapter localAdapter;   // currently used as local declaration in InitWGPU, both
static wgpu::Device localDevice;

void RequestAdapter(wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message)
{
    if (status != wgpu::RequestAdapterStatus::Success)
    {
        printf("Failed to get an adapter: %s\n", message.data);
        return;
    }
    localAdapter = std::move(adapter);
}

void RequestDevice(wgpu::RequestDeviceStatus status, wgpu::Device device, wgpu::StringView message)
{
    if (status != wgpu::RequestDeviceStatus::Success)
    {
        printf("Failed to get an device: %s\n", message.data);
        return;
    }
    localDevice = std::move(device);
}
#endif

Added notes:

  • I unified the two #ifdef __EMSCRIPTEN__ blocks in IntWGPU: now - before (previous/current imgui WGPU example)

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Feb 17, 2025

Hi, Omar.

It's frustrating to work on Dawn: last branch, downloaded Saturday, causes "segmentation fault" on WebGPU Vulkan backend.
And also all the DAWN examples (HelloTriangle, Anemometer, etc) have the same problem: on my PCs this happens with NVidia RTX 3080 (Linux) and AMD RX 6700 XT (Windows 11).
I have included in the code a way to force a backendType change to D3D11 (or D3D12), for Windows, as workaround.
Currently, have no option for Linux where Vulkan is the only option.
This does not happens in Emscripten

Edit - current problem is reported here:
https://issues.chromium.org/issues/397448368

About the GLFW example

Exploring the Dawn Source Code (the documentation is poor) I made some optimizations and correction to the example:

A new function has been inserted to directly create the device, without the use of callbacks
It is not used anywhere, there is only this note: - Synchronous adapter.CreateDevice(const wgpu::DeviceDescriptor*) may be called.

Currently there is no similar option for Adapter, not for wgpu::Instance class, but only from dawn::native::Instance, this is an example of implementation:

	// Declare DAWN RAII instead of wgpu::Instance
    dawn::native::Instance instance(&instanceDescriptor);

    // Enumerate all devices
    std::vector<dawn::native::Adapter> adapterList = instance.EnumerateAdapters((WGPURequestAdapterOptions*) nullptr);
    assert(!adapterList.empty());

    // we get first available
    dawn::native::Adapter localAdapter { adapterList[0] };

But works only with DAWN (even if it does not involve the EMISCRIPTEN side), for this I currently did not use it

About GLFW viewport error:

It occurs only on window resize, not always, and only when enlarging.

Validation error: Viewport bounds (x: 0.000000, y: 0.000000, width: 1757.999878, height: 1259.000000) are not contained in the render target dimensions (1758 x 1256).
 - While encoding [RenderPassEncoder (unlabeled)].SetViewport(0.000000, 0.000000, 1757.999878, 1259.000000, 0.000000, 1.000000).
 - While finishing [CommandEncoder (unlabeled)].

This because, currently, GLFW does not manage the framebuffer, but only the frame size: it's the example that deals with the downsizing of the framebuffer/Surface, based on the FrameSize acquired through GLFW:

  • First, when the window is resized, the example resize the Surface (framebuffer).
  • Then, ImGui calls glfwGetFramebufferSize from ImGui_ImplGLFW_NewFrame to set io.DisplaySize, but really gets only the "frame size" of the window, which can also be varied in the meantime, during the window drag, respect to Surface resized previously from example.
  • End, ImGui_ImplWGPU_RenderDrawData calls wgpuRenderPassEncoderSetViewport with the DisplaySize parameters, and if the Viewport is bigger of the Surface dimensions, an error occurs.

To avoid a further bothersome inconvenience that happens in this situation:
Viewport bounds (x: 0.000000, y: 0.000000, width: 747.000000, height: 864.000061) are not contained in the render target dimensions (747 x 864).
e.g. Viewport width: 864.000061 vs Surface width: 864, that happens from this call: wgpuRenderPassEncoderSetViewport(ctx, 0, 0, draw_data->FramebufferScale.x * draw_data->DisplaySize.x, draw_data->FramebufferScale.y * draw_data->DisplaySize.y, 0, 1);
A workaround (without to distort ImGui behavior) is to set the Surface just a pixel bigger of that acquired by FrameSize

This not happens in SDL because the "frame size" not change asynchronously, but only after aSDL_PollEvent call, so two calls of SDL_GetWindowSize, in the same iteration cycle, get the same sizes

The only option that works with GLFW is the one in which the example passes the Surface sizes to ImGui_ImplGLFW_NewFrame, but this distorts the current ImGui method and moreover, sooner or later, GLFW will be adapted to the WebGPU platform.

Anyway here there is an online GLFW EMSCRIPTEN example where I have modified ImGui_ImplGLFW_NewFrame that acquires the correct FrameBufferSize from the example, and all works fine.
(tested with last Google Chrome Canary, with Unsafe WebGPU Support - Enabled)

Currently the SDL example hasn't been changed yet

{ WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
{ WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
{ WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
#endif
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this fix compatible with the VertexAttribute struct in the Rust implementation? https://docs.rs/wgpu/latest/wgpu/struct.VertexAttribute.html

As far as I know, the nextInChain field at the front is exclusive to the Google Dawn implementation. I think #ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN should be used here.

@alan-j-hu
Copy link
Contributor

I made a distinct PR for the issue mentioned above at #8438.

Because I'm working with IMGUI and Dawn and this is a compile error, I would prefer to have this fix merged sooner (if this larger PR takes longer to merge). I'm unsure if this is bad etiquette, feel free to disregard.

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Mar 4, 2025

Current status of example_glfw_wgpu

First of all: the problem in DAWN with VK_KHR_cooperative_matrix (Vulkan backend) was solved.
https://issues.chromium.org/issues/397448368
(helped to find it)

Windows 11 (24H2)

All works fine - no problems, nor in native, nor in web

  • Native tested with backends: Vulkan / DX12 / DX11
  • Web tested in Chrome-Canary v.135

MacOS (Sequoia 15.3.1)

All works fine - no problems, nor in native, nor in web

  • Native tested with Metal backend
  • Web tested in Safary technology preview (Release 214 / WebKit 20622.1.2.111.3)

Linux Wayland (Gnome 47 / KDE-Plasma 6.3.1)

All works fine - no problems, nor in native, nor in web

  • Native tested with Vulkan backend
  • Web tested in Chrome-Canary v.135

Linux X11

Native have problems both: X11 on Xorg (WM: marco / xfwm4) and also X11 on Wayland

  • Validation Layer messages due different surface size (described here) continue to appear
  • Now the app sometime crashes on resizing window (due backend error), but it happens also with DAWN internal samples (e.g. ManualSurfaceTest)
  • Native tested with Vulkan backend

No problems in Web browser

  • Web tested in Chrome-Canary v.135

Note

The problems remain only in the X11 native.
Also the previous problem (Validation Layer messages due different surface size) was eliminated both in Web (EMSCRIPTEN) and in Linux Wayland.
It was not my merit: the example remained (practically) the same.

About example_sdl2_wgpu

Same tests done and same behavior as the example_glfw_wgpu, with the only differences:
always and only in Linux X11

  • in X11, the warnings of the Validation Layer (different surface size) do NOT appear.
  • in Linux works only X11 on X11 and Wayland on Wayland: X11 on Wayland seg-fault on Surface creation
  • now (here too, as in GLFW example) the app sometime crashes on resizing window (due internal backend error)

All tests are performed and compiled with:
DAWN 4dc49409e47bda9c777ccaa4028993361f8187cf 01 - Mar - 2025
Web release: EMSCRIPTEN v.4.0.4

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Mar 25, 2025

Last commits add check_surface_texture_status function to check the WGPUSurfaceTexture .status and recreate the Surface in case of "not optimal" (bad) status.
Now the check doesn't crash anymore thanks to the patch released yesterday by DWAN (following the bug report I had opened about 2 weeks ago)
It also fixes the texture handle return value in case of "texture lost" status.

Now the examples work well.

Only the problem of the validation layer messages remains, and only in GLFW example running in X11.
But there must be an inherent problem in X11 (as also I have reported here)

In the meantime I added others WGPU / ImGui examples:

ImGuIZMO.quat WebGPU examples

And a very simple wgpu imgui mandelbrot example just to test and support (with and w/o imgui) the [bug report opened](https://issues.chromium.org/issues/403297812

@Starkium
Copy link

Starkium commented Jun 4, 2025

has there been any testing with SDL3, webgpu, and IMGUI? I didn't see an example, and this seemed to be closest. I'm using webgpu-native personally, but I could adapt it.

@ypujante
Copy link
Contributor

ypujante commented Jun 9, 2025

@ocornut I am not sure what is the status of this PR, but I just wanted to let you know that in Emscripten 4.0.10 (which was just released), the flag -sUSE_WEBGPU=1 is now deprecated and has a replacement: --use-port=emdawnwebgpu (which MUST be used both in compile and link phase, so the EMS flag in Makefile.emscripten).

The good news is that using this new syntax allow for using a much more recent version of Dawb/WebGPU both for the desktop and for Emscripten (v20250531.224602) as of Emscripten 4.0.10 and that includes all the API changes...

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Jun 10, 2025

@ocornut I am not sure what is the status of this PR, but I just wanted to let you know that in Emscripten 4.0.10 (which was just released), the flag -sUSE_WEBGPU=1 is now deprecated and has a replacement: --use-port=emdawnwebgpu (which MUST be used both in compile and link phase, so the EMS flag in Makefile.emscripten).

That's correct.
But this method anyway existed also before EMSCRIPTEN version 4.0.10: the only difference is that now it becomes "official".
First you need Before it was necessary to download, install and configure separately emdawnwebgpu, (that was "unofficial" fork of EMSCRIPTEN for WebGPU developed by Google Dawn, now official in EMSCRIPTEN 4.0.10)

So currently remain always and anyway 4 development methods:

  • NATIVE: using DAWN or WGPU SDK (some minimal differences in structures and functions calls)
  • WEB: using EMSCRIPTEN
    • with --use-port=emdawnwebgpu flag (NEW available and official in EMSCRIPTEN)), using DAWN SDK (structures and functions calls)
    • with -sUSE_WEBGPU=1 flag, using WGPU SDK (structures and functions calls, now deprecated)

In the next few days I will also modify the examples (mentioned in this thread) to adapt them to the new version of EMSCRIPTEN

@ypujante
Copy link
Contributor

First you need to download, install and configure separately emdawnwebgpu, (that was "unofficial" fork of EMSCRIPTEN for WebGPU developed by Google Dawn, now official in EMSCRIPTEN 4.0.10)

Just to clarify, with --use-port=emdawnwebgpu you do not download the (emdawnwebgpu) project separately. That is the beauty of Emscripten ports: it does it for you. Prior to 4.0.10, you are correct that you could use it but you had to download it. Now it is just a matter of changing which flag to use (and of course fix the API changes...). Looking forward to this PR landing in master as I need it for own project.

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Jun 11, 2025

Just to clarify, with --use-port=emdawnwebgpu you do not download the (emdawnwebgpu) project separately. That is the beauty of Emscripten ports: it does it for you. Prior to 4.0.10, you are correct that you could use it but you had to download it.

Sorry, my bad ... (my bad English, in this case)
I meant to say (as you rightly pointed out): Before Emscripten 4.0.10 was necessary to download, install and configure separately emdawnwebgpu (even for this complex and precarious mechanism I had not integrated it in the examples)... obviously now it's finally integrated in EMSCRIPTEN and it's an "official" option.
(in Italian first and before have same phoneme/word.. my mistake)

Thanks for the clarification.

Now it is just a matter of changing which flag to use (and of course fix the API changes...). Looking forward to this PR landing in master as I need it for own project.

I just started working: I plan it can be ready tomorrow or the day after tomorrow.


// Synchronously (wait until) acquire Adapter
auto waitedAdapterFunc { instance.RequestAdapter(&adapterOptions, wgpu::CallbackMode::WaitAnyOnly, onRequestAdapter) };
instance.WaitAny(waitedAdapterFunc, UINT64_MAX);
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this work in Emscripten? Doesn't it require to use -sASYNCIFY=1?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does this work in Emscripten? Doesn't it require to use -sASYNCIFY=1?

Yes, it's required.
As I just posted below:

Copy link
Contributor

Choose a reason for hiding this comment

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

Would there be a way to avoid waiting on the cpp side? Adding -sASINCIFY is not a trivial change as it has some serious consequences (see doc)

1 (default): Run binaryen’s Asyncify pass to transform the code using asyncify. This emits a normal wasm file in the end, so it works everywhere, but it has a significant cost in terms of code size and speed. See https://emscripten.org/docs/porting/asyncify.html

Prior to this change, I could use ImGui (and I do) without using asyncify.

I suppose this change is only affecting the example and is not in the webgpu backend as far as I can tell so I guess I can try to find a way to initialize WebGPU in my project without relying on WaitAny / asyncify

Copy link
Contributor Author

@BrutPitt BrutPitt Jun 12, 2025

Choose a reason for hiding this comment

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

Yes, I meant in this example it is required, it's required by WaitAny

Before it was not necessary, because async() was set externally, via JS

I don't know if it will be possible to use WaitAny in the future without -sASYNCIFY=1 (with the previous method): based on this comment WaitAny (emwgpuWaitAny) will be removed via prepocessor, without the above EMSCRIPTEN flag

I suppose this change is only affecting the example and is not in the webgpu backend as far as I can tell so I guess I can try to find a way to initialize WebGPU in my project without relying on WaitAny / asyncify

asyncify should only be about the Future data type (like WGPUFutureWaitInfo parameter of WaitAny)

Copy link
Contributor Author

@BrutPitt BrutPitt Jun 13, 2025

Choose a reason for hiding this comment

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

I don't know if it will be possible to use WaitAny in the future without -sASYNCIFY=1 (with the previous method): based on this comment WaitAny (emwgpuWaitAny) will be removed via prepocessor, without the above EMSCRIPTEN flag

Thinking about it, it's actually doable:
Here is the "old" ImGui example_glfw_wgpu, adapted with few changes to EMSCRIPEN 4.0.10 with "--use-port=emdawnwebgpu" flag and linked w/o -sASINCIFY=1
https://github.com/BrutPitt/myRepos/tree/master/wgpu_examples/example_glfw_wgpu

I hope it can be useful to you

(async() module is only for the Adapter and Device acquisition, done externally, in the HTML template via JS)

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for providing an example that works without ASINCIFY!

@ocornut
Copy link
Owner

ocornut commented Jun 12, 2025

FYI i have just added support for the new ImGuiBackendFlags_RendererHasTextures protocol in the WebGPU/WGPU backend: 571dae9, which is likely to create conflicts with this PR. Please rebase over latest as you cleanup. Thank you.

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Jun 12, 2025

About changes

  • It was necessary to comment on this #define from imgui_impl_wgpu.cpp: now Google Down code can be used both in Native and EMSCRIPTEN with "--use-port=emdawnwebgpu" flag mode with few differences.

    • ToDo: better #define discrimination / identificatione between IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU and EMSCRIPTEN (for both)
  • I had to modify the HTML "template" file for EMSCRIPTEN:
    whoever wrote the first version of the example, inserted the Adapter and Device acquisition in JavaScript inside the HTML file.
    In DAWN this is no longer necessary: ​​Native and WEB share the same code for Adapter and Device initialization, while for EMSCRIPTEN with -sUSE_WEBGPU=1 flag, I brought internally the JavaScript initialization inside the EM_ASYNC_JS macro

    • It would also be possible to eliminate the inline JS code and use only the CPP, even if it is slightly longer
  • I kept the initialization bool InitWGPU(GLFWwindow* window) separate, in different defines (different EMSCRIPTEN flags), for better reading and code management, even if some assignments are repeated.
    (Obviously there is no contraindication to integrating them into a single function)

  • Changes in CMakeFiles.txt

throw Error("WebGPU not supported.");
}

const adapter = await navigator.gpu.requestAdapter();
Copy link
Contributor

@ypujante ypujante Jun 13, 2025

Choose a reason for hiding this comment

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

I noticed that you introduced support for both --use-port=emdawnwebgpu and -sUSE_WEBGPU=1 via CMake option. But this code removes the adapter/device entirely from the JavaScript section. How does it work with -sUSE_WEBGPU=1 then? I thought it was required as there was no other way to obtain the device.

Copy link
Contributor Author

@BrutPitt BrutPitt Jun 13, 2025

Choose a reason for hiding this comment

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

As reported in previous post, I moved it internally in the CPP source code, using EMSCRIPTEN EM_ASYNC_JS macro to call JS code directly from C/CPP

Then I call it here

I had to use EM_ASYNC_JSmacro (which then mandatory requires -sASINCIFY=1), instead of EM_JS, because await mandatory requires it

Copy link
Contributor Author

@BrutPitt BrutPitt Jun 13, 2025

Choose a reason for hiding this comment

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

I thought it was required as there was no other way to obtain the device.

Using JS is not the only method to acquire Adaper and Device using -sUSE_WEBGPU=1 flag, of course it can also be done via C/CPP, but it's just longer:

// Adapter and device request functions
WGPUAdapter requestAdapter(WGPUInstance instance, WGPURequestAdapterOptions const * options) {
    struct UserData {
        WGPUAdapter adapter = nullptr;
        bool adapterAcquired = false;
    } userData;

    auto onAdapterRequest = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, char const * message, void * pUserData) {
        if (status == WGPURequestAdapterStatus_Success) ((UserData *) pUserData)->adapter = adapter;
        else                                            printf("Could not get WebGPU adapter: %s \n", message);

        ((UserData *) pUserData)->adapterAcquired = true;
    };

    wgpuInstanceRequestAdapter(instance,  options,  onAdapterRequest, &userData);

    while (!userData.adapterAcquired)  emscripten_sleep(100);   // wait until adapter is acquired
    assert(userData.adapter!=nullptr);                          // sanity check
    return userData.adapter;
}

WGPUDevice requestDevice(WGPUAdapter adapter, WGPUDeviceDescriptor const * descriptor) {
    struct UserData {
        WGPUDevice device = nullptr;
        bool deviceAcquired = false;
    } userData;

    auto onDeviceRequest = [](WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * pUserData) {
        if (status == WGPURequestDeviceStatus_Success) ((UserData *) pUserData)->device = device;
        else                                           printf("Could not get WebGPU device: %s \n", message);

        ((UserData *) pUserData)->deviceAcquired = true;
    };

    wgpuAdapterRequestDevice(adapter, descriptor, onDeviceRequest, &userData);

    while (!userData.deviceAcquired) emscripten_sleep(100);     // wait until device is acquired
    assert(userData.device!=nullptr);                           // sanity check

    return userData.device;
}

Subsequently to acquire Adapter and Device:

    wgpu::Adapter adapter(requestAdapter(instance.Get(), {}));
    wgpu::Device device(requestDevice(adapter.Get(), {}));;

N.B.
This code has not been tested on this example
I took this from another code of mine, it should work the same, but it might also need some adaptation.

P.S.
Also this code requires -sASINCIFY=1 because emscripten_sleep requires it

@ypujante
Copy link
Contributor

@BrutPitt When you think you are done with your PR, I will be more than happy to test the Emscripten part locally if you want. Just let me know.

@ypujante
Copy link
Contributor

To follow up on the use of ASYNCIFY, I changed my example code (on a branch for now) to get rid of ASYNCIFY entirely. You can see for yourself how I did it.

The idea is to use WaitAny but with a timeout of 0 and "wait" until the device is initialized using the Emscripten main loop.

Is it convoluted compared to the ASYNCIFY version, absolutely! But the end result is pretty dramatic:

// compiled in -O2 mode
// without ASYNCIFY
-rwxr-xr-x@ 1 ypujante  staff  39552 Jun 15 08:51 index.wasm
// with ASYNCIFY
-rwxr-xr-x@ 1 ypujante  staff  56754 Jun 15 08:52 index.wasm

I am not suggesting we should change it for ImGui but my original concern about introducing ASYNCIFY is valid. Like I pointed out, this change is only in the example code, not in the backend code so I am not too worried about it. And for people who care, there are other ways to do it. So I am good on my end.

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Jun 15, 2025

Briefly about latest changes.
I will comment, soon, more specifically and directly on the commit changes.
Mostly changes in imgui_impl_wgpu.cpp (although very few and almost exclusively concern the use of #define)

Now the example covers all 4 compilation methods:

  • Native / Desktop:
    • Google DAWN
    • WGPU-Native
  • WEB: using EMSCRIPTEN
    • with --use-port=emdawnwebgpu flag (official EMSCRIPTEN >= 4.0.10), that it uses Google DAWN
    • with -sUSE_WEBGPU=1 flag, that it uses an "outated" WGPU functions calls and structures (deprecated in EMSCRIPTEN >= 4.0.10)

The differences between the four methods concern mostly the acquisition of Adapter and Device and the creation of the Surface (in WebGPU initialization)
Now they are systematically divided in two distinct sections (between DAWN initialization and WGPU initialization at the end of the main.cpp file) and each one internally includes both Native and WEB (via EMSCRIPTEN).
This allowed me to separate the executing code of IMGUI which is (practically) UNIQUE for all 4 methods.

Support for WGPU-Native has been introduced.

Neither the previous code, nor my subsequent changes, supported WGPU-Native directly (it was only done through EMSCRIPTEN: obviously I'm talking about the example_glfw_wgpu code)

To allow this I had to introduce a new file: glfw_wgpu.c
In WGPU-Native there is no internal support for GLFW (as there is in DAWN), but each example (in the official WGPU-Native repo) integrates a similar piece of code.
I simply created a function from it (making it even more "readable") to allow the use of GLFW, and I put it in an external file, to avoid confusion with the IMGUI example/code

@ocornut
This is obviously a personal design, based on the (my personal) best integration of the 4 methods.
Of course your point of view will be centered on the best solution for IMGUI and I am aware that it might not even coincide.

I await feedback, requests, suggestions and criticisms from everyone

The example currently has been tested in:

  • Linux X11/Wayland (all 4 build methods)
  • Windows 11, only Native/Desktop (both DAWN and WGPU, also compiled with VS2022 and CLion, using MS compiler for both)

P.S.
I will probably refine and optimize the code in the next few days, as well as testing it on MacOS.
The SDL2 version has not been modified yet, I await feedback on these changes first

@ocornut
Copy link
Owner

ocornut commented Oct 31, 2025

This section in the CMakefile for GLFW+WGPU is a problem, the GLFW_EXPOSE_NATIVE_XXXX define should be be there.

        set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
        find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
        if(WIN32)
            add_definitions(-DGLFW_EXPOSE_NATIVE_WIN32)
            set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
        elseif(UNIX AND NOT APPLE)
            add_definitions(-DGLFW_EXPOSE_NATIVE_X11)
            add_definitions(-DGLFW_EXPOSE_NATIVE_WAYLAND)
            set(OS_LIBRARIES "-lm -ldl")
        elseif(APPLE)
            add_definitions(-DGLFW_EXPOSE_NATIVE_COCOA)
            set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
        endif()

I removed them and adjust the logic in in example_glfw_wgpu/main.cpp and used __has_include() to avoid breaking #9024.

@ocornut ocornut force-pushed the master branch 4 times, most recently from 789bc0a to ceeb1f1 Compare October 31, 2025 18:02
@ocornut
Copy link
Owner

ocornut commented Oct 31, 2025

I have now resculpted entire history to be nicer and merged as 4 commits in master:

  • d0e3b1d - Backends: WebGPU: added ImGui_ImplWGPU_CreateWGPUSurfaceHelper().
  • c5b2a84 - Backends: WebGPU: added smaller and debug helpers.
  • 778aed9 - Examples: GLFW+WebGPU: update to latest specs and to work on Emscripten 4.0.10+ and latest Dawn-Native, WGPU-Native.
  • ff672b2 - Examples: SDL2+WebGPU, SDL3+WebGPU: add new examples.

This closes #8381, #8567, #8191, #7435
I am keeping #8831 open because we could consider adding support for IMGUI_IMPL_WEBGPU_BACKEND_WGVK ?

Could you verify that:

#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#include <webgpu/webgpu_cpp.h>  // for wgpu::Device, wgpu::DeviceLostReason, wgpu::ErrorType used by validation layer callbacks.
#elif !defined(__EMSCRIPTEN__)
#include <webgpu/wgpu.h>        // WGPULogLevel
#endif

Is needed in imgui_impl_wgpu.h ?
And do a sanity check by comparing the diff of the 4 commits + comparing all build files/cmake/scripts to ensure everything is as close as possible to matching?

Thanks for your time and patience with this. I can safely say this has been one of the most frustrating PR i had to deal with but I am very glad this is done and mostly solved.

Mostly the main problems were:

  • 5 platforms (windows, mac, x11, wayland, emscripten) + many variations (dawn, wgpu, emscripten 3 vs 4) + mostly foreign tech that I don't know + webgpu designers and google engineers seems to hate programmers.
  • Build scripts. Needing to compile DAWN. Relying on cmakefile. I think if you provided straight Makefile and put more focus on WGPU-Native it would have been easier to build. As you may have noticed I gave you on testing most native platforms for now because it's too slow and messy to build Dawn (I am sure other fixes will come next but that's fine, we've got a base).
  • Not being careful enough with coding style. I know it's not easy and original examples were full of issues already. I always use my git tools (Fork + WinMerge) to compare and review changes many times to massage them.

But we got to the end of it thanks to your patience and continued explanation. Thanks again!

PS: I'm still not super excited about the amount of debug helpers we added. For this reason I am currently describing them as internals in the imgui_impl_wgpu.h file. It would have been better if WebGPU provided those in the specs.

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Nov 1, 2025

Could you verify that:

#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#include <webgpu/webgpu_cpp.h>  // for wgpu::Device, wgpu::DeviceLostReason, wgpu::ErrorType used by validation layer callbacks.
#elif !defined(__EMSCRIPTEN__)
#include <webgpu/wgpu.h>        // WGPULogLevel
#endif

With the latest changes, it can be modified as follows:

#include <webgpu/webgpu.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
#include <webgpu/wgpu.h>        // WGPULogLevel
#endif

And in imgui_impl_wgpu.cpp the following line can be removed:

#include <webgpu/webgpu.h>

Already done! (both ... pushed in my fork)

(I also optimized the headers in all main.cpp)

Is needed in imgui_impl_wgpu.h ? And do a sanity check by comparing the diff of the 4 commits + comparing all build files/cmake/scripts to ensure everything is as close as possible to matching?

This weekend I'm taking a comprehensive test.

This closes #8381, #8567, #8191, #7435 I am keeping #8831 open because we could consider adding support for IMGUI_IMPL_WEBGPU_BACKEND_WGVK ?

I'll look at it as soon as I finish the tests.

Thanks for your time and patience with this. I can safely say this has been one of the most frustrating PR i had to deal with but I am very glad this is done and mostly solved.

Mostly the main problems were:

* 5 platforms (windows, mac, x11, wayland, emscripten) + many variations (dawn, wgpu, emscripten 3 vs 4) + mostly foreign tech that I don't know + webgpu designers and google engineers seems to hate programmers.

* Build scripts. Needing to compile DAWN. Relying on cmakefile. I think if you provided straight Makefile and put more focus on WGPU-Native it would have been easier to build. As you may have noticed I gave you on testing most native platforms for now because it's too slow and messy to build Dawn (I am sure other fixes will come next but that's fine, we've got a base).

* Not being careful enough with coding style. I know it's not easy and original examples were full of issues already. I always use my git tools (Fork + WinMerge) to compare and review changes many times to massage them.

But we got to the end of it thanks to your patience and continued explanation. Thanks again!

Thanks to you for ImGui!

PS: I'm still not super excited about the amount of debug helpers we added. For this reason I am currently describing them as internals in the imgui_impl_wgpu.h file. It would have been better if WebGPU provided those in the specs.

I know you said that external files are difficult to maintain, but perhaps (at least) CreateWGPUSurface could be moved to three separate files (e.g., WGPU folder in backends)?
(removing from main.cpp and possibly also from imgui_impl_wgpu)

Since they will be removed when the respective frameworks support WebGPU (Hopefully soon.).
(it's just an idea)

Two changes (pushed):

CMakeLists.txt

I added the code for using Dawn “pre-built” library.
Nothing changes for user parameters: if I find a “pre-built” in IMGUI_DAWN_DIR, I use it, otherwise I build the library starting from IMGUI_DAWN_DIR.

There seem to be some problems in Windows, it seems to be the same as this one (already discussed) .
https://issues.chromium.org/issues/441317244

Update:
For those who want to build a pre-built library (to install)

Simply put: the workaround described (in above link) is still valid (not fully resolved), so for Windows it is necessary to compile (still/always) with the following options enabled (also the version to be installed):

    option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
    option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)

or passing they via command line

-DDAWN_FORCE_SYSTEM_COMPONENT_LOAD=ON -DTINT_BUILD_SPV_WRITER=ON

*Required: these options are not enabled by default.

CreateWGPUSurface (in main.cpp)

I moved it to the bottom of the file.

I know you don't like it when I “move” functions ;-) , but there's a good reason for it:

First, let's remove these lines.

#undef Status                       // X11 headers are leaking this.
#undef Success                      // X11 headers are leaking this.

Second, especially if the user wanted to modify the example may encounter further problems: there are many other X11 header entries that can cause issues (e.g. None, Always, etc)

ocornut pushed a commit that referenced this pull request Nov 3, 2025
ocornut added a commit that referenced this pull request Nov 3, 2025
ocornut pushed a commit that referenced this pull request Nov 3, 2025
@ocornut
Copy link
Owner

ocornut commented Nov 3, 2025

I also optimized the headers in all main.cpp
(== removed #include #include <webgpu/webgpu.h>`)

I don't think this is good nor required. We want optimize headers or library ccode from unnecessarily including headers that are not needed. But we also want example code to be explicit and self-documenting, and the main.cpp can include this even if imgui_impl_wgpu.h already does.

CreateWGPUSurface (in main.cpp)
I moved it to the bottom of the file.
I know you don't like it when I “move” functions ;-) , but there's a good reason for it:
First, let's remove these lines.
#undef Status // X11 headers are leaking this.
#undef Success // X11 headers are leaking this.

Previously it was explicit that this is the workaround. So user carrying things into their file would find the solution at a glance. Now the situation is that user modifying the code might get into this "new" issue and not know what to do. I applied a modified commit with the #undef Status from imgui code + comments about the leak.

I also fixed a few more inconsistencies (e.g. made declaration statics).

Further changes should be made in a new PR probably.

@BrutPitt
Copy link
Contributor Author

BrutPitt commented Nov 4, 2025

I also optimized the headers in all main.cpp
(== removed #include #include <webgpu/webgpu.h>`)

I don't think this is good nor required. We want optimize headers or library ccode from unnecessarily including headers that are not needed. But we also want example code to be explicit and self-documenting, and the main.cpp can include this even if imgui_impl_wgpu.h already does.

CreateWGPUSurface (in main.cpp)
I moved it to the bottom of the file.
I know you don't like it when I “move” functions ;-) , but there's a good reason for it:
First, let's remove these lines.
#undef Status // X11 headers are leaking this.
#undef Success // X11 headers are leaking this.

Previously it was explicit that this is the workaround. So user carrying things into their file would find the solution at a glance. Now the situation is that user modifying the code might get into this "new" issue and not know what to do. I applied a modified commit with the #undef Status from imgui code + comments about the leak.

I also fixed a few more inconsistencies (e.g. made declaration statics).

Further changes should be made in a new PR probably.

OK
Just two last thing, this line:

#if !defined(__EMSCRIPTEN__) && (defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN))

It can simply be:

#if !defined(__EMSCRIPTEN__)

*In Native, at least one IMGUI_IMPL_WEBGPU_BACKEND_XXXX must be defined
(same thing in imgui_impl_wgpu)

Just to clarify the mechanism:
One of the two: IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU is always selected based on the choice of IMGUI_DAWN_DIR or IMGUI_WGPU_DIR (respectively).
(I preferred not to include additional build options, but to select based on the chosen library.)

And this also occurs in EMSCRIPTEN to differentiate the new syntax (IMGUI_IMPL_WEBGPU_BACKEND_DAWN+__EMSCRIPTEN__) from the old/deprecated one (IMGUI_IMPL_WEBGPU_BACKEND_WGPU+__EMSCRIPTEN__).
(Here too, I preferred to avoid adding further definitions, given that the code will be merged when it becomes unique.)

That said, it is important to note that by forcing this (it was already selected/controlled by the CMake option):

#if (__EMSCRIPTEN_major__ >= 4) && (__EMSCRIPTEN_minor__ >= 0) && (__EMSCRIPTEN_tiny__ >= 10)
#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
#else
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
#endif

You avoid the possibility of building the example (or any other project) with the old (deprecated) syntax even with EMS >= 4.0.10.
Currently, this possibility was left open, as described in the README:

Generate Emscripten forcing -sUSE_WEBGPU=1 deprecated flag even with EMS >= 4.0.10

  • emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir
    • it set IMGUI_IMPL_WEBGPU_BACKEND_WGPU compiler define

(and even the code in imgui_impl_wgpu would currently be set up to do so)

Of course it's fine, but it was important to point out that the above CMake option is no longer valid: will end up generating a compilation error with EMS >= 4.0.10

... really the last thing:

You may want to add in imgui_impl_wgpu:

#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#error at least one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN and IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
#endif

in addition to the control that already exists:

#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#error Exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
#endif

Currently, this is also true in EMS.
In the event of EMS code unification and the removal of IMGUI_IMPL_WEBGPU_BACKEND_XXXX in EMS (no longer necessary), it will be possible to differentiate EMSCRIPTEN from Native.

CMake already checks both things (for all examples), but obviously imgui_impl_wgpu will be used (alone) in other projects.
(Hopefully) the final/global unification (final WebGPU specifications) will not require any code differentiation, but currently it is necessary to know “which” code you are dealing with.

@ocornut
Copy link
Owner

ocornut commented Nov 7, 2025

Pushed a simplification 86daa89

@ypujante
Copy link
Contributor

ypujante commented Nov 7, 2025

@ocornut @BrutPitt I just wanted to point out that -sUSE_WEBGPU was completely removed from Emscripten v 4.0.18 (see ChangeLog). Honestly I am a bit surprised that it was removed so quickly after being deprecated... but it has. Which makes this PR and changes quite valuable...

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants