I've been hacking away at this for the last few days and have finally gotten both D3D12 and Vulkan going on my Vive2 (Windows only).
I used pretty much the approach suggested by Austin above, which basically just involved adding some openxr config info to AdapterDiscoveryOptions structs, eg:
// DawnNative.h, namespace dawn::native
//
struct DAWN_NATIVE_EXPORT OpenXRConfigBase {
bool enabled = false; // OpenXR off by default
};
// VulkanBackend.h, namespace dawn::native::vulkan
//
struct DAWN_NATIVE_EXPORT OpenXRConfig : dawn::native::OpenXRConfigBase {
std::function<::VkResult(PFN_vkGetInstanceProcAddr,
const VkInstanceCreateInfo*,
const VkAllocationCallbacks*,
VkInstance*)>
CreateVkInstance;
std::function<::VkResult(VkInstance, VkPhysicalDevice*)> GetVkPhysicalDevice;
std::function<::VkResult(PFN_vkGetInstanceProcAddr,
VkPhysicalDevice,
const VkDeviceCreateInfo*,
const VkAllocationCallbacks*,
VkDevice*)>
CreateVkDevice;
};
(Note: You need to use ::VkResult as
dawn::native privately wraps VkResult. They're 2 completely different types, but look the same to the compiler if you only #include the dawn public headers!)
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase {
AdapterDiscoveryOptions();
bool forceSwiftShader = false;
OpenXRConfig openXRConfig;
};
So to get an xr compatible 'dawn' adapter you need to go:
auto opts = new dawn::native::vulkan::AdapterDiscoverOptions();
opts->openXRConfig.enabled = true;
opts->
CreateVkInstance = [=](...){...};
opts->
GetVkPhysicalDevice = [=](...){...};
opts->CreateVkDevice = [=](...){...};
instance->DiscoverAdapters(opts);
...etc...
I also had to add a few helpers to VulkanBackend:
DAWN_NATIVE_EXPORT VkPhysicalDevice GetVkPhysicalDevice(WGPUDevice device);
DAWN_NATIVE_EXPORT VkDevice GetVkDevice(WGPUDevice device);
DAWN_NATIVE_EXPORT uint32_t GetGraphicsQueueFamily(WGPUDevice device);
DAWN_NATIVE_EXPORT WGPUTexture CreateWGPUTexture(WGPUDevice device, const WGPUTextureDescriptor* descriptor, VkImage_T* image);
(Note: You needed to use VkImage_T* here as dawn privately wrap the VkImage type.)
Some of these are kind of redundant as they end up returning the same thingscreated by OpenXR in the first place, but this nicely separates wgpu device creation from openxr session creation IMO.
I haven't done a OpenXRConfig for D3D12 yet as D3D12 OpenXR 'just works' for me, ie: I just pass in the (only) d3d12 webgpu device and OpenXR works fine. This wont be the case for everyone though and one needs to be written although it looks like it'll be much simpler (The D3DDevice needs to have a specific 'LUID' which can be passed in via OpenXRConfig). I'm pretty sure OpenGL will also be pretty simple, but have no idea what's involved with metal.
So in my own 'tinyxr' library I've ended up with:
// Creates a (hopefully) XR compatible wgpu device
WGPUDevice createXRCompatibleWGPUDevice(WGPUBackendType);
// Create an XR session from a wgpu device.
XRSession createXRSession(WGPUDevice device);
I've also put together a little 'dawnxr' library that replaces a bunch of OpenXR functions with dawn compatible equivalents, and adds a dawn backend that works the same as the various KHR backends, which makes the above createXRSession much easier to write. I'll upload this to github soon.
Bye!
Mark