Cogs.Core
GraphicsDeviceWebGPU.cpp
1#include "Foundation/Platform/WindowData.h"
2
3#include "GraphicsDeviceWebGPU.h"
4
5#ifndef __EMSCRIPTEN__
6#include "dawn/webgpu_cpp_print.h"
7#include "dawn/dawn_proc.h"
8#include "dawn/native/DawnNative.h"
9#endif
10
11#ifdef __EMSCRIPTEN__
12#include <emscripten/version.h>
13#endif
14
15#include "Foundation/Logging/Logger.h"
16
17namespace {
18 Cogs::Logging::Log logger = Cogs::Logging::getLogger("GraphicsDeviceWebGPU");
19
20 void request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void * userdata, void * /* userdata2 */)
21 {
23 char const *msg = message.data ? message.data : "";
24 int siz = message.data ? static_cast<int>(message.length) : 0;
25 char const *stat = status == WGPURequestAdapterStatus_Success ? "success" : "";
26 LOG_INFO(logger, "request_adapter %p %.*s %s", adapter, siz, msg, stat);
27 ptr->initialize_adapter(adapter);
28 }
29
30 void request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void * userdata, void * /* userdata2 */)
31 {
33 char const *msg = message.data ? message.data : "";
34 int siz = message.data ? static_cast<int>(message.length) : 0;
35 char const *stat = status == WGPURequestDeviceStatus_Success ? "success" : "";
36 LOG_INFO(logger, "request_device %p %.*s %s", device, siz, msg, stat);
37 ptr->initialize_device(device);
38 }
39
40 void error_callback(const WGPUDevice * /* device */, WGPUErrorType type, WGPUStringView message, void * userdata1, void * /* userdata2 */)
41 {
43 (void)ptr;
44 LOG_ERROR(logger, "WebGPU err (%d) %.*s", type, WGPUStringViewFormat(message));
45 }
46
47#ifndef __EMSCRIPTEN__
48 void logging_callback(WGPULoggingType type, WGPUStringView message, void * userdata1, void * /* userdata2 */)
49 {
51 (void)ptr;
52 LOG_INFO(logger, "WebGPU log (%d) x%.*s", type, WGPUStringViewFormat(message));
53 }
54#endif
55
56 // void queue_done_callback(WGPUQueueWorkDoneStatus status, void * userdata)
57 // {
58 // Cogs::GraphicsDeviceWebGPU *ptr = (Cogs::GraphicsDeviceWebGPU*)userdata;
59 // (void)ptr;
60 // LOG_INFO(logger, "queue_done (%d)", status);
61 // }
62
63 void device_lost(const WGPUDevice * /* device */, WGPUDeviceLostReason reason, WGPUStringView message, void * userdata, void * /* userdata2 */)
64 {
66 (void)ptr;
67 if(reason == WGPUDeviceLostReason_Destroyed)
68 LOG_INFO(logger, "device_lost (%d) %.*s", reason, WGPUStringViewFormat(message));
69 else if(reason != WGPUDeviceLostReason_CallbackCancelled) {
70 LOG_FATAL(logger, "device_lost (%d) %.*s", reason, WGPUStringViewFormat(message));
71 assert(reason == WGPUDeviceLostReason_Destroyed);
72 }
73 }
74
75 WGPULimits WebGPUDefaultLimits()
76 {
77 // WebGPU default limits (Minimum required limits for an implementation).
78 WGPULimits limits = WGPU_LIMITS_INIT;
79 limits.maxTextureDimension1D = 8192;
80 limits.maxTextureDimension2D = 8192;
81 limits.maxTextureDimension3D = 2048;
82 limits.maxTextureArrayLayers = 256;
83 limits.maxBindGroups = 4;
84 limits.maxBindGroupsPlusVertexBuffers = 24;
85 limits.maxBindingsPerBindGroup = 1000;
86 limits.maxDynamicUniformBuffersPerPipelineLayout = 8;
87 limits.maxDynamicStorageBuffersPerPipelineLayout = 4;
88 limits.maxSampledTexturesPerShaderStage = 16;
89 limits.maxSamplersPerShaderStage = 16;
90 limits.maxStorageBuffersPerShaderStage = 8;
91 limits.maxStorageTexturesPerShaderStage = 4;
92 limits.maxUniformBuffersPerShaderStage = 12;
93 limits.maxUniformBufferBindingSize = 65536;
94 limits.maxStorageBufferBindingSize = 134217728;
95 limits.minUniformBufferOffsetAlignment = 256;
96 limits.minStorageBufferOffsetAlignment = 256;
97 limits.maxVertexBuffers = 8;
98 limits.maxBufferSize = 268435456;
99 limits.maxVertexAttributes = 16;
100 limits.maxVertexBufferArrayStride = 2048;
101 limits.maxInterStageShaderVariables = 16;
102 limits.maxColorAttachments = 8;
103 limits.maxColorAttachmentBytesPerSample = 32;
104 limits.maxComputeWorkgroupStorageSize = 16384;
105 limits.maxComputeInvocationsPerWorkgroup = 256;
106 limits.maxComputeWorkgroupSizeX = 256;
107 limits.maxComputeWorkgroupSizeY = 256;
108 limits.maxComputeWorkgroupSizeZ = 64;
109 limits.maxComputeWorkgroupsPerDimension = 65535;
110 limits.maxImmediateSize = 64;
111 return limits;
112 }
113}
114
115namespace Cogs {
116
117 GraphicsDeviceWebGPU::GraphicsDeviceWebGPU(RenderingAllocatorInfo* /*allocator*/)
118 {
119 buffers.initialize(this);
120 effects.initialize(this, &buffers);
121 pipeline_states.initialize(this);
122 renderTargets.initialize(this);
123 context.initialize(this);
124 textures.initialize(this);
125 }
126
127 GraphicsDeviceWebGPU::~GraphicsDeviceWebGPU()
128 {
129 destroy();
130 }
131
133 {
134 if (settings.ioHandler) {
135 effects.setIOHandler(settings.ioHandler);
136 }
137
138#ifndef __EMSCRIPTEN__
139 // Load dawn procs
140 DawnProcTable procTable = dawn::native::GetProcs();
141 dawnProcSetProcs(&procTable);
142#endif
143
144 // Create instance
145 WGPUInstanceDescriptor instance_desc = WGPU_INSTANCE_DESCRIPTOR_INIT;
146 instance = wgpuCreateInstance(&instance_desc);
147
148 // Create surface
149 WGPUSurfaceDescriptor surface_desc = WGPU_SURFACE_DESCRIPTOR_INIT;
150 surface_desc.label = {"WebGPU Surface", WGPU_STRLEN};
151#if defined(_WIN32)
152 WGPUSurfaceSourceWindowsHWND hwnd_window = {};
153 hwnd_window.chain.sType = WGPUSType_SurfaceSourceWindowsHWND;
154 hwnd_window.hinstance = ::GetModuleHandle(nullptr);
155 hwnd_window.hwnd = settings.windowData->windowHandle;
156 surface_desc.nextInChain = (WGPUChainedStruct*)&hwnd_window;
157 // WGPUSurfaceDescriptorFromWindowsCoreWindow windows_core_window = {};
158 // WGPUSType_SurfaceDescriptorFromWindowsCoreWindow;
159 // void * coreWindow;
160 // WGPUSurfaceDescriptorFromWindowsSwapChainPanel windows_swap_chain_panel = {};
161 // WGPUSType_SurfaceDescriptorFromWindowsSwapChainPanel;
162 // void * swapChainPanel;
163#elif defined(__EMSCRIPTEN__)
164 WGPUEmscriptenSurfaceSourceCanvasHTMLSelector html_canvas = WGPU_EMSCRIPTEN_SURFACE_SOURCE_CANVAS_HTML_SELECTOR_INIT;
165 html_canvas.chain.sType = WGPUSType_EmscriptenSurfaceSourceCanvasHTMLSelector;
166 html_canvas.selector = {"canvas", WGPU_STRLEN};
167 surface_desc.nextInChain = (WGPUChainedStruct*)&html_canvas;
168#elif defined(__APPLE__)
169 // WGPUSurfaceDescriptorFromMetalLayer metal_layer = {};
170 // metal_layer.chain.sType = WGPUSType_SurfaceDescriptorFromMetalLayer;
171 // void * layer;
172 static_assert(false, "Implement WebGPU Apple surface");
173#elif defined(__linux__)
174 WGPUSurfaceDescriptorFromXlibWindow x11_window = {};
175 x11_window.chain.sType = WGPUSType_SurfaceSourceXlibWindow;
176 x11_window.display = settings.windowData->display;
177 x11_window.window = settings.windowData->windowHandle;
178 surface_desc.nextInChain = (WGPUChainedStruct*)&x11_window;
179 // WGPUSurfaceDescriptorFromWaylandSurface wayland_surface = {};
180 // wayland_surface.chain.sType = WGPUSType_SurfaceDescriptorFromWaylandSurface;
181 // wayland_surface.display = settings.windowData->display;
182 // void * surface;
183#elif defined(__ANDROID_API__)
184 // WGPUSurfaceDescriptorFromAndroidNativeWindow android_window = {};
185 // android_window.chain.sType = WGPUSType_SurfaceDescriptorFromAndroidNativeWindow;
186 // void * window;
187 static_assert(false, "Implement WebGPU Android surface");
188#endif
189 surface = wgpuInstanceCreateSurface(instance, &surface_desc);
190
191 // Get adapter
192 WGPURequestAdapterOptions adapter_options = WGPU_REQUEST_ADAPTER_OPTIONS_INIT;
193 adapter_options.nextInChain;
194 adapter_options.compatibleSurface = surface;
195 adapter_options.powerPreference = WGPUPowerPreference_HighPerformance;
196 adapter_options.forceFallbackAdapter;
197 adapter_options.backendType = WGPUBackendType_D3D11;
198 has_device = false;
199 WGPURequestAdapterCallbackInfo callbackInfo = WGPU_REQUEST_ADAPTER_CALLBACK_INFO_INIT;
200 callbackInfo.nextInChain = nullptr;
201 callbackInfo.callback = request_adapter;
202 callbackInfo.mode = WGPUCallbackMode_AllowSpontaneous;
203 callbackInfo.userdata1 = this;
204
205 WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, callbackInfo);
206
207 WGPUFutureWaitInfo waitInfo = WGPU_FUTURE_WAIT_INFO_INIT;
208 waitInfo.future = future;
209 wgpuInstanceWaitAny(instance, 1, &waitInfo, 0);
210
211 return true;
212 }
213
214 void GraphicsDeviceWebGPU::initialize_adapter(WGPUAdapter adapter_in)
215 {
216 adapter = adapter_in;
217
218 // size_t wgpuAdapterEnumerateFeatures(WGPUAdapter adapter, WGPUFeatureName * features) WGPU_FUNCTION_ATTRIBUTE;
219
220 WGPUAdapterInfo properties = WGPU_ADAPTER_INFO_INIT;
221 // WGPUDawnAdapterPropertiesPowerPreference power_pref = {};
222 // WGPUPowerPreference powerPreference;
223 wgpuAdapterGetInfo(adapter, &properties);
224 LOG_INFO(logger, "vendorID %u", properties.vendorID);
225 LOG_INFO(logger, "vendor %.*s", WGPUStringViewFormat(properties.vendor));
226 LOG_INFO(logger, "architecture %.*s", WGPUStringViewFormat(properties.architecture));
227 LOG_INFO(logger, "deviceID %u", properties.deviceID);
228 LOG_INFO(logger, "device %.*s", WGPUStringViewFormat(properties.device));
229 LOG_INFO(logger, "description %.*s", WGPUStringViewFormat(properties.description));
230 LOG_INFO(logger, "adapterType %d", properties.adapterType);
231 LOG_INFO(logger, "backendType %d", properties.backendType);
232 LOG_INFO(logger, "subgroupMinSize %u", properties.subgroupMinSize);
233 LOG_INFO(logger, "subgroupMaxSize %u", properties.subgroupMaxSize);
234
235 if(properties.vendorID == 4130)
236 capabilities.vendor = Vendors::AMD;
237 else if(properties.vendorID == 4318)
238 capabilities.vendor = Vendors::nVidia;
239 else if(properties.vendorID == 32902)
240 capabilities.vendor = Vendors::Intel;
241 else if(properties.vendorID == 4203)
242 capabilities.vendor = Vendors::Apple;
243
244 if(properties.vendorID == 4130){ // AMD
245 if(strstr(properties.device.data, "FireGL") != nullptr){
246 capabilities.series = Series::FireGL;
247 }
248 else if(strstr(properties.device.data, "RadeonX") != nullptr){
249 capabilities.series = Series::RadeonX;
250 }
251 else if(strstr(properties.device.data, "RadeonHD") != nullptr){
252 capabilities.series = Series::RadeonHD;
253 }
254 }
255 else if(properties.vendorID == 4318){ // nVidia
256 if(strstr(properties.device.data, "QuadroFX") != nullptr){
257 capabilities.series = Series::QuadroFX;
258 }
259 else if(strstr(properties.device.data, "Quadro") != nullptr){
260 capabilities.series = Series::Quadro;
261 }
262 else if(strstr(properties.device.data, "GeForce") != nullptr){
263 capabilities.series = Series::geForce;
264 }
265 }
266 else if(properties.vendorID == 32902){ // Intel
267 if(strstr(properties.device.data, "IrisPro") != nullptr){
268 capabilities.series = Series::IrisPro;
269 }
270 else if(strstr(properties.device.data, "Iris") != nullptr){
271 capabilities.series = Series::Iris;
272 }
273 else if(strstr(properties.device.data, "HD") != nullptr){
274 capabilities.series = Series::HD;
275 }
276 }
277
278 capabilities.model = properties.deviceID;
279
280 WGPULimits adapter_limits = WGPU_LIMITS_INIT;
281 if(wgpuAdapterGetLimits(adapter, &adapter_limits)){
282 LOG_INFO(logger, "adapter_limits ");
283 LOG_INFO(logger, "maxTextureDimension1D %u", adapter_limits.maxTextureDimension1D);
284 LOG_INFO(logger, "maxTextureDimension2D %u", adapter_limits.maxTextureDimension2D);
285 LOG_INFO(logger, "maxTextureDimension3D %u", adapter_limits.maxTextureDimension3D);
286 LOG_INFO(logger, "maxTextureArrayLayers %u", adapter_limits.maxTextureArrayLayers);
287 LOG_INFO(logger, "maxBindGroups %u", adapter_limits.maxBindGroups);
288 LOG_INFO(logger, "maxBindGroupsPlusVertexBuffers %u", adapter_limits.maxBindGroupsPlusVertexBuffers);
289 LOG_INFO(logger, "maxBindingsPerBindGroup %u", adapter_limits.maxBindingsPerBindGroup);
290 LOG_INFO(logger, "maxDynamicUniformBuffersPerPipelineLayout %u", adapter_limits.maxDynamicUniformBuffersPerPipelineLayout);
291 LOG_INFO(logger, "maxDynamicStorageBuffersPerPipelineLayout %u", adapter_limits.maxDynamicStorageBuffersPerPipelineLayout);
292 LOG_INFO(logger, "maxSampledTexturesPerShaderStage %u", adapter_limits.maxSampledTexturesPerShaderStage);
293 LOG_INFO(logger, "maxSamplersPerShaderStage %u", adapter_limits.maxSamplersPerShaderStage);
294 LOG_INFO(logger, "maxStorageBuffersPerShaderStage %u", adapter_limits.maxStorageBuffersPerShaderStage);
295 LOG_INFO(logger, "maxStorageTexturesPerShaderStage %u", adapter_limits.maxStorageTexturesPerShaderStage);
296 LOG_INFO(logger, "maxUniformBuffersPerShaderStage %u", adapter_limits.maxUniformBuffersPerShaderStage);
297 LOG_INFO(logger, "maxUniformBufferBindingSize %llu", adapter_limits.maxUniformBufferBindingSize);
298 LOG_INFO(logger, "maxStorageBufferBindingSize %llu", adapter_limits.maxStorageBufferBindingSize);
299 LOG_INFO(logger, "minUniformBufferOffsetAlignment %u", adapter_limits.minUniformBufferOffsetAlignment);
300 LOG_INFO(logger, "minStorageBufferOffsetAlignment %u", adapter_limits.minStorageBufferOffsetAlignment);
301 LOG_INFO(logger, "maxVertexBuffers %u", adapter_limits.maxVertexBuffers);
302 LOG_INFO(logger, "maxBufferSize %llu", adapter_limits.maxBufferSize);
303 LOG_INFO(logger, "maxVertexAttributes %u", adapter_limits.maxVertexAttributes);
304 LOG_INFO(logger, "maxVertexBufferArrayStride %u", adapter_limits.maxVertexBufferArrayStride);
305 LOG_INFO(logger, "maxInterStageShaderVariables %u", adapter_limits.maxInterStageShaderVariables);
306 LOG_INFO(logger, "maxColorAttachments %u", adapter_limits.maxColorAttachments);
307 LOG_INFO(logger, "maxColorAttachmentBytesPerSample %u", adapter_limits.maxColorAttachmentBytesPerSample);
308 LOG_INFO(logger, "maxComputeWorkgroupStorageSize %u", adapter_limits.maxComputeWorkgroupStorageSize);
309 LOG_INFO(logger, "maxComputeInvocationsPerWorkgroup %u", adapter_limits.maxComputeInvocationsPerWorkgroup);
310 LOG_INFO(logger, "maxComputeWorkgroupSizeX %u", adapter_limits.maxComputeWorkgroupSizeX);
311 LOG_INFO(logger, "maxComputeWorkgroupSizeY %u", adapter_limits.maxComputeWorkgroupSizeY);
312 LOG_INFO(logger, "maxComputeWorkgroupSizeZ %u", adapter_limits.maxComputeWorkgroupSizeZ);
313 LOG_INFO(logger, "maxComputeWorkgroupsPerDimension %u", adapter_limits.maxComputeWorkgroupsPerDimension);
314 LOG_INFO(logger, "maxImmediateSize %u", adapter_limits.maxImmediateSize);
315 }
316
317 // Sample adapter_limits (GTX 1070)
318 // maxTextureDimension1D 16384
319 // maxTextureDimension2D 16384
320 // maxTextureDimension3D 2048
321 // maxTextureArrayLayers 2048
322 // maxBindGroups 4
323 // maxBindingsPerBindGroup 1000
324 // maxDynamicUniformBuffersPerPipelineLayout 0
325 // maxDynamicStorageBuffersPerPipelineLayout 0
326 // maxSampledTexturesPerShaderStage 16
327 // maxSamplersPerShaderStage 16
328 // maxStorageBuffersPerShaderStage 8
329 // maxStorageTexturesPerShaderStage 8
330 // maxUniformBuffersPerShaderStage 12
331 // maxUniformBufferBindingSize 65536
332 // maxStorageBufferBindingSize 134217728
333 // minUniformBufferOffsetAlignment 256
334 // minStorageBufferOffsetAlignment 256
335 // maxVertexBuffers 8
336 // maxBufferSize 2147483648
337 // maxVertexAttributes 16
338 // maxVertexBufferArrayStride 2048
339 // maxInterStageShaderVariables 16
340 // maxColorAttachments 8
341 // maxColorAttachmentBytesPerSample 32
342 // maxComputeWorkgroupStorageSize 32768
343 // maxComputeInvocationsPerWorkgroup 1024
344 // maxComputeWorkgroupSizeX 1024
345 // maxComputeWorkgroupSizeY 1024
346 // maxComputeWorkgroupSizeZ 64
347 // maxComputeWorkgroupsPerDimension 65535
348 // maxImmediateSize 0
349
350 // Required limits
351 // WGPULimits required_limits = WGPU_LIMITS_INIT; // Request limits undefined
352 // WGPULimits required_limits = WebGPUDefaultLimits(); // Request WebGPU default limits
353 WGPULimits required_limits = adapter_limits; // Request adapter limits
354
355 std::vector<WGPUFeatureName> features;
356
357 if(wgpuAdapterHasFeature(adapter, WGPUFeatureName_TextureCompressionBC)) {
358 features.push_back(WGPUFeatureName_TextureCompressionBC);
359 capabilities.capabilities.TextureCompressionBPTC = true;
360 }
361 if(wgpuAdapterHasFeature(adapter, WGPUFeatureName_TextureCompressionASTC)) {
362 features.push_back(WGPUFeatureName_TextureCompressionASTC);
363 capabilities.capabilities.TextureCompressionASTC = true;
364 }
365 if(wgpuAdapterHasFeature(adapter, WGPUFeatureName_TextureCompressionETC2)) {
366 features.push_back(WGPUFeatureName_TextureCompressionETC2);
367 capabilities.capabilities.TextureCompressionETC = true;
368 }
369 if(wgpuAdapterHasFeature(adapter, WGPUFeatureName_Float32Filterable)) {
370 features.push_back(WGPUFeatureName_Float32Filterable);
371 }
372
373 // Get device
374 WGPUDeviceDescriptor device_desc = WGPU_DEVICE_DESCRIPTOR_INIT;
375 device_desc.label = {"WebGPU device", WGPU_STRLEN};
376
377 device_desc.requiredFeatureCount = features.size();
378 device_desc.requiredFeatures = features.data();
379 device_desc.requiredLimits = &required_limits;
380 device_desc.defaultQueue.label = {"Default WebGPU queue", WGPU_STRLEN};
381
382 WGPUDeviceLostCallbackInfo deviceLostCallbackInfo = WGPU_DEVICE_LOST_CALLBACK_INFO_INIT;
383 deviceLostCallbackInfo.nextInChain = nullptr;
384 deviceLostCallbackInfo.callback = device_lost;
385 deviceLostCallbackInfo.mode = WGPUCallbackMode_AllowSpontaneous;
386 deviceLostCallbackInfo.userdata1 = this;
387 device_desc.deviceLostCallbackInfo = deviceLostCallbackInfo;
388
389 WGPUUncapturedErrorCallbackInfo uncapturedErrorCallbackInfo = WGPU_UNCAPTURED_ERROR_CALLBACK_INFO_INIT;
390 uncapturedErrorCallbackInfo.nextInChain = nullptr;
391 uncapturedErrorCallbackInfo.callback = error_callback;
392 uncapturedErrorCallbackInfo.userdata1 = this;
393 device_desc.uncapturedErrorCallbackInfo = uncapturedErrorCallbackInfo;
394 // WGPUDawnTogglesDescriptor toggles_desc = {};
395 // toggles_desc.chain;
396 // toggles_desc.enabledTogglesCount;
397 // toggles_desc.enabledToggles;
398 // toggles_desc.disabledTogglesCount;
399 // toggles_desc.disabledToggles;
400 // WGPUDawnCacheDeviceDescriptor dawn_cache_desc = {};
401 // dawn_cache_desc.chain;
402 // dawn_cache_desc.isolationKey;
403
404 WGPURequestDeviceCallbackInfo requestDeviceCallbackInfo = WGPU_REQUEST_DEVICE_CALLBACK_INFO_INIT;
405 requestDeviceCallbackInfo.nextInChain = nullptr;
406 requestDeviceCallbackInfo.mode = WGPUCallbackMode_AllowSpontaneous;
407 requestDeviceCallbackInfo.userdata1 = this;
408 requestDeviceCallbackInfo.callback = request_device;
409 WGPUFuture future = wgpuAdapterRequestDevice(adapter, &device_desc, requestDeviceCallbackInfo);
410
411 WGPUFutureWaitInfo waitInfo = WGPU_FUTURE_WAIT_INFO_INIT;
412 waitInfo.future = future;
413 wgpuInstanceWaitAny(instance, 1, &waitInfo, 0);
414 }
415
416 void GraphicsDeviceWebGPU::maybeCreateUploadCommandEncoder()
417 {
418 if(commandEncoder) return;
419 WGPUCommandEncoderDescriptor command_encoder_desc = WGPU_COMMAND_ENCODER_DESCRIPTOR_INIT;
420 command_encoder_desc.label = {"Upload Command Encoder", WGPU_STRLEN};
421 commandEncoder = wgpuDeviceCreateCommandEncoder(device, &command_encoder_desc);
422 }
423 void GraphicsDeviceWebGPU::initialize_device(WGPUDevice device_in)
424 {
425 device = device_in;
426
427 // Setup logging
428#ifndef __EMSCRIPTEN__
429 WGPULoggingCallbackInfo loggingCallbackInfo = {};
430 loggingCallbackInfo.nextInChain = nullptr;
431 loggingCallbackInfo.callback = logging_callback;
432 loggingCallbackInfo.userdata1 = this;
433 wgpuDeviceSetLoggingCallback(device, loggingCallbackInfo);
434#endif
435
436 WGPULimits device_limits = WGPU_LIMITS_INIT;
437 if(wgpuDeviceGetLimits(device, &device_limits)){
438 LOG_INFO(logger, "device_limits ");
439 LOG_INFO(logger, "maxTextureDimension1D %u", device_limits.maxTextureDimension1D);
440 LOG_INFO(logger, "maxTextureDimension2D %u", device_limits.maxTextureDimension2D);
441 LOG_INFO(logger, "maxTextureDimension3D %u", device_limits.maxTextureDimension3D);
442 LOG_INFO(logger, "maxTextureArrayLayers %u", device_limits.maxTextureArrayLayers);
443 LOG_INFO(logger, "maxBindGroups %u", device_limits.maxBindGroups);
444 LOG_INFO(logger, "maxBindGroupsPlusVertexBuffers %u", device_limits.maxBindGroupsPlusVertexBuffers);
445 LOG_INFO(logger, "maxBindingsPerBindGroup %u", device_limits.maxBindingsPerBindGroup);
446 LOG_INFO(logger, "maxDynamicUniformBuffersPerPipelineLayout %u", device_limits.maxDynamicUniformBuffersPerPipelineLayout);
447 LOG_INFO(logger, "maxDynamicStorageBuffersPerPipelineLayout %u", device_limits.maxDynamicStorageBuffersPerPipelineLayout);
448 LOG_INFO(logger, "maxSampledTexturesPerShaderStage %u", device_limits.maxSampledTexturesPerShaderStage);
449 LOG_INFO(logger, "maxSamplersPerShaderStage %u", device_limits.maxSamplersPerShaderStage);
450 LOG_INFO(logger, "maxStorageBuffersPerShaderStage %u", device_limits.maxStorageBuffersPerShaderStage);
451 LOG_INFO(logger, "maxStorageTexturesPerShaderStage %u", device_limits.maxStorageTexturesPerShaderStage);
452 LOG_INFO(logger, "maxUniformBuffersPerShaderStage %u", device_limits.maxUniformBuffersPerShaderStage);
453 LOG_INFO(logger, "maxUniformBufferBindingSize %llu", device_limits.maxUniformBufferBindingSize);
454 LOG_INFO(logger, "maxStorageBufferBindingSize %llu", device_limits.maxStorageBufferBindingSize);
455 LOG_INFO(logger, "minUniformBufferOffsetAlignment %u", device_limits.minUniformBufferOffsetAlignment);
456 LOG_INFO(logger, "minStorageBufferOffsetAlignment %u", device_limits.minStorageBufferOffsetAlignment);
457 LOG_INFO(logger, "maxVertexBuffers %u", device_limits.maxVertexBuffers);
458 LOG_INFO(logger, "maxBufferSize %llu", device_limits.maxBufferSize);
459 LOG_INFO(logger, "maxVertexAttributes %u", device_limits.maxVertexAttributes);
460 LOG_INFO(logger, "maxVertexBufferArrayStride %u", device_limits.maxVertexBufferArrayStride);
461 LOG_INFO(logger, "maxInterStageShaderVariables %u", device_limits.maxInterStageShaderVariables);
462 LOG_INFO(logger, "maxColorAttachments %u", device_limits.maxColorAttachments);
463 LOG_INFO(logger, "maxColorAttachmentBytesPerSample %u", device_limits.maxColorAttachmentBytesPerSample);
464 LOG_INFO(logger, "maxComputeWorkgroupStorageSize %u", device_limits.maxComputeWorkgroupStorageSize);
465 LOG_INFO(logger, "maxComputeInvocationsPerWorkgroup %u", device_limits.maxComputeInvocationsPerWorkgroup);
466 LOG_INFO(logger, "maxComputeWorkgroupSizeX %u", device_limits.maxComputeWorkgroupSizeX);
467 LOG_INFO(logger, "maxComputeWorkgroupSizeY %u", device_limits.maxComputeWorkgroupSizeY);
468 LOG_INFO(logger, "maxComputeWorkgroupSizeZ %u", device_limits.maxComputeWorkgroupSizeZ);
469 LOG_INFO(logger, "maxComputeWorkgroupsPerDimension %u", device_limits.maxComputeWorkgroupsPerDimension);
470 LOG_INFO(logger, "maxImmediateSize %u", device_limits.maxImmediateSize);
471 }
472
473 // Update capabilities
474 capabilities.capabilities.RenderPass = true;
475 capabilities.capabilities.SyncObjects = false; // TODO
476 capabilities.capabilities.GeometryShaders = false;
477 capabilities.capabilities.TessellationShaders = false;
478 capabilities.capabilities.ComputeShaders = false; // TODO
479 capabilities.capabilities.SupportsHlsl = false;
480 capabilities.capabilities.SupportsMultipleThreads = false;
481 capabilities.capabilities.ConstantBufferOffsetAlignment = device_limits.minUniformBufferOffsetAlignment;
482 capabilities.capabilities.ConstantBufferRange = true;
483 capabilities.capabilities.MaxTexture2DSize = device_limits.maxTextureDimension2D;
484 capabilities.capabilities.MaxTexture3DSize = device_limits.maxTextureDimension3D;
485 capabilities.capabilities.MaxTextureArrayLayers = device_limits.maxTextureArrayLayers;
486
487 defaultSwapChain.initialize(device, surface);
488
489 queue = wgpuDeviceGetQueue(device);
490
491 LOG_INFO(logger, "Has WebGPU Device");
492 has_device = true;
493 }
494
495 void GraphicsDeviceWebGPU::destroy()
496 {
497 wgpuInstanceRelease(instance);
498 LOG_INFO(logger, "WebGPU destroy");
499 if(commandEncoder){
500 wgpuCommandEncoderRelease(commandEncoder);
501 commandEncoder = nullptr;
502 }
503 wgpuQueueRelease(queue);
504 defaultSwapChain.destroy();
505 wgpuSurfaceRelease(surface);
506
507 wgpuDeviceRelease(device);
508 wgpuAdapterRelease(adapter);
509 }
510
512 {
513 buffers.releaseResources();
514 effects.releaseResources();
515 textures.releaseResources();
516 renderTargets.releaseResources();
517 }
518
520 {
521 context.beginFrame();
522
523 if(commandEncoder){
524 WGPUCommandBufferDescriptor command_buffer_desc = WGPU_COMMAND_BUFFER_DESCRIPTOR_INIT;
525 command_buffer_desc.label = {"Upload Command Buffer", WGPU_STRLEN};
526 WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish(commandEncoder, &command_buffer_desc);
527 wgpuCommandEncoderRelease(commandEncoder);
528 commandEncoder = nullptr;
529 wgpuQueueSubmit(queue, 1, &command_buffer);
530 buffers.resetInstances();
531 }
532
533 context.ClearBindGroups();
534
535#ifndef __EMSCRIPTEN__
536 // Emscripten: wgpuInstanceProcessEvents is unsupported (use requestAnimationFrame via html5.h instead)
537 wgpuInstanceProcessEvents(instance);
538 wgpuDeviceTick(device);
539#endif
540
541 defaultSwapChain.beginFrame();
542
543 WGPUCommandEncoderDescriptor command_encoder_desc = WGPU_COMMAND_ENCODER_DESCRIPTOR_INIT;
544 command_encoder_desc.label = {"Default Command Encoder", WGPU_STRLEN};
545 commandEncoder = wgpuDeviceCreateCommandEncoder(device, &command_encoder_desc);
546 context.setDefaults();
547 }
548
549 void GraphicsDeviceWebGPU::endFrame(uint32_t syncInterval, PresentFlags presentFlags)
550 {
551 context.updateRenderPass();
552 context.endRenderPassInt();
553
554#ifndef __EMSCRIPTEN__
555 WGPUTexelCopyTextureInfo src = WGPU_TEXEL_COPY_TEXTURE_INFO_INIT;
556 src.texture = defaultSwapChain.resolveTexture;
557 src.mipLevel = 0;
558 src.origin = {0, 0, 0};
559 src.aspect = WGPUTextureAspect_All;
560 WGPUTexelCopyTextureInfo dst = WGPU_TEXEL_COPY_TEXTURE_INFO_INIT;
561 WGPUSurfaceTexture surfaceTexture = context.graphicsDevice->defaultSwapChain.getTextureData();
562 dst.texture = surfaceTexture.texture;
563 dst.mipLevel = 0;
564 dst.origin = {0, 0, 0};
565 dst.aspect = WGPUTextureAspect_All;
566 WGPUExtent3D copy_size = {(uint32_t)defaultSwapChain.set_width, (uint32_t)defaultSwapChain.set_height, 1};
567 wgpuCommandEncoderCopyTextureToTexture(commandEncoder, &src, &dst, &copy_size);
568#endif
569
570 WGPUCommandBufferDescriptor command_buffer_desc = WGPU_COMMAND_BUFFER_DESCRIPTOR_INIT;
571 command_buffer_desc.label = {"Default Command Buffer", WGPU_STRLEN};
572 WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish(commandEncoder, &command_buffer_desc);
573 wgpuCommandEncoderRelease(commandEncoder);
574 commandEncoder = nullptr;
575 wgpuQueueSubmit(queue, 1, &command_buffer);
576 buffers.resetInstances();
577
578 // wgpuQueueOnSubmittedWorkDone
579
580 defaultSwapChain.endFrame(syncInterval, presentFlags);
581
582 context.SwapBindGroups();
583 }
584
585 Cogs::ResourceStatistics Cogs::GraphicsDeviceWebGPU::getResourceStatistics()
586 {
587 ResourceStatistics stats{};
588
589 stats.bufferMemoryConsumption = buffers.bufferMemoryConsumption;
590 stats.textureMemoryConsumption = textures.textureMemoryConsumption;
591 stats.bufferCount = static_cast<uint32_t>(buffers.buffers.size());
592 stats.vertexArrayObjectCount = 0;
593 stats.inputLayoutCount = static_cast<uint32_t>(buffers.inputLayouts.size());
594 stats.textureCount = static_cast<uint32_t>(textures.textures.size());
595 stats.samplerStateCount = static_cast<uint32_t>(textures.samplerStates.size());
596 stats.effectCount = static_cast<uint32_t>(effects.effects.size());
597 stats.blendStateCount = 0;
598 stats.rasterizerStateCount = 0;
599 stats.depthStencilStateCount = 0;
600 stats.rendertargetsCount = static_cast<uint32_t>(renderTargets.render_targets.size());
601 stats.framebufferCount = 0;
602
603 return stats;
604 }
605}
virtual void releaseResources() override
Releases all allocated buffer resources.
Definition: BuffersWebGPU.h:73
virtual void releaseResources() override
Release all allocated effect resources.
virtual void beginFrame() override
Signal the beginning of a new frame to the graphics device.
virtual void releaseResources() override
Release all resources allocated.
virtual bool initialize() override
Initializes the graphics device with the settings previous set through calling setSettings.
virtual void endFrame(uint32_t=0, PresentFlags=PresentFlags::None) override
Signal the end of a frame to the graphics device.
Log implementation class.
Definition: LogManager.h:140
virtual void releaseResources() override
Release all allocated render target resources.
virtual void beginFrame() override
Signal the beginning of a new frame to the graphics device.
virtual void endFrame(uint32_t syncInterval=0, PresentFlags presentFlags=PresentFlags::None) override
Signal the end of a frame to the graphics device.
virtual void releaseResources() override
Release all allocated texture resources.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
PresentFlags
Flags controlling presentation.
Definition: Common.h:166
void setIOHandler(IIOHandler *handler) override
Sets an external I/O handler to use for I/O operations.
uint32_t MaxTexture3DSize
Using D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION as default.
Definition: ICapabilities.h:81
uint32_t MaxTexture2DSize
Using D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION as default.
Definition: ICapabilities.h:80
bool SyncObjects
Support for syncronization objects.
Definition: ICapabilities.h:86
uint32_t MaxTextureArrayLayers
Using D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION as default.
Definition: ICapabilities.h:83
unsigned ConstantBufferOffsetAlignment
Minimum offset alignment when binding constant buffers.
Definition: ICapabilities.h:78
bool ConstantBufferRange
supports binding a range of a constant buffer.
Definition: ICapabilities.h:90
struct WindowData * windowData
Native window handle used to initialize the graphics device.
IIOHandler * ioHandler
Optional pointer to an IO handler.
@ HD
Intel HD.
Definition: ICapabilities.h:52
@ QuadroFX
nVidia Quadro FX professional graphics adapters.
Definition: ICapabilities.h:50
@ Iris
Intel Iris.
Definition: ICapabilities.h:54
@ IrisPro
Intel Iris Pro.
Definition: ICapabilities.h:56
@ FireGL
AMD FireGL series.
Definition: ICapabilities.h:43
@ geForce
nVidia geForce consumer adapters.
Definition: ICapabilities.h:46
@ RadeonX
AMD Radeon X series.
Definition: ICapabilities.h:39
@ RadeonHD
AMD Radeon HD series.
Definition: ICapabilities.h:41
@ Quadro
nVidia Quadro professional graphics adapters.
Definition: ICapabilities.h:48
@ Apple
Apple silicon.
Definition: ICapabilities.h:24
@ nVidia
nVidia Corporation.
Definition: ICapabilities.h:20