From 2f44430536cf391c2681fa801fbdfc2d83d437d4 Mon Sep 17 00:00:00 2001 From: Sebastian Emanuel Dawid Date: Fri, 15 Aug 2025 23:01:43 +0200 Subject: [PATCH 1/8] Added native support for creating WebGPU surfaces Note that this commit only adds support when running on Wayland. --- include/GLFW/glfw3.h | 39 ++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 10 ++++---- src/internal.h | 42 ++++++++++++++++++++++++++++++++++ src/webgpu.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ src/wl_platform.h | 2 ++ src/wl_window.c | 19 ++++++++++++++++ 6 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 src/webgpu.c diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 79b06288..516852a9 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -115,6 +115,10 @@ extern "C" { * VK_USE_PLATFORM_WIN32_KHR) so we offer our replacement symbols after it. */ +#if defined(GLFW_INCLUDE_WEBGPU) + #include +#endif /* WebGPU header */ + /* It is customary to use APIENTRY for OpenGL function pointer declarations on * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ @@ -6525,6 +6529,41 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window #endif /*VK_VERSION_1_0*/ +#if defined(WEBGPU_H_) + +/*! @brief Provide the address of the `wgpuInstanceCreateSurface` function to GLFW. + * + * This function passes the address provided for the `wgpuInstanceCreateSurface` function + * to GLFW. + * + * @param[in] addr The address of the `wgpuInstanceCreateSurface` function. + * + * @since Added in version 3.5 + * + * @ingroup webgpu + */ +GLFWAPI void glfwSetWGPUInstanceCreateSurfaceAddr(WGPUSurface (*addr)(WGPUInstance, const WGPUSurfaceDescriptor*)); + +/*! @brief Creates a WebGPU surface for the specified window. + * + * This function creates a WebGPU surface for the specified window. + * + * If the surface could not be created this function returns `NULL`. + * + * It is the callers responsibility to destroy the surface. The 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. + * @return The handle of the surface. This is `NULL` if an error occurred. + * + * @since Added in version 3.5 + * + * @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 2cbe8a73..0b482ac3 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 @@ -128,7 +129,8 @@ set_target_properties(glfw PROPERTIES C_STANDARD 99 C_EXTENSIONS OFF DEFINE_SYMBOL _GLFW_BUILD_DLL - FOLDER "GLFW3") + FOLDER "GLFW3" + EXPORT_COMPILE_COMMANDS ON) target_include_directories(glfw PUBLIC "$" diff --git a/src/internal.h b/src/internal.h index 4f097aa8..1ee044c9 100644 --- a/src/internal.h +++ b/src/internal.h @@ -331,6 +331,42 @@ typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,con typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*); #define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr +// forward declare WebGPU types +typedef struct WGPUInstanceImpl* WGPUInstance; +typedef struct WGPUSurfaceImpl* WGPUSurface; + +typedef struct WGPUStringView { + char const * data; + size_t length; +} WGPUStringView; + +typedef enum WGPUSType { + WGPUSType_ShaderSourceSPIRV = 0x00000001, + WGPUSType_ShaderSourceWGSL = 0x00000002, + WGPUSType_RenderPassMaxDrawCount = 0x00000003, + WGPUSType_SurfaceSourceMetalLayer = 0x00000004, + WGPUSType_SurfaceSourceWindowsHWND = 0x00000005, + WGPUSType_SurfaceSourceXlibWindow = 0x00000006, + WGPUSType_SurfaceSourceWaylandSurface = 0x00000007, + WGPUSType_SurfaceSourceAndroidNativeWindow = 0x00000008, + WGPUSType_SurfaceSourceXCBWindow = 0x00000009, + WGPUSType_Force32 = 0x7FFFFFFF +} WGPUSType; + +typedef struct WGPUChainedStruct { + struct WGPUChainedStruct const * next; + WGPUSType sType; +} WGPUChainedStruct; + +typedef struct WGPUSurfaceDescriptor { + WGPUChainedStruct const * nextInChain; + WGPUStringView label; +} WGPUSurfaceDescriptor; + +typedef WGPUSurface (*PFN_wgpuInstanceCreateSurface)(WGPUInstance, const WGPUSurfaceDescriptor*); + +#define wgpuInstanceCreateSurface _glfw.wgpu.instanceCreateSurface + #include "platform.h" #define GLFW_NATIVE_INCLUDE_NONE @@ -759,6 +795,8 @@ struct _GLFWplatform void (*getRequiredInstanceExtensions)(char**); GLFWbool (*getPhysicalDevicePresentationSupport)(VkInstance,VkPhysicalDevice,uint32_t); VkResult (*createWindowSurface)(VkInstance,_GLFWwindow*,const VkAllocationCallbacks*,VkSurfaceKHR*); + // webgpu + WGPUSurface (*createWindowWGPUSurface)(WGPUInstance, _GLFWwindow*); }; // Library global data @@ -875,6 +913,10 @@ struct _GLFWlibrary GLFWbool EXT_headless_surface; } vk; + struct { + PFN_wgpuInstanceCreateSurface instanceCreateSurface; + } wgpu; + struct { GLFWmonitorfun monitor; GLFWjoystickfun joystick; diff --git a/src/webgpu.c b/src/webgpu.c new file mode 100644 index 00000000..7a32cfe3 --- /dev/null +++ b/src/webgpu.c @@ -0,0 +1,54 @@ +//======================================================================== +// GLFW 3.5 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) Sebastian Dawid +// +// 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. +// +//======================================================================== + +#include "internal.h" + +#include +#include + +GLFWAPI void glfwSetWGPUInstanceCreateSurfaceAddr(WGPUSurface (*addr)(WGPUInstance, const WGPUSurfaceDescriptor*)) { + _GLFW_REQUIRE_INIT() + _glfw.wgpu.instanceCreateSurface = addr; +} + +GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL) + + _GLFWwindow* window = (_GLFWwindow*)handle; + + assert(window != NULL); + assert(instance != NULL); + assert(_glfw.wgpu.instanceCreateSurface != NULL); + + if (window->context.client != GLFW_NO_API) + { + _glfwInputError(GLFW_INVALID_VALUE, + "WebGPU: Window surface creation requires the window to have the client API set to GLFW_NO_API"); + return NULL; + }; + + return _glfw.platform.createWindowWGPUSurface(instance, window); +} diff --git a/src/wl_platform.h b/src/wl_platform.h index c3e45693..1f910319 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -678,6 +678,8 @@ void _glfwGetRequiredInstanceExtensionsWayland(char** extensions); GLFWbool _glfwGetPhysicalDevicePresentationSupportWayland(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); +WGPUSurface _glfwCreateWindowWGPUSurfaceWayland(WGPUInstance instance, _GLFWwindow* window); + void _glfwFreeMonitorWayland(_GLFWmonitor* monitor); void _glfwGetMonitorPosWayland(_GLFWmonitor* monitor, int* xpos, int* ypos); void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor, float* xscale, float* yscale); diff --git a/src/wl_window.c b/src/wl_window.c index b33a2262..f19d5a73 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -3326,6 +3326,25 @@ VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance, return err; } +typedef struct WGPUSurfaceSourceWaylandSurface { + WGPUChainedStruct chain; + void * display; + void * surface; +} WGPUSurfaceSourceWaylandSurface; + +WGPUSurface _glfwCreateWindowWGPUSurfaceWayland(WGPUInstance instance, _GLFWwindow* window) { + WGPUSurfaceSourceWaylandSurface waylandSurface; + waylandSurface.chain.sType = WGPUSType_SurfaceSourceWaylandSurface; + waylandSurface.chain.next = NULL; + waylandSurface.surface = window->wl.surface; + waylandSurface.display = _glfw.wl.display; + + WGPUSurfaceDescriptor surfaceDescriptor; + surfaceDescriptor.nextInChain = &waylandSurface.chain; + surfaceDescriptor.label = (WGPUStringView){ NULL, SIZE_MAX }; + + return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); +} ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// From 8dc6a1f00b4bc1bda2d00e2fcb758ada0301ae1c Mon Sep 17 00:00:00 2001 From: Sebastian Emanuel Dawid Date: Fri, 15 Aug 2025 23:12:47 +0200 Subject: [PATCH 2/8] Add surface creation function to wl platform initialization --- src/wl_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wl_init.c b/src/wl_init.c index ef9e4503..f6490c91 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -515,7 +515,8 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform) .getEGLNativeWindow = _glfwGetEGLNativeWindowWayland, .getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsWayland, .getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportWayland, - .createWindowSurface = _glfwCreateWindowSurfaceWayland + .createWindowSurface = _glfwCreateWindowSurfaceWayland, + .createWindowWGPUSurface = _glfwCreateWindowWGPUSurfaceWayland }; void* module = _glfwPlatformLoadModule("libwayland-client.so.0"); From cb0c28908f78ddef154e55a9fc3fda43f2829108 Mon Sep 17 00:00:00 2001 From: Sebastian Emanuel Dawid Date: Fri, 15 Aug 2025 23:38:04 +0200 Subject: [PATCH 3/8] Try loading surface creation function via `dlsym` instead --- include/GLFW/glfw3.h | 13 ------------- src/init.c | 2 ++ src/internal.h | 2 ++ src/webgpu.c | 11 +++++++---- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 516852a9..f920bd7b 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -6531,19 +6531,6 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window #if defined(WEBGPU_H_) -/*! @brief Provide the address of the `wgpuInstanceCreateSurface` function to GLFW. - * - * This function passes the address provided for the `wgpuInstanceCreateSurface` function - * to GLFW. - * - * @param[in] addr The address of the `wgpuInstanceCreateSurface` function. - * - * @since Added in version 3.5 - * - * @ingroup webgpu - */ -GLFWAPI void glfwSetWGPUInstanceCreateSurfaceAddr(WGPUSurface (*addr)(WGPUInstance, const WGPUSurfaceDescriptor*)); - /*! @brief Creates a WebGPU surface for the specified window. * * This function creates a WebGPU surface for the specified window. diff --git a/src/init.c b/src/init.c index dbd5a900..d31d111e 100644 --- a/src/init.c +++ b/src/init.c @@ -402,6 +402,8 @@ GLFWAPI int glfwInit(void) if (!_glfwSelectPlatform(_glfw.hints.init.platformID, &_glfw.platform)) return GLFW_FALSE; + _glfwLoadWGPUInstanceCreateSurfaceAddr(); + if (!_glfw.platform.init()) { terminate(); diff --git a/src/internal.h b/src/internal.h index 1ee044c9..4b860140 100644 --- a/src/internal.h +++ b/src/internal.h @@ -1051,6 +1051,8 @@ GLFWbool _glfwInitVulkan(int mode); void _glfwTerminateVulkan(void); const char* _glfwGetVulkanResultString(VkResult result); +void _glfwLoadWGPUInstanceCreateSurfaceAddr(void); + size_t _glfwEncodeUTF8(char* s, uint32_t codepoint); char** _glfwParseUriList(char* text, int* count); diff --git a/src/webgpu.c b/src/webgpu.c index 7a32cfe3..5b841bc2 100644 --- a/src/webgpu.c +++ b/src/webgpu.c @@ -28,11 +28,14 @@ #include #include - -GLFWAPI void glfwSetWGPUInstanceCreateSurfaceAddr(WGPUSurface (*addr)(WGPUInstance, const WGPUSurfaceDescriptor*)) { - _GLFW_REQUIRE_INIT() - _glfw.wgpu.instanceCreateSurface = addr; +#if defined(_GLFW_WIN32) +// TODO: Implement Window version +#else +#include +void _glfwLoadWGPUInstanceCreateSurfaceAddr() { + _glfw.wgpu.instanceCreateSurface = dlsym(RTLD_DEFAULT, "wgpuInstanceCreateSurface"); } +#endif GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* handle) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL) From 37812b7e36c392a68f617e820f3a113026af8e66 Mon Sep 17 00:00:00 2001 From: Sebastian Emanuel Dawid Date: Fri, 15 Aug 2025 23:39:30 +0200 Subject: [PATCH 4/8] Revert "Try loading surface creation function via `dlsym` instead" This reverts commit cb0c28908f78ddef154e55a9fc3fda43f2829108. --- include/GLFW/glfw3.h | 13 +++++++++++++ src/init.c | 2 -- src/internal.h | 2 -- src/webgpu.c | 11 ++++------- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index f920bd7b..516852a9 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -6531,6 +6531,19 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window #if defined(WEBGPU_H_) +/*! @brief Provide the address of the `wgpuInstanceCreateSurface` function to GLFW. + * + * This function passes the address provided for the `wgpuInstanceCreateSurface` function + * to GLFW. + * + * @param[in] addr The address of the `wgpuInstanceCreateSurface` function. + * + * @since Added in version 3.5 + * + * @ingroup webgpu + */ +GLFWAPI void glfwSetWGPUInstanceCreateSurfaceAddr(WGPUSurface (*addr)(WGPUInstance, const WGPUSurfaceDescriptor*)); + /*! @brief Creates a WebGPU surface for the specified window. * * This function creates a WebGPU surface for the specified window. diff --git a/src/init.c b/src/init.c index d31d111e..dbd5a900 100644 --- a/src/init.c +++ b/src/init.c @@ -402,8 +402,6 @@ GLFWAPI int glfwInit(void) if (!_glfwSelectPlatform(_glfw.hints.init.platformID, &_glfw.platform)) return GLFW_FALSE; - _glfwLoadWGPUInstanceCreateSurfaceAddr(); - if (!_glfw.platform.init()) { terminate(); diff --git a/src/internal.h b/src/internal.h index 4b860140..1ee044c9 100644 --- a/src/internal.h +++ b/src/internal.h @@ -1051,8 +1051,6 @@ GLFWbool _glfwInitVulkan(int mode); void _glfwTerminateVulkan(void); const char* _glfwGetVulkanResultString(VkResult result); -void _glfwLoadWGPUInstanceCreateSurfaceAddr(void); - size_t _glfwEncodeUTF8(char* s, uint32_t codepoint); char** _glfwParseUriList(char* text, int* count); diff --git a/src/webgpu.c b/src/webgpu.c index 5b841bc2..7a32cfe3 100644 --- a/src/webgpu.c +++ b/src/webgpu.c @@ -28,14 +28,11 @@ #include #include -#if defined(_GLFW_WIN32) -// TODO: Implement Window version -#else -#include -void _glfwLoadWGPUInstanceCreateSurfaceAddr() { - _glfw.wgpu.instanceCreateSurface = dlsym(RTLD_DEFAULT, "wgpuInstanceCreateSurface"); + +GLFWAPI void glfwSetWGPUInstanceCreateSurfaceAddr(WGPUSurface (*addr)(WGPUInstance, const WGPUSurfaceDescriptor*)) { + _GLFW_REQUIRE_INIT() + _glfw.wgpu.instanceCreateSurface = addr; } -#endif GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* handle) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL) From 205bf6c768c2de25b706af27152bbbc1381781bc Mon Sep 17 00:00:00 2001 From: Sebastian Emanuel Dawid Date: Fri, 15 Aug 2025 23:57:40 +0200 Subject: [PATCH 5/8] Add WebGPU support to X11 --- src/x11_init.c | 3 ++- src/x11_platform.h | 2 ++ src/x11_window.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/x11_init.c b/src/x11_init.c index 6b34c263..c90babe1 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -1246,7 +1246,8 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) .getEGLNativeWindow = _glfwGetEGLNativeWindowX11, .getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsX11, .getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportX11, - .createWindowSurface = _glfwCreateWindowSurfaceX11 + .createWindowSurface = _glfwCreateWindowSurfaceX11, + .createWindowWGPUSurface = _glfwCreateWindowWGPUSurfaceX11 }; // HACK: If the application has left the locale as "C" then both wide diff --git a/src/x11_platform.h b/src/x11_platform.h index 30326c5b..af1ad314 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -963,6 +963,8 @@ void _glfwGetRequiredInstanceExtensionsX11(char** extensions); GLFWbool _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); VkResult _glfwCreateWindowSurfaceX11(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); +WGPUSurface _glfwCreateWindowWGPUSurfaceX11(WGPUInstance instance, _GLFWwindow* window); + void _glfwFreeMonitorX11(_GLFWmonitor* monitor); void _glfwGetMonitorPosX11(_GLFWmonitor* monitor, int* xpos, int* ypos); void _glfwGetMonitorContentScaleX11(_GLFWmonitor* monitor, float* xscale, float* yscale); diff --git a/src/x11_window.c b/src/x11_window.c index 322349f0..5a60f7a0 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -3282,6 +3282,53 @@ VkResult _glfwCreateWindowSurfaceX11(VkInstance instance, } } +typedef struct WGPUSurfaceSourceXCBWindow { + WGPUChainedStruct chain; + void * connection; + uint32_t window; +} WGPUSurfaceSourceXCBWindow; + +typedef struct WGPUSurfaceSourceXlibWindow { + WGPUChainedStruct chain; + void * display; + uint64_t window; +} WGPUSurfaceSourceXlibWindow; + +WGPUSurface _glfwCreateWindowWGPUSurfaceX11(WGPUInstance instance, _GLFWwindow* window) +{ + WGPUSurfaceDescriptor surfaceDescriptor; + + if (_glfw.x11.x11xcb.handle) + { + WGPUSurfaceSourceXCBWindow xcbSurface; + xcbSurface.chain.sType = WGPUSType_SurfaceSourceXCBWindow; + xcbSurface.chain.next = NULL; + xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display); + if (!connection) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "X11: Failed to retrieve XCB connection"); + return NULL; + } + xcbSurface.connection = connection; + xcbSurface.window = window->x11.handle; + surfaceDescriptor.nextInChain = &xcbSurface.chain; + } + else + { + WGPUSurfaceSourceXlibWindow xlibSurface; + xlibSurface.chain.sType = WGPUSType_SurfaceSourceXlibWindow; + xlibSurface.chain.next = NULL; + xlibSurface.display = _glfw.x11.display; + xlibSurface.window = window->x11.handle; + surfaceDescriptor.nextInChain = &xlibSurface.chain; + } + + surfaceDescriptor.label = (WGPUStringView){ NULL, SIZE_MAX }; + + return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// From 4cbb4db70c5f2f15f4c11c9eb30e544995ded693 Mon Sep 17 00:00:00 2001 From: Sebastian Dawid Date: Sat, 16 Aug 2025 00:30:16 +0200 Subject: [PATCH 6/8] Add WebGPU support for Windows --- src/win32_init.c | 3 ++- src/win32_platform.h | 2 ++ src/win32_window.c | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/win32_init.c b/src/win32_init.c index 6b6e9d08..1a66b976 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -669,7 +669,8 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) .getEGLNativeWindow = _glfwGetEGLNativeWindowWin32, .getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsWin32, .getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportWin32, - .createWindowSurface = _glfwCreateWindowSurfaceWin32 + .createWindowSurface = _glfwCreateWindowSurfaceWin32, + .createWindowWGPUSurface = _glfwCreateWindowWGPUSurfaceWin32 }; *platform = win32; diff --git a/src/win32_platform.h b/src/win32_platform.h index 49cceba6..905c86bb 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -544,6 +544,8 @@ void _glfwGetRequiredInstanceExtensionsWin32(char** extensions); GLFWbool _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); +WGPUSurface _glfwCreateWindowWGPUSurfaceWin32(WGPUInstance instance, _GLFWwindow* window); + void _glfwFreeMonitorWin32(_GLFWmonitor* monitor); void _glfwGetMonitorPosWin32(_GLFWmonitor* monitor, int* xpos, int* ypos); void _glfwGetMonitorContentScaleWin32(_GLFWmonitor* monitor, float* xscale, float* yscale); diff --git a/src/win32_window.c b/src/win32_window.c index 26f9684b..e1a8411a 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2562,6 +2562,26 @@ VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance, return err; } +typedef struct WGPUSurfaceSourceWindowsHWND { + WGPUChainedStruct chain; + void * hinstance; + void * hwnd; +} WGPUSurfaceSourceWindowsHWND; + +WGPUSurface _glfwCreateWindowWGPUSurfaceWin32(WGPUInstance instance, _GLFWwindow *window) { + WGPUSurfaceSourceWindowsHWND windowsSurface; + windowsSurface.chain.sType = WGPUSType_SurfaceSourceWindowsHWND; + windowsSurface.chain.next = NULL; + windowsSurface.hinstance = _glfw.win32.instance; + windowsSurface.hwnd = window->win32.handle; + + WGPUSurfaceDescriptor surfaceDescriptor; + surfaceDescriptor.nextInChain = &windowsSurface.chain; + surfaceDescriptor.label = (WGPUStringView){ NULL, SIZE_MAX }; + + return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); +} + GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); From 44f8a80ade160087d9cb4341467683170f60acf1 Mon Sep 17 00:00:00 2001 From: Sebastian Emanuel Dawid Date: Sat, 16 Aug 2025 00:46:54 +0200 Subject: [PATCH 7/8] Add WebGPU support for MacOS --- src/cocoa_init.m | 3 ++- src/cocoa_platform.h | 2 ++ src/cocoa_window.m | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 15dc4ec4..0df7a330 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -564,7 +564,8 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform) .getEGLNativeWindow = _glfwGetEGLNativeWindowCocoa, .getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsCocoa, .getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportCocoa, - .createWindowSurface = _glfwCreateWindowSurfaceCocoa + .createWindowSurface = _glfwCreateWindowSurfaceCocoa, + .createWindowWGPUSurface = _glfwCreateWindowWGPUSurfaceCocoa }; *platform = cocoa; diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 4d1d66ae..f7fa7b6f 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -276,6 +276,8 @@ void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions); GLFWbool _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); +WGPUSurface _glfwCreateWindowWGPUSurfaceCocoa(WGPUInstance instance, _GLFWwindow* window); + void _glfwFreeMonitorCocoa(_GLFWmonitor* monitor); void _glfwGetMonitorPosCocoa(_GLFWmonitor* monitor, int* xpos, int* ypos); void _glfwGetMonitorContentScaleCocoa(_GLFWmonitor* monitor, float* xscale, float* yscale); diff --git a/src/cocoa_window.m b/src/cocoa_window.m index e69b5fe0..9b5d1bc5 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -2020,6 +2020,26 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, } // autoreleasepool } +typedef struct WGPUSurfaceSourceMetalLayer { + WGPUChainedStruct chain; + void * layer; +} WGPUSurfaceSourceMetalLayer; + +WGPUSurface _glfwCreateWindowWGPUSurfaceCocoa(WGPUInstance instance, _GLFWwindow* window) { + [window->ns.view setLayer:window->ns.layer]; + [window->ns.view setWantsLayer:YES]; + + WGPUSurfaceSourceMetalLayer metalSurface; + metalSurface.chain.next = NULL; + metalSurface.chain.sType = WGPUSType_SurfaceSourceMetalLayer; + metalSurface.layer = window->ns.layer; + + WGPUSurfaceDescriptor surfaceDescriptor; + surfaceDescriptor.nextInChain = &metalSurface.chain; + surfaceDescriptor.label = (WGPUStringView){ NULL, SIZE_MAX }; + + return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); +} ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// From 54fcbc82205cd0ca81e9fb099840c49f25457ac9 Mon Sep 17 00:00:00 2001 From: Sebastian Emanuel Dawid Date: Wed, 27 Aug 2025 00:46:35 +0200 Subject: [PATCH 8/8] Adjust formatting of new code to fit in with the rest of the code --- src/cocoa_window.m | 6 ++++-- src/internal.h | 12 ++++++++---- src/webgpu.c | 6 ++++-- src/win32_window.c | 6 ++++-- src/wl_window.c | 6 ++++-- src/x11_window.c | 6 ++++-- 6 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 9b5d1bc5..e5dc0af3 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -2020,12 +2020,14 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, } // autoreleasepool } -typedef struct WGPUSurfaceSourceMetalLayer { +typedef struct WGPUSurfaceSourceMetalLayer +{ WGPUChainedStruct chain; void * layer; } WGPUSurfaceSourceMetalLayer; -WGPUSurface _glfwCreateWindowWGPUSurfaceCocoa(WGPUInstance instance, _GLFWwindow* window) { +WGPUSurface _glfwCreateWindowWGPUSurfaceCocoa(WGPUInstance instance, _GLFWwindow* window) +{ [window->ns.view setLayer:window->ns.layer]; [window->ns.view setWantsLayer:YES]; diff --git a/src/internal.h b/src/internal.h index 1ee044c9..5e409f5a 100644 --- a/src/internal.h +++ b/src/internal.h @@ -335,12 +335,14 @@ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const c typedef struct WGPUInstanceImpl* WGPUInstance; typedef struct WGPUSurfaceImpl* WGPUSurface; -typedef struct WGPUStringView { +typedef struct WGPUStringView +{ char const * data; size_t length; } WGPUStringView; -typedef enum WGPUSType { +typedef enum WGPUSType +{ WGPUSType_ShaderSourceSPIRV = 0x00000001, WGPUSType_ShaderSourceWGSL = 0x00000002, WGPUSType_RenderPassMaxDrawCount = 0x00000003, @@ -353,12 +355,14 @@ typedef enum WGPUSType { WGPUSType_Force32 = 0x7FFFFFFF } WGPUSType; -typedef struct WGPUChainedStruct { +typedef struct WGPUChainedStruct +{ struct WGPUChainedStruct const * next; WGPUSType sType; } WGPUChainedStruct; -typedef struct WGPUSurfaceDescriptor { +typedef struct WGPUSurfaceDescriptor +{ WGPUChainedStruct const * nextInChain; WGPUStringView label; } WGPUSurfaceDescriptor; diff --git a/src/webgpu.c b/src/webgpu.c index 7a32cfe3..e4155220 100644 --- a/src/webgpu.c +++ b/src/webgpu.c @@ -29,12 +29,14 @@ #include #include -GLFWAPI void glfwSetWGPUInstanceCreateSurfaceAddr(WGPUSurface (*addr)(WGPUInstance, const WGPUSurfaceDescriptor*)) { +GLFWAPI void glfwSetWGPUInstanceCreateSurfaceAddr(WGPUSurface (*addr)(WGPUInstance, const WGPUSurfaceDescriptor*)) +{ _GLFW_REQUIRE_INIT() _glfw.wgpu.instanceCreateSurface = addr; } -GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* handle) { +GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* handle) +{ _GLFW_REQUIRE_INIT_OR_RETURN(NULL) _GLFWwindow* window = (_GLFWwindow*)handle; diff --git a/src/win32_window.c b/src/win32_window.c index e1a8411a..1a1f6ecd 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2562,13 +2562,15 @@ VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance, return err; } -typedef struct WGPUSurfaceSourceWindowsHWND { +typedef struct WGPUSurfaceSourceWindowsHWND +{ WGPUChainedStruct chain; void * hinstance; void * hwnd; } WGPUSurfaceSourceWindowsHWND; -WGPUSurface _glfwCreateWindowWGPUSurfaceWin32(WGPUInstance instance, _GLFWwindow *window) { +WGPUSurface _glfwCreateWindowWGPUSurfaceWin32(WGPUInstance instance, _GLFWwindow *window) +{ WGPUSurfaceSourceWindowsHWND windowsSurface; windowsSurface.chain.sType = WGPUSType_SurfaceSourceWindowsHWND; windowsSurface.chain.next = NULL; diff --git a/src/wl_window.c b/src/wl_window.c index f19d5a73..4a25b48a 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -3326,13 +3326,15 @@ VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance, return err; } -typedef struct WGPUSurfaceSourceWaylandSurface { +typedef struct WGPUSurfaceSourceWaylandSurface +{ WGPUChainedStruct chain; void * display; void * surface; } WGPUSurfaceSourceWaylandSurface; -WGPUSurface _glfwCreateWindowWGPUSurfaceWayland(WGPUInstance instance, _GLFWwindow* window) { +WGPUSurface _glfwCreateWindowWGPUSurfaceWayland(WGPUInstance instance, _GLFWwindow* window) +{ WGPUSurfaceSourceWaylandSurface waylandSurface; waylandSurface.chain.sType = WGPUSType_SurfaceSourceWaylandSurface; waylandSurface.chain.next = NULL; diff --git a/src/x11_window.c b/src/x11_window.c index 5a60f7a0..72a1a6b0 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -3282,13 +3282,15 @@ VkResult _glfwCreateWindowSurfaceX11(VkInstance instance, } } -typedef struct WGPUSurfaceSourceXCBWindow { +typedef struct WGPUSurfaceSourceXCBWindow +{ WGPUChainedStruct chain; void * connection; uint32_t window; } WGPUSurfaceSourceXCBWindow; -typedef struct WGPUSurfaceSourceXlibWindow { +typedef struct WGPUSurfaceSourceXlibWindow +{ WGPUChainedStruct chain; void * display; uint64_t window;