Skip 2D rendering if stereo enabled and fix MSAA2D with 3D issue.

This commit is contained in:
Bastiaan Olij 2023-10-20 10:51:48 +11:00
parent f8818f85e6
commit 425e943576
3 changed files with 52 additions and 26 deletions

View File

@ -235,7 +235,7 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
RID render_target = render_buffers->get_render_target();
ERR_FAIL_COND_V(render_target.is_null(), RID());
RID target_buffer;
if (texture_storage->render_target_get_msaa(render_target) == RS::VIEWPORT_MSAA_DISABLED) {
if (view_count > 1 || texture_storage->render_target_get_msaa(render_target) == RS::VIEWPORT_MSAA_DISABLED) {
target_buffer = texture_storage->render_target_get_rd_texture(render_target);
} else {
target_buffer = texture_storage->render_target_get_rd_texture_msaa(render_target);

View File

@ -351,6 +351,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RID color_texture = use_upscaled_texture ? rb->get_upscaled_texture() : rb->get_internal_texture();
Size2i color_size = use_upscaled_texture ? target_size : rb->get_internal_size();
bool dest_is_msaa_2d = rb->get_view_count() == 1 && texture_storage->render_target_get_msaa(render_target) != RS::VIEWPORT_MSAA_DISABLED;
if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes)) {
RENDER_TIMESTAMP("Depth of Field");
RD::get_singleton()->draw_command_begin_label("DOF");
@ -567,7 +569,12 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
// 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.
// Bit nasty but...
dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
if (dest_is_msaa_2d) {
dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target));
} else {
dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
}
}
tone_mapper->tonemapper(color_texture, dest_fb, tonemap);
@ -585,6 +592,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
fsr->fsr_upscale(rb, source_texture, dest_texture);
}
if (dest_is_msaa_2d) {
// We can't upscale directly into our MSAA buffer so we need to do a copy
RID source_texture = texture_storage->render_target_get_rd_texture(render_target);
RID dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target));
copy_effects->copy_to_fb_rect(source_texture, dest_fb, Rect2i(Point2i(), rb->get_target_size()));
}
RD::get_singleton()->draw_command_end_label();
}

View File

@ -116,19 +116,30 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
p_viewport->render_buffers.unref();
} else {
const float EPSILON = 0.0001;
float scaling_3d_scale = p_viewport->scaling_3d_scale;
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
bool upscaler_available = p_viewport->fsr_enabled;
if ((!upscaler_available || scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_BILINEAR || scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && scaling_3d_scale >= (1.0 - EPSILON) && scaling_3d_scale <= (1.0 + EPSILON)) {
// No 3D scaling on bilinear or FSR? Ignore scaling mode, this just introduces overhead.
// - Mobile can't perform optimal path
// - FSR does an extra pass (or 2 extra passes if 2D-MSAA is enabled)
// Scaling = 1.0 on FSR2 has benefits
scaling_3d_scale = 1.0;
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
}
bool scaling_3d_is_fsr = (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) || (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2);
bool use_taa = p_viewport->use_taa;
if (scaling_3d_is_fsr && (scaling_3d_scale > 1.0)) {
if (scaling_3d_is_fsr && (scaling_3d_scale >= (1.0 + EPSILON))) {
// FSR is not designed for downsampling.
// Fall back to bilinear scaling.
WARN_PRINT_ONCE("FSR 3D resolution scaling is not designed for downsampling. Falling back to bilinear 3D resolution scaling.");
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
}
bool upscaler_available = p_viewport->fsr_enabled;
if (scaling_3d_is_fsr && !upscaler_available) {
// FSR is not actually available.
// Fall back to bilinear scaling.
@ -143,8 +154,8 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
use_taa = false;
}
int width;
int height;
int target_width;
int target_height;
int render_width;
int render_height;
@ -152,40 +163,40 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR:
// Clamp 3D rendering resolution to reasonable values supported on most hardware.
// This prevents freezing the engine or outright crashing on lower-end GPUs.
width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384);
height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384);
render_width = width;
render_height = height;
target_width = p_viewport->size.width;
target_height = p_viewport->size.height;
render_width = CLAMP(target_width * scaling_3d_scale, 1, 16384);
render_height = CLAMP(target_height * scaling_3d_scale, 1, 16384);
break;
case RS::VIEWPORT_SCALING_3D_MODE_FSR:
case RS::VIEWPORT_SCALING_3D_MODE_FSR2:
width = p_viewport->size.width;
height = p_viewport->size.height;
render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling)
render_height = MAX(height * scaling_3d_scale, 1.0);
target_width = p_viewport->size.width;
target_height = p_viewport->size.height;
render_width = MAX(target_width * scaling_3d_scale, 1.0); // target_width / (target_width * scaling)
render_height = MAX(target_height * scaling_3d_scale, 1.0);
break;
case RS::VIEWPORT_SCALING_3D_MODE_OFF:
width = p_viewport->size.width;
height = p_viewport->size.height;
render_width = width;
render_height = height;
target_width = p_viewport->size.width;
target_height = p_viewport->size.height;
render_width = target_width;
render_height = target_height;
break;
default:
// This is an unknown mode.
WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode));
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
scaling_3d_scale = 1.0;
width = p_viewport->size.width;
height = p_viewport->size.height;
render_width = width;
render_height = height;
target_width = p_viewport->size.width;
target_height = p_viewport->size.height;
render_width = target_width;
render_height = target_height;
break;
}
uint32_t jitter_phase_count = 0;
if (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2) {
// Implementation has been copied from ffxFsr2GetJitterPhaseCount.
jitter_phase_count = uint32_t(8.0f * pow(float(width) / render_width, 2.0f));
jitter_phase_count = uint32_t(8.0f * pow(float(target_width) / render_width, 2.0f));
} else if (use_taa) {
// Default jitter count for TAA.
jitter_phase_count = 16;
@ -201,7 +212,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
RenderSceneBuffersConfiguration rb_config;
rb_config.set_render_target(p_viewport->render_target);
rb_config.set_internal_size(Size2i(render_width, render_height));
rb_config.set_target_size(Size2(width, height));
rb_config.set_target_size(Size2(target_width, target_height));
rb_config.set_view_count(p_viewport->view_count);
rb_config.set_scaling_3d_mode(scaling_3d_mode);
rb_config.set_msaa_3d(p_viewport->msaa_3d);
@ -259,6 +270,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
/* Camera should always be BEFORE any other 3D */
bool can_draw_2d = !p_viewport->disable_2d && p_viewport->view_count == 1; // Stereo rendering does not support 2D, no depth data
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
int scenario_canvas_max_layer = 0;
bool force_clear_render_target = false;
@ -272,7 +284,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (RSG::scene->is_scenario(p_viewport->scenario)) {
RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario);
if (RSG::scene->is_environment(environment)) {
if (!p_viewport->disable_2d && !viewport_is_environment_disabled(p_viewport)) {
if (can_draw_2d && !viewport_is_environment_disabled(p_viewport)) {
scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS;
scenario_canvas_max_layer = RSG::scene->environment_get_canvas_max_layer(environment);
} else if (RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS) {
@ -307,7 +319,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
_draw_3d(p_viewport);
}
if (!p_viewport->disable_2d) {
if (can_draw_2d) {
RBMap<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);