Skip to content

Commit 967e2d4

Browse files
committed
Merge pull request #108761 from allenwp/108757-fix-mobile-hdr2d-debanding
Fix debanding for Mobile rendering method with HDR 2D.
2 parents 598409b + a033656 commit 967e2d4

File tree

6 files changed

+83
-24
lines changed

6 files changed

+83
-24
lines changed

servers/rendering/renderer_rd/effects/tone_mapper.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,11 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
123123
tonemap.push_constant.flags |= p_settings.use_color_correction ? TONEMAP_FLAG_USE_COLOR_CORRECTION : 0;
124124

125125
tonemap.push_constant.flags |= p_settings.use_fxaa ? TONEMAP_FLAG_USE_FXAA : 0;
126-
// When convert_to_srgb is false: postpone debanding until convert_to_srgb is true (usually during blit).
127-
tonemap.push_constant.flags |= (p_settings.use_debanding && p_settings.convert_to_srgb) ? TONEMAP_FLAG_USE_DEBANDING : 0;
126+
if (p_settings.debanding_mode == TonemapSettings::DEBANDING_MODE_8_BIT) {
127+
tonemap.push_constant.flags |= TONEMAP_FLAG_USE_8_BIT_DEBANDING;
128+
} else if (p_settings.debanding_mode == TonemapSettings::DEBANDING_MODE_10_BIT) {
129+
tonemap.push_constant.flags |= TONEMAP_FLAG_USE_10_BIT_DEBANDING;
130+
}
128131
tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
129132
tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
130133

@@ -208,8 +211,11 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
208211
tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
209212

210213
tonemap.push_constant.flags |= p_settings.use_color_correction ? TONEMAP_FLAG_USE_COLOR_CORRECTION : 0;
211-
// When convert_to_srgb is false: postpone debanding until convert_to_srgb is true (usually during blit).
212-
tonemap.push_constant.flags |= (p_settings.use_debanding && p_settings.convert_to_srgb) ? TONEMAP_FLAG_USE_DEBANDING : 0;
214+
if (p_settings.debanding_mode == TonemapSettings::DEBANDING_MODE_8_BIT) {
215+
tonemap.push_constant.flags |= TONEMAP_FLAG_USE_8_BIT_DEBANDING;
216+
} else if (p_settings.debanding_mode == TonemapSettings::DEBANDING_MODE_10_BIT) {
217+
tonemap.push_constant.flags |= TONEMAP_FLAG_USE_10_BIT_DEBANDING;
218+
}
213219
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
214220

215221
tonemap.push_constant.flags |= p_settings.convert_to_srgb ? TONEMAP_FLAG_CONVERT_TO_SRGB : 0;

servers/rendering/renderer_rd/effects/tone_mapper.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ class ToneMapper {
6363
TONEMAP_FLAG_USE_AUTO_EXPOSURE = (1 << 2),
6464
TONEMAP_FLAG_USE_COLOR_CORRECTION = (1 << 3),
6565
TONEMAP_FLAG_USE_FXAA = (1 << 4),
66-
TONEMAP_FLAG_USE_DEBANDING = (1 << 5),
67-
TONEMAP_FLAG_CONVERT_TO_SRGB = (1 << 6),
66+
TONEMAP_FLAG_USE_8_BIT_DEBANDING = (1 << 5),
67+
TONEMAP_FLAG_USE_10_BIT_DEBANDING = (1 << 6),
68+
TONEMAP_FLAG_CONVERT_TO_SRGB = (1 << 7),
6869
};
6970

7071
struct TonemapPushConstant {
@@ -141,7 +142,12 @@ class ToneMapper {
141142
RID color_correction_texture;
142143

143144
bool use_fxaa = false;
144-
bool use_debanding = false;
145+
enum DebandingMode {
146+
DEBANDING_MODE_DISABLED,
147+
DEBANDING_MODE_8_BIT,
148+
DEBANDING_MODE_10_BIT,
149+
};
150+
DebandingMode debanding_mode = DEBANDING_MODE_DISABLED;
145151
Vector2i texture_size;
146152
uint32_t view_count = 1;
147153

servers/rendering/renderer_rd/renderer_compositor_rd.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
9696
blit.push_constant.upscale = p_render_targets[i].lens_distortion.upscale;
9797
blit.push_constant.aspect_ratio = p_render_targets[i].lens_distortion.aspect_ratio;
9898
blit.push_constant.convert_to_srgb = texture_storage->render_target_is_using_hdr(p_render_targets[i].render_target);
99-
// If convert_to_srgb is false, debanding was applied earlier (usually in tonemapping).
100-
blit.push_constant.use_debanding = uint32_t(blit.push_constant.convert_to_srgb && texture_storage->render_target_is_using_debanding(p_render_targets[i].render_target));
99+
blit.push_constant.use_debanding = texture_storage->render_target_is_using_debanding(p_render_targets[i].render_target);
101100

102101
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blit.push_constant, sizeof(BlitPushConstant));
103102
RD::get_singleton()->draw_list_draw(draw_list, true);

servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
615615

616616
RendererRD::ToneMapper::TonemapSettings tonemap;
617617

618+
bool using_hdr = texture_storage->render_target_is_using_hdr(render_target);
619+
618620
tonemap.exposure_texture = luminance->get_current_luminance_buffer(rb);
619621
if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && tonemap.exposure_texture.is_valid()) {
620622
tonemap.use_auto_exposure = true;
@@ -653,7 +655,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
653655
tonemap.use_fxaa = true;
654656
}
655657

