[VR] Quest 3 Stereo Rendering — Per-Eye Covariance, Shared Compute, Performance Fixes#225
Open
arghyasur1991 wants to merge 2 commits intoaras-p:mainfrom
Open
[VR] Quest 3 Stereo Rendering — Per-Eye Covariance, Shared Compute, Performance Fixes#225arghyasur1991 wants to merge 2 commits intoaras-p:mainfrom
arghyasur1991 wants to merge 2 commits intoaras-p:mainfrom
Conversation
Single-pass instanced and multiview stereo rendering for Quest 3: - Per-eye model-view and projection matrices in compute shader for correct covariance projection (fixes severe VR visual artifacts) - Shared covariance/SH computation between eyes (compute once for left, reuse for right — only clip position differs) - Sort once, render twice — sorting uses center eye matrix - Stereo composite shader with tex2darray sampling per eye - clip() instead of discard in fragment shader (Adreno TBDR perf) - Dispatch based on splat count instead of view buffer count - View data buffer doubled for stereo (left + right eye data) Made-with: Cursor
- Skip stereo path in editor (!Application.isEditor) to prevent incorrect isStereo detection with MockHMD/OpenXR in play mode - Check cameraTargetDescriptor.dimension == Tex2DArray to skip stereo for OVROverlayCanvas and other stereo-enabled-but-2D cameras - Use cameraTargetDescriptor for RT creation instead of XRSettings.eyeTextureDesc (fixes depth/color dimension mismatch) - Guard m_Sorter.Dispatch with m_Sorter.Valid for GPUs lacking wave intrinsics Made-with: Cursor
This was referenced Mar 16, 2026
Author
|
not raising PR yet, but there are more performance optimizations present in https://github.com/arghyasur1991/UnityGaussianSplatting/tree/feature/quest-stereo-perf and my fork's main branch which allows rendering gaussian splats count as high as 300k at 16-18FPS in quest 3 without any jittering/visible frame drops (even from closeups).
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #173 with a cleaner, more correct implementation. Includes all fixes from the discussion there.
Summary
Adds single-pass instanced and multiview stereo rendering support for Quest 3 (and other VR headsets using URP), building on the approach from #173 with key correctness and performance improvements:
StereoMatricescbuffer. The original [VR] Single Pass Instanced/Multiview Support for Gaussian Splatting in URP #173 usedUNITY_MATRIX_VP/_MatrixMV(center eye) for covariance math, causing visible artifacts ("thorny ferns") in VR. This fix computes correct 2D covariance per eye.clip()instead ofdiscardin the fragment shader for better Adreno TBDR performance.m_SplatCountinstead ofm_GpuView.countfor compute dispatch (view buffer is 2x for stereo).Bug fixes (from #173 discussion)
!Application.isEditorprevents falseisStereodetection with MockHMD/OpenXR in editor play mode (fixes #173 comment — right eye rendering black)cameraTargetDescriptorinstead ofXRSettings.eyeTextureDescfor RT creation, fixing depth/color surface dimension errors on Questm_Sorter.Validcheck before dispatch for GPUs lacking wave intrinsicsStereo rendering approach
The
CSCalcViewDatacompute kernel now:_IsStereouniformCalculateEyeViewData()with left-eye matrices (full covariance + SH), copies result for right eye with only the clip position recomputed from right-eye VP matrix_SplatViewData[idx * 2](left) and_SplatViewData[idx * 2 + 1](right)RenderGaussianSplats.shaderindexes into view data viainstID * 2 + eyeIndexThe URP feature detects stereo via
XRSettings+Tex2DArraycheck, usesPrepareSplats()(sort + calc view data once) thenRenderPreparedSplats()per eye, compositing through a stereo tex2darray composite shader.What's NOT in this PR
unity_StereoEyeIndexusage (doesn't work withDrawProceduralon Quest 3 — manual 2-draw-call workaround used instead, see TODO in code)Tested on