Vulkan: isRenderTargetFormatSupported() returns false for every depth/stencil format
- Dominant language
- C++
- Stars
- 20.5k
- Forks
- 2.3k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 83
Description
`VulkanDriver::isRenderTargetFormatSupported` tests the color attachment bit, which no depth or
stencil format ever has:
```cpp
// filament/backend/src/vulkan/VulkanDriver.cpp
bool VulkanDriver::isRenderTargetFormatSupported(TextureFormat format) {
...
vkGetPhysicalDeviceFormatProperties(mPlatform->getPhysicalDevice(), vkformat, &info);
return (info.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) != 0;
}
```
So `DEPTH16`, `DEPTH24`, `DEPTH32F`, `DEPTH24_STENCIL8`, `DEPTH32F_STENCIL8` and `STENCIL8` all
answer false, whatever the device supports. The bit to test for those is
`VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT`.
The other backends disagree: OpenGL's implementation lists depth and stencil formats among the
supported ones, and Metal returns true for anything with a valid `MTLPixelFormat`. Vulkan is the
outlier.
### Why it matters
It makes the query unusable for picking a depth/stencil format, which is the one place a caller
would want it. `RendererUtils::colorPass` currently picks without asking:
```cpp
// filament/src/RendererUtils.cpp
TextureFormat const stencilFormat = isES2 ?
TextureFormat::DEPTH24_STENCIL8 : TextureFormat::DEPTH32F_STENCIL8;
```
Vulkan guarantees one of `VK_FORMAT_D32_SFLOAT_S8_UINT` / `VK_FORMAT_D24_UNORM_S8_UINT` and not
both, so a device can lack the one chosen. On a Raspberry Pi 5 (V3D 7.1.7.0, V3DV Mesa) it does:
```
D32_SFLOAT_S8_UINT optimalTilingFeatures = 0x0
D24_UNORM_S8_UINT optimalTilingFeatures = 0xce01 (DEPTH_STENCIL_ATTACHMENT_BIT set)
```
A view with `setStencilBufferEnabled(true)` allocates the first anyway, and V3DV segfaults inside
`vkCreateImageView` on the first attachment view over it -- `VulkanTexture::getAttachmentView` <-
`VulkanAttachment::getImageView` <- `VulkanRenderTarget`, three frames into the first pass, with
nothing in the log naming a format. Substituting `DEPTH24_STENCIL8` runs indefinitely.
Fixing the query is what lets the format be chosen by capability rather than by constant. Happy to
send a PR for the query alone if that is useful; the format selection is a separate call.
Filament 1.75.0, and unchanged on `main` as of today.
Contributor guide
Research direction
Start in filament/backend/src/vulkan/VulkanDriver.cpp at VulkanDriver::isRenderTargetFormatSupported and compare the format-feature checks with the OpenGL and Metal implementations mentioned in the issue. Verify the listed depth and stencil formats against the appropriate Vulkan capability bit, including the Raspberry Pi 5 values described. Done means supported formats no longer all return false and unsupported formats remain rejected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend, computer-graphics
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100