소스 검색

Initial plumbing for XR and OpenXRVk gem (#2)

* Initial plumbing for XR and OpenXRVk gem
- Added support to initialize XR gem and register OPenxrvk gem with it
- XR::Factory support to create appropriate backend specific objects
- Implementation for RPI::XRRenderingInterface that currently allows RPI to init XR instance
- Implementation for RHI::XRRenderingInterface that allows RHI to create native instance, physical device and device
- Added support to load vulkan function pointers via glad
- Added validation mode support to allow for better logging/validation
- Commented out dead code which can be pulled in later if needed or removed entirely
- Various other misc changes

Signed-off-by: moudgils <[email protected]>

* Minor fixup of spacing

Signed-off-by: moudgils <[email protected]>

* Fixup spacing + comments

Signed-off-by: moudgils <[email protected]>

* Added support to activate XR gem before RPI gem
Addressed PR feedback

Signed-off-by: moudgils <[email protected]>
moudgils 3 년 전
부모
커밋
6cb98644ec
32개의 변경된 파일988개의 추가작업 그리고 540개의 파일을 삭제
  1. 1 1
      Gems/OpenXRVk/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake
  2. 2 2
      Gems/OpenXRVk/Code/CMakeLists.txt
  3. 15 20
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkDevice.h
  4. 0 62
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkFactory.h
  5. 38 0
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkFunctionLoader.h
  6. 3 0
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkGraphicsBinding.h
  7. 3 0
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkInput.h
  8. 60 24
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkInstance.h
  9. 5 30
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkPhysicalDevice.h
  10. 3 0
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkSession.h
  11. 3 0
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkSwapChain.h
  12. 0 111
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkSystem.h
  13. 45 0
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkSystemComponent.h
  14. 53 1
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkUtils.h
  15. 32 0
      Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXrVkGladFunctionLoader.h
  16. 64 4
      Gems/OpenXRVk/Code/Source/OpenXRVkDevice.cpp
  17. 0 72
      Gems/OpenXRVk/Code/Source/OpenXRVkFactory.cpp
  18. 59 0
      Gems/OpenXRVk/Code/Source/OpenXRVkFunctionLoader.cpp
  19. 44 0
      Gems/OpenXRVk/Code/Source/OpenXRVkGladFunctionLoader.cpp
  20. 3 0
      Gems/OpenXRVk/Code/Source/OpenXRVkInput.cpp
  21. 381 7
      Gems/OpenXRVk/Code/Source/OpenXRVkInstance.cpp
  22. 25 18
      Gems/OpenXRVk/Code/Source/OpenXRVkModule.cpp
  23. 19 3
      Gems/OpenXRVk/Code/Source/OpenXRVkPhysicalDevice.cpp
  24. 6 4
      Gems/OpenXRVk/Code/Source/OpenXRVkSession.cpp
  25. 4 2
      Gems/OpenXRVk/Code/Source/OpenXRVkSwapChain.cpp
  26. 0 173
      Gems/OpenXRVk/Code/Source/OpenXRVkSystem.cpp
  27. 58 0
      Gems/OpenXRVk/Code/Source/OpenXRVkSystemComponent.cpp
  28. 43 2
      Gems/OpenXRVk/Code/Source/OpenXRVkUtils.cpp
  29. 2 0
      Gems/OpenXRVk/Code/Source/Platform/Android/OpenXRVk_Traits_Android.h
  30. 2 0
      Gems/OpenXRVk/Code/Source/Platform/Linux/OpenXRVk_Traits_Linux.h
  31. 2 0
      Gems/OpenXRVk/Code/Source/Platform/Windows/OpenXRVk_Traits_Windows.h
  32. 13 4
      Gems/OpenXRVk/Code/openxrvk_private_common_files.cmake

+ 1 - 1
Gems/OpenXRVk/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake

@@ -9,4 +9,4 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #
 
-ly_associate_package(PACKAGE_NAME OpenXR-1.0.22-rev1-linux  TARGETS OpenXR  PACKAGE_HASH 919237b00b79faf11120d6e866773598a77b12fbcf7ccae4b8967d57e6f0719f)
+ly_associate_package(PACKAGE_NAME OpenXR-1.0.22-rev2-linux  TARGETS OpenXR  PACKAGE_HASH 7d9045de0078a3f4a88bea2e3167e2c159acc8c62ac40ae15f8a31902b8d1f08)

+ 2 - 2
Gems/OpenXRVk/Code/CMakeLists.txt

@@ -58,8 +58,8 @@ ly_add_target(
             3rdParty::OpenXR
             3rdParty::glad_vulkan
             AZ::AtomCore
-            Gem::Atom_RPI.Public
-            Gem::XR
+	    Gem::Atom_RHI_Vulkan.Reflect
+            Gem::XR.Static
 )
 
 ly_add_target(

+ 15 - 20
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkDevice.h

@@ -8,38 +8,33 @@
 
 #pragma once
 
-
-
 #include <XR/XRDevice.h>
 #include <OpenXRVk_Platform.h>
 
 namespace OpenXRVk
 {
-    class DeviceDescriptor final
-        : public XR::DeviceDescriptor
-    {
-    public:
-        AZ_CLASS_ALLOCATOR(DeviceDescriptor, AZ::SystemAllocator, 0);
-        AZ_RTTI(DeviceDescriptor, "{B0DB4670-A233-4F3F-A5C7-5D2B76F6D911}", XR::DeviceDescriptor);
-
-        DeviceDescriptor() = default;
-        virtual ~DeviceDescriptor() = default;
-
-        //any extra info for a generic xr device
-    };
-
-    // Class that will help manage VkDevice
+    //! Vulkan specific XR device back-end class that will help manage 
+    //! xr specific vulkan native objects related to device.
     class Device final
-        : public XR::Device
+    : public XR::Device
     {
     public:
         AZ_CLASS_ALLOCATOR(Device, AZ::SystemAllocator, 0);
         AZ_RTTI(Device, "{81FD9B99-EDA5-4381-90EC-335073554379}", XR::Device);
 
-        static AZStd::intrusive_ptr<Device> Create();
-        AZ::RHI::ResultCode InitDeviceInternal() override;
+        static XR::Ptr<Device> Create();
+
+        //////////////////////////////////////////////////////////////////////////
+        // XR::Device overrides
+        // Create the xr specific native device object and populate the XRDeviceDescriptor with it.
+        AZ::RHI::ResultCode InitDeviceInternal(AZ::RHI::XRDeviceDescriptor* instanceDescriptor) override;
+        //////////////////////////////////////////////////////////////////////////
 
     private:
-        VkDevice m_nativeDevice;
+
+        //! Clean native objects.
+        void ShutdownInternal() override;
+
+        VkDevice m_xrVkDevice = VK_NULL_HANDLE;
     };
 }

+ 0 - 62
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkFactory.h

@@ -1,62 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#pragma once
-
-#include <XR/XRFactory.h>
-
-#include <OpenXRVk_Platform.h>
-#include <OpenXRVk/OpenXRVkDevice.h>
-#include <OpenXRVk/OpenXRVkInstance.h>
-#include <OpenXRVk/OpenXRVkPhysicalDevice.h>
-#include <OpenXRVk/OpenXRVkSession.h>
-#include <OpenXRVk/OpenXRVkInput.h>
-#include <OpenXRVk/OpenXRVkSwapChain.h>
-#include <OpenXRVk/OpenXRVkGraphicsBinding.h>
-
-namespace OpenXRVk
-{
-    //! Interface responsible for creating all the XR objects which are
-    //! internally backed by concrete objects
-    class Factory final
-        : public XR::Factory
-    {
-    public:
-        AZ_CLASS_ALLOCATOR(Factory, AZ::SystemAllocator, 0);
-        AZ_RTTI(Factory, "{11C46EF4-2AB5-47F7-B4F6-D30DDD53F1D8}", XR::Factory);
-
-        Factory();
-        ~Factory();
-
-        // Create XR::Instance object
-        AZStd::intrusive_ptr<XR::Instance> CreateInstance() override;
-
-        // Create XR::Device object
-        AZStd::intrusive_ptr<XR::Device> CreateDevice() override;
-
-        // Return a list of XR::PhysicalDevice
-        AZStd::vector<AZStd::intrusive_ptr<XR::PhysicalDevice>> EnumerateDeviceList() override;
-
-        // Create XR::Session object
-        AZStd::intrusive_ptr<XR::Session> CreateSession() override;
-
-        // Create XR::Input object
-        AZStd::intrusive_ptr<XR::Input> CreateInput() override;
-
-        // Create XR::SwapChain object
-        AZStd::intrusive_ptr<XR::SwapChain> CreateSwapchain() override;
-
-        // Create XR::ViewSwapChain object
-        AZStd::intrusive_ptr<XR::SwapChain::View> CreateViewSwapchain() override;
-
-        // Create RPI::XR::GraphicsBindingDescriptor that will contain
-        // renderer information needed to start a session
-        AZStd::intrusive_ptr<XR::GraphicsBindingDescriptor> CreateGraphicsBindingDescriptor() override;
-
-    };
-}

+ 38 - 0
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkFunctionLoader.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Memory/SystemAllocator.h>
+#include <AzCore/std/smart_ptr/unique_ptr.h>
+#include <AzCore/Module/DynamicModuleHandle.h>
+
+namespace OpenXRVk
+{
+    class FunctionLoader
+    {
+    public:
+        AZ_CLASS_ALLOCATOR(FunctionLoader, AZ::SystemAllocator, 0);
+
+        static AZStd::unique_ptr<FunctionLoader> Create();
+
+        //! Load vulkan specific dlls.
+        bool Init();
+
+        //! Unload the dlls.
+        void Shutdown();
+
+        virtual ~FunctionLoader();
+    protected:
+
+        virtual bool InitInternal() = 0;
+        virtual void ShutdownInternal() = 0;
+
+        AZStd::unique_ptr<AZ::DynamicModuleHandle> m_moduleHandle;
+    };
+}

+ 3 - 0
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkGraphicsBinding.h

@@ -13,6 +13,8 @@
 
 namespace OpenXRVk
 {
+    //todo:: Pull this in if needed or remove
+    /*
     class GraphicsBindingDescriptor final
         : public XR::GraphicsBindingDescriptor
     {
@@ -31,4 +33,5 @@ namespace OpenXRVk
         AZ_RTTI(GraphicsBinding, "{1001E681-EA2E-4898-AC08-B93AA5B63508}", XR::GraphicsBinding);
 
     };
+    */
 }

+ 3 - 0
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkInput.h

@@ -13,6 +13,8 @@
 
 namespace OpenXRVk
 {
+    //Todo: Pull this in when needed or remove
+    /*
     class InputDescriptor final
         : public XR::InputDescriptor
     {
@@ -60,4 +62,5 @@ namespace OpenXRVk
         };
         InputState m_input;
     };
+    */
 }

+ 60 - 24
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkInstance.h

@@ -8,46 +8,82 @@
 
 #pragma once
 
-#include <XR/XRInstance.h>
 #include <AzCore/std/containers/vector.h>
-#include <AzCore/std/smart_ptr/intrusive_ptr.h>
+#include <Atom/RHI/ValidationLayer.h>
 #include <OpenXRVk_Platform.h>
+#include <OpenXRVk/OpenXRVkFunctionLoader.h>
+#include <OpenXRVk/OpenXRVkPhysicalDevice.h>
+#include <XR/XRInstance.h>
 
 namespace OpenXRVk
 {
-    class InstanceDescriptor final
-        : public XR::InstanceDescriptor
-    {
-    public:
-        AZ_CLASS_ALLOCATOR(InstanceDescriptor, AZ::SystemAllocator, 0);
-        AZ_RTTI(InstanceDescriptor, "{F7D29A7A-5841-4B6F-ADFE-3734316BC63D}", XR::InstanceDescriptor);
-
-        InstanceDescriptor() = default;
-        virtual ~InstanceDescriptor() = default;
-
-        //any extra info a openxr instance descriptor needs
-    };
-
-    // Class that will help manage XrInstance
+    //! Vulkan specific XR instance back-end class that will help manage 
+    //! XR specific vulkan native objects
     class Instance final
-        : public XR::Instance
+    : public XR::Instance
     {
     public:
         AZ_CLASS_ALLOCATOR(Instance, AZ::SystemAllocator, 0);
         AZ_RTTI(Instance, "{1A62DF32-2909-431C-A938-B1E841A50768}", XR::Instance);
 
         Instance() = default;
-        virtual ~Instance() = default;
+        ~Instance() = default;
+
+        static XR::Ptr<Instance> Create();
+
+        //////////////////////////////////////////////////////////////////////////
+        // XR::Instance overrides
+        AZ::RHI::ResultCode InitInstanceInternal(AZ::RHI::ValidationMode m_validationMode) override;
+        AZ::RHI::ResultCode InitNativeInstance(AZ::RHI::XRInstanceDescriptor* instanceDescriptor) override;
+        AZ::u32 GetNumPhysicalDevices() override;
+        AZ::RHI::ResultCode GetXRPhysicalDevice(AZ::RHI::XRPhysicalDeviceDescriptor* physicalDeviceDescriptor, int32_t index) override;
+        //////////////////////////////////////////////////////////////////////////
+		
+        //! Enumerate supported extension names.
+        XR::StringList GetInstanceExtensionNames(const char* layerName = nullptr) const;
+		
+        //! Enumerate supported layer names.
+        XR::StringList GetInstanceLayerNames() const;
 
-        static AZStd::intrusive_ptr<Instance> Create();
-        virtual AZ::RHI::ResultCode InitInstanceInternal() override;
+        //! Enumerate and log view configurations.
+        void LogViewConfigurations();
+
+        //! Enumerate and log environment blend mode.
+        void LogEnvironmentBlendMode(XrViewConfigurationType type);
+
+        //! Get the XRInstance.
+        XrInstance GetXRInstance();
+
+        //! Get System id.
+        XrSystemId GetXRSystemId();
+
+        //! Get native VkInstance.
+        VkInstance GetVkInstance();
+
+        //! Get XR environment blend mode.
+        XrEnvironmentBlendMode GetEnvironmentBlendMode();
+
+        //! Get XR configuration type.
+        XrViewConfigurationType GetViewConfigType();
+
+        //! Ge the active VkPhysicalDevice.
+        VkPhysicalDevice GetActivePhysicalDevice();
 
     private:
+
+        //! Clean native objects. 
+        void ShutdownInternal() override;
+
         XrInstance m_xrInstance{ XR_NULL_HANDLE };
-        AZStd::vector<XrApiLayerProperties> m_layers;
-        AZStd::vector<XrExtensionProperties> m_extensions;
+        VkInstance m_xrVkInstance = VK_NULL_HANDLE;
         XrFormFactor m_formFactor{ XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY };
-        XrSystemId m_systemId{ XR_NULL_SYSTEM_ID };
-        VkInstance m_instance = VK_NULL_HANDLE;
+        XrViewConfigurationType m_viewConfigType{ XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO };
+        XrEnvironmentBlendMode m_environmentBlendMode{ XR_ENVIRONMENT_BLEND_MODE_OPAQUE };
+        XrSystemId m_xrSystemId{ XR_NULL_SYSTEM_ID };
+        XR::RawStringList m_requiredLayers;
+        XR::RawStringList m_requiredExtensions;
+        AZStd::unique_ptr<FunctionLoader> m_functionLoader;
+        AZStd::vector<VkPhysicalDevice> m_supportedXRDevices;
+        AZ::u32 m_physicalDeviceActiveIndex = 0;
     };
 }

+ 5 - 30
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkPhysicalDevice.h

@@ -8,37 +8,12 @@
 
 #pragma once
 
-#include <XR/XRPhysicalDevice.h>
+#include <AzCore/std/containers/vector.h>
 #include <OpenXRVk_Platform.h>
 
-namespace OpenXRVk
+namespace OpenXRVk::PhysicalDevice
 {
-    class PhysicalDeviceDescriptor final
-        : public XR::PhysicalDeviceDescriptor
-    {
-    public:
-        AZ_CLASS_ALLOCATOR(PhysicalDeviceDescriptor, AZ::SystemAllocator, 0);
-        AZ_RTTI(PhysicalDeviceDescriptor, "{CB485C38-E723-4593-ADCF-DFE220A6A24B}", XR::PhysicalDeviceDescriptor);
-
-        PhysicalDeviceDescriptor() = default;
-        virtual ~PhysicalDeviceDescriptor() = default;
-
-        // Other data related to openxr physical device
-    };
-
-    // This class will be responsible for iterating over all the compatible physical
-    // devices and picking one that will be used for the app
-    class PhysicalDevice final
-        : public XR::PhysicalDevice
-    {
-    public:
-        AZ_CLASS_ALLOCATOR(PhysicalDevice, AZ::SystemAllocator, 0);
-        AZ_RTTI(PhysicalDevice, "{7CE8D7C1-7CC6-4841-9505-DED2761617AC}", XR::PhysicalDevice);
-
-        PhysicalDevice() = default;
-        virtual ~PhysicalDevice() = default;
-
-        static AZStd::vector<AZStd::intrusive_ptr<XR::PhysicalDevice>> EnumerateDeviceList();
-    };
-} // namespace XR
+    //! API to enumerate and return physical devices.
+    static AZStd::vector<VkPhysicalDevice> EnumerateDeviceList(XrSystemId xrSystemId, XrInstance xrInstance, VkInstance vkInstance); 
+}
 

+ 3 - 0
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkSession.h

@@ -14,6 +14,8 @@
 
 namespace OpenXRVk
 {
+    //Todo: Pull this in when needed or remove
+    /*
     class SessionDescriptor final
         : public XR::SessionDescriptor 
     {
@@ -53,4 +55,5 @@ namespace OpenXRVk
         XrSessionState m_sessionState{ XR_SESSION_STATE_UNKNOWN };
         XrFrameState m_frameState{ XR_TYPE_FRAME_STATE };
     };
+    */
 }

+ 3 - 0
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkSwapChain.h

@@ -13,6 +13,8 @@
 
 namespace OpenXRVk
 {
+    //Pull this in if needed or remove
+    /*
     class SwapChainDescriptor final
         : public XR::SwapChainDescriptor
     {
@@ -90,4 +92,5 @@ namespace OpenXRVk
         AZStd::vector<XrView> m_views;
         int64_t m_colorSwapchainFormat{ -1 };
     };
+    */
 }

+ 0 - 111
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkSystem.h

@@ -1,111 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#pragma once
-
-#include <AzCore/Component/TickBus.h>
-
-#include <XR/XRSystem.h>
-
-#include <OpenXRVk_Platform.h>
-
-#include <OpenXRVk/OpenXRVkInstance.h>
-#include <OpenXRVk/OpenXRVkDevice.h>
-#include <OpenXRVk/OpenXRVkSwapChain.h>
-#include <OpenXRVk/OpenXRVkInput.h>
-#include <OpenXRVk/OpenXRVkSession.h>
-#include <OpenXRVk/OpenXRVkGraphicsBinding.h>
-
-namespace OpenXRVk
-{
-    class System final
-        : public XR::System
-        , public AZ::SystemTickBus::Handler
-    {
-    public:
-        AZ_CLASS_ALLOCATOR(System, AZ::SystemAllocator, 0);
-        AZ_RTTI(System, "{FBAFDEE2-0A03-4EA8-98E9-A1C8DB32DBCF}", XR::System);
-
-        ///////////////////////////////////////////////////////////////////////////////////
-        // SystemInterface
-        // Accessor functions for RHI objects that are populated by backend XR gems
-        // This will allow XR gem to provide device related data to RHI
-        // Initialize XR instance and device
-        AZ::RHI::ResultCode InitializeSystem() override;
-
-        // Initialize a XR session
-        AZ::RHI::ResultCode InitializeSession() override;
-
-        // Indicate start of a frame
-        void BeginFrame() override;
-
-        // Indicate end of a frame
-        void EndFrame() override;
-
-        // Indicate start of a XR view to help with synchronizing XR swap chain
-        void BeginView() override;
-
-        // Indicate end of a XR view to help with synchronizing XR swap chain
-        void EndView() override;
-
-        // Manage session lifecycle to track if RenderFrame should be called.
-        bool IsSessionRunning() const override;
-
-        // Create a swap chain which will responsible for managing
-        // multiple XR swap chains and multiple swap chain images within it
-        AZ::RHI::ResultCode CreateSwapchain() override;
-
-        AZ::RPI::XRDeviceDescriptor* GetDeviceDescriptor() override;
-
-        // Provide access to instance specific data to RHI
-        AZ::RPI::XRInstanceDescriptor* GetInstanceDescriptor() override;
-
-        // Provide Swap chain specific data to RHI
-        AZ::RPI::XRSwapChainImageDescriptor* GetSwapChainImageDescriptor(AZ::u16 swapchainIndex) override;
-
-        // Provide access to Graphics Binding specific data that RHI can populate
-        AZ::RPI::XRGraphicsBindingDescriptor* GetGraphicsBindingDescriptor() override;
-        ///////////////////////////////////////////////////////////////////////////////////
-
-    public:
-        // Access supported Layers and extension names
-        const AZStd::vector<AZStd::string>& GetLayerNames();
-
-        const AZStd::vector<AZStd::string>& GetExtensionNames();
-
-        // Create XR instance object and initialize it
-        AZ::RHI::ResultCode InitInstance();
-
-        // Create XR device object and initialize it
-        AZ::RHI::ResultCode InitDevice();
-
-    private:
-
-        ///////////////////////////////////////////////////////////////////////////////////
-        // SystemTickBus
-        // System Tick to poll input data
-        void OnSystemTick() override;
-        //////////////////////////////////////////////////////////////////////////////////
-
-        AZStd::vector<AZStd::string> m_layerNames;
-        AZStd::vector<AZStd::string> m_extentionNames;
-
-        AZStd::intrusive_ptr<OpenXRVk::Instance> m_instance;
-        AZStd::intrusive_ptr<OpenXRVk::Device> m_device;
-        AZStd::intrusive_ptr<OpenXRVk::Session> m_session;
-        AZStd::intrusive_ptr<OpenXRVk::Input> m_input;
-        AZStd::intrusive_ptr<OpenXRVk::SwapChain> m_swapChain;
-        bool m_requestRestart = false;
-        bool m_exitRenderLoop = false;
-        AZStd::intrusive_ptr<OpenXRVk::DeviceDescriptor> m_deviceDesc;
-        AZStd::intrusive_ptr<OpenXRVk::InstanceDescriptor> m_instanceDesc;
-        AZStd::vector<AZStd::intrusive_ptr<OpenXRVk::SwapChainDescriptor>> m_swapchainDesc;
-        AZStd::vector<AZStd::intrusive_ptr<OpenXRVk::SwapChainImageDescriptor>> m_swapchainImageDesc;
-        AZStd::intrusive_ptr<OpenXRVk::GraphicsBindingDescriptor> m_graphicsBindingDesc;
-    };
-}

+ 45 - 0
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkSystemComponent.h

@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <XR/XRFactory.h>
+#include <AzCore/Component/Component.h>
+
+namespace OpenXRVk
+{
+    //! This class is the component related to the vulkan backend of XR.
+    class SystemComponent final
+    : public AZ::Component
+    , public XR::Factory
+    {
+    public:
+        AZ_COMPONENT(SystemComponent, "{C0ABD1CE-FD3C-48C3-8AE8-C098BCCFC604}");
+
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
+        static void Reflect(AZ::ReflectContext* context);
+
+        SystemComponent();
+        ~SystemComponent();
+
+        //////////////////////////////////////////////////////////////////////////
+        // Component
+        void Activate() override;
+        void Deactivate() override;
+        //////////////////////////////////////////////////////////////////////////
+
+        ///////////////////////////////////////////////////////////////////
+        // XR::Factory overrides
+        // Create OpenXRVk::Instance object
+        virtual XR::Ptr<XR::Instance> CreateInstance();
+
+        // Create OpenXRVk::Device object
+        virtual XR::Ptr<XR::Device> CreateDevice();
+        ///////////////////////////////////////////////////////////////////
+    };
+}

+ 53 - 1
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXRVkUtils.h

@@ -9,11 +9,63 @@
 #pragma once
 
 #include <Atom/RHI.Reflect/Base.h>
-
 #include <OpenXRVk_Platform.h>
+#include <XR/XRBase.h>
+
+// Macro to generate stringify functions for OpenXR enumerations based data provided in openxr_reflection.h
+#define ENUM_CASE_STR(name, val) case name: return #name;
+#define MAKE_XR_TO_STRING_FUNC(enumType)                  \
+    inline const char* to_string(enumType e) {         \
+        switch (e) {                                   \
+            XR_LIST_ENUM_##enumType(ENUM_CASE_STR)     \
+            default: return "Unknown " #enumType;      \
+        }                                              \
+    }
+
+
+MAKE_XR_TO_STRING_FUNC(XrReferenceSpaceType);
+MAKE_XR_TO_STRING_FUNC(XrViewConfigurationType);
+MAKE_XR_TO_STRING_FUNC(XrEnvironmentBlendMode);
+MAKE_XR_TO_STRING_FUNC(XrSessionState);
+MAKE_XR_TO_STRING_FUNC(XrResult);
+MAKE_XR_TO_STRING_FUNC(XrFormFactor);
 
 namespace OpenXRVk
 {
+
+#define RETURN_XR_RESULT_IF_UNSUCCESSFUL(result) \
+    if (result != XR_SUCCESS) {\
+        return result;\
+    }
+
+#define RETURN_IF_UNSUCCESSFUL(result) \
+    if (result != XR_SUCCESS) {\
+        return;\
+    }
+
+#define RETURN_RESULTCODE_IF_UNSUCCESSFUL(result) \
+    if (result != AZ::RHI::ResultCode::SUCCESS) {\
+        return result;\
+    }
+    
+#define WARN_IF_UNSUCCESSFUL(result) \
+    if (result != XR_SUCCESS) {\
+        AZ_Warning("OpenXrVk", false, "Warning error code: %s", to_string(result));\
+    }
+
+#define ASSERT_IF_UNSUCCESSFUL(result) \
+    if (result != XR_SUCCESS) {\
+        AZ_Assert(false, "Assert error code: %s", to_string(result));\
+    }
+
     AZ::RHI::ResultCode ConvertResult(XrResult xrResult);
     bool IsSuccess(XrResult result);
+    bool IsError(XrResult result);
+    const char* GetResultString(const XrResult result);
+    XR::RawStringList FilterList(const XR::RawStringList& source, const XR::StringList& filter);
+
+    //! Input is an array of chars with multiple ' ' char embedded in it, indicating the start of a new string. 
+    //! Iterate through the characters while caching the starting pointer to a string 
+    //! and every time ' ' is encountered replace it with '\0' to indicate the end of a string.
+    AZStd::vector<const char*> ParseExtensionString(char* names);
 }

+ 32 - 0
Gems/OpenXRVk/Code/Include/OpenXRVk/OpenXrVkGladFunctionLoader.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+#include <OpenXRVk/OpenXRVkFunctionLoader.h>
+#include <AzCore/Memory/SystemAllocator.h>
+
+namespace OpenXRVk
+{
+    class GladFunctionLoader:
+        public FunctionLoader
+    {
+    public:
+        AZ_CLASS_ALLOCATOR(GladFunctionLoader, AZ::SystemAllocator, 0);
+
+        GladFunctionLoader() = default;
+        virtual ~GladFunctionLoader() = default;
+
+    private:
+        //////////////////////////////////////////////////////////////////////////
+        // FunctionLoader overrrides
+        //! Load the the function pointers from the vulkan dll.
+        bool InitInternal() override;
+        //! Unload appropriate data.
+        void ShutdownInternal() override;
+    };
+}

+ 64 - 4
Gems/OpenXRVk/Code/Source/OpenXRVkDevice.cpp

@@ -7,18 +7,78 @@
  */
 
 #include <OpenXRVk/OpenXRVkDevice.h>
+#include <OpenXRVk/OpenXRVkInstance.h>
+#include <OpenXRVk/OpenXRVkUtils.h>
+#include <Atom/RHI.Reflect/Vulkan/XRVkDescriptors.h>
+#include <AzCore/Casting/numeric_cast.h>
 
 namespace OpenXRVk
 {
-    AZStd::intrusive_ptr<Device> Device::Create()
+    XR::Ptr<Device> Device::Create()
     {
         return aznew Device;
     }
 
-    AZ::RHI::ResultCode Device::InitDeviceInternal()
+    AZ::RHI::ResultCode Device::InitDeviceInternal(AZ::RHI::XRDeviceDescriptor* deviceDescriptor)
     {
-        // Create Vulkan Device
-        //m_nativeDevice = Create();
+        AZ::Vulkan::XRDeviceDescriptor* xrDeviceDescriptor = static_cast<AZ::Vulkan::XRDeviceDescriptor*>(deviceDescriptor);
+        Instance* xrVkInstance = static_cast<Instance*>(GetInstance().get());
+        XrVulkanDeviceCreateInfoKHR xrDeviceCreateInfo{ XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR };
+        xrDeviceCreateInfo.systemId = xrVkInstance->GetXRSystemId();
+        xrDeviceCreateInfo.pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
+        xrDeviceCreateInfo.vulkanCreateInfo = xrDeviceDescriptor->m_inputData.m_deviceCreateInfo;
+        xrDeviceCreateInfo.vulkanPhysicalDevice = xrVkInstance->GetActivePhysicalDevice();
+        xrDeviceCreateInfo.vulkanAllocator = nullptr;
+
+        PFN_xrGetVulkanDeviceExtensionsKHR pfnGetVulkanDeviceExtensionsKHR = nullptr;
+        XrResult result = xrGetInstanceProcAddr(
+            xrVkInstance->GetXRInstance(), "xrGetVulkanDeviceExtensionsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanDeviceExtensionsKHR));
+        ASSERT_IF_UNSUCCESSFUL(result);
+
+        AZ::u32 deviceExtensionNamesSize = 0;
+        result = pfnGetVulkanDeviceExtensionsKHR(xrVkInstance->GetXRInstance(), xrDeviceCreateInfo.systemId, 0, &deviceExtensionNamesSize, nullptr);
+        ASSERT_IF_UNSUCCESSFUL(result);
+
+        AZStd::vector<char> deviceExtensionNames(deviceExtensionNamesSize);
+        result = pfnGetVulkanDeviceExtensionsKHR(
+	        xrVkInstance->GetXRInstance(), xrDeviceCreateInfo.systemId, deviceExtensionNamesSize, &deviceExtensionNamesSize, &deviceExtensionNames[0]);
+        ASSERT_IF_UNSUCCESSFUL(result);
+
+        AZStd::vector<const char*> extensions = ParseExtensionString(&deviceExtensionNames[0]);
+        for (uint32_t i = 0; i < xrDeviceCreateInfo.vulkanCreateInfo->enabledExtensionCount; ++i)
+        {
+            extensions.push_back(xrDeviceCreateInfo.vulkanCreateInfo->ppEnabledExtensionNames[i]);
+        }
+
+        VkPhysicalDeviceFeatures features{};
+        memcpy(&features, xrDeviceCreateInfo.vulkanCreateInfo->pEnabledFeatures, sizeof(features));
+
+        VkDeviceCreateInfo deviceInfo{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
+        memcpy(&deviceInfo, xrDeviceCreateInfo.vulkanCreateInfo, sizeof(deviceInfo));
+        deviceInfo.pEnabledFeatures = &features;
+        deviceInfo.enabledExtensionCount = aznumeric_cast<AZ::u32>(extensions.size());
+        deviceInfo.ppEnabledExtensionNames = extensions.empty() ? nullptr : extensions.data();
+
+        //Create VkDevice
+        auto pfnCreateDevice = (PFN_vkCreateDevice)xrDeviceCreateInfo.pfnGetInstanceProcAddr(xrVkInstance->GetVkInstance(), "vkCreateDevice");
+        VkResult vulkanResult = pfnCreateDevice(xrDeviceCreateInfo.vulkanPhysicalDevice, &deviceInfo, xrDeviceCreateInfo.vulkanAllocator, &m_xrVkDevice);
+        if (vulkanResult != VK_SUCCESS)
+        {
+            return AZ::RHI::ResultCode::Fail;
+        }
+		
+        //Populate the output data of the descriptor
+        xrDeviceDescriptor->m_outputData.m_xrVkDevice = m_xrVkDevice;
+
         return AZ::RHI::ResultCode::Success;
     }
+
+    void Device::ShutdownInternal()
+    {
+        if (m_xrVkDevice != VK_NULL_HANDLE)
+        {
+            vkDestroyDevice(m_xrVkDevice, nullptr);
+            m_xrVkDevice = VK_NULL_HANDLE;
+        }
+    }
 }

+ 0 - 72
Gems/OpenXRVk/Code/Source/OpenXRVkFactory.cpp

@@ -1,72 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#include <OpenXRVk/OpenXRVkFactory.h>
-#include <AzCore/Memory/Memory.h>
-
-namespace OpenXRVk
-{
-    Factory::Factory()
-    {
-        XR::Factory::Register(this);
-    }
-
-    Factory::~Factory()
-    {
-        XR::Factory::Unregister(this);
-    }
-
-    // Create XR::Instance object
-    AZStd::intrusive_ptr<XR::Instance> CreateInstance()
-    {
-        return aznew Instance;
-    }
-
-    // Create XR::Device object
-    AZStd::intrusive_ptr<XR::Device> CreateDevice()
-    {
-        return aznew Device;
-    }
-
-    // Return a list of XR::PhysicalDevice
-    AZStd::vector<AZStd::intrusive_ptr<XR::PhysicalDevice>> EnumerateDeviceList()
-    {
-        return PhysicalDevice::EnumerateDeviceList();
-    }
-
-    // Create XR::Session object
-    AZStd::intrusive_ptr<XR::Session> CreateSession()
-    {
-        return aznew Session;
-    }
-
-    // Create XR::Input object
-    AZStd::intrusive_ptr<XR::Input> CreateInput()
-    {
-        return aznew Input;
-    }
-
-    // Create XR::SwapChain object
-    AZStd::intrusive_ptr<XR::SwapChain> CreateSwapchain()
-    {
-        return aznew SwapChain;
-    }
-
-    // Create XR::ViewSwapChain object
-    AZStd::intrusive_ptr<XR::SwapChain::View> CreateViewSwapchain()
-    {
-        return aznew SwapChain::View;
-    }
-
-    // Create RPI::XR::GraphicsBindingDescriptor that will contain
-    // renderer information needed to start a session
-    AZStd::intrusive_ptr<XR::GraphicsBindingDescriptor> CreateGraphicsBindingDescriptor()
-    {
-        return aznew GraphicsBindingDescriptor;
-    }
-}

+ 59 - 0
Gems/OpenXRVk/Code/Source/OpenXRVkFunctionLoader.cpp

@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <AzCore/std/containers/vector.h>
+#include <OpenXRVk/OpenXRVkFunctionLoader.h>
+#include <OpenXRVk_Platform.h>
+#include <OpenXRVk_Traits_Platform.h>
+
+namespace OpenXRVk
+{
+    FunctionLoader::~FunctionLoader()
+    {
+        AZ_Assert(!m_moduleHandle, "Shutdown was not called before destroying this FunctionLoader");
+    }
+
+    bool FunctionLoader::Init()
+    {
+        const AZStd::vector<const char*> libs = {
+            VULKAN_DLL,
+            VULKAN_1_DLL
+        };
+
+        for (const char* libName : libs)
+        {
+            m_moduleHandle = AZ::DynamicModuleHandle::Create(libName);
+            if (m_moduleHandle->Load(false))
+            {
+                break;
+            }
+            else
+            {
+                m_moduleHandle = nullptr;
+            }
+        }
+
+        if (!m_moduleHandle)
+        {
+            AZ_Warning("Vulkan", false, "Could not find Vulkan library.");
+            return false;
+        }
+            
+        return InitInternal();
+    }
+
+    void FunctionLoader::Shutdown()
+    {
+        ShutdownInternal();
+        if (m_moduleHandle)
+        {
+            m_moduleHandle->Unload();
+        }
+        m_moduleHandle = nullptr;
+    }
+}

+ 44 - 0
Gems/OpenXRVk/Code/Source/OpenXRVkGladFunctionLoader.cpp

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <AzCore/PlatformIncl.h>
+#define GLAD_VULKAN_IMPLEMENTATION
+#include <OpenXRVk_Platform.h>
+
+#include <OpenXRVk/OpenXRVkGladFunctionLoader.h>
+#include <AzCore/Module/DynamicModuleHandle.h>
+
+namespace
+{
+    GLADapiproc LoadFunctionFromLibrary(void* userPtr, const char *name)
+    {
+        AZ::DynamicModuleHandle* moduleHandle = reinterpret_cast<AZ::DynamicModuleHandle*>(userPtr);
+        AZ_Assert(moduleHandle, "Invalid module handle");
+        return moduleHandle->GetFunction<GLADapiproc>(name);
+    }
+}
+
+namespace OpenXRVk
+{
+    AZStd::unique_ptr<FunctionLoader> FunctionLoader::Create()
+    {
+        return AZStd::make_unique<GladFunctionLoader>();
+    }
+
+    bool GladFunctionLoader::InitInternal()
+    {
+        // Since que don't have the vulkan instance or device yet, we just load the function pointers from the loader
+        // using dlsym or similar.
+        return gladLoadVulkanUserPtr(VK_NULL_HANDLE, &LoadFunctionFromLibrary, m_moduleHandle.get()) != 0;
+    }
+
+    void GladFunctionLoader::ShutdownInternal()
+    {
+        gladLoaderUnloadVulkan();
+    }
+}

+ 3 - 0
Gems/OpenXRVk/Code/Source/OpenXRVkInput.cpp

@@ -10,6 +10,8 @@
 
 namespace OpenXRVk
 {
+    //Todo: Pull this in when needed or remove
+    /*
     AZStd::intrusive_ptr<XR::Input> Input::Create()
     {
         return nullptr;
@@ -48,4 +50,5 @@ namespace OpenXRVk
     {
         // m_session->HandleSessionStateChangedEvent
     }
+    */
 }

+ 381 - 7
Gems/OpenXRVk/Code/Source/OpenXRVkInstance.cpp

@@ -7,20 +7,394 @@
  */
 
 #include <OpenXRVk/OpenXRVkInstance.h>
+#include <OpenXRVk/OpenXRVkUtils.h>
+#include <Atom/RHI.Reflect/Vulkan/XRVkDescriptors.h>
+#include <AzCore/Casting/numeric_cast.h>
 
 namespace OpenXRVk
 {
     AZStd::intrusive_ptr<Instance> Instance::Create()
     {
-        return nullptr;
+        return aznew Instance;
     }
 
-    AZ::RHI::ResultCode Instance::InitInstanceInternal()
+    XR::StringList Instance::GetInstanceExtensionNames(const char* layerName /*= nullptr*/) const
     {
-        AZ::RHI::ResultCode res = XR::Instance::InitInstanceInternal();
-        // xrCreateInstance(m_xrInstance)
-        // xrGetSystem(m_systemId)
-        // vkCreateInstance(m_instance)
-        return res;
+        XR::StringList extensionNames;
+        AZ::u32 extPropertyCount = 0;
+        XrResult result = xrEnumerateInstanceExtensionProperties(layerName, 0, &extPropertyCount, nullptr);
+        if (IsError(result) || extPropertyCount == 0)
+        {
+            return extensionNames;
+        }
+
+        AZStd::vector<XrExtensionProperties> extProperties;
+        extProperties.resize(extPropertyCount);
+
+        for (XrExtensionProperties& extension : extProperties)
+        {
+            extension.type = XR_TYPE_EXTENSION_PROPERTIES;
+        }
+
+        result = xrEnumerateInstanceExtensionProperties(layerName, aznumeric_cast<AZ::u32>(extProperties.size()), &extPropertyCount, extProperties.data());
+        if (IsError(result))
+        {
+            return extensionNames;
+        }
+
+        extensionNames.reserve(extensionNames.size() + extProperties.size());
+        for (uint32_t extPropertyIndex = 0; extPropertyIndex < extPropertyCount; extPropertyIndex++)
+        {
+            extensionNames.emplace_back(extProperties[extPropertyIndex].extensionName);
+        }
+
+        return extensionNames;
+    }
+
+    XR::StringList Instance::GetInstanceLayerNames() const
+    {
+        XR::StringList layerNames;
+        AZ::u32 layerPropertyCount = 0;
+        XrResult result = xrEnumerateApiLayerProperties(0, &layerPropertyCount, nullptr);
+        if (IsError(result) || layerPropertyCount == 0)
+        {
+            return layerNames;
+        }
+
+        AZStd::vector<XrApiLayerProperties> layerProperties(layerPropertyCount);
+        for (XrApiLayerProperties& layer : layerProperties)
+        {
+            layer.type = XR_TYPE_API_LAYER_PROPERTIES;
+        }
+
+        result = xrEnumerateApiLayerProperties(aznumeric_cast<AZ::u32>(layerProperties.size()), &layerPropertyCount, layerProperties.data());
+        if (IsError(result))
+        {
+            return layerNames;
+        }
+
+        layerNames.reserve(layerNames.size() + layerProperties.size());
+        for (uint32_t layerPropertyIndex = 0; layerPropertyIndex < layerPropertyCount; ++layerPropertyIndex)
+        {
+            layerNames.emplace_back(layerProperties[layerPropertyIndex].layerName);
+        }
+
+        return layerNames;
+    }
+
+    AZ::RHI::ResultCode Instance::InitInstanceInternal(AZ::RHI::ValidationMode validationMode)
+    {
+        XR::RawStringList optionalLayers = XR::RawStringList{};
+        XR::RawStringList optionalExtensions = XR::RawStringList{ { XR_KHR_VULKAN_ENABLE_EXTENSION_NAME } };
+
+        XR::StringList instanceLayerNames = GetInstanceLayerNames();
+        XR::RawStringList supportedLayers = FilterList(optionalLayers, instanceLayerNames);
+        m_requiredLayers.insert(m_requiredLayers.end(), supportedLayers.begin(), supportedLayers.end());
+
+        XR::StringList instanceExtensions = GetInstanceExtensionNames();
+        XR::RawStringList supportedExtensions = FilterList(optionalExtensions, instanceExtensions);
+        m_requiredExtensions.insert(m_requiredExtensions.end(), supportedExtensions.begin(), supportedExtensions.end());
+
+        if (validationMode == AZ::RHI::ValidationMode::Enabled)
+        {
+            AZ_Printf("OpenXrVk", "Available Extensions: (%i)\n", instanceExtensions.size());
+            for (const AZStd::string& extension : instanceExtensions)
+            {
+                AZ_Printf("OpenXrVk", "Name=%s\n", extension.c_str());
+            }
+
+            AZ_Printf("OpenXrVk", "Available Layers: (%i)\n", instanceLayerNames.size());
+            for (const AZStd::string& layerName : instanceLayerNames)
+            {
+                AZ_Printf("OpenXrVk", "Name=%s \n", layerName.c_str());
+            }
+        }
+
+        AZ_Assert(m_xrInstance == XR_NULL_HANDLE, "XR Instance is already initialized");
+        XrInstanceCreateInfo createInfo{ XR_TYPE_INSTANCE_CREATE_INFO };
+        createInfo.next = nullptr;
+        createInfo.enabledExtensionCount = aznumeric_cast<AZ::u32>(supportedExtensions.size());
+        createInfo.enabledExtensionNames = supportedExtensions.data();
+        createInfo.enabledApiLayerCount = aznumeric_cast<AZ::u32>(supportedLayers.size());
+        createInfo.enabledApiLayerNames = supportedLayers.data();
+
+        azstrncpy(createInfo.applicationInfo.applicationName, XR_MAX_APPLICATION_NAME_SIZE, "O3deApp", 4);
+        createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
+
+        //Create XR instance
+        XrResult result = xrCreateInstance(&createInfo, &m_xrInstance);
+        if(IsError(result))
+        {
+            AZ_Warning("OpenXrVk", false, "Failed to create XR instance");
+            return AZ::RHI::ResultCode::Fail;
+        }
+
+        if (validationMode == AZ::RHI::ValidationMode::Enabled)
+        {
+            XrInstanceProperties instanceProperties{ XR_TYPE_INSTANCE_PROPERTIES };
+            result = xrGetInstanceProperties(m_xrInstance, &instanceProperties);
+            if (IsSuccess(result))
+            {
+                AZStd::string verStr = AZStd::string::format("%d.%d.%d",
+                XR_VERSION_MAJOR(instanceProperties.runtimeVersion),
+                XR_VERSION_MINOR(instanceProperties.runtimeVersion),
+                XR_VERSION_PATCH(instanceProperties.runtimeVersion));
+                AZ_Printf("OpenXrVk", "Instance RuntimeName=%s RuntimeVersion=%s\n", instanceProperties.runtimeName, verStr.c_str());
+            }
+        }
+
+        AZ_Assert(m_xrInstance != XR_NULL_HANDLE, "XR Isntance is Null");
+        AZ_Assert(m_xrSystemId == XR_NULL_SYSTEM_ID, "XR System id already initialized");
+
+        //TODO::Add support for handheld display
+        m_formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
+
+        //TODO::Add support for other view configuration types
+        m_viewConfigType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
+
+        //TODO::Add support for other environment blend types
+        m_environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
+
+        XrSystemGetInfo systemInfo{ XR_TYPE_SYSTEM_GET_INFO };
+        systemInfo.formFactor = m_formFactor;
+        result = xrGetSystem(m_xrInstance, &systemInfo, &m_xrSystemId);
+        if (IsError(result))
+        {
+            AZ_Warning("OpenXrVk", false, "Failed to get XR System id");
+            return AZ::RHI::ResultCode::Fail;
+        }
+
+        // Query the runtime Vulkan API version requirements
+        XrGraphicsRequirementsVulkan2KHR graphicsRequirements{ XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR };
+        PFN_xrGetVulkanGraphicsRequirementsKHR pfnGetVulkanGraphicsRequirementsKHR = nullptr;
+        result = xrGetInstanceProcAddr(m_xrInstance, "xrGetVulkanGraphicsRequirementsKHR",
+                                       reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanGraphicsRequirementsKHR));
+        WARN_IF_UNSUCCESSFUL(result);
+
+        XrGraphicsRequirementsVulkanKHR legacyRequirements{ XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR };
+        result = pfnGetVulkanGraphicsRequirementsKHR(m_xrInstance, m_xrSystemId, &legacyRequirements);
+        WARN_IF_UNSUCCESSFUL(result);
+        graphicsRequirements.maxApiVersionSupported = legacyRequirements.maxApiVersionSupported;
+        graphicsRequirements.minApiVersionSupported = legacyRequirements.minApiVersionSupported;
+
+        if (validationMode == AZ::RHI::ValidationMode::Enabled)
+        {
+            AZ_Printf("OpenXrVk", "graphicsRequirements.maxApiVersionSupported %d.%d.%d\n",
+            XR_VERSION_MAJOR(graphicsRequirements.maxApiVersionSupported),
+            XR_VERSION_MINOR(graphicsRequirements.maxApiVersionSupported),
+            XR_VERSION_PATCH(graphicsRequirements.maxApiVersionSupported));
+
+            AZ_Printf("OpenXrVk", "graphicsRequirements.minApiVersionSupported %d.%d.%d\n",
+            XR_VERSION_MAJOR(graphicsRequirements.minApiVersionSupported),
+            XR_VERSION_MINOR(graphicsRequirements.minApiVersionSupported),
+            XR_VERSION_PATCH(graphicsRequirements.minApiVersionSupported));
+
+            AZ_Printf("OpenXrVk", "Using system %d for form factor %s\n", m_xrSystemId, to_string(m_formFactor));
+            LogViewConfigurations();
+        }
+		
+        return AZ::RHI::ResultCode::Success;
+    }
+
+    void Instance::LogViewConfigurations()
+    {
+        AZ::u32 viewConfigTypeCount = 0;
+        XrResult result = xrEnumerateViewConfigurations(m_xrInstance, m_xrSystemId, 0, &viewConfigTypeCount, nullptr);
+        RETURN_IF_UNSUCCESSFUL(result);
+
+        AZStd::vector<XrViewConfigurationType> viewConfigTypes(viewConfigTypeCount);
+        result = xrEnumerateViewConfigurations(m_xrInstance, m_xrSystemId, viewConfigTypeCount, &viewConfigTypeCount, viewConfigTypes.data());
+        RETURN_IF_UNSUCCESSFUL(result);
+
+        AZ_Warning("OpenXrVk", aznumeric_cast<AZ::u32>(viewConfigTypes.size()) == viewConfigTypeCount, "Size Mismatch");
+
+        AZ_Printf("OpenXrVk", "Available View Configuration Types: (%d)\n", viewConfigTypeCount);
+        for (XrViewConfigurationType viewConfigType : viewConfigTypes)
+        {
+            AZ_Printf("OpenXrVk", "View Configuration Type: %s %s\n", to_string(viewConfigType),
+            viewConfigType == m_viewConfigType ? "(Selected)" : "");
+
+            XrViewConfigurationProperties viewConfigProperties{ XR_TYPE_VIEW_CONFIGURATION_PROPERTIES };
+            result = xrGetViewConfigurationProperties(m_xrInstance, m_xrSystemId, viewConfigType, &viewConfigProperties);
+            RETURN_IF_UNSUCCESSFUL(result);
+
+            AZ_Printf("OpenXrVk", "View configuration FovMutable=%s\n", viewConfigProperties.fovMutable == XR_TRUE ? "True" : "False");
+
+            AZ::u32 viewCount = 0;
+            result = xrEnumerateViewConfigurationViews(m_xrInstance, m_xrSystemId, viewConfigType, 0, &viewCount, nullptr);
+            RETURN_IF_UNSUCCESSFUL(result);
+            if (viewCount > 0)
+            {
+                AZStd::vector<XrViewConfigurationView> views(viewCount);
+                for (XrViewConfigurationView& view : views)
+                {
+                    view.type = XR_TYPE_VIEW_CONFIGURATION_VIEW;
+                }
+                result = xrEnumerateViewConfigurationViews(m_xrInstance, m_xrSystemId, viewConfigType, viewCount, &viewCount, views.data());
+                RETURN_IF_UNSUCCESSFUL(result);
+
+                for (uint32_t i = 0; i < views.size(); i++)
+                {
+                    const XrViewConfigurationView& view = views[i];
+                    AZ_Printf(
+                        "OpenXrVk", "View [%d]: Recommended Width=%d Height=%d SampleCount=%d\n", i, view.recommendedImageRectWidth,
+                        view.recommendedImageRectHeight, view.recommendedSwapchainSampleCount);
+                    AZ_Printf(
+                        "OpenXrVk", "View [%d]:     Maximum Width=%d Height=%d SampleCount=%d\n", i, view.maxImageRectWidth,
+                        view.maxImageRectHeight, view.maxSwapchainSampleCount);
+                }
+            }
+            else
+            {
+                AZ_Printf("OpenXrVk", "Empty view configuration type\n");
+            }
+
+            LogEnvironmentBlendMode(viewConfigType);
+        }
+    }
+
+    void Instance::LogEnvironmentBlendMode(XrViewConfigurationType type)
+    {
+        AZ::u32 count = 0;
+        XrResult result = xrEnumerateEnvironmentBlendModes(m_xrInstance, m_xrSystemId, type, 0, &count, nullptr);
+        AZ_Warning("OpenXrVk", count > 0, "BlendModes not supported");
+        RETURN_IF_UNSUCCESSFUL(result);
+
+        AZ_Printf("OpenXrVk", "Available Environment Blend Mode count : (%d)\n", count);
+
+        AZStd::vector<XrEnvironmentBlendMode> blendModes(count);
+        result = xrEnumerateEnvironmentBlendModes(m_xrInstance, m_xrSystemId, type, count, &count, blendModes.data());
+        RETURN_IF_UNSUCCESSFUL(result);
+
+        bool blendModeFound = false;
+        for (XrEnvironmentBlendMode mode : blendModes)
+        {
+            const bool blendModeMatch = (mode == m_environmentBlendMode);
+            AZ_Printf("OpenXrVk", "Environment Blend Mode (%s) : %s\n", to_string(mode), blendModeMatch ? "(Selected)" : "");
+            blendModeFound |= blendModeMatch;
+        }
+    }
+
+    AZ::RHI::ResultCode Instance::InitNativeInstance(AZ::RHI::XRInstanceDescriptor* instanceDescriptor)
+    {
+        m_functionLoader = FunctionLoader::Create();
+        if (!m_functionLoader->Init())
+        {
+            AZ_Warning("Vulkan", false, "OpenXRVk Could not initialized function loader.");
+            return AZ::RHI::ResultCode::Fail;
+        }
+
+        AZ::Vulkan::XRInstanceDescriptor* xrInstanceDescriptor = static_cast<AZ::Vulkan::XRInstanceDescriptor*>(instanceDescriptor);
+        XrVulkanInstanceCreateInfoKHR createInfo{ XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR };
+        createInfo.systemId = m_xrSystemId;
+        createInfo.pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
+        createInfo.vulkanCreateInfo = xrInstanceDescriptor->m_inputData.m_createInfo;
+        createInfo.vulkanAllocator = nullptr;
+
+        PFN_xrGetVulkanInstanceExtensionsKHR pfnGetVulkanInstanceExtensionsKHR = nullptr;
+        XrResult result = xrGetInstanceProcAddr(m_xrInstance, "xrGetVulkanInstanceExtensionsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanInstanceExtensionsKHR));
+        ASSERT_IF_UNSUCCESSFUL(result);
+
+        AZ::u32 extensionNamesSize = 0;
+        result = pfnGetVulkanInstanceExtensionsKHR(m_xrInstance, m_xrSystemId, 0, &extensionNamesSize, nullptr);
+        ASSERT_IF_UNSUCCESSFUL(result);
+
+        AZStd::vector<char> extensionNames(extensionNamesSize);
+        result = pfnGetVulkanInstanceExtensionsKHR(m_xrInstance, m_xrSystemId, extensionNamesSize, &extensionNamesSize, &extensionNames[0]);
+        ASSERT_IF_UNSUCCESSFUL(result);
+		
+        AZStd::vector<const char*> extensions = ParseExtensionString(&extensionNames[0]);
+        for (uint32_t i = 0; i < createInfo.vulkanCreateInfo->enabledExtensionCount; ++i)
+        {
+            extensions.push_back(createInfo.vulkanCreateInfo->ppEnabledExtensionNames[i]);
+        }
+
+        VkInstanceCreateInfo instInfo{ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
+        memcpy(&instInfo, createInfo.vulkanCreateInfo, sizeof(instInfo));
+        instInfo.enabledExtensionCount = aznumeric_cast<AZ::u32>(extensions.size());
+        instInfo.ppEnabledExtensionNames = extensions.empty() ? nullptr : extensions.data();
+
+        auto pfnCreateInstance = (PFN_vkCreateInstance)createInfo.pfnGetInstanceProcAddr(nullptr, "vkCreateInstance");
+        VkResult vkResult = pfnCreateInstance(&instInfo, nullptr, &m_xrVkInstance);
+        if (vkResult != VK_SUCCESS)
+        {
+            return AZ::RHI::ResultCode::Fail;
+        }
+		
+        //Populate the instance descriptor with the correct VkInstance
+        xrInstanceDescriptor->m_outputData.m_xrVkInstance = m_xrVkInstance;
+
+        //Get the list of Physical devices
+        m_supportedXRDevices = PhysicalDevice::EnumerateDeviceList(m_xrSystemId, m_xrInstance, m_xrVkInstance);
+        if (m_supportedXRDevices.size() > 1)
+        {
+            //Just use the first device at the moment.
+            m_physicalDeviceActiveIndex = 0;
+        }
+        return AZ::RHI::ResultCode::Success;
+    }
+
+    void Instance::ShutdownInternal()
+    {
+        if (m_xrVkInstance != VK_NULL_HANDLE)
+        {
+            m_supportedXRDevices.clear();
+
+            vkDestroyInstance(m_xrVkInstance, nullptr);
+            m_functionLoader = VK_NULL_HANDLE;
+        }
+
+        if (m_functionLoader)
+        {
+            m_functionLoader->Shutdown();
+        }
+        m_functionLoader = nullptr;
+    }
+
+    AZ::RHI::ResultCode Instance::GetXRPhysicalDevice(AZ::RHI::XRPhysicalDeviceDescriptor* physicalDeviceDescriptor, int32_t index)
+    {
+        AZ::Vulkan::XRPhysicalDeviceDescriptor* xrPhysicalDeviceDescriptor = static_cast<AZ::Vulkan::XRPhysicalDeviceDescriptor*>(physicalDeviceDescriptor);
+        if (xrPhysicalDeviceDescriptor && (index < m_supportedXRDevices.size()))
+        {
+            xrPhysicalDeviceDescriptor->m_outputData.m_xrVkPhysicalDevice = m_supportedXRDevices[index];
+            return AZ::RHI::ResultCode::Success;
+        }
+        return AZ::RHI::ResultCode::Fail;
+    }
+
+    AZ::u32 Instance::GetNumPhysicalDevices()
+    {
+        return aznumeric_cast<AZ::u32>(m_supportedXRDevices.size());
+    }
+
+    VkPhysicalDevice Instance::GetActivePhysicalDevice()
+    {
+        AZ_Assert(m_physicalDeviceActiveIndex < m_supportedXRDevices.size(), "Index out of range");
+        return m_supportedXRDevices[m_physicalDeviceActiveIndex];
+    }
+
+    XrInstance Instance::GetXRInstance()
+    {
+        return m_xrInstance;
+    }
+
+    XrSystemId Instance::GetXRSystemId()
+    {
+        return m_xrSystemId;
+    }
+
+    VkInstance Instance::GetVkInstance()
+    {
+        return m_xrVkInstance;
+    }
+
+    XrEnvironmentBlendMode Instance::GetEnvironmentBlendMode()
+    {
+        return m_environmentBlendMode;
+    }
+
+    XrViewConfigurationType Instance::GetViewConfigType()
+    {
+        return m_viewConfigType;
     }
 }

+ 25 - 18
Gems/OpenXRVk/Code/Source/OpenXRVkModule.cpp

@@ -8,31 +8,38 @@
 
 #include <AzCore/Memory/SystemAllocator.h>
 #include <AzCore/Module/Module.h>
+#include <OpenXrVk/OpenXrVkSystemComponent.h>
 
-namespace AZ
-{
-    namespace OpenXRVk
+namespace OpenXRVk
+{   
+    //! This module is in charge of loading system components related to Openxrvk. 
+    class Module
+        : public AZ::Module
     {
-        /**
-        * This module is in charge of loading the RHI reflection descriptor and the
-        * system components in charge of managing the different factory backends.
-        */
-        class Module
-            : public AZ::Module
+    public:
+        AZ_RTTI(Module, "{C34AA64E-0983-4D30-A33C-0D7C7676A20E}", AZ::Module);
+        AZ_CLASS_ALLOCATOR(Module, AZ::SystemAllocator, 0);
+
+        Module()
+            : AZ::Module()
         {
-        public:
-            AZ_RTTI(Module, "{C34AA64E-0983-4D30-A33C-0D7C7676A20E}", AZ::Module);
-            AZ_CLASS_ALLOCATOR(Module, AZ::SystemAllocator, 0);
+            m_descriptors.insert(m_descriptors.end(), {
+                    SystemComponent::CreateDescriptor(),
+            });
+        }
 
-            Module()
-                : AZ::Module()
+        AZ::ComponentTypeList GetRequiredSystemComponents() const override
+        {
+            return
             {
-            }
-        };
-    }
+                azrtti_typeid<OpenXRVk::SystemComponent>()
+            };
+        }
+    };
 }
 
+
 // DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM
 // The first parameter should be GemName_GemIdLower
 // The second should be the fully qualified name of the class above
-AZ_DECLARE_MODULE_CLASS(Gem_OpenXRVk, AZ::OpenXRVk::Module)
+AZ_DECLARE_MODULE_CLASS(Gem_OpenXRVk, OpenXRVk::Module)

+ 19 - 3
Gems/OpenXRVk/Code/Source/OpenXRVkPhysicalDevice.cpp

@@ -7,12 +7,28 @@
  */
 
 #include <OpenXRVk/OpenXRVkPhysicalDevice.h>
+#include <OpenXRVk/OpenXRVkUtils.h>
 
 namespace OpenXRVk
 {
-    AZStd::vector<AZStd::intrusive_ptr<XR::PhysicalDevice>> PhysicalDevice::EnumerateDeviceList()
+    AZStd::vector<VkPhysicalDevice> PhysicalDevice::EnumerateDeviceList(XrSystemId xrSystemId, XrInstance xrInstance, VkInstance vkInstance)
     {
-        AZStd::vector<AZStd::intrusive_ptr<XR::PhysicalDevice>> res;
-        return res;
+        AZStd::vector<VkPhysicalDevice> physicalDevices;
+		
+        XrVulkanGraphicsDeviceGetInfoKHR deviceGetInfo{ XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR };
+        deviceGetInfo.systemId = xrSystemId;
+        deviceGetInfo.vulkanInstance = vkInstance;
+        VkPhysicalDevice vkPhysicalDevice = VK_NULL_HANDLE;
+
+        PFN_xrGetVulkanGraphicsDeviceKHR pfnGetVulkanGraphicsDeviceKHR = nullptr;
+        XrResult result = xrGetInstanceProcAddr(
+	        xrInstance, "xrGetVulkanGraphicsDeviceKHR", reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanGraphicsDeviceKHR));
+        ASSERT_IF_UNSUCCESSFUL(result);
+
+        //TODO::Look into api that can retreive multiple physicall devices if connected
+        result = pfnGetVulkanGraphicsDeviceKHR(xrInstance, xrSystemId, vkInstance, &vkPhysicalDevice);
+        ASSERT_IF_UNSUCCESSFUL(result);
+        physicalDevices.push_back(vkPhysicalDevice);
+        return physicalDevices;
     }
 }

+ 6 - 4
Gems/OpenXRVk/Code/Source/OpenXRVkSession.cpp

@@ -10,6 +10,8 @@
 
 namespace OpenXRVk
 {
+    //Todo: Pull this in when needed or remove
+    /*
     AZStd::intrusive_ptr<Session> Session::Create()
     {
         return nullptr;
@@ -28,9 +30,9 @@ namespace OpenXRVk
     }
 
     void Session::HandleSessionStateChangedEvent(
-        const XrEventDataSessionStateChanged& /*stateChangedEvent*/,
-        bool* /*exitRenderLoop*/,
-        bool* /*requestRestart*/)
+        const XrEventDataSessionStateChanged&,
+        bool*,
+        bool*)
     {
         // Handle Session state changes
     }
