summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-01-31 13:57:51 +0100
committerskal <pascal.massimino@gmail.com>2026-01-31 13:57:51 +0100
commite3daca37aa134a6885c8ae5c508c3d7f7bfc600a (patch)
tree69578c5e3376603219bc341e8975e289cede9bdd
parent3af9f70bec1f50c980288e2213035693f4b737ce (diff)
Add Windows cross-compilation support (MinGW) and emulation (Wine)
-rw-r--r--.gitignore4
-rw-r--r--CMakeLists.txt85
-rw-r--r--cmake/Toolchain-MinGW-w64.cmake19
-rwxr-xr-xscripts/build_win.sh34
-rwxr-xr-xscripts/fetch_win_deps.sh29
-rwxr-xr-xscripts/run_win.sh9
-rw-r--r--src/gpu/gpu.cc156
-rw-r--r--src/gpu/gpu.h2
-rw-r--r--third_party/glfw3webgpu/glfw3webgpu.c14
9 files changed, 286 insertions, 66 deletions
diff --git a/.gitignore b/.gitignore
index 19f8336..e03779e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,7 @@ src/test_assets_data.cc
assets/final/*.spec
assets/wav/
+build_native/
+build_win/
+third_party/windows/
+wgpu_temp/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 410ebc1..d25065c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,20 +24,58 @@ endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
-# Find wgpu-native (system install)
-find_library(WGPU_LIBRARY NAMES wgpu_native libwgpu_native REQUIRED)
-find_path(WGPU_INCLUDE_DIR NAMES webgpu.h PATH_SUFFIXES webgpu-headers REQUIRED)
+if (DEMO_CROSS_COMPILE_WIN32)
+ # --- Windows Cross-Compilation Configuration ---
+ add_definitions(-DDEMO_CROSS_COMPILE_WIN32)
+ set(WINDOWS_DEPS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/windows")
-include_directories(
- src
- third_party
- ${WGPU_INCLUDE_DIR}
- third_party/glfw3webgpu
-)
+ # WGPU-Native
+ # We use the headers from the fetched deps
+ set(WGPU_INCLUDE_DIR "${WINDOWS_DEPS_DIR}/include/webgpu")
+ # Link against the import library
+ set(WGPU_LIBRARY "${WINDOWS_DEPS_DIR}/lib/libwgpu_native.dll.a")
+
+ # GLFW 3.4
+ set(GLFW3_INCLUDE_DIR "${WINDOWS_DEPS_DIR}/include")
+ set(GLFW3_LIBRARY "${WINDOWS_DEPS_DIR}/lib/libglfw3.a")
+
+ include_directories(
+ src
+ third_party
+ ${WGPU_INCLUDE_DIR}
+ ${GLFW3_INCLUDE_DIR}
+ third_party/glfw3webgpu
+ )
+
+ # Link libraries
+ # ws2_32 is winsock, required by some deps
+ set(DEMO_LIBS
+ ${GLFW3_LIBRARY}
+ ${WGPU_LIBRARY}
+ -lgdi32 -lws2_32 -luser32 -lkernel32 -lshell32 -ladvapi32 -ldwmapi
+ )
-find_package(glfw3 REQUIRED)
+ # Statically link C/C++ runtime to avoid needing extra DLLs
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
-set(DEMO_LIBS glfw ${WGPU_LIBRARY})
+else()
+ # --- Native Build Configuration ---
+
+ # Find wgpu-native (system install)
+ find_library(WGPU_LIBRARY NAMES wgpu_native libwgpu_native REQUIRED)
+ find_path(WGPU_INCLUDE_DIR NAMES webgpu.h PATH_SUFFIXES webgpu-headers REQUIRED)
+
+ include_directories(
+ src
+ third_party
+ ${WGPU_INCLUDE_DIR}
+ third_party/glfw3webgpu
+ )
+
+ find_package(glfw3 REQUIRED)
+
+ set(DEMO_LIBS glfw ${WGPU_LIBRARY})
+endif()
# Platform-specific dependencies
if (APPLE)
@@ -52,15 +90,24 @@ if (APPLE)
"-framework Cocoa"
"-framework QuartzCore"
)
+elseif (DEMO_CROSS_COMPILE_WIN32)
+ # Windows deps already handled above
else()
# Assume Linux/other POSIX-like systems might need these
list(APPEND DEMO_LIBS pthread m dl)
endif()
-# Asset Packing Tool (Always needed for build)
-add_executable(asset_packer
- tools/asset_packer.cc
-)
+# Asset Packing Tool
+if (DEFINED ASSET_PACKER_PATH)
+ # Use externally provided tool (e.g., for cross-compilation)
+ set(ASSET_PACKER_CMD ${ASSET_PACKER_PATH})
+ set(ASSET_PACKER_DEPENDS ${ASSET_PACKER_PATH})
+else()
+ # Build tool as part of the project
+ add_executable(asset_packer tools/asset_packer.cc)
+ set(ASSET_PACKER_CMD $<TARGET_FILE:asset_packer>)
+ set(ASSET_PACKER_DEPENDS asset_packer)
+endif()
# Configure DEMO asset generation
set(DEMO_ASSETS_TXT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/assets/final/demo_assets.txt)
@@ -70,8 +117,8 @@ set(GENERATED_DEMO_ASSETS_DATA_CC ${CMAKE_CURRENT_BINARY_DIR}/src/assets_data.cc
add_custom_command(
OUTPUT ${GENERATED_DEMO_ASSETS_H} ${GENERATED_DEMO_ASSETS_DATA_CC}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/src
- COMMAND $<TARGET_FILE:asset_packer> ${DEMO_ASSETS_TXT_PATH} ${GENERATED_DEMO_ASSETS_H} ${GENERATED_DEMO_ASSETS_DATA_CC}
- DEPENDS asset_packer ${DEMO_ASSETS_TXT_PATH}
+ COMMAND ${ASSET_PACKER_CMD} ${DEMO_ASSETS_TXT_PATH} ${GENERATED_DEMO_ASSETS_H} ${GENERATED_DEMO_ASSETS_DATA_CC}
+ DEPENDS ${ASSET_PACKER_DEPENDS} ${DEMO_ASSETS_TXT_PATH}
COMMENT "Generating demo assets.h and assets_data.cc"
)
@@ -87,8 +134,8 @@ set(GENERATED_TEST_ASSETS_DATA_CC ${CMAKE_CURRENT_BINARY_DIR}/src/test_assets_da
add_custom_command(
OUTPUT ${GENERATED_TEST_ASSETS_H} ${GENERATED_TEST_ASSETS_DATA_CC}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/src
- COMMAND $<TARGET_FILE:asset_packer> ${TEST_ASSETS_TXT_PATH} ${GENERATED_TEST_ASSETS_H} ${GENERATED_TEST_ASSETS_DATA_CC}
- DEPENDS asset_packer ${TEST_ASSETS_TXT_PATH}
+ COMMAND ${ASSET_PACKER_CMD} ${TEST_ASSETS_TXT_PATH} ${GENERATED_TEST_ASSETS_H} ${GENERATED_TEST_ASSETS_DATA_CC}
+ DEPENDS ${ASSET_PACKER_DEPENDS} ${TEST_ASSETS_TXT_PATH}
COMMENT "Generating test assets.h and assets_data.cc"
)
diff --git a/cmake/Toolchain-MinGW-w64.cmake b/cmake/Toolchain-MinGW-w64.cmake
new file mode 100644
index 0000000..57c146a
--- /dev/null
+++ b/cmake/Toolchain-MinGW-w64.cmake
@@ -0,0 +1,19 @@
+set(CMAKE_SYSTEM_NAME Windows)
+
+# Specify the cross compiler
+set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
+set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
+set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
+
+# Where is the target environment located
+set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32 /usr/local/opt/mingw-w64)
+
+# Adjust the default behavior of the FIND_XXX() commands:
+# search for headers and libraries in the target environment,
+# search for programs in the host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+# Define a flag to identify this specific build
+set(DEMO_CROSS_COMPILE_WIN32 ON)
diff --git a/scripts/build_win.sh b/scripts/build_win.sh
new file mode 100755
index 0000000..493e322
--- /dev/null
+++ b/scripts/build_win.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+set -e
+
+# 1. Build native tools (asset_packer)
+echo "Building native tools..."
+cmake -S . -B build_native -DDEMO_BUILD_TOOLS=OFF -DDEMO_BUILD_TESTS=OFF
+cmake --build build_native --target asset_packer
+
+# 2. Cross-compile for Windows
+echo "Cross-compiling for Windows..."
+cmake -S . -B build_win \
+ -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-MinGW-w64.cmake \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DASSET_PACKER_PATH=$(pwd)/build_native/asset_packer \
+ -DDEMO_BUILD_TOOLS=OFF \
+ -DDEMO_BUILD_TESTS=OFF
+
+cmake --build build_win
+
+# 3. Copy runtime DLLs to build_win so we can run it
+cp third_party/windows/lib/wgpu_native.dll build_win/
+
+# Copy MinGW DLLs (pthread, etc.)
+echo "Copying MinGW DLLs..."
+MINGW_BIN=$(dirname $(find /opt/homebrew -name "libwinpthread-1.dll" | grep x86_64 | head -n 1))
+if [ -d "$MINGW_BIN" ]; then
+ cp "$MINGW_BIN/libwinpthread-1.dll" build_win/
+ cp "$MINGW_BIN/libgcc_s_seh-1.dll" build_win/ 2>/dev/null || true
+ cp "$MINGW_BIN/libstdc++-6.dll" build_win/ 2>/dev/null || true
+else
+ echo "Warning: Could not find MinGW DLLs. You might need them to run the exe."
+fi
+
+echo "Build complete. Output: build_win/demo64k.exe"
diff --git a/scripts/fetch_win_deps.sh b/scripts/fetch_win_deps.sh
new file mode 100755
index 0000000..a32f047
--- /dev/null
+++ b/scripts/fetch_win_deps.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+set -e
+set -x
+
+# Create directories
+mkdir -p third_party/windows/lib
+mkdir -p third_party/windows/include/GLFW
+
+echo "Fetching GLFW 3.4..."
+curl -L -o glfw.zip https://github.com/glfw/glfw/releases/download/3.4/glfw-3.4.bin.WIN64.zip
+unzip -q glfw.zip
+cp glfw-3.4.bin.WIN64/lib-mingw-w64/libglfw3.a third_party/windows/lib/
+cp glfw-3.4.bin.WIN64/include/GLFW/* third_party/windows/include/GLFW/
+rm -rf glfw.zip glfw-3.4.bin.WIN64
+
+echo "Fetching wgpu-native v0.19.4.1..."
+curl -L -o wgpu.zip https://github.com/gfx-rs/wgpu-native/releases/download/v0.19.4.1/wgpu-windows-x86_64-release.zip
+unzip -q wgpu.zip -d wgpu_temp
+# Copy import library (renaming for MinGW convention, though it can usually read .lib)
+cp wgpu_temp/wgpu_native.dll.lib third_party/windows/lib/libwgpu_native.dll.a
+# Copy runtime DLL (will be needed next to executable)
+cp wgpu_temp/wgpu_native.dll third_party/windows/lib/wgpu_native.dll
+# Copy headers
+mkdir -p third_party/windows/include/webgpu
+cp wgpu_temp/webgpu.h third_party/windows/include/webgpu/
+cp wgpu_temp/wgpu.h third_party/windows/include/webgpu/
+rm -rf wgpu.zip wgpu_temp
+
+echo "Windows dependencies fetched."
diff --git a/scripts/run_win.sh b/scripts/run_win.sh
new file mode 100755
index 0000000..853a985
--- /dev/null
+++ b/scripts/run_win.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+if [ ! -f build_win/demo64k.exe ]; then
+ echo "Error: build_win/demo64k.exe not found. Run scripts/build_win.sh first."
+ exit 1
+fi
+
+echo "Running with Wine..."
+# Wine might output a lot of debug info, but for now we let it flow.
+wine build_win/demo64k.exe "$@"
diff --git a/src/gpu/gpu.cc b/src/gpu/gpu.cc
index 92c661b..40be1d2 100644
--- a/src/gpu/gpu.cc
+++ b/src/gpu/gpu.cc
@@ -6,20 +6,83 @@
#include "platform.h"
#include <GLFW/glfw3.h>
-#include <webgpu.h>
-#include <wgpu.h>
+#include <math.h>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
-#include <math.h>
#include <vector>
#ifndef STRIP_ALL
#include <iostream>
#endif
+// --- WebGPU Headers & Compatibility ---
+#if defined(DEMO_CROSS_COMPILE_WIN32)
+// Windows (MinGW) using wgpu-native v0.19.4.1
+#include <webgpu/webgpu.h>
+#include <webgpu/wgpu.h>
+
+// Type Shims
+using WGPUStringView = const char *;
+static const char *str_view(const char *str) { return str; }
+static const char *label_view(const char *str) { return str; }
+
+// Renamed Types/Enums
+#define WGPUSType_ShaderSourceWGSL WGPUSType_ShaderModuleWGSLDescriptor
+using WGPUShaderSourceWGSL = WGPUShaderModuleWGSLDescriptor;
+#define WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal \
+ WGPUSurfaceGetCurrentTextureStatus_Success
+#define WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal \
+ WGPUSurfaceGetCurrentTextureStatus_Success
+
+// Callback Mode Shim (Not used in old API signatures, but needed for ifdef
+// logic)
+#define WGPUCallbackMode_WaitAnyOnly 0
+
+// Wait Shim
+static void wgpuInstanceWaitAny(WGPUInstance instance, size_t, void *,
+ uint64_t) {
+ wgpuInstanceProcessEvents(instance);
+}
+
+// Uncaptured Error Callback Helper
+static void set_error_callback(WGPUDevice device,
+ WGPUErrorCallback callback) {
+ wgpuDeviceSetUncapturedErrorCallback(device, callback, nullptr);
+}
+
+#else
+// Native (macOS/Linux) using newer wgpu-native
+#include <webgpu.h>
+#include <wgpu.h>
+
+static WGPUStringView label_view(const char *str) {
+#ifndef STRIP_ALL
+ if (!str)
+ return {nullptr, 0};
+ return {str, strlen(str)};
+#else
+ (void)str;
+ return {nullptr, 0};
+#endif
+}
+
+static WGPUStringView str_view(const char *str) {
+ if (!str)
+ return {nullptr, 0};
+ return {str, strlen(str)};
+}
+
+static void set_error_callback(WGPUDevice device,
+ WGPUErrorCallback callback) {
+ // Handled in descriptor for new API, mostly.
+ // But we can also set it here if needed, or define a no-op if descriptor handles it.
+ // For new API, we set it in WGPUDeviceDescriptor.uncapturedErrorCallbackInfo.
+}
+#endif
+
static WGPUInstance g_instance = nullptr;
static WGPUAdapter g_adapter = nullptr;
static WGPUDevice g_device = nullptr;
@@ -44,30 +107,13 @@ struct Particle {
float color[4]; // r, g, b, a
};
-static WGPUStringView label_view(const char *str) {
-#ifndef STRIP_ALL
- if (!str)
- return {nullptr, 0};
- return {str, strlen(str)};
-#else
- (void)str;
- return {nullptr, 0};
-#endif
-}
-
-static WGPUStringView str_view(const char *str) {
- if (!str)
- return {nullptr, 0};
- return {str, strlen(str)};
-}
-
// --- Helper Functions ---
-GpuBuffer gpu_create_buffer(size_t size, WGPUBufferUsage usage,
+GpuBuffer gpu_create_buffer(size_t size, uint32_t usage,
const void *data) {
WGPUBufferDescriptor desc = {};
desc.label = label_view("GpuBuffer");
- desc.usage = usage;
+ desc.usage = (WGPUBufferUsage)usage; // Cast for C++ strictness with enums
desc.size = size;
desc.mappedAtCreation = (data != nullptr); // Map if we have initial data
@@ -139,10 +185,7 @@ RenderPass gpu_create_render_pass(const char *shader_code,
color_target.writeMask = WGPUColorWriteMask_All;
color_target.blend = nullptr;
- // Add additive blending for particles if it's the particle pass (hacky check
- // based on vertex count or similar? No, let's just enable additive blending
- // for everything for now as it looks cool for the demo, or make it
- // configurable later. For now, simple replacement)
+ // Add additive blending for particles
WGPUBlendState blend = {};
blend.color.srcFactor = WGPUBlendFactor_SrcAlpha;
blend.color.dstFactor = WGPUBlendFactor_One;
@@ -234,45 +277,47 @@ ComputePass gpu_create_compute_pass(const char *shader_code,
#ifndef STRIP_ALL
static void handle_request_adapter(WGPURequestAdapterStatus status,
- WGPUAdapter adapter, WGPUStringView message,
- void *userdata1, void *userdata2) {
+ WGPUAdapter adapter, const char *message,
+ void *userdata) {
if (status == WGPURequestAdapterStatus_Success) {
- *((WGPUAdapter *)userdata1) = adapter;
+ *((WGPUAdapter *)userdata) = adapter;
} else {
- printf("Request adapter failed: %.*s\n", (int)message.length, message.data);
+ printf("Request adapter failed: %s\n", message ? message : "Unknown");
}
}
static void handle_request_device(WGPURequestDeviceStatus status,
- WGPUDevice device, WGPUStringView message,
- void *userdata1, void *userdata2) {
+ WGPUDevice device, const char *message,
+ void *userdata) {
if (status == WGPURequestDeviceStatus_Success) {
- *((WGPUDevice *)userdata1) = device;
+ *((WGPUDevice *)userdata) = device;
} else {
- printf("Request device failed: %.*s\n", (int)message.length, message.data);
+ printf("Request device failed: %s\n", message ? message : "Unknown");
}
}
-static void handle_device_error(WGPUDevice const *device, WGPUErrorType type,
- WGPUStringView message, void *userdata1,
- void *userdata2) {
- printf("WebGPU Error: %.*s\n", (int)message.length, message.data);
+static void handle_device_error(WGPUErrorType type, const char *message,
+ void *userdata) {
+ printf("WebGPU Error: %s\n", message ? message : "Unknown");
}
#else
static void handle_request_adapter(WGPURequestAdapterStatus status,
- WGPUAdapter adapter, WGPUStringView message,
- void *userdata1, void *userdata2) {
+ WGPUAdapter adapter, const char *message,
+ void *userdata) {
if (status == WGPURequestAdapterStatus_Success) {
- *((WGPUAdapter *)userdata1) = adapter;
+ *((WGPUAdapter *)userdata) = adapter;
}
}
static void handle_request_device(WGPURequestDeviceStatus status,
- WGPUDevice device, WGPUStringView message,
- void *userdata1, void *userdata2) {
+ WGPUDevice device, const char *message,
+ void *userdata) {
if (status == WGPURequestDeviceStatus_Success) {
- *((WGPUDevice *)userdata1) = device;
+ *((WGPUDevice *)userdata) = device;
}
}
#endif
+// ... (Shaders omitted for brevity, they are unchanged) ...
+
+
const char *main_shader_wgsl = R"(
struct Uniforms {
audio_peak : f32,
@@ -442,23 +487,39 @@ void gpu_init(GLFWwindow *window) {
adapter_opts.compatibleSurface = g_surface;
adapter_opts.powerPreference = WGPUPowerPreference_HighPerformance;
+#if defined(DEMO_CROSS_COMPILE_WIN32)
+ wgpuInstanceRequestAdapter(g_instance, &adapter_opts, handle_request_adapter,
+ &g_adapter);
+#else
wgpuInstanceRequestAdapter(g_instance, &adapter_opts,
{nullptr, WGPUCallbackMode_WaitAnyOnly,
handle_request_adapter, &g_adapter, nullptr});
+#endif
while (!g_adapter)
wgpuInstanceWaitAny(g_instance, 0, nullptr, 0);
WGPUDeviceDescriptor device_desc = {};
#ifndef STRIP_ALL
+#if !defined(DEMO_CROSS_COMPILE_WIN32)
device_desc.uncapturedErrorCallbackInfo.callback = handle_device_error;
#endif
+#endif
+#if defined(DEMO_CROSS_COMPILE_WIN32)
+ wgpuAdapterRequestDevice(g_adapter, &device_desc, handle_request_device,
+ &g_device);
+#else
wgpuAdapterRequestDevice(g_adapter, &device_desc,
{nullptr, WGPUCallbackMode_WaitAnyOnly,
handle_request_device, &g_device, nullptr});
+#endif
while (!g_device)
wgpuInstanceWaitAny(g_instance, 0, nullptr, 0);
+#if defined(DEMO_CROSS_COMPILE_WIN32) && !defined(STRIP_ALL)
+ set_error_callback(g_device, handle_device_error);
+#endif
+
g_queue = wgpuDeviceGetQueue(g_device);
WGPUSurfaceCapabilities caps = {};
@@ -509,8 +570,9 @@ void gpu_init(GLFWwindow *window) {
g_particle_buffer =
gpu_create_buffer(sizeof(Particle) * NUM_PARTICLES,
- WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst |
- WGPUBufferUsage_Vertex,
+ (WGPUBufferUsage)(WGPUBufferUsage_Storage |
+ WGPUBufferUsage_CopyDst |
+ WGPUBufferUsage_Vertex),
initial_particles.data());
// Initialize Particle Compute Pass
@@ -581,7 +643,9 @@ void gpu_draw(float audio_peak, float aspect_ratio, float time) {
color_attachment.storeOp = WGPUStoreOp_Store;
float flash = audio_peak * 0.2f;
color_attachment.clearValue = {0.05 + flash, 0.1 + flash, 0.2 + flash, 1.0};
+#if !defined(DEMO_CROSS_COMPILE_WIN32)
color_attachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
+#endif
WGPURenderPassDescriptor render_pass_desc = {};
render_pass_desc.colorAttachmentCount = 1;
diff --git a/src/gpu/gpu.h b/src/gpu/gpu.h
index 58b0307..a78c433 100644
--- a/src/gpu/gpu.h
+++ b/src/gpu/gpu.h
@@ -42,7 +42,7 @@ struct ResourceBinding {
// WGPUBufferBindingType_Storage
};
-GpuBuffer gpu_create_buffer(size_t size, WGPUBufferUsage usage,
+GpuBuffer gpu_create_buffer(size_t size, uint32_t usage,
const void *data = nullptr);
ComputePass gpu_create_compute_pass(const char *shader_code,
ResourceBinding *bindings,
diff --git a/third_party/glfw3webgpu/glfw3webgpu.c b/third_party/glfw3webgpu/glfw3webgpu.c
index 27bf9ec..a3f36e6 100644
--- a/third_party/glfw3webgpu/glfw3webgpu.c
+++ b/third_party/glfw3webgpu/glfw3webgpu.c
@@ -136,6 +136,19 @@ WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* windo
HWND hwnd = glfwGetWin32Window(window);
HINSTANCE hinstance = GetModuleHandle(NULL);
+#if defined(DEMO_CROSS_COMPILE_WIN32)
+ // Old API (wgpu-native v0.19)
+ WGPUSurfaceDescriptorFromWindowsHWND fromWindowsHWND;
+ fromWindowsHWND.chain.sType = WGPUSType_SurfaceDescriptorFromWindowsHWND;
+ fromWindowsHWND.chain.next = NULL;
+ fromWindowsHWND.hinstance = hinstance;
+ fromWindowsHWND.hwnd = hwnd;
+
+ WGPUSurfaceDescriptor surfaceDescriptor;
+ surfaceDescriptor.nextInChain = (const WGPUChainedStruct*)&fromWindowsHWND;
+ surfaceDescriptor.label = NULL;
+#else
+ // New API
WGPUSurfaceSourceWindowsHWND fromWindowsHWND;
fromWindowsHWND.chain.sType = WGPUSType_SurfaceSourceWindowsHWND;
fromWindowsHWND.chain.next = NULL;
@@ -145,6 +158,7 @@ WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* windo
WGPUSurfaceDescriptor surfaceDescriptor;
surfaceDescriptor.nextInChain = &fromWindowsHWND.chain;
surfaceDescriptor.label = (WGPUStringView){ NULL, WGPU_STRLEN };
+#endif
return wgpuInstanceCreateSurface(instance, &surfaceDescriptor);
}