From 26a8ef471a727a1192ac0766ae5955fedd6ce665 Mon Sep 17 00:00:00 2001 From: Elie Michel Date: Tue, 24 Sep 2024 09:05:39 +0200 Subject: [PATCH] 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 */