You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Optimize glow and tonemap gather step in the mobile renderer
Mobile devices are typically bandwidth bound which means we need to do as few texture samples as possible. They typically use TBDR GPUs which means that all rendering takes place on special optimized tiles. As a side effect, reading back memory from tile to VRAM is really slow, especially on Mali devices. This commit uses a technique where you do a small blur while downsampling, and then another small blur while upsampling to get really high quality glow. While this doesn't reduce the renderpass count very much, it does reduce the texture read bandwidth by almost 10 times. Overall glow was more texture-read bound than memory write, bound, so this was a huge win. A side effect of this new technique is that we can gather the glow as we upsample instead of gathering the glow in the final tonemap pass. Doing so allows us to significantly reduce the cost of the tonemap pass as well.
This commit is contained in:
@@ -568,58 +568,99 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
int max_glow_level = -1;
|
||||
|
||||
if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
|
||||
RENDER_TIMESTAMP("Glow");
|
||||
RD::get_singleton()->draw_command_begin_label("Gaussian Glow");
|
||||
|
||||
rb->allocate_blur_textures();
|
||||
|
||||
int mipmaps = int(rb->get_texture_format(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1).mipmaps);
|
||||
Vector<float> glow_levels = environment_get_glow_levels(p_render_data->environment);
|
||||
bool use_debanding = rb->get_use_debanding() && !texture_storage->render_target_is_using_hdr(render_target);
|
||||
|
||||
int max_glow_index = -1;
|
||||
int min_glow_level = RS::MAX_GLOW_LEVELS;
|
||||
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
|
||||
if (environment_get_glow_levels(p_render_data->environment)[i] > 0.0) {
|
||||
int mipmaps = int(rb->get_texture_format(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1).mipmaps);
|
||||
if (i >= mipmaps) {
|
||||
max_glow_level = mipmaps - 1;
|
||||
} else {
|
||||
max_glow_level = i;
|
||||
}
|
||||
if (glow_levels[i] > 0.01) {
|
||||
max_glow_index = MAX(max_glow_index, i);
|
||||
min_glow_level = MIN(min_glow_level, i);
|
||||
}
|
||||
}
|
||||
|
||||
max_glow_index = MIN(max_glow_index, mipmaps - 1);
|
||||
|
||||
float luminance_multiplier = rb->get_luminance_multiplier();
|
||||
for (uint32_t l = 0; l < rb->get_view_count(); l++) {
|
||||
for (int i = 0; i < (max_glow_level + 1); i++) {
|
||||
Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, i);
|
||||
if (can_use_storage) {
|
||||
RD::get_singleton()->draw_command_begin_label("Gaussian Glow");
|
||||
RID luminance_texture;
|
||||
if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) {
|
||||
luminance_texture = luminance->get_current_luminance_buffer(rb); // this will return and empty RID if we don't have an auto exposure buffer
|
||||
}
|
||||
for (uint32_t l = 0; l < rb->get_view_count(); l++) {
|
||||
Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0);
|
||||
RID source = rb->get_internal_texture(l);
|
||||
RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, 0);
|
||||
copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale);
|
||||
|
||||
if (i == 0) {
|
||||
RID luminance_texture;
|
||||
if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) {
|
||||
luminance_texture = luminance->get_current_luminance_buffer(rb); // this will return and empty RID if we don't have an auto exposure buffer
|
||||
}
|
||||
RID source = rb->get_internal_texture(l);
|
||||
RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
|
||||
if (can_use_storage) {
|
||||
copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale);
|
||||
} else {
|
||||
RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view
|
||||
copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale);
|
||||
}
|
||||
} else {
|
||||
RID source = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i - 1);
|
||||
RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
|
||||
|
||||
if (can_use_storage) {
|
||||
copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment));
|
||||
} else {
|
||||
RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view
|
||||
copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment));
|
||||
}
|
||||
for (int i = 1; i < (max_glow_index + 1); i++) {
|
||||
source = dest;
|
||||
vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, i);
|
||||
dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
|
||||
copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment));
|
||||
}
|
||||
}
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
} else {
|
||||
// For the mobile renderer we blur down and up the mip chain. Which works out to (2*level-1) passes. This
|
||||
// allows us to gather our levels at low resolutions and ultimately save a lot of texture read bandwidth.
|
||||
// The tradeoff is that we need to use single-pass blur to minimize the number of render passes.
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
RID source;
|
||||
RID dest;
|
||||
|
||||
for (uint32_t l = 0; l < rb->get_view_count(); l++) {
|
||||
RD::get_singleton()->draw_command_begin_label("Gaussian Glow downsample");
|
||||
|
||||
Size2i source_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_COLOR, 0);
|
||||
|
||||
source = rb->get_internal_texture(l);
|
||||
dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, 1); // Level 1 is quarter res.
|
||||
|
||||
copy_effects->gaussian_glow_downsample_raster(source, dest, luminance_multiplier, source_size, environment_get_glow_strength(p_render_data->environment), true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment));
|
||||
|
||||
Size2i vp_size;
|
||||
for (int i = 1; i < (max_glow_index + 1); i++) {
|
||||
source = dest;
|
||||
vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, i);
|
||||
dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i + 1);
|
||||
|
||||
copy_effects->gaussian_glow_downsample_raster(source, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment));
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
RD::get_singleton()->draw_command_begin_label("Gaussian Glow upsample");
|
||||
|
||||
if (max_glow_index <= 0) {
|
||||
// Only layer 1 is visible, just copy over.
|
||||
source = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); // Technically a waste, but oh well. I'm not optimizing for the case of only level 1.
|
||||
vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 2); // RB_TEX_BLUR_0 is double the size of RB_TEX_BLUR_1, so go up a mip level.
|
||||
dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, l, 2);
|
||||
RID blend_tex = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, 1);
|
||||
source_size = vp_size;
|
||||
|
||||
copy_effects->gaussian_glow_upsample_raster(source, dest, blend_tex, luminance_multiplier, source_size, vp_size, glow_levels[0], 0.0, use_debanding);
|
||||
}
|
||||
|
||||
for (int i = max_glow_index - 1; i >= 0; i--) {
|
||||
source = dest;
|
||||
source_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, i + 3);
|
||||
vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, i + 2); // RB_TEX_BLUR_0 is double the size of RB_TEX_BLUR_1, so go up a mip level.
|
||||
dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, l, i + 2);
|
||||
RID blend_tex = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i + 1);
|
||||
|
||||
copy_effects->gaussian_glow_upsample_raster(source, dest, blend_tex, luminance_multiplier, source_size, vp_size, glow_levels[i], i == (max_glow_index - 1) ? glow_levels[i + 1] : 1.0, use_debanding);
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -640,8 +681,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
|
||||
if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
|
||||
tonemap.use_glow = true;
|
||||
tonemap.glow_mode = RendererRD::ToneMapper::TonemapSettings::GlowMode(environment_get_glow_blend_mode(p_render_data->environment));
|
||||
tonemap.glow_intensity = environment_get_glow_blend_mode(p_render_data->environment) == RS::ENV_GLOW_BLEND_MODE_MIX ? environment_get_glow_mix(p_render_data->environment) : environment_get_glow_intensity(p_render_data->environment);
|
||||
tonemap.glow_mode = environment_get_glow_blend_mode(p_render_data->environment);
|
||||
tonemap.glow_intensity = tonemap.glow_mode == RS::ENV_GLOW_BLEND_MODE_MIX ? environment_get_glow_mix(p_render_data->environment) : environment_get_glow_intensity(p_render_data->environment);
|
||||
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
|
||||
tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i];
|
||||
}
|
||||
@@ -650,7 +691,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
tonemap.glow_texture_size.x = msize.width;
|
||||
tonemap.glow_texture_size.y = msize.height;
|
||||
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;
|
||||
tonemap.glow_texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1);
|
||||
|
||||
if (can_use_storage) {
|
||||
tonemap.glow_texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1);
|
||||
} else {
|
||||
tonemap.glow_texture = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 2, rb->get_view_count());
|
||||
}
|
||||
|
||||
if (environment_get_glow_map(p_render_data->environment).is_valid()) {
|
||||
tonemap.glow_map_strength = environment_get_glow_map_strength(p_render_data->environment);
|
||||
tonemap.glow_map = texture_storage->texture_get_rd_texture(environment_get_glow_map(p_render_data->environment));
|
||||
@@ -698,24 +745,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
|
||||
RID dest_fb;
|
||||
RD::DataFormat dest_fb_format;
|
||||
RD::DataFormat format_for_debanding;
|
||||
if (spatial_upscaler != nullptr || use_smaa) {
|
||||
// If we use a spatial upscaler to upscale or SMAA to antialias we need to write our result into an intermediate buffer.
|
||||
// Note that this is cached so we only create the texture the first time.
|
||||
dest_fb_format = rb->get_base_data_format();
|
||||
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);
|
||||
dest_fb = FramebufferCacheRD::get_singleton()->get_cache(dest_texture);
|
||||
if (use_smaa) {
|
||||
format_for_debanding = dest_fb_format;
|
||||
} else {
|
||||
// Debanding is currently not supported when using spatial upscaling, so apply it before scaling.
|
||||
// This produces suboptimal results because the image will be modified by spatial upscaling after
|
||||
// debanding has been applied. Ideally, debanding should be applied as the final step before quantization
|
||||
// to integer values, but in the case of MetalFX, it may not be worth the performance cost of creating a new
|
||||
// intermediate buffer. In the case of FSR 1.0, the work of adding debanding support hasn't been done yet.
|
||||
// Assume that the DataFormat that will be used by spatial_upscaler is the same as render_target_get_color_format.
|
||||
format_for_debanding = texture_storage->render_target_get_color_format(using_hdr, tonemap.convert_to_srgb);
|
||||
}
|
||||
tonemap.dest_texture_size = rb->get_internal_size();
|
||||
} else {
|
||||
// If we do a bilinear upscale we just render into our render target and our shader will upscale automatically.
|
||||
// Target size in this case is lying as we never get our real target size communicated.
|
||||
@@ -723,30 +759,27 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
|
||||
if (dest_is_msaa_2d) {
|
||||
dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target));
|
||||
// Assume that the DataFormat of render_target_get_rd_texture_msaa is the same as render_target_get_color_format.
|
||||
format_for_debanding = texture_storage->render_target_get_color_format(using_hdr, tonemap.convert_to_srgb);
|
||||
texture_storage->render_target_set_msaa_needs_resolve(render_target, true); // Make sure this gets resolved.
|
||||
} else {
|
||||
dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
|
||||
// Assume that the DataFormat of render_target_get_rd_framebuffer is the same as render_target_get_color_format.
|
||||
format_for_debanding = texture_storage->render_target_get_color_format(using_hdr, tonemap.convert_to_srgb);
|
||||
}
|
||||
tonemap.dest_texture_size = texture_storage->render_target_get_size(render_target);
|
||||
}
|
||||
|
||||
if (rb->get_use_debanding()) {
|
||||
if (_is_8bit_data_format(format_for_debanding)) {
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_8_BIT;
|
||||
} else if (_is_10bit_data_format(format_for_debanding)) {
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_DISABLED;
|
||||
if (rb->get_use_debanding() && !using_hdr) {
|
||||
if (!can_use_storage && (use_smaa || spatial_upscaler)) {
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_10_BIT;
|
||||
} else {
|
||||
// In this case, debanding will be handled later when quantizing to an integer data format. (During blit or SMAA, for example.)
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_DISABLED;
|
||||
} else if (!(use_smaa || spatial_upscaler)) {
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_8_BIT;
|
||||
}
|
||||
} else {
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_DISABLED;
|
||||
}
|
||||
|
||||
tone_mapper->tonemapper(color_texture, dest_fb, tonemap);
|
||||
if (can_use_storage) {
|
||||
tone_mapper->tonemapper(color_texture, dest_fb, tonemap);
|
||||
} else {
|
||||
tone_mapper->tonemapper_mobile(color_texture, dest_fb, tonemap);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
@@ -756,6 +789,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
RD::get_singleton()->draw_command_begin_label("SMAA");
|
||||
|
||||
bool using_hdr = texture_storage->render_target_is_using_hdr(render_target);
|
||||
|
||||
RID dest_fb;
|
||||
if (spatial_upscaler) {
|
||||
rb->create_texture(SNAME("SMAA"), SNAME("destination"), rb->get_base_data_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);
|
||||
@@ -765,79 +799,31 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
RID source_texture = rb->get_texture_slice(SNAME("Tonemapper"), SNAME("destination"), v, 0);
|
||||
|
||||
RID dest_texture;
|
||||
RD::DataFormat format_for_debanding;
|
||||
if (spatial_upscaler) {
|
||||
dest_texture = rb->get_texture_slice(SNAME("SMAA"), SNAME("destination"), v, 0);
|
||||
// Debanding is currently not supported when using spatial upscaling, so apply it before scaling.
|
||||
// This produces suboptimal results because the image will be modified by spatial upscaling after
|
||||
// debanding has been applied. Ideally, debanding should be applied as the final step before quantization
|
||||
// to integer values, but in the case of MetalFX, it may not be worth the performance cost of creating a new
|
||||
// intermediate buffer. In the case of FSR 1.0, the work of adding debanding support hasn't been done yet.
|
||||
// Assume that the DataFormat that will be used by spatial_upscaler is the same as render_target_get_color_format.
|
||||
format_for_debanding = texture_storage->render_target_get_color_format(using_hdr, !using_hdr);
|
||||
} else {
|
||||
dest_texture = texture_storage->render_target_get_rd_texture_slice(render_target, v);
|
||||
// Assume that the DataFormat is the same as render_target_get_color_format.
|
||||
format_for_debanding = texture_storage->render_target_get_color_format(using_hdr, !using_hdr);
|
||||
}
|
||||
dest_fb = FramebufferCacheRD::get_singleton()->get_cache(dest_texture);
|
||||
|
||||
if (rb->get_use_debanding()) {
|
||||
if (_is_8bit_data_format(format_for_debanding)) {
|
||||
smaa->debanding_mode = RendererRD::SMAA::DebandingMode::DEBANDING_MODE_8_BIT;
|
||||
} else if (_is_10bit_data_format(format_for_debanding)) {
|
||||
smaa->debanding_mode = RendererRD::SMAA::DebandingMode::DEBANDING_MODE_10_BIT;
|
||||
} else {
|
||||
// In this case, debanding will be handled later when quantizing to an integer data format. (During blit, for example.)
|
||||
smaa->debanding_mode = RendererRD::SMAA::DebandingMode::DEBANDING_MODE_DISABLED;
|
||||
}
|
||||
} else {
|
||||
smaa->debanding_mode = RendererRD::SMAA::DebandingMode::DEBANDING_MODE_DISABLED;
|
||||
}
|
||||
|
||||
smaa->process(rb, source_texture, dest_fb);
|
||||
smaa->process(rb, source_texture, dest_fb, rb->get_use_debanding() && !using_hdr);
|
||||
}
|
||||
} else {
|
||||
RID source_texture = rb->get_texture(SNAME("Tonemapper"), SNAME("destination"));
|
||||
RD::DataFormat format_for_debanding;
|
||||
|
||||
if (spatial_upscaler) {
|
||||
RID dest_texture = rb->create_texture(SNAME("SMAA"), SNAME("destination"), rb->get_base_data_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);
|
||||
dest_fb = FramebufferCacheRD::get_singleton()->get_cache(dest_texture);
|
||||
// Debanding is currently not supported when using spatial upscaling, so apply it before scaling.
|
||||
// This produces suboptimal results because the image will be modified by spatial upscaling after
|
||||
// debanding has been applied. Ideally, debanding should be applied as the final step before quantization
|
||||
// to integer values, but in the case of MetalFX, it may not be worth the performance cost of creating a new
|
||||
// intermediate buffer. In the case of FSR 1.0, the work of adding debanding support hasn't been done yet.
|
||||
// Assume that the DataFormat that will be used by spatial_upscaler is the same as render_target_get_color_format.
|
||||
format_for_debanding = texture_storage->render_target_get_color_format(using_hdr, !using_hdr);
|
||||
} else {
|
||||
if (dest_is_msaa_2d) {
|
||||
dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target));
|
||||
// Assume that the DataFormat of render_target_get_rd_texture_msaa is the same as render_target_get_color_format.
|
||||
format_for_debanding = texture_storage->render_target_get_color_format(using_hdr, !using_hdr);
|
||||
texture_storage->render_target_set_msaa_needs_resolve(render_target, true); // Make sure this gets resolved.
|
||||
} else {
|
||||
dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
|
||||
// Assume that the DataFormat of render_target_get_rd_framebuffer is the same as render_target_get_color_format.
|
||||
format_for_debanding = texture_storage->render_target_get_color_format(using_hdr, !using_hdr);
|
||||
}
|
||||
}
|
||||
|
||||
if (rb->get_use_debanding()) {
|
||||
if (_is_8bit_data_format(format_for_debanding)) {
|
||||
smaa->debanding_mode = RendererRD::SMAA::DebandingMode::DEBANDING_MODE_8_BIT;
|
||||
} else if (_is_10bit_data_format(format_for_debanding)) {
|
||||
smaa->debanding_mode = RendererRD::SMAA::DebandingMode::DEBANDING_MODE_10_BIT;
|
||||
} else {
|
||||
// In this case, debanding will be handled later when quantizing to an integer data format. (During blit, for example.)
|
||||
smaa->debanding_mode = RendererRD::SMAA::DebandingMode::DEBANDING_MODE_DISABLED;
|
||||
}
|
||||
} else {
|
||||
smaa->debanding_mode = RendererRD::SMAA::DebandingMode::DEBANDING_MODE_DISABLED;
|
||||
}
|
||||
|
||||
smaa->process(rb, source_texture, dest_fb);
|
||||
smaa->process(rb, source_texture, dest_fb, rb->get_use_debanding() && !using_hdr);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
@@ -939,21 +925,12 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
|
||||
tonemap.view_count = rb->get_view_count();
|
||||
|
||||
if (rb->get_use_debanding()) {
|
||||
// Assume that the DataFormat of p_framebuffer is the same as render_target_get_color_format.
|
||||
RD::DataFormat dest_fb_format = texture_storage->render_target_get_color_format(using_hdr, tonemap.convert_to_srgb);
|
||||
if (dest_fb_format >= RD::DATA_FORMAT_R8_UNORM && dest_fb_format <= RD::DATA_FORMAT_A8B8G8R8_SRGB_PACK32) {
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_8_BIT;
|
||||
} else if (dest_fb_format >= RD::DATA_FORMAT_A2R10G10B10_UNORM_PACK32 && dest_fb_format <= RD::DATA_FORMAT_A2B10G10R10_SINT_PACK32) {
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_10_BIT;
|
||||
} else {
|
||||
// In this case, debanding will be handled later when quantizing to an integer data format. (During blit, for example.)
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_DISABLED;
|
||||
}
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_8_BIT;
|
||||
} else {
|
||||
tonemap.debanding_mode = RendererRD::ToneMapper::TonemapSettings::DebandingMode::DEBANDING_MODE_DISABLED;
|
||||
}
|
||||
|
||||
tone_mapper->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
|
||||
tone_mapper->tonemapper_subpass(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
@@ -1714,7 +1691,7 @@ void RendererSceneRenderRD::init() {
|
||||
debug_effects = memnew(RendererRD::DebugEffects);
|
||||
luminance = memnew(RendererRD::Luminance(!can_use_storage));
|
||||
smaa = memnew(RendererRD::SMAA);
|
||||
tone_mapper = memnew(RendererRD::ToneMapper);
|
||||
tone_mapper = memnew(RendererRD::ToneMapper(!can_use_storage));
|
||||
if (can_use_vrs) {
|
||||
vrs = memnew(RendererRD::VRS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user