Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Update example and Makefile
Makefile has been updated for the current state of emscripten, featuring --use-port=emdawnwebgpu and REMOVING -sUSE_WEBGPU=1
The example is again up to date with webgpu.h and doesn't require webgpu_cpp anymore
  • Loading branch information
manuel5975p committed Jul 23, 2025
commit f0640b8f6a50a658a4a9634680d919a544bbba88
11 changes: 4 additions & 7 deletions backends/imgui_impl_wgpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-07-23: Update to latest version of webgpu.h
// 2025-06-12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. (#8465)
// 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes.
// 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083)
Expand Down Expand Up @@ -54,7 +55,7 @@
//#endif
#else
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten!
//#error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten!
#endif
#endif

Expand Down Expand Up @@ -259,7 +260,7 @@ static WGPUShaderModule ImGui_ImplWGPU_CreateShaderModule(const char* wgsl_sourc
{
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();

#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPLE_WEBGPU_BACKEND_WGVK)
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
WGPUShaderSourceWGSL wgsl_desc = {};
wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
wgsl_desc.code = { wgsl_source, WGPU_STRLEN };
Expand Down Expand Up @@ -694,7 +695,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
// Vertex input configuration
WGPUVertexAttribute attribute_desc[] =
{
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(WEBGPU_BACKEND_EMDAWNWEBGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
{ nullptr, WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
Expand Down Expand Up @@ -742,11 +743,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
// Create depth-stencil State
WGPUDepthStencilState depth_stencil_state = {};
depth_stencil_state.format = bd->depthStencilFormat;
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
#else
depth_stencil_state.depthWriteEnabled = false;
#endif
depth_stencil_state.depthCompare = WGPUCompareFunction_Always;
depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always;
depth_stencil_state.stencilFront.failOp = WGPUStencilOperation_Keep;
Expand Down
5 changes: 2 additions & 3 deletions examples/example_glfw_wgpu/Makefile.emscripten
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ EMS =

# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
# Note: For glfw, we use emscripten-glfw port (contrib.glfw3) instead of (-s USE_GLFW=3) to get a better support for High DPI displays.
EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3
LDFLAGS += -s USE_WEBGPU=1
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
EMS += -DWEBGPU_BACKEND_EMDAWNWEBGPU -DIMGUI_IMPL_WEBGPU_BACKEND_DAWN -sDISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3 --use-port=emdawnwebgpu
LDFLAGS += -sASYNCIFY=2 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1

# Build as single file (binary text encoded in .html file)
#LDFLAGS += -sSINGLE_FILE
Expand Down
31 changes: 29 additions & 2 deletions examples/example_glfw_wgpu/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
## How to Build

### Desktop Builds

- Download and compile one of the three WebGPU on desktop implementations:
- [Dawn](https://dawn.googlesource.com/dawn)
- [WGPU](https://github.com/gfx-rs/wgpu-native) (requires Rust)
- [WGVK](https://github.com/manuel5975p/WGVK) (Lightweight, Vulkan only)


Once compiled, imgui's backend code can be compiled and linked to the webgpu implementation library, as an example to WGVK on X11:

```
g++ -o example -D_GLFW_X11 -DIMGUI_IMPL_WEBGPU_BACKEND_DAWN imgui_demo.cpp imgui.cpp imgui_draw.cpp imgui_widgets.cpp imgui_tables.cpp examples/example_glfw_wgpu/main.cpp backends/imgui_impl_wgpu.cpp backends/imgui_impl_glfw.cpp -I . -I backends -I <path_to_WGVK>/include/ <path_to_WGVK>/build/libwgvk.a
```

This command is assumed to be run from imgui's root directory.

Explanation of the options:
- `-D_GLFW_X11` required to expose X11 handles. Replace with `-D_GLFW_WAYLAND` for wayland or `-D_GLFW_WIN32` for windows
- `-DIMGUI_IMPL_WEBGPU_BACKEND_DAWN` because WGVK mimics dawn
- `-I . -I backends` Include paths for imgui
- `-I <path_to_WGVK>/include/` include path for `<webgpu/webgpu.h>`

### Web Builds
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions

- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
Expand All @@ -10,10 +33,14 @@

- Requires recent Emscripten as WGPU is still a work-in-progress API.

## How to Run
## How to run Web Builds

To run on a local machine:
- Make sure your browse supports WGPU and it is enabled. WGPU is still WIP not enabled by default in most browser.
- For Chrome:
- Enable the experimental flags JSPI and WebGPU in chrome://flags/
- For Firefox:
- Enable the experimental flags wasm_js_promise_integration and WebGPU in about:config

- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
- Otherwise, generally you will need a local webserver:
- Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
Expand Down
65 changes: 44 additions & 21 deletions examples/example_glfw_wgpu/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_wgpu.h"
#include "wgvk.h"
#include <webgpu/webgpu.h>

#ifdef __EMSCRIPTEN__
#include <webgpu/webgpu_cpp.h>
#endif

#include <stdio.h>
#include <iostream>

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/html5_webgpu.h>
#else
#endif
#include <GLFW/glfw3.h>
Expand Down Expand Up @@ -361,8 +365,26 @@ static WGPUDevice RequestDevice(WGPUAdapter& adapter)
}
#endif

static void resizeCallback(GLFWwindow* window, int width, int height){
WGPUTextureFormat surfaceViewFormat = WGPUTextureFormat_BGRA8Unorm;

WGPUSurfaceConfiguration surfaceConfig = {
.nextInChain = nullptr,
.device = wgpu_device,
.format = WGPUTextureFormat_BGRA8Unorm,
.usage = WGPUTextureUsage_RenderAttachment,
.width = (uint32_t)width,
.height = (uint32_t)height,
.viewFormatCount = 1,
.viewFormats = &surfaceViewFormat,
.alphaMode = WGPUCompositeAlphaMode_Opaque,
.presentMode = WGPUPresentMode_Fifo,
};
wgpuSurfaceConfigure(wgpu_surface, &surfaceConfig);
}
static bool InitWGPU(GLFWwindow* window)
{
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_WGVK
WGPUInstanceLayerSelection lsel{
.chain = {
nullptr,
Expand All @@ -372,9 +394,13 @@ static bool InitWGPU(GLFWwindow* window)
lsel.instanceLayerCount = 1;
const char* validation = "VK_LAYER_KHRONOS_validation";
lsel.instanceLayers = &validation;
WGPUInstanceDescriptor idesc{.nextInChain = &lsel.chain};

WGPUInstanceDescriptor idesc{.nextInChain = &lsel.chain};
wgpu_instance = wgpuCreateInstance(&idesc);
#else
wgpu_instance = wgpuCreateInstance(nullptr);
#endif


#ifdef __EMSCRIPTEN__
wgpu_device = emscripten_webgpu_get_device();
Expand All @@ -388,14 +414,20 @@ static bool InitWGPU(GLFWwindow* window)
#endif

#ifdef __EMSCRIPTEN__
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc;
wgpu::Surface surface = instance.CreateSurface(&surface_desc);

wgpu::Adapter adapter = {};
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);

WGPUSurfaceDescriptor surface_desc;
WGPUEmscriptenSurfaceSourceCanvasHTMLSelector html_surface_desc{};
html_surface_desc.chain.sType = WGPUSType_EmscriptenSurfaceSourceCanvasHTMLSelector;
html_surface_desc.selector = WGPUStringView{
.data = "#canvas",
.length = 7
};

surface_desc.nextInChain = &html_surface_desc.chain;
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);

// wgpu::Adapter adapter = {}; // wgpuSurfaceGetPreferredFormat is no more, the correct way would be to pick the first format set by wgpuSurfaceGetCapabilities
wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm;
#else
wgpu_surface = glfwCreateWindowWGPUSurface(wgpu_instance, window);
if (!wgpu_surface)
Expand All @@ -418,23 +450,14 @@ static bool InitWGPU(GLFWwindow* window)
wgpuSurfaceConfigure(wgpu_surface, &surfaceConfig);

#endif

glfwSetWindowSizeCallback(window, resizeCallback);
//wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr);

return true;
}


/**
* This is an extension of GLFW for WebGPU, abstracting away the details of
* OS-specific operations.
*
* This file is part of the "Learn WebGPU for C++" book.
* https://eliemichel.github.io/LearnWebGPU
*
* Most of this code comes from the wgpu-native triangle example:
* https://github.com/gfx-rs/wgpu-native/blob/master/examples/triangle/main.c
*
* MIT License
* Copyright (c) 2022-2025 Elie Michel and the wgpu-native authors
*
Expand Down