Issue in Pimax OpenXR runtime causing VRAM overhead with OFXR

This issue is for Pimax to fix a problem with Pimax OpenXR that will cause VRAM usage from OFXR to almost double.
The current work-around is to use sboys3 SteamVR driver instead.

Summary

The Pimax OpenXR runtime allocates an additional full-size copy of every swapchain image an application submits, inside the application’s process, at the image’s first xrEndFrame. The copies are not released when the swapchain is destroyed; they stay until the session ends. SteamVR, with the same application at the same per-eye resolution, allocates no such copy.

For an application that uses several swapchains this doubles the video memory each image costs. OFXR Bridge (an OpenXR API layer that generates intermediate frames) submits through 4 private swapchains of 3 images each on top of the game’s own. On a Pimax Crystal at 5424×5356 per eye those 12 images cost 1.39 GB to create and the runtime then adds 0.85 GB of copies at their first submission. An earlier build of the layer with 8 private swapchains (24 images) measured 2.97 GB of copies: the cost follows the image count exactly. The same game, mode and pixel count on SteamVR show no such growth.

Setup

  • Pimax Crystal, Pimax Play (current version as of 2026-10-04), Pimax OpenXR runtime active.
  • RTX 5090 (32 GB), Windows 11 Pro 26200, Ryzen.
  • Microsoft Flight Simulator 2024, DirectX 12, native OpenXR, 90 Hz.
  • Runtime-recommended per-eye size: 5424×5356 (xrEnumerateViewConfigurationViews).
  • Swapchains requested by the game: 2 colour R8G8B8A8_UNORM_SRGB (one per eye) and 2 depth D32_FLOAT_S8X24_UINT, 5424×5356, 3 images each.
  • OFXR Bridge adds, per eye, 2 colour swapchains of the same create info (format, size, usage), 3 images each: 12 images in all.

Memory was read in-process with IDXGIAdapter3::QueryVideoMemoryInfo(DXGI_MEMORY_SEGMENT_GROUP_LOCAL) on the game’s adapter, from inside the game, at each step below and once a second afterwards. The figures are the whole process (game + runtime DLL + layer).

What was observed

Time is from the OpenXR session’s creation. Each line is the process’s local video memory after the step.

Time Step Usage Change
0.04 s xrCreateSession returned 13.07 GB
0.19–0.29 s 4 game swapchains created and enumerated 12.99 GB (game freeing its previous set)
0.62 s game allocates its render targets 15.12 GB +2.13 GB (the game’s own)
0.67–0.97 s layer creates 4 private swapchains (12 images) and its own buffers 17.56 GB +2.44 GB, matches the create infos
1.06–1.11 s first xrAcquireSwapchainImage / xrWaitSwapchainImage on each private swapchain 17.61 GB +0.05 GB
1.08–1.65 s first ~70 xrEndFrame calls, which cycle every private image through the runtime 18.45 GB +0.84 GB
1.65–5.8 s steady play 18.3–18.4 GB flat
6.65–6.74 s layer destroys its 4 private swapchains and buffers, game destroys its 4 13.64 GB −4.7 GB: the create-time allocations come back, the 0.84 GB does not (0.57 GB above the session’s start)
  • The runtime hands back R8G8B8A8_UNORM images (typeless twin of the sRGB request), one mip, no array, 116 MB each at this size.
  • The +0.84 GB equals 7.3 images of 116 MB. 12 private images were submitted for the first time in that window; the game’s own 6 had been submitted before the layer armed.
  • Nothing is allocated at first acquire; the allocation happens at first submission.
  • The same run with the layer’s two optical-flow backends (NVIDIA Optical Flow and FidelityFX) gives identical results, and the layer makes no GPU allocation after its initialization step.

Comparison on SteamVR (same PC, same game, same mode, 6104×4780 per eye, 29.2 Mpx against 29.1):

Step Usage
session created 13.29 GB
after the layer’s 4 private swapchains and buffers 19.01 GB
steady play, 6–14 s 16.6–16.8 GB

No growth after the first submissions; the layer’s own allocations are the only extra.

The earlier build: twice the images, twice the copies

The previous build of the layer submitted through 8 private swapchains (24 images), everything else the same:

24 private images 12 private images
Growth across the first submissions, none of it the layer’s +2.97 GB +0.84 GB
MSFS 2024 steady state in VR, Pimax OpenXR 21.5 GB 18.4 GB
Same session on SteamVR, same pixel count 16.4 GB 16.6 GB

24 images, 2.97 GB; 12 images, 0.84 GB. The per-image copy is the whole difference between the two runtimes at equal resolution.

Why it matters

  • Any application with more than one or two swapchains pays twice per image on Pimax OpenXR and once elsewhere.
  • Because the copies are not released with the swapchain, an application that recreates its swapchains (MSFS 2024 does so on every world or settings transition) accumulates them for the length of the session.
  • On 16 GB cards at Crystal resolutions this is the difference between fitting and paging.

What we would ask

  1. Release the per-image copies when the swapchain is destroyed.
  2. If possible, compose from the application’s images (or from a shared handle to them) instead of copying, as SteamVR’s compositor does; or document the copy so applications can size for it.

How to reproduce

  1. Pimax Crystal on Pimax OpenXR, any OpenXR D3D12 application that creates several swapchains; or MSFS 2024 with OFXR Bridge (GitHub - djules75/OFXR-Bridge: Frame generation for VR using Optical Flow · GitHub) armed, which creates 4 (8 in version 0.2.9.1).
  2. Watch the process’s dedicated GPU memory (Task Manager → Details → Dedicated GPU memory, or QueryVideoMemoryInfo from inside).
  3. It rises by one image’s size per image at the first xrEndFrame that names it, and does not fall when the swapchain is destroyed.

The flight logs of both sessions, with every step time-stamped, are available on request.

4 Likes

Hope Pimax supports the OFXR app. It is a game changer and I’m sure it can get even better. Thank you so much for this!

5 Likes

As a temp work around, could the user set .90 or .80 render quality in piplay/evo?

This has been forwarded to our dev team. They’ll look into the OpenXR runtime when they have time, as we’ve received other reports of OpenXR-related issues as well.

1 Like