RESOLVED FIXED270079
PlayCanvas WebGPU examples failed to run
https://bugs.webkit.org/show_bug.cgi?id=270079
Summary PlayCanvas WebGPU examples failed to run
Martin
Reported 2024-02-26 04:43:27 PST
Created attachment 470048 [details] validation errors WebGPU engine examples do not run in Safari Tech Preview 189 (Safari 17.4, WebKit 19619.1.3.2) url: https://playcanvas.github.io/ By default they just don't work, even though the clear color changes in some examples. No errors are reported in the console. With the debug engine build using wgpu.pushErrorScope('validation') and device.wgpu.popErrorScope().then((error) => { console.log(error); } we get validation errors with no reason given. Our internal tracking ticket: https://github.com/playcanvas/engine/issues/6088 Note that the example work in Chrome WebGPU.
Attachments
validation errors (507.76 KB, image/png)
2024-02-26 04:43 PST, Martin
no flags
https://playcanvas.github.io/#/misc/hello-world (746.60 KB, image/png)
2024-04-08 23:22 PDT, Mike Wyrzykowski
no flags
Radar WebKit Bug Importer
Comment 1 2024-03-04 04:44:13 PST
Mike Wyrzykowski
Comment 2 2024-03-04 09:21:32 PST
I see a shader compilation failure when running locally: 1 error generated while compiling the shader: 100:6: type in function call does not match parameter type: expected 'ptr<workgroup, array<atomic<u32>, 1>, read_write>', found 'ptr<uniform, host_shareable, read>' As this is allowed by Chrome, we need to see if Chrome is in line with the specification or if this is a bug in our WGSL -> metal step
Mike Wyrzykowski
Comment 3 2024-04-08 22:29:42 PDT
Shader compilation is fixed and now I see a validation error: "insufficient dynamic offsets in layout for bind group" will investigate
Mike Wyrzykowski
Comment 4 2024-04-08 22:46:09 PDT
There is an issue in playcanvas. playcanvas is using 288 for the dynamic offset, but WebGPU's default alignment is 256. It appears playcanvas is assuming an alignment of 32, which is not supported currently in WebKit as some platforms require 256 byte alignments. Relevant sections of the WebGPU specification: https://www.w3.org/TR/webgpu/#programmable-passes-bind-groups ... If bufferLayout.type is "uniform": dynamicOffset must be a multiple of minUniformBufferOffsetAlignment. If bufferLayout.type is "storage" or "read-only-storage": dynamicOffset must be a multiple of minStorageBufferOffsetAlignment. ... and https://www.w3.org/TR/webgpu/#limits ... minUniformBufferOffsetAlignment GPUSize32 alignment 256 bytes The required alignment for GPUBufferBinding.offset and the dynamic offsets provided in setBindGroup(), for bindings with a GPUBindGroupLayoutEntry entry for which entry.buffer?.type is "uniform". minStorageBufferOffsetAlignment GPUSize32 alignment 256 bytes The required alignment for GPUBufferBinding.offset and the dynamic offsets provided in setBindGroup(), for bindings with a GPUBindGroupLayoutEntry entry for which entry.buffer?.type is "storage" or "read-only-storage".
Mike Wyrzykowski
Comment 5 2024-04-08 22:52:58 PDT
There are still other issues preventing the playcanvas samples from working, some may be WebKit bugs, I am investigating
Mike Wyrzykowski
Comment 6 2024-04-08 23:02:04 PDT
Next error we see is during pipeline creation: "Shader is incompatible with layout pipeline"
Mike Wyrzykowski
Comment 7 2024-04-08 23:12:40 PDT
Specifically the pipeline has a sampler_comparison sampler but we think the source is using a sampler
Mike Wyrzykowski
Comment 9 2024-04-08 23:23:19 PDT
If I skip the sampler - sampler_comparison validation, the cube renders but is clipped by the far plane
Mike Wyrzykowski
Comment 10 2024-04-08 23:27:53 PDT
gputrace shows it to be clipped since some post-transform z values of the cube are negative
Martin
Comment 11 2024-04-11 01:39:29 PDT
Thanks for looking into this. PlayCanvas is using minUniformBufferOffsetAlignment correctly here I believe, but it's reported by the device as 32: GPUSupportedLimits maxBindGroups: 11 maxBindGroupsPlusVertexBuffers: 30 maxBindingsPerBindGroup: 65535 maxBufferSize: 2147483644 maxColorAttachmentBytesPerSample: 64 maxColorAttachments: 8 maxComputeInvocationsPerWorkgroup: 1024 maxComputeWorkgroupSizeX: 1024 maxComputeWorkgroupSizeY: 1024 maxComputeWorkgroupSizeZ: 1024 maxComputeWorkgroupStorageSize: 32768 maxComputeWorkgroupsPerDimension: 65535 maxDynamicStorageBuffersPerPipelineLayout: 65535 maxDynamicUniformBuffersPerPipelineLayout: 65535 maxInterStageShaderComponents: 124 maxInterStageShaderVariables: 124 maxSampledTexturesPerShaderStage: 44 maxSamplersPerShaderStage: 22 maxStorageBufferBindingSize: 2147483644 maxStorageBuffersPerShaderStage: 44 maxStorageTexturesPerShaderStage: 44 maxTextureArrayLayers: 2048 maxTextureDimension1D: 16384 maxTextureDimension2D: 16384 maxTextureDimension3D: 2048 maxUniformBufferBindingSize: 2147483644 maxUniformBuffersPerShaderStage: 44 maxVertexAttributes: 30 maxVertexBufferArrayStride: 65532 maxVertexBuffers: 12 minStorageBufferOffsetAlignment: 32 minUniformBufferOffsetAlignment: 32 This is on M1 Max 14.4.1 (23E224) with Safari Tech Preview Release 191 (Safari 17.4, WebKit 19619.1.6.3). If I hardcode this to 256, I get the half clipped cube spinning around as you mentioned.
Martin
Comment 12 2024-04-11 02:16:35 PDT
I also had a look at the comparison sampler. I create the sampler with this descriptor: addressModeU: "clamp-to-edge" addressModeV: "clamp-to-edge" addressModeW: "repeat" compare: "less" magFilter: "linear" maxAnisotropy: 1 minFilter: "linear" Which I think should be a valid comparison sampler? Based on the spec: compare, of type GPUCompareFunction When provided the sampler will be a comparison sampler with the specified GPUCompareFunction. NOTE: Comparison samplers may use filtering, but the sampling results will be implementation-dependent and may differ from the normal filtering rules. Thanks!
Mike Wyrzykowski
Comment 13 2024-04-11 09:41:22 PDT
Oh that's right we do support 32 byte alignment, I was looking at non-Apple silicon Macs which are limited to 256 byte alignment in WebKit. Is PlayCanvas requesting 32 byte alignment in its call to GPUAdapter.requestDevice()? I tried logging the limits from the web process: % git diff diff --git a/Source/WebCore/Modules/WebGPU/GPUAdapter.cpp b/Source/WebCore/Modules/WebGPU/GPUAdapter.cpp index b626e3eac2b2..d5807b80d552 100644 --- a/Source/WebCore/Modules/WebGPU/GPUAdapter.cpp +++ b/Source/WebCore/Modules/WebGPU/GPUAdapter.cpp @@ -109,6 +109,10 @@ void GPUAdapter::requestDevice(ScriptExecutionContext& scriptExecutionContext, c return; } + if (deviceDescriptor) { + for (auto& [key,value] : deviceDescriptor->requiredLimits) + WTFLogAlways("%s, %llu", key.utf8().data(), value); + } m_backing->requestDevice(convertToBacking(deviceDescriptor), [deviceDescriptor, promise = WTFMove(promise), scriptExecutionContextRef = Ref { scriptExecutionContext }](RefPtr<WebGPU::Device>&& device) mutable { if (!device.get()) promise.reject(Exception(ExceptionCode::OperationError)); but I don't see PlayCanvas requesting requiredLimits: https://www.w3.org/TR/webgpu/#dom-gpudevicedescriptor-requiredlimits It's very possible we are failing conversion however
Mike Wyrzykowski
Comment 14 2024-04-11 09:42:15 PDT
The comparison sampler I assume is a WebKit bug for now. Thank you for providing how you create it, hopefully that will help us narrow down why we fail validation
Martin
Comment 15 2024-04-12 05:35:54 PDT
This is the start up code: https://github.com/playcanvas/engine/blob/af7d32caea14eca53d432ad9e7bff005be9a9094/src/platform/graphics/webgpu/webgpu-graphics-device.js#L219-L256 We provide empty requiredLimits currently, which should use the defaults I think: // Note that we can request limits, but it does not seem to be supported at the moment requiredLimits: { },
Mike Wyrzykowski
Comment 16 2024-04-12 09:12:06 PDT
oh empty requiredLimits is why 256 byte alignment is being used: https://www.w3.org/TR/webgpu/#limits "The default is used if a value is not explicitly specified in requiredLimits." the defaults value for minUniformBufferOffsetAlignment is 256: minUniformBufferOffsetAlignment GPUSize32 alignment 256 bytes Is Chrome also reporting 32 and allowing you to use 32 with empty limits? If so, I will file a Chromium issue I'll work around this for now and investigate the other issues
Mike Wyrzykowski
Comment 17 2024-04-12 09:13:25 PDT
GPUSupportedLimits is to inform what can be requested, but defaults are used if not explicitly requested
Martin
Comment 18 2024-04-12 09:33:41 PDT
Chrome gives me this with {} request: maxBindGroups: 4 maxBindGroupsPlusVertexBuffers: 24 maxBindingsPerBindGroup: 1000 maxBufferSize: 4294967296 maxColorAttachmentBytesPerSample: 128 maxColorAttachments: 8 maxComputeInvocationsPerWorkgroup: 1024 maxComputeWorkgroupSizeX: 1024 maxComputeWorkgroupSizeY: 1024 maxComputeWorkgroupSizeZ: 64 maxComputeWorkgroupStorageSize: 32768 maxComputeWorkgroupsPerDimension: 65535 maxDynamicStorageBuffersPerPipelineLayout: 8 maxDynamicUniformBuffersPerPipelineLayout: 10 maxInterStageShaderComponents: 112 maxInterStageShaderVariables: 28 maxSampledTexturesPerShaderStage: 16 maxSamplersPerShaderStage: 16 maxStorageBufferBindingSize: 4294967292 maxStorageBuffersPerShaderStage: 10 maxStorageTexturesPerShaderStage: 8 maxTextureArrayLayers: 256 maxTextureDimension1D: 16384 maxTextureDimension2D: 16384 maxTextureDimension3D: 2048 maxUniformBufferBindingSize: 65536 maxUniformBuffersPerShaderStage: 12 maxVertexAttributes: 30 maxVertexBufferArrayStride: 2048 maxVertexBuffers: 8 minStorageBufferOffsetAlignment: 256 minUniformBufferOffsetAlignment: 256
Mike Wyrzykowski
Comment 19 2024-04-12 09:35:52 PDT
That explains the dynamic buffer offsets, the GPUSupportedLimits are the maximum (or in case of alignments, minimum) which can be requested. But if you don't explicitly request different values, the defaults are used during device creation.
Mike Wyrzykowski
Comment 20 2024-04-12 11:37:57 PDT
Found another WebKit issue: https://bugs.webkit.org/show_bug.cgi?id=272598 will try to fix this one by Monday
Mike Wyrzykowski
Comment 21 2024-04-16 11:07:18 PDT
To conclude this, the WebKit issues are tracked by: https://bugs.webkit.org/show_bug.cgi?id=272598 https://bugs.webkit.org/show_bug.cgi?id=272617 https://bugs.webkit.org/show_bug.cgi?id=272637 and with the PlayCanvas issue with limits corrected, I successfully run all WebGPU samples from https://playcanvas.github.io/ on my M2 MacBook Pro. I didn't test on Intel Macs yet, if you try those and notice any issues please file another issue.
Note You need to log in before you can comment on or make changes to this bug.