Added Dawn WebGPU support.

Added support for Google's Dawn WebGPU implementation.
You control which one's used via the option "SDL_WGPU_LIB" where it's
either "wgpu-native" or "dawn".
This commit is contained in:
The Stickmahn 2026-05-31 16:37:54 +02:00
parent 1629c545f1
commit ea6a51fed7
13 changed files with 227 additions and 22 deletions

View file

@ -383,7 +383,8 @@ dep_option(SDL_RENDER_GPU "Enable the SDL_GPU render driver" ON "SDL_RE
dep_option(SDL_VIVANTE "Use Vivante EGL video driver" ON "${UNIX_SYS};SDL_CPU_ARM32" OFF)
dep_option(SDL_VULKAN "Enable Vulkan support" "${SDL_VULKAN_DEFAULT}" "SDL_VIDEO;ANDROID OR APPLE OR LINUX OR FREEBSD OR OPENBSD OR WINDOWS OR CYGWIN" OFF)
dep_option(SDL_WGPU "Enable experimental WGPU support" "${SDL_WGPU_DEFAULT}" "SDL_VIDEO" OFF)
dep_option(SDL_WGPU_STATIC "Statically link wgpu_native" OFF "SDL_WGPU" OFF)
dep_option(SDL_WGPU_STATIC "Statically link the WebGPU library" OFF "SDL_WGPU" OFF)
option_string(SDL_WGPU_LIB "The library which SDL will use for WebGPU. Either 'wgpu-native' or 'dawn'" "wgpu-native")
dep_option(SDL_RENDER_VULKAN "Enable the Vulkan render driver" ON "SDL_RENDER;SDL_VULKAN" OFF)
dep_option(SDL_METAL "Enable Metal support" ON "APPLE" OFF)
set_option(SDL_OPENVR "Use OpenVR video driver" OFF)
@ -3538,22 +3539,33 @@ elseif(NGAGE)
)
endif()
# wgpu_native static linking shenanigans
# webgpu static linking shenanigans
if (SDL_WGPU_STATIC)
find_library(
WGPU_STATIC_LIB NAMES wgpu_native wgpu_native.lib libwgpu_native
HINTS ${WGPU_STATIC_LIB_DIR} ${CMAKE_SOURCE_DIR}
REQUIRED
)
# FIXME: i don't know how to make it look nice like everything else :(
message("-- wgpu_native -> ${WGPU_STATIC_LIB}")
if (HAVE_DAWN)
find_library(
WGPU_STATIC_LIB NAMES libwebgpu_dawn webgpu_dawn
HINTS ${WGPU_STATIC_LIB_DIR} ${CMAKE_SOURCE_DIR}
REQUIRED
)
message("-- Using Dawn as WebGPU implementation")
elseif(HAVE_WGPU_NATIVE)
find_library(
WGPU_STATIC_LIB NAMES libwgpu_native wgpu_native
HINTS ${WGPU_STATIC_LIB_DIR} ${CMAKE_SOURCE_DIR}
REQUIRED
)
message("-- Using wgpu-native (statically linked) as WebGPU implementation")
endif()
if (SDL_STATIC)
target_link_libraries(SDL3-static PRIVATE ${WGPU_STATIC_LIB})
elseif (SDL_SHARED)
target_link_libraries(SDL3-shared PRIVATE ${WGPU_STATIC_LIB})
endif()
elseif (HAVE_WGPU_NATIVE)
# We don't have to do anything here,
# but we'll still message that we're using wgpu-native (dyn) as our WebGPU lib.
message("-- Using wgpu-native (dynamically linked) as WebGPU implementation")
endif()
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/SDL_dialog.c)

View file