656-
tonemap.use_debanding = rb->get_use_debanding();
657658
tonemap.texture_size = Vector2i(color_size.x, color_size.y);
658659

659660
if (p_render_data->environment.is_valid()) {
@@ -665,7 +666,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
665666
tonemap.use_color_correction = false;
666667
tonemap.use_1d_color_correction = false;
667668
tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
668-
tonemap.convert_to_srgb = !texture_storage->render_target_is_using_hdr(render_target);
669+
tonemap.convert_to_srgb = !using_hdr;
669670

670671
if (can_use_effects && p_render_data->environment.is_valid()) {
671672
tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment);
@@ -683,24 +684,43 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
683684
tonemap.view_count = rb->get_view_count();
684685

685686
RID dest_fb;
687+
RD::DataFormat dest_fb_format;
686688
if (spatial_upscaler != nullptr || use_smaa) {
687689
// If we use a spatial upscaler to upscale or SMAA to antialias we need to write our result into an intermediate buffer.
688690
// Note that this is cached so we only create the texture the first time.
689-
RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT, RD::TEXTURE_SAMPLES_1, Size2i(), 0, 1, true, true);
691+
dest_fb_format = _render_buffers_get_color_format();
692+
RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), dest_fb_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT, RD::TEXTURE_SAMPLES_1, Size2i(), 0, 1, true, true);
690693
dest_fb = FramebufferCacheRD::get_singleton()->get_cache(dest_texture);
691694
} else {
692695
// If we do a bilinear upscale we just render into our render target and our shader will upscale automatically.
693696
// Target size in this case is lying as we never get our real target size communicated.
694697
// Bit nasty but...
695698

696699
if (dest_is_msaa_2d) {
700+
// Assume that the DataFormat of render_target_get_rd_texture_msaa is the same as render_target_get_color_format.
701+
dest_fb_format = texture_storage->render_target_get_color_format(using_hdr, tonemap.convert_to_srgb);
697702
dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target));
698703
texture_storage->render_target_set_msaa_needs_resolve(render_target, true); // Make sure this gets resolved.
699704
} else {
705+
// Assume that the DataFormat of render_target_get_rd_framebuffer is the same as render_target_get_color_format.
706+
dest_fb_format = texture_storage->render_target_get_color_format(using_hdr, tonemap.convert_to_srgb);
700707
dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
701708
}
702709
}
703710

711+
if (rb->get_use_debanding()) {
712+
if (dest_fb_format >= RD::DATA_FORMAT_R8_UNORM && dest_fb_format <= RD::DATA_FORMAT_A8B8G8R8_SRGB_PACK32) {
713+
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_8_BIT;
714+
} else if (dest_fb_format >= RD::DATA_FORMAT_A2R10G10B10_UNORM_PACK32 && dest_fb_format <= RD::DATA_FORMAT_A2B10G10R10_SINT_PACK32) {
715+
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_10_BIT;
716+
} else {
717+
// In this case, debanding will be handled later when quantizing to an integer data format. (During blit, for example.)
718+
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_DISABLED;
719+
}
720+
} else {
721+
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_DISABLED;
722+
}
723+
704724
tone_mapper->tonemapper(color_texture, dest_fb, tonemap);
705725

706726
RD::get_singleton()->draw_command_end_label();
@@ -814,6 +834,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
814834
ERR_FAIL_MSG("Auto Exposure is not supported when using subpasses.");
815835
}
816836

837+
bool using_hdr = texture_storage->render_target_is_using_hdr(rb->get_render_target());
838+
817839
tonemap.use_glow = false;
818840
tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
819841
tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
@@ -823,7 +845,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
823845
tonemap.use_color_correction = false;
824846
tonemap.use_1d_color_correction = false;
825847
tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
826-
tonemap.convert_to_srgb = !texture_storage->render_target_is_using_hdr(rb->get_render_target());
848+
tonemap.convert_to_srgb = !using_hdr;
827849

828850
if (can_use_effects && p_render_data->environment.is_valid()) {
829851
tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment);
@@ -837,12 +859,26 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
837859
}
838860
}
839861

840-
tonemap.use_debanding = rb->get_use_debanding();
841862
tonemap.texture_size = Vector2i(target_size.x, target_size.y);
842863

843864
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
844865
tonemap.view_count = rb->get_view_count();
845866

