I have found a temporary solution in my issue: How to fix `sdl3webgpu` to run a simple example in January 2026 · Issue #7 · eliemichel/sdl3webgpu · GitHub This is a copy of the solution below from the issue.
Maybe it will be useful for someone who want to start to practice with WebGPU using SDL3 to create apps in C or C++ for Windows and Web (using Emscripten and WebAssembly). You need to copy two files in your project: sdl3webgpu.h and sdl3webgpu.c. Maybe someone will write how to improve something.
I use this version of the sdl3webgpu: GitHub - eliemichel/sdl3webgpu at 4fa9d70935e41c075f664b231ee10a64262a8ac7 That commit was created 9 month ago. It is the last commit at this moment.
At first time it did not work but Gemini 3 helped to fix it:
Before:
sdl3webgpu.h
WGPUSurface SDL_GetWGPUSurface(WGPUInstance instance, SDL_Window* window);
After:
WGPUSurface wgpuSurfaceCreateFromSDLWindow(WGPUInstance instance, SDL_Window *window);
Before:
sdl3webgpu.c
SDL_GetWGPUSurface(WGPUInstance instance, SDL_Window *window)
After:
WGPUSurface wgpuSurfaceCreateFromSDLWindow(WGPUInstance instance, SDL_Window *window)
Before:
sdl3webgpu.c
#elif defined(__EMSCRIPTEN__)
{
#ifdef WEBGPU_BACKEND_EMDAWNWEBGPU
WGPUEmscriptenSurfaceSourceCanvasHTMLSelector fromCanvasHTMLSelector;
fromCanvasHTMLSelector.chain.sType = WGPUSType_EmscriptenSurfaceSourceCanvasHTMLSelector;
#else
WGPUSurfaceDescriptorFromCanvasHTMLSelector fromCanvasHTMLSelector;
fromCanvasHTMLSelector.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
#endif
fromCanvasHTMLSelector.chain.next = NULL;
fromCanvasHTMLSelector.selector = "canvas";
WGPUSurfaceDescriptor surfaceDescriptor;
surfaceDescriptor.nextInChain = &fromCanvasHTMLSelector.chain;
surfaceDescriptor.label = NULL;
return wgpuInstanceCreateSurface(instance, &surfaceDescriptor);
}
After:
#elif defined(__EMSCRIPTEN__)
{
// Emscripten/Dawn naming convention
WGPUSurfaceDescriptorFromCanvasHTMLSelector fromCanvasHTMLSelector;
fromCanvasHTMLSelector.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
fromCanvasHTMLSelector.chain.next = NULL;
fromCanvasHTMLSelector.selector = "canvas";
WGPUSurfaceDescriptor surfaceDescriptor;
surfaceDescriptor.nextInChain = &fromCanvasHTMLSelector.chain;
surfaceDescriptor.label = NULL; // On Web this is usually just a char*
return wgpuInstanceCreateSurface(instance, &surfaceDescriptor);
}
Source code of the simple example: webgpu-sdl3-c.zip (9.2 KB). This example simply changes the background color over time.
Now I can compile and run this simple example with SDL3 for Windows and Web. I use these commands on Windows:
config-exe
build-exe
run-exe
These are batch files - see my archive with a source code above.
So, it is my first window in WebGPU for Windows: webgpu-sdl3-c-exe.zip (zip: 5.43 MB, unzipped: 15.9 MB)
I can build my example with Emscripten/WebAssembly and upload to Vercel: https://webgpu-sdl3-c.vercel.app/
vercel login
vercel
Run vercel --prod to overwrite later.
Libs for Windows and WASM that my example uses:
- CMake 4.0.3
- Emscripten 4.0.15
- MinGW GCC 11.2
- wgpu-windows-x86_64-gnu-release-27.0.4.0.zip (Release v27.0.4.0 · gfx-rs/wgpu-native · GitHub)
- SDL3-3.4.0-win32-x64.zip (1.1 MB)
- SDL3-devel-3.4.0-mingw.zip (2.6 MB)
- SDL3-devel-3.4.0-wasm.zip (1.2 MB)
I use CMake and absolute paths for libs:
CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(webgpu-sdl3-c)
add_executable(app)
# 1. Set the path to where you unzipped wgpu-native
set(WGPU_PATH "H:/libs/wgpu-windows-x86_64-gnu-release-27.0.4.0")
target_sources(app PRIVATE
src/main.c
src/sdl3webgpu.h
src/sdl3webgpu.c
)
if (EMSCRIPTEN)
# This prevents the "linker setting ignored during compilation" warning
target_link_options(app PRIVATE "-sUSE_WEBGPU=1")
# This tells Emscripten to link the WebGPU library
target_link_libraries(app PRIVATE "webgpu")
set(SDL3_DIR "H:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3")
elseif (WIN32)
list(APPEND CMAKE_PREFIX_PATH "H:/libs/SDL3-devel-3.4.0-mingw")
target_link_libraries(app PRIVATE "${WGPU_PATH}/lib/libwgpu_native.dll.a")
else()
message(WARNING "Unknown platform!")
endif()
find_package(SDL3 REQUIRED)
# Only include the Windows WGPU path if we are NOT on Emscripten
if (NOT EMSCRIPTEN)
target_include_directories(app PRIVATE ${WGPU_PATH}/include)
endif()
target_link_libraries(app PRIVATE SDL3::SDL3)
# Copy the DLL to the folder where your .exe is
add_custom_command(TARGET app POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${WGPU_PATH}/bin/wgpu_native.dll" $<TARGET_FILE_DIR:app>
)


