Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c501646

Browse files
author
Christopher Manthei
committedAug 26, 2021
Updated Graphics Binding with OpenXR info
- Also made a small fix for the native tutorial.
1 parent 5b35411 commit c501646

File tree

2 files changed

+80
-17
lines changed

2 files changed

+80
-17
lines changed
 

‎articles/remote-rendering/concepts/graphics-bindings.md

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Once set up, the graphics binding gives access to various functions that affect
2121

2222
In Unity, the entire binding is handled by the `RemoteUnityClientInit` struct passed into `RemoteManagerUnity.InitializeManager`. To set the graphics mode, the `GraphicsApiType` field has to be set to the chosen binding. The field will be automatically populated depending on whether an XRDevice is present. The behavior can be manually overridden with the following behaviors:
2323

24-
* **HoloLens 2**: the [Windows Mixed Reality](#windows-mixed-reality) graphics binding is always used.
24+
* **HoloLens 2**: the [OpenXR](#openxr) or the [Windows Mixed Reality](#windows-mixed-reality) graphics binding is used depending on the active Unity XR plugin.
2525
* **Flat UWP desktop app**: [Simulation](#simulation) is always used.
2626
* **Unity editor**: [Simulation](#simulation) is always used unless a WMR VR headset is connected in which case ARR will be disabled to allow to debug the non-ARR related parts of the application. See also [holographic remoting](../how-tos/unity/holographic-remoting.md).
2727

@@ -33,22 +33,23 @@ To select a graphics binding, take the following two steps: First, the graphics
3333

3434
```cs
3535
RemoteRenderingInitialization managerInit = new RemoteRenderingInitialization();
36-
managerInit.GraphicsApi = GraphicsApiType.WmrD3D11;
36+
managerInit.GraphicsApi = GraphicsApiType.OpenXrD3D11;
3737
managerInit.ConnectionType = ConnectionType.General;
3838
managerInit.Right = ///...
3939
RemoteManagerStatic.StartupRemoteRendering(managerInit);
4040
```
4141

4242
```cpp
4343
RemoteRenderingInitialization managerInit;
44-
managerInit.GraphicsApi = GraphicsApiType::WmrD3D11;
44+
managerInit.GraphicsApi = GraphicsApiType::OpenXrD3D11;
4545
managerInit.ConnectionType = ConnectionType::General;
4646
managerInit.Right = ///...
4747
StartupRemoteRendering(managerInit); // static function in namespace Microsoft::Azure::RemoteRendering
4848

4949
```
50-
51-
The call above is necessary to initialize Azure Remote Rendering into the holographic APIs. This function must be called before any holographic API is called and before any other Remote Rendering APIs are accessed. Similarly, the corresponding de-init function `RemoteManagerStatic.ShutdownRemoteRendering();` should be called after no holographic APIs are being called anymore.
50+
The call above must be called before any other Remote Rendering APIs are accessed.
51+
Similarly, the corresponding de-init function `RemoteManagerStatic.ShutdownRemoteRendering();` should be called after all other Remote Rendering objects are already destoyed.
52+
For WMR `StartupRemoteRendering` also needs to be called before any holographic API is called. For OpenXR the same applies for any OpenXR related APIs.
5253
5354
## <span id="access">Accessing graphics binding
5455
@@ -80,17 +81,79 @@ if (ApiHandle<GraphicsBinding> binding = currentSession->GetGraphicsBinding())
8081

8182
## Graphic APIs
8283

83-
There are currently two graphics APIs that can be selected, `WmrD3D11` and `SimD3D11`. A third one `Headless` exists but is not yet supported on the client side.
84+
There are currently three graphics APIs that can be selected, `OpenXrD3D11`, `WmrD3D11` and `SimD3D11`. A fourth one `Headless` exists but is not yet supported on the client side.
85+
86+
### OpenXR
87+
88+
`GraphicsApiType.OpenXrD3D11` is the default binding to run on HoloLens 2. It will create the `GraphicsBindingOpenXrD3d11` binding. In this mode Azure Remote Rendering creates a OpenXR API layer to integrate itself into the OpenXR runtime.
89+
90+
To access the derived graphics bindings, the base `GraphicsBinding` has to be cast.
91+
There are three things that need to be done to use the OpenXR binding:
92+
93+
#### Package custom OpenXR layer json
94+
95+
To use Remote Rendering with OpenXR the custom OpenXR API layer needs to be activated. This is done by calling `StartupRemoteRendering` mentioned in the previous section. However, as a prerequisite the `XrApiLayer_msft_holographic_remoting.json` needs to be packaged with the application so it can be loaded. This is done automatically if the **"Microsoft.Azure.RemoteRendering.Cpp"** NuGet package is added to a project.
96+
97+
#### Inform Remote Rendering of the used XR Space
98+
99+
This is needed to align remote and locally rendered content.
100+
101+
```cs
102+
RenderingSession currentSession = ...;
103+
ulong space = ...; // XrSpace cast to ulong
104+
GraphicsBindingOpenXrD3d11 openXrBinding = (currentSession.GraphicsBinding as GraphicsBindingOpenXrD3d11);
105+
if (openXrBinding.UpdateAppSpace(space) == Result.Success)
106+
{
107+
...
108+
}
109+
```
110+
111+
```cpp
112+
ApiHandle<RenderingSession> currentSession = ...;
113+
XrSpace space = ...;
114+
ApiHandle<GraphicsBindingOpenXrD3d11> openXrBinding = currentSession->GetGraphicsBinding().as<GraphicsBindingOpenXrD3d11>();
115+
#ifdef _M_ARM64
116+
if (openXrBinding->UpdateAppSpace(reinterpret_cast<uint64_t>(space)) == Result::Success)
117+
#else
118+
if (openXrBinding->UpdateAppSpace(space) == Result::Success)
119+
#endif
120+
{
121+
...
122+
}
123+
```
124+
125+
Where the above `XrSpace` is the one used by the application that defines the world space coordinate system in which coordinates in the API are expressed in.
126+
127+
#### Render remote image (OpenXR)
128+
129+
At the start of each frame, the remote frame needs to be rendered into the back buffer. This is done by calling `BlitRemoteFrame`, which will fill both color and depth information for both eyes into the currently bound render target. Thus it is important to do so after binding the full back buffer as a render target.
130+
131+
> [!WARNING]
132+
> After the remote image was blit into the backbuffer, the local content should be rendered using a single-pass stereo rendering technique, e.g. using **SV_RenderTargetArrayIndex**. Using other stereo rendering techniques, such as rendering each eye in a separate pass, can result in major performance degradation or graphical artifacts and should be avoided.
133+
134+
```cs
135+
RenderingSession currentSession = ...;
136+
GraphicsBindingOpenXrD3d11 openXrBinding = (currentSession.GraphicsBinding as GraphicsBindingOpenXrD3d11);
137+
openXrBinding.BlitRemoteFrame();
138+
```
139+
140+
```cpp
141+
ApiHandle<RenderingSession> currentSession = ...;
142+
ApiHandle<GraphicsBindingOpenXrD3d11> openXrBinding = currentSession->GetGraphicsBinding().as<GraphicsBindingOpenXrD3d11>();
143+
openXrBinding->BlitRemoteFrame();
144+
```
84145

85146
### Windows Mixed Reality
86147

87-
`GraphicsApiType.WmrD3D11` is the default binding to run on HoloLens 2. It will create the `GraphicsBindingWmrD3d11` binding. In this mode Azure Remote Rendering hooks directly into the holographic APIs.
148+
`GraphicsApiType.WmrD3D11` is the previously used graphics binding to run on HoloLens 2. It will create the `GraphicsBindingWmrD3d11` binding. In this mode Azure Remote Rendering hooks directly into the holographic APIs.
88149

89150
To access the derived graphics bindings, the base `GraphicsBinding` has to be cast.
90151
There are two things that need to be done to use the WMR binding:
91152

92153
#### Inform Remote Rendering of the used coordinate system
93154

155+
This is needed to align remote and locally rendered content.
156+
94157
```cs
95158
RenderingSession currentSession = ...;
96159
IntPtr ptr = ...; // native pointer to ISpatialCoordinateSystem
@@ -107,18 +170,15 @@ void* ptr = ...; // native pointer to ISpatialCoordinateSystem
107170
ApiHandle<GraphicsBindingWmrD3d11> wmrBinding = currentSession->GetGraphicsBinding().as<GraphicsBindingWmrD3d11>();
108171
if (wmrBinding->UpdateUserCoordinateSystem(ptr) == Result::Success)
109172
{
110-
//...
173+
...
111174
}
112175
```
113176
114177
Where the above `ptr` must be a pointer to a native `ABI::Windows::Perception::Spatial::ISpatialCoordinateSystem` object that defines the world space coordinate system in which coordinates in the API are expressed in.
115178
116-
#### Render remote image
117-
118-
At the start of each frame, the remote frame needs to be rendered into the back buffer. This is done by calling `BlitRemoteFrame`, which will fill both color and depth information for both eyes into the currently bound render target. Thus it is important to do so after binding the full back buffer as a render target.
179+
#### Render remote image (WMR)
119180
120-
> [!WARNING]
121-
> After the remote image was blit into the backbuffer, the local content should be rendered using a single-pass stereo rendering technique, e.g. using **SV_RenderTargetArrayIndex**. Using other stereo rendering techniques, such as rendering each eye in a separate pass, can result in major performance degradation or graphical artifacts and should be avoided.
181+
The same considerations as in the OpenXR case above apply here. The API calls look like this:
122182
123183
```cs
124184
RenderingSession currentSession = ...;

‎articles/remote-rendering/tutorials/native-cpp/hololens/integrate-remote-rendering-into-holographic-app.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,13 @@ void HolographicAppMain::StartModelLoading()
318318
[this](RR::Status status, RR::ApiHandle<RR::LoadModelResult> result)
319319
{
320320
m_modelLoadResult = RR::StatusToResult(status);
321-
m_modelLoadFinished = true; // successful if m_modelLoadResult==RR::Result::Success
322-
char buffer[1024];
323-
sprintf_s(buffer, "Remote Rendering: Model loading completed. Result: %s\n", RR::ResultToString(m_modelLoadResult));
324-
OutputDebugStringA(buffer);
321+
m_modelLoadFinished = true;
322+
323+
if (m_modelLoadResult == RR::Result::Success)
324+
{
325+
RR::Double3 pos = { 0.0, 0.0, -2.0 };
326+
result->GetRoot()->SetPosition(pos);
327+
}
325328
},
326329
// progress update callback
327330
[this](float progress)

0 commit comments

Comments
 (0)
Please sign in to comment.