vulkan: enumerate portability-subset Vulkan implementations on macOS#67
vulkan: enumerate portability-subset Vulkan implementations on macOS#67scasekar wants to merge 1 commit into
Conversation
Dawn's Vulkan backend on macOS currently does not enumerate MoltenVK as
an adapter. Two upstream gaps stack:
1. `vkCreateInstance` doesn't request `VK_KHR_portability_enumeration`
and doesn't set `VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR`
on `createInfo.flags`. Per the Vulkan loader spec, non-conformant
(portability-subset) Vulkan implementations like MoltenVK are
invisible to applications that don't opt-in via this flag.
`vkEnumeratePhysicalDevices` returns 0 devices, and Dawn reports
`wgpu::RequestAdapterStatus::Unavailable` / "No supported adapters".
2. `Backend::DiscoverPhysicalDevices` short-circuits with
`#if DAWN_PLATFORM_IS(MACOS) ... if (icd == ICD::None) continue;`
based on the historical assumption that no non-SwiftShader Vulkan
is available on Mac. MoltenVK loads via the normal loader ICD path
(ICD::None from Dawn's perspective), so this skip prevents Dawn
from ever probing it — even after gap (1) is fixed.
Three surgical changes:
- VulkanExtensions.h: add `InstanceExt::PortabilityEnumeration` (a new
enumerant before `EnumCount`).
- VulkanExtensions.cpp: add the `{InstanceExt::PortabilityEnumeration,
"VK_KHR_portability_enumeration"}` entry to the name table, and a
matching case in `EnsureDependencies` (no transitive dependencies).
- BackendVk.cpp:
- In `CreateVkInstance`, set `VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR`
on `createInfo.flags` when the loader advertises the extension.
- Remove the `#if DAWN_PLATFORM_IS(MACOS) ... continue` that skips
`ICD::None` on macOS.
Quest/Android implications: Adreno Vulkan is a fully conformant
implementation, NOT portability-subset, so the loader doesn't advertise
the extension there and the new `if (HasExt(...))` flag-set is a no-op.
The ICD::None loop already runs on Android. So this change is mac-only
behavior in practice.
Verified on Apple Silicon (M1, macOS 14, AppleClang 17, Vulkan SDK
1.4.341, MoltenVK 1.4.1) — same backend-agnostic WGSL triangle renders
byte-identical PNG (3,885 bytes, MD5 bfb7f207fb7e0535a829e5f0a63df60b)
on both `--backend metal` and `--backend vulkan` from the same
triangle.cpp binary.
End-to-end stereo XR render via dawnxr against Meta XR Simulator 71.0.0
also works — 276 frames in 5s at 1680x1760 per eye (Quest 3 native
projection resolution).
Discovered during a pre-proposal feasibility spike for an upcoming Navy
SBIR phase-I VR application (DON26BZ01-NV015) where Dawn-native + OpenXR
is the primary delivery surface for Quest 3 with the same WebGPU
codebase targeting desktop browsers. The portability_enumeration support
is broadly useful for any Mac developer working on the Quest-target
Vulkan code path locally without a real Vulkan headset.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
Why MoltenVK instead of KosmicKrisp? |
|
Also, currently we just use SwiftShader for local development of the Vulkan backend on Mac. Is that insufficient for you? |
|
Thanks both. @dj2: Why MoltenVK vs KosmicKrisp? The PR title was misleading and I've retitled it. The patch isn't MoltenVK-specific; it implements what the Vulkan loader spec asks of any application that wants to enumerate portability-subset implementations. Enabling @kainino0x: Is SwiftShader insufficient? We're targeting Quest 3 via Android NDK and using the Meta XR Simulator on Mac for inner-loop work. We tend to iterate on performance enhancements in the simulator, which is hard to do against a CPU rasterizer. |
|
I don't know about the |
|
Closing in favor of upf-gti#1, which is the more appropriate landing point since wgpuEngine's FetchDawn.cmake fetches from that fork. Empirical test results (KosmicKrisp discovery with and without the skip) and rationale are in the new PR. Per @dj2's KosmicKrisp-is-conformant correction, the new PR drops the Thanks both for the review, the feedback redirected this toward a cleaner home. |
Summary
Three surgical edits that let Dawn's Vulkan backend enumerate and use portability-subset Vulkan implementations (MoltenVK, KosmicKrisp, future) on macOS hosts. Without these, requesting
wgpu::BackendType::Vulkanon macOS returnsRequestAdapterStatus::Unavailable("No supported adapters") even whenvulkaninfofinds the same ICD through the same loader.Note: I'm aware Dawn's primary code review happens on Gerrit (dawn-review.googlesource.com). Happy to re-submit there if preferred — opening this here first as draft so I can link upstream PRs to the spike artifacts. Please let me know which workflow you'd like.
Why
Two upstream gaps stack:
Gap 1:
vkCreateInstancedoesn't opt in to portability enumeration.Per the Vulkan loader spec, non-conformant (portability-subset) Vulkan implementations are invisible to applications that don't:
VK_KHR_portability_enumeration, ANDVK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHRonVkInstanceCreateInfo::flags.Dawn does neither. Result:
vkEnumeratePhysicalDevicesreturns 0 on macOS even though a portability-subset ICD is loaded.Gap 2:
Backend::DiscoverPhysicalDevicesskipsICD::Noneon macOS.That assumption predates Apple Silicon portability-subset Vulkan implementations (MoltenVK, KosmicKrisp). These ICDs are loaded via the loader's normal ICD path (which is
ICD::Nonefrom Dawn's perspective), so the skip prevents Dawn from probing them — even after Gap 1 is fixed.Changes
src/dawn/native/vulkan/VulkanExtensions.h: addInstanceExt::PortabilityEnumerationenumerant.src/dawn/native/vulkan/VulkanExtensions.cpp: add{InstanceExt::PortabilityEnumeration, "VK_KHR_portability_enumeration"}to the name table + a matching case inEnsureDependencies(no transitive deps).src/dawn/native/vulkan/BackendVk.cpp:CreateVkInstance, setVK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHRoncreateInfo.flagswhen the loader advertises the extension.ICD::Noneskip inBackend::DiscoverPhysicalDevices. Replace it with a comment explaining the now-fixed historical concern.Behavior on non-Apple platforms
HasExt(...)returns false, the newcreateInfo.flags |=is a no-op. TheICD::Noneloop already ran on Android (no#if DAWN_PLATFORM_IS(ANDROID)guard) so removing the macOS skip changes nothing there.Test plan
-DDAWN_ENABLE_VULKAN=ON -DTINT_BUILD_SPV_WRITER=ON.bfb7f207fb7e0535a829e5f0a63df60b) on--backend metaland--backend vulkanfrom the sametriangle.cppbinary.HasExt(PortabilityEnumeration)which is false on conformant Vulkan implementations.Context
Discovered while iterating on a Quest 3 (Android NDK + Adreno Vulkan) Dawn-native + OpenXR application using the Meta XR Simulator on Mac as the inner-loop validation target. The portability_enumeration support is broadly useful for any Mac developer working on a Quest-target Vulkan code path locally without a real Vulkan headset — collapsing iteration time from minutes-with-headset-don/doff to seconds at a desktop terminal.