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

[3.x] GLES2 & GLES3 - Use gl_FragColor temporary #84529

Merged
merged 1 commit into from
Jan 29, 2024

Conversation

lawnjelly
Copy link
Member

@lawnjelly lawnjelly commented Nov 6, 2023

On some hardware, modifying gl_FragColor multiple times (or more likely reading from gl_FragColor) can cause large performance drops. This PR writes to a standard temporary variable instead, and copies across to gl_FragColor once only at the end of the fragment shader.

This could potentially lead to large gains in performance on affected hardware (so far I've measured from 2x increase in fps (GLES2) to 4x (GLES3)).

Temporary variable is called frag_color in GLES2, and frag_color in GLES3 (In GLES3 the final output is renamed to frag_color_final).

Partially addresses #84526.

Notes

  • The problem shows most in fill rate limited circumstances, e.g. with MSAA, and where frag_color is read / modified more than once.
  • Should work with custom shaders as they write to e.g. ALBEDO rather than frag_color directly.
  • No changes needed for 2D as far as I can see.
  • May also be worth doing in 4.x, especially GLES3.
  • See Write / reading frag_color multiple times in shader seems to cause performance problem #84526 (comment) for tests on different hardware.
  • Although I've only measured increases in performance through scene.glsl, I've included the fix for other potentially affected shaders, as there is no evidence of a drop in performance and potential for gain, especially if these shaders are later modified.

Example Project

(Simple box with fog and emission)
Before 51 fps
After 104 fps

glFragColor.zip

@Calinou
Copy link
Member

Calinou commented Nov 6, 2023

Tested locally, it works as expected (no rendering issues). I can't notice any performance difference on a RTX 4090 (even at 8K) but it's not exactly the kind of GPU targeted by this optimization 🙂

@lawnjelly
Copy link
Member Author

Tested locally, it works as expected (no rendering issues). I can't notice any performance difference on a RTX 4090 (even at 8K) but it's not exactly the kind of GPU targeted by this optimization 🙂

It may not be a bottleneck on your super GPU, especially with such a simple test project (or not have the vulnerability). I bumped up the MSAA to make the difference show up more in the test project. It may appear more when the GPU is stressed by fill rate.

@lawnjelly lawnjelly changed the title [3.x] GLES2 - Use gl_FragColor temporary [3.x] GLES2 & GLES3 - Use gl_FragColor temporary Nov 6, 2023
@lawnjelly lawnjelly marked this pull request as ready for review November 7, 2023 11:48
@lawnjelly lawnjelly requested a review from a team as a code owner November 7, 2023 11:48
On some hardware, modifying gl_FragColor multiple times can cause large performance drops. This PR writes to a standard temporary variable instead, and copies across to gl_FragColor once only at the end of the fragment shader.

This could potentially lead to large gains in performance on affected hardware.
Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

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

I haven't tested locally, but I trust your testing on this. Issues would be immediately apparent if they appear.

@akien-mga akien-mga merged commit 30b81a4 into godotengine:3.x Jan 29, 2024
13 checks passed
@akien-mga
Copy link
Member

Thanks!

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

Successfully merging this pull request may close these issues.

4 participants