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, char const * message, void * userdata)
21 {
23 char const *msg = message ? message : "";
24 char const *stat = status == WGPURequestAdapterStatus_Success ? "success" : "";
25 LOG_INFO(logger, "request_adapter %p %s %s", adapter, msg, stat);
26 ptr->initialize_adapter(adapter);
27 }
28
29 void request_device(WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * userdata)
30 {
32 char const *msg = message ? message : "";
33 char const *stat = status == WGPURequestDeviceStatus_Success ? "success" : "";
34 LOG_INFO(logger, "request_device %p %s %s", device, msg, stat);
35 ptr->initialize_device(device);
36 }
37
38 void error_callback(WGPUErrorType type, char const * message, void * userdata)
39 {
41 (void)ptr;
42 LOG_ERROR(logger, "WebGPU err (%d) %s", type, message);
43 }
44
45#ifndef EMSCRIPTEN
46 void logging_callback(WGPULoggingType type, char const * message, void * userdata)
47 {
49 (void)ptr;
50 LOG_INFO(logger, "WebGPU log (%d) x%s", type, message);
51 }
52#endif
53
54 // void queue_done_callback(WGPUQueueWorkDoneStatus status, void * userdata)
55 // {
56 // Cogs::GraphicsDeviceWebGPU *ptr = (Cogs::GraphicsDeviceWebGPU*)userdata;
57 // (void)ptr;
58 // LOG_INFO(logger, "queue_done (%d)", status);
59 // }
60
61 void device_lost(WGPUDeviceLostReason reason, char const * message, void * userdata)
62 {
64 (void)ptr;
65 if(reason == WGPUDeviceLostReason_Destroyed)
66 LOG_INFO(logger, "device_lost (%d) %s", reason, message);
67 else
68 LOG_FATAL(logger, "device_lost (%d) %s", reason, message);
69 assert(reason == WGPUDeviceLostReason_Destroyed);
70 }
71
72 WGPULimits WebGPUDefaultLimits()
73 {
74 // WebGPU default limits (Minimum required limits for an implementation).
75 WGPULimits limits = {};
76 limits.maxTextureDimension1D = 8192;
77 limits.maxTextureDimension2D = 8192;
78 limits.maxTextureDimension3D = 2048;
79 limits.maxTextureArrayLayers = 256;
80 limits.maxBindGroups = 4;
81 // limits.maxBindGroupsPlusVertexBuffers = 24;
82#ifndef EMSCRIPTEN
83 limits.maxBindingsPerBindGroup = 1000;
84#endif
85 limits.maxDynamicUniformBuffersPerPipelineLayout = 8;
86 limits.maxDynamicStorageBuffersPerPipelineLayout = 4;
87 limits.maxSampledTexturesPerShaderStage = 16;
88 limits.maxSamplersPerShaderStage = 16;
89 limits.maxStorageBuffersPerShaderStage = 8;
90 limits.maxStorageTexturesPerShaderStage = 4;
91 limits.maxUniformBuffersPerShaderStage = 12;
92 limits.maxUniformBufferBindingSize = 65536;
93 limits.maxStorageBufferBindingSize = 134217728;
94 limits.minUniformBufferOffsetAlignment = 256;
95 limits.minStorageBufferOffsetAlignment = 256;
96 limits.maxVertexBuffers = 8;
97#ifndef EMSCRIPTEN
98 limits.maxBufferSize = 268435456;
99#endif
100 limits.maxVertexAttributes = 16;
101 limits.maxVertexBufferArrayStride = 2048;
102 limits.maxInterStageShaderComponents = 60;
103#ifndef EMSCRIPTEN
104 limits.maxInterStageShaderVariables = 16;
105 limits.maxColorAttachments = 8;
106 limits.maxColorAttachmentBytesPerSample = 32;
107#endif
108 limits.maxComputeWorkgroupStorageSize = 16384;
109 limits.maxComputeInvocationsPerWorkgroup = 256;
110 limits.maxComputeWorkgroupSizeX = 256;
111 limits.maxComputeWorkgroupSizeY = 256;
112 limits.maxComputeWorkgroupSizeZ = 64;
113 limits.maxComputeWorkgroupsPerDimension = 65535;
114 return limits;
115 }
116}
117
118namespace Cogs {
119
120 GraphicsDeviceWebGPU::GraphicsDeviceWebGPU(RenderingAllocatorInfo* /*allocator*/)
121 {
122 buffers.initialize(this);
123 effects.initialize(this, &buffers);
124 pipeline_states.initialize(this);
125 renderTargets.initialize(this);
126 context.initialize(this);
127 textures.initialize(this);
128 }
129
130 GraphicsDeviceWebGPU::~GraphicsDeviceWebGPU()
131 {
132 destroy();
133 }
134
136 {
137 if (settings.ioHandler) {
138 effects.setIOHandler(settings.ioHandler);
139 }
140
141#ifndef EMSCRIPTEN
142 // Load dawn procs
143 DawnProcTable procTable = dawn::native::GetProcs();
144 dawnProcSetProcs(&procTable);
145#endif
146
147 // Create instance
148 WGPUInstanceDescriptor instance_desc = {};
149 instance = wgpuCreateInstance(&instance_desc);
150
151 // Create surface
152 WGPUSurfaceDescriptor surface_desc = {};
153 surface_desc.label = "WebGPU Surface";
154#if defined(_WIN32)
155 WGPUSurfaceDescriptorFromWindowsHWND hwnd_window = {};
156 hwnd_window.chain.sType = WGPUSType_SurfaceDescriptorFromWindowsHWND;
157 hwnd_window.hinstance = ::GetModuleHandle(nullptr);
158 hwnd_window.hwnd = settings.windowData->windowHandle;
159 surface_desc.nextInChain = (WGPUChainedStruct*)&hwnd_window;
160 // WGPUSurfaceDescriptorFromWindowsCoreWindow windows_core_window = {};
161 // WGPUSType_SurfaceDescriptorFromWindowsCoreWindow;
162 // void * coreWindow;
163 // WGPUSurfaceDescriptorFromWindowsSwapChainPanel windows_swap_chain_panel = {};
164 // WGPUSType_SurfaceDescriptorFromWindowsSwapChainPanel;
165 // void * swapChainPanel;
166#elif defined(EMSCRIPTEN)
167 WGPUSurfaceDescriptorFromCanvasHTMLSelector html_canvas = {};
168 html_canvas.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
169 html_canvas.selector = "canvas";
170 surface_desc.nextInChain = (WGPUChainedStruct*)&html_canvas;
171#elif defined(__APPLE__)
172 // WGPUSurfaceDescriptorFromMetalLayer metal_layer = {};
173 // metal_layer.chain.sType = WGPUSType_SurfaceDescriptorFromMetalLayer;
174 // void * layer;
175 static_assert(false, "Implement WebGPU Apple surface");
176#elif defined(__linux__)
177 WGPUSurfaceDescriptorFromXlibWindow x11_window = {};
178 x11_window.chain.sType = WGPUSType_SurfaceDescriptorFromXlibWindow;
179 x11_window.display = settings.windowData->display;
180 x11_window.window = settings.windowData->windowHandle;
181 surface_desc.nextInChain = (WGPUChainedStruct*)&x11_window;
182 // WGPUSurfaceDescriptorFromWaylandSurface wayland_surface = {};
183 // wayland_surface.chain.sType = WGPUSType_SurfaceDescriptorFromWaylandSurface;
184 // wayland_surface.display = settings.windowData->display;
185 // void * surface;
186#elif defined(__ANDROID_API__)
187 // WGPUSurfaceDescriptorFromAndroidNativeWindow android_window = {};
188 // android_window.chain.sType = WGPUSType_SurfaceDescriptorFromAndroidNativeWindow;
189 // void * window;
190 static_assert(false, "Implement WebGPU Android surface");
191#endif
192 surface = wgpuInstanceCreateSurface(instance, &surface_desc);
193
194 // Get adapter
195 WGPURequestAdapterOptions adapter_options = {};
196 adapter_options.nextInChain;
197 adapter_options.compatibleSurface = surface;
198 adapter_options.powerPreference = WGPUPowerPreference_Undefined;
199 adapter_options.forceFallbackAdapter;
200#ifndef EMSCRIPTEN
201 adapter_options.compatibilityMode;
202#endif
203 has_device = false;
204 wgpuInstanceRequestAdapter(instance, &adapter_options, request_adapter, this);
205
206 return true;
207 }
208
209 void GraphicsDeviceWebGPU::initialize_adapter(WGPUAdapter adapter_in)
210 {
211 adapter = adapter_in;
212
213 // size_t wgpuAdapterEnumerateFeatures(WGPUAdapter adapter, WGPUFeatureName * features) WGPU_FUNCTION_ATTRIBUTE;
214
215 WGPUAdapterProperties properties = {};
216 // WGPUDawnAdapterPropertiesPowerPreference power_pref = {};
217 // WGPUPowerPreference powerPreference;
218 wgpuAdapterGetProperties(adapter, &properties);
219 LOG_INFO(logger, "vendorID %u", properties.vendorID);
220#ifndef EMSCRIPTEN
221 LOG_INFO(logger, "vendorName %s", properties.vendorName);
222 LOG_INFO(logger, "architecture %s", properties.architecture);
223#endif
224 LOG_INFO(logger, "deviceID %u", properties.deviceID);
225 LOG_INFO(logger, "name %s", properties.name);
226 LOG_INFO(logger, "driverDescription %s", properties.driverDescription);
227 LOG_INFO(logger, "adapterType %d", properties.adapterType);
228 LOG_INFO(logger, "backendType %d", properties.backendType);
229#ifndef EMSCRIPTEN
230 LOG_INFO(logger, "compatibilityMode %s", properties.compatibilityMode?"true":"false");
231#endif
232
233 if(properties.vendorID == 4130)
234 capabilities.vendor = Vendors::AMD;
235 else if(properties.vendorID == 4318)
236 capabilities.vendor = Vendors::nVidia;
237 else if(properties.vendorID == 32902)
238 capabilities.vendor = Vendors::Intel;
239 else if(properties.vendorID == 4203)
240 capabilities.vendor = Vendors::Apple;
241
242 if(properties.vendorID == 4130){ // AMD
243 if(strstr(properties.name, "FireGL") != nullptr){
244 capabilities.series = Series::FireGL;
245 }
246 else if(strstr(properties.name, "RadeonX") != nullptr){
247 capabilities.series = Series::RadeonX;
248 }
249 else if(strstr(properties.name, "RadeonHD") != nullptr){
250 capabilities.series = Series::RadeonHD;
251 }
252 }
253 else if(properties.vendorID == 4318){ // nVidia
254 if(strstr(properties.name, "QuadroFX") != nullptr){
255 capabilities.series = Series::QuadroFX;
256 }
257 else if(strstr(properties.name, "Quadro") != nullptr){
258 capabilities.series = Series::Quadro;
259 }
260 else if(strstr(properties.name, "GeForce") != nullptr){
261 capabilities.series = Series::geForce;
262 }
263 }
264 else if(properties.vendorID == 32902){ // Intel
265 if(strstr(properties.name, "IrisPro") != nullptr){
266 capabilities.series = Series::IrisPro;
267 }
268 else if(strstr(properties.name, "Iris") != nullptr){
269 capabilities.series = Series::Iris;
270 }
271 else if(strstr(properties.name, "HD") != nullptr){
272 capabilities.series = Series::HD;
273 }
274 }
275
276 capabilities.model = properties.deviceID;
277
278#ifndef EMSCRIPTEN
279 WGPUSupportedLimits adapter_limits = {};
280 if(wgpuAdapterGetLimits(adapter, &adapter_limits)){
281 LOG_INFO(logger, "adapter_limits ");
282 LOG_INFO(logger, "maxTextureDimension1D %u", adapter_limits.limits.maxTextureDimension1D);
283 LOG_INFO(logger, "maxTextureDimension2D %u", adapter_limits.limits.maxTextureDimension2D);
284 LOG_INFO(logger, "maxTextureDimension3D %u", adapter_limits.limits.maxTextureDimension3D);
285 LOG_INFO(logger, "maxTextureArrayLayers %u", adapter_limits.limits.maxTextureArrayLayers);
286 LOG_INFO(logger, "maxBindGroups %u", adapter_limits.limits.maxBindGroups);
287#ifndef EMSCRIPTEN
288 LOG_INFO(logger, "maxBindingsPerBindGroup %u", adapter_limits.limits.maxBindingsPerBindGroup);
289#endif
290 LOG_INFO(logger, "maxDynamicUniformBuffersPerPipelineLayout %u", adapter_limits.limits.maxDynamicUniformBuffersPerPipelineLayout);
291 LOG_INFO(logger, "maxDynamicStorageBuffersPerPipelineLayout %u", adapter_limits.limits.maxDynamicStorageBuffersPerPipelineLayout);
292 LOG_INFO(logger, "maxSampledTexturesPerShaderStage %u", adapter_limits.limits.maxSampledTexturesPerShaderStage);
293 LOG_INFO(logger, "maxSamplersPerShaderStage %u", adapter_limits.limits.maxSamplersPerShaderStage);
294 LOG_INFO(logger, "maxStorageBuffersPerShaderStage %u", adapter_limits.limits.maxStorageBuffersPerShaderStage);
295 LOG_INFO(logger, "maxStorageTexturesPerShaderStage %u", adapter_limits.limits.maxStorageTexturesPerShaderStage);
296 LOG_INFO(logger, "maxUniformBuffersPerShaderStage %u", adapter_limits.limits.maxUniformBuffersPerShaderStage);
297 LOG_INFO(logger, "maxUniformBufferBindingSize %llu", adapter_limits.limits.maxUniformBufferBindingSize);
298 LOG_INFO(logger, "maxStorageBufferBindingSize %llu", adapter_limits.limits.maxStorageBufferBindingSize);
299 LOG_INFO(logger, "minUniformBufferOffsetAlignment %u", adapter_limits.limits.minUniformBufferOffsetAlignment);
300 LOG_INFO(logger, "minStorageBufferOffsetAlignment %u", adapter_limits.limits.minStorageBufferOffsetAlignment);
301 LOG_INFO(logger, "maxVertexBuffers %u", adapter_limits.limits.maxVertexBuffers);
302#ifndef EMSCRIPTEN
303 LOG_INFO(logger, "maxBufferSize %llu", adapter_limits.limits.maxBufferSize);
304#endif
305 LOG_INFO(logger, "maxVertexAttributes %u", adapter_limits.limits.maxVertexAttributes);
306 LOG_INFO(logger, "maxVertexBufferArrayStride %u", adapter_limits.limits.maxVertexBufferArrayStride);
307 LOG_INFO(logger, "maxInterStageShaderComponents %u", adapter_limits.limits.maxInterStageShaderComponents);
308#ifndef EMSCRIPTEN
309 LOG_INFO(logger, "maxInterStageShaderVariables %u", adapter_limits.limits.maxInterStageShaderVariables);
310 LOG_INFO(logger, "maxColorAttachments %u", adapter_limits.limits.maxColorAttachments);
311 LOG_INFO(logger, "maxColorAttachmentBytesPerSample %u", adapter_limits.limits.maxColorAttachmentBytesPerSample);
312#endif
313 LOG_INFO(logger, "maxComputeWorkgroupStorageSize %u", adapter_limits.limits.maxComputeWorkgroupStorageSize);
314 LOG_INFO(logger, "maxComputeInvocationsPerWorkgroup %u", adapter_limits.limits.maxComputeInvocationsPerWorkgroup);
315 LOG_INFO(logger, "maxComputeWorkgroupSizeX %u", adapter_limits.limits.maxComputeWorkgroupSizeX);
316 LOG_INFO(logger, "maxComputeWorkgroupSizeY %u", adapter_limits.limits.maxComputeWorkgroupSizeY);
317 LOG_INFO(logger, "maxComputeWorkgroupSizeZ %u", adapter_limits.limits.maxComputeWorkgroupSizeZ);
318 LOG_INFO(logger, "maxComputeWorkgroupsPerDimension %u", adapter_limits.limits.maxComputeWorkgroupsPerDimension);
319 }
320#endif
321
322 // Sample adapter_limits (GTX 1070)
323 // maxTextureDimension1D 16384
324 // maxTextureDimension2D 16384
325 // maxTextureDimension3D 2048
326 // maxTextureArrayLayers 2048
327 // maxBindGroups 4
328 // maxBindingsPerBindGroup 1000
329 // maxDynamicUniformBuffersPerPipelineLayout 0
330 // maxDynamicStorageBuffersPerPipelineLayout 0
331 // maxSampledTexturesPerShaderStage 16
332 // maxSamplersPerShaderStage 16
333 // maxStorageBuffersPerShaderStage 8
334 // maxStorageTexturesPerShaderStage 8
335 // maxUniformBuffersPerShaderStage 12
336 // maxUniformBufferBindingSize 65536
337 // maxStorageBufferBindingSize 134217728
338 // minUniformBufferOffsetAlignment 256
339 // minStorageBufferOffsetAlignment 256
340 // maxVertexBuffers 8
341 // maxBufferSize 2147483648
342 // maxVertexAttributes 16
343 // maxVertexBufferArrayStride 2048
344 // maxInterStageShaderComponents 60
345 // maxInterStageShaderVariables 16
346 // maxColorAttachments 8
347 // maxColorAttachmentBytesPerSample 32
348 // maxComputeWorkgroupStorageSize 32768
349 // maxComputeInvocationsPerWorkgroup 1024
350 // maxComputeWorkgroupSizeX 1024
351 // maxComputeWorkgroupSizeY 1024
352 // maxComputeWorkgroupSizeZ 64
353 // maxComputeWorkgroupsPerDimension 65535
354
355 // Required limits
356 WGPURequiredLimits required_limits = {};
357 required_limits.limits = WebGPUDefaultLimits(); // Request WebGPU default limits
358
359 // Some buggy limits
360 required_limits.limits.maxDynamicUniformBuffersPerPipelineLayout = 0;
361 required_limits.limits.maxDynamicStorageBuffersPerPipelineLayout = 0;
362
363 WGPUFeatureName features[] = {
364 WGPUFeatureName_TextureCompressionBC,
365#ifndef EMSCRIPTEN
366 WGPUFeatureName_SurfaceCapabilities
367#endif
368 };
369
370 // Get device
371 WGPUDeviceDescriptor device_desc = {};
372 device_desc.label = "WebGPU device";
373
374#if defined(EMSCRIPTEN) && (__EMSCRIPTEN_major__ <= 3) && (__EMSCRIPTEN_minor__ <= 1) && (__EMSCRIPTEN_tiny__ < 61)
375 // Name of this field changed sometime before emscripten 3.1.61
376 device_desc.requiredFeaturesCount = sizeof(features)/sizeof(features[0]);
377#else
378 device_desc.requiredFeatureCount = sizeof(features)/sizeof(features[0]);
379#endif
380 device_desc.requiredFeatures = features;
381 device_desc.requiredLimits = &required_limits;
382 device_desc.defaultQueue.label = "Default WebGPU queue";
383 device_desc.deviceLostCallback = device_lost;
384 device_desc.deviceLostUserdata = this;
385 // WGPUDawnTogglesDescriptor toggles_desc = {};
386 // toggles_desc.chain;
387 // toggles_desc.enabledTogglesCount;
388 // toggles_desc.enabledToggles;
389 // toggles_desc.disabledTogglesCount;
390 // toggles_desc.disabledToggles;
391 // WGPUDawnCacheDeviceDescriptor dawn_cache_desc = {};
392 // dawn_cache_desc.chain;
393 // dawn_cache_desc.isolationKey;
394
395 wgpuAdapterRequestDevice(adapter, &device_desc, request_device, this);
396 }
397
398 void GraphicsDeviceWebGPU::initialize_device(WGPUDevice device_in)
399 {
400 device = device_in;
401
402 // Setup logging
403#ifndef EMSCRIPTEN
404 wgpuDeviceSetLoggingCallback(device, logging_callback, this);
405#endif
406 wgpuDeviceSetUncapturedErrorCallback(device, error_callback, this);
407
408 WGPUSupportedLimits device_limits = {};
409 if(wgpuDeviceGetLimits(device, &device_limits)){
410 LOG_INFO(logger, "device_limits ");
411 LOG_INFO(logger, "maxTextureDimension1D %u", device_limits.limits.maxTextureDimension1D);
412 LOG_INFO(logger, "maxTextureDimension2D %u", device_limits.limits.maxTextureDimension2D);
413 LOG_INFO(logger, "maxTextureDimension3D %u", device_limits.limits.maxTextureDimension3D);
414 LOG_INFO(logger, "maxTextureArrayLayers %u", device_limits.limits.maxTextureArrayLayers);
415 LOG_INFO(logger, "maxBindGroups %u", device_limits.limits.maxBindGroups);
416#ifndef EMSCRIPTEN
417 LOG_INFO(logger, "maxBindingsPerBindGroup %u", device_limits.limits.maxBindingsPerBindGroup);
418#endif
419 LOG_INFO(logger, "maxDynamicUniformBuffersPerPipelineLayout %u", device_limits.limits.maxDynamicUniformBuffersPerPipelineLayout);
420 LOG_INFO(logger, "maxDynamicStorageBuffersPerPipelineLayout %u", device_limits.limits.maxDynamicStorageBuffersPerPipelineLayout);
421 LOG_INFO(logger, "maxSampledTexturesPerShaderStage %u", device_limits.limits.maxSampledTexturesPerShaderStage);
422 LOG_INFO(logger, "maxSamplersPerShaderStage %u", device_limits.limits.maxSamplersPerShaderStage);
423 LOG_INFO(logger, "maxStorageBuffersPerShaderStage %u", device_limits.limits.maxStorageBuffersPerShaderStage);
424 LOG_INFO(logger, "maxStorageTexturesPerShaderStage %u", device_limits.limits.maxStorageTexturesPerShaderStage);
425 LOG_INFO(logger, "maxUniformBuffersPerShaderStage %u", device_limits.limits.maxUniformBuffersPerShaderStage);
426 LOG_INFO(logger, "maxUniformBufferBindingSize %llu", device_limits.limits.maxUniformBufferBindingSize);
427 LOG_INFO(logger, "maxStorageBufferBindingSize %llu", device_limits.limits.maxStorageBufferBindingSize);
428 LOG_INFO(logger, "minUniformBufferOffsetAlignment %u", device_limits.limits.minUniformBufferOffsetAlignment);
429 LOG_INFO(logger, "minStorageBufferOffsetAlignment %u", device_limits.limits.minStorageBufferOffsetAlignment);
430 LOG_INFO(logger, "maxVertexBuffers %u", device_limits.limits.maxVertexBuffers);
431#ifndef EMSCRIPTEN
432 LOG_INFO(logger, "maxBufferSize %llu", device_limits.limits.maxBufferSize);
433#endif
434 LOG_INFO(logger, "maxVertexAttributes %u", device_limits.limits.maxVertexAttributes);
435 LOG_INFO(logger, "maxVertexBufferArrayStride %u", device_limits.limits.maxVertexBufferArrayStride);
436 LOG_INFO(logger, "maxInterStageShaderComponents %u", device_limits.limits.maxInterStageShaderComponents);
437#ifndef EMSCRIPTEN
438 LOG_INFO(logger, "maxInterStageShaderVariables %u", device_limits.limits.maxInterStageShaderVariables);
439 LOG_INFO(logger, "maxColorAttachments %u", device_limits.limits.maxColorAttachments);
440 LOG_INFO(logger, "maxColorAttachmentBytesPerSample %u", device_limits.limits.maxColorAttachmentBytesPerSample);
441#endif
442 LOG_INFO(logger, "maxComputeWorkgroupStorageSize %u", device_limits.limits.maxComputeWorkgroupStorageSize);
443 LOG_INFO(logger, "maxComputeInvocationsPerWorkgroup %u", device_limits.limits.maxComputeInvocationsPerWorkgroup);
444 LOG_INFO(logger, "maxComputeWorkgroupSizeX %u", device_limits.limits.maxComputeWorkgroupSizeX);
445 LOG_INFO(logger, "maxComputeWorkgroupSizeY %u", device_limits.limits.maxComputeWorkgroupSizeY);
446 LOG_INFO(logger, "maxComputeWorkgroupSizeZ %u", device_limits.limits.maxComputeWorkgroupSizeZ);
447 LOG_INFO(logger, "maxComputeWorkgroupsPerDimension %u", device_limits.limits.maxComputeWorkgroupsPerDimension);
448 }
449
450 // Update capabilities
451 capabilities.capabilities.RenderPass = true;
452 capabilities.capabilities.SyncObjects = false; // TODO
453 capabilities.capabilities.GeometryShaders = false;
454 capabilities.capabilities.TessellationShaders = false;
455 capabilities.capabilities.ComputeShaders = false; // TODO
456 capabilities.capabilities.SupportsHlsl = false;
457 capabilities.capabilities.SupportsMultipleThreads = false;
458 capabilities.capabilities.ConstantBufferOffsetAlignment = device_limits.limits.minUniformBufferOffsetAlignment;
459 capabilities.capabilities.ConstantBufferRange = true;
460 capabilities.capabilities.MaxTexture2DSize = device_limits.limits.maxTextureDimension2D;
461 capabilities.capabilities.MaxTexture3DSize = device_limits.limits.maxTextureDimension3D;
462 capabilities.capabilities.MaxTextureArrayLayers = device_limits.limits.maxTextureArrayLayers;
463
464 defaultSwapChain.initialize(device, surface);
465
466 queue = wgpuDeviceGetQueue(device);
467
468 WGPUCommandEncoderDescriptor command_encoder_desc = {};
469 command_encoder_desc.label = "Initialize Command Encoder";
470 commandEncoder = wgpuDeviceCreateCommandEncoder(device, &command_encoder_desc);
471
472 LOG_INFO(logger, "Has WebGPU Device");
473 has_device = true;
474 }
475
476 void GraphicsDeviceWebGPU::destroy()
477 {
478 LOG_INFO(logger, "WebGPU destroy");
479 if(commandEncoder){
480 wgpuCommandEncoderRelease(commandEncoder);
481 commandEncoder = nullptr;
482 }
483 wgpuQueueRelease(queue);
484 defaultSwapChain.destroy();
485 wgpuDeviceRelease(device);
486 wgpuAdapterRelease(adapter);
487 wgpuSurfaceRelease(surface);
488 wgpuInstanceRelease(instance);
489 }
490
492 {
493 buffers.releaseResources();
494 effects.releaseResources();
495 textures.releaseResources();
496 renderTargets.releaseResources();
497 }
498
500 {
501 if(commandEncoder){
502 WGPUCommandBufferDescriptor command_buffer_desc = {};
503 command_buffer_desc.label = "Inittialize Command Buffer";
504 WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish(commandEncoder, &command_buffer_desc);
505 wgpuCommandEncoderRelease(commandEncoder);
506 commandEncoder = nullptr;
507 wgpuQueueSubmit(queue, 1, &command_buffer);
508 buffers.resetInstances();
509 }
510
511#ifndef EMSCRIPTEN
512 // Emscripten: wgpuInstanceProcessEvents is unsupported (use requestAnimationFrame via html5.h instead)
513 wgpuInstanceProcessEvents(instance);
514 wgpuDeviceTick(device);
515#endif
516
517 defaultSwapChain.beginFrame();
518
519 WGPUCommandEncoderDescriptor command_encoder_desc = {};
520 command_encoder_desc.label = "Default Command Encoder";
521 commandEncoder = wgpuDeviceCreateCommandEncoder(device, &command_encoder_desc);
522 context.setDefaults();
523 }
524
525 void GraphicsDeviceWebGPU::endFrame(uint32_t syncInterval, uint32_t presentFlags)
526 {
527 context.updateRenderPass();
528 context.endRenderPassInt();
529
530#ifndef EMSCRIPTEN
531 WGPUImageCopyTexture src = {};
532 src.texture = defaultSwapChain.resolveTexture;
533 src.mipLevel = 0;
534 src.origin = {0, 0, 0};
535 src.aspect = WGPUTextureAspect_All;
536 WGPUImageCopyTexture dst = {};
537 dst.texture = wgpuSwapChainGetCurrentTexture(defaultSwapChain.swapChain);
538 dst.mipLevel = 0;
539 dst.origin = {0, 0, 0};
540 dst.aspect = WGPUTextureAspect_All;
541 WGPUExtent3D copy_size = {(uint32_t)defaultSwapChain.set_width, (uint32_t)defaultSwapChain.set_height, 1};
542 wgpuCommandEncoderCopyTextureToTexture(commandEncoder, &src, &dst, &copy_size);
543#endif
544
545 WGPUCommandBufferDescriptor command_buffer_desc = {};
546 command_buffer_desc.label = "Default Command Buffer";
547 WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish(commandEncoder, &command_buffer_desc);
548 wgpuCommandEncoderRelease(commandEncoder);
549 commandEncoder = nullptr;
550 wgpuQueueSubmit(queue, 1, &command_buffer);
551 buffers.resetInstances();
552
553 // wgpuQueueOnSubmittedWorkDone
554
555 defaultSwapChain.endFrame(syncInterval, presentFlags);
556 }
557
558}
virtual void releaseResources() override
Releases all allocated buffer resources.
Definition: BuffersWebGPU.h:61
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 endFrame(uint32_t=0, uint32_t=PresentFlags::None) override
Signal the end of a 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.
Log implementation class.
Definition: LogManager.h:139
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, uint32_t 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:180
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
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