Skip to content

Use half float precision buffer for 3D when HDR2D is enabled#109971

Merged
Repiteo merged 1 commit into
godotengine:masterfrom
clayjohn:hdr2d-mobile
Oct 22, 2025
Merged

Use half float precision buffer for 3D when HDR2D is enabled#109971
Repiteo merged 1 commit into
godotengine:masterfrom
clayjohn:hdr2d-mobile

Conversation

@clayjohn

@clayjohn clayjohn commented Aug 25, 2025

Copy link
Copy Markdown
Member

Fixes: #86098
Fixes: #106282
Closes: godotengine/godot-proposals#7878

This took a bit of refactoring. Originally we selected a 3D framebuffer format based purely on whether we were in the mobile renderer or the Forward+ renderer. For the 2D framebuffer, we selected based on the presence of the HDR2D setting.

This created a strange incompatibility when using glow with HDR2D with the mobile renderer. Your 2D content would be rendered in HDR. Then copied into an LDR framebuffer. Then copied back to HDR with glow applied.

While there is a theoretical benefit to using an LDR framebuffer in 3D (especially when using glow), it just isn't compatiblity with 2D HDR. It is much better quality-wise to keep everything in HDR from beginning to end.

The biggest change is that we now look to the RenderBuffers class to determine if we should use an HDR format and whether we need to use a luminance multiplier. The RenderBuffers are automatically recreated if we switch to HDR, so this ensures that every part of the pipeline uses the same settings.

Reflections and sky still use LDR always since they can be shared between several Viewports and not all viewports necessarily have the same HDR2D setting. In the future we may want to consider making ReflectionProbes and Sky always use HDR. But that decision is out of scope for this PR.

@beicause

beicause commented Sep 2, 2025

Copy link
Copy Markdown
Contributor

Does this mean even not targeting 2D, enabling HDR 2D will cause 3D to use an RGBAH buffer? (Related: godotengine/godot-proposals#7878)

@clayjohn

clayjohn commented Sep 2, 2025

Copy link
Copy Markdown
Member Author

Does this mean even not targeting 2D, enabling HDR 2D will cause 3D to use an RGBAH buffer? (Related: godotengine/godot-proposals#7878)

That's right! Thank you for pointing that out

@beicause

beicause commented Sep 2, 2025

Copy link
Copy Markdown
Contributor

If so, this may cause a performance regression in 3D projects with HDR2D enabled, which could be unexpected (the term "HDR 2D" is not accurate anymore, docs need changes).

@clayjohn

clayjohn commented Sep 2, 2025

Copy link
Copy Markdown
Member Author

If so, this may cause a performance regression in 3D projects with HDR2D enabled, which could be unexpected (the term "HDR 2D" is not accurate anymore).

That's right. We discussed the performance tradeoff at length in #86098 and in subsequent rendering meetings and decided that it was worth the change. If 2D is using full HDR, then the entire pipeline should use full HDR.

That being said, its not necessarily going to be a performance regression because:

  1. Not all games are bandwidth limited. This change only hurts bandwidth limited games
  2. It opens up more opportunities to share resources between 2D and 3D which can have a positive impact on performance
  3. Most modern phones support framebuffer compression for RGBA16 buffers now. So the original reason to limit to RGB10A2 is gone now for many devices
  4. Once we support HDR output, this change is 100% necessary and will improve performance since we won't have to do a needless copy to promote the RGB10A2 buffer to full RGBA16.
  5. If users were already using HDR2D, they are paying the cost of having a RGBA16 buffer already, so they have already decided to accept reduced performance for the benefits it provides.

Overall, we felt that making this change was worthwhile.

@Calinou Calinou left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tested locally on many demo projects and https://github.com/Calinou/godot-reflection, it works as expected.

However, the sky appears visibly darker in Truck Town when HDR 2D is enabled in the project settings:

hdr_2d_mobile.mp4

This also carries over to the running project. However, reflection probes are not affected by this issue, even if you force them to update by moving them after changing the setting:

hdr_2d_mobile_reflection_probes.mp4

(The NaN you see in the reflection probe on the sun also occurs in master; I'll open a separate issue. Edit: #110207)

Either way, this has the upside of making viewport debanding functional in Mobile if HDR 2D is also enabled.

It's worth investigating for a future PR if we should also switch over the sky and reflection probes to HDR. This would improve visual consistency with Forward+ and increase the viability of HDR output for the Mobile renderer, but this needs its own proposal.

@clayjohn

clayjohn commented Sep 2, 2025

Copy link
Copy Markdown
Member Author

It's worth investigating for a future PR if we should also switch over the sky and reflection probes to HDR. This would improve visual consistency with Forward+ and increase the viability of HDR output for the Mobile renderer, but this needs its own proposal.

See the last paragraph in the PR description above

Reflections and sky still use LDR always since they can be shared between several Viewports and not all viewports necessarily have the same HDR2D setting. In the future we may want to consider making ReflectionProbes and Sky always use HDR. But that decision is out of scope for this PR.

@beicause

This comment was marked as off-topic.

Comment thread servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp Outdated
@allenwp

allenwp commented Sep 21, 2025

Copy link
Copy Markdown
Contributor

I'm actually not immediately sure why from glancing at the code changes, but this PR breaks debanding in the following configuration:

  • Mobile renderer
  • SMAA antialiasing
  • HDR 2D disabled

View these screenshots in a dark viewing environment at 100% scaling:

Godot 4.5 This PR
godot-4 5 this-pr

MRP: mobile-hdr-2d-debanding.zip

SMAA causes the first tonemap pass to match the scene rendering buffer format, which is 10-bit when HDR 2D is disabled, so 10-bit debanding in the tonemap shader is required for this configuration.

The code that detects what buffer format should be used for debanding makes a lot of assumptions about data formats because the exact format of a given buffer isn't really saved in an accessible way for easy access. It's possible that the debanding code now thinks that this configuration is using a 16 bit buffer for even though it is actually using a 10 bit buffer?

Edit: Sorry, some of what I wrote in the first pass of this comment wasn't quite right... I think I've corrected it(?) To be honest, I need to dig deep into this every time I try and think about it because it's a little complicated to keep track of the different buffer formats used through the different passes with each renderer and HDR 2D configuration 😵‍💫

@clayjohn

Copy link
Copy Markdown
Member Author

@allenwp I think I may have fixed that issue in the last rebase when I fixed the conflicts. I can't repro that issue right now. Your MRP looks totally fine and matches the behaviour in Godot 4.5

Screenshot 2025-10-20 at 9 08 58 PM

This is necessary for Environment effects like Glow to work correctly.
@Repiteo Repiteo merged commit ec62f12 into godotengine:master Oct 22, 2025
20 checks passed
@Repiteo

Repiteo commented Oct 22, 2025

Copy link
Copy Markdown
Contributor

Thanks!

@allenwp

allenwp commented Oct 22, 2025

Copy link
Copy Markdown
Contributor

@allenwp I think I may have fixed that issue in the last rebase when I fixed the conflicts. I can't repro that issue right now. Your MRP looks totally fine and matches the behaviour in Godot 4.5

Just got around to testing this and reviewing the updated PR that was merged: yes, this looks good! Thanks!

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

Projects

None yet

6 participants