Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGLRenderer: Improve efficiency of transmission pass for WebXR #28078

Closed
wants to merge 4 commits into from

Conversation

mrxz
Copy link
Contributor

@mrxz mrxz commented Apr 7, 2024

Related issue: #28073 and #22594

Description
This PR attempts to improve the efficiency of the transmission pass (for WebXR). The render targets used were incorrectly sized and rendering was interleaved with the main scene rendering (#22594). See the following before and after logs made using ovrgpuprofiler on a Quest 3.

Before:

Surface 0    | 3360x1760 | color 32bit, depth 24bit, stencil 0 bit, MSAA 4, Mode: 2 (SwBinning) | 72  288x320 bins ( 57  rendered) |  2.93 ms | 171 stages : Render : 0.244ms StoreColor : 0.392ms Blit : 0.004ms Preempt : 1.296ms StoreDepthStencil : 0.509ms
Surface 1    | 3360x1760 | color 64bit, depth 24bit, stencil 0 bit, MSAA 4, Mode: 1 (HwBinning) | 96  288x224 bins ( 96  rendered) |  5.29 ms | 291 stages : Binning : 0.069ms Render : 2.149ms StoreColor : 1.14ms Blit : 0.689ms StoreDepthStencil : 0.19ms
Surface 2    | 3360x1760 | color 32bit, depth 24bit, stencil 0 bit, MSAA 4, Mode: 1 (HwBinning) | 72  288x320 bins ( 72  rendered) |  5.80 ms | 222 stages : Binning : 0.274ms LoadColor : 0.075ms Render : 1.788ms StoreColor : 0.073ms Preempt : 2.62ms LoadDepthStencil : 0.255ms StoreDepthStencil : 0.072ms
Surface 3    | 3360x1760 | color 64bit, depth 24bit, stencil 0 bit, MSAA 4, Mode: 1 (HwBinning) | 96  288x224 bins ( 96  rendered) |  5.26 ms | 291 stages : Binning : 0.067ms Render : 2.143ms StoreColor : 1.141ms Blit : 0.659ms StoreDepthStencil : 0.184ms
Surface 4    | 3360x1760 | color 32bit, depth 24bit, stencil 0 bit, MSAA 4, Mode: 1 (HwBinning) | 72  288x320 bins ( 72  rendered) |  5.49 ms | 204 stages : Binning : 0.264ms LoadColor : 0.084ms Render : 1.773ms StoreColor : 0.082ms Preempt : 2.594ms LoadDepthStencil : 0.087ms

Background clear WebXR buffer -> left eye transmission -> left eye WebXR buffer -> right eye transmission -> right eye WebXR buffer

After:

Surface 0    | 3360x1760 | color 32bit, depth 24bit, stencil 0 bit, MSAA 4, Mode: 0 (Direct)    | 1   3360x1760 bins ( 1   rendered) |  0.00 ms | 1   stages : Render : 0.002ms
Surface 1    | 1680x1760 | color 64bit, depth 24bit, stencil 0 bit, MSAA 4, Mode: 1 (HwBinning) | 48  288x224 bins ( 48  rendered) |  3.22 ms | 147 stages : Binning : 0.07ms Render : 1.343ms StoreColor : 0.689ms Blit : 0.386ms StoreDepthStencil : 0.114ms
Surface 2    | 1680x1760 | color 64bit, depth 24bit, stencil 0 bit, MSAA 4, Mode: 1 (HwBinning) | 48  288x224 bins ( 48  rendered) |  5.27 ms | 150 stages : Binning : 0.067ms Render : 1.37ms StoreColor : 0.7ms Blit : 0.395ms Preempt : 1.84ms StoreDepthStencil : 0.115ms
Surface 3    | 3360x1760 | color 32bit, depth 24bit, stencil 0 bit, MSAA 4, Mode: 1 (HwBinning) | 72  288x320 bins ( 46  rendered) |  2.94 ms | 94  stages : Binning : 0.143ms Render : 2.157ms StoreColor : 0.37ms Blit : 0.005ms

WebXR buffer (no-op) -> left eye transmission -> right eye transmission -> WebXR buffer (background clear, left and right eye)

The individual changes are kept as individual commits for easier review. It might also make sense to split this up into individual PRs, as while they all serve the same goal, they do stand on their own. In order:

  • [f6a71b2] Size the transmissionRenderTarget based on the current viewport (or would-be viewport for WebXR).
    • Note the dimensions in the after logs are now half the width of the full framebuffer
    • This fix also applies to nested render calls from e.g. Reflector, which now match the dimensions of their render target.
  • [66a769f] Move rendering of the transmission pass outside and before the renderScene method, allowing transmission passes for both eyes to be rendered in advance.
  • [4e9490b] Split WebGLBackground to treat backgrounds that insert themselves into the render list differently from ones causing a clear.
    • Depending on the scene setup and clear flags, the WebGLBackground could perform a clear, but it can also inserts entries in the render list. A clear causes a "StoreColor" and "StoreDepthStencil" when switching to the transmission render target, despite the framebuffer being effectively empty. At the same time the background items are needed in the render list before rendering the transmission pass, so this commit splits the two behaviours.
  • [94bd720] Replace specific __transmissionRenderTarget flag with __ignoreDepthValues as neither depth nor stencil are needed after rendering
    • I had hoped to save on the StoreDepthStencil from the transmission passes, as the depth isn't needed any more. However it seems that when the multisample RTT extension is used this code path isn't used (i.e. __ignoreDepthValues has no effect on Quest). A follow-up PR should address this, though I'm not sure what the best place for this logic would be.

This contribution is funded by Fern Solutions

@mrxz mrxz changed the title Webxr transmission WebGLRenderer: Improve efficiency of transmission pass for WebXR Apr 7, 2024
Copy link

github-actions bot commented Apr 7, 2024

📦 Bundle size

Full ESM build, minified and gzipped.

Filesize dev Filesize PR Diff
672.7 kB (166.7 kB) 672.9 kB (166.7 kB) +257 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Filesize dev Filesize PR Diff
452.4 kB (109.2 kB) 452.6 kB (109.3 kB) +280 B

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 8, 2024

Awesome!

Do you think we can split up the PR so we can review and merge the changes step by step? That would make the review process easier and it's more likely to get changes faster into the core. Can we start with f6a71b2?

Regarding this commit, I agree it makes sense to switch from the default drawing buffer size to the current/active viewport when sizing the transmission render target. So this change looks good to me!

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 9, 2024

Now that f6a71b2 is in, how about moving on with 66a769f in a next PR?

@mrxz
Copy link
Contributor Author

mrxz commented Apr 9, 2024

Now that f6a71b2 is in, how about moving on with 66a769f in a next PR?

Opened a PR for it: #28097

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 11, 2024

I'm not sure I get 4e9490b yet 😇 . Can we discuss it in a next PR?

@mrxz
Copy link
Contributor Author

mrxz commented Apr 11, 2024

I'm not sure I get 4e9490b yet 😇 . Can we discuss it in a next PR?

Of course! 😁 Here's the next PR: #28118

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 13, 2024

Almost there^^! Only 94bd720 left.

@mrxz
Copy link
Contributor Author

mrxz commented Apr 13, 2024

Almost there^^! Only 94bd720 left.

Created a PR: #28132

Also somehow only just noticed a problem with double sided transmissive materials with the Oculus Browser (or rather any browser that supports WEBGL_multisampled_render_to_texture): #28131

@mrxz mrxz closed this Apr 14, 2024
@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 14, 2024

@mrxz Thank you for this great contribution! And for your patience during the review process^^. Splitting up the change into multiple PRs made it much easier to discuss and integrate everything into the renderer!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants