Dear ImGui SDL3 + WebGPU 示例:Dawn、WGPU-Native 与 Emscripten 三种构建路线完整指南
【免费下载链接】imguiDear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies项目地址: https://gitcode.com/GitHub_Trending/im/imgui
本文围绕 Dear ImGui 仓库中的 example_sdl3_wgpu 官方示例展开,系统讲解其桌面端(Google Dawn / WGPU-Native / WGVK)与 Web 端(Emscripten)的完整构建流程、CMake 关键选项与 Makefile 编译方式,并结合 CMakeLists.txt、Makefile.emscripten 和 main.cpp 的源码,深入剖析后端宏选择、Surface 创建与每帧渲染管线的实现细节,帮助读者掌握在三种 WebGPU 运行时之间切换构建 ImGui 图形界面的实操方案。
一、示例定位与文件构成
example_sdl3_wgpu是 Dear ImGui 官方示例之一,组合了SDL3 平台后端与WebGPU 渲染后端,用于演示如何在桌面或浏览器中通过 WebGPU 渲染 ImGui 界面。它包含 4 个核心文件:
| 文件 | 职责 |
|---|---|
| main.cpp | 示例主程序:SDL 窗口创建、WebGPU 设备/表面初始化、ImGui 主循环与每帧提交 |
| CMakeLists.txt | 统一构建脚本,负责桌面(Dawn/WGPU/WGVK)与 Emscripten 两条路线的全部配置 |
| Makefile.emscripten | 不依赖 CMake 的 Emscripten 构建脚本,产出web/index.html、web/index.js、web/index.wasm三件套 |
| README.md | 官方构建/运行说明(本文主体参考文档) |
从源码构成看,该示例编译的核心源码为main.cpp、backends/imgui_impl_sdl3.cpp、backends/imgui_impl_wgpu.cpp以及五个核心库文件imgui.cpp、imgui_draw.cpp、imgui_demo.cpp、imgui_tables.cpp、imgui_widgets.cpp(见 CMakeLists.txt)。
WebGPU 后端必须在编译期三选一:IMGUI_IMPL_WEBGPU_BACKEND_DAWN、IMGUI_IMPL_WEBGPU_BACKEND_WGPU、IMGUI_IMPL_WEBGPU_BACKEND_WGVK。imgui_impl_wgpu.cpp 中有硬性校验:一个都没定义则直接#error;在 Emscripten 环境下定义 WGPU(即旧版-sUSE_WEBGPU=1)同样触发#error,因为 Emscripten < 4.0.10 的旧方案已不再受支持。
二、桌面端路线一:CMake + Google Dawn(官方推荐)
官方文档给出的三步命令为:
# 1. 获取 Dawn 源码(clone 到当前目录下的 dawn/ 文件夹) # 2. 生成构建系统(通过 IMGUI_DAWN_DIR 指定 Dawn 目录) cmake -B build -DIMGUI_DAWN_DIR=dawn # 3. 构建 cmake --build build产物位置为build/example_sdl3_wgpu[.exe]或build/Debug/example_sdl3_wgpu[.exe]。
从 CMakeLists.txt 的源码可以确认几个关键前提:
- CMake >= 3.22(
cmake_minimum_required(VERSION 3.22),注释明确说明是 Dawn 的要求); - C++ 标准为 C++20(
set(CMAKE_CXX_STANDARD 20),同样是 Dawn 的要求); - 未指定构建类型时默认 Debug(
if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug ...))。
当指定了IMGUI_DAWN_DIR时,CMake 会先通过find_package(Dawn)尝试寻找已安装好的 Dawn;若未找到,则回退到add_subdirectory将 Dawn 作为子项目直接源码构建,并预设了一组裁剪选项以加速编译(见 CMakeLists.txt):
DAWN_USE_GLFW=OFF:禁用 Dawn 自带的 GLFW(本示例使用 SDL3);DAWN_BUILD_MONOLITHIC_LIBRARY=STATIC:构建静态单库;- 关闭
DAWN_BUILD_SAMPLES、TINT_BUILD_CMD_TOOLS、TINT_BUILD_DOCS、TINT_BUILD_TESTS等无关组件; - Linux 下自动检测
XDG_SESSION_TYPE,若当前会话是 Wayland 则打开DAWN_USE_WAYLAND(可用-DDAWN_USE_WAYLAND=X覆盖)。
构建成功后 CMake 会打印Dawn Installation has been found!,并最终链接webgpu_dawn目标。
三、桌面端路线二:CMake + WGPU-Native 预编译模块
如果不想从零编译 Dawn(首次源码编译 Dawn 耗时较长),可以改用 gfx-rs 提供的WGPU-Native自动生成的预编译二进制模块:
# 1. 下载 WGPU-Native 对应平台/编译器的预编译模块(来自 gfx-rs/wgpu-native 的 Releases 页) # 2. 解压到自选目录 your_preferred_folder # 3. 生成(路径支持绝对路径,也支持相对当前目录的相对路径) cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder # 4. 构建 cmake --build build从 CMakeLists.txt 看,IMGUI_WGPU_DIR路线会:
- 在
${IMGUI_WGPU_DIR}/lib下用find_library查找libwgpu_native.a/wgpu_native.lib/wgpu_native之一(REQUIRED,找不到直接失败); - 按平台追加系统库:Windows 链接
d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject,Linux 追加-lm -ldl; - 定义
IMGUI_IMPL_WEBGPU_BACKEND_WGPU,并把${IMGUI_WGPU_DIR}/include加入头文件搜索路径(CMakeLists.txt)。
源码中更新的第三条路线:WGVK
值得注意的一点是:当前仓库的 CMakeLists.txt 头部注释中还收录了 README 尚未覆盖的第三条桌面路线——WGVK,并且被标注为 “MUCH EASIER”(更简单):
# 1. git clone WGVK 仓库到 wgvk/ 目录 # 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk # 3. cmake --build build从源码看,WGVK 路线要求系统已安装 Vulkan(find_package(Vulkan REQUIRED)),会把${IMGUI_WGVK_DIR}/src/wgvk.c直接编入示例目标,定义IMGUI_IMPL_WEBGPU_BACKEND_WGVK,并按平台注入SUPPORT_WIN32_SURFACE/SUPPORT_METAL_SURFACE/SUPPORT_WAYLAND_SURFACE/SUPPORT_XLIB_SURFACE宏(CMakeLists.txt)。这与 imgui_impl_wgpu.cpp 变更日志一致:WGVK 后端于 2026-03-25 加入,且支持在 WGSL 不可用时回退到 SPIR-V 着色器。三条路线互斥:IMGUI_DAWN_DIR、IMGUI_WGPU_DIR、IMGUI_WGVK_DIR只能指定其一,同时指定会触发FATAL_ERROR(CMakeLists.txt)。
四、Web 端路线:Emscripten 构建 WASM
CMake 方式
官方文档的步骤:
- 按 Emscripten 官方说明安装 Emscripten SDK;
- 安装 Ninja 构建系统;
emcmake cmake -G Ninja -B build,可选追加-DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py";cmake --build build。
从 CMakeLists.txt 的源码实现看,EMSCRIPTEN分支有几个硬性约束和默认值:
- 版本门槛:
EMSCRIPTEN_VERSION低于4.0.15直接FATAL_ERROR(SDL3 的 Emscripten port 要求此最低版本;README 中 “ems >= 4.0.10 才启用--use-port=emdawnwebgpu” 的说明与此兼容——4.0.15 已满足 4.0.10 的前提); - 默认 WebGPU flag:
IMGUI_EMSCRIPTEN_WEBGPU_FLAG缓存变量默认值为--use-port=emdawnwebgpu,Emscripten 4.0.10 引入的该 port 会把 Dawn 打进 WASM 运行时; - 同时定义
IMGUI_IMPL_WEBGPU_BACKEND_DAWN,并附加-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1。
Emscripten 链接参数完整列表见 CMakeLists.txt,关键项含义:
| 选项 | 作用 |
|---|---|
--use-port=emdawnwebgpu | 使用 Dawn 作为 WebGPU 实现(可用IMGUI_EMSCRIPTEN_WEBGPU_FLAG覆盖) |
-sUSE_SDL=3 | 引入 Emscripten 的 SDL3 port |
-sWASM=1 | 产出真 WASM |
-sASYNCIFY=1 | 异步转换,WebGPU 的 Promise 式 API 需要 |
-sALLOW_MEMORY_GROWTH=1 | 允许堆增长 |
-sNO_EXIT_RUNTIME=0 | 允许exit终止运行时 |
-sASSERTIONS=1 | 开启断言便于调试 |
--shell-file=.../shell_minimal.html | 使用仓库自带的精简 HTML 壳 shell_minimal.html |
OUTPUT_NAME = "index" | 最终产物为index.html(配合.js/.wasm) |
同步 Emscripten 到最新 Dawn
README 还说明:若希望 Emscripten 构建使用最新版本的 Dawn,需下载 Google 每日发布的port-emdawnwgpu-package(来自 dawn 的 Releases),解压后将步骤 3 替换为:
emcmake cmake -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py" -G Ninja -B build文档特别提示:N.B.Emscripten 产出的 WASM 要正确工作,还需要对应版本(或更新)的 Google Canary(面向开发者的 nightly 构建)浏览器内核,以包含最新的 WebGPU 变更。外部 WebGPU 库方案(IMGUI_EMSCRIPTEN_WEBGPU_FLAG指向本地 port)同样要求 Emscripten >= 4.0.10 或该包声明的最低要求。
逐步 CMake 命令速查
对应 README 的 “CMake by step” 小节,四种生成方式汇总如下:
| 场景 | 命令 | 效果 |
|---|---|---|
| Dawn 源码构建 | cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -B build_dir | 定义IMGUI_IMPL_WEBGPU_BACKEND_DAWN |
| WGPU-Native | cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -B build_dir | 定义IMGUI_IMPL_WEBGPU_BACKEND_WGPU |
| WGVK(源码新增) | cmake -G Ninja -DIMGUI_WGVK_DIR=path_to_wgvk -B build_dir | 定义IMGUI_IMPL_WEBGPU_BACKEND_WGVK |
| Emscripten | emcmake cmake -G Ninja -B build_dir | EMS >= 4.0.10 自动用--use-port=emdawnwebgpu;更低版本直接中止(旧-sUSE_WEBGPU=1已不支持) |
| Emscripten + 外部 WebGPU 包 | emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B build_dir | 定义IMGUI_IMPL_WEBGPU_BACKEND_DAWN |
生成之后的构建命令永远相同:
cmake --build build_dir # 由 CMake 调用生成阶段选定的构建器 # 或显式调用构建器: cd build_dir && ninja常用 CMake 选项(README “CMake useful options” 全量继承)
生成器类型(-G)——Ninja 之外的替代构建器:
-G Ninja:ninja 构建器;-G "Unix Makefiles":make 构建器;-G "Visual Studio 17 2022" -A x64:生成 VS 2022 解决方案(仅 Windows,仅原生构建,且 Dawn 并非官方支持该方式构建)。
示例——用 make 替代 ninja:
cmake -G "Unix Makefiles" -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir注意:语法大小写敏感;生成器名含空格时必须加
""。
目录:SDK 路径可为绝对路径或相对当前目录的路径;不同生成配置必须使用不同的where_to_build_dir。
构建类型:默认Debug,可改为:
-DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_BUILD_TYPE=RelWithDebInfo示例——构建 Release:
cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -DCMAKE_BUILD_TYPE=Release -B where_to_build_dirSDL3(含 GLFW/SDL2)依赖查找与包管理器:头文件与库默认在系统/编译器路径(环境变量)中查找,可直接把开发工具路径加入环境变量而无需修改CMakeLists.txt。例如 Clang 的搜索环境变量:头文件CPATH、C_INCLUDE_PATH、CPLUS_INCLUDE_PATH;库文件LIBRARY_PATH。使用 vcpkg / conan 等包管理器时,追加:
-DCMAKE_TOOLCHAIN_FILE=path/to/package_manager.cmake以 vcpkg 为例的完整命令:
cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir \ -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake \ -B where_to_build_dir对应 CMake 侧的查找逻辑是find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)(CMakeLists.txt),头文件目录经target_include_directories注入示例目标。
五、不用 CMake:make -f Makefile.emscripten
Makefile.emscripten 提供了一条纯 Emscripten 路径,前提同样是已安装 Emscripten SDK 并加载其环境变量(Windows 上可能需要先执行emsdk/emsdk_env.bat)。在example_sdl3_wgpu/目录下执行:
make -f Makefile.emscripten会产出web/index.html、web/index.js、web/index.wasm三个文件,三者缺一不可。该 Makefile 的关键变量与选项:
- 编译/链接均使用
emcc/em++;编译告警级别-Wall -Wformat -Os; EMS += -s USE_SDL=3 -s DISABLE_EXCEPTION_CATCHING=1,并同时附加--use-port=emdawnwebgpu(要求 Emscripten >= 4.0.10,注释见 Makefile.emscripten);- 链接期追加
-s WASM=1、-s ALLOW_MEMORY_GROWTH=1、-s ASYNCIFY=1、-s NO_EXIT_RUNTIME=0、-s ASSERTIONS=1,并指定--shell-file ../libs/emscripten/shell_minimal.html; USE_FILE_SYSTEM ?= 0开关:默认 0 时追加-s NO_FILESYSTEM=1并定义IMGUI_DISABLE_FILE_FUNCTIONS(关闭文件访问);置 1 时启用文件系统并把misc/fonts/以--preload-file ../../misc/fonts@/fonts预加载进包内,运行时从/fonts路径访问;- 可选
-sSINGLE_FILE(被注释掉)可将 WASM 二进制编码进单个 HTML; - 内置
serve目标:python3 -m http.server -d web;clean目标清理产物。
六、运行产物与浏览器要求
桌面原生构建:直接运行build/example_sdl3_wgpu[.exe](或build/Debug/下同名文件)即可弹出 SDL3 窗口展示 ImGui 演示界面。CMake 的 Emscripten 注释还建议用emrun build/index.html快速预览 Web 构建(CMakeLists.txt)。
Web 构建(README “How to Run” 全量要求):
- 浏览器必须支持并已启用 WebGPU;WebGPU 仍是 WIP(工作进行中)API,多数浏览器默认未开启;
make serve会用 Python3 起一个本地 webserver,然后访问http://localhost:8000;- 其他等价的本地服务器方式:Emscripten 的
emrun web/index.html --browser firefox(起临时服务器并启动 Firefox);Python 3 内置python -m http.server -d web(即make serve的实现); - 原因引用自 Emscripten 文档:Chrome、Safari 等浏览器不支持
file://下的 XHR 请求,无法加载 HTML 依赖的.wasm等附加文件,必须通过本地 webserver 访问; - 若通过网络(而非本地)访问,Firefox 等浏览器会把 Gamepad API 限制在安全上下文(如 https),本示例启用了 Gamepad 支持(见下文主循环)。
七、源码级解析:初始化与每帧渲染管线
WebGPU 实例、设备与 Surface 的获取
main.cpp 的InitWGPU()是所有后端共用的初始化流程:
- 创建
WGPUInstance,并把TimedWaitAny列入requiredFeatures——这是后续用同步方式(WaitAny等待 Future)获取 Adapter/Device 的前提; - 通过
RequestAdapter/RequestDevice同步取得设备。Dawn 后端走 C++ 封装(wgpu::Instance),WGPU/WGVK 后端走纯 C 回调风格;WGPU-Native 还额外注册了wgpuSetLogCallback(日志级别 Warn)用于把 wgpu 内部日志转发到 stderr; - 创建 Surface。桌面平台由 CreateWGPUSurface() 完成——由于 SDL3 目前尚无官方的 WebGPU Surface 接口,该 stub 通过
SDL_GetWindowProperties读取平台原生句柄:Windows 取SDL_PROP_WINDOW_WIN32_HWND_POINTER,macOS 取 CocoaNSWindow,Linux 区分 Wayland(wl_display+wl_surface)与 X11(Display*+ window number),再交给ImGui_ImplWGPU_CreateWGPUSurfaceHelper(接口定义见 imgui_impl_wgpu.h)。Emscripten 下则直接以 CSS 选择器#canvas描述 Surface 源; - 用
wgpuSurfaceGetCapabilities从 Surface 能力中取首选格式,随后wgpuSurfaceConfigure:presentMode=Fifo、alphaMode=Auto、usage=RenderAttachment,并取出WGPUQueue。
ImGui WebGPU 后端初始化参数
示例按 imgui_impl_wgpu.h 的ImGui_ImplWGPU_InitInfo结构初始化(见 main.cpp):
| 字段 | 示例取值 | 说明 |
|---|---|---|
Device | 上一步得到的wgpu_device | WebGPU 设备 |
NumFramesInFlight | 3 | 三缓冲帧资源池(顶点/索引缓冲轮转) |
RenderTargetFormat | Surface 首选格式 | 渲染目标格式,须与 Surface 配置一致 |
DepthStencilFormat | WGPUTextureFormat_Undefined | 本示例无深度模板附件 |
PipelineMultisampleState | count=1,mask 全 1 | 多采样默认关闭 |
头文件还声明了配套 API:ImGui_ImplWGPU_NewFrame、ImGui_ImplWGPU_RenderDrawData(draw_data, pass_encoder)、ImGui_ImplWGPU_CreateDeviceObjects/InvalidateDeviceObjects(设备重建而不丢 ImGui 状态)、ImGui_ImplWGPU_UpdateTexture(动态字体纹理的按需更新),以及辅助函数ImGui_ImplWGPU_IsSurfaceStatusError/IsSurfaceStatusSubOptimal与调试工具ImGui_ImplWGPU_DebugPrintAdapterInfo(初始化时即打印 Adapter 类型/后端类型)。
主循环中的 Surface 状态处理
每帧开头,示例先检查 Surface 纹理状态(main.cpp):
- Error 状态:打印
Unrecoverable Surface Texture status=...后abort()——不可恢复; - SubOptimal 状态:释放当前纹理、按当前窗口像素尺寸重新
ResizeSurface配置 Surface 并continue跳过本帧——这是应对窗口缩放/显示器变化的标准处理,也解释了为何ResizeSurface()同时更新wgpu_surface_configuration与记录宽度/高度。
渲染提交链与缓冲增长策略
每帧的渲染提交(main.cpp)顺序为:ImGui::Render()生成ImDrawData→ 从wgpuSurfaceGetCurrentTexture取得的纹理创建WGPUTextureView→ 构造WGPURenderPassDescriptor(loadOp=Clear、storeOp=Store,清屏色为clear_color预乘 alpha)→wgpuDeviceCreateCommandEncoder+BeginRenderPass→ImGui_ImplWGPU_RenderDrawData(draw_data, pass)→End→Finish得到命令缓冲 →wgpuQueueSubmit→ 原生平台再wgpuSurfacePresent;Dawn 后端最后调用wgpuDeviceTick(注释说明:这是 Dawn 显示验证错误的必要步骤),Emscripten 下没有 present/tick。
后端内部的ImGui_ImplWGPU_RenderDrawData(imgui_impl_wgpu.cpp)实现细节包括:
- 先处理
draw_data->Textures中的纹理更新(动态字体图集支持,对应RendererHasTextures能力); - 帧资源按
frameIndex % numFramesInFlight轮转;当TotalVtxCount/TotalIdxCount超过现有容量时销毁旧缓冲并按“需求 + 5000 顶点 / + 10000 索引”扩容重建; - 所有 DrawList 的顶点/索引用
memcpy拼接进单一连续缓冲,经wgpuQueueWriteBuffer一次性上传; - 大网格支持:通过 16 位索引配合顶点偏移实现 64k+ 顶点渲染(
RendererHasVtxOffset能力,见 imgui_impl_wgpu.h); - 绘制回调支持
DrawCallback_ResetRenderState/SetSamplerLinear/SetSamplerNearest,渲染状态经platform_io.Renderer_RenderState(ImGui_ImplWGPU_RenderState,含 Device 与 RenderPassEncoder)暴露给回调。
Emscripten 专属行为差异
main.cpp 在__EMSCRIPTEN__下:把io.IniFilename置空(禁用 ini 文件读写,与IMGUI_DISABLE_FILE_FUNCTIONS呼应),并用 emscripten_mainloop_stub.h 的EMSCRIPTEN_MAINLOOP_BEGIN/END把主循环包装为浏览器 rAF 驱动;present/Tick段也被#ifndef __EMSCRIPTEN__排除。
八、小结
example_sdl3_wgpu演示了 Dear ImGui 接入 WebGPU 的完整工程形态:桌面端可在 Dawn 源码构建、WGPU-Native 预编译模块、WGVK 三条路线中按构建成本与依赖偏好选择(CMake 通过三个互斥的IMGUI_*_DIR变量切换,并自动定义对应的IMGUI_IMPL_WEBGPU_BACKEND_*宏);Web 端则以 Emscripten 4.0.15+ 配合--use-port=emdawnwebgpu为准,产出index.html/js/wasm三件套,经本地 webserver 在支持 WebGPU 的浏览器中运行。理解CMakeLists.txt的分支逻辑、Makefile.emscripten的 Emscripten 选项组合,以及main.cpp中 Surface 配置/重建与每帧提交链,是复现与改造该示例的关键依据。
【免费下载链接】imguiDear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies项目地址: https://gitcode.com/GitHub_Trending/im/imgui
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考