Skip to content

Commit

Permalink
Vulkan: enabled OpenXR support through XR_KHR_vulkan_enable2
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Dec 16, 2024
1 parent 14fce79 commit ffa20fd
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
toolset: ["Win32", "x64"]
build_type: ["Debug", "Release"]
cmake_generator: ["Visual Studio 17 2022"]
cmake_args: ["-DDILIGENT_BUILD_TESTS=ON -DDILIGENT_NO_WEBGPU=OFF"]
cmake_args: ["-DDILIGENT_BUILD_TESTS=ON -DDILIGENT_NO_WEBGPU=OFF -DDILIGENT_USE_OPENXR=ON "]
platform: ["Win32"]

include:
Expand Down
22 changes: 22 additions & 0 deletions Graphics/GraphicsEngine/interface/GraphicsTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -3408,6 +3408,22 @@ struct ImmediateContextCreateInfo
typedef struct ImmediateContextCreateInfo ImmediateContextCreateInfo;


#if DILIGENT_USE_OPENXR
/// OpenXR attributes
struct OpenXRAttribs
{
/// A pointer to the xrGetInstanceProcAddr function.
void* GetInstanceProcAddr DEFAULT_INITIALIZER(nullptr);

/// OpenXR instance handle (XrInstance).
Uint64 Instance DEFAULT_INITIALIZER(0);

/// OpenXR system id (XrSystemId).
Uint64 SystemId DEFAULT_INITIALIZER(0);
};
typedef struct OpenXRAttribs OpenXRAttribs;
#endif