@ -946,8 +946,39 @@ macro(CheckWGPU)
if(SDL_WGPU)
set(SDL_VIDEO_WGPU 1)
if(SDL_WGPU_LIB STREQUAL "dawn")
set(WGPU_DAWN 1)
set(HAVE_DAWN TRUE)
# Dawn's a C++ library, so we'll have to enable C++
enable_language(CXX)
# Dawn includes
if(HAVE_WAYLAND)
sdl_sources("${SDL3_SOURCE_DIR}/src/video/wayland/SDL_waylandwgpu_dawn.cpp")
endif()
if(HAVE_X11)
sdl_sources("${SDL3_SOURCE_DIR}/src/video/x11/SDL_x11wgpu_dawn.cpp")
endif()
if(WINDOWS)
sdl_sources("${SDL3_SOURCE_DIR}/src/video/windows/SDL_windowswgpu_dawn.cpp")
endif()
elseif(SDL_WGPU_LIB STREQUAL "wgpu-native")
set(WGPU_NATIVE 1)
set(HAVE_WGPU_NATIVE TRUE)
else()
message(FATAL_ERROR "SDL_WGPU_LIB is neither 'wgpu-native' nor 'dawn'!")
endif()
if(SDL_WGPU_STATIC)
set(WGPU_STATIC 1)
elseif(SDL_WGPU_LIB STREQUAL "dawn")
# SDL's been configured to use Dawn & dynamic linking, however; Dawn does not support dynamic linking.
# FIXME: I don't know if this should error out? Maybe just toggle on static link and warn the user?
message(FATAL_ERROR "SDL has been configured to use Dawn as its WebGPU implementation, however, it has also been configured to dynamically link the WebGPU library.\nDawn does not support dynamic linking.")
endif()
endif()
endmacro()

View file

@ -490,6 +490,8 @@
/* Enable experimental WGPU support */
#cmakedefine SDL_VIDEO_WGPU 1
#cmakedefine WGPU_STATIC 1
#cmakedefine WGPU_NATIVE 1
#cmakedefine WGPU_DAWN 1
/* Enable GPU support */
#cmakedefine SDL_GPU_D3D11 1

View file

@ -30,6 +30,15 @@
#include "SDL_internal.h"
// define to prevent C++ name mangling on extern functions
#ifdef WGPU_DAWN
#define WGPU_EXTERN extern "C"
#endif
#ifdef WGPU_NATIVE
#define WGPU_EXTERN extern
#endif
#ifndef WEBGPU_H_
#define NO_WEBGPU_HEADER
#endif
@ -104,8 +113,6 @@ typedef struct WGPUSurfaceSourceWindowsHWND {
typedef WGPUSurface (*WGPUProcInstanceCreateSurface)(WGPUInstance instance, WGPUSurfaceDescriptor const *descriptor) WGPU_FUNCTION_ATTRIBUTE;
#if defined(WGPU_STATIC)
extern WGPUSurface wgpuInstanceCreateSurface(WGPUInstance instance, WGPUSurfaceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE;
#endif
WGPU_EXTERN WGPUSurface wgpuInstanceCreateSurface(WGPUInstance instance, WGPUSurfaceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE;
#endif

View file

@ -4,7 +4,19 @@
#include <SDL3/SDL_wgpu.h>
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_WAYLAND)
extern WGPUSurface Wayland_WGPU_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, WGPUInstance instance);
// Dawn's a C++ lib so we'll have to do this to prevent any name mangling.
#ifdef __cplusplus
extern "C" {
#else
extern
#endif
WGPUSurface Wayland_WGPU_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, WGPUInstance instance);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,46 @@
// NOTE:
// Dawn's a C++ library.
// So, if you want to use C++, you have to have a .cpp file.
// The code in this file is largely identical to the native one.
// A couple changes though:
// C++ isn't a fan of forward declaring enums, so we can't use SDL_waylandvideo.h,
// but that's fine; we're not using anything that isn't in SDL_sysvideo.h.
// I also had to add a cast for SDL_GetPointerProperty to wl_display/surface.
#include "SDL_internal.h"
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_WAYLAND) && defined(WGPU_DAWN)
#include "../SDL_wgpu_defs.h"
#include "../SDL_sysvideo.h"
#include "SDL_waylandwgpu.h"
#include <SDL3/SDL_wgpu.h>
WGPUSurface
Wayland_WGPU_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, WGPUInstance instance)
{
SDL_PropertiesID windowProperties = SDL_GetWindowProperties(window);
struct wl_display *display = (wl_display*)SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, 0);
struct wl_surface *surface = (wl_surface*)SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, 0);
WGPUSurfaceDescriptor desc;
WGPUSurfaceSourceWaylandSurface source;
source.chain.sType = WGPUSType_SurfaceSourceWaylandSurface;
source.chain.next = NULL;
source.surface = surface;
source.display = display;
// TODO: I don't know the convention on what label the surface should have?
// I'll just leave it NULL for now. - TheStickmahn
desc.label = (WGPUStringView){ NULL, WGPU_STRLEN };
desc.nextInChain = &source.chain;
// Dawn doesn't support dynamically loading, so we're just always using wgpuInstanceCreateSurface.
return wgpuInstanceCreateSurface(instance, &desc);
}
#endif

View file