@@ -49,5 +51,5 @@ namespace OpenXRVk
     {
         return m_sessionState == XR_SESSION_STATE_FOCUSED;
     }
-
+    */
 }

+ 4 - 2
Gems/OpenXRVk/Code/Source/OpenXRVkSwapChain.cpp

@@ -7,10 +7,11 @@
  */
 
 #include <OpenXRVk/OpenXRVkSwapChain.h>
-#include <OpenXRVk/OpenXRVkFactory.h>
 
 namespace OpenXRVk
 {
+    //Pull this in if needed or remove
+    /*
     AZStd::intrusive_ptr<SwapChain> SwapChain::Create()
     {
         return aznew SwapChain;
@@ -26,7 +27,7 @@ namespace OpenXRVk
         return aznew SwapChain::View;
     }
 
-    AZ::RHI::ResultCode SwapChain::View::Init(XrSwapchain /*handle*/, AZ::u32 /*width*/, AZ::u32 /*height*/)
+    AZ::RHI::ResultCode SwapChain::View::Init(XrSwapchain handle, AZ::u32 width, AZ::u32 height)
     {
         return AZ::RHI::ResultCode::Success;
     }
@@ -47,4 +48,5 @@ namespace OpenXRVk
         }
         return AZ::RHI::ResultCode::Success;
     }
