From 16c2cdce6ad1d89d3c537f2c2cff743449925125 Mon Sep 17 00:00:00 2001 From: skal Date: Sun, 8 Feb 2026 08:33:55 +0100 Subject: feat(platform): Centralize platform-specific WebGPU code and improve shader composition --- src/platform/platform.cc | 87 +++++++++++++++++++++++++++++++++++++++++++++++- src/platform/platform.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+), 1 deletion(-) (limited to 'src/platform') diff --git a/src/platform/platform.cc b/src/platform/platform.cc index 29b3af3..2b8529a 100644 --- a/src/platform/platform.cc +++ b/src/platform/platform.cc @@ -5,6 +5,7 @@ #include "platform/platform.h" #include "glfw3webgpu.h" #include +#include // --- Callbacks --- @@ -128,4 +129,88 @@ WGPUSurface platform_create_wgpu_surface(WGPUInstance instance, double platform_get_time() { return glfwGetTime(); -} \ No newline at end of file +} + +// --- WebGPU Request Helpers --- + +#if defined(DEMO_CROSS_COMPILE_WIN32) +static void _platform_adapter_cb_win32(WGPURequestAdapterStatus status, + WGPUAdapter adapter, const char* message, + void* userdata) { + if (status == WGPURequestAdapterStatus_Success) { + *((WGPUAdapter*)userdata) = adapter; + } else { + printf("Request adapter failed: %s\n", message ? message : "Unknown"); + } +} + +void platform_wgpu_request_adapter(WGPUInstance instance, + const WGPURequestAdapterOptions* options, + WGPUAdapter* out_adapter) { + wgpuInstanceRequestAdapter(instance, options, _platform_adapter_cb_win32, + out_adapter); +} + +static void _platform_device_cb_win32(WGPURequestDeviceStatus status, + WGPUDevice device, const char* message, + void* userdata) { + if (status == WGPURequestDeviceStatus_Success) { + *((WGPUDevice*)userdata) = device; + } else { + printf("Request device failed: %s\n", message ? message : "Unknown"); + } +} + +void platform_wgpu_request_device(WGPUAdapter adapter, + const WGPUDeviceDescriptor* descriptor, + WGPUDevice* out_device) { + wgpuAdapterRequestDevice(adapter, descriptor, _platform_device_cb_win32, + out_device); +} + +#else + +static void _platform_adapter_cb_native(WGPURequestAdapterStatus status, + WGPUAdapter adapter, + WGPUStringView message, void* userdata, + void* userdata2) { + (void)userdata2; + if (status == WGPURequestAdapterStatus_Success) { + *((WGPUAdapter*)userdata) = adapter; + } else { + printf("Request adapter failed: %.*s\n", (int)message.length, message.data); + } +} + +void platform_wgpu_request_adapter(WGPUInstance instance, + const WGPURequestAdapterOptions* options, + WGPUAdapter* out_adapter) { + WGPURequestAdapterCallbackInfo cb = {}; + cb.mode = WGPUCallbackMode_WaitAnyOnly; + cb.callback = _platform_adapter_cb_native; + cb.userdata1 = out_adapter; + wgpuInstanceRequestAdapter(instance, options, cb); +} + +static void _platform_device_cb_native(WGPURequestDeviceStatus status, + WGPUDevice device, + WGPUStringView message, void* userdata, + void* userdata2) { + (void)userdata2; + if (status == WGPURequestDeviceStatus_Success) { + *((WGPUDevice*)userdata) = device; + } else { + printf("Request device failed: %.*s\n", (int)message.length, message.data); + } +} + +void platform_wgpu_request_device(WGPUAdapter adapter, + const WGPUDeviceDescriptor* descriptor, + WGPUDevice* out_device) { + WGPURequestDeviceCallbackInfo cb = {}; + cb.mode = WGPUCallbackMode_WaitAnyOnly; + cb.callback = _platform_device_cb_native; + cb.userdata1 = out_device; + wgpuAdapterRequestDevice(adapter, descriptor, cb); +} +#endif diff --git a/src/platform/platform.h b/src/platform/platform.h index 0a98850..ddea7af 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -22,6 +22,9 @@ #define WGPUCallbackMode_WaitAnyOnly 0 typedef WGPUShaderModuleWGSLDescriptor WGPUShaderSourceWGSL; +// Texture compatibility typedefs +typedef WGPUImageCopyTexture WGPU_TEX_COPY_INFO; +typedef WGPUTextureDataLayout WGPU_TEX_DATA_LAYOUT; static inline const char* str_view(const char* str) { return str; @@ -39,10 +42,44 @@ platform_wgpu_set_error_callback(WGPUDevice device, wgpuDeviceSetUncapturedErrorCallback(device, callback, nullptr); } +// Helper to create a WGPUShaderModuleDescriptor with platform-specific chain +static inline WGPUShaderModuleDescriptor platform_create_shader_module_descriptor( + const char* shader_code) { + WGPUShaderSourceWGSL* wgsl_src = new WGPUShaderSourceWGSL(); + wgsl_src->chain.sType = WGPUSType_ShaderSourceWGSL; + wgsl_src->code = str_view(shader_code); + + WGPUShaderModuleDescriptor shader_desc = {}; + shader_desc.nextInChain = &wgsl_src->chain; + shader_desc.label = label_view(nullptr); // Use label_view for cross-platform compatibility + + return shader_desc; +} + +// Macro to set the depth stencil state for render pipelines +#define PLATFORM_SET_PIPELINE_DEPTH_STENCIL(pipeline_desc, depth_stencil_state_ptr) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wuninitialized\"") \ + _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") \ + do { \ + if (depth_stencil_state_ptr) { \ + if (defined(DEMO_CROSS_COMPILE_WIN32)) { \ + (pipeline_desc).depthStencilState = *(depth_stencil_state_ptr); \ + } else { \ + (pipeline_desc).depthStencil = (depth_stencil_state_ptr); \ + } \ + } \ + } while (0) \ + _Pragma("clang diagnostic pop") + #else #include #include +// Texture compatibility typedefs +typedef WGPUTexelCopyTextureInfo WGPU_TEX_COPY_INFO; +typedef WGPUTexelCopyBufferLayout WGPU_TEX_DATA_LAYOUT; + static inline WGPUStringView str_view(const char* str) { if (!str) return {nullptr, 0}; @@ -69,8 +106,55 @@ platform_wgpu_set_error_callback(WGPUDevice device, // Handled in descriptor for new API, but provided for compatibility if needed // elsewhere } + +// Helper to create a WGPUShaderModuleDescriptor with platform-specific chain +static inline WGPUShaderModuleDescriptor platform_create_shader_module_descriptor( + const char* shader_code) { + WGPUShaderModuleDescriptor shader_desc = {}; + // Need to dynamically allocate wgsl_src, as it needs to persist for the lifetime of shader_desc. + WGPUShaderSourceWGSL* wgsl_src = new WGPUShaderSourceWGSL(); + wgsl_src->chain.sType = WGPUSType_ShaderSourceWGSL; + wgsl_src->code = str_view(shader_code); + + shader_desc.nextInChain = &wgsl_src->chain; + shader_desc.label = label_view(nullptr); + return shader_desc; +} + +// Macro to set the depth stencil state for render pipelines +#define PLATFORM_SET_PIPELINE_DEPTH_STENCIL(pipeline_desc, depth_stencil_state_ptr) \ + do { \ + (pipeline_desc).depthStencil = (depth_stencil_state_ptr); \ + } while (0) #endif +// Helper to extract error message from platform-specific string type +static inline const char* platform_wgpu_get_error_message( +#if defined(DEMO_CROSS_COMPILE_WIN32) + const char* message +#else + WGPUStringView message +#endif +) { +#if defined(DEMO_CROSS_COMPILE_WIN32) + return message ? message : "Unknown"; +#else + // Warning: Returns raw pointer to view data, typically not null-terminated! + // Use '%.*s' printf format with message.length if possible. + // This helper is best effort. + return message.data; +#endif +} + +// Platform-agnostic WebGPU request helpers +void platform_wgpu_request_adapter(WGPUInstance instance, + const WGPURequestAdapterOptions* options, + WGPUAdapter* out_adapter); + +void platform_wgpu_request_device(WGPUAdapter adapter, + const WGPUDeviceDescriptor* descriptor, + WGPUDevice* out_device); + // Forward declare GLFWwindow to avoid including the full header here. struct GLFWwindow; -- cgit v1.2.3