Browse Source

Merge pull request #71309 from BastiaanOlij/improve_renderscaling_options

Improving communication of scaling settings to renderer implementation
Rémi Verschelde 2 years ago
parent
commit
ac104a69b8

+ 2 - 1
drivers/gles3/storage/render_scene_buffers_gles3.cpp

@@ -37,13 +37,14 @@ RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
 	free_render_buffer_data();
 }
 
-void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
 	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
 
 	//internal_size.x = p_internal_size.x; // ignore for now
 	//internal_size.y = p_internal_size.y;
 	width = p_target_size.x;
 	height = p_target_size.y;
+	//scaling_3d_mode = p_scaling_3d_mode
 	//fsr_sharpness = p_fsr_sharpness;
 	//texture_mipmap_bias = p_texture_mipmap_bias;
 	render_target = p_render_target;

+ 1 - 1
drivers/gles3/storage/render_scene_buffers_gles3.h

@@ -81,7 +81,7 @@ public:
 private:
 public:
 	virtual ~RenderSceneBuffersGLES3();
-	virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+	virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
 
 	virtual void set_fsr_sharpness(float p_fsr_sharpness) override{};
 	virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override{};

+ 11 - 5
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

@@ -251,7 +251,7 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
 			Size2i target_size = render_buffers->get_target_size();
 			Size2i internal_size = render_buffers->get_internal_size();
 
-			// can't do our blit pass if resolutions don't match
+			// can't do our blit pass if resolutions don't match, this should already have been checked.
 			ERR_FAIL_COND_V(target_size != internal_size, RID());
 
 			// - opaque pass
@@ -715,20 +715,26 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 		// setup rendering to render buffer
 		screen_size = p_render_data->render_buffers->get_internal_size();
 
-		if (rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) {
-			// can't do blit subpass
+		if (rb->get_scaling_3d_mode() != RS::VIEWPORT_SCALING_3D_MODE_OFF) {
+			// can't do blit subpass because we're scaling
 			using_subpass_post_process = false;
 		} else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) {
-			// can't do blit subpass
+			// can't do blit subpass because we're using post processes
 			using_subpass_post_process = false;
 		}
 
 		if (scene_state.used_screen_texture || scene_state.used_depth_texture) {
-			// can't use our last two subpasses
+			// can't use our last two subpasses because we're reading from screen texture or depth texture
 			using_subpass_transparent = false;
 			using_subpass_post_process = false;
 		}
 
+		// We do this last because our get_color_fbs creates and caches the framebuffer if we need it.
+		if (using_subpass_post_process && rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) {
+			// can't do blit subpass because we don't have all subpasses
+			using_subpass_post_process = false;
+		}
+
 		if (using_subpass_post_process) {
 			// all as subpasses
 			framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES);

+ 2 - 5
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -539,7 +539,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
 		tonemap.view_count = rb->get_view_count();
 
 		RID dest_fb;
-		if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) {
+		if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) {
 			// If we use FSR to upscale we need to write our result into an intermediate buffer.
 			// Note that this is cached so we only create the texture the first time.
 			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);
@@ -556,10 +556,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
 		RD::get_singleton()->draw_command_end_label();
 	}
 
-	if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) {
-		// TODO Investigate? Does this work? We never write into our render target and we've already done so up above in our tonemapper.
-		// I think FSR should either work before our tonemapper or as an alternative of our tonemapper.
-
+	if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) {
 		RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale");
 
 		for (uint32_t v = 0; v < rb->get_view_count(); v++) {

+ 3 - 7
servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp

@@ -96,7 +96,7 @@ void RenderSceneBuffersRD::cleanup() {
 	named_textures.clear();
 }
 
-void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 
@@ -104,12 +104,7 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna
 
 	target_size = p_target_size;
 	internal_size = p_internal_size;
-
-	// FIXME, right now we do this because only our clustered renderer supports FSR upscale
-	// this does mean that with linear upscale if we use subpasses, we could get into trouble.
-	if (!can_be_storage) {
-		internal_size = target_size;
-	}
+	scaling_3d_mode = p_scaling_3d_mode;
 
 	if (p_use_taa) {
 		// Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness.
@@ -193,6 +188,7 @@ void RenderSceneBuffersRD::configure_for_reflections(const Size2i p_reflection_s
 	target_size = p_reflection_size;
 	internal_size = p_reflection_size;
 	render_target = RID();
+	scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
 	fsr_sharpness = 0.0;
 	msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
 	screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;

+ 3 - 1
servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h

@@ -73,6 +73,7 @@ private:
 
 	// The internal size of the textures we render 3D to in case we render at a lower resolution and upscale
 	Size2i internal_size = Size2i(0, 0);
+	RS::ViewportScaling3DMode scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
 	float fsr_sharpness = 0.2f;
 
 	// Aliassing settings
@@ -139,7 +140,7 @@ public:
 	void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; }
 
 	void cleanup();
-	virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+	virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
 	void configure_for_reflections(const Size2i p_reflection_size);
 	virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
 	virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
@@ -172,6 +173,7 @@ public:
 	_FORCE_INLINE_ uint32_t get_view_count() const { return view_count; }
 	_FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; }
 	_FORCE_INLINE_ Size2i get_target_size() const { return target_size; }
+	_FORCE_INLINE_ RS::ViewportScaling3DMode get_scaling_3d_mode() const { return scaling_3d_mode; }
 	_FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; }
 	_FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; }
 	_FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; }