+    */
 }

+ 0 - 173
Gems/OpenXRVk/Code/Source/OpenXRVkSystem.cpp

@@ -1,173 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#include <OpenXRVk/OpenXRVkSystem.h>
-#include <OpenXRVk/OpenXRVkFactory.h>
-
-namespace OpenXRVk
-{
-    // Accessor functions for RHI objects that are populated by backend XR gems
-    // This will allow XR gem to provide device related data to RHI
-    AZ::RPI::XRDeviceDescriptor* System::GetDeviceDescriptor()
-    {
-        return m_deviceDesc.get();
-    }
-
-    // Provide access to instance specific data to RHI
-    AZ::RPI::XRInstanceDescriptor* System::GetInstanceDescriptor()
-    {
-        return m_instanceDesc.get();
-    }
-
-    // Provide Swapchain specific data to RHI
-    AZ::RPI::XRSwapChainImageDescriptor* System::GetSwapChainImageDescriptor(AZ::u16 swapchainIndex)
-    {
-        return m_swapchainImageDesc[swapchainIndex].get();
-    }
-
-    // Provide access to Graphics Binding specific data that RHI can populate
-    AZ::RPI::XRGraphicsBindingDescriptor* System::GetGraphicsBindingDescriptor()
-    {
-        return m_graphicsBindingDesc.get();
-    }
-
-    // Access supported Layers and extension names
-    const AZStd::vector<AZStd::string>& System::GetLayerNames()
-    {
-        return m_layerNames;
-    }
-
-    const AZStd::vector<AZStd::string>& System::GetExtensionNames()
-    {
-        return m_extentionNames;
-    }
-
-    // Create XR instance object and initialize it
-    AZ::RHI::ResultCode System::InitInstance()
-    {
-//         m_instance = Factory::Get().CreateInstance();
-// 
-//         if (m_instance)
-//         {
-//             return m_instance->InitInstanceInternal();
-//         }
-        return AZ::RHI::ResultCode::Fail;
-    }
-
-    // Create XR device object and initialize it
-    AZ::RHI::ResultCode System::InitDevice()
-    {
-//         m_device = Factory::Get().CreateDevice();
-// 
-//         // Get a list of XR compatible devices
-//         AZStd::vector<AZStd::intrusive_ptr<PhysicalDevice>> physicalDeviceList = Factory::Get().EnumerateDeviceList();
-// 
-//         // Code to pick the correct device.
-//         // For now we can just pick the first device in the list
-// 
-//         if (m_device)
-//         {
-//             return m_device->InitDeviceInternal();
-//         }
-        return AZ::RHI::ResultCode::Fail;
-    }
-
-    // Initialize XR instance and device
-    AZ::RHI::ResultCode System::InitializeSystem()
-    {
-//         AZ::RHI::ResultCode instResult = InitInstance();
-//         if (instResult != AZ::RHI::ResultCode::Success)
-//         {
-//             AZ_Assert(false, "XR Instance creation failed");
-//             return instResult;
-//         }
-// 
-//         AZ::RHI::ResultCode deviceResult = InitDevice();
-//         if (deviceResult != AZ::RHI::ResultCode::Success)
-//         {
-//             AZ_Assert(false, "XR device creation failed");
-//             return deviceResult;
-//         }
-        return AZ::RHI::ResultCode::Success;
-    }
-
-    // Initialize a XR session
-    AZ::RHI::ResultCode System::InitializeSession()
-    {
-//         m_session = Factory::Get().CreateSession();
-// 
-//         if (m_session)
-//         {
-//             XR::SessionDescriptor sessionDesc;
-//             m_graphicsBindingDesc = Factory::Get().CreateGraphicsBindingDescriptor();
-//             sessionDesc.m_graphicsBinding = RPISystem::Get()->PopulateGrapicsBinding(m_graphicsBindingDesc);
-//             AZ::RHI::ResultCode sessionResult = m_session->Init(sessionDesc);
-//             AZ_Assert(sessionResult == AZ::RHI::ResultCode::Success, "Session init failed");
-// 
-//             m_xrInput = Factory::Get().CreateInput();
-//             return m_xrInput->InitializeActions();
-//         }
-        return AZ::RHI::ResultCode::Fail;
-    }
-
-    // Manage session lifecycle to track if RenderFrame should be called.
-    bool System::IsSessionRunning() const
-    {
-        return m_session->IsSessionRunning();
-    }
-
-    // Create a Swapchain which will responsible for managing
-    // multiple XR swapchains and multiple swapchain images within it
-    AZ::RHI::ResultCode System::CreateSwapchain()
-    {
-//         m_swapChain = Factory::Get().CreateSwapchain();
-// 
-//         if (m_swapChain)
-//         {
-//             AZ::RHI::ResultCode swapchainCreationResult = m_swapChain->Init(sessionDesc);
-//             AZ_Assert(sessionResult == AZ::RHI::ResultCode::Success, "Swapchain init failed");
-//             return swapchainCreationResult;
-//         }
-        return AZ::RHI::ResultCode::Fail;
-    }
-
-    // Indicate start of a frame
-    void System::BeginFrame()
-    {
-    }
-
-    // Indicate end of a frame
-    void System::EndFrame()
-    {
-    }
-
-    // Indicate start of a XR view to help with synchronizing XR swapchain
-    void System::BeginView()
-    {
-    }
-
-    // Indicate end of a XR view to help with synchronizing XR swapchain
-    void System::EndView()
-    {
-    }
-
-    // System Tick to poll input data
-    void System::OnSystemTick()
-    {
-//         m_input->PollEvents();
-//         if (exitRenderLoop)
-//         {
-//             break;
-//         }
-// 
-//         if (IsSessionRunning())
-//         {
-//             m_input->PollActions();
-//         }
-    }
-}

