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

[4.x] Use depth prepass to increase opaque render performance #70214

Merged
merged 1 commit into from
Dec 23, 2022

Conversation

Ansraer
Copy link
Contributor

@Ansraer Ansraer commented Dec 17, 2022

Some minor performance improvements I came up with while investigating #68959.

  1. Disable writing depth in opaque pass since we have already done so in the pre pass.
  2. Change depth comparison op to equal in the opaque pass.
    This has the big advantage that transparent fragments can be discarded by the early test before they even enter the fragment stage. We thus save ourselves from starting a fragment shader just to immediately quit it again when we discard.

I tested this PR using https://github.com/Rytelier/Godot-4-forest-benchmark and got the following results:

Details

image

As you can see this change can reduce the time needed for the opaque pass by up to half.
According to renderdoc 33678, 12582, and 3654 are all meshes used to render the leaves of the trees.

Visually I could see no difference between the rendered frames.

(Kinda) fixes #60364

This PR is not applicable to the mobile renderer, since it has no prepass. I am fairly certain that a similar change could be implemented in the OpenGL renderer, but it appears to be currently broken

@clayjohn
Copy link
Member

clayjohn commented Dec 17, 2022

I am fairly certain that a similar change could be implemented in the OpenGL renderer, but it appears to be currently broken

What seems broken? This change should be applicable to the OpenGL renderer as well

@Ansraer
Copy link
Contributor Author

Ansraer commented Dec 17, 2022

Checked the log, and it would appear that GL doesn't like many of the image formats that were used with the clustered renderer. Also, it would appear that refraction is currently broken. Whenever I try to start godot complains about the following:

ERROR: SceneShaderGLES3: Fragment shader compilation failed:
ERROR: 0:955: 'm_SCREEN_TEXTURE' : undeclared identifier
ERROR: 0:955: '' : compilation terminated
ERROR: 2 compilation errors.  No code generated.

A quick search would imply that this is caused by Line 1230 in material.cpp.

code += " float ref_amount = 1.0 - albedo.a * albedo_tex.a;\n";
code += " EMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n";
code += " ALBEDO *= 1.0 - ref_amount;\n";

@Calinou
Copy link
Member

Calinou commented Dec 17, 2022

Is this change relevant for 3.x's GLES3 renderer, which features a depth prepass?

@clayjohn
Copy link
Member

clayjohn commented Dec 17, 2022

Checked the log, and it would appear that GL doesn't like many of the image formats that were used with the clustered renderer. Also, it would appear that refraction is currently broken. Whenever I try to start godot complains about the following:

ERROR: SceneShaderGLES3: Fragment shader compilation failed:
ERROR: 0:955: 'm_SCREEN_TEXTURE' : undeclared identifier
ERROR: 0:955: '' : compilation terminated
ERROR: 2 compilation errors.  No code generated.

A quick search would imply that this is caused by Line 1230 in material.cpp.

code += " float ref_amount = 1.0 - albedo.a * albedo_tex.a;\n";
code += " EMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n";
code += " ALBEDO *= 1.0 - ref_amount;\n";

Ah yes, SCREEN_TEXTURE hasn't been re-implemented yet. I should do something to make sure it doesn't result in a compile error though. You shouldn't need the SCREEN_TEXTURE to test these changes though

@Calinou
Copy link
Member

Calinou commented Dec 17, 2022

I've tested this change on https://github.com/Calinou/godot-reflection, but it doesn't improve things much on a Radeon RX 6900 XT (Mesa RADV). This was tested by running the project without the editor in the background and staying at the spawn location. GPU is forced into a high power state with gamemode to avoid fluctuations.

1152×864

Before After (this PR)
806 FPS (1.24 mspf) 817 FPS (1.22 mspf)

3840×2160

Before After (this PR)
138 FPS (7.24 mspf) 139 FPS (7.19 mspf)

This can be reproduced when disabling all environment effects as well (uncheck everything in Environment, but keep Tonemap on Filmic):

3840×2160 (no effects)

Before After (this PR)
430 FPS (2.32 mspf) 442 FPS (2.26 mspf)

@Ansraer
Copy link
Contributor Author

Ansraer commented Dec 18, 2022

@Calinou That scene is a bad test case for this PR since it is >90% solid geometry.

What I do is leverage the depth pre-pass to make the rendering of alpha-clipped elements far cheaper, which doesn't really matter in scenes without alphaclipped objects. You should see at least some speedup if you open a scene with vegetation or hair cards.

I think there is a link to an example project in my original post.

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.

Other than this one small comment, I think this should be good!

@akien-mga akien-mga merged commit 2e07477 into godotengine:master Dec 23, 2022
@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.

Vulkan: Massive performance hit when rendering transparent objects
4 participants