/// Engine creation information
struct EngineCreateInfo
{
Expand Down Expand Up @@ -3478,6 +3494,12 @@ struct EngineCreateInfo
/// operations in the engine
struct IMemoryAllocator* pRawMemAllocator DEFAULT_INITIALIZER(nullptr);

#if DILIGENT_USE_OPENXR
/// An optional pointer to the OpenXR attributes, must be set if OpenXR is used.
/// See Diligent::OpenXRAttribs.
const OpenXRAttribs* pXRAttribs DEFAULT_INITIALIZER(nullptr);
#endif

/// An optional thread pool for asynchronous shader and pipeline state compilation.
///
/// \remarks When AsyncShaderCompilation device feature is enabled, the engine will use
Expand Down
7 changes: 7 additions & 0 deletions Graphics/GraphicsEngineVulkan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ else()
find_library(Vulkan_LIBRARY NAMES vulkan)
list(APPEND PRIVATE_DEPENDENCIES ${Vulkan_LIBRARY})
endif()
if(DILIGENT_USE_OPENXR)
list(APPEND PRIVATE_DEPENDENCIES OpenXR::headers)
endif()

set(PUBLIC_DEPENDENCIES
Diligent-GraphicsEngineVkInterface
Expand Down Expand Up @@ -311,6 +314,10 @@ if (${DILIGENT_NO_GLSLANG})
message("GLSLang is not being built. Vulkan backend will only be able to consume SPIRV byte code.")
endif()

if(DILIGENT_USE_OPENXR)
list(APPEND PRIVATE_COMPILE_DEFINITIONS DILIGENT_USE_OPENXR=1)
endif()

target_compile_definitions(Diligent-GraphicsEngineVk-static
PRIVATE
${PRIVATE_COMPILE_DEFINITIONS}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 Diligent Graphics LLC
* Copyright 2019-2024 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -62,6 +62,13 @@ class VulkanInstance : public std::enable_shared_from_this<VulkanInstance>
VkAllocationCallbacks* pVkAllocator = nullptr;
uint32_t IgnoreDebugMessageCount = 0;
const char* const* ppIgnoreDebugMessageNames = nullptr;

struct OpenXRInfo
{
uint64_t Instance = 0;
uint64_t SystemId = 0;
void* GetInstanceProcAddr = nullptr;
} XR;
};
static std::shared_ptr<VulkanInstance> Create(const CreateInfo& CI);

Expand All @@ -82,7 +89,8 @@ class VulkanInstance : public std::enable_shared_from_this<VulkanInstance>
bool IsExtensionAvailable(const char* ExtensionName)const;
bool IsExtensionEnabled (const char* ExtensionName)const;

VkPhysicalDevice SelectPhysicalDevice(uint32_t AdapterId)const;
VkPhysicalDevice SelectPhysicalDevice(uint32_t AdapterId)const noexcept(false);
VkPhysicalDevice SelectPhysicalDeviceForOpenXR(const CreateInfo::OpenXRInfo& XRInfo)const noexcept(false);

VkAllocationCallbacks* GetVkAllocator() const {return m_pVkAllocator;}
VkInstance GetVkInstance() const {return m_VkInstance; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 Diligent Graphics LLC
* Copyright 2019-2024 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -92,10 +92,15 @@ class VulkanLogicalDevice : public std::enable_shared_from_this<VulkanLogicalDev
public:
using ExtensionFeatures = VulkanPhysicalDevice::ExtensionFeatures;

static std::shared_ptr<VulkanLogicalDevice> Create(const VulkanPhysicalDevice& PhysicalDevice,
const VkDeviceCreateInfo& DeviceCI,
const ExtensionFeatures& EnabledExtFeatures,
const VkAllocationCallbacks* vkAllocator);
struct CreateInfo
{
const VulkanPhysicalDevice& PhysicalDevice;
const VkDevice vkDevice;
const VkPhysicalDeviceFeatures& EnabledFeatures;
const ExtensionFeatures& EnabledExtFeatures;
const VkAllocationCallbacks* const vkAllocator;
};
static std::shared_ptr<VulkanLogicalDevice> Create(const CreateInfo& CI);

// clang-format off
VulkanLogicalDevice (const VulkanLogicalDevice&) = delete;
Expand Down Expand Up @@ -243,10 +248,7 @@ class VulkanLogicalDevice : public std::enable_shared_from_this<VulkanLogicalDev
const ExtensionFeatures& GetEnabledExtFeatures() const { return m_EnabledExtFeatures; }

private:
VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice,
const VkDeviceCreateInfo& DeviceCI,
const ExtensionFeatures& EnabledExtFeatures,
const VkAllocationCallbacks* vkAllocator);
VulkanLogicalDevice(const CreateInfo& CI);

template <typename VkObjectType,
VulkanHandleTypeId VkTypeId,
Expand Down
94 changes: 90 additions & 4 deletions Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
# include "FileSystem.hpp"
#endif

#if DILIGENT_USE_OPENXR
# define XR_USE_GRAPHICS_API_VULKAN
# include <openxr/openxr_platform.h>
#endif

namespace Diligent
{
namespace
Expand Down Expand Up @@ -620,6 +625,43 @@ void EngineFactoryVkImpl::EnumerateAdapters(Version MinVersion,
}
}

#if DILIGENT_USE_OPENXR
VkResult CreateVulkanDeviceForOpenXR(const OpenXRAttribs& XRAttribs,
VkPhysicalDevice PhysicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDevice* pDevice) noexcept(false)
{
XrInstance xrInstance = XR_NULL_HANDLE;
static_assert(sizeof(XrInstance) == sizeof(XRAttribs.Instance), "XrInstance size mismatch");
memcpy(&xrInstance, &XRAttribs.Instance, sizeof(XrInstance));

PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr = reinterpret_cast<PFN_xrGetInstanceProcAddr>(XRAttribs.GetInstanceProcAddr);
PFN_xrCreateVulkanDeviceKHR xrCreateVulkanDeviceKHR = nullptr;
if (XR_FAILED(xrGetInstanceProcAddr(xrInstance, "xrCreateVulkanDeviceKHR", reinterpret_cast<PFN_xrVoidFunction*>(&xrCreateVulkanDeviceKHR))))
{
LOG_ERROR_AND_THROW("Failed to get xrCreateVulkanDeviceKHR function");
}
VERIFY_EXPR(xrCreateVulkanDeviceKHR != nullptr);

XrVulkanDeviceCreateInfoKHR VulkanDeviceCI{XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR};
static_assert(sizeof(VulkanDeviceCI.systemId) == sizeof(XRAttribs.SystemId), "systemId size mismatch");
memcpy(&VulkanDeviceCI.systemId, &XRAttribs.SystemId, sizeof(VulkanDeviceCI.systemId));
VulkanDeviceCI.createFlags = 0;
VulkanDeviceCI.pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
VulkanDeviceCI.vulkanPhysicalDevice = PhysicalDevice;
VulkanDeviceCI.vulkanCreateInfo = pCreateInfo;
VulkanDeviceCI.vulkanAllocator = pAllocator;

VkResult vkRes = VK_ERROR_UNKNOWN;
if (XR_FAILED(xrCreateVulkanDeviceKHR(xrInstance, &VulkanDeviceCI, pDevice, &vkRes)))
{
LOG_ERROR_AND_THROW("Failed to create Vulkan device for OpenXR");
}
return vkRes;
}
#endif

void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& EngineCI,
IRenderDevice** ppDevice,
IDeviceContext** ppContexts)
Expand Down Expand Up @@ -664,10 +706,34 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& En
InstanceCI.IgnoreDebugMessageCount = EngineCI.IgnoreDebugMessageCount;
InstanceCI.ppIgnoreDebugMessageNames = EngineCI.ppIgnoreDebugMessageNames;

#if DILIGENT_USE_OPENXR
if (EngineCI.pXRAttribs != nullptr && EngineCI.pXRAttribs->Instance != 0)
{
InstanceCI.XR.Instance = EngineCI.pXRAttribs->Instance;
InstanceCI.XR.SystemId = EngineCI.pXRAttribs->SystemId;
InstanceCI.XR.GetInstanceProcAddr = EngineCI.pXRAttribs->GetInstanceProcAddr;
}
#endif

auto Instance = VulkanUtilities::VulkanInstance::Create(InstanceCI);

auto vkDevice = Instance->SelectPhysicalDevice(EngineCI.AdapterId);
auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create({*Instance, vkDevice, /*LogExtensions = */ true});
VkPhysicalDevice vkPhysDevice = VK_NULL_HANDLE;
#if DILIGENT_USE_OPENXR
if (InstanceCI.XR.Instance != 0)
{
if (EngineCI.AdapterId != DEFAULT_ADAPTER_ID)
{
LOG_WARNING_MESSAGE("AdapterId is ignored when OpenXR is used as the physical device is selected by OpenXR runtime");
}
vkPhysDevice = Instance->SelectPhysicalDeviceForOpenXR(InstanceCI.XR);
}
else
#endif
{
vkPhysDevice = Instance->SelectPhysicalDevice(EngineCI.AdapterId);
}

auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create({*Instance, vkPhysDevice, /*LogExtensions = */ true});

std::vector<const char*> DeviceExtensions;
if (Instance->IsExtensionEnabled(VK_KHR_SURFACE_EXTENSION_NAME))
Expand Down Expand Up @@ -1199,8 +1265,28 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& En
vkDeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data();
vkDeviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());

