Uniform buffer loads fail on Metal backend on Intel GPUs
- Dominant language
- C++
- Stars
- 20.5k
- Forks
- 2.3k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 83
Description
**Describe the bug**
There are visible shadow artifacts when using the Metal backend with Intel GPUs. Based on our investigations the root cause is that uniform buffer loads sometimes fail. I could repro it on tag v1.49.0 but on current `main` too.
**To Reproduce**
Just run gltf_viewer sample with `FILAMENT_FORCE_INTEGRATED_GPU=1` on a device which has Intel GPU (default view settings).
**Expected behavior**
No visual artifacts.
**Screenshots**
https://github.com/google/filament/assets/12460850/8783e405-9dd4-4d4f-91c4-4a4cd0a91dfd
**Logs**
The actual log is spammed with warnings because SPIRV-Cross generates unused variables in Metal shaders. I hope this is enough:
```
FEngine (64 bits) created at 0x10c024c00 (threading is enabled)
FEngine resolved backend: Metal
2024-02-21 21:49:09.908852+0100 gltf_viewer[22812:97578] Metal GPU Frame Capture Enabled
2024-02-21 21:49:09.909171+0100 gltf_viewer[22812:97578] Metal API Validation Enabled
Selected physical device 'Intel(R) UHD Graphics 630'
Supported GPU families:
MTLGPUFamilyCommon3
MTLGPUFamilyMac2
Features:
readWriteTextureSupport: true
Backend feature level: 3
FEngine feature level: 3
```
**Desktop (please complete the following information):**
- OS: macOS (tested on 13.2 and 14.1)
- GPU: Intel UHD 630 and Intel Iris Plus Graphics 640
- Backend: Metal
**Additional context**
Here's a screenshot of an Xcode frame capture of gltf_viewer sample with the DamagedHelmet model. This is a draw call from the shadow pass. `initObjectUniforms()` can see the per-renderable UBO (see highlighted variables at the bottom) but the thread local variables (e.g. `object_uniforms_worldFromModelNormalMatrix`) contain zeros at the end of the function. This is not the only affected draw call, only the first of them. Here it's related to the **UBO containing an array**, so setting `FILAMENT_HAS_FEATURE_INSTANCING` to false fixes this particular draw call, but the issue reappears around SSAO.

The [currently accessible Metal Feature Set Tables](https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf) says Mac2 family GPUs use 32 byte alignment (see _Minimum constant buffer offset alignment_) but Apple originally recommended 256, they just changed it ~2 years ago (I can attach the old _Metal Feature Set Tables.pdf_, if interested). Filament uses 32 bytes too for Mac2 GPUs. We were suspecting UBO alignment issues but setting `METAL_CONSTANT_BUFFER_OFFSET_ALIGNMENT` to 256 doesn't help.
Any ideas what could this be?
Contributor guide
Assessment
This issue has not been assessed yet.