├── .github ├── FUNDING.yml └── workflows │ └── cmake.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── examples ├── .gitignore ├── CMakeLists.txt ├── hello-glfw3webgpu.c └── utils.cmake ├── glfw3webgpu.c └── glfw3webgpu.h /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: eliemichel 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=DNEEF8GDX2EV6¤cy_code=EUR&source=url'] 15 | -------------------------------------------------------------------------------- /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | env: 10 | BUILD_TYPE: Release 11 | 12 | jobs: 13 | build: 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | system: [ Linux-x64, Windows-MSVC-x64, Windows-MSYS-x64, MacOS-x64, MacOS-ARM ] 18 | webgpu-backend: [ DAWN, WGPU ] 19 | link-type: [ SHARED, STATIC ] 20 | build-type: [ Debug, Release ] 21 | 22 | include: 23 | - system: Linux-x64 24 | runner: ubuntu-latest 25 | install-deps: | 26 | sudo apt-get update -y 27 | sudo apt-get install -y libwayland-dev libxkbcommon-dev xorg-dev 28 | 29 | - system: Windows-MSVC-x64 30 | runner: windows-latest 31 | exe-extension: .exe 32 | is-multiconfig: true 33 | 34 | - system: Windows-MSYS-x64 35 | runner: windows-latest 36 | msystem: ucrt64 37 | exe-extension: .exe 38 | 39 | - system: MacOS-ARM 40 | runner: macos-latest 41 | 42 | - system: MacOS-x64 43 | runner: macos-13 44 | 45 | - system: emscripten 46 | runner: ubuntu-latest 47 | webgpu-backend: EMSCRIPTEN 48 | link-type: STATIC 49 | build-type: Release 50 | cmake-wrapper: emcmake 51 | emsdk-version: 3.1.61 52 | 53 | # Latest version of Dawn to not support static linking 54 | exclude: 55 | - webgpu-backend: DAWN 56 | link-type: STATIC 57 | 58 | runs-on: ${{ matrix.runner }} 59 | 60 | steps: 61 | - uses: actions/checkout@v4 62 | 63 | - name: Install dependencies 64 | if: ${{ matrix.install-deps }} 65 | run: ${{ matrix.install-deps }} 66 | 67 | - name: Setup MSYS 68 | if: ${{ matrix.msystem }} 69 | uses: msys2/setup-msys2@v2 70 | with: 71 | msystem: ${{ matrix.msystem }} 72 | pacboy: >- 73 | toolchain:p 74 | cmake:p 75 | ninja:p 76 | 77 | - name: Setup emscripten 78 | if: ${{ matrix.emsdk-version }} 79 | uses: mymindstorm/setup-emsdk@v14 80 | with: 81 | version: ${{ matrix.emsdk-version }} 82 | 83 | - name: Configure CMake 84 | if: ${{ ! matrix.msystem }} 85 | run: > 86 | ${{ matrix.cmake-wrapper }} cmake 87 | -S examples 88 | -B build 89 | -DWEBGPU_BACKEND=${{ matrix.webgpu-backend }} 90 | -D${{ matrix.webgpu-backend }}_LINK_TYPE=${{ matrix.link-type }} 91 | -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} 92 | 93 | - name: Build 94 | if: ${{ ! matrix.msystem }} 95 | run: > 96 | cmake 97 | --build build 98 | --config ${{ matrix.build-type }} 99 | 100 | # This is a hack to work around the lack of ${{ variables }} in 'shell' parameter 101 | # We use the SHELL env variable as the value of 'shell' 102 | - name: Configure CMake (MSYS) 103 | if: ${{ matrix.msystem }} 104 | shell: msys2 {0} 105 | run: > 106 | cmake 107 | -S examples 108 | -B build 109 | -DWEBGPU_BACKEND=${{ matrix.webgpu-backend }} 110 | -D${{ matrix.webgpu-backend }}_LINK_TYPE=${{ matrix.link-type }} 111 | -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} 112 | 113 | - name: Build (MSYS) 114 | if: ${{ matrix.msystem }} 115 | shell: msys2 {0} 116 | run: > 117 | cmake 118 | --build build 119 | --config ${{ matrix.build-type }} 120 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | releases/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This is only meant to be included as a subdirectory in another project. 2 | # It assumes that targets 'glfw' and 'webgpu' exist. 3 | # Look at examples/CMakeLists.txt to see how to use it in a project. 4 | 5 | # The glfw3webgpu target 6 | add_library(glfw3webgpu STATIC glfw3webgpu.c) 7 | target_include_directories(glfw3webgpu PUBLIC .) 8 | target_link_libraries(glfw3webgpu PUBLIC glfw webgpu) 9 | 10 | # Copy compile definitions that are PRIVATE in glfw 11 | if (GLFW_BUILD_COCOA) 12 | target_compile_definitions(glfw3webgpu PRIVATE _GLFW_COCOA) 13 | target_compile_options(glfw3webgpu PRIVATE -x objective-c) 14 | target_link_libraries(glfw3webgpu PRIVATE "-framework Cocoa" "-framework CoreVideo" "-framework IOKit" "-framework QuartzCore") 15 | endif() 16 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | Copyright (c) 2022-2024 Élie Michel and the wgpu-native authors 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CMake Badge 2 | 3 |
4 | 5 | 6 | 7 | Learn WebGPU Logo 8 | 9 | 10 | LearnWebGPU  |  WebGPU-C++  |  WebGPU-distribution
11 | glfw3webgpu  |  sdl2webgpu  |  sdl3webgpu 12 | 13 | Discord | Join us! 14 |
15 | 16 | 17 | GLFW WebGPU Extension 18 | ===================== 19 | 20 | This is an extension for the great [GLFW](https://www.glfw.org/) library for using it with **WebGPU native**. It was written as part of the [Learn WebGPU for native C++](https://eliemichel.github.io/LearnWebGPU) tutorial series. 21 | 22 | Table of Contents 23 | ----------------- 24 | 25 | - [Overview](#overview) 26 | - [Usage](#usage) 27 | - [Example](#example) 28 | - [License](#license) 29 | 30 | Overview 31 | -------- 32 | 33 | This extension simply provides the following function: 34 | 35 | ```C 36 | WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* window); 37 | ``` 38 | 39 | Given a GLFW window, `glfwCreateWindowWGPUSurface` returns a WebGPU *surface* that corresponds to the window's back-end. This is a process that is highly platform-specific, which is why I believe it belongs to GLFW. 40 | 41 | Usage 42 | ----- 43 | 44 | **NB** The current version of this extension is written for GLFW 3.4. Up to version 1.2.0, it was written for GLFW 3.3.8. 45 | 46 | Your project must link to an implementation of WebGPU (providing `webgpu.h`) and of course to GLFW. Then: 47 | 48 | **Option A** If you use CMake, you can simply include this project as a subdirectory with `add_subdirectory(glfw3webgpu)` (see the content of [`CMakeLists.txt`](CMakeLists.txt)). 49 | 50 | **Option B** Just copy [`glfw3webgpu.h`](glfw3webgpu.h) and [`glfw3webgpu.c`](glfw3webgpu.c) to your project's source tree. On MacOS, you must add the compile option `-x objective-c` and the link libraries `-framework Cocoa`, `-framework CoreVideo`, `-framework IOKit`, and `-framework QuartzCore`. 51 | 52 | Example 53 | ------- 54 | 55 | Thanks to this extension it is possible to simply write a fully cross-platform WebGPU hello world: 56 | 57 | ```C 58 | #include "glfw3webgpu.h" 59 | 60 | #define GLFW_INCLUDE_NONE 61 | #include 62 | #include 63 | #include 64 | 65 | int main(int argc, char* argv[]) { 66 | // Init WebGPU 67 | WGPUInstanceDescriptor desc; 68 | desc.nextInChain = NULL; 69 | WGPUInstance instance = wgpuCreateInstance(&desc); 70 | 71 | // Init GLFW 72 | glfwInit(); 73 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 74 | GLFWwindow* window = glfwCreateWindow(640, 480, "Learn WebGPU", NULL, NULL); 75 | 76 | // Here we create our WebGPU surface from the window! 77 | WGPUSurface surface = glfwCreateWindowWGPUSurface(instance, window); 78 | printf("surface = %p", surface); 79 | 80 | // Terminate GLFW 81 | while (!glfwWindowShouldClose(window)) glfwPollEvents(); 82 | glfwDestroyWindow(window); 83 | glfwTerminate(); 84 | 85 | return 0; 86 | } 87 | ``` 88 | 89 | **NB** The linking process depends on the implementation of WebGPU that you are using. You can find detailed instructions for the `wgpu-native` implementation in [this Hello WebGPU chapter](https://eliemichel.github.io/LearnWebGPU/getting-started/hello-webgpu.html). You may also check out [`examples/CMakeLists.txt`](examples/CMakeLists.txt). 90 | 91 | License 92 | ------- 93 | 94 | See [LICENSE.txt](LICENSE.txt). 95 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | webgpu/ 3 | glfw/ 4 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This example comes from https://eliemichel.github.io/LearnWebGPU 2 | cmake_minimum_required(VERSION 3.11.0...3.25.0) 3 | project(glfw3webgpu-examples VERSION 1.0.0 LANGUAGES C) 4 | 5 | include(FetchContent) 6 | include(utils.cmake) 7 | 8 | # Dependencies 9 | if (EMSCRIPTEN) 10 | 11 | add_library(glfw INTERFACE) 12 | target_link_options(glfw INTERFACE -sUSE_GLFW=3) 13 | 14 | add_library(webgpu INTERFACE) 15 | target_link_options(webgpu INTERFACE -sUSE_WEBGPU=1) 16 | function(target_copy_webgpu_binaries) 17 | endfunction() 18 | 19 | else (EMSCRIPTEN) 20 | 21 | FetchContent_Declare( 22 | glfw-light 23 | URL https://eliemichel.github.io/LearnWebGPU/_downloads/6873a344e35ea9f5e4fc7e5cc85d3ab8/glfw-3.4.0-light.zip 24 | URL_HASH MD5=e6684142080457e9227e4f78a6f84fc2 25 | ) 26 | FetchContent_Declare( 27 | webgpu 28 | URL https://github.com/eliemichel/WebGPU-distribution/archive/refs/tags/main-v0.3.0-alpha.zip 29 | URL_HASH MD5=ea1195dc6c7661c36aa13ea5b734b86e 30 | ) 31 | FetchContent_MakeAvailable(glfw-light webgpu) 32 | 33 | endif (EMSCRIPTEN) 34 | 35 | # The glfw3webgpu target 36 | # NB: We specify a second argument only because this is an out-of-tree 37 | # directory, no need to do this in your case. 38 | add_subdirectory(.. glfw3webgpu) 39 | 40 | # Example 41 | add_executable(hello-glfw3webgpu hello-glfw3webgpu.c) 42 | target_link_libraries(hello-glfw3webgpu PRIVATE glfw webgpu glfw3webgpu) 43 | set_target_properties(hello-glfw3webgpu PROPERTIES CXX_STANDARD 17) 44 | target_treat_all_warnings_as_errors(hello-glfw3webgpu) 45 | target_copy_webgpu_binaries(hello-glfw3webgpu) 46 | -------------------------------------------------------------------------------- /examples/hello-glfw3webgpu.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This is an extension of GLFW for WebGPU, abstracting away the details of 3 | * OS-specific operations. 4 | * 5 | * This file is part of the "Learn WebGPU for C++" book. 6 | * https://eliemichel.github.io/LearnWebGPU 7 | * 8 | * MIT License 9 | * Copyright (c) 2022-2024 Elie Michel 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #include "glfw3webgpu.h" 31 | 32 | #define GLFW_INCLUDE_NONE 33 | #include 34 | #include 35 | #include 36 | 37 | int main(int argc, char* argv[]) { 38 | (void)argc; 39 | (void)argv; 40 | 41 | // Init WebGPU 42 | WGPUInstance instance = wgpuCreateInstance(NULL); 43 | 44 | // Init GLFW 45 | glfwInit(); 46 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 47 | GLFWwindow* window = glfwCreateWindow(640, 480, "Learn WebGPU", NULL, NULL); 48 | 49 | // Here we create our WebGPU surface from the window! 50 | WGPUSurface surface = glfwCreateWindowWGPUSurface(instance, window); 51 | printf("surface = %p", (void*)surface); 52 | 53 | // Terminate GLFW 54 | while (!glfwWindowShouldClose(window)) glfwPollEvents(); 55 | glfwDestroyWindow(window); 56 | glfwTerminate(); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /examples/utils.cmake: -------------------------------------------------------------------------------- 1 | function(target_treat_all_warnings_as_errors Target) 2 | # Treat warnings as errors 3 | set_target_properties(${Target} PROPERTIES COMPILE_WARNING_AS_ERROR ON) 4 | 5 | # Turn all warnings on 6 | if (MSVC) 7 | target_compile_options(${Target} PRIVATE /W4) 8 | else() 9 | target_compile_options(${Target} PRIVATE -Wall -Wextra -pedantic) 10 | endif() 11 | endfunction() 12 | -------------------------------------------------------------------------------- /glfw3webgpu.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This is an extension of GLFW for WebGPU, abstracting away the details of 3 | * OS-specific operations. 4 | * 5 | * This file is part of the "Learn WebGPU for C++" book. 6 | * https://eliemichel.github.io/LearnWebGPU 7 | * 8 | * Most of this code comes from the wgpu-native triangle example: 9 | * https://github.com/gfx-rs/wgpu-native/blob/master/examples/triangle/main.c 10 | * 11 | * MIT License 12 | * Copyright (c) 2022-2025 Elie Michel and the wgpu-native authors 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy 15 | * of this software and associated documentation files (the "Software"), to deal 16 | * in the Software without restriction, including without limitation the rights 17 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | * copies of the Software, and to permit persons to whom the Software is 19 | * furnished to do so, subject to the following conditions: 20 | * 21 | * The above copyright notice and this permission notice shall be included in all 22 | * copies or substantial portions of the Software. 23 | * 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | * SOFTWARE. 31 | */ 32 | 33 | #include "glfw3webgpu.h" 34 | 35 | #include 36 | 37 | #include 38 | 39 | #ifdef __EMSCRIPTEN__ 40 | # define GLFW_EXPOSE_NATIVE_EMSCRIPTEN 41 | # ifndef GLFW_PLATFORM_EMSCRIPTEN // not defined in older versions of emscripten 42 | # define GLFW_PLATFORM_EMSCRIPTEN 0 43 | # endif 44 | #else // __EMSCRIPTEN__ 45 | # ifdef _GLFW_X11 46 | # define GLFW_EXPOSE_NATIVE_X11 47 | # endif 48 | # ifdef _GLFW_WAYLAND 49 | # define GLFW_EXPOSE_NATIVE_WAYLAND 50 | # endif 51 | # ifdef _GLFW_COCOA 52 | # define GLFW_EXPOSE_NATIVE_COCOA 53 | # endif 54 | # ifdef _GLFW_WIN32 55 | # define GLFW_EXPOSE_NATIVE_WIN32 56 | # endif 57 | #endif // __EMSCRIPTEN__ 58 | 59 | #ifdef GLFW_EXPOSE_NATIVE_COCOA 60 | # include 61 | # include 62 | #endif 63 | 64 | #ifndef __EMSCRIPTEN__ 65 | # include 66 | #endif 67 | 68 | WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* window) { 69 | #ifndef __EMSCRIPTEN__ 70 | switch (glfwGetPlatform()) { 71 | #else 72 | // glfwGetPlatform is not available in older versions of emscripten 73 | switch (GLFW_PLATFORM_EMSCRIPTEN) { 74 | #endif 75 | 76 | #ifdef GLFW_EXPOSE_NATIVE_X11 77 | case GLFW_PLATFORM_X11: { 78 | Display* x11_display = glfwGetX11Display(); 79 | Window x11_window = glfwGetX11Window(window); 80 | 81 | WGPUSurfaceSourceXlibWindow fromXlibWindow; 82 | fromXlibWindow.chain.sType = WGPUSType_SurfaceSourceXlibWindow; 83 | fromXlibWindow.chain.next = NULL; 84 | fromXlibWindow.display = x11_display; 85 | fromXlibWindow.window = x11_window; 86 | 87 | WGPUSurfaceDescriptor surfaceDescriptor; 88 | surfaceDescriptor.nextInChain = &fromXlibWindow.chain; 89 | surfaceDescriptor.label = (WGPUStringView){ NULL, WGPU_STRLEN }; 90 | 91 | return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); 92 | } 93 | #endif // GLFW_EXPOSE_NATIVE_X11 94 | 95 | #ifdef GLFW_EXPOSE_NATIVE_WAYLAND 96 | case GLFW_PLATFORM_WAYLAND: { 97 | struct wl_display* wayland_display = glfwGetWaylandDisplay(); 98 | struct wl_surface* wayland_surface = glfwGetWaylandWindow(window); 99 | 100 | WGPUSurfaceSourceWaylandSurface fromWaylandSurface; 101 | fromWaylandSurface.chain.sType = WGPUSType_SurfaceSourceWaylandSurface; 102 | fromWaylandSurface.chain.next = NULL; 103 | fromWaylandSurface.display = wayland_display; 104 | fromWaylandSurface.surface = wayland_surface; 105 | 106 | WGPUSurfaceDescriptor surfaceDescriptor; 107 | surfaceDescriptor.nextInChain = &fromWaylandSurface.chain; 108 | surfaceDescriptor.label = (WGPUStringView){ NULL, WGPU_STRLEN }; 109 | 110 | return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); 111 | } 112 | #endif // GLFW_EXPOSE_NATIVE_WAYLAND 113 | 114 | #ifdef GLFW_EXPOSE_NATIVE_COCOA 115 | case GLFW_PLATFORM_COCOA: { 116 | id metal_layer = [CAMetalLayer layer]; 117 | NSWindow* ns_window = glfwGetCocoaWindow(window); 118 | [ns_window.contentView setWantsLayer : YES] ; 119 | [ns_window.contentView setLayer : metal_layer] ; 120 | 121 | WGPUSurfaceSourceMetalLayer fromMetalLayer; 122 | fromMetalLayer.chain.sType = WGPUSType_SurfaceSourceMetalLayer; 123 | fromMetalLayer.chain.next = NULL; 124 | fromMetalLayer.layer = metal_layer; 125 | 126 | WGPUSurfaceDescriptor surfaceDescriptor; 127 | surfaceDescriptor.nextInChain = &fromMetalLayer.chain; 128 | surfaceDescriptor.label = (WGPUStringView){ NULL, WGPU_STRLEN }; 129 | 130 | return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); 131 | } 132 | #endif // GLFW_EXPOSE_NATIVE_COCOA 133 | 134 | #ifdef GLFW_EXPOSE_NATIVE_WIN32 135 | case GLFW_PLATFORM_WIN32: { 136 | HWND hwnd = glfwGetWin32Window(window); 137 | HINSTANCE hinstance = GetModuleHandle(NULL); 138 | 139 | WGPUSurfaceSourceWindowsHWND fromWindowsHWND; 140 | fromWindowsHWND.chain.sType = WGPUSType_SurfaceSourceWindowsHWND; 141 | fromWindowsHWND.chain.next = NULL; 142 | fromWindowsHWND.hinstance = hinstance; 143 | fromWindowsHWND.hwnd = hwnd; 144 | 145 | WGPUSurfaceDescriptor surfaceDescriptor; 146 | surfaceDescriptor.nextInChain = &fromWindowsHWND.chain; 147 | surfaceDescriptor.label = (WGPUStringView){ NULL, WGPU_STRLEN }; 148 | 149 | return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); 150 | } 151 | #endif // GLFW_EXPOSE_NATIVE_WIN32 152 | 153 | #ifdef GLFW_EXPOSE_NATIVE_EMSCRIPTEN 154 | case GLFW_PLATFORM_EMSCRIPTEN: { 155 | # ifdef WEBGPU_BACKEND_EMDAWNWEBGPU 156 | WGPUEmscriptenSurfaceSourceCanvasHTMLSelector fromCanvasHTMLSelector; 157 | fromCanvasHTMLSelector.chain.sType = WGPUSType_EmscriptenSurfaceSourceCanvasHTMLSelector; 158 | fromCanvasHTMLSelector.selector = (WGPUStringView){ "canvas", WGPU_STRLEN }; 159 | # else 160 | WGPUSurfaceDescriptorFromCanvasHTMLSelector fromCanvasHTMLSelector; 161 | fromCanvasHTMLSelector.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector; 162 | fromCanvasHTMLSelector.selector = "canvas"; 163 | # endif 164 | fromCanvasHTMLSelector.chain.next = NULL; 165 | 166 | WGPUSurfaceDescriptor surfaceDescriptor; 167 | surfaceDescriptor.nextInChain = &fromCanvasHTMLSelector.chain; 168 | # ifdef WEBGPU_BACKEND_EMDAWNWEBGPU 169 | surfaceDescriptor.label = (WGPUStringView){ NULL, WGPU_STRLEN }; 170 | # else 171 | surfaceDescriptor.label = NULL; 172 | # endif 173 | return wgpuInstanceCreateSurface(instance, &surfaceDescriptor); 174 | } 175 | #endif // GLFW_EXPOSE_NATIVE_EMSCRIPTEN 176 | 177 | default: 178 | // Unsupported platform 179 | return NULL; 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /glfw3webgpu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This is an extension of GLFW for WebGPU, abstracting away the details of 3 | * OS-specific operations. 4 | * 5 | * This file is part of the "Learn WebGPU for C++" book. 6 | * https://eliemichel.github.io/LearnWebGPU 7 | * 8 | * MIT License 9 | * Copyright (c) 2022-2024 Elie Michel and the wgpu-native authors 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #ifndef _glfw3_webgpu_h_ 31 | #define _glfw3_webgpu_h_ 32 | 33 | #include 34 | #include 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /*! @brief Creates a WebGPU surface for the specified window. 41 | * 42 | * This function creates a WGPUSurface object for the specified window. 43 | * 44 | * If the surface cannot be created, this function returns `NULL`. 45 | * 46 | * It is the responsibility of the caller to destroy the window surface. The 47 | * window surface must be destroyed using `wgpuSurfaceRelease`. 48 | * 49 | * @param[in] instance The WebGPU instance to create the surface in. 50 | * @param[in] window The window to create the surface for. 51 | * @return The handle of the surface. This is set to `NULL` if an error 52 | * occurred. 53 | * 54 | * @ingroup webgpu 55 | */ 56 | WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* window); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | 62 | #endif // _glfw3_webgpu_h_ 63 | --------------------------------------------------------------------------------