+ 58 - 0
Gems/OpenXRVk/Code/Source/OpenXRVkSystemComponent.cpp

@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <OpenXrVk/OpenXrVkSystemComponent.h>
+#include <OpenXrVk/OpenXrVkInstance.h>
+#include <OpenXrVk/OpenXrVkDevice.h>
+#include <AzCore/Serialization/SerializeContext.h>
+
+namespace OpenXRVk
+{
+    void SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
+    {
+        provided.push_back(XR::Factory::GetPlatformService());
+    }
+
+    void SystemComponent::Reflect(AZ::ReflectContext* context)
+    {
+        if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<SystemComponent, AZ::Component>()
+                ->Version(1);
+        }
+    }
+
+    SystemComponent::SystemComponent()
+    {
+        // Only have Vulkan back-end implementation for XR at the moment so register it. 
+        XR::Factory::Register(this);
+    }
+
+    SystemComponent::~SystemComponent()
+    {
+        XR::Factory::Unregister(this);
+    }
+
+    XR::Ptr<XR::Instance> SystemComponent::CreateInstance()
+    {
+        return Instance::Create();
+    }
+
+    XR::Ptr<XR::Device> SystemComponent::CreateDevice()
+    {
+        return Device::Create();
+    }
+
+    void SystemComponent::Activate()
+    {
+    }
+
+    void SystemComponent::Deactivate()
+    {
+    }
+}

