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

Add MAY_DISCARD shader def, enabling early depth tests for most cases #6697

Merged
merged 6 commits into from
May 29, 2023

Conversation

coreh
Copy link
Contributor

@coreh coreh commented Nov 20, 2022

Objective

  • Right now we can't really benefit from early depth testing in our PBR shader because it includes codepaths with discard, even for situations where they are not necessary.

Solution

  • This PR introduces a new MeshPipelineKey and shader def, MAY_DISCARD;
  • All possible material/mesh options that that may result in discards being needed must set MAY_DISCARD ahead of time:
    • Right now, this is only AlphaMode::Mask(f32), but in the future might include other options/effects; (e.g. one effect I'm personally interested in is bayer dither pseudo-transparency for LOD transitions of opaque meshes)
  • Shader codepaths that can discard are guarded by an #ifdef MAY_DISCARD preprocessor directive:
    • Right now, this is just one branch in alpha_discard();
  • If MAY_DISCARD is not set, the @early_depth_test attribute is added to the PBR fragment shader. This is a not yet documented, possibly non-standard WGSL extension I found browsing Naga's source code. I opened a PR to document it there. My understanding is that for backends where this attribute is supported, it will force an explicit opt-in to early depth test. (e.g. via layout(early_fragment_tests) in; in GLSL)

Caveats

  • I included @early_depth_test for the sake of us being explicit, and avoiding the need for the driver to be “smart” about enabling this feature. That way, if we make a mistake and include a discard unguarded by MAY_DISCARD, it will either produce errors or noticeable visual artifacts so that we'll catch early, instead of causing a performance regression.
    • I'm not sure explicit early depth test is supported on the naga Metal backend, which is what I'm currently using, so I can't really test the explicit early depth test enable, I would like others with Vulkan/GL hardware to test it if possible;
  • I would like some guidance on how to measure/verify the performance benefits of this;
  • If I understand it correctly, this, or something like this is needed to fully reap the performance gains enabled by [Merged by Bors] - Add depth and normal prepass  #6284;
  • This will most definitely conflict with [Merged by Bors] - Add depth and normal prepass  #6284 and [Merged by Bors] - Standard Material Blend Modes #6644. I can fix the conflicts as needed, depending on whether/the order they end up being merging in.

Changelog

Changed

  • Early depth tests are now enabled whenever possible for meshes using StandardMaterial, reducing the number of fragments evaluated for scenes with lots of occlusions.

Copy link
Contributor

@IceSentry IceSentry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a good approach to me. It will conflict with the prepass, but that's only because the prepass PR also contains essentially the same logic. So this will help make the prepass PR that tiny bit simpler.

@alice-i-cecile alice-i-cecile added A-Rendering Drawing game state to the screen C-Performance A change motivated by improving speed, memory usage or compile times labels Nov 21, 2022
Copy link
Contributor

@kurtkuehnert kurtkuehnert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice simple and scoped change. I have got nothing to add here.
A benchmark would indeed be interesting, but should not be necessary for merging this PR.

@coreh
Copy link
Contributor Author

coreh commented Jan 21, 2023

Now that #6284 has been merged, we should be able to reap some noticeable benefit from early depth tests.

@IceSentry just to confirm, did you include anything to the effect of this PR in #6284? I gave it a quick glance and couldn't find anything that specifically gates the discard statements, but maybe I missed it. If you did, this PR is somewhat redundant now, if not, it should still be relevant.

It looks like #6644 might also be merged soon. I'll wait until then, so that I fix the conflicts all at once.

Can someone help me come up with a good benchmark to verify early depth testing is benefiting us? I was thinking of something like a couple thousand complicated meshes, randomly positioned, overlapping each other, all opaque. Is there a recommended way to measure the amount of time spent running the shaders directly from the code? I'm thinking about using Metal System Trace on Instruments on macOS, but that only covers one platform and one API, ideally we'd have something more generic.

image

@IceSentry
Copy link
Contributor

IceSentry commented Jan 21, 2023

No I didn't include this since I expected this PR to be merged. It would most likely help since currently the prepass has a pretty high negative performance impact. Right now the prepass only becomes a performance improvements when the fragment shader is really heavy, otherwise it's mostly useful for special effects.

When you update this PR, make sure you also look at the prepass shaders, I think some of them use discard.

coreh added 4 commits May 10, 2023 21:05
- It is only currently supported by the GLES3.1+ wgpu backend;
- Enabling it would require special backend-specific code;
- Using it in the shaders would require adding a `#define` specifically for it;
- Only benefit is that it prevents adding accidental unguarded `discard;`
  statements that may harm performance.
@IceSentry IceSentry added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label May 24, 2023
@alice-i-cecile alice-i-cecile added this pull request to the merge queue May 29, 2023
Merged via the queue into bevyengine:main with commit 4465f25 May 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Performance A change motivated by improving speed, memory usage or compile times S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants