1#include "Foundation/Platform/WindowData.h"
3#include "GraphicsDeviceWebGPU.h"
6#include "dawn/webgpu_cpp_print.h"
7#include "dawn/dawn_proc.h"
8#include "dawn/native/DawnNative.h"
12#include <emscripten/version.h>
15#include "Foundation/Logging/Logger.h"
20 void request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter,
char const * message,
void * userdata)
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);
29 void request_device(WGPURequestDeviceStatus status, WGPUDevice device,
char const * message,
void * userdata)
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);
38 void error_callback(WGPUErrorType type,
char const * message,
void * userdata)
42 LOG_ERROR(logger,
"WebGPU err (%d) %s", type, message);
46 void logging_callback(WGPULoggingType type,
char const * message,
void * userdata)
50 LOG_INFO(logger,
"WebGPU log (%d) x%s", type, message);
61 void device_lost(WGPUDeviceLostReason reason,
char const * message,
void * userdata)
65 if(reason == WGPUDeviceLostReason_Destroyed)
66 LOG_INFO(logger,
"device_lost (%d) %s", reason, message);
68 LOG_FATAL(logger,
"device_lost (%d) %s", reason, message);
69 assert(reason == WGPUDeviceLostReason_Destroyed);
72 WGPULimits WebGPUDefaultLimits()
75 WGPULimits limits = {};
76 limits.maxTextureDimension1D = 8192;
77 limits.maxTextureDimension2D = 8192;
78 limits.maxTextureDimension3D = 2048;
79 limits.maxTextureArrayLayers = 256;
80 limits.maxBindGroups = 4;
83 limits.maxBindingsPerBindGroup = 1000;
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;
98 limits.maxBufferSize = 268435456;
100 limits.maxVertexAttributes = 16;
101 limits.maxVertexBufferArrayStride = 2048;
102 limits.maxInterStageShaderComponents = 60;
104 limits.maxInterStageShaderVariables = 16;
105 limits.maxColorAttachments = 8;
106 limits.maxColorAttachmentBytesPerSample = 32;
108 limits.maxComputeWorkgroupStorageSize = 16384;
109 limits.maxComputeInvocationsPerWorkgroup = 256;
110 limits.maxComputeWorkgroupSizeX = 256;
111 limits.maxComputeWorkgroupSizeY = 256;
112 limits.maxComputeWorkgroupSizeZ = 64;
113 limits.maxComputeWorkgroupsPerDimension = 65535;
120 GraphicsDeviceWebGPU::GraphicsDeviceWebGPU(RenderingAllocatorInfo* )
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);
130 GraphicsDeviceWebGPU::~GraphicsDeviceWebGPU()
143 DawnProcTable procTable = dawn::native::GetProcs();
144 dawnProcSetProcs(&procTable);
148 WGPUInstanceDescriptor instance_desc = {};
149 instance = wgpuCreateInstance(&instance_desc);
152 WGPUSurfaceDescriptor surface_desc = {};
153 surface_desc.label =
"WebGPU Surface";
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;
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__)
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;
186#elif defined(__ANDROID_API__)
190 static_assert(
false,
"Implement WebGPU Android surface");
192 surface = wgpuInstanceCreateSurface(instance, &surface_desc);
195 WGPURequestAdapterOptions adapter_options = {};
196 adapter_options.nextInChain;
197 adapter_options.compatibleSurface = surface;
198 adapter_options.powerPreference = WGPUPowerPreference_Undefined;
199 adapter_options.forceFallbackAdapter;
201 adapter_options.compatibilityMode;
204 wgpuInstanceRequestAdapter(instance, &adapter_options, request_adapter,
this);
209 void GraphicsDeviceWebGPU::initialize_adapter(WGPUAdapter adapter_in)
211 adapter = adapter_in;
215 WGPUAdapterProperties properties = {};
218 wgpuAdapterGetProperties(adapter, &properties);
219 LOG_INFO(logger,
"vendorID %u", properties.vendorID);
221 LOG_INFO(logger,
"vendorName %s", properties.vendorName);
222 LOG_INFO(logger,
"architecture %s", properties.architecture);
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);
230 LOG_INFO(logger,
"compatibilityMode %s", properties.compatibilityMode?
"true":
"false");
233 if(properties.vendorID == 4130)
235 else if(properties.vendorID == 4318)
237 else if(properties.vendorID == 32902)
239 else if(properties.vendorID == 4203)
242 if(properties.vendorID == 4130){
243 if(strstr(properties.name,
"FireGL") !=
nullptr){
246 else if(strstr(properties.name,
"RadeonX") !=
nullptr){
249 else if(strstr(properties.name,
"RadeonHD") !=
nullptr){
253 else if(properties.vendorID == 4318){
254 if(strstr(properties.name,
"QuadroFX") !=
nullptr){
257 else if(strstr(properties.name,
"Quadro") !=
nullptr){
260 else if(strstr(properties.name,
"GeForce") !=
nullptr){
264 else if(properties.vendorID == 32902){
265 if(strstr(properties.name,
"IrisPro") !=
nullptr){
268 else if(strstr(properties.name,
"Iris") !=
nullptr){
271 else if(strstr(properties.name,
"HD") !=
nullptr){
276 capabilities.model = properties.deviceID;
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);
288 LOG_INFO(logger,
"maxBindingsPerBindGroup %u", adapter_limits.limits.maxBindingsPerBindGroup);
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);
303 LOG_INFO(logger,
"maxBufferSize %llu", adapter_limits.limits.maxBufferSize);
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);
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);
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);
356 WGPURequiredLimits required_limits = {};
357 required_limits.limits = WebGPUDefaultLimits();
360 required_limits.limits.maxDynamicUniformBuffersPerPipelineLayout = 0;
361 required_limits.limits.maxDynamicStorageBuffersPerPipelineLayout = 0;
363 WGPUFeatureName features[] = {
364 WGPUFeatureName_TextureCompressionBC,
366 WGPUFeatureName_SurfaceCapabilities
371 WGPUDeviceDescriptor device_desc = {};
372 device_desc.label =
"WebGPU device";
374#if defined(EMSCRIPTEN) && (__EMSCRIPTEN_major__ <= 3) && (__EMSCRIPTEN_minor__ <= 1) && (__EMSCRIPTEN_tiny__ < 61)
376 device_desc.requiredFeaturesCount =
sizeof(features)/
sizeof(features[0]);
378 device_desc.requiredFeatureCount =
sizeof(features)/
sizeof(features[0]);
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;
395 wgpuAdapterRequestDevice(adapter, &device_desc, request_device,
this);
398 void GraphicsDeviceWebGPU::initialize_device(WGPUDevice device_in)
404 wgpuDeviceSetLoggingCallback(device, logging_callback,
this);
406 wgpuDeviceSetUncapturedErrorCallback(device, error_callback,
this);
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);
417 LOG_INFO(logger,
"maxBindingsPerBindGroup %u", device_limits.limits.maxBindingsPerBindGroup);
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);
432 LOG_INFO(logger,
"maxBufferSize %llu", device_limits.limits.maxBufferSize);
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);
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);
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);
451 capabilities.capabilities.RenderPass =
true;
453 capabilities.capabilities.GeometryShaders =
false;
454 capabilities.capabilities.TessellationShaders =
false;
455 capabilities.capabilities.ComputeShaders =
false;
456 capabilities.capabilities.SupportsHlsl =
false;
457 capabilities.capabilities.SupportsMultipleThreads =
false;
460 capabilities.capabilities.
MaxTexture2DSize = device_limits.limits.maxTextureDimension2D;
461 capabilities.capabilities.
MaxTexture3DSize = device_limits.limits.maxTextureDimension3D;
464 defaultSwapChain.initialize(device, surface);
466 queue = wgpuDeviceGetQueue(device);
468 WGPUCommandEncoderDescriptor command_encoder_desc = {};
469 command_encoder_desc.label =
"Initialize Command Encoder";
470 commandEncoder = wgpuDeviceCreateCommandEncoder(device, &command_encoder_desc);
472 LOG_INFO(logger,
"Has WebGPU Device");
476 void GraphicsDeviceWebGPU::destroy()
478 LOG_INFO(logger,
"WebGPU destroy");
480 wgpuCommandEncoderRelease(commandEncoder);
481 commandEncoder =
nullptr;
483 wgpuQueueRelease(queue);
484 defaultSwapChain.destroy();
485 wgpuDeviceRelease(device);
486 wgpuAdapterRelease(adapter);
487 wgpuSurfaceRelease(surface);
488 wgpuInstanceRelease(instance);
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();
513 wgpuInstanceProcessEvents(instance);
514 wgpuDeviceTick(device);
519 WGPUCommandEncoderDescriptor command_encoder_desc = {};
520 command_encoder_desc.label =
"Default Command Encoder";
521 commandEncoder = wgpuDeviceCreateCommandEncoder(device, &command_encoder_desc);
522 context.setDefaults();
527 context.updateRenderPass();
528 context.endRenderPassInt();
531 WGPUImageCopyTexture src = {};
532 src.texture = defaultSwapChain.resolveTexture;
534 src.origin = {0, 0, 0};
535 src.aspect = WGPUTextureAspect_All;
536 WGPUImageCopyTexture dst = {};
537 dst.texture = wgpuSwapChainGetCurrentTexture(defaultSwapChain.swapChain);
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, ©_size);
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();
555 defaultSwapChain.
endFrame(syncInterval, presentFlags);
virtual void releaseResources() override
Releases all allocated buffer resources.
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.
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
Contains all Cogs related functionality.
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.
uint32_t MaxTexture2DSize
Using D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION as default.
bool SyncObjects
Support for syncronization objects.
uint32_t MaxTextureArrayLayers
Using D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION as default.
unsigned ConstantBufferOffsetAlignment
Minimum offset alignment when binding constant buffers.
bool ConstantBufferRange
supports binding a range of a constant buffer.
struct WindowData * windowData
Native window handle used to initialize the graphics device.
IIOHandler * ioHandler
Optional pointer to an IO handler.
@ QuadroFX
nVidia Quadro FX professional graphics adapters.
@ FireGL
AMD FireGL series.
@ geForce
nVidia geForce consumer adapters.
@ RadeonX
AMD Radeon X series.
@ RadeonHD
AMD Radeon HD series.
@ Quadro
nVidia Quadro professional graphics adapters.
@ nVidia
nVidia Corporation.