+ 43 - 2
Gems/OpenXRVk/Code/Source/OpenXRVkUtils.cpp

@@ -7,7 +7,7 @@
  */
 
 #include <OpenXRVk/OpenXRVkUtils.h>
-//#include <AzCore/Debug/Trace.h>
+#include <AzCore/Debug/Trace.h>
 
 namespace OpenXRVk
 {
@@ -28,9 +28,50 @@ namespace OpenXRVk
     {
         if (result != XR_SUCCESS)
         {
-            //AZ_Error("XR", false, "ERROR: XR API method failed: %s", GetResultString(result));
+            AZ_Error("XR", false, "ERROR: XR API method failed: %s", GetResultString(result));
             return false;
         }
         return true;
     }
+
+    bool IsError(XrResult result)
+    {
+        return IsSuccess(result) == false;
+    }
+
+    const char* GetResultString(const XrResult result)
+    {
+        return to_string(result);
+    }
+
+    XR::RawStringList FilterList(const XR::RawStringList& source, const XR::StringList& filter)
+    {
+        XR::RawStringList filteredList;
+        for (auto& item : source)
+        {
+            if (AZStd::find(filter.begin(), filter.end(), item) != filter.end())
+            {
+                filteredList.push_back(item);
+            }
+        }
+        return filteredList;
+    }
+
+    AZStd::vector<const char*> ParseExtensionString(char* names)
+    {
+        AZStd::vector<const char*> list;
+        while (*names != 0)
+        {
+            list.push_back(names);
+            while (*(++names) != 0)
+            {
+                if (*names == ' ')
+                {
+                    *names++ = '\0';
+                    break;
+                }
+            }
+        }
+        return list;
+    }
 }

