Closed moudgils closed 2 years ago
Hey just want to chime in on this. I am so happy this is finally an RFC.
Is there going to be some form of interaction framework for the OpenXR side of things? Here are some examples of interaction frameworks for various engines.
https://vreue4.com/ - Unreal Engine https://www.vrtk.io/ - Unity
Hey just want to chime in on this. I am so happy this is finally an RFC.
Is there going to be some form of interaction framework for the OpenXR side of things? Here are some examples of interaction frameworks for various engines.
https://vreue4.com/ - Unreal Engine https://www.vrtk.io/ - Unity
Once we have XR gem in place the idea is that it will provide access to all XR objects. As a result other gems will be able to communicate with the XR gem and build more advanced framework around XR related data processing. This specific RFC mostly focuses on the rendering side of XR interactions with Atom (O3de renderer) but I can imagine other gems working with XR gem and processing data related to input, audio, etc.
Hey just want to chime in on this. I am so happy this is finally an RFC. Is there going to be some form of interaction framework for the OpenXR side of things? Here are some examples of interaction frameworks for various engines. https://vreue4.com/ - Unreal Engine https://www.vrtk.io/ - Unity
Once we have XR gem in place the idea is that it will provide access to all XR objects. As a result other gems will be able to communicate with the XR gem and build more advanced framework around XR related data processing. This specific RFC mostly focuses on the rendering side of XR interactions with Atom (O3de renderer) but I can imagine other gems working with XR gem and processing data related to input, audio, etc.
Ok good to know and thank you for replying to my question. :)
Approved by sig/graphics-audio on May 18th, 2022
Should approved RFC's be visible here? https://github.com/o3de/sig-graphics-audio/tree/main/rfcs
Yes. It needs to be manually moved there but I think only a few people have permission to do that.
OpenXR
Summary:
OpenXR is an open royalty-free API standard from Khronos, providing engines with native access to a range of devices. It provides access to following API and we will need to add support for it in a modular fashion within O3DE. The api to add support for is as follows
What is the relevance of this feature?
This feature will help allow O3DE to work with VR (virtual reality), AR(Augmented reality) and MR(mixed reality). Initially this work will only focus on OpenXr Vk and DX12 but it can be expanded to include other xr backends. As a start this document will mostly focus on Quest2 as a testing platform.
Goals This document aims to provide framework around setting up XR related functionality that will need to work with Atom (O3de renderer) in an abstract modular manner. As part of setting up this framework we want to adhere to following goals.
Technical design description:
Proposed Framework
In order to gain a high level understanding attached are three diagrams related to
Gem structure
XR gem is responsible for implementing any interface (we could have more than one) needed by other gems. The interface will provide access to XR related data as well as functions to update the data as needed. In this document we will mostly be focusing on the rendering interface. This gem will hold common objects which will be extended by the backend gems like OpenXrVk, OpenXrDx12, etc. This will allow the XR gem to contain any common functionality that exists across all XR backends. XR gem will have no idea which backend is running under hood and to do that it will use the Factory pattern.
At a high level the design will be setup such that only XR gems will be including Atom gems and not vice versa. The RPI will provide XR specific rendering interface which is then implemented by the XR gems. This interface will be specified within XRSystemInterface and will live within RPI gem. This way Atom will not need to have a dependency on XR tech stack and should still work if the concrete implementation for this interface is not provided. With this design if the binaries related to XR gems are modified it will have no impact on binaries for Atom gems. This header file can be setup as a HEADERONLY module called RPI.XR.Interface within RPI’s cmakefile. The XRSystem class within the XR gem will extend from this interface and provide implementation as described below.
For this document we are only focusing on the vulkan implementation via OpenxrVk gem but later on it will be easy to support for DX12 via OpenxrDx12 gem or even other backends for more devices if needed
UML diagram for XR related functionality The color for each class dictate they will be in a specific gem.
XRSystemInterface
- Interface related to XR rendering and it lives within RPI. If in future a different gem (other than XR gem discussed here) wants to provide an implementation for this gem it can be done.XRSystem
(Singleton) - The class implementing all the interface functionality. More details with code provided further in this document. This class will hold all the XR objects and each XR object will be extended and backed by a class that will live in another gem. For example XR::Instance will be extended by OpenXrVk::Instance. Each XR object will also inherit fromAZStd::intrusive_refcount
in order to attain refcount support. The XR version of the objects will contain all the common code plus any validation code related for that object. Further down I have added code with comments to better explain the purpose of each object and how it will interact with other objects.OpenXrVk::SystemComponent
- This will act as a way to register OpenXrVk as a Factory at runtime and we can then useXR::FactoryManagerSystemComponent
to pick which factory to use (based on which rhi is picked by Atom). This will ensure we do not pick an incorrect factory for a platfor. For example we do not want to register OpenXrVk on Mac. It will provide a way to create objects that are from OpenXrVk namespace.RHI::XR::XXXDescriptors
- The definitions of these descriptors will live in RHI side but it will populated by XR gems. This will ensure that RHI gems will have no dependency on XR gems. The XR gem will include RHI gem headers and OpenXrVk gem will include RHI::Vk gem headers. That way OpenXrVk gem code can cast a RHI::XXXDescriptor object to RHI::Vulkan::XXXDescriptor and populate it accordingly.XR Render Pipeline (No view instancing)
Above is an example of what a render pipeline for a frame may look like initially. It is small yet big enough to cover most of the use cases we may encounter for a scene on a VR device. It has support for skinning, shadows, direct lighting, PBR shading, sky box, transparent objects (i.e particles), tonemapping and ui. Since the pipeline will be data driven it should be easy to modify or create new ones for a game’s specific needs.
BeginXRViewPass/EndXRViewPass
- These passes are setup so that RHI can call into XR (as part of Execution phase of the framegraph) and synchronize XR swapchain images. Part of this synchronization would contain calls like xrAcquireSwapchainImage, xrWaitSwapchainImage and xrReleaseSwapchainImage for multiple views.CopyToXRSwapChain
- This pass will be used to copy the final image to the XR swapchain image for a given view.Initially we will duplicate all the CPU Pass work for multiple views as that will be easy to add and will not require core changes to any of the current rendering features. Further down the line we can look into adding MultiView/View instancing support whereby we just have one pipeline and it will be able to do the work for multiple views and write out to multiple render target textures. This will require much bigger changes within RPI and RHI space and hence should be considered as a separate feature to be added later on.
XRSystemInterface (pseudocode) As part of writing this document it was easier for me to just write pseudo code in order to explain how all the code within XR gems will look like. I have added comments within the pseudocode to provide more context.
Once XR gem is activated it will initialize the XRSystem and then register iteself with RPI gem . The initialization may involve checking some criteria which may evolve later on. As a start it can just be as simple as checking a command line parameter (-xr=openxr). We should add an enum to the XRSystemInterface header which will allow us to capture the result of all XRSystem calls. The backend XR gems implementing the XR interface will return this ResultCode for most of the calls and allow the XR gem to take action based on the return code.
XR::XRSystemInterface pseudo code - Here is a possible starting interface used by the XR gem. This is mostly based on OpenXR functionality.
XR::XRSystem pseudo code - This will be implementing the Interface described above. It is a singleton so it can be accessed by other gems for anything related to XR.
Since XRSystem inherits from AZ::SystemTickBus::Handler it will be able to use OnSystemTick to poll input as shown in the pseudocode above.
XR::Factory pseudo code As explained above we will have XR objects which are implemented by Openxr gems like OpenXrVk. In order to help get this working we can setup a XR factory that is extended by SystemComponent within OpenXrVk
The factory will act as an interface for creating XR objects. It will be a singleton and be accessed by a call to XR::Factory::Get(). The OpenXrVk::SystemComponent will be responsible creating OpenXrVk objects by calling the static function Create that resides in all the OpenXrVk objects.
Below are all the XR objects which will define higher level common functionality. XR objects have no idea which gem will be implementing the XR backend. These objects should hopefully encapsulate most of the XR specific data and the API around these objects would be subject to change in future. Most of these objects are self explanatory and does not require further clarification around why they are needed. For deeper insight look at the code for OpenXrVk version of these objects.
OpenXRVk::XX pseudo code - This code will be part of OpenXrVk gem. Below is an example of one possible backend implementation for XR functionality
We will also need to add support for proper validation logging. This will allow us to better debug error codes across XR api. For example a function like this will be needed to log errors in case of a non successful XR error code.
RPI Following stuff will need to be done at RPI level
RHI
Debugging
Profiling
CPU perf - Usually cpu perf is not that hard to analysis. On PC we can use Pix but on Android we can use O3de’s in-built cpu profiler. It should already have support to export out serialized cpu profiling data that we can load on PC later for analysis.
GPU perf analysis in general is a very tricky thing on android (due to tiled GPUS) but hopefully native device tools would serve best for perf analysis.
Performance
1. Multi View / View instancing support As part of the perf work the first big change we should do is to implement “Multi View” support within Atom. This will essentially allow us to not duplicate CPU work related to all the passes for left and the right eye. We should be able to add support that will allow the passes to write out to texture arrays. This will be a fairly significant change to Atom. DX12 - https://microsoft.github.io/DirectX-Specs/d3d/ViewInstancing.html VK - https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html Metal - https://developer.apple.com/documentation/metal/render_passes/rendering_to_multiple_viewports_in_a_draw_command?language=objc
XR Render Pipeline (MultiView support) High level RHI changes
High level RPI
2. VRS (Foveated rendering) support - This will require a separate doc on VRS abstraction
3. Mobile specific optimizations (via O3de scalability work) - We can use it to disable features within the XR pipeline or lower configuration settings per feature that can help yield better perf. For example
What are the advantages of the feature?
What are the disadvantages of the feature?
How will this be implemented or integrated into the O3DE environment?
Recommended Development Plan in iterative steps
Are there any alternatives to this feature?
No alternatives at the moment
How will users learn this feature?
Oen questions?