We currently hand two framebuffers to Babylon.js per-frame, one for each eye, pointing to different layers in the color & depth texture arrays provided by the OpenXR runtime. Ideally, we would use one framebuffer per-frame with the entire texture arrays attached and render to it in one set of draw calls (instead of two, one per eye) using the GL_OVR_multiview2 extension. This will allow us to avoid two full renders per frame. In rendering-dominated scenarios, we could see up to a ~40% decrease in frame time, almost doubling our framerate.
Babylon.js currently has support for WebXR Projection Layers, which means that there already exists a path in Babylon.js to render stereo views to a texture array in a single pass, although there still remains lots of work to get BabylonNative to provide the multiview render target and set up view instanced rendering.
D3D12 supports view instancing, which will allow us to use a built-in variable, SV_ViewID in our hlsl shaders that will closely match the gl_ViewID_OVR built-in variable provided by the GL_OVR_multiview2 extension.
Here's a breakdown of what would need to get done to connect these two:
When creating the pipeline state object on D3D12 for a pipeline that should use multiview, we need to add a D3D12_VIEW_INSTANCING_DESC to the PSO and set the ViewInstanceCount to 2.
The hardest part here will be finding a way to change the contract (possibly by adding a parameter to getPipelineState) so that we can send the view instance count to bgfx in a way that works for D3D12 but doesn't disturb things on all of the other rendering backends.
BabylonNative (2)
Change the framebuffers we make for XR rendering to use texture arrays when eyeCount > 1 and specify multiview = true for the multiview XR render targets that we hand off to Babylon.js (naturally this will be false on monocular/mobile devices)
Leverage the new bgfx contract to create the Babylon shader's pipeline state object with view instancing for shaders with the multiview extension enabled, which we can detect with glslang.
Babylon.js
Implement bindMultiviewFramebuffer for NativeEngine. This will likely just alias the existing bindFramebuffer.
We currently hand two framebuffers to Babylon.js per-frame, one for each eye, pointing to different layers in the color & depth texture arrays provided by the OpenXR runtime. Ideally, we would use one framebuffer per-frame with the entire texture arrays attached and render to it in one set of draw calls (instead of two, one per eye) using the GL_OVR_multiview2 extension. This will allow us to avoid two full renders per frame. In rendering-dominated scenarios, we could see up to a ~40% decrease in frame time, almost doubling our framerate.
Babylon.js currently has support for WebXR Projection Layers, which means that there already exists a path in Babylon.js to render stereo views to a texture array in a single pass, although there still remains lots of work to get BabylonNative to provide the multiview render target and set up view instanced rendering.
D3D12 supports view instancing, which will allow us to use a built-in variable,
SV_ViewID
in our hlsl shaders that will closely match thegl_ViewID_OVR
built-in variable provided by the GL_OVR_multiview2 extension.Here's a breakdown of what would need to get done to connect these two:
BuiltInViewIndex
that outputsSV_ViewID
when using shader model 6.1 or greater.D3D12_VIEW_INSTANCING_DESC
to the PSO and set theViewInstanceCount
to 2.getPipelineState
) so that we can send the view instance count to bgfx in a way that works for D3D12 but doesn't disturb things on all of the other rendering backends.eyeCount > 1
and specifymultiview = true
for the multiview XR render targets that we hand off to Babylon.js (naturally this will be false on monocular/mobile devices)bindMultiviewFramebuffer
forNativeEngine
. This will likely just alias the existingbindFramebuffer
.