From 546548dc449be8ee5bc5e5fee4b7b9058d45db89 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sat, 7 Dec 2024 16:28:02 -0800 Subject: [PATCH] Vulkan: enabled OpenXR support through XR_KHR_vulkan_enable2 --- .github/workflows/build-windows.yml | 2 +- .../GraphicsEngine/interface/GraphicsTypes.h | 19 +++ Graphics/GraphicsEngineVulkan/CMakeLists.txt | 7 + .../VulkanUtilities/VulkanInstance.hpp | 12 +- .../VulkanUtilities/VulkanLogicalDevice.hpp | 20 +-- .../src/EngineFactoryVk.cpp | 94 ++++++++++- .../src/VulkanUtilities/VulkanInstance.cpp | 148 +++++++++++++++++- .../VulkanUtilities/VulkanLogicalDevice.cpp | 32 ++-- ThirdParty/CMakeLists.txt | 4 + ThirdParty/OpenXR-SDK/CMakeLists.txt | 14 ++ 10 files changed, 312 insertions(+), 40 deletions(-) create mode 100644 ThirdParty/OpenXR-SDK/CMakeLists.txt diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index e1dc82a66..57c218717 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -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: diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 3fb21da3a..1600f8a20 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -3408,6 +3408,21 @@ struct ImmediateContextCreateInfo typedef struct ImmediateContextCreateInfo ImmediateContextCreateInfo; +/// 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; + + /// Engine creation information struct EngineCreateInfo { @@ -3504,6 +3519,10 @@ struct EngineCreateInfo // The structure must be 8-byte aligned Uint32 Padding DEFAULT_INITIALIZER(0); + /// An optional pointer to the OpenXR attributes, must be set if OpenXR is used. + /// See Diligent::OpenXRAttribs. + const OpenXRAttribs *pXRAttribs DEFAULT_INITIALIZER(nullptr); + #if DILIGENT_CPP_INTERFACE EngineCreateInfo() noexcept { diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt index 9d45358ba..225e3ed26 100644 --- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt +++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt @@ -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 @@ -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} diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp index dd5040f2b..451eb94bd 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp @@ -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"); @@ -62,6 +62,13 @@ class VulkanInstance : public std::enable_shared_from_this 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 Create(const CreateInfo& CI); @@ -82,7 +89,8 @@ class VulkanInstance : public std::enable_shared_from_this 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; } diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp index 945612f16..c530007fc 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp @@ -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"); @@ -92,10 +92,15 @@ class VulkanLogicalDevice : public std::enable_shared_from_this 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 Create(const CreateInfo& CI); // clang-format off VulkanLogicalDevice (const VulkanLogicalDevice&) = delete; @@ -243,10 +248,7 @@ class VulkanLogicalDevice : public std::enable_shared_from_this +#endif + namespace Diligent { namespace @@ -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(XRAttribs.GetInstanceProcAddr); + PFN_xrCreateVulkanDeviceKHR xrCreateVulkanDeviceKHR = nullptr; + if (XR_FAILED(xrGetInstanceProcAddr(xrInstance, "xrCreateVulkanDeviceKHR", reinterpret_cast(&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) @@ -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 DeviceExtensions; if (Instance->IsExtensionEnabled(VK_KHR_SURFACE_EXTENSION_NAME)) @@ -1199,8 +1265,28 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& En vkDeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data(); vkDeviceCreateInfo.enabledExtensionCount = static_cast(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(); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp index 92fe33d47..071de873d 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp @@ -45,6 +45,11 @@ # include "GLSLangUtils.hpp" #endif +#if DILIGENT_USE_OPENXR +# define XR_USE_GRAPHICS_API_VULKAN +# include +#endif + #include "PlatformDefinitions.h" namespace VulkanUtilities @@ -164,6 +169,79 @@ bool VulkanInstance::IsExtensionEnabled(const char* ExtensionName) const return false; } +#if DILIGENT_USE_OPENXR +static uint32_t GetRequiredOpenXRVulkanVersion(uint32_t VulkanVersion, + XrInstance xrInstance, + XrSystemId xrSystemId, + PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr) noexcept(false) +{ + PFN_xrGetVulkanGraphicsRequirements2KHR xrGetVulkanGraphicsRequirements2KHR = nullptr; + if (XR_SUCCEEDED(xrGetInstanceProcAddr(xrInstance, "xrGetVulkanGraphicsRequirements2KHR", reinterpret_cast(&xrGetVulkanGraphicsRequirements2KHR)))) + { + VERIFY_EXPR(xrGetVulkanGraphicsRequirements2KHR != nullptr); + + XrGraphicsRequirementsVulkan2KHR xrVulkan2Req{XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR}; + if (XR_SUCCEEDED(xrGetVulkanGraphicsRequirements2KHR(xrInstance, xrSystemId, &xrVulkan2Req))) + { + auto XrVersionToVkVersion = [](XrVersion XrVersion) { + return VK_MAKE_API_VERSION(0, XR_VERSION_MAJOR(XrVersion), XR_VERSION_MINOR(XrVersion), 0); + }; + + uint32_t MinVkVersion = XrVersionToVkVersion(xrVulkan2Req.minApiVersionSupported); + if (VulkanVersion < MinVkVersion) + { + LOG_ERROR_AND_THROW("OpenXR requires Vulkan version ", VK_API_VERSION_MAJOR(MinVkVersion), '.', VK_API_VERSION_MINOR(MinVkVersion), + ", but this device only supports Vulkan ", VK_API_VERSION_MAJOR(VulkanVersion), '.', VK_API_VERSION_MINOR(VulkanVersion)); + } + uint32_t MaxVkVersion = VK_MAKE_API_VERSION(0, XR_VERSION_MAJOR(xrVulkan2Req.maxApiVersionSupported), XR_VERSION_MINOR(xrVulkan2Req.maxApiVersionSupported), 0); + if (MaxVkVersion < VulkanVersion) + { + LOG_INFO_MESSAGE("This device supports Vulkan ", VK_API_VERSION_MAJOR(VulkanVersion), '.', VK_API_VERSION_MINOR(VulkanVersion), + ", but OpenXR was only tested with Vulkan up to ", VK_API_VERSION_MAJOR(MaxVkVersion), '.', VK_API_VERSION_MINOR(MaxVkVersion), + ". Proceeding with Vulkan ", VK_API_VERSION_MAJOR(MaxVkVersion), '.', VK_API_VERSION_MINOR(MaxVkVersion), '.'); + VulkanVersion = MaxVkVersion; + } + } + else + { + LOG_WARNING_MESSAGE("Failed to get Vulkan requirements from OpenXR. Proceeding without checking Vulkan instance version requirements."); + } + } + + return VulkanVersion; +} + +static VkResult CreateVkInstanceForOpenXR(XrInstance xrInstance, + XrSystemId xrSystemId, + PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr, + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* vkAllocator, + VkInstance* pInstance) +{ + PFN_xrCreateVulkanInstanceKHR xrCreateVulkanInstanceKHR = nullptr; + if (XR_FAILED(xrGetInstanceProcAddr(xrInstance, "xrCreateVulkanInstanceKHR", reinterpret_cast(&xrCreateVulkanInstanceKHR)))) + { + LOG_ERROR_AND_THROW("Failed to get xrCreateVulkanInstanceKHR function"); + } + VERIFY_EXPR(xrCreateVulkanInstanceKHR != nullptr); + + XrVulkanInstanceCreateInfoKHR xrVkInstanceCreateInfo{XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR}; + xrVkInstanceCreateInfo.systemId = xrSystemId; + xrVkInstanceCreateInfo.createFlags = 0; + xrVkInstanceCreateInfo.pfnGetInstanceProcAddr = vkGetInstanceProcAddr; + xrVkInstanceCreateInfo.vulkanCreateInfo = pCreateInfo; + xrVkInstanceCreateInfo.vulkanAllocator = vkAllocator; + + VkResult vkRes = VK_ERROR_UNKNOWN; + if (XR_FAILED(xrCreateVulkanInstanceKHR(xrInstance, &xrVkInstanceCreateInfo, pInstance, &vkRes))) + { + LOG_ERROR_AND_THROW("Failed to create Vulkan instance using OpenXR"); + } + + return vkRes; +} +#endif + std::shared_ptr VulkanInstance::Create(const CreateInfo& CI) { auto Instance = new VulkanInstance{CI}; @@ -294,7 +372,7 @@ VulkanInstance::VulkanInstance(const CreateInfo& CI) : ". Please initialize 'ppInstanceExtensionNames' member of EngineVkCreateInfo struct."); } - auto ApiVersion = CI.ApiVersion; + uint32_t ApiVersion = CI.ApiVersion; #if DILIGENT_USE_VOLK if (vkEnumerateInstanceVersion != nullptr && ApiVersion > VK_API_VERSION_1_0) { @@ -312,6 +390,27 @@ VulkanInstance::VulkanInstance(const CreateInfo& CI) : ApiVersion = VK_API_VERSION_1_0; #endif +#if DILIGENT_USE_OPENXR + XrInstance xrInstance = XR_NULL_HANDLE; + XrSystemId xrSystemId = XR_NULL_SYSTEM_ID; + PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr = nullptr; + if (CI.XR.Instance != 0) + { + if (CI.XR.GetInstanceProcAddr == nullptr) + LOG_ERROR_AND_THROW("xrGetInstanceProcAddr must not be null"); + + static_assert(sizeof(XrInstance) == sizeof(CI.XR.Instance), "XrInstance size mismatch"); + memcpy(&xrInstance, &CI.XR.Instance, sizeof(XrInstance)); + static_assert(sizeof(XrSystemId) == sizeof(CI.XR.SystemId), "XrSystemId size mismatch"); + memcpy(&xrSystemId, &CI.XR.SystemId, sizeof(XrSystemId)); + xrGetInstanceProcAddr = reinterpret_cast(CI.XR.GetInstanceProcAddr); + } + if (xrInstance != 0) + { + ApiVersion = GetRequiredOpenXRVulkanVersion(ApiVersion, xrInstance, xrSystemId, xrGetInstanceProcAddr); + } +#endif + std::vector InstanceLayers; // Use VK_DEVSIM_FILENAME environment variable to define the simulation layer @@ -430,7 +529,17 @@ VulkanInstance::VulkanInstance(const CreateInfo& CI) : InstanceCreateInfo.enabledLayerCount = static_cast(InstanceLayers.size()); InstanceCreateInfo.ppEnabledLayerNames = InstanceLayers.empty() ? nullptr : InstanceLayers.data(); - auto res = vkCreateInstance(&InstanceCreateInfo, m_pVkAllocator, &m_VkInstance); + VkResult res = VK_ERROR_UNKNOWN; +#if DILIGENT_USE_OPENXR + if (xrInstance != XR_NULL_HANDLE) + { + res = CreateVkInstanceForOpenXR(xrInstance, xrSystemId, xrGetInstanceProcAddr, &InstanceCreateInfo, m_pVkAllocator, &m_VkInstance); + } + else +#endif + { + res = vkCreateInstance(&InstanceCreateInfo, m_pVkAllocator, &m_VkInstance); + } CHECK_VK_ERROR_AND_THROW(res, "Failed to create Vulkan instance"); #if DILIGENT_USE_VOLK @@ -497,7 +606,7 @@ VulkanInstance::~VulkanInstance() #endif } -VkPhysicalDevice VulkanInstance::SelectPhysicalDevice(uint32_t AdapterId) const +VkPhysicalDevice VulkanInstance::SelectPhysicalDevice(uint32_t AdapterId) const noexcept(false) { const auto IsGraphicsAndComputeQueueSupported = [](VkPhysicalDevice Device) { uint32_t QueueFamilyCount = 0; @@ -563,10 +672,41 @@ VkPhysicalDevice VulkanInstance::SelectPhysicalDevice(uint32_t AdapterId) const } else { - LOG_ERROR_MESSAGE("Failed to find suitable physical device"); + LOG_ERROR_AND_THROW("Failed to find suitable physical device"); } return SelectedPhysicalDevice; } +VkPhysicalDevice VulkanInstance::SelectPhysicalDeviceForOpenXR(const CreateInfo::OpenXRInfo& XRInfo) const noexcept(false) +{ +#if DILIGENT_USE_OPENXR + XrInstance xrInstance = XR_NULL_HANDLE; + static_assert(sizeof(XrInstance) == sizeof(XRInfo.Instance), "XrInstance size mismatch"); + memcpy(&xrInstance, &XRInfo.Instance, sizeof(XrInstance)); + + XrVulkanGraphicsDeviceGetInfoKHR vkGraphicsDeviceGetInfo{XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR}; + static_assert(sizeof(vkGraphicsDeviceGetInfo.systemId) == sizeof(XRInfo.SystemId), "SystemId Size mismatch"); + memcpy(&vkGraphicsDeviceGetInfo.systemId, &XRInfo.SystemId, sizeof(vkGraphicsDeviceGetInfo.systemId)); + vkGraphicsDeviceGetInfo.vulkanInstance = m_VkInstance; + + PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr = reinterpret_cast(XRInfo.GetInstanceProcAddr); + PFN_xrGetVulkanGraphicsDevice2KHR xrGetVulkanGraphicsDevice2KHR = nullptr; + if (XR_FAILED(xrGetInstanceProcAddr(xrInstance, "xrGetVulkanGraphicsDevice2KHR", reinterpret_cast(&xrGetVulkanGraphicsDevice2KHR)))) + { + LOG_ERROR_AND_THROW("Failed to get xrGetVulkanGraphicsDevice2KHR function"); + } + + VkPhysicalDevice vkDevice = VK_NULL_HANDLE; + if (XR_FAILED(xrGetVulkanGraphicsDevice2KHR(xrInstance, &vkGraphicsDeviceGetInfo, &vkDevice))) + { + LOG_ERROR_AND_THROW("Failed to get Vulkan physical device for OpenXR"); + } + + return vkDevice; +#else + LOG_ERROR_AND_THROW("OpenXR is not supported. Use DILIGENT_USE_OPENXR CMake option to enable it."); +#endif +} + } // namespace VulkanUtilities diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp index 3e12fd1eb..5af23de4e 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 Diligent Graphics LLC + * Copyright 2019-2024 Diligent Graphics LLC * Copyright 2015-2019 Egor Yusov * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,12 +34,9 @@ namespace VulkanUtilities { -std::shared_ptr VulkanLogicalDevice::Create(const VulkanPhysicalDevice& PhysicalDevice, - const VkDeviceCreateInfo& DeviceCI, - const ExtensionFeatures& EnabledExtFeatures, - const VkAllocationCallbacks* vkAllocator) +std::shared_ptr VulkanLogicalDevice::Create(const CreateInfo& CI) { - auto* LogicalDevice = new VulkanLogicalDevice{PhysicalDevice, DeviceCI, EnabledExtFeatures, vkAllocator}; + auto* LogicalDevice = new VulkanLogicalDevice{CI}; return std::shared_ptr{LogicalDevice}; } @@ -48,17 +45,12 @@ VulkanLogicalDevice::~VulkanLogicalDevice() vkDestroyDevice(m_VkDevice, m_VkAllocator); } -VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice, - const VkDeviceCreateInfo& DeviceCI, - const ExtensionFeatures& EnabledExtFeatures, - const VkAllocationCallbacks* vkAllocator) : - m_VkAllocator{vkAllocator}, - m_EnabledFeatures{*DeviceCI.pEnabledFeatures}, - m_EnabledExtFeatures{EnabledExtFeatures} +VulkanLogicalDevice::VulkanLogicalDevice(const CreateInfo& CI) : + m_VkDevice{CI.vkDevice}, + m_VkAllocator{CI.vkAllocator}, + m_EnabledFeatures{CI.EnabledFeatures}, + m_EnabledExtFeatures{CI.EnabledExtFeatures} { - auto res = vkCreateDevice(PhysicalDevice.GetVkDeviceHandle(), &DeviceCI, vkAllocator, &m_VkDevice); - CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device"); - #if DILIGENT_USE_VOLK // Since we only use one device at this time, load device function entries // https://github.com/zeux/volk#optimizing-device-calls @@ -96,9 +88,9 @@ VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDe VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT; - if (DeviceCI.pEnabledFeatures->geometryShader) + if (m_EnabledFeatures.geometryShader) GraphicsStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; - if (DeviceCI.pEnabledFeatures->tessellationShader) + if (m_EnabledFeatures.tessellationShader) GraphicsStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT; if (m_EnabledExtFeatures.MeshShader.meshShader != VK_FALSE && m_EnabledExtFeatures.MeshShader.taskShader != VK_FALSE) GraphicsStages |= VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT | VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT; @@ -118,12 +110,12 @@ VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDe GraphicsAccessMask |= VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT; } - const auto QueueCount = PhysicalDevice.GetQueueProperties().size(); + const auto QueueCount = CI.PhysicalDevice.GetQueueProperties().size(); m_SupportedStagesMask.resize(QueueCount, 0); m_SupportedAccessMask.resize(QueueCount, 0); for (size_t q = 0; q < QueueCount; ++q) { - const auto& Queue = PhysicalDevice.GetQueueProperties()[q]; + const auto& Queue = CI.PhysicalDevice.GetQueueProperties()[q]; auto& StageMask = m_SupportedStagesMask[q]; auto& AccessMask = m_SupportedAccessMask[q]; diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt index f78c4163b..1a560564d 100644 --- a/ThirdParty/CMakeLists.txt +++ b/ThirdParty/CMakeLists.txt @@ -171,6 +171,10 @@ if (WEBGPU_SUPPORTED) set_directory_root_folder("dawn" "DiligentCore/ThirdParty/dawn") endif() +if(DILIGENT_USE_OPENXR) + add_subdirectory(OpenXR-SDK EXCLUDE_FROM_ALL) +endif() + if ((${DILIGENT_BUILD_GOOGLE_TEST}) AND (NOT TARGET gtest)) set(INSTALL_GTEST OFF CACHE BOOL "Do not install googletest") set(BUILD_GMOCK OFF CACHE BOOL "Do not build gmock") diff --git a/ThirdParty/OpenXR-SDK/CMakeLists.txt b/ThirdParty/OpenXR-SDK/CMakeLists.txt new file mode 100644 index 000000000..39ef1e8d1 --- /dev/null +++ b/ThirdParty/OpenXR-SDK/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required (VERSION 3.11) + +include(FetchContent) + +# openxr_loader - From github.com/KhronosGroup +set(BUILD_TESTS OFF) +set(BUILD_API_LAYERS ON) +FetchContent_Declare( + OpenXR + URL_HASH MD5=924a94a2da0b5ef8e82154c623d88644 + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + URL https://github.com/KhronosGroup/OpenXR-SDK-Source/archive/refs/tags/release-1.0.34.zip +) +FetchContent_MakeAvailable(OpenXR)