+ 34 - 34
servers/rendering/renderer_viewport.cpp

@@ -115,9 +115,8 @@ 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 scaling_3d_scale = p_viewport->scaling_3d_scale;
+			float scaling_3d_scale = p_viewport->scaling_3d_scale;
 			RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
-			bool scaling_enabled = true;
 
 			if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) {
 				// FSR is not designed for downsampling.
@@ -133,7 +132,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
 			}
 
 			if (scaling_3d_scale == 1.0) {
-				scaling_enabled = false;
+				scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
 			}
 
 			int width;
@@ -141,36 +140,37 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
 			int render_width;
 			int render_height;
 
-			if (scaling_enabled) {
-				switch (scaling_3d_mode) {
-					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;
-						break;
-					case RS::VIEWPORT_SCALING_3D_MODE_FSR:
-						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);
-						break;
-					default:
-						// This is an unknown mode.
-						WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode));
-						width = p_viewport->size.width;
-						height = p_viewport->size.height;
-						render_width = width;
-						render_height = height;
-						break;
-				}
-			} else {
-				width = p_viewport->size.width;
-				height = p_viewport->size.height;
-				render_width = width;
-				render_height = height;
+			switch (scaling_3d_mode) {
+				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;
+					break;
+				case RS::VIEWPORT_SCALING_3D_MODE_FSR:
+					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);
+					break;
+				case RS::VIEWPORT_SCALING_3D_MODE_OFF:
+					width = p_viewport->size.width;
+					height = p_viewport->size.height;
+					render_width = width;
+					render_height = 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;
+					break;
 			}
 
 			p_viewport->internal_size = Size2(render_width, render_height);
@@ -179,7 +179,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
 			// to compensate for the loss of sharpness.
 			const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias;
 
-			p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count);
+			p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), scaling_3d_mode, p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count);
 		}
 	}
 }

+ 2 - 2
servers/rendering/storage/render_scene_buffers.cpp

@@ -34,8 +34,8 @@ void RenderSceneBuffers::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("configure", "render_target", "internal_size", "target_size", "fsr_sharpness", "texture_mipmap_bias", "msaa", "screen_space_aa", "use_taa", "use_debanding", "view_count"), &RenderSceneBuffers::configure);
 }
 
-void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
-	GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count);
+void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+	GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_scaling_3d_mode, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count);
 };
 
 void RenderSceneBuffers::set_fsr_sharpness(float p_fsr_sharpness) {

+ 2 - 2
servers/rendering/storage/render_scene_buffers.h

@@ -40,7 +40,7 @@ class RenderSceneBuffers : public RefCounted {
 protected:
 	static void _bind_methods();
 
-	GDVIRTUAL10(_configure, RID, Size2i, Size2i, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t)
+	GDVIRTUAL11(_configure, RID, Size2i, Size2i, RS::ViewportScaling3DMode, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t)
 	GDVIRTUAL1(_set_fsr_sharpness, float)
 	GDVIRTUAL1(_set_texture_mipmap_bias, float)
 	GDVIRTUAL1(_set_use_debanding, bool)
@@ -49,7 +49,7 @@ public:
 	RenderSceneBuffers(){};
 	virtual ~RenderSceneBuffers(){};
 
-	virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count);
+	virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count);
 
 	// for those settings that are unlikely to require buffers to be recreated, we'll add setters
 	virtual void set_fsr_sharpness(float p_fsr_sharpness);

+ 2 - 1
servers/rendering_server.h

@@ -802,7 +802,8 @@ public:
 	enum ViewportScaling3DMode {
 		VIEWPORT_SCALING_3D_MODE_BILINEAR,
 		VIEWPORT_SCALING_3D_MODE_FSR,
-		VIEWPORT_SCALING_3D_MODE_MAX
+		VIEWPORT_SCALING_3D_MODE_MAX,
+		VIEWPORT_SCALING_3D_MODE_OFF = 255, // for internal use only
 	};
 
 	virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0;