// Handles windowing, input, and native surface creation. // Consolidates platform-specific shims for WebGPU. #pragma once #include #include // WebGPU specific headers and shims #if defined(DEMO_CROSS_COMPILE_WIN32) #include #include #define WGPUOptionalBool_True true #define WGPUOptionalBool_False false #define WGPUSType_ShaderSourceWGSL WGPUSType_ShaderModuleWGSLDescriptor #define WGPU_DEPTH_SLICE_UNDEFINED 0xffffffff #define WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal \ WGPUSurfaceGetCurrentTextureStatus_Success #define WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal \ WGPUSurfaceGetCurrentTextureStatus_Success #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; } static inline const char* label_view(const char* str) { return str; } static inline void platform_wgpu_wait_any(WGPUInstance instance) { wgpuInstanceProcessEvents(instance); } static inline void platform_wgpu_set_error_callback(WGPUDevice device, WGPUErrorCallback callback) { 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}; return {str, strlen(str)}; } static inline WGPUStringView label_view(const char* str) { #if !defined(STRIP_ALL) if (!str) return {nullptr, 0}; return {str, strlen(str)}; #else (void)str; return {nullptr, 0}; #endif } static inline void platform_wgpu_wait_any(WGPUInstance instance) { wgpuInstanceWaitAny(instance, 0, nullptr, 0); } static inline void platform_wgpu_set_error_callback(WGPUDevice device, WGPUUncapturedErrorCallback callback) { // 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; struct PlatformState { GLFWwindow* window = nullptr; int width = 1280; int height = 720; float aspect_ratio = 1.0f; double time = 0.0; bool is_fullscreen = false; // Store windowed geometry for fullscreen toggle int windowed_x = 0, windowed_y = 0, windowed_w = 0, windowed_h = 0; }; // Refactored platform API PlatformState platform_init(bool fullscreen, int width, int height); void platform_shutdown(PlatformState* state); void platform_poll(PlatformState* state); bool platform_should_close(PlatformState* state); void platform_toggle_fullscreen(PlatformState* state); // WebGPU specific surface creation WGPUSurface platform_create_wgpu_surface(WGPUInstance instance, PlatformState* state); // Global time query (if needed without state) double platform_get_time();