867+
if (rb->get_use_debanding()) {
868+
// Assume that the DataFormat of p_framebuffer is the same as render_target_get_color_format.
869+
RD::DataFormat dest_fb_format = texture_storage->render_target_get_color_format(using_hdr, tonemap.convert_to_srgb);
870+
if (dest_fb_format >= RD::DATA_FORMAT_R8_UNORM && dest_fb_format <= RD::DATA_FORMAT_A8B8G8R8_SRGB_PACK32) {
871+
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_8_BIT;
872+
} else if (dest_fb_format >= RD::DATA_FORMAT_A2R10G10B10_UNORM_PACK32 && dest_fb_format <= RD::DATA_FORMAT_A2B10G10R10_SINT_PACK32) {
873+
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_10_BIT;
874+
} else {
875+
// In this case, debanding will be handled later when quantizing to an integer data format. (During blit, for example.)
876+
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_DISABLED;
877+
}
878+
} else {
879+
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_DISABLED;
880+
}
881+
846882
tone_mapper->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
847883

848884
RD::get_singleton()->draw_command_end_label();

servers/rendering/renderer_rd/shaders/blit.glsl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,17 @@ void main() {
135135

136136
if (data.convert_to_srgb) {
137137
color.rgb = linear_to_srgb(color.rgb); // Regular linear -> SRGB conversion.
138-
// When convert_to_srgb is true, debanding was skipped in tonemap.glsl.
138+
139+
// Even if debanding was applied earlier in the rendering process, it must
140+
// be reapplied after the linear_to_srgb floating point operations.
141+
// When the linear_to_srgb operation was not performed, the source is
142+
// already an 8-bit format and debanding cannot be effective. In this
143+
// case, GPU driver rounding error can add noise so debanding should be
144+
// skipped entirely.
139145
if (data.use_debanding) {
140146
color.rgb += screen_space_dither(gl_FragCoord.xy);
141147
}
148+
142149
color.rgb = clamp(color.rgb, vec3(0.0), vec3(1.0));
143150
}
144151
}

servers/rendering/renderer_rd/shaders/effects/tonemap.glsl

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ layout(set = 3, binding = 0) uniform sampler3D source_color_correction;
6565
#define FLAG_USE_AUTO_EXPOSURE (1 << 2)
6666
#define FLAG_USE_COLOR_CORRECTION (1 << 3)
6767
#define FLAG_USE_FXAA (1 << 4)
68-
#define FLAG_USE_DEBANDING (1 << 5)
69-
#define FLAG_CONVERT_TO_SRGB (1 << 6)
68+
#define FLAG_USE_8_BIT_DEBANDING (1 << 5)
69+
#define FLAG_USE_10_BIT_DEBANDING (1 << 6)
70+
#define FLAG_CONVERT_TO_SRGB (1 << 7)
7071

7172
layout(push_constant, std430) uniform Params {
7273
vec3 bcs;
@@ -819,16 +820,15 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
819820
// NOTE: `frag_coord` is in pixels (i.e. not normalized UV).
820821
// This dithering must be applied after encoding changes (linear/nonlinear) have been applied
821822
// as the final step before quantization from floating point to integer values.
822-
vec3 screen_space_dither(vec2 frag_coord) {
823+
vec3 screen_space_dither(vec2 frag_coord, float bit_alignment_diviser) {
823824
// Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR.
824825
// Removed the time component to avoid passing time into this shader.
825826
vec3 dither = vec3(dot(vec2(171.0, 231.0), frag_coord));
826827
dither.rgb = fract(dither.rgb / vec3(103.0, 71.0, 97.0));
827828

828829
// Subtract 0.5 to avoid slightly brightening the whole viewport.
829830
// Use a dither strength of 100% rather than the 37.5% suggested by the original source.
830-
// Divide by 255 to align to 8-bit quantization.
831-
return (dither.rgb - 0.5) / 255.0;
831+
return (dither.rgb - 0.5) / bit_alignment_diviser;
832832
}
833833

834834
void main() {
@@ -910,10 +910,15 @@ void main() {
910910
// linear because the color correction texture sampling does this for us.
911911
}
912912

913-
if (bool(params.flags & FLAG_USE_DEBANDING)) {
914-
// Debanding should be done at the end of tonemapping, but before writing to the LDR buffer.
915-
// Otherwise, we're adding noise to an already-quantized image.
916-
color.rgb += screen_space_dither(gl_FragCoord.xy);
913+
// Debanding should be done at the end of tonemapping, but before writing to the LDR buffer.
914+
// Otherwise, we're adding noise to an already-quantized image.
915+
916+
if (bool(params.flags & FLAG_USE_8_BIT_DEBANDING)) {
917+
// Divide by 255 to align to 8-bit quantization.
918+
color.rgb += screen_space_dither(gl_FragCoord.xy, 255.0);
919+
} else if (bool(params.flags & FLAG_USE_10_BIT_DEBANDING)) {
920+
// Divide by 1023 to align to 10-bit quantization.
921+
color.rgb += screen_space_dither(gl_FragCoord.xy, 1023.0);
917922
}
918923

919924
frag_color = color;

0 commit comments

Comments
 (0)