auto vkAllocator = Instance->GetVkAllocator();
auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(*PhysicalDevice, vkDeviceCreateInfo, EnabledExtFeats, vkAllocator);
VkAllocationCallbacks* vkAllocator = Instance->GetVkAllocator();
VkDevice vkDevice = VK_NULL_HANDLE;
VkResult vkRes = VK_ERROR_UNKNOWN;
#if DILIGENT_USE_OPENXR
if (InstanceCI.XR.Instance != 0)
{
vkRes = CreateVulkanDeviceForOpenXR(*EngineCI.pXRAttribs, PhysicalDevice->GetVkDeviceHandle(), &vkDeviceCreateInfo, vkAllocator, &vkDevice);
}
else
#endif
{
vkRes = vkCreateDevice(PhysicalDevice->GetVkDeviceHandle(), &vkDeviceCreateInfo, vkAllocator, &vkDevice);
}
CHECK_VK_ERROR_AND_THROW(vkRes, "Failed to create logical device");

auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create({
*PhysicalDevice,
vkDevice,
*vkDeviceCreateInfo.pEnabledFeatures,
EnabledExtFeats,
vkAllocator,
});

auto& RawMemAllocator = GetRawAllocator();

Expand Down
Loading

0 comments on commit ffa20fd

Please sign in to comment.