+ 2 - 0
Gems/OpenXRVk/Code/Source/Platform/Android/OpenXRVk_Traits_Android.h

@@ -7,3 +7,5 @@
  */
 #pragma once
 
+#define VULKAN_DLL "vulkan.dll"
+#define VULKAN_1_DLL "vulkan-1.dll"

+ 2 - 0
Gems/OpenXRVk/Code/Source/Platform/Linux/OpenXRVk_Traits_Linux.h

@@ -7,3 +7,5 @@
  */
 #pragma once
 
+#define VULKAN_DLL "vulkan.dll"
+#define VULKAN_1_DLL "vulkan-1.dll"

+ 2 - 0
Gems/OpenXRVk/Code/Source/Platform/Windows/OpenXRVk_Traits_Windows.h

@@ -7,3 +7,5 @@
  */
 #pragma once
 
+#define VULKAN_DLL "vulkan.dll"
+#define VULKAN_1_DLL "vulkan-1.dll"

+ 13 - 4
Gems/OpenXRVk/Code/openxrvk_private_common_files.cmake

@@ -8,7 +8,6 @@
 
 set(FILES
     Include/OpenXRVk/OpenXRVkDevice.h
-    Include/OpenXRVk/OpenXRVkFactory.h
     Include/OpenXRVk/OpenXRVkGraphicsBinding.h
     Include/OpenXRVk/OpenXRVkInput.h
     Include/OpenXRVk/OpenXRVkInstance.h
@@ -16,10 +15,11 @@ set(FILES
     Include/OpenXRVk/OpenXRVkSession.h
     Include/OpenXRVk/OpenXRVkSpace.h
     Include/OpenXRVk/OpenXRVkSwapChain.h
-    Include/OpenXRVk/OpenXRVkSystem.h
+    Include/OpenXRVk/OpenXRVkSystemComponent.h
     Include/OpenXRVk/OpenXRVkUtils.h
+    Include/OpenXRVk/OpenXRVkFunctionLoader.h
+    Include/OpenXRVk/OpenXRVkGladFunctionLoader.h
     Source/OpenXRVkDevice.cpp
-    Source/OpenXRVkFactory.cpp
     Source/OpenXRVkGraphicsBinding.cpp
     Source/OpenXRVkInput.cpp
     Source/OpenXRVkInstance.cpp
@@ -27,6 +27,15 @@ set(FILES
     Source/OpenXRVkSession.cpp
     Source/OpenXRVkSpace.cpp
     Source/OpenXRVkSwapChain.cpp
-    Source/OpenXRVkSystem.cpp
+    Source/OpenXRVkSystemComponent.cpp
     Source/OpenXRVkUtils.cpp
+    Source/OpenXRVkFunctionLoader.cpp
+    Source/OpenXRVkGladFunctionLoader.cpp
 )
+
+set(SKIP_UNITY_BUILD_INCLUSION_FILES
+    # The following file defines GLAD_VULKAN_IMPLEMENTATION before including vulkan.h changing
+    # the behavior inside vulkan.h. Other files also includes vulkan.h so this file cannot
+    # be added to unity, other files could end up including vulkan.h and making this one fail.
+    Source/OpenXRVkGladFunctionLoader.cpp
+)