From 1ae5376a310910c663aa184b4cf61e5dce0f57eb Mon Sep 17 00:00:00 2001 From: Elie Michel Date: Wed, 3 May 2023 09:35:25 +0200 Subject: [PATCH 1/3] Add glfwCreateWindowWGPUSurface --- CMakeLists.txt | 4 ++ include/GLFW/glfw3.h | 28 ++++++++ src/CMakeLists.txt | 17 +++-- src/webgpu.c | 164 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 src/webgpu.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b51ae96..f7d2bb76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ cmake_dependent_option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on "WIN32" OFF) cmake_dependent_option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON "MSVC" OFF) +option(GLFW_BUILD_WEBGPU "Build support for WebGPU" OFF) set(GLFW_LIBRARY_TYPE "${GLFW_LIBRARY_TYPE}" CACHE STRING "Library type override for GLFW (SHARED, STATIC, OBJECT, or empty to follow BUILD_SHARED_LIBS)") @@ -75,6 +76,9 @@ endif() if (GLFW_BUILD_X11) message(STATUS "Including X11 support") endif() +if (GLFW_BUILD_WEBGPU) + message(STATUS "Including WebGPU support") +endif() #-------------------------------------------------------------------- # Apply Microsoft C runtime library option diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 58b395cd..9a45689f 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -247,6 +247,10 @@ extern "C" { #endif /* OpenGL and OpenGL ES headers */ +#if defined(GLFW_INCLUDE_WEBGPU) + #include +#endif /* webgpu header */ + #if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL) /* GLFW_DLL must be defined by applications that are linking against the DLL * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW @@ -6396,6 +6400,30 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window #endif /*VK_VERSION_1_0*/ +#if defined(WEBGPU_H_) + +/*! @brief Creates a WebGPU surface for the specified window. + * + * This function creates a WGPUSurface object for the specified window. + * + * If the surface cannot be created, this function returns `NULL`. + * + * It is the responsibility of the caller to destroy the window surface. The + * window surface must be destroyed using `wgpuSurfaceDrop` (wgpu-native) or + * `wgpuSurfaceRelease` (Dawn/emscripten). + * + * @param[in] instance The WebGPU instance to create the surface in. + * @param[in] window The window to create the surface for. + * @return The handle of the surface. This is set to `NULL` if an error + * occurred. + * + * @since Added in version 3.4. + * + * @ingroup webgpu + */ +GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* window); + +#endif /* WEBGPU_H_ */ /************************************************************************* * Global definition cleanup diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 01f191c9..8a77ac8c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,9 +3,10 @@ add_library(glfw ${GLFW_LIBRARY_TYPE} "${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h" "${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h" internal.h platform.h mappings.h - context.c init.c input.c monitor.c platform.c vulkan.c window.c - egl_context.c osmesa_context.c null_platform.h null_joystick.h - null_init.c null_monitor.c null_window.c null_joystick.c) + context.c init.c input.c monitor.c platform.c vulkan.c webgpu.c + window.c egl_context.c osmesa_context.c null_platform.h + null_joystick.h null_init.c null_monitor.c null_window.c + null_joystick.c) # The time, thread and module code is shared between all backends on a given OS, # including the null backend, which still needs those bits to be functional @@ -249,7 +250,7 @@ endif() # source files that VS will build (Clang ignores this because we set -std=c99) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") set_source_files_properties(context.c init.c input.c monitor.c platform.c vulkan.c - window.c null_init.c null_joystick.c null_monitor.c + webgpu.c window.c null_init.c null_joystick.c null_monitor.c null_window.c win32_init.c win32_joystick.c win32_module.c win32_monitor.c win32_time.c win32_thread.c win32_window.c wgl_context.c egl_context.c osmesa_context.c PROPERTIES @@ -321,6 +322,14 @@ if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND) endif() endif() +if (GLFW_BUILD_WEBGPU) + target_compile_definitions(glfw PRIVATE _GLFW_BUILD_WEBGPU) + if (APPLE) + target_compile_options(glfw PRIVATE -x objective-c) + target_link_libraries(glfw PRIVATE "-framework Cocoa" "-framework CoreVideo" "-framework IOKit" "-framework QuartzCore") + endif () +endif () + if (GLFW_BUILD_SHARED_LIBRARY) if (WIN32) if (MINGW) diff --git a/src/webgpu.c b/src/webgpu.c new file mode 100644 index 00000000..28448722 --- /dev/null +++ b/src/webgpu.c @@ -0,0 +1,164 @@ +//======================================================================== +// GLFW 3.4 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2022-2023 Elie Michel and the +// wgpu-native authors. +// Most of the code from this file comes from the wgpu-native triangle example: +// https://github.com/gfx-rs/wgpu-native/blob/master/examples/triangle/main.c +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// Please use C89 style variable declarations in this file because VS 2010 +//======================================================================== + +#if defined(_GLFW_BUILD_WEBGPU) + +#include + +#define WGPU_TARGET_MACOS 1 +#define WGPU_TARGET_LINUX_X11 2 +#define WGPU_TARGET_WINDOWS 3 +#define WGPU_TARGET_LINUX_WAYLAND 4 + +#if defined(_WIN32) +#define WGPU_TARGET WGPU_TARGET_WINDOWS +#elif defined(__APPLE__) +#define WGPU_TARGET WGPU_TARGET_MACOS +#elif defined(_GLFW_WAYLAND) +#define WGPU_TARGET WGPU_TARGET_LINUX_WAYLAND +#else +#define WGPU_TARGET WGPU_TARGET_LINUX_X11 +#endif + +#if WGPU_TARGET == WGPU_TARGET_MACOS +#include +#include +#endif + +#include +#if WGPU_TARGET == WGPU_TARGET_MACOS +#define GLFW_EXPOSE_NATIVE_COCOA +#elif WGPU_TARGET == WGPU_TARGET_LINUX_X11 +#define GLFW_EXPOSE_NATIVE_X11 +#elif WGPU_TARGET == WGPU_TARGET_LINUX_WAYLAND +#define GLFW_EXPOSE_NATIVE_WAYLAND +#elif WGPU_TARGET == WGPU_TARGET_WINDOWS +#define GLFW_EXPOSE_NATIVE_WIN32 +#endif +#include + +////////////////////////////////////////////////////////////////////////// +////// GLFW public API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* window) { +#if WGPU_TARGET == WGPU_TARGET_MACOS + { + id metal_layer = NULL; + NSWindow* ns_window = glfwGetCocoaWindow(window); + [ns_window.contentView setWantsLayer : YES] ; + metal_layer = [CAMetalLayer layer]; + [ns_window.contentView setLayer : metal_layer] ; + return wgpuInstanceCreateSurface( + instance, + &(WGPUSurfaceDescriptor){ + .label = NULL, + .nextInChain = + (const WGPUChainedStruct*)&( + WGPUSurfaceDescriptorFromMetalLayer) { + .chain = + (WGPUChainedStruct){ + .next = NULL, + .sType = WGPUSType_SurfaceDescriptorFromMetalLayer, + }, + .layer = metal_layer, + }, + }); + } +#elif WGPU_TARGET == WGPU_TARGET_LINUX_X11 + { + Display* x11_display = glfwGetX11Display(); + Window x11_window = glfwGetX11Window(window); + return wgpuInstanceCreateSurface( + instance, + &(WGPUSurfaceDescriptor){ + .label = NULL, + .nextInChain = + (const WGPUChainedStruct*)&( + WGPUSurfaceDescriptorFromXlibWindow) { + .chain = + (WGPUChainedStruct){ + .next = NULL, + .sType = WGPUSType_SurfaceDescriptorFromXlibWindow, + }, + .display = x11_display, + .window = x11_window, + }, + }); + } +#elif WGPU_TARGET == WGPU_TARGET_LINUX_WAYLAND + { + struct wl_display* wayland_display = glfwGetWaylandDisplay(); + struct wl_surface* wayland_surface = glfwGetWaylandWindow(window); + return wgpuInstanceCreateSurface( + instance, + &(WGPUSurfaceDescriptor){ + .label = NULL, + .nextInChain = + (const WGPUChainedStruct*)&( + WGPUSurfaceDescriptorFromWaylandSurface) { + .chain = + (WGPUChainedStruct){ + .next = NULL, + .sType = + WGPUSType_SurfaceDescriptorFromWaylandSurface, +}, +.display = wayland_display, +.surface = wayland_surface, + }, + }); + } +#elif WGPU_TARGET == WGPU_TARGET_WINDOWS + { + HWND hwnd = glfwGetWin32Window(window); + HINSTANCE hinstance = GetModuleHandle(NULL); + return wgpuInstanceCreateSurface( + instance, + &(WGPUSurfaceDescriptor){ + .label = NULL, + .nextInChain = + (const WGPUChainedStruct*)&( + WGPUSurfaceDescriptorFromWindowsHWND) { + .chain = + (WGPUChainedStruct){ + .next = NULL, + .sType = WGPUSType_SurfaceDescriptorFromWindowsHWND, + }, + .hinstance = hinstance, + .hwnd = hwnd, + }, + }); + } +#else +#error "Unsupported WGPU_TARGET" +#endif +} +#endif /* _GLFW_BUILD_WEBGPU */ From a2f8d94a7b4e8cdef8e66914bee7abae5d6eca71 Mon Sep 17 00:00:00 2001 From: Elie Michel Date: Sun, 8 Oct 2023 10:23:37 +0200 Subject: [PATCH 2/3] Minor coding style changes --- include/GLFW/glfw3.h | 3 +-- src/webgpu.c | 59 ++++++++++++++++++++------------------------ 2 files changed, 28 insertions(+), 34 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 9a45689f..d7f3f08a 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -6409,8 +6409,7 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window * If the surface cannot be created, this function returns `NULL`. * * It is the responsibility of the caller to destroy the window surface. The - * window surface must be destroyed using `wgpuSurfaceDrop` (wgpu-native) or - * `wgpuSurfaceRelease` (Dawn/emscripten). + * window surface must be destroyed using `wgpuSurfaceRelease`. * * @param[in] instance The WebGPU instance to create the surface in. * @param[in] window The window to create the surface for. diff --git a/src/webgpu.c b/src/webgpu.c index 28448722..1b4180ca 100644 --- a/src/webgpu.c +++ b/src/webgpu.c @@ -74,20 +74,19 @@ GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindo { id metal_layer = NULL; NSWindow* ns_window = glfwGetCocoaWindow(window); - [ns_window.contentView setWantsLayer : YES] ; + [ns_window.contentView setWantsLayer : YES]; metal_layer = [CAMetalLayer layer]; - [ns_window.contentView setLayer : metal_layer] ; + [ns_window.contentView setLayer : metal_layer]; return wgpuInstanceCreateSurface( instance, &(WGPUSurfaceDescriptor){ - .label = NULL, + .label = NULL, .nextInChain = (const WGPUChainedStruct*)&( WGPUSurfaceDescriptorFromMetalLayer) { - .chain = - (WGPUChainedStruct){ - .next = NULL, - .sType = WGPUSType_SurfaceDescriptorFromMetalLayer, + .chain = (WGPUChainedStruct){ + .next = NULL, + .sType = WGPUSType_SurfaceDescriptorFromMetalLayer, }, .layer = metal_layer, }, @@ -100,14 +99,13 @@ GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindo return wgpuInstanceCreateSurface( instance, &(WGPUSurfaceDescriptor){ - .label = NULL, + .label = NULL, .nextInChain = (const WGPUChainedStruct*)&( WGPUSurfaceDescriptorFromXlibWindow) { - .chain = - (WGPUChainedStruct){ - .next = NULL, - .sType = WGPUSType_SurfaceDescriptorFromXlibWindow, + .chain = (WGPUChainedStruct){ + .next = NULL, + .sType = WGPUSType_SurfaceDescriptorFromXlibWindow, }, .display = x11_display, .window = x11_window, @@ -121,21 +119,19 @@ GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindo return wgpuInstanceCreateSurface( instance, &(WGPUSurfaceDescriptor){ - .label = NULL, + .label = NULL, .nextInChain = (const WGPUChainedStruct*)&( WGPUSurfaceDescriptorFromWaylandSurface) { - .chain = - (WGPUChainedStruct){ - .next = NULL, - .sType = - WGPUSType_SurfaceDescriptorFromWaylandSurface, -}, -.display = wayland_display, -.surface = wayland_surface, + .chain = (WGPUChainedStruct){ + .next = NULL, + .sType = WGPUSType_SurfaceDescriptorFromWaylandSurface, }, + .display = wayland_display, + .surface = wayland_surface, + }, }); - } + } #elif WGPU_TARGET == WGPU_TARGET_WINDOWS { HWND hwnd = glfwGetWin32Window(window); @@ -143,20 +139,19 @@ GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindo return wgpuInstanceCreateSurface( instance, &(WGPUSurfaceDescriptor){ - .label = NULL, + .label = NULL, .nextInChain = (const WGPUChainedStruct*)&( WGPUSurfaceDescriptorFromWindowsHWND) { - .chain = - (WGPUChainedStruct){ - .next = NULL, - .sType = WGPUSType_SurfaceDescriptorFromWindowsHWND, + .chain = (WGPUChainedStruct){ + .next = NULL, + .sType = WGPUSType_SurfaceDescriptorFromWindowsHWND, + }, + .hinstance = hinstance, + .hwnd = hwnd, }, - .hinstance = hinstance, - .hwnd = hwnd, - }, - }); - } + }); + } #else #error "Unsupported WGPU_TARGET" #endif From 26a8ef471a727a1192ac0766ae5955fedd6ce665 Mon Sep 17 00:00:00 2001 From: Elie Michel Date: Tue, 24 Sep 2024 09:05:39 +0200 Subject: [PATCH 3/3] Upgrade to runtime backend switch and new Dawn --- src/CMakeLists.txt | 7 +- src/webgpu.c | 253 ++++++++++++++++++++++++++------------------- 2 files changed, 150 insertions(+), 110 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 26065b12..d664a523 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -291,9 +291,10 @@ endif() if (GLFW_BUILD_WEBGPU) target_compile_definitions(glfw PRIVATE _GLFW_BUILD_WEBGPU) - if (APPLE) - target_compile_options(glfw PRIVATE -x objective-c) - target_link_libraries(glfw PRIVATE "-framework Cocoa" "-framework CoreVideo" "-framework IOKit" "-framework QuartzCore") + if (GLFW_BUILD_COCOA) + target_compile_options(glfw PRIVATE -x objective-c) + target_link_libraries(glfw PRIVATE "-framework QuartzCore") + set(glfw_PKG_LIBS "${glfw_PKG_LIBS} -framework QuartzCore") endif () endif () diff --git a/src/webgpu.c b/src/webgpu.c index 1b4180ca..3191da0f 100644 --- a/src/webgpu.c +++ b/src/webgpu.c @@ -1,7 +1,7 @@ //======================================================================== // GLFW 3.4 - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2022-2023 Elie Michel and the +// Copyright (c) 2022-2024 Elie Michel and the // wgpu-native authors. // Most of the code from this file comes from the wgpu-native triangle example: // https://github.com/gfx-rs/wgpu-native/blob/master/examples/triangle/main.c @@ -31,129 +31,168 @@ #if defined(_GLFW_BUILD_WEBGPU) -#include +#ifdef __EMSCRIPTEN__ +# define GLFW_EXPOSE_NATIVE_EMSCRIPTEN +# ifndef GLFW_PLATFORM_EMSCRIPTEN // not defined in older versions of emscripten +# define GLFW_PLATFORM_EMSCRIPTEN 0 +# endif +#else // __EMSCRIPTEN__ +# ifdef _GLFW_X11 +# define GLFW_EXPOSE_NATIVE_X11 +# endif +# ifdef _GLFW_WAYLAND +# define GLFW_EXPOSE_NATIVE_WAYLAND +# endif +# ifdef _GLFW_COCOA +# define GLFW_EXPOSE_NATIVE_COCOA +# endif +# ifdef _GLFW_WIN32 +# define GLFW_EXPOSE_NATIVE_WIN32 +# endif +#endif // __EMSCRIPTEN__ -#define WGPU_TARGET_MACOS 1 -#define WGPU_TARGET_LINUX_X11 2 -#define WGPU_TARGET_WINDOWS 3 -#define WGPU_TARGET_LINUX_WAYLAND 4 - -#if defined(_WIN32) -#define WGPU_TARGET WGPU_TARGET_WINDOWS -#elif defined(__APPLE__) -#define WGPU_TARGET WGPU_TARGET_MACOS -#elif defined(_GLFW_WAYLAND) -#define WGPU_TARGET WGPU_TARGET_LINUX_WAYLAND -#else -#define WGPU_TARGET WGPU_TARGET_LINUX_X11 +#ifdef GLFW_EXPOSE_NATIVE_COCOA +# include +# include #endif -#if WGPU_TARGET == WGPU_TARGET_MACOS -#include -#include +#ifndef __EMSCRIPTEN__ +# include #endif -#include -#if WGPU_TARGET == WGPU_TARGET_MACOS -#define GLFW_EXPOSE_NATIVE_COCOA -#elif WGPU_TARGET == WGPU_TARGET_LINUX_X11 -#define GLFW_EXPOSE_NATIVE_X11 -#elif WGPU_TARGET == WGPU_TARGET_LINUX_WAYLAND -#define GLFW_EXPOSE_NATIVE_WAYLAND -#elif WGPU_TARGET == WGPU_TARGET_WINDOWS -#define GLFW_EXPOSE_NATIVE_WIN32 -#endif -#include - ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// -GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* window) { -#if WGPU_TARGET == WGPU_TARGET_MACOS - { - id metal_layer = NULL; - NSWindow* ns_window = glfwGetCocoaWindow(window); - [ns_window.contentView setWantsLayer : YES]; - metal_layer = [CAMetalLayer layer]; - [ns_window.contentView setLayer : metal_layer]; - return wgpuInstanceCreateSurface( - instance, - &(WGPUSurfaceDescriptor){ - .label = NULL, - .nextInChain = - (const WGPUChainedStruct*)&( - WGPUSurfaceDescriptorFromMetalLayer) { - .chain = (WGPUChainedStruct){ - .next = NULL, - .sType = WGPUSType_SurfaceDescriptorFromMetalLayer, - }, - .layer = metal_layer, - }, - }); - } -#elif WGPU_TARGET == WGPU_TARGET_LINUX_X11 - { +WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* window) { +#ifndef __EMSCRIPTEN__ + switch (glfwGetPlatform()) { +#else + // glfwGetPlatform is not available in older versions of emscripten + switch (GLFW_PLATFORM_EMSCRIPTEN) { +#endif + +#ifdef GLFW_EXPOSE_NATIVE_X11 + case GLFW_PLATFORM_X11: { Display* x11_display = glfwGetX11Display(); Window x11_window = glfwGetX11Window(window); - return wgpuInstanceCreateSurface( - instance, - &(WGPUSurfaceDescriptor){ - .label = NULL, - .nextInChain = - (const WGPUChainedStruct*)&( - WGPUSurfaceDescriptorFromXlibWindow) { - .chain = (WGPUChainedStruct){ - .next = NULL, - .sType = WGPUSType_SurfaceDescriptorFromXlibWindow, - }, - .display = x11_display, - .window = x11_window, - }, - }); + +# ifdef WEBGPU_BACKEND_DAWN + WGPUSurfaceSourceXlibWindow fromXlibWindow; + fromXlibWindow.chain.sType = WGPUSType_SurfaceSourceXlibWindow; +# else + WGPUSurfaceDescriptorFromXlibWindow fromXlibWindow; + fromXlibWindow.chain.sType = WGPUSType_SurfaceDescriptorFromXlibWindow; +# endif + fromXlibWindow.chain.next = NULL; + fromXlibWindow.display = x11_display; + fromXlibWindow.window = x11_window; + + WGPUSurfaceDescriptor surfaceDescriptor; + surfaceDescriptor.nextInChain = &fromXlibWindow.chain; + surfaceDescriptor.label = NULL; + + return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); } -#elif WGPU_TARGET == WGPU_TARGET_LINUX_WAYLAND - { +#endif // GLFW_EXPOSE_NATIVE_X11 + +#ifdef GLFW_EXPOSE_NATIVE_WAYLAND + case GLFW_PLATFORM_WAYLAND: { struct wl_display* wayland_display = glfwGetWaylandDisplay(); struct wl_surface* wayland_surface = glfwGetWaylandWindow(window); - return wgpuInstanceCreateSurface( - instance, - &(WGPUSurfaceDescriptor){ - .label = NULL, - .nextInChain = - (const WGPUChainedStruct*)&( - WGPUSurfaceDescriptorFromWaylandSurface) { - .chain = (WGPUChainedStruct){ - .next = NULL, - .sType = WGPUSType_SurfaceDescriptorFromWaylandSurface, - }, - .display = wayland_display, - .surface = wayland_surface, - }, - }); + +# ifdef WEBGPU_BACKEND_DAWN + WGPUSurfaceSourceWaylandSurface fromWaylandSurface; + fromWaylandSurface.chain.sType = WGPUSType_SurfaceSourceWaylandSurface; +# else + WGPUSurfaceDescriptorFromWaylandSurface fromWaylandSurface; + fromWaylandSurface.chain.sType = WGPUSType_SurfaceDescriptorFromWaylandSurface; +# endif + fromWaylandSurface.chain.next = NULL; + fromWaylandSurface.display = wayland_display; + fromWaylandSurface.surface = wayland_surface; + + WGPUSurfaceDescriptor surfaceDescriptor; + surfaceDescriptor.nextInChain = &fromWaylandSurface.chain; + surfaceDescriptor.label = NULL; + + return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); } -#elif WGPU_TARGET == WGPU_TARGET_WINDOWS - { +#endif // GLFW_EXPOSE_NATIVE_WAYLAND + +#ifdef GLFW_EXPOSE_NATIVE_COCOA + case GLFW_PLATFORM_COCOA: { + id metal_layer = [CAMetalLayer layer]; + NSWindow* ns_window = glfwGetCocoaWindow(window); + [ns_window.contentView setWantsLayer : YES] ; + [ns_window.contentView setLayer : metal_layer] ; + +# ifdef WEBGPU_BACKEND_DAWN + WGPUSurfaceSourceMetalLayer fromMetalLayer; + fromMetalLayer.chain.sType = WGPUSType_SurfaceSourceMetalLayer; +# else + WGPUSurfaceDescriptorFromMetalLayer fromMetalLayer; + fromMetalLayer.chain.sType = WGPUSType_SurfaceDescriptorFromMetalLayer; +# endif + fromMetalLayer.chain.next = NULL; + fromMetalLayer.layer = metal_layer; + + WGPUSurfaceDescriptor surfaceDescriptor; + surfaceDescriptor.nextInChain = &fromMetalLayer.chain; + surfaceDescriptor.label = NULL; + + return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); + } +#endif // GLFW_EXPOSE_NATIVE_COCOA + +#ifdef GLFW_EXPOSE_NATIVE_WIN32 + case GLFW_PLATFORM_WIN32: { HWND hwnd = glfwGetWin32Window(window); HINSTANCE hinstance = GetModuleHandle(NULL); - return wgpuInstanceCreateSurface( - instance, - &(WGPUSurfaceDescriptor){ - .label = NULL, - .nextInChain = - (const WGPUChainedStruct*)&( - WGPUSurfaceDescriptorFromWindowsHWND) { - .chain = (WGPUChainedStruct){ - .next = NULL, - .sType = WGPUSType_SurfaceDescriptorFromWindowsHWND, - }, - .hinstance = hinstance, - .hwnd = hwnd, - }, - }); + +# ifdef WEBGPU_BACKEND_DAWN + WGPUSurfaceSourceWindowsHWND fromWindowsHWND; + fromWindowsHWND.chain.sType = WGPUSType_SurfaceSourceWindowsHWND; +# else + WGPUSurfaceDescriptorFromWindowsHWND fromWindowsHWND; + fromWindowsHWND.chain.sType = WGPUSType_SurfaceDescriptorFromWindowsHWND; +# endif + fromWindowsHWND.chain.next = NULL; + fromWindowsHWND.hinstance = hinstance; + fromWindowsHWND.hwnd = hwnd; + + WGPUSurfaceDescriptor surfaceDescriptor; + surfaceDescriptor.nextInChain = &fromWindowsHWND.chain; + surfaceDescriptor.label = NULL; + + return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); + } +#endif // GLFW_EXPOSE_NATIVE_X11 + +#ifdef GLFW_EXPOSE_NATIVE_EMSCRIPTEN + case GLFW_PLATFORM_EMSCRIPTEN: { +# ifdef WEBGPU_BACKEND_DAWN + WGPUSurfaceSourceCanvasHTMLSelector_Emscripten fromCanvasHTMLSelector; + fromCanvasHTMLSelector.chain.sType = WGPUSType_SurfaceSourceCanvasHTMLSelector_Emscripten; +# 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); + } +#endif // GLFW_EXPOSE_NATIVE_X11 + + default: + // Unsupported platform + return NULL; } -#else -#error "Unsupported WGPU_TARGET" -#endif } + #endif /* _GLFW_BUILD_WEBGPU */