1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
// Handles windowing, input, and native surface creation.
// Consolidates platform-specific shims for WebGPU.
#pragma once
#include <cstdint>
#include <cstring>
// WebGPU specific headers and shims
#if defined(DEMO_CROSS_COMPILE_WIN32)
#include <webgpu/webgpu.h>
#include <webgpu/wgpu.h>
#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 <webgpu.h>
#include <wgpu.h>
// 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();
|