@ -1,6 +1,6 @@
#include "SDL_internal.h"
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_WAYLAND)
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_WAYLAND) && defined(WGPU_NATIVE)
#include "SDL_waylandvideo.h"
#include "../SDL_wgpu_defs.h"

View file

@ -6,7 +6,20 @@
#include <SDL3/SDL_wgpu.h>
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_WINDOWS)
extern WGPUSurface WIN_WGPU_CreateSurface(SDL_VSDL_VideoDevice *_this, SDL_Window *window, WGPUInstance instance);
// Dawn's a C++ lib so we'll have to do this to prevent any name mangling.
#ifdef __cplusplus
extern "C" {
#else
extern
#endif
WGPUSurface WIN_WGPU_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, WGPUInstance instance);
#ifdef __cplusplus
}
#endif
#endif
#endif // SDL_windowswgpu_h_

View file

@ -0,0 +1,32 @@
// NOTE: Again, Dawn's a C++ library.
#include "SDL_internal.h"
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_WINDOWS) && defined(WGPU_NATIVE)
#include "SDL_windowsvideo.h"
#include "../SDL_wgpu_defs.h"
#include "SDL_windoiwswgpu.h"
WGPUSurface WIN_WGPU_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, WGPUInstance instance)
{
SDL_PropertiesID windowProperties = SDL_GetWindowProperties(window);
void *hwnd = SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WIN32_HWND_POINTER, 0);
void *hinstance = SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WIN32_INSTANCE_POINTER, 0);
WGPUSurfaceDescriptor desc;
WGPUSurfaceSourceWindowsHWND source;
source.hwnd = hwnd;
source.hinstance = hinstance;
source.chain.sType = WGPUSType_SurfaceSourceXlibWindow;
source.chain.next = NULL;
desc.label = (WGPUStringView){ NULL, WGPU_STRLEN };
desc.nextInChain = &source.chain;
return wgpuInstanceCreateSurface(instance, &desc);
}
#endif

View file

@ -1,7 +1,7 @@
#include "SDL_internal.h"
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_WINDOWS)
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_WINDOWS) && defined(WGPU_NATIVE)
#include "SDL_windowsvideo.h"
#include "../SDL_wgpu_defs.h"

View file

@ -1,10 +1,22 @@
#ifndef SDL_x11wgpu_h_
#define SDL_x11wgpu_h_
#ifndef SDL_waylandwgpu_h_
#define SDL_waylandwgpu_h_
#include <SDL3/SDL_wgpu.h>
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_X11)
extern WGPUSurface X11_WGPU_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, WGPUInstance instance);
#ifdef __cplusplus
extern "C" {
#else
extern
#endif
#endif // SDL_x11wgpu_h_
WGPUSurface X11_WGPU_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, WGPUInstance instance);
#ifdef __cplusplus
}
#endif
#endif
#endif // SDL_waylandwgpu_h_

View file

@ -0,0 +1,37 @@
// NOTE: Again, Dawn is a C++ library.
// We had to remove SDL_x11video.h since that uses the register keyword which was removed in C++17.
// That means we can't use Display, but that's not an issue since we're using a pointer to Display, which is a struct.
// We'll just make it a generic struct pointer.
#include "SDL_internal.h"
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_X11) && defined(WGPU_DAWN)
#include "../SDL_wgpu_defs.h"
#include "../SDL_sysvideo.h"
#include "SDL_x11wgpu.h"
#include <SDL3/SDL_wgpu.h>
WGPUSurface X11_WGPU_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, WGPUInstance instance)
{
SDL_PropertiesID windowProperties = SDL_GetWindowProperties(window);
struct Display *x11_display = (Display*)SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, 0);
int x11_window = SDL_GetNumberProperty(windowProperties, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
WGPUSurfaceDescriptor desc;
WGPUSurfaceSourceXlibWindow source;
source.window = x11_window;
source.display = x11_display;
source.chain.sType = WGPUSType_SurfaceSourceXlibWindow;
source.chain.next = NULL;
desc.label = (WGPUStringView){ NULL, WGPU_STRLEN };
desc.nextInChain = &source.chain;
return wgpuInstanceCreateSurface(instance, &desc);
}
#endif

View file

@ -1,6 +1,7 @@
#include "SDL_internal.h"
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_X11)
#if defined(SDL_VIDEO_WGPU) && defined(SDL_VIDEO_DRIVER_X11) && defined(WGPU_NATIVE)
#include "SDL_x11video.h"
#include "../SDL_wgpu_defs.h"