Browse Source

Extracting render buffers and changing it to a more generic solution

Bastiaan Olij 3 years ago
parent
commit
2cd84be64d
49 changed files with 2877 additions and 2125 deletions
  1. 15 85
      drivers/gles3/rasterizer_scene_gles3.cpp
  2. 10 51
      drivers/gles3/rasterizer_scene_gles3.h
  3. 103 0
      drivers/gles3/storage/render_scene_buffers_gles3.cpp
  4. 98 0
      drivers/gles3/storage/render_scene_buffers_gles3.h
  5. 6 7
      servers/rendering/dummy/rasterizer_scene_dummy.h
  6. 15 10
      servers/rendering/renderer_rd/effects/copy_effects.cpp
  7. 2 2
      servers/rendering/renderer_rd/effects/copy_effects.h
  8. 127 0
      servers/rendering/renderer_rd/effects/fsr.cpp
  9. 73 0
      servers/rendering/renderer_rd/effects/fsr.h
  10. 92 0
      servers/rendering/renderer_rd/effects/ss_effects.cpp
  11. 29 0
      servers/rendering/renderer_rd/effects/ss_effects.h
  12. 138 0
      servers/rendering/renderer_rd/effects/taa.cpp
  13. 68 0
      servers/rendering/renderer_rd/effects/taa.h
  14. 8 33
      servers/rendering/renderer_rd/effects/vrs.cpp
  15. 1 1
      servers/rendering/renderer_rd/effects/vrs.h
  16. 0 158
      servers/rendering/renderer_rd/effects_rd.cpp
  17. 0 65
      servers/rendering/renderer_rd/effects_rd.h
  18. 48 46
      servers/rendering/renderer_rd/environment/fog.cpp
  19. 15 6
      servers/rendering/renderer_rd/environment/fog.h
  20. 114 129
      servers/rendering/renderer_rd/environment/gi.cpp
  21. 118 95
      servers/rendering/renderer_rd/environment/gi.h
  22. 7 5
      servers/rendering/renderer_rd/environment/sky.cpp
  23. 2 1
      servers/rendering/renderer_rd/environment/sky.h
  24. 213 429
      servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
  25. 54 49
      servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
  26. 166 205
      servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
  27. 30 33
      servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
  28. 2 2
      servers/rendering/renderer_rd/framebuffer_cache_rd.h
  29. 234 508
      servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
  30. 31 168
      servers/rendering/renderer_rd/renderer_scene_render_rd.h
  31. 0 0
      servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl
  32. 0 0
      servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl
  33. 0 0
      servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl
  34. 48 0
      servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h
  35. 559 0
      servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
  36. 256 0
      servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
  37. 20 0
      servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
  38. 2 0
      servers/rendering/renderer_rd/storage_rd/texture_storage.h
  39. 2 2
      servers/rendering/renderer_rd/storage_rd/utilities.cpp
  40. 4 5
      servers/rendering/renderer_scene.h
  41. 5 6
      servers/rendering/renderer_scene_cull.cpp
  42. 4 5
      servers/rendering/renderer_scene_cull.h
  43. 7 7
      servers/rendering/renderer_scene_render.h
  44. 12 7
      servers/rendering/renderer_viewport.cpp
  45. 2 1
      servers/rendering/renderer_viewport.h
  46. 26 0
      servers/rendering/rendering_device.h
  47. 51 0
      servers/rendering/storage/render_scene_buffers.cpp
  48. 60 0
      servers/rendering/storage/render_scene_buffers.h
  49. 0 4
      servers/xr/xr_interface_extension.cpp

+ 15 - 85
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -568,7 +568,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
 	dirty_sky_list = nullptr;
 }
 
-void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
+void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
 	GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton();
 	GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
 	ERR_FAIL_COND(p_render_data->environment.is_null());
@@ -1718,23 +1718,23 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
 	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
-void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
 	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
 	GLES3::Config *config = GLES3::Config::get_singleton();
 	RENDER_TIMESTAMP("Setup 3D Scene");
 
-	RenderBuffers *rb = nullptr;
+	Ref<RenderSceneBuffersGLES3> rb;
 	if (p_render_buffers.is_valid()) {
-		rb = render_buffers_owner.get_or_null(p_render_buffers);
-		ERR_FAIL_COND(!rb);
+		rb = p_render_buffers;
+		ERR_FAIL_COND(rb.is_null());
 	}
 
 	// Assign render data
 	// Use the format from rendererRD
 	RenderDataGLES3 render_data;
 	{
-		render_data.render_buffers = p_render_buffers;
-		render_data.transparent_bg = rb->is_transparent;
+		render_data.render_buffers = rb;
+		render_data.transparent_bg = rb.is_valid() ? rb->is_transparent : false;
 		// Our first camera is used by default
 		render_data.cam_transform = p_camera_data->main_transform;
 		render_data.inv_cam_transform = render_data.cam_transform.affine_inverse();
@@ -1886,7 +1886,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
 
 			sky_energy_multiplier *= bg_energy_multiplier;
 
-			_setup_sky(&render_data, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size);
+			_setup_sky(&render_data, *render_data.lights, projection, render_data.cam_transform, screen_size);
 
 			if (environment_get_sky(render_data.environment).is_valid()) {
 				if (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY || (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_BG && environment_get_background(render_data.environment) == RS::ENV_BG_SKY)) {
@@ -2005,8 +2005,8 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
 
 	_render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true);
 
-	if (p_render_buffers.is_valid()) {
-		_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
+	if (rb.is_valid()) {
+		_render_buffers_debug_draw(rb, p_shadow_atlas, p_occluder_debug_tex);
 	}
 	glDisable(GL_BLEND);
 	texture_storage->render_target_disable_clear_request(rb->render_target);
@@ -2328,74 +2328,10 @@ void RasterizerSceneGLES3::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_dra
 	debug_draw = p_debug_draw;
 }
 
-RID RasterizerSceneGLES3::render_buffers_create() {
-	RenderBuffers rb;
-	return render_buffers_owner.make_rid(rb);
-}
-
-void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::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();
-
-	RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
-	ERR_FAIL_COND(!rb);
-
-	//rb->internal_width = p_internal_width; // ignore for now
-	//rb->internal_height = p_internal_height;
-	rb->width = p_width;
-	rb->height = p_height;
-	//rb->fsr_sharpness = p_fsr_sharpness;
-	rb->render_target = p_render_target;
-	//rb->msaa = p_msaa;
-	//rb->screen_space_aa = p_screen_space_aa;
-	//rb->use_debanding = p_use_debanding;
-	//rb->view_count = p_view_count;
-
-	_free_render_buffer_data(rb);
-
-	GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
-
-	rb->is_transparent = rt->is_transparent;
-
-	// framebuffer
-	glGenFramebuffers(1, &rb->framebuffer);
-	glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer);
-
-	glBindTexture(GL_TEXTURE_2D, rt->color);
-	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
-
-	glGenTextures(1, &rb->depth_texture);
-	glBindTexture(GL_TEXTURE_2D, rb->depth_texture);
-
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
-
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rb->depth_texture, 0);
-
-	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
-	glBindTexture(GL_TEXTURE_2D, 0);
-	glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
-
-	if (status != GL_FRAMEBUFFER_COMPLETE) {
-		_free_render_buffer_data(rb);
-		WARN_PRINT("Could not create 3D renderbuffer, status: " + texture_storage->get_framebuffer_error(status));
-		return;
-	}
-}
-
-void RasterizerSceneGLES3::_free_render_buffer_data(RenderBuffers *rb) {
-	if (rb->depth_texture) {
-		glDeleteTextures(1, &rb->depth_texture);
-		rb->depth_texture = 0;
-	}
-	if (rb->framebuffer) {
-		glDeleteFramebuffers(1, &rb->framebuffer);
-		rb->framebuffer = 0;
-	}
+Ref<RenderSceneBuffers> RasterizerSceneGLES3::render_buffers_create() {
+	Ref<RenderSceneBuffersGLES3> rb;
+	rb.instantiate();
+	return rb;
 }
 
 //clear render buffers
@@ -2423,7 +2359,7 @@ void RasterizerSceneGLES3::_free_render_buffer_data(RenderBuffers *rb) {
 	}
 */
 
-void RasterizerSceneGLES3::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
+void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
 }
 
 void RasterizerSceneGLES3::gi_set_use_half_resolution(bool p_enable) {
@@ -2454,12 +2390,6 @@ bool RasterizerSceneGLES3::free(RID p_rid) {
 		ERR_FAIL_COND_V(!sky, false);
 		_free_sky_data(sky);
 		sky_owner.free(p_rid);
-	} else if (render_buffers_owner.owns(p_rid)) {
-		RenderBuffers *rb = render_buffers_owner.get_or_null(p_rid);
-		ERR_FAIL_COND_V(!rb, false);
-		_free_render_buffer_data(rb);
-		render_buffers_owner.free(p_rid);
-
 	} else if (light_instance_owner.owns(p_rid)) {
 		LightInstance *light_instance = light_instance_owner.get_or_null(p_rid);
 		ERR_FAIL_COND_V(!light_instance, false);

+ 10 - 51
drivers/gles3/rasterizer_scene_gles3.h

@@ -45,6 +45,7 @@
 #include "shaders/cubemap_filter.glsl.gen.h"
 #include "shaders/sky.glsl.gen.h"
 #include "storage/material_storage.h"
+#include "storage/render_scene_buffers_gles3.h"
 #include "storage/utilities.h"
 
 enum RenderListType {
@@ -91,7 +92,7 @@ enum {
 };
 
 struct RenderDataGLES3 {
-	RID render_buffers = RID();
+	Ref<RenderSceneBuffersGLES3> render_buffers;
 	bool transparent_bg = false;
 
 	Transform3D cam_transform = Transform3D();
@@ -490,52 +491,11 @@ protected:
 	double time;
 	double time_step = 0;
 
-	struct RenderBuffers {
-		int internal_width = 0;
-		int internal_height = 0;
-		int width = 0;
-		int height = 0;
-		//float fsr_sharpness = 0.2f;
-		RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
-		//RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
-		//bool use_debanding = false;
-		//uint32_t view_count = 1;
-
-		bool is_transparent = false;
-
-		RID render_target;
-		GLuint internal_texture = 0; // Used for rendering when post effects are enabled
-		GLuint depth_texture = 0; // Main depth texture
-		GLuint framebuffer = 0; // Main framebuffer, contains internal_texture and depth_texture or render_target->color and depth_texture
-
-		//built-in textures used for ping pong image processing and blurring
-		struct Blur {
-			RID texture;
-
-			struct Mipmap {
-				RID texture;
-				int width;
-				int height;
-				GLuint fbo;
-			};
-
-			Vector<Mipmap> mipmaps;
-		};
-
-		Blur blur[2]; //the second one starts from the first mipmap
-	};
-
 	bool screen_space_roughness_limiter = false;
 	float screen_space_roughness_limiter_amount = 0.25;
 	float screen_space_roughness_limiter_limit = 0.18;
 
-	mutable RID_Owner<RenderBuffers, true> render_buffers_owner;
-
-	void _free_render_buffer_data(RenderBuffers *rb);
-	void _allocate_blur_textures(RenderBuffers *rb);
-	void _allocate_depth_backbuffer_textures(RenderBuffers *rb);
-
-	void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
+	void _render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
 
 	/* Camera Attributes */
 
@@ -626,7 +586,7 @@ protected:
 	Sky *dirty_sky_list = nullptr;
 	mutable RID_Owner<Sky, true> sky_owner;
 
-	void _setup_sky(const RenderDataGLES3 *p_render_data, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
+	void _setup_sky(const RenderDataGLES3 *p_render_data, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
 	void _invalidate_sky(Sky *p_sky);
 	void _update_dirty_skys();
 	void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier);
@@ -657,14 +617,14 @@ public:
 
 	/* SDFGI UPDATE */
 
-	void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
-	int sdfgi_get_pending_region_count(RID p_render_buffers) const override {
+	void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
+	int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override {
 		return 0;
 	}
-	AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override {
+	AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override {
 		return AABB();
 	}
-	uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override {
+	uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override {
 		return 0;
 	}
 
@@ -751,7 +711,7 @@ public:
 
 	void voxel_gi_set_quality(RS::VoxelGIQuality) override;
 
-	void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+	void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
 	void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
 	void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override;
 
@@ -769,8 +729,7 @@ public:
 		return debug_draw;
 	}
 
-	RID render_buffers_create() override;
-	void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+	Ref<RenderSceneBuffers> render_buffers_create() override;
 	void gi_set_use_half_resolution(bool p_enable) override;
 
 	void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override;

+ 103 - 0
drivers/gles3/storage/render_scene_buffers_gles3.cpp

@@ -0,0 +1,103 @@
+/*************************************************************************/
+/*  render_scene_buffers_gles3.cpp                                       */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifdef GLES3_ENABLED
+
+#include "render_scene_buffers_gles3.h"
+#include "texture_storage.h"
+
+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) {
+	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;
+	//fsr_sharpness = p_fsr_sharpness;
+	//texture_mipmap_bias = p_texture_mipmap_bias;
+	render_target = p_render_target;
+	//msaa = p_msaa;
+	//screen_space_aa = p_screen_space_aa;
+	//use_debanding = p_use_debanding;
+	//view_count = p_view_count;
+
+	free_render_buffer_data();
+
+	GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
+
+	is_transparent = rt->is_transparent;
+
+	// framebuffer
+	glGenFramebuffers(1, &framebuffer);
+	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+
+	glBindTexture(GL_TEXTURE_2D, rt->color);
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+
+	glGenTextures(1, &depth_texture);
+	glBindTexture(GL_TEXTURE_2D, depth_texture);
+
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
+
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
+
+	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+	glBindTexture(GL_TEXTURE_2D, 0);
+	glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
+
+	if (status != GL_FRAMEBUFFER_COMPLETE) {
+		free_render_buffer_data();
+		WARN_PRINT("Could not create 3D renderbuffer, status: " + texture_storage->get_framebuffer_error(status));
+		return;
+	}
+}
+
+void RenderSceneBuffersGLES3::free_render_buffer_data() {
+	if (depth_texture) {
+		glDeleteTextures(1, &depth_texture);
+		depth_texture = 0;
+	}
+	if (framebuffer) {
+		glDeleteFramebuffers(1, &framebuffer);
+		framebuffer = 0;
+	}
+}
+
+#endif // GLES3_ENABLED

+ 98 - 0
drivers/gles3/storage/render_scene_buffers_gles3.h

@@ -0,0 +1,98 @@
+/*************************************************************************/
+/*  render_scene_buffers_gles3.h                                         */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef RENDER_SCENE_BUFFERS_GLES3_H
+#define RENDER_SCENE_BUFFERS_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "servers/rendering/storage/render_scene_buffers.h"
+
+#include "platform_config.h"
+#ifndef OPENGL_INCLUDE_H
+#include <GLES3/gl3.h>
+#else
+#include OPENGL_INCLUDE_H
+#endif
+
+class RenderSceneBuffersGLES3 : public RenderSceneBuffers {
+	GDCLASS(RenderSceneBuffersGLES3, RenderSceneBuffers);
+
+public:
+	// Original implementation, need to investigate which ones we'll keep like this and what we'll change...
+
+	int internal_width = 0;
+	int internal_height = 0;
+	int width = 0;
+	int height = 0;
+	//float fsr_sharpness = 0.2f;
+	RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
+	//RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+	//bool use_debanding = false;
+	//uint32_t view_count = 1;
+
+	bool is_transparent = false;
+
+	RID render_target;
+	GLuint internal_texture = 0; // Used for rendering when post effects are enabled
+	GLuint depth_texture = 0; // Main depth texture
+	GLuint framebuffer = 0; // Main framebuffer, contains internal_texture and depth_texture or render_target->color and depth_texture
+
+	//built-in textures used for ping pong image processing and blurring
+	struct Blur {
+		RID texture;
+
+		struct Mipmap {
+			RID texture;
+			int width;
+			int height;
+			GLuint fbo;
+		};
+
+		Vector<Mipmap> mipmaps;
+	};
+
+	Blur blur[2]; //the second one starts from the first mipmap
+
+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 set_fsr_sharpness(float p_fsr_sharpness) override{};
+	virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override{};
+	virtual void set_use_debanding(bool p_use_debanding) override{};
+
+	void free_render_buffer_data();
+};
+
+#endif // GLES3_ENABLED
+
+#endif // RENDER_SCENE_BUFFERS_GLES3_H

+ 6 - 7
servers/rendering/dummy/rasterizer_scene_dummy.h

@@ -106,10 +106,10 @@ public:
 
 	/* SDFGI UPDATE */
 
-	void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
-	int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
-	AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
-	uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
+	void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
+	int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override { return 0; }
+	AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return AABB(); }
+	uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return 0; }
 
 	/* SKY API */
 
@@ -180,7 +180,7 @@ public:
 
 	void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
 
-	void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
+	void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
 	void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
 	void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override {}
 
@@ -188,8 +188,7 @@ public:
 	void set_time(double p_time, double p_step) override {}
 	void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
 
-	RID render_buffers_create() override { return RID(); }
-	void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
+	Ref<RenderSceneBuffers> render_buffers_create() override { return Ref<RenderSceneBuffers>(); }
 	void gi_set_use_half_resolution(bool p_enable) override {}
 
 	void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}

+ 15 - 10
servers/rendering/renderer_rd/effects/copy_effects.cpp

@@ -705,7 +705,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
 	RD::get_singleton()->compute_list_end();
 }
 
-void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
+void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
 	ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
 
 	UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -713,6 +713,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
 	MaterialStorage *material_storage = MaterialStorage::get_singleton();
 	ERR_FAIL_NULL(material_storage);
 
+	RID half_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_half_texture);
+	RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
 	memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
 
 	BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
@@ -737,14 +740,14 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
 	RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 
 	RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
-	RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half }));
+	RD::Uniform u_half_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_half_texture }));
 
 	RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
 	ERR_FAIL_COND(shader.is_null());
 
 	//HORIZONTAL
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
+	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(half_framebuffer)));
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
 	if (p_auto_exposure.is_valid() && p_first_pass) {
 		RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
@@ -764,9 +767,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
 	ERR_FAIL_COND(shader.is_null());
 
 	//VERTICAL
-	draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0);
+	draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
+	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture), 0);
 	RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
 
 	blur_raster.push_constant.flags = base_flags;
@@ -810,9 +813,11 @@ void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const
 	RD::get_singleton()->compute_list_end();
 }
 
-void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
+void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
 	ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
 
+	RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
 	UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
 	ERR_FAIL_NULL(uniform_set_cache);
 	MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -833,8 +838,8 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebu
 	RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode);
 	ERR_FAIL_COND(shader.is_null());
 
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
 	RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
 	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));

+ 2 - 2
servers/rendering/renderer_rd/effects/copy_effects.h

@@ -322,10 +322,10 @@ public:
 
 	void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
 	void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
-	void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
+	void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
 
 	void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
-	void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
+	void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
 
 	void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
 

+ 127 - 0
servers/rendering/renderer_rd/effects/fsr.cpp

@@ -0,0 +1,127 @@
+/*************************************************************************/
+/*  fsr.cpp                                                              */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "fsr.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+FSR::FSR() {
+	Vector<String> FSR_upscale_modes;
+
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+	// MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
+	FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+#else
+	// Everyone else can use normal mode when available.
+	if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
+		FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
+	} else {
+		FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+	}
+#endif
+
+	fsr_shader.initialize(FSR_upscale_modes);
+
+	shader_version = fsr_shader.version_create();
+	pipeline = RD::get_singleton()->compute_pipeline_create(fsr_shader.version_get_shader(shader_version, 0));
+}
+
+FSR::~FSR() {
+	fsr_shader.version_free(shader_version);
+}
+
+void FSR::fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture) {
+	UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+	ERR_FAIL_NULL(uniform_set_cache);
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+	ERR_FAIL_NULL(material_storage);
+
+	Size2i internal_size = p_render_buffers->get_internal_size();
+	Size2i target_size = p_render_buffers->get_target_size();
+	float fsr_upscale_sharpness = p_render_buffers->get_fsr_sharpness();
+
+	if (!p_render_buffers->has_texture(SNAME("FSR"), SNAME("upscale_texture"))) {
+		RD::DataFormat format = p_render_buffers->get_base_data_format();
+		uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+		uint32_t layers = 1; // we only need one layer, in multiview we're processing one layer at a time.
+
+		p_render_buffers->create_texture(SNAME("FSR"), SNAME("upscale_texture"), format, usage_bits, RD::TEXTURE_SAMPLES_1, target_size, layers);
+	}
+
+	RID upscale_texture = p_render_buffers->get_texture(SNAME("FSR"), SNAME("upscale_texture"));
+
+	FSRUpscalePushConstant push_constant;
+	memset(&push_constant, 0, sizeof(FSRUpscalePushConstant));
+
+	int dispatch_x = (target_size.x + 15) / 16;
+	int dispatch_y = (target_size.y + 15) / 16;
+
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
+
+	push_constant.resolution_width = internal_size.width;
+	push_constant.resolution_height = internal_size.height;
+	push_constant.upscaled_width = target_size.width;
+	push_constant.upscaled_height = target_size.height;
+	push_constant.sharpness = fsr_upscale_sharpness;
+
+	RID shader = fsr_shader.version_get_shader(shader_version, 0);
+	ERR_FAIL_COND(shader.is_null());
+
+	RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+	//FSR Easc
+	RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, p_source_rd_texture });
+	RD::Uniform u_upscale_texture(RD::UNIFORM_TYPE_IMAGE, 0, { upscale_texture });
+
+	push_constant.pass = FSR_UPSCALE_PASS_EASU;
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_upscale_texture), 1);
+
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
+
+	RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+	RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+	//FSR Rcas
+	RD::Uniform u_upscale_texture_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, upscale_texture });
+	RD::Uniform u_destination_texture(RD::UNIFORM_TYPE_IMAGE, 0, { p_destination_texture });
+
+	push_constant.pass = FSR_UPSCALE_PASS_RCAS;
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_texture_with_sampler), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_destination_texture), 1);
+
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
+
+	RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+
+	RD::get_singleton()->compute_list_end(compute_list);
+}

+ 73 - 0
servers/rendering/renderer_rd/effects/fsr.h

@@ -0,0 +1,73 @@
+/*************************************************************************/
+/*  fsr.h                                                                */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef FSR_RD_H
+#define FSR_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class FSR {
+public:
+	FSR();
+	~FSR();
+
+	void fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture);
+
+private:
+	enum FSRUpscalePass {
+		FSR_UPSCALE_PASS_EASU = 0,
+		FSR_UPSCALE_PASS_RCAS = 1
+	};
+
+	struct FSRUpscalePushConstant {
+		float resolution_width;
+		float resolution_height;
+		float upscaled_width;
+		float upscaled_height;
+		float sharpness;
+		int pass;
+		int _unused0, _unused1;
+	};
+
+	FsrUpscaleShaderRD fsr_shader;
+	RID shader_version;
+	RID pipeline;
+};
+
+} // namespace RendererRD
+
+#endif // FSR_RD_H

+ 92 - 0
servers/rendering/renderer_rd/effects/ss_effects.cpp

@@ -32,6 +32,7 @@
 
 #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
 #include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
 #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
 
 using namespace RendererRD;
@@ -333,6 +334,22 @@ SSEffects::SSEffects() {
 			}
 		}
 	}
+
+	// Subsurface scattering
+	{
+		Vector<String> sss_modes;
+		sss_modes.push_back("\n#define USE_11_SAMPLES\n");
+		sss_modes.push_back("\n#define USE_17_SAMPLES\n");
+		sss_modes.push_back("\n#define USE_25_SAMPLES\n");
+
+		sss.shader.initialize(sss_modes);
+
+		sss.shader_version = sss.shader.version_create();
+
+		for (int i = 0; i < sss_modes.size(); i++) {
+			sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
+		}
+	}
 }
 
 SSEffects::~SSEffects() {
@@ -376,6 +393,11 @@ SSEffects::~SSEffects() {
 		RD::get_singleton()->free(ssao.importance_map_load_counter);
 	}
 
+	{
+		// Cleanup Subsurface scattering
+		sss.shader.version_free(sss.shader_version);
+	}
+
 	singleton = nullptr;
 }
 
@@ -1713,3 +1735,73 @@ void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) {
 		p_ssr_buffers.normal_scaled = RID();
 	}
 }
+
+/* Subsurface scattering */
+
+void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
+	UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+	ERR_FAIL_NULL(uniform_set_cache);
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+	ERR_FAIL_NULL(material_storage);
+
+	RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+	// Our intermediate buffer is only created if we haven't created it already.
+	RD::DataFormat format = p_render_buffers->get_base_data_format();
+	uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+	uint32_t layers = 1; // We only need one layer, we're handling one view at a time
+	uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH);
+	RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps);
+
+	Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
+	p.normal /= p.d;
+	float unit_size = p.normal.x;
+
+	{ //scale color and depth to half
+		RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+		sss.push_constant.camera_z_far = p_camera.get_z_far();
+		sss.push_constant.camera_z_near = p_camera.get_z_near();
+		sss.push_constant.orthogonal = p_camera.is_orthogonal();
+		sss.push_constant.unit_size = unit_size;
+		sss.push_constant.screen_size[0] = p_screen_size.x;
+		sss.push_constant.screen_size[1] = p_screen_size.y;
+		sss.push_constant.vertical = false;
+		sss.push_constant.scale = p_scale;
+		sss.push_constant.depth_scale = p_depth_scale;
+
+		RID shader = sss.shader.version_get_shader(sss.shader_version, p_quality - 1);
+		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]);
+
+		RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));
+		RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));
+		RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate }));
+		RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
+		RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth }));
+
+		// horizontal
+
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
+
+		RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
+
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+		RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+		// vertical
+
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
+
+		sss.push_constant.vertical = true;
+		RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
+
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+		RD::get_singleton()->compute_list_end();
+	}
+}

+ 29 - 0
servers/rendering/renderer_rd/effects/ss_effects.h

@@ -44,9 +44,12 @@
 #include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl.gen.h"
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/rendering_server.h"
 
+class RenderSceneBuffersRD;
+
 namespace RendererRD {
 
 class SSEffects {
@@ -168,6 +171,9 @@ public:
 	void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets);
 	void ssr_free(SSRRenderBuffers &p_ssr_buffers);
 
+	/* subsurface scattering */
+	void sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
+
 private:
 	/* SS Downsampler */
 
@@ -501,6 +507,29 @@ private:
 		RID shader_version;
 		RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX];
 	} ssr_filter;
+
+	/* Subsurface scattering */
+
+	struct SubSurfaceScatteringPushConstant {
+		int32_t screen_size[2];
+		float camera_z_far;
+		float camera_z_near;
+
+		uint32_t vertical;
+		uint32_t orthogonal;
+		float unit_size;
+		float scale;
+
+		float depth_scale;
+		uint32_t pad[3];
+	};
+
+	struct SubSurfaceScattering {
+		SubSurfaceScatteringPushConstant push_constant;
+		SubsurfaceScatteringShaderRD shader;
+		RID shader_version;
+		RID pipelines[3]; //3 quality levels
+	} sss;
 };
 
 } // namespace RendererRD

+ 138 - 0
servers/rendering/renderer_rd/effects/taa.cpp

@@ -0,0 +1,138 @@
+/*************************************************************************/
+/*  taa.cpp                                                              */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "taa.h"
+#include "servers/rendering/renderer_rd/effects/copy_effects.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+TAA::TAA() {
+	Vector<String> taa_modes;
+	taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
+	taa_shader.initialize(taa_modes);
+	shader_version = taa_shader.version_create();
+	pipeline = RD::get_singleton()->compute_pipeline_create(taa_shader.version_get_shader(shader_version, 0));
+}
+
+TAA::~TAA() {
+	taa_shader.version_free(shader_version);
+}
+
+void TAA::msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers) {
+	if (!p_render_buffers->has_velocity_buffer(true)) {
+		// nothing to resolve
+		return;
+	}
+
+	for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
+		RID velocity_buffer_msaa = p_render_buffers->get_velocity_buffer(true, v);
+		RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
+
+		RD::get_singleton()->texture_resolve_multisample(velocity_buffer_msaa, velocity_buffer);
+	}
+}
+
+void TAA::resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
+	UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+	ERR_FAIL_NULL(uniform_set_cache);
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+	ERR_FAIL_NULL(material_storage);
+
+	RID shader = taa_shader.version_get_shader(shader_version, 0);
+	ERR_FAIL_COND(shader.is_null());
+
+	RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+	TAAResolvePushConstant push_constant;
+	memset(&push_constant, 0, sizeof(TAAResolvePushConstant));
+	push_constant.resolution_width = p_resolution.width;
+	push_constant.resolution_height = p_resolution.height;
+	push_constant.disocclusion_threshold = 0.025f;
+	push_constant.disocclusion_scale = 10.0f;
+
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
+
+	RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
+	RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
+	RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
+	RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
+	RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
+	RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
+
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(TAAResolvePushConstant));
+	RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
+	RD::get_singleton()->compute_list_end();
+}
+
+void TAA::process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far) {
+	CopyEffects *copy_effects = CopyEffects::get_singleton();
+
+	uint32_t view_count = p_render_buffers->get_view_count();
+	Size2i internal_size = p_render_buffers->get_internal_size();
+	Size2i target_size = p_render_buffers->get_target_size();
+
+	bool just_allocated = false;
+	if (!p_render_buffers->has_texture(SNAME("taa"), SNAME("history"))) {
+		uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+		p_render_buffers->create_texture(SNAME("taa"), SNAME("history"), p_format, usage_bits);
+		p_render_buffers->create_texture(SNAME("taa"), SNAME("temp"), p_format, usage_bits);
+
+		p_render_buffers->create_texture(SNAME("taa"), SNAME("prev_velocity"), RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits);
+
+		just_allocated = true;
+	}
+
+	RD::get_singleton()->draw_command_begin_label("TAA");
+
+	for (uint32_t v = 0; v < view_count; v++) {
+		// Get our (cached) slices
+		RID internal_texture = p_render_buffers->get_internal_texture(v);
+		RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
+		RID taa_history = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("history"), v, 0);
+		RID taa_prev_velocity = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("prev_velocity"), v, 0);
+
+		if (!just_allocated) {
+			RID depth_texture = p_render_buffers->get_depth_texture(v);
+			RID taa_temp = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("temp"), v, 0);
+			resolve(internal_texture, taa_temp, depth_texture, velocity_buffer, taa_prev_velocity, taa_history, Size2(internal_size.x, internal_size.y), p_z_near, p_z_far);
+			copy_effects->copy_to_rect(taa_temp, internal_texture, Rect2(0, 0, internal_size.x, internal_size.y));
+		}
+
+		copy_effects->copy_to_rect(internal_texture, taa_history, Rect2(0, 0, internal_size.x, internal_size.y));
+		copy_effects->copy_to_rect(velocity_buffer, taa_prev_velocity, Rect2(0, 0, target_size.x, target_size.y));
+	}
+
+	RD::get_singleton()->draw_command_end_label();
+}

+ 68 - 0
servers/rendering/renderer_rd/effects/taa.h

@@ -0,0 +1,68 @@
+/*************************************************************************/
+/*  taa.h                                                                */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef TAA_RD_H
+#define TAA_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class TAA {
+public:
+	TAA();
+	~TAA();
+
+	void msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers);
+	void process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far);
+
+private:
+	struct TAAResolvePushConstant {
+		float resolution_width;
+		float resolution_height;
+		float disocclusion_threshold;
+		float disocclusion_scale;
+	};
+
+	TaaResolveShaderRD taa_shader;
+	RID shader_version;
+	RID pipeline;
+
+	void resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
+};
+
+} // namespace RendererRD
+
+#endif // TAA_RD_H

+ 8 - 33
servers/rendering/renderer_rd/effects/vrs.cpp

@@ -91,47 +91,22 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
 	RD::get_singleton()->draw_list_end();
 }
 
-void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) {
-	// TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm
-
+Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
 	// TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
 	// obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
 	// our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
 	// of the VRS buffer to supply.
 	Size2i texel_size = Size2i(16, 16);
 
-	RD::TextureFormat tf;
-	if (p_view_count > 1) {
-		tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
-	} else {
-		tf.texture_type = RD::TEXTURE_TYPE_2D;
-	}
-	tf.format = RD::DATA_FORMAT_R8_UINT;
-	tf.width = p_base_width / texel_size.x;
-	if (p_base_width % texel_size.x != 0) {
-		tf.width++;
+	int width = p_base_size.x / texel_size.x;
+	if (p_base_size.x % texel_size.x != 0) {
+		width++;
 	}
-	tf.height = p_base_height / texel_size.y;
-	if (p_base_height % texel_size.y != 0) {
-		tf.height++;
+	int height = p_base_size.y / texel_size.y;
+	if (p_base_size.y % texel_size.y != 0) {
+		height++;
 	}
-	tf.array_layers = p_view_count; // create a layer for every view
-	tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-	tf.samples = RD::TEXTURE_SAMPLES_1;
-
-	p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
-	// by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control
-	Vector<RID> fb;
-	fb.push_back(p_vrs_texture);
-
-	RD::FramebufferPass pass;
-	pass.color_attachments.push_back(0);
-
-	Vector<RD::FramebufferPass> passes;
-	passes.push_back(pass);
-
-	p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count);
+	return Size2i(width, height);
 }
 
 void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {

+ 1 - 1
servers/rendering/renderer_rd/effects/vrs.h

@@ -66,7 +66,7 @@ public:
 
 	void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false);
 
-	void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb);
+	Size2i get_vrs_texture_size(const Size2i p_base_size) const;
 	void update_vrs_texture(RID p_vrs_fb, RID p_render_target);
 };
 

+ 0 - 158
servers/rendering/renderer_rd/effects_rd.cpp

@@ -108,115 +108,6 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m
 	return uniform_set;
 }
 
-void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) {
-	memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
-
-	int dispatch_x = (p_size.x + 15) / 16;
-	int dispatch_y = (p_size.y + 15) / 16;
-
-	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline);
-
-	FSR_upscale.push_constant.resolution_width = p_internal_size.width;
-	FSR_upscale.push_constant.resolution_height = p_internal_size.height;
-	FSR_upscale.push_constant.upscaled_width = p_size.width;
-	FSR_upscale.push_constant.upscaled_height = p_size.height;
-	FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness;
-
-	//FSR Easc
-	FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU;
-	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
-	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 1);
-
-	RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
-
-	RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
-	RD::get_singleton()->compute_list_add_barrier(compute_list);
-
-	//FSR Rcas
-	FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS;
-	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0);
-	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1);
-
-	RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
-
-	RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
-
-	RD::get_singleton()->compute_list_end(compute_list);
-}
-
-void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
-	UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
-	ERR_FAIL_NULL(uniform_set_cache);
-
-	RID shader = TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0);
-	ERR_FAIL_COND(shader.is_null());
-
-	memset(&TAA_resolve.push_constant, 0, sizeof(TAAResolvePushConstant));
-	TAA_resolve.push_constant.resolution_width = p_resolution.width;
-	TAA_resolve.push_constant.resolution_height = p_resolution.height;
-	TAA_resolve.push_constant.disocclusion_threshold = 0.025f;
-	TAA_resolve.push_constant.disocclusion_scale = 10.0f;
-
-	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, TAA_resolve.pipeline);
-
-	RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
-	RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
-	RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
-	RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
-	RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
-	RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
-
-	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
-	RD::get_singleton()->compute_list_set_push_constant(compute_list, &TAA_resolve.push_constant, sizeof(TAAResolvePushConstant));
-	RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
-	RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
-	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
-	Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
-	p.normal /= p.d;
-	float unit_size = p.normal.x;
-
-	{ //scale color and depth to half
-		sss.push_constant.camera_z_far = p_camera.get_z_far();
-		sss.push_constant.camera_z_near = p_camera.get_z_near();
-		sss.push_constant.orthogonal = p_camera.is_orthogonal();
-		sss.push_constant.unit_size = unit_size;
-		sss.push_constant.screen_size[0] = p_screen_size.x;
-		sss.push_constant.screen_size[1] = p_screen_size.y;
-		sss.push_constant.vertical = false;
-		sss.push_constant.scale = p_scale;
-		sss.push_constant.depth_scale = p_depth_scale;
-
-		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]);
-
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse2), 1);
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
-
-		RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
-
-		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
-		RD::get_singleton()->compute_list_add_barrier(compute_list);
-
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse2), 0);
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse), 1);
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
-
-		sss.push_constant.vertical = true;
-		RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
-
-		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
-		RD::get_singleton()->compute_list_end();
-	}
-}
-
 void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
 	ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
 
@@ -377,27 +268,6 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
 }
 
 EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
-	{
-		Vector<String> FSR_upscale_modes;
-
-#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
-		// MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
-		FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
-#else
-		// Everyone else can use normal mode when available.
-		if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
-			FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
-		} else {
-			FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
-		}
-#endif
-
-		FSR_upscale.shader.initialize(FSR_upscale_modes);
-
-		FSR_upscale.shader_version = FSR_upscale.shader.version_create();
-		FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0));
-	}
-
 	prefer_raster_effects = p_prefer_raster_effects;
 
 	if (prefer_raster_effects) {
@@ -445,23 +315,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
 		roughness_limiter.pipeline = RD::get_singleton()->compute_pipeline_create(roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0));
 	}
 
-	if (!prefer_raster_effects) {
-		{
-			Vector<String> sss_modes;
-			sss_modes.push_back("\n#define USE_11_SAMPLES\n");
-			sss_modes.push_back("\n#define USE_17_SAMPLES\n");
-			sss_modes.push_back("\n#define USE_25_SAMPLES\n");
-
-			sss.shader.initialize(sss_modes);
-
-			sss.shader_version = sss.shader.version_create();
-
-			for (int i = 0; i < sss_modes.size(); i++) {
-				sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
-			}
-		}
-	}
-
 	{
 		Vector<String> sort_modes;
 		sort_modes.push_back("\n#define MODE_SORT_BLOCK\n");
@@ -477,14 +330,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
 		}
 	}
 
-	{
-		Vector<String> taa_modes;
-		taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
-		TAA_resolve.shader.initialize(taa_modes);
-		TAA_resolve.shader_version = TAA_resolve.shader.version_create();
-		TAA_resolve.pipeline = RD::get_singleton()->compute_pipeline_create(TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0));
-	}
-
 	RD::SamplerState sampler;
 	sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
 	sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
@@ -523,8 +368,6 @@ EffectsRD::~EffectsRD() {
 	RD::get_singleton()->free(default_mipmap_sampler);
 	RD::get_singleton()->free(index_buffer); //array gets freed as dependency
 
-	FSR_upscale.shader.version_free(FSR_upscale.shader_version);
-	TAA_resolve.shader.version_free(TAA_resolve.shader_version);
 	if (prefer_raster_effects) {
 		luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
 	} else {
@@ -532,7 +375,6 @@ EffectsRD::~EffectsRD() {
 	}
 	if (!prefer_raster_effects) {
 		roughness_limiter.shader.version_free(roughness_limiter.shader_version);
-		sss.shader.version_free(sss.shader_version);
 	}
 	sort.shader.version_free(sort.shader_version);
 }

+ 0 - 65
servers/rendering/renderer_rd/effects_rd.h

@@ -33,13 +33,10 @@
 
 #include "core/math/projection.h"
 #include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
-#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h"
 #include "servers/rendering/renderer_scene_render.h"
 
 #include "servers/rendering_server.h"
@@ -48,42 +45,6 @@ class EffectsRD {
 private:
 	bool prefer_raster_effects;
 
-	enum FSRUpscalePass {
-		FSR_UPSCALE_PASS_EASU = 0,
-		FSR_UPSCALE_PASS_RCAS = 1
-	};
-
-	struct FSRUpscalePushConstant {
-		float resolution_width;
-		float resolution_height;
-		float upscaled_width;
-		float upscaled_height;
-		float sharpness;
-		int pass;
-		int _unused0, _unused1;
-	};
-
-	struct FSRUpscale {
-		FSRUpscalePushConstant push_constant;
-		FsrUpscaleShaderRD shader;
-		RID shader_version;
-		RID pipeline;
-	} FSR_upscale;
-
-	struct TAAResolvePushConstant {
-		float resolution_width;
-		float resolution_height;
-		float disocclusion_threshold;
-		float disocclusion_scale;
-	};
-
-	struct TAAResolve {
-		TAAResolvePushConstant push_constant;
-		TaaResolveShaderRD shader;
-		RID shader_version;
-		RID pipeline;
-	} TAA_resolve;
-
 	enum LuminanceReduceMode {
 		LUMINANCE_REDUCE_READ,
 		LUMINANCE_REDUCE,
@@ -143,27 +104,6 @@ private:
 
 	} roughness_limiter;
 
-	struct SubSurfaceScatteringPushConstant {
-		int32_t screen_size[2];
-		float camera_z_far;
-		float camera_z_near;
-
-		uint32_t vertical;
-		uint32_t orthogonal;
-		float unit_size;
-		float scale;
-
-		float depth_scale;
-		uint32_t pad[3];
-	};
-
-	struct SubSurfaceScattering {
-		SubSurfaceScatteringPushConstant push_constant;
-		SubsurfaceScatteringShaderRD shader;
-		RID shader_version;
-		RID pipelines[3]; //3 quality levels
-	} sss;
-
 	enum SortMode {
 		SORT_MODE_BLOCK,
 		SORT_MODE_STEP,
@@ -230,16 +170,11 @@ private:
 public:
 	bool get_prefer_raster_effects();
 
-	void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness);
-	void taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
-
 	void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
 	void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
 
 	void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
 
-	void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
-
 	void sort_buffer(RID p_uniform_set, int p_size);
 
 	EffectsRD(bool p_prefer_raster_effects);

+ 48 - 46
servers/rendering/renderer_rd/environment/fog.cpp

@@ -473,7 +473,7 @@ Fog::FogShaderData::~FogShaderData() {
 ////////////////////////////////////////////////////////////////////////////////
 // Volumetric Fog
 
-Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) {
+void Fog::VolumetricFog::init(const Vector3i &fog_size, RID p_sky_shader) {
 	width = fog_size.x;
 	height = fog_size.y;
 	depth = fog_size.z;
@@ -591,6 +591,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 	RENDER_TIMESTAMP("> Volumetric Fog");
 	RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
 
+	Ref<VolumetricFog> fog = p_settings.vfog;
+
 	if (p_fog_volumes.size() > 0) {
 		RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
 
@@ -623,9 +625,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 		params.z_far = z_far;
 		params.time = p_settings.time;
 
-		params.fog_volume_size[0] = p_settings.vfog->width;
-		params.fog_volume_size[1] = p_settings.vfog->height;
-		params.fog_volume_size[2] = p_settings.vfog->depth;
+		params.fog_volume_size[0] = fog->width;
+		params.fog_volume_size[1] = fog->height;
+		params.fog_volume_size[2] = fog->depth;
 
 		params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env);
 		params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
@@ -638,7 +640,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 
 		RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
 
-		if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) {
+		if (fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) {
 			Vector<RD::Uniform> uniforms;
 
 			{
@@ -649,7 +651,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 				u.binding = 1;
-				u.append_id(p_settings.vfog->emissive_map);
+				u.append_id(fog->emissive_map);
 				uniforms.push_back(u);
 			}
 
@@ -669,7 +671,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 				u.binding = 3;
-				u.append_id(p_settings.vfog->density_map);
+				u.append_id(fog->density_map);
 				uniforms.push_back(u);
 			}
 
@@ -681,11 +683,11 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 				u.binding = 4;
-				u.append_id(p_settings.vfog->light_map);
+				u.append_id(fog->light_map);
 				uniforms.push_back(u);
 			}
 
-			p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+			fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
 		}
 
 		RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -731,7 +733,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
 				// Local fog volume.
 				Vector3i points[8];
-				Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+				Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth);
 				float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
 				points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
 				points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
@@ -742,7 +744,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 				points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
 				points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
 
-				min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1);
+				min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
 				max = Vector3i(1, 1, 1);
 
 				for (int j = 0; j < 8; j++) {
@@ -753,9 +755,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 				kernel_size = max - min;
 			} else {
 				// Volume type global runs on all cells
-				extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+				extents = Vector3(fog->width, fog->height, fog->depth);
 				min = Vector3i(0, 0, 0);
-				kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth));
+				kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth));
 			}
 
 			if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
@@ -777,7 +779,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 
 			RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
 
-			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
 			RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant));
 			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
 			if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
@@ -795,7 +797,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 		RD::get_singleton()->compute_list_end();
 	}
 
-	if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) {
+	if (fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->process_uniform_set_density)) {
 		//re create uniform set if needed
 		Vector<RD::Uniform> uniforms;
 		Vector<RD::Uniform> copy_uniforms;
@@ -875,7 +877,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 8;
-			u.append_id(p_settings.vfog->light_density_map);
+			u.append_id(fog->light_density_map);
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -884,7 +886,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 9;
-			u.append_id(p_settings.vfog->fog_map);
+			u.append_id(fog->fog_map);
 			uniforms.push_back(u);
 		}
 
@@ -892,7 +894,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 9;
-			u.append_id(p_settings.vfog->prev_light_density_map);
+			u.append_id(fog->prev_light_density_map);
 			copy_uniforms.push_back(u);
 		}
 
@@ -909,7 +911,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.binding = 11;
-			u.append_id(p_settings.voxel_gl_buffer);
+			u.append_id(p_settings.voxel_gi_buffer);
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -944,7 +946,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 15;
-			u.append_id(p_settings.vfog->prev_light_density_map);
+			u.append_id(fog->prev_light_density_map);
 			uniforms.push_back(u);
 		}
 		{
@@ -955,7 +957,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 			u.binding = 16;
-			u.append_id(p_settings.vfog->density_map);
+			u.append_id(fog->density_map);
 			uniforms.push_back(u);
 		}
 		{
@@ -966,7 +968,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 			u.binding = 17;
-			u.append_id(p_settings.vfog->light_map);
+			u.append_id(fog->light_map);
 			uniforms.push_back(u);
 		}
 
@@ -978,7 +980,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 			u.binding = 18;
-			u.append_id(p_settings.vfog->emissive_map);
+			u.append_id(fog->emissive_map);
 			uniforms.push_back(u);
 		}
 
@@ -992,9 +994,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 			uniforms.push_back(u);
 		}
 
-		p_settings.vfog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
+		fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
 
-		p_settings.vfog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
+		fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
 
 		RID aux7 = uniforms.write[7].get_id(0);
 		RID aux8 = uniforms.write[8].get_id(0);
@@ -1002,17 +1004,17 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 		uniforms.write[7].set_id(0, aux8);
 		uniforms.write[8].set_id(0, aux7);
 
-		p_settings.vfog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
+		fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
 
 		uniforms.remove_at(8);
 		uniforms.write[7].set_id(0, aux7);
-		p_settings.vfog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
+		fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
 	}
 
-	bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi != nullptr);
+	bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi.is_valid());
 
 	if (using_sdfgi) {
-		if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) {
+		if (fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->sdfgi_uniform_set)) {
 			Vector<RD::Uniform> uniforms;
 
 			{
@@ -1039,12 +1041,12 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 				uniforms.push_back(u);
 			}
 
-			p_settings.vfog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
+			fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
 		}
 	}
 
-	p_settings.vfog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
-	p_settings.vfog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
+	fog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
+	fog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
 
 	VolumetricFogShader::ParamsUBO params;
 
@@ -1079,9 +1081,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 	params.ambient_color[2] = ambient_color.b;
 	params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env);
 
-	params.fog_volume_size[0] = p_settings.vfog->width;
-	params.fog_volume_size[1] = p_settings.vfog->height;
-	params.fog_volume_size[2] = p_settings.vfog->depth;
+	params.fog_volume_size[0] = fog->width;
+	params.fog_volume_size[1] = fog->height;
+	params.fog_volume_size[2] = fog->depth;
 
 	params.directional_light_count = p_directional_light_count;
 
@@ -1149,19 +1151,19 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 
 	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
 
-	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set_density, 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set_density, 0);
 
 	if (using_sdfgi) {
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->sdfgi_uniform_set, 1);
 	}
-	RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+	RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
 	RD::get_singleton()->compute_list_add_barrier(compute_list);
 
 	// Copy fog to history buffer
 	if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) {
 		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->copy_uniform_set, 0);
-		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->copy_uniform_set, 0);
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
 		RD::get_singleton()->compute_list_add_barrier(compute_list);
 	}
 	RD::get_singleton()->draw_command_end_label();
@@ -1172,8 +1174,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 		RENDER_TIMESTAMP("Filter Fog");
 
 		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0);
-		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0);
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
 
 		RD::get_singleton()->compute_list_end();
 		//need restart for buffer update
@@ -1183,8 +1185,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 
 		compute_list = RD::get_singleton()->compute_list_begin();
 		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set2, 0);
-		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set2, 0);
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
 
 		RD::get_singleton()->compute_list_add_barrier(compute_list);
 		RD::get_singleton()->draw_command_end_label();
@@ -1194,8 +1196,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
 	RD::get_singleton()->draw_command_begin_label("Integrate Fog");
 
 	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
-	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0);
-	RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0);
+	RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1);
 
 	RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
 

+ 15 - 6
servers/rendering/renderer_rd/environment/fog.h

@@ -38,8 +38,11 @@
 #include "servers/rendering/renderer_rd/environment/gi.h"
 #include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
 #include "servers/rendering/storage/utilities.h"
 
+#define RB_SCOPE_FOG SNAME("Fog")
+
 namespace RendererRD {
 
 class Fog : public RendererFog {
@@ -261,7 +264,10 @@ public:
 	void fog_instance_free(RID p_rid);
 
 	/* Volumetric FOG */
-	struct VolumetricFog {
+	class VolumetricFog : public RenderBufferCustomDataRD {
+		GDCLASS(VolumetricFog, RenderBufferCustomDataRD)
+
+	public:
 		enum {
 			MAX_TEMPORAL_FRAMES = 16
 		};
@@ -290,7 +296,10 @@ public:
 
 		int last_shadow_filter = -1;
 
-		VolumetricFog(const Vector3i &fog_size, RID p_sky_shader);
+		virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
+		virtual void free_data() override{};
+
+		void init(const Vector3i &fog_size, RID p_sky_shader);
 		~VolumetricFog();
 	};
 
@@ -304,7 +313,7 @@ public:
 		uint32_t max_cluster_elements;
 		bool volumetric_fog_filter_active;
 		RID shadow_sampler;
-		RID voxel_gl_buffer;
+		RID voxel_gi_buffer;
 		RID shadow_atlas_depth;
 		RID omni_light_buffer;
 		RID spot_light_buffer;
@@ -312,11 +321,11 @@ public:
 		RID directional_light_buffer;
 
 		// Objects related to our render buffer
-		VolumetricFog *vfog;
+		Ref<VolumetricFog> vfog;
 		ClusterBuilderRD *cluster_builder;
 		GI *gi;
-		GI::SDFGI *sdfgi;
-		GI::RenderBuffersGI *rbgi;
+		Ref<GI::SDFGI> sdfgi;
+		Ref<GI::RenderBuffersGI> rbgi;
 		RID env;
 		SkyRD *sky;
 	};

+ 114 - 129
servers/rendering/renderer_rd/environment/gi.cpp

@@ -34,6 +34,7 @@
 #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
 #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
 #include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
 #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_server_default.h"
 
@@ -384,6 +385,13 @@ RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
 	return voxel_gi->sdf_texture;
 }
 
+Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const {
+	VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+	ERR_FAIL_COND_V(!voxel_gi, nullptr);
+
+	return &voxel_gi->dependency;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // SDFGI
 
@@ -1121,7 +1129,11 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
 	reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);
 }
 
-void GI::SDFGI::erase() {
+void GI::SDFGI::free_data() {
+	// we don't free things here, we handle SDFGI differently at the moment destructing the object when it needs to change.
+}
+
+GI::SDFGI::~SDFGI() {
 	for (uint32_t i = 0; i < cascades.size(); i++) {
 		const SDFGI::Cascade &c = cascades[i];
 		RD::get_singleton()->free(c.light_data);
@@ -1982,10 +1994,9 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
 	}
 }
 
-void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) {
+void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) {
 	//print_line("rendering region " + itos(p_region));
-	RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
-	ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
+	ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but...
 	AABB bounds;
 	Vector3i from;
 	Vector3i size;
@@ -2342,9 +2353,8 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr
 	}
 }
 
-void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
-	RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
-	ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
+void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
+	ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but...
 
 	RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights");
 
@@ -3572,25 +3582,27 @@ void GI::free() {
 	}
 }
 
-GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
-	SDFGI *sdfgi = memnew(SDFGI);
+Ref<GI::SDFGI> GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
+	Ref<SDFGI> sdfgi;
+	sdfgi.instantiate();
 
 	sdfgi->create(p_env, p_world_position, p_requested_history_size, this);
 
 	return sdfgi;
 }
 
-void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
+void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
+	ERR_FAIL_COND(p_render_buffers.is_null());
+
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	ERR_FAIL_NULL(texture_storage);
 
 	r_voxel_gi_instances_used = 0;
 
-	// feels a little dirty to use our container this way but....
-	RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
-	ERR_FAIL_COND(rb == nullptr);
-
-	RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers);
+	Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
+	ERR_FAIL_COND(rbgi.is_null());
 
+	RID voxel_gi_buffer = rbgi->get_voxel_gi_buffer();
 	VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES];
 
 	bool voxel_gi_instances_changed = false;
@@ -3601,7 +3613,7 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff
 	for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
 		RID texture;
 		if (i < (int)p_voxel_gi_instances.size()) {
-			VoxelGIInstance *gipi = get_probe_instance(p_voxel_gi_instances[i]);
+			VoxelGIInstance *gipi = voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]);
 
 			if (gipi) {
 				texture = gipi->texture;
@@ -3653,28 +3665,30 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff
 			texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
 		}
 
-		if (texture != rb->rbgi.voxel_gi_textures[i]) {
+		if (texture != rbgi->voxel_gi_textures[i]) {
 			voxel_gi_instances_changed = true;
-			rb->rbgi.voxel_gi_textures[i] = texture;
+			rbgi->voxel_gi_textures[i] = texture;
 		}
 	}
 
 	if (voxel_gi_instances_changed) {
 		for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
-			if (RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) {
-				RD::get_singleton()->free(rb->rbgi.uniform_set[v]);
+			if (RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) {
+				RD::get_singleton()->free(rbgi->uniform_set[v]);
 			}
-			rb->rbgi.uniform_set[v] = RID();
+			rbgi->uniform_set[v] = RID();
 		}
-		if (rb->volumetric_fog) {
-			if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
-				RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
-				RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
-				RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
+		if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
+			Ref<Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
+
+			if (RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) {
+				RD::get_singleton()->free(fog->fog_uniform_set);
+				RD::get_singleton()->free(fog->process_uniform_set);
+				RD::get_singleton()->free(fog->process_uniform_set2);
 			}
-			rb->volumetric_fog->fog_uniform_set = RID();
-			rb->volumetric_fog->process_uniform_set = RID();
-			rb->volumetric_fog->process_uniform_set2 = RID();
+			fog->fog_uniform_set = RID();
+			fog->process_uniform_set = RID();
+			fog->process_uniform_set2 = RID();
 		}
 	}
 
@@ -3687,7 +3701,14 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff
 	}
 }
 
-void GI::RenderBuffersGI::free() {
+RID GI::RenderBuffersGI::get_voxel_gi_buffer() {
+	if (voxel_gi_buffer.is_null()) {
+		voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::VoxelGIData) * GI::MAX_VOXEL_GI_INSTANCES);
+	}
+	return voxel_gi_buffer;
+}
+
+void GI::RenderBuffersGI::free_data() {
 	for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
 		if (RD::get_singleton()->uniform_set_is_valid(uniform_set[v])) {
 			RD::get_singleton()->free(uniform_set[v]);
@@ -3700,28 +3721,13 @@ void GI::RenderBuffersGI::free() {
 		scene_data_ubo = RID();
 	}
 
-	if (ambient_buffer.is_valid()) {
-		RD::get_singleton()->free(ambient_buffer);
-		RD::get_singleton()->free(reflection_buffer);
-		ambient_buffer = RID();
-		reflection_buffer = RID();
-
-		// these are automatically freed when we free the textures, so just reset..
-		for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
-			ambient_slice[v] = RID();
-			reflection_slice[v] = RID();
-		}
-
-		view_count = 0;
-	}
-
 	if (voxel_gi_buffer.is_valid()) {
 		RD::get_singleton()->free(voxel_gi_buffer);
 		voxel_gi_buffer = RID();
 	}
 }
 
-void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
+void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances) {
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 
@@ -3729,65 +3735,38 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 
 	RD::get_singleton()->draw_command_begin_label("GI Render");
 
-	RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
-	ERR_FAIL_COND(rb == nullptr);
+	ERR_FAIL_COND(p_render_buffers.is_null());
 
-	if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) {
-		// Free our old buffer if applicable
-		if (rb->rbgi.ambient_buffer.is_valid()) {
-			RD::get_singleton()->free(rb->rbgi.ambient_buffer);
-			RD::get_singleton()->free(rb->rbgi.reflection_buffer);
+	Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
+	ERR_FAIL_COND(rbgi.is_null());
 
-			for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
-				rb->rbgi.ambient_slice[v] = RID();
-				rb->rbgi.reflection_slice[v] = RID();
-			}
-		}
+	Size2i internal_size = p_render_buffers->get_internal_size();
+
+	if (rbgi->using_half_size_gi != half_resolution) {
+		p_render_buffers->clear_context(RB_SCOPE_GI);
+	}
 
-		// Remember the view count we're using
-		rb->rbgi.view_count = p_view_count;
+	if (!p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) {
+		Size2i size = internal_size;
+		uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
 
-		// Create textures for our ambient and reflection data
-		RD::TextureFormat tf;
-		tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
-		tf.width = rb->internal_width;
-		tf.height = rb->internal_height;
 		if (half_resolution) {
-			tf.width >>= 1;
-			tf.height >>= 1;
-		}
-		if (p_view_count > 1) {
-			tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
-			tf.array_layers = p_view_count;
-		} else {
-			tf.texture_type = RD::TEXTURE_TYPE_2D;
-			tf.array_layers = 1;
-		}
-		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-		rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
-		RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer");
-		rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
-		RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer");
-		rb->rbgi.using_half_size_gi = half_resolution;
-
-		if (p_view_count == 1) {
-			// Just copy, we don't need to create slices
-			rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer;
-			rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer;
-		} else {
-			for (uint32_t v = 0; v < p_view_count; v++) {
-				rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0);
-				rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0);
-			}
+			size.x >>= 1;
+			size.y >>= 1;
 		}
+
+		p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_AMBIENT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size);
+		p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_REFLECTION, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size);
+
+		rbgi->using_half_size_gi = half_resolution;
 	}
 
 	// Setup our scene data
 	{
 		SceneData scene_data;
 
-		if (rb->rbgi.scene_data_ubo.is_null()) {
-			rb->rbgi.scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData));
+		if (rbgi->scene_data_ubo.is_null()) {
+			rbgi->scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData));
 		}
 
 		for (uint32_t v = 0; v < p_view_count; v++) {
@@ -3801,10 +3780,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 		// Note that we will be ignoring the origin of this transform.
 		RendererRD::MaterialStorage::store_transform(p_cam_transform, scene_data.cam_transform);
 
-		scene_data.screen_size[0] = rb->internal_width;
-		scene_data.screen_size[1] = rb->internal_height;
+		scene_data.screen_size[0] = internal_size.x;
+		scene_data.screen_size[1] = internal_size.y;
 
-		RD::get_singleton()->buffer_update(rb->rbgi.scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
+		RD::get_singleton()->buffer_update(rbgi->scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
 	}
 
 	// Now compute the contents of our buffers.
@@ -3826,22 +3805,28 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 	push_constant.z_far = p_projections[0].get_z_far();
 
 	// these are only used if we have 1 view, else we use the projections in our scene data
-	push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]);
-	push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]);
+	push_constant.proj_info[0] = -2.0f / (internal_size.x * p_projections[0].matrix[0][0]);
+	push_constant.proj_info[1] = -2.0f / (internal_size.y * p_projections[0].matrix[1][1]);
 	push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0];
 	push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1];
 
-	bool use_sdfgi = rb->sdfgi != nullptr;
+	bool use_sdfgi = p_render_buffers->has_custom_data(RB_SCOPE_SDFGI);
 	bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
 
+	Ref<SDFGI> sdfgi;
+	if (use_sdfgi) {
+		sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI);
+	}
+
 	uint32_t pipeline_specialization = 0;
-	if (rb->rbgi.using_half_size_gi) {
+	if (rbgi->using_half_size_gi) {
 		pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES;
 	}
 	if (p_view_count > 1) {
 		pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX;
 	}
-	if (p_vrs_slices[0].is_valid()) {
+	bool has_vrs_texture = p_render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE);
+	if (has_vrs_texture) {
 		pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS;
 	}
 
@@ -3851,15 +3836,15 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 		push_constant.view_index = v;
 
 		// setup our uniform set
-		if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) {
+		if (rbgi->uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) {
 			Vector<RD::Uniform> uniforms;
 			{
 				RD::Uniform u;
 				u.binding = 1;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
-					if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
-						u.append_id(rb->sdfgi->cascades[j].sdf_tex);
+					if (use_sdfgi && j < sdfgi->cascades.size()) {
+						u.append_id(sdfgi->cascades[j].sdf_tex);
 					} else {
 						u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
 					}
@@ -3871,8 +3856,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				u.binding = 2;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
-					if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
-						u.append_id(rb->sdfgi->cascades[j].light_tex);
+					if (use_sdfgi && j < sdfgi->cascades.size()) {
+						u.append_id(sdfgi->cascades[j].light_tex);
 					} else {
 						u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
 					}
@@ -3884,8 +3869,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				u.binding = 3;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
-					if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
-						u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex);
+					if (use_sdfgi && j < sdfgi->cascades.size()) {
+						u.append_id(sdfgi->cascades[j].light_aniso_0_tex);
 					} else {
 						u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
 					}
@@ -3897,8 +3882,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				u.binding = 4;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
-					if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
-						u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex);
+					if (use_sdfgi && j < sdfgi->cascades.size()) {
+						u.append_id(sdfgi->cascades[j].light_aniso_1_tex);
 					} else {
 						u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
 					}
@@ -3909,8 +3894,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 5;
-				if (rb->sdfgi) {
-					u.append_id(rb->sdfgi->occlusion_texture);
+				if (use_sdfgi) {
+					u.append_id(sdfgi->occlusion_texture);
 				} else {
 					u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
@@ -3935,7 +3920,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 9;
-				u.append_id(rb->rbgi.ambient_slice[v]);
+				u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_AMBIENT, v, 0));
 				uniforms.push_back(u);
 			}
 
@@ -3943,7 +3928,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 10;
-				u.append_id(rb->rbgi.reflection_slice[v]);
+				u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_REFLECTION, v, 0));
 				uniforms.push_back(u);
 			}
 
@@ -3951,8 +3936,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 11;
-				if (rb->sdfgi) {
-					u.append_id(rb->sdfgi->lightprobe_texture);
+				if (use_sdfgi) {
+					u.append_id(sdfgi->lightprobe_texture);
 				} else {
 					u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
 				}
@@ -3962,7 +3947,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 12;
-				u.append_id(rb->views[v].view_depth);
+				u.append_id(p_render_buffers->get_depth_texture(v));
 				uniforms.push_back(u);
 			}
 			{
@@ -3991,7 +3976,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 				u.binding = 16;
-				u.append_id(rb->rbgi.voxel_gi_buffer);
+				u.append_id(rbgi->get_voxel_gi_buffer());
 				uniforms.push_back(u);
 			}
 			{
@@ -3999,7 +3984,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 17;
 				for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
-					u.append_id(rb->rbgi.voxel_gi_textures[i]);
+					u.append_id(rbgi->voxel_gi_textures[i]);
 				}
 				uniforms.push_back(u);
 			}
@@ -4007,29 +3992,29 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 				u.binding = 18;
-				u.append_id(rb->rbgi.scene_data_ubo);
+				u.append_id(rbgi->scene_data_ubo);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 19;
-				RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS);
+				RID buffer = has_vrs_texture ? p_render_buffers->get_texture_slice(RB_SCOPE_VRS, RB_TEXTURE, v, 0) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS);
 				u.append_id(buffer);
 				uniforms.push_back(u);
 			}
 
-			rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
+			rbgi->uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
 		}
 
 		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]);
-		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rbgi->uniform_set[v], 0);
 		RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
 
-		if (rb->rbgi.using_half_size_gi) {
-			RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1);
+		if (rbgi->using_half_size_gi) {
+			RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x >> 1, internal_size.y >> 1, 1);
 		} else {
-			RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1);
+			RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x, internal_size.y, 1);
 		}
 	}
 
@@ -4053,21 +4038,21 @@ void GI::voxel_gi_instance_free(RID p_rid) {
 }
 
 void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
-	VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+	VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
 	ERR_FAIL_COND(!voxel_gi);
 
 	voxel_gi->transform = p_xform;
 }
 
 bool GI::voxel_gi_needs_update(RID p_probe) const {
-	VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+	VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
 	ERR_FAIL_COND_V(!voxel_gi, false);
 
 	return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe);
 }
 
 void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
-	VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+	VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
 	ERR_FAIL_COND(!voxel_gi);
 
 	voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render);

+ 118 - 95
servers/rendering/renderer_rd/environment/gi.h

@@ -44,10 +44,17 @@
 #include "servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/rendering/rendering_device.h"
 #include "servers/rendering/storage/utilities.h"
 
+#define RB_SCOPE_GI SNAME("rbgi")
+#define RB_SCOPE_SDFGI SNAME("sdfgi")
+
+#define RB_TEX_AMBIENT SNAME("ambient")
+#define RB_TEX_REFLECTION SNAME("reflection")
+
 // Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
 struct RenderDataRD;
 class RendererSceneRenderRD;
@@ -89,6 +96,60 @@ public:
 		Dependency dependency;
 	};
 
+	/* VOXEL_GI INSTANCE */
+
+	//@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
+
+	struct VoxelGIInstance {
+		// access to our containers
+		GI *gi = nullptr;
+
+		RID probe;
+		RID texture;
+		RID write_buffer;
+
+		struct Mipmap {
+			RID texture;
+			RID uniform_set;
+			RID second_bounce_uniform_set;
+			RID write_uniform_set;
+			uint32_t level;
+			uint32_t cell_offset;
+			uint32_t cell_count;
+		};
+		Vector<Mipmap> mipmaps;
+
+		struct DynamicMap {
+			RID texture; //color normally, or emission on first pass
+			RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
+			RID depth; //actual depth buffer for the first pass, float depth for later passes
+			RID normal; //normal buffer for the first pass
+			RID albedo; //emission buffer for the first pass
+			RID orm; //orm buffer for the first pass
+			RID fb; //used for rendering, only valid on first map
+			RID uniform_set;
+			uint32_t size;
+			int mipmap; // mipmap to write to, -1 if no mipmap assigned
+		};
+
+		Vector<DynamicMap> dynamic_maps;
+
+		int slot = -1;
+		uint32_t last_probe_version = 0;
+		uint32_t last_probe_data_version = 0;
+
+		//uint64_t last_pass = 0;
+		uint32_t render_index = 0;
+
+		bool has_dynamic_object_data = false;
+
+		Transform3D transform;
+
+		void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
+		void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+		void free_resources();
+	};
+
 private:
 	static GI *singleton;
 
@@ -98,6 +159,8 @@ private:
 
 	/* VOXEL_GI INSTANCE */
 
+	mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
+
 	struct VoxelGILight {
 		uint32_t type;
 		float energy;
@@ -370,9 +433,40 @@ private:
 public:
 	static GI *get_singleton() { return singleton; }
 
+	/* GI */
+
+	enum {
+		MAX_VOXEL_GI_INSTANCES = 8
+	};
+
+	// Struct for use in render buffer
+	class RenderBuffersGI : public RenderBufferCustomDataRD {
+		GDCLASS(RenderBuffersGI, RenderBufferCustomDataRD)
+
+	private:
+		RID voxel_gi_buffer;
+
+	public:
+		RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
+
+		RID full_buffer;
+		RID full_dispatch;
+		RID full_mask;
+
+		/* GI buffers */
+		bool using_half_size_gi = false;
+
+		RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
+		RID scene_data_ubo;
+
+		RID get_voxel_gi_buffer();
+
+		virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
+		virtual void free_data() override;
+	};
+
 	/* VOXEL GI API */
 
-	VoxelGI *get_voxel_gi(RID p_rid) { return voxel_gi_owner.get_or_null(p_rid); };
 	bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); };
 
 	virtual RID voxel_gi_allocate() override;
@@ -422,72 +516,23 @@ public:
 
 	RID voxel_gi_get_sdf_texture(RID p_voxel_gi);
 
-	/* VOXEL_GI INSTANCE */
-
-	//@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
-
-	struct VoxelGIInstance {
-		// access to our containers
-		GI *gi = nullptr;
-
-		RID probe;
-		RID texture;
-		RID write_buffer;
-
-		struct Mipmap {
-			RID texture;
-			RID uniform_set;
-			RID second_bounce_uniform_set;
-			RID write_uniform_set;
-			uint32_t level;
-			uint32_t cell_offset;
-			uint32_t cell_count;
-		};
-		Vector<Mipmap> mipmaps;
+	Dependency *voxel_gi_get_dependency(RID p_voxel_gi) const;
 
-		struct DynamicMap {
-			RID texture; //color normally, or emission on first pass
-			RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
-			RID depth; //actual depth buffer for the first pass, float depth for later passes
-			RID normal; //normal buffer for the first pass
-			RID albedo; //emission buffer for the first pass
-			RID orm; //orm buffer for the first pass
-			RID fb; //used for rendering, only valid on first map
-			RID uniform_set;
-			uint32_t size;
-			int mipmap; // mipmap to write to, -1 if no mipmap assigned
-		};
-
-		Vector<DynamicMap> dynamic_maps;
-
-		int slot = -1;
-		uint32_t last_probe_version = 0;
-		uint32_t last_probe_data_version = 0;
-
-		//uint64_t last_pass = 0;
-		uint32_t render_index = 0;
-
-		bool has_dynamic_object_data = false;
-
-		Transform3D transform;
-
-		void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
-		void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
-		void free_resources();
-	};
-
-	mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
-
-	_FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const {
-		return voxel_gi_instance_owner.get_or_null(p_probe);
-	};
+	/* VOXEL_GI INSTANCE */
 
 	_FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) {
-		VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+		VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
 		ERR_FAIL_COND_V(!voxel_gi, RID());
 		return voxel_gi->texture;
 	};
 
+	_FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) {
+		VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
+		ERR_FAIL_NULL(voxel_gi);
+
+		voxel_gi->render_index = p_index;
+	};
+
 	bool voxel_gi_instance_owns(RID p_rid) const {
 		return voxel_gi_instance_owner.owns(p_rid);
 	}
@@ -498,7 +543,10 @@ public:
 
 	/* SDFGI */
 
-	struct SDFGI {
+	class SDFGI : public RenderBufferCustomDataRD {
+		GDCLASS(SDFGI, RenderBufferCustomDataRD)
+
+	public:
 		enum {
 			MAX_CASCADES = 8,
 			CASCADE_SIZE = 128,
@@ -624,8 +672,11 @@ public:
 		int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically
 		RID integrate_sky_uniform_set;
 
+		virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
+		virtual void free_data() override;
+		~SDFGI();
+
 		void create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi);
-		void erase();
 		void update(RID p_env, const Vector3 &p_world_position);
 		void update_light();
 		void update_probes(RID p_env, RendererRD::SkyRD::Sky *p_sky);
@@ -637,8 +688,8 @@ public:
 		void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
 
 		void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render);
-		void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization);
-		void render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
+		void render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization);
+		void render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
 	};
 
 	RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
@@ -655,34 +706,6 @@ public:
 
 	int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; }
 
-	/* GI */
-	enum {
-		MAX_VOXEL_GI_INSTANCES = 8
-	};
-
-	// Struct for use in render buffer
-	struct RenderBuffersGI {
-		RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
-		RID voxel_gi_buffer;
-
-		RID full_buffer;
-		RID full_dispatch;
-		RID full_mask;
-
-		/* GI buffers */
-		RID ambient_buffer;
-		RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID reflection_buffer;
-		RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS];
-		bool using_half_size_gi = false;
-		uint32_t view_count = 1;
-
-		RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID scene_data_ubo;
-
-		void free();
-	};
-
 	struct SDFGIData {
 		float grid_size[3];
 		uint32_t max_cascades;
@@ -787,10 +810,10 @@ public:
 	void init(RendererRD::SkyRD *p_sky);
 	void free();
 
-	SDFGI *create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
+	Ref<SDFGI> create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
 
-	void setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
-	void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
+	void setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
+	void process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances);
 
 	RID voxel_gi_instance_create(RID p_base);
 	void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);

+ 7 - 5
servers/rendering/renderer_rd/environment/sky.cpp

@@ -35,6 +35,7 @@
 #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
 #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
 #include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
 #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_server_default.h"
 #include "servers/rendering/rendering_server_globals.h"
@@ -1109,7 +1110,7 @@ SkyRD::~SkyRD() {
 	RD::get_singleton()->free(index_buffer); //array gets freed as dependency
 }
 
-void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
 	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
 	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	ERR_FAIL_COND(p_env.is_null());
@@ -1294,24 +1295,25 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh
 	//setup fog variables
 	sky_scene_state.ubo.volumetric_fog_enabled = false;
 	if (p_render_buffers.is_valid()) {
-		if (p_scene_render->render_buffers_has_volumetric_fog(p_render_buffers)) {
+		if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
+			Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
 			sky_scene_state.ubo.volumetric_fog_enabled = true;
 
-			float fog_end = p_scene_render->render_buffers_get_volumetric_fog_end(p_render_buffers);
+			float fog_end = fog->length;
 			if (fog_end > 0.0) {
 				sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
 			} else {
 				sky_scene_state.ubo.volumetric_fog_inv_length = 1.0;
 			}
 
-			float fog_detail_spread = p_scene_render->render_buffers_get_volumetric_fog_detail_spread(p_render_buffers); //reverse lookup
+			float fog_detail_spread = fog->spread; //reverse lookup
 			if (fog_detail_spread > 0.0) {
 				sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
 			} else {
 				sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0;
 			}
 
-			sky_scene_state.fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
+			sky_scene_state.fog_uniform_set = fog->sky_uniform_set;
 		}
 	}
 

+ 2 - 1
servers/rendering/renderer_rd/environment/sky.h

@@ -42,6 +42,7 @@
 
 // Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
 class RendererSceneRenderRD;
+class RenderSceneBuffersRD;
 
 namespace RendererRD {
 
@@ -296,7 +297,7 @@ public:
 	void set_texture_format(RD::DataFormat p_texture_format);
 	~SkyRD();
 
-	void setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
+	void setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
 	void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
 	void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); // only called by clustered renderer
 	void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);

File diff suppressed because it is too large
+ 213 - 429
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp


+ 54 - 49
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h

@@ -33,12 +33,22 @@
 
 #include "core/templates/paged_allocator.h"
 #include "servers/rendering/renderer_rd/effects/resolve.h"
+#include "servers/rendering/renderer_rd/effects/taa.h"
 #include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h"
 #include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
 #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
 #include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h"
 #include "servers/rendering/renderer_rd/storage_rd/utilities.h"
 
+#define RB_SCOPE_FORWARD_CLUSTERED SNAME("forward_clustered")
+
+#define RB_TEX_SPECULAR SNAME("specular")
+#define RB_TEX_SPECULAR_MSAA SNAME("specular_msaa")
+#define RB_TEX_ROUGHNESS SNAME("normal_roughnesss")
+#define RB_TEX_ROUGHNESS_MSAA SNAME("normal_roughnesss_msaa")
+#define RB_TEX_VOXEL_GI SNAME("voxel_gi")
+#define RB_TEX_VOXEL_GI_MSAA SNAME("voxel_gi_msaa")
+
 namespace RendererSceneRenderImplementation {
 
 class RenderForwardClustered : public RendererSceneRenderRD {
@@ -81,73 +91,67 @@ class RenderForwardClustered : public RendererSceneRenderRD {
 
 	/* Framebuffer */
 
-	struct RenderBufferDataForwardClustered : public RenderBufferData {
-		//for rendering, may be MSAAd
-
-		RID color;
-		RID depth;
-		RID specular;
-		RID normal_roughness_buffer;
-		RID voxelgi_buffer;
-		RID velocity_buffer;
+	class RenderBufferDataForwardClustered : public RenderBufferCustomDataRD {
+		GDCLASS(RenderBufferDataForwardClustered, RenderBufferCustomDataRD)
 
-		RS::ViewportMSAA msaa;
-		RD::TextureSamples texture_samples;
-		bool use_taa;
+	private:
+		RenderSceneBuffersRD *render_buffers = nullptr;
+		RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
 
-		RID color_msaa;
-		RID depth_msaa;
-		RID specular_msaa;
-		RID normal_roughness_buffer_msaa;
-		RID voxelgi_buffer_msaa;
-		RID velocity_buffer_msaa;
+	public:
+		//for rendering, may be MSAAd
 
-		RID depth_fb;
-		RID depth_normal_roughness_fb;
-		RID depth_normal_roughness_voxelgi_fb;
-		RID color_only_fb;
-		RID specular_only_fb;
+		enum DepthFrameBufferType {
+			DEPTH_FB,
+			DEPTH_FB_ROUGHNESS,
+			DEPTH_FB_ROUGHNESS_VOXELGI
+		};
 
-		RID vrs;
+		RID render_sdfgi_uniform_set;
 
-		int width, height;
-		HashMap<uint32_t, RID> color_framebuffers;
+		RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA); }
+		RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA, p_layer, 0); }
 
-		// for multiview
-		uint32_t view_count = 1;
-		RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
-		RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
-		RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID specular_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID depth_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
-		RID vrs_views[RendererSceneRender::MAX_RENDER_VIEWS];
+		RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA); }
+		RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA, p_layer, 0); }
 
-		RID render_sdfgi_uniform_set;
 		void ensure_specular();
+		bool has_specular() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); }
+		RID get_specular() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); }
+		RID get_specular(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR, p_layer, 0); }
+		RID get_specular_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR_MSAA, p_layer, 0); }
+
+		void ensure_normal_roughness_texture();
+		bool has_normal_roughness() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); }
+		RID get_normal_roughness() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); }
+		RID get_normal_roughness(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS, p_layer, 0); }
+		RID get_normal_roughness_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA); }
+		RID get_normal_roughness_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA, p_layer, 0); }
+
 		void ensure_voxelgi();
-		void ensure_velocity();
-		void clear();
-		virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
+		bool has_voxelgi() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); }
+		RID get_voxelgi() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); }
+		RID get_voxelgi(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI, p_layer, 0); }
+		RID get_voxelgi_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI_MSAA, p_layer, 0); }
+
+		RID get_color_only_fb();
 		RID get_color_pass_fb(uint32_t p_color_pass_flags);
+		RID get_depth_fb(DepthFrameBufferType p_type = DEPTH_FB);
+		RID get_specular_only_fb();
 
-		~RenderBufferDataForwardClustered();
+		virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
+		virtual void free_data() override;
 	};
 
-	virtual RenderBufferData *_create_render_buffer_data() override;
-	void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb);
+	virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
 
 	RID render_base_uniform_set;
 
 	uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
 
 	virtual void _base_uniforms_changed() override;
-	virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
-	virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
+	virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
+	virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
 
 	bool base_uniform_set_updated = false;
 	void _update_render_base_uniform_set();
@@ -612,6 +616,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
 	virtual void _update_shader_quality_settings() override;
 
 	RendererRD::Resolve *resolve_effects = nullptr;
+	RendererRD::TAA *taa = nullptr;
 
 protected:
 	virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
@@ -623,7 +628,7 @@ protected:
 
 	virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
 	virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
-	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
+	virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
 	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
 
 public:

+ 166 - 205
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

@@ -69,183 +69,175 @@ void RenderForwardMobile::_map_forward_id(ForwardIDType p_type, ForwardID p_id,
 
 /* Render buffer */
 
-void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
-	if (color_msaa.is_valid()) {
-		RD::get_singleton()->free(color_msaa);
-		color_msaa = RID();
+void RenderForwardMobile::RenderBufferDataForwardMobile::free_data() {
+	// this should already be done but JIC..
+	if (render_buffers) {
+		render_buffers->clear_context(RB_SCOPE_MOBILE);
 	}
+}
 
-	if (depth_msaa.is_valid()) {
-		RD::get_singleton()->free(depth_msaa);
-		depth_msaa = RID();
+void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBuffersRD *p_render_buffers) {
+	if (render_buffers) {
+		// JIC
+		free_data();
 	}
 
-	color = RID();
-	depth = RID();
-	for (int i = 0; i < FB_CONFIG_MAX; i++) {
-		color_fbs[i] = RID();
-	}
-}
+	render_buffers = p_render_buffers;
+	ERR_FAIL_NULL(render_buffers); // Huh? really?
 
-void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) {
-	clear();
+	RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d();
+	if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
+		// Create our MSAA textures...
 
-	msaa = p_msaa;
-	vrs = p_vrs_texture;
+		RD::DataFormat format = render_buffers->get_base_data_format();
+		uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
 
-	Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer);
+		const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
+			RD::TEXTURE_SAMPLES_1,
+			RD::TEXTURE_SAMPLES_2,
+			RD::TEXTURE_SAMPLES_4,
+			RD::TEXTURE_SAMPLES_8,
+		};
 
-	width = p_width;
-	height = p_height;
-	bool is_scaled = (target_size.width != p_width) || (target_size.height != p_height);
-	view_count = p_view_count;
+		texture_samples = ts[msaa_3d];
 
-	color = p_color_buffer;
-	depth = p_depth_buffer;
+		render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples);
 
-	// We are creating 4 configurations here for our framebuffers.
+		format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+		usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
 
-	if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
-		Vector<RID> fb;
-		fb.push_back(p_color_buffer); // 0 - color buffer
-		fb.push_back(depth); // 1 - depth buffer
-		if (vrs.is_valid()) {
-			fb.push_back(vrs); // 2 - vrs texture
-		}
+		render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples);
+	}
+}
 
-		// Now define our subpasses
-		Vector<RD::FramebufferPass> passes;
-		RD::FramebufferPass pass;
+RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type) {
+	ERR_FAIL_NULL_V(render_buffers, RID());
 
-		// re-using the same attachments
-		pass.color_attachments.push_back(0);
-		pass.depth_attachment = 1;
-		if (vrs.is_valid()) {
-			pass.vrs_attachment = 2;
-		}
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	ERR_FAIL_NULL_V(texture_storage, RID());
 
-		// - opaque pass
-		passes.push_back(pass);
-		color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+	// We use our framebuffer cache here instead of building these in RenderBufferDataForwardMobile::configure
+	// This approach ensures we only build the framebuffers we actually need for this viewport.
+	// In the (near) future this means that if we cycle through a texture chain for our render target, we'll also support
+	// this.
 
-		// - add sky pass
-		passes.push_back(pass);
-		color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+	RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d();
+	bool use_msaa = msaa_3d != RS::VIEWPORT_MSAA_DISABLED;
 
-		// - add alpha pass
-		passes.push_back(pass);
-		color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+	uint32_t view_count = render_buffers->get_view_count();
 
-		if (!is_scaled) {
-			// - add blit to 2D pass
-			int target_buffer_id = fb.size();
-			fb.push_back(p_target_buffer); // 2/3 - target buffer
+	RID vrs_texture;
+	if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) {
+		vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
+	}
 
-			RD::FramebufferPass blit_pass;
-			blit_pass.color_attachments.push_back(target_buffer_id);
-			blit_pass.input_attachments.push_back(0);
-			passes.push_back(blit_pass); // this doesn't need VRS
+	Vector<RID> textures;
+	int color_buffer_id = 0;
+	textures.push_back(use_msaa ? get_color_msaa() : render_buffers->get_internal_texture()); // 0 - color buffer
+	textures.push_back(use_msaa ? get_depth_msaa() : render_buffers->get_depth_texture()); // 1 - depth buffer
+	if (vrs_texture.is_valid()) {
+		textures.push_back(vrs_texture); // 2 - vrs texture
+	}
+	if (use_msaa) {
+		color_buffer_id = textures.size();
+		textures.push_back(render_buffers->get_internal_texture()); // color buffer for resolve
 
-			color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
-		} else {
-			// can't do our blit pass if resolutions don't match
-			color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
-		}
-	} else {
-		RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
+		// TODO add support for resolving depth buffer!!!
+	}
 
-		RD::TextureFormat tf;
-		if (view_count > 1) {
-			tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
-		} else {
-			tf.texture_type = RD::TEXTURE_TYPE_2D;
-		}
-		tf.format = color_format;
-		tf.width = p_width;
-		tf.height = p_height;
-		tf.array_layers = view_count; // create a layer for every view
-		tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+	// Now define our subpasses
+	Vector<RD::FramebufferPass> passes;
 
-		const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
-			RD::TEXTURE_SAMPLES_1,
-			RD::TEXTURE_SAMPLES_2,
-			RD::TEXTURE_SAMPLES_4,
-			RD::TEXTURE_SAMPLES_8,
-		};
+	// Define our base pass, we'll be re-using this
+	RD::FramebufferPass pass;
+	pass.color_attachments.push_back(0);
+	pass.depth_attachment = 1;
+	if (vrs_texture.is_valid()) {
+		pass.vrs_attachment = 2;
+	}
+
+	switch (p_config_type) {
+		case FB_CONFIG_ONE_PASS: {
+			// just one pass
+			if (use_msaa) {
+				// Add resolve
+				pass.resolve_attachments.push_back(color_buffer_id);
+			}
+			passes.push_back(pass);
 
-		texture_samples = ts[p_msaa];
-		tf.samples = texture_samples;
+			return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
+		} break;
+		case FB_CONFIG_TWO_SUBPASSES: {
+			// - opaque pass
+			passes.push_back(pass);
 
-		color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+			// - add sky pass
+			if (use_msaa) {
+				// add resolve
+				pass.resolve_attachments.push_back(color_buffer_id);
+			}
+			passes.push_back(pass);
 
-		tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
-		tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+			return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
+		} break;
+		case FB_CONFIG_THREE_SUBPASSES: {
+			// - opaque pass
+			passes.push_back(pass);
 
-		depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+			// - add sky pass
+			passes.push_back(pass);
 
-		{
-			Vector<RID> fb;
-			fb.push_back(color_msaa); // 0 - msaa color buffer
-			fb.push_back(depth_msaa); // 1 - msaa depth buffer
-			if (vrs.is_valid()) {
-				fb.push_back(vrs); // 2 - vrs texture
+			// - add alpha pass
+			if (use_msaa) {
+				// add resolve
+				pass.resolve_attachments.push_back(color_buffer_id);
 			}
+			passes.push_back(pass);
 
-			// Now define our subpasses
-			Vector<RD::FramebufferPass> passes;
-			RD::FramebufferPass pass;
+			return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
+		} break;
+		case FB_CONFIG_FOUR_SUBPASSES: {
+			Size2i target_size = render_buffers->get_target_size();
+			Size2i internal_size = render_buffers->get_internal_size();
 
-			// re-using the same attachments
-			pass.color_attachments.push_back(0);
-			pass.depth_attachment = 1;
-			if (vrs.is_valid()) {
-				pass.vrs_attachment = 2;
-			}
+			// can't do our blit pass if resolutions don't match
+			ERR_FAIL_COND_V(target_size != internal_size, RID());
 
 			// - opaque pass
 			passes.push_back(pass);
 
 			// - add sky pass
-			int color_buffer_id = fb.size();
-			fb.push_back(color); // color buffer
-			passes.push_back(pass); // without resolve for our 3 + 4 subpass config
-			{
-				// but with resolve for our 2 subpass config
-				Vector<RD::FramebufferPass> two_passes;
-				two_passes.push_back(pass); // opaque subpass without resolve
-				pass.resolve_attachments.push_back(color_buffer_id);
-				two_passes.push_back(pass); // sky subpass with resolve
+			passes.push_back(pass);
 
-				color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count);
+			// - add alpha pass
+			if (use_msaa) {
+				// add resolve
+				pass.resolve_attachments.push_back(color_buffer_id);
 			}
-
-			// - add alpha pass (with resolve, we just added that above)
 			passes.push_back(pass);
-			color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
 
-			{
-				// we also need our one pass with resolve
-				Vector<RD::FramebufferPass> one_pass_with_resolve;
-				one_pass_with_resolve.push_back(pass); // note our pass configuration already has resolve..
-				color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count);
-			}
+			// - add blit to 2D pass
+			RID render_target = render_buffers->get_render_target();
+			ERR_FAIL_COND_V(render_target.is_null(), RID());
+			RID target_buffer = texture_storage->render_target_get_rd_texture(render_target);
+			ERR_FAIL_COND_V(target_buffer.is_null(), RID());
 
-			if (!is_scaled) {
-				// - add blit to 2D pass
-				int target_buffer_id = fb.size();
-				fb.push_back(p_target_buffer); // target buffer
-				RD::FramebufferPass blit_pass;
-				blit_pass.color_attachments.push_back(target_buffer_id);
-				blit_pass.input_attachments.push_back(color_buffer_id);
-				passes.push_back(blit_pass);
+			int target_buffer_id = textures.size();
+			textures.push_back(target_buffer); // target buffer
 
-				color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
-			} else {
-				// can't do our blit pass if resolutions don't match
-				color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
-			}
-		}
-	}
+			RD::FramebufferPass blit_pass;
+			blit_pass.input_attachments.push_back(color_buffer_id); // Read from our (resolved) color buffer
+			blit_pass.color_attachments.push_back(target_buffer_id); // Write into our target buffer
+			// this doesn't need VRS
+			passes.push_back(blit_pass);
+
+			return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
+		} break;
+		default:
+			break;
+	};
+
+	return RID();
 }
 
 RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_depth) {
@@ -274,12 +266,11 @@ RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_
 	return RD::get_singleton()->framebuffer_create_multipass(fb, passes);
 }
 
-RenderForwardMobile::RenderBufferDataForwardMobile::~RenderBufferDataForwardMobile() {
-	clear();
-}
+void RenderForwardMobile::setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) {
+	Ref<RenderBufferDataForwardMobile> data;
+	data.instantiate();
 
-RendererSceneRenderRD::RenderBufferData *RenderForwardMobile::_create_render_buffer_data() {
-	return memnew(RenderBufferDataForwardMobile);
+	p_render_buffers->set_custom_data(RB_SCOPE_MOBILE, data);
 }
 
 bool RenderForwardMobile::free(RID p_rid) {
@@ -314,9 +305,11 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 	//there should always be enough uniform buffers for render passes, otherwise bugs
 	ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
 
-	RenderBufferDataForwardMobile *rb = nullptr;
+	Ref<RenderBufferDataForwardMobile> rb_data;
+	Ref<RenderSceneBuffersRD> rb;
 	if (p_render_data && p_render_data->render_buffers.is_valid()) {
-		rb = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
+		rb = p_render_data->render_buffers;
+		rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
 	}
 
 	// default render buffer and scene state uniform set
@@ -442,8 +435,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		RD::Uniform u;
 		u.binding = 9;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
-		RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
+		RID texture;
+		if (rb.is_valid() && rb->has_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH)) {
+			texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH);
+		} else {
+			texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
+		}
 		u.append_id(texture);
 		uniforms.push_back(u);
 	}
@@ -451,7 +448,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		RD::Uniform u;
 		u.binding = 10;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
+		RID bbt = rb_data.is_valid() ? rb->get_back_buffer_texture() : RID();
 		RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
 		u.append_id(texture);
 		uniforms.push_back(u);
@@ -500,9 +497,9 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co
 }
 
 void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
-	RenderBufferDataForwardMobile *render_buffer = nullptr;
+	Ref<RenderBufferDataForwardMobile> rb_data;
 	if (p_render_data->render_buffers.is_valid()) {
-		render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
+		rb_data = p_render_data->render_buffers->get_custom_data(RB_SCOPE_MOBILE);
 	}
 
 	RENDER_TIMESTAMP("Setup 3D Scene");
@@ -538,12 +535,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 		p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size();
 	}
 
-	if (render_buffer) {
+	if (rb_data.is_valid()) {
 		// setup rendering to render buffer
-		screen_size.x = render_buffer->width;
-		screen_size.y = render_buffer->height;
+		screen_size = p_render_data->render_buffers->get_internal_size();
 
-		if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) {
+		if (rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) {
 			// can't do blit subpass
 			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))) {
@@ -559,13 +555,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 
 		if (using_subpass_post_process) {
 			// all as subpasses
-			framebuffer = render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES];
+			framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES);
 		} else if (using_subpass_transparent) {
 			// our tonemap pass is separate
-			framebuffer = render_buffer->color_fbs[FB_CONFIG_THREE_SUBPASSES];
+			framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_THREE_SUBPASSES);
 		} else {
 			// only opaque and sky as subpasses
-			framebuffer = render_buffer->color_fbs[FB_CONFIG_TWO_SUBPASSES];
+			framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_TWO_SUBPASSES);
 		}
 	} else if (p_render_data->reflection_probe.is_valid()) {
 		uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
@@ -626,7 +622,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 				clear_color.g *= bg_energy_multiplier;
 				clear_color.b *= bg_energy_multiplier;
 				/*
-				if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
+				if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
 					draw_sky_fog_only = true;
 					RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
 				}
@@ -638,7 +634,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 				clear_color.g *= bg_energy_multiplier;
 				clear_color.b *= bg_energy_multiplier;
 				/*
-				if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
+				if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
 					draw_sky_fog_only = true;
 					RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
 				}
@@ -708,7 +704,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 	}
 
 	RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS];
-	_pre_opaque_render(p_render_data, false, false, false, nullrids, RID(), nullrids);
+	_pre_opaque_render(p_render_data, false, false, false, nullrids, RID());
 
 	uint32_t spec_constant_base_flags = 0;
 
@@ -728,7 +724,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 		}
 	}
 	{
-		if (render_buffer) {
+		if (rb_data.is_valid()) {
 			RD::get_singleton()->draw_command_begin_label("Render 3D Pass");
 		} else {
 			RD::get_singleton()->draw_command_begin_label("Render Reflection Probe Pass");
@@ -759,8 +755,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 			// regular forward for now
 			Vector<Color> c;
 			c.push_back(clear_color.srgb_to_linear()); // our render buffer
-			if (render_buffer) {
-				if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+			if (rb_data.is_valid()) {
+				if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
 					c.push_back(clear_color.srgb_to_linear()); // our resolve buffer
 				}
 				if (using_subpass_post_process) {
@@ -859,8 +855,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 			// note if we are using MSAA we should get an automatic resolve through our subpass configuration.
 
 			// blit to tonemap
-			if (render_buffer && using_subpass_post_process) {
-				_post_process_subpass(render_buffer->color, framebuffer, p_render_data);
+			if (rb_data.is_valid() && using_subpass_post_process) {
+				_post_process_subpass(p_render_data->render_buffers->get_internal_texture(), framebuffer, p_render_data);
 			}
 
 			RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
@@ -869,7 +865,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 		} else {
 			RENDER_TIMESTAMP("Render Transparent");
 
-			framebuffer = render_buffer->color_fbs[FB_CONFIG_ONE_PASS];
+			framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
 
 			// this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation
 			// _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
@@ -897,7 +893,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 		}
 	}
 
-	if (render_buffer && !using_subpass_post_process) {
+	if (rb_data.is_valid() && !using_subpass_post_process) {
 		RD::get_singleton()->draw_command_begin_label("Post process pass");
 
 		// If we need extra effects we do this in its own pass
@@ -908,7 +904,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 		RD::get_singleton()->draw_command_end_label(); // Post process pass
 	}
 
-	if (render_buffer) {
+	if (rb_data.is_valid()) {
 		_disable_clear_request(p_render_data);
 	}
 }
@@ -1132,7 +1128,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *>
 	RD::get_singleton()->draw_command_end_label();
 }
 
-void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
+void RenderForwardMobile::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
 	// we don't do GI in low end..
 }
 
@@ -1364,15 +1360,11 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 	}
 }
 
-RID RenderForwardMobile::_render_buffers_get_normal_texture(RID p_render_buffers) {
-	// RenderBufferDataForwardMobile *rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_buffers);
-
-	// We don't have this. This is for debugging
-	// return rb->normal_roughness_buffer;
+RID RenderForwardMobile::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
 	return RID();
 }
 
-RID RenderForwardMobile::_render_buffers_get_velocity_texture(RID p_render_buffers) {
+RID RenderForwardMobile::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
 	return RID();
 }
 
@@ -1625,37 +1617,6 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
 	//time global variables
 	scene_state.ubo.time = time;
 
-	/*
-	scene_state.ubo.gi_upscale_for_msaa = false;
-	scene_state.ubo.volumetric_fog_enabled = false;
-	scene_state.ubo.fog_enabled = false;
-
-	if (p_render_data->render_buffers.is_valid()) {
-		RenderBufferDataForwardMobile *render_buffers = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
-		if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {
-			scene_state.ubo.gi_upscale_for_msaa = true;
-		}
-
-		if (render_buffers_has_volumetric_fog(p_render_data->render_buffers)) {
-			scene_state.ubo.volumetric_fog_enabled = true;
-			float fog_end = render_buffers_get_volumetric_fog_end(p_render_data->render_buffers);
-			if (fog_end > 0.0) {
-				scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
-			} else {
-				scene_state.ubo.volumetric_fog_inv_length = 1.0;
-			}
-
-			float fog_detail_spread = render_buffers_get_volumetric_fog_detail_spread(p_render_data->render_buffers); //reverse lookup
-			if (fog_detail_spread > 0.0) {
-				scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
-			} else {
-				scene_state.ubo.volumetric_fog_detail_spread = 1.0;
-			}
-		}
-	}
-
-	*/
-
 	if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
 		scene_state.ubo.use_ambient_light = true;
 		scene_state.ubo.ambient_light_color_energy[0] = 1;

+ 30 - 33
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h

@@ -37,6 +37,8 @@
 #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
 #include "servers/rendering/renderer_rd/storage_rd/utilities.h"
 
+#define RB_SCOPE_MOBILE SNAME("mobile")
+
 namespace RendererSceneRenderImplementation {
 
 class RenderForwardMobile : public RendererSceneRenderRD {
@@ -107,43 +109,38 @@ protected:
 
 	/* Render Buffer */
 
-	// We can have:
-	// - 4 subpasses combining the full render cycle
-	// - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
-	// - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
-	enum RenderBufferMobileFramebufferConfigType {
-		FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
-		FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
-		FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
-		FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
-		FB_CONFIG_MAX
-	};
-
-	struct RenderBufferDataForwardMobile : public RenderBufferData {
-		RID color;
-		RID depth;
-		// RID normal_roughness_buffer;
+	class RenderBufferDataForwardMobile : public RenderBufferCustomDataRD {
+		GDCLASS(RenderBufferDataForwardMobile, RenderBufferCustomDataRD);
 
-		RS::ViewportMSAA msaa;
-		RD::TextureSamples texture_samples;
-
-		RID color_msaa;
-		RID depth_msaa;
-		// RID normal_roughness_buffer_msaa;
+	public:
+		// We can have:
+		// - 4 subpasses combining the full render cycle
+		// - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
+		// - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
+		enum FramebufferConfigType {
+			FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
+			FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
+			FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
+			FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
+			FB_CONFIG_MAX
+		};
 
-		RID vrs;
+		RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA); }
+		RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, p_layer, 0); }
 
-		RID color_fbs[FB_CONFIG_MAX];
-		int width, height;
-		uint32_t view_count;
+		RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA); }
+		RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, p_layer, 0); }
 
-		void clear();
-		virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
+		RID get_color_fbs(FramebufferConfigType p_config_type);
+		virtual void free_data() override;
+		virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
 
-		~RenderBufferDataForwardMobile();
+	private:
+		RenderSceneBuffersRD *render_buffers = nullptr;
+		RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
 	};
 
-	virtual RenderBufferData *_create_render_buffer_data() override;
+	virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
 
 	/* Rendering */
 
@@ -218,15 +215,15 @@ protected:
 
 	virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
 	virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
-	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
+	virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
 	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
 
 	uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
 
 	virtual void _base_uniforms_changed() override;
 	void _update_render_base_uniform_set();
-	virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
-	virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
+	virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
+	virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
 
 	void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
 	void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1);

+ 2 - 2
servers/rendering/renderer_rd/framebuffer_cache_rd.h

@@ -200,7 +200,7 @@ public:
 	RID get_cache(Args... args) {
 		uint32_t h = hash_murmur3_one_32(1); //1 view
 		h = hash_murmur3_one_32(sizeof...(Args), h);
-		h = _hash_args(h, args...);
+		h = _hash_rids(h, args...);
 		h = hash_murmur3_one_32(0, h); // 0 passes
 		h = hash_fmix32(h);
 
@@ -228,7 +228,7 @@ public:
 	RID get_cache_multiview(uint32_t p_views, Args... args) {
 		uint32_t h = hash_murmur3_one_32(p_views);
 		h = hash_murmur3_one_32(sizeof...(Args), h);
-		h = _hash_args(h, args...);
+		h = _hash_rids(h, args...);
 		h = hash_murmur3_one_32(0, h); // 0 passes
 		h = hash_fmix32(h);
 

File diff suppressed because it is too large
+ 234 - 508
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp


+ 31 - 168
servers/rendering/renderer_rd/renderer_scene_render_rd.h

@@ -37,18 +37,21 @@
 #include "servers/rendering/renderer_rd/cluster_builder_rd.h"
 #include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
 #include "servers/rendering/renderer_rd/effects/copy_effects.h"
+#include "servers/rendering/renderer_rd/effects/fsr.h"
 #include "servers/rendering/renderer_rd/effects/ss_effects.h"
 #include "servers/rendering/renderer_rd/effects/tone_mapper.h"
 #include "servers/rendering/renderer_rd/effects/vrs.h"
 #include "servers/rendering/renderer_rd/environment/fog.h"
 #include "servers/rendering/renderer_rd/environment/gi.h"
 #include "servers/rendering/renderer_rd/environment/sky.h"
+#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
 #include "servers/rendering/renderer_scene.h"
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/rendering/rendering_device.h"
 
 struct RenderDataRD {
-	RID render_buffers;
+	Ref<RenderSceneBuffersRD> render_buffers;
 
 	Transform3D cam_transform;
 	Projection cam_projection;
@@ -104,15 +107,12 @@ protected:
 	RendererRD::BokehDOF *bokeh_dof = nullptr;
 	RendererRD::CopyEffects *copy_effects = nullptr;
 	RendererRD::ToneMapper *tone_mapper = nullptr;
+	RendererRD::FSR *fsr = nullptr;
 	RendererRD::VRS *vrs = nullptr;
 	double time = 0.0;
 	double time_step = 0.0;
 
-	struct RenderBufferData {
-		virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) = 0;
-		virtual ~RenderBufferData() {}
-	};
-	virtual RenderBufferData *_create_render_buffer_data() = 0;
+	virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
 
 	void _setup_lights(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows);
 	void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
@@ -127,31 +127,28 @@ protected:
 
 	virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) = 0;
 	virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
-	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0;
+	virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0;
 	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
 
-	void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
-	void _debug_draw_cluster(RID p_render_buffers);
-
-	RenderBufferData *render_buffers_get_data(RID p_render_buffers);
+	void _debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
+	void _debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers);
 
 	virtual void _base_uniforms_changed() = 0;
-	virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
-	virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0;
+	virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
+	virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
 
-	void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
-	void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
-	void _process_sss(RID p_render_buffers, const Projection &p_camera);
-	void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
+	void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
+	void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
+	void _process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera);
+	void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
 
-	void _copy_framebuffer_to_ssil(RID p_render_buffers);
-	void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far);
+	void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers);
 
 	bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
 	void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
 	void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi);
 
-	void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices);
+	void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer);
 
 	void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
 	void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
@@ -424,131 +421,22 @@ private:
 
 	bool use_physical_light_units = false;
 
-	/* RENDER BUFFERS */
+	/* Cluster builder */
 
 	ClusterBuilderSharedDataRD cluster_builder_shared;
 	ClusterBuilderRD *current_cluster_builder = nullptr;
 
-	struct RenderBuffers {
-		RenderBufferData *data = nullptr;
-		int internal_width = 0;
-		int internal_height = 0;
-		int width = 0;
-		int height = 0;
-		float fsr_sharpness = 0.2f;
-		RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
-		RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
-		bool use_taa = false;
-		bool use_debanding = false;
-		uint32_t view_count = 1;
-
-		RID render_target;
-
-		uint64_t auto_exposure_version = 1;
-
-		RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0]
-		RID internal_texture; //main texture for rendering to, must be filled after done rendering
-		RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling)
-		RID depth_texture; //main depth texture
-		RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
-		RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
-		RID vrs_texture; // texture for vrs.
-		RID vrs_fb; // framebuffer to write to our vrs texture
-
-		// Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images)
-		struct View {
-			RID view_texture; // texture slice for this view/layer
-			RID view_depth; // depth slice for this view/layer
-			RID view_fb; // framebuffer for this view/layer, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
-		};
-		Vector<View> views;
-
-		RendererRD::GI::SDFGI *sdfgi = nullptr;
-		RendererRD::GI::RenderBuffersGI rbgi;
-		RendererRD::Fog::VolumetricFog *volumetric_fog = nullptr;
-
-		ClusterBuilderRD *cluster_builder = nullptr;
-
-		//built-in textures used for ping pong image processing and blurring
-		struct Blur {
-			RID texture;
-
-			struct Mipmap {
-				RID texture;
-				int width;
-				int height;
-
-				// only used on mobile renderer
-				RID fb;
-				RID half_texture;
-				RID half_fb;
-			};
-
-			struct Layer {
-				Vector<Mipmap> mipmaps;
-			};
-
-			Vector<Layer> layers;
-		};
-
-		Blur blur[2]; //the second one starts from the first mipmap
-
-		struct WeightBuffers {
-			RID weight;
-			RID fb; // FB with both texture and weight writing into one level lower
-		};
-
-		// 2 full size, 2 half size
-		WeightBuffers weight_buffers[4]; // Only used in raster
-
-		RID depth_back_texture;
-		RID depth_back_fb; // only used on mobile
-
-		struct Luminance {
-			Vector<RID> reduce;
-			RID current;
-
-			// used only on mobile renderer
-			Vector<RID> fb;
-			RID current_fb;
-		} luminance;
-
-		struct SSEffects {
-			RID linear_depth;
-			Vector<RID> linear_depth_slices;
-
-			RID downsample_uniform_set;
-
-			Projection last_frame_projection;
-			Transform3D last_frame_transform;
-
-			RendererRD::SSEffects::SSAORenderBuffers ssao;
-			RendererRD::SSEffects::SSILRenderBuffers ssil;
-		} ss_effects;
+	/* RENDER BUFFERS */
 
-		RendererRD::SSEffects::SSRRenderBuffers ssr;
+	void _allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb);
 
-		struct TAA {
-			RID history;
-			RID temp;
-			RID prev_velocity; // Last frame velocity buffer
-		} taa;
-	};
+	void _render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
 
 	/* GI */
 	bool screen_space_roughness_limiter = false;
 	float screen_space_roughness_limiter_amount = 0.25;
 	float screen_space_roughness_limiter_limit = 0.18;
 
-	mutable RID_Owner<RenderBuffers> render_buffers_owner;
-
-	void _free_render_buffer_data(RenderBuffers *rb);
-	void _allocate_blur_textures(RenderBuffers *rb);
-	void _allocate_depth_backbuffer_textures(RenderBuffers *rb);
-	void _allocate_luminance_textures(RenderBuffers *rb);
-
-	void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
-
 	/* Cluster */
 
 	struct Cluster {
@@ -727,11 +615,14 @@ private:
 	uint32_t volumetric_fog_depth = 128;
 	bool volumetric_fog_filter_active = true;
 
-	void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
+	void _update_volumetric_fog(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
 
 public:
 	static RendererSceneRenderRD *get_singleton() { return singleton; }
 
+	/* Cluster builder */
+	ClusterBuilderSharedDataRD *get_cluster_builder_shared() { return &cluster_builder_shared; }
+
 	/* GI */
 
 	RendererRD::GI *get_gi() { return &gi; }
@@ -774,10 +665,10 @@ public:
 
 	/* SDFGI UPDATE */
 
-	virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
-	virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const override;
-	virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override;
-	virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override;
+	virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
+	virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override;
+	virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
+	virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
 	RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
 
 	/* SKY API */
@@ -1071,42 +962,14 @@ public:
 	virtual float _render_buffers_get_luminance_multiplier();
 	virtual RD::DataFormat _render_buffers_get_color_format();
 	virtual bool _render_buffers_can_be_storage();
-	virtual RID render_buffers_create() override;
-	virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+	virtual Ref<RenderSceneBuffers> render_buffers_create() override;
 	virtual void gi_set_use_half_resolution(bool p_enable) override;
 
-	RID render_buffers_get_depth_texture(RID p_render_buffers);
-	RID render_buffers_get_ao_texture(RID p_render_buffers);
-	RID render_buffers_get_ssil_texture(RID p_render_buffers);
-	RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
-	RID render_buffers_get_back_depth_texture(RID p_render_buffers);
-	RID render_buffers_get_voxel_gi_buffer(RID p_render_buffers);
 	RID render_buffers_get_default_voxel_gi_buffer();
-	RID render_buffers_get_gi_ambient_texture(RID p_render_buffers);
-	RID render_buffers_get_gi_reflection_texture(RID p_render_buffers);
-
-	uint32_t render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const;
-	bool render_buffers_is_sdfgi_enabled(RID p_render_buffers) const;
-	RID render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const;
-	Vector3 render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const;
-	Vector3i render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const;
-	float render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const;
-	float render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const;
-	uint32_t render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const;
-	uint32_t render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const;
-	bool render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const;
-	float render_buffers_get_sdfgi_energy(RID p_render_buffers) const;
-	RID render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const;
-
-	bool render_buffers_has_volumetric_fog(RID p_render_buffers) const;
-	RID render_buffers_get_volumetric_fog_texture(RID p_render_buffers);
-	RID render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers);
-	float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
-	float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
 
 	virtual void update_uniform_sets(){};
 
-	virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+	virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
 
 	virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
 

+ 0 - 0
servers/rendering/renderer_rd/shaders/fsr_upscale.glsl → servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl


+ 0 - 0
servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl → servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl


+ 0 - 0
servers/rendering/renderer_rd/shaders/taa_resolve.glsl → servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl


+ 48 - 0
servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h

@@ -0,0 +1,48 @@
+/*************************************************************************/
+/*  render_buffer_custom_data_rd.h                                       */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef RENDER_BUFFER_CUSTOM_DATA_RD_H
+#define RENDER_BUFFER_CUSTOM_DATA_RD_H
+
+#include "core/object/ref_counted.h"
+
+class RenderSceneBuffersRD;
+
+class RenderBufferCustomDataRD : public RefCounted {
+	GDCLASS(RenderBufferCustomDataRD, RefCounted);
+
+public:
+	virtual void configure(RenderSceneBuffersRD *p_render_buffers) = 0;
+	virtual void free_data() = 0; // called on cleanup
+
+private:
+};
+
+#endif // RENDER_BUFFER_CUSTOM_DATA_RD_H

+ 559 - 0
servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp

@@ -0,0 +1,559 @@
+/*************************************************************************/
+/*  render_scene_buffers_rd.cpp                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+
+RenderSceneBuffersRD::RenderSceneBuffersRD() {
+}
+
+RenderSceneBuffersRD::~RenderSceneBuffersRD() {
+	cleanup();
+
+	data_buffers.clear();
+
+	// need to investigate if we can remove these things.
+	if (cluster_builder) {
+		memdelete(cluster_builder);
+	}
+}
+
+void RenderSceneBuffersRD::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("has_texture", "context", "name"), &RenderSceneBuffersRD::has_texture);
+	// FIXME we can't pass RD::DataFormat, RD::TextureSamples and RD::TextureView in ClassDB, need to solve views differently...
+	// ClassDB::bind_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique"), &RenderSceneBuffersRD::create_texture);
+	// ClassDB::bind_method(D_METHOD("create_texture_from_format", "context", "name", "format", "view", "unique"), &RenderSceneBuffersRD::create_texture_from_format);
+	// ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture);
+	ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture);
+	// ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format);
+	ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice);
+	ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size);
+	ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context);
+}
+
+void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) {
+	ERR_FAIL_COND(p_named_texture.texture.is_null());
+
+	uint32_t size = p_named_texture.format.array_layers * p_named_texture.format.mipmaps;
+	p_named_texture.sizes.resize(size);
+
+	Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height);
+
+	for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) {
+		for (uint32_t layer = 0; layer < p_named_texture.format.array_layers; layer++) {
+			uint32_t index = layer * p_named_texture.format.mipmaps + mipmap;
+
+			p_named_texture.sizes.ptrw()[index] = mipmap_size;
+		}
+
+		mipmap_size.width = MAX(1, mipmap_size.width >> 1);
+		mipmap_size.height = MAX(1, mipmap_size.height >> 1);
+	}
+}
+
+void RenderSceneBuffersRD::free_named_texture(NamedTexture &p_named_texture) {
+	if (p_named_texture.texture.is_valid()) {
+		RD::get_singleton()->free(p_named_texture.texture);
+	}
+	p_named_texture.texture = RID();
+	p_named_texture.slices.clear(); // slices should be freed automatically as dependents...
+}
+
+void RenderSceneBuffersRD::cleanup() {
+	// Free our data buffers (but don't destroy them)
+	for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
+		E.value->free_data();
+	}
+
+	// Clear our named textures
+	for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
+		free_named_texture(E.value);
+	}
+	named_textures.clear();
+
+	// old stuff, to be re-evaluated...
+
+	for (int i = 0; i < luminance.fb.size(); i++) {
+		RD::get_singleton()->free(luminance.fb[i]);
+	}
+	luminance.fb.clear();
+
+	for (int i = 0; i < luminance.reduce.size(); i++) {
+		RD::get_singleton()->free(luminance.reduce[i]);
+	}
+	luminance.reduce.clear();
+
+	if (luminance.current_fb.is_valid()) {
+		RD::get_singleton()->free(luminance.current_fb);
+		luminance.current_fb = RID();
+	}
+
+	if (luminance.current.is_valid()) {
+		RD::get_singleton()->free(luminance.current);
+		luminance.current = RID();
+	}
+
+	if (ss_effects.linear_depth.is_valid()) {
+		RD::get_singleton()->free(ss_effects.linear_depth);
+		ss_effects.linear_depth = RID();
+		ss_effects.linear_depth_slices.clear();
+	}
+
+	sse->ssao_free(ss_effects.ssao);
+	sse->ssil_free(ss_effects.ssil);
+	sse->ssr_free(ssr);
+}
+
+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) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+	ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
+
+	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;
+	}
+
+	if (p_use_taa) {
+		// Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness.
+		// This restores sharpness in still images to be roughly at the same level as without TAA,
+		// but moving scenes will still be blurrier.
+		p_texture_mipmap_bias -= 0.5;
+	}
+
+	if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
+		// Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness.
+		// If both TAA and FXAA are enabled, combine their negative LOD biases together.
+		p_texture_mipmap_bias -= 0.25;
+	}
+
+	material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
+
+	// need to check if we really need to do this here..
+	RendererSceneRenderRD::get_singleton()->update_uniform_sets();
+
+	render_target = p_render_target;
+	fsr_sharpness = p_fsr_sharpness;
+	msaa_3d = p_msaa_3d;
+	screen_space_aa = p_screen_space_aa;
+	use_taa = p_use_taa;
+	use_debanding = p_use_debanding;
+	view_count = p_view_count;
+
+	/* may move this into our clustered renderer data object */
+	if (can_be_storage) {
+		if (cluster_builder == nullptr) {
+			cluster_builder = memnew(ClusterBuilderRD);
+		}
+		cluster_builder->set_shared(RendererSceneRenderRD::get_singleton()->get_cluster_builder_shared());
+	}
+
+	// cleanout any old buffers we had.
+	cleanup();
+
+	// create our 3D render buffers
+	{
+		// Create our color buffer(s)
+		uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (can_be_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+		usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
+
+		// our internal texture should have MSAA support if applicable
+		if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
+			usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+		}
+
+		create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR, base_data_format, usage_bits);
+	}
+
+	// Create our depth buffer
+	{
+		// TODO If we have depth buffer supplied externally, pick this up
+
+		RD::DataFormat format;
+		uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+		if (msaa_3d == RS::VIEWPORT_MSAA_DISABLED) {
+			format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, (RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT)) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+			usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+		} else {
+			format = RD::DATA_FORMAT_R32_SFLOAT;
+			usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+		}
+
+		create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, format, usage_bits);
+	}
+
+	// VRS (note, our vrs object will only be set if VRS is supported)
+	RID vrs_texture;
+	RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
+	if (vrs && vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
+		uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+		vrs_texture = create_texture(RB_SCOPE_VRS, RB_TEXTURE, RD::DATA_FORMAT_R8_UINT, usage_bits, RD::TEXTURE_SAMPLES_1, vrs->get_vrs_texture_size(internal_size));
+	}
+
+	for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
+		E.value->configure(this);
+	}
+
+	if (cluster_builder) {
+		RID sampler = RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+		cluster_builder->setup(internal_size, max_cluster_elements, get_depth_texture(), sampler, get_internal_texture());
+	}
+}
+
+void RenderSceneBuffersRD::set_fsr_sharpness(float p_fsr_sharpness) {
+	fsr_sharpness = p_fsr_sharpness;
+}
+
+void RenderSceneBuffersRD::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+	material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
+}
+
+void RenderSceneBuffersRD::set_use_debanding(bool p_use_debanding) {
+	use_debanding = p_use_debanding;
+}
+
+// Named textures
+
+bool RenderSceneBuffersRD::has_texture(const StringName &p_context, const StringName &p_texture_name) const {
+	NTKey key(p_context, p_texture_name);
+
+	return named_textures.has(key);
+}
+
+RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique) {
+	// Keep some useful data, we use default values when these are 0.
+	Size2i size = p_size == Size2i(0, 0) ? internal_size : p_size;
+	uint32_t layers = p_layers == 0 ? view_count : p_layers;
+	uint32_t mipmaps = p_mipmaps == 0 ? 1 : p_mipmaps;
+
+	// Create our texture
+	RD::TextureFormat tf;
+	tf.format = p_data_format;
+	if (layers > 1) {
+		tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+	}
+
+	tf.width = size.x;
+	tf.height = size.y;
+	tf.depth = 1;
+	tf.array_layers = layers;
+	tf.mipmaps = mipmaps;
+	tf.usage_bits = p_usage_bits;
+	tf.samples = p_texture_samples;
+
+	return create_texture_from_format(p_context, p_texture_name, tf, RD::TextureView(), p_unique);
+}
+
+RID RenderSceneBuffersRD::create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view, bool p_unique) {
+	// TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimisation.
+
+	NTKey key(p_context, p_texture_name);
+
+	// check if this is a known texture
+	if (named_textures.has(key)) {
+		return named_textures[key].texture;
+	}
+
+	// Add a new entry..
+	NamedTexture &named_texture = named_textures[key];
+	named_texture.format = p_texture_format;
+	named_texture.is_unique = p_unique;
+	named_texture.texture = RD::get_singleton()->texture_create(p_texture_format, p_view);
+
+	Array arr;
+	arr.push_back(p_context);
+	arr.push_back(p_texture_name);
+	RD::get_singleton()->set_resource_name(named_texture.texture, String("RenderBuffer {0}/{1}").format(arr));
+
+	update_sizes(named_texture);
+
+	// The rest is lazy created..
+
+	return named_texture.texture;
+}
+
+RID RenderSceneBuffersRD::create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view) {
+	NTKey view_key(p_context, p_view_name);
+
+	// check if this is a known texture
+	if (named_textures.has(view_key)) {
+		return named_textures[view_key].texture;
+	}
+
+	NTKey key(p_context, p_texture_name);
+
+	ERR_FAIL_COND_V(!named_textures.has(key), RID());
+
+	NamedTexture &named_texture = named_textures[key];
+	NamedTexture &view_texture = named_textures[view_key];
+
+	view_texture.format = named_texture.format;
+	view_texture.is_unique = named_texture.is_unique;
+
+	view_texture.texture = RD::get_singleton()->texture_create_shared(p_view, named_texture.texture);
+
+	Array arr;
+	arr.push_back(p_context);
+	arr.push_back(p_view_name);
+	RD::get_singleton()->set_resource_name(view_texture.texture, String("RenderBuffer View {0}/{1}").format(arr));
+
+	update_sizes(named_texture);
+
+	return view_texture.texture;
+}
+
+RID RenderSceneBuffersRD::get_texture(const StringName &p_context, const StringName &p_texture_name) const {
+	NTKey key(p_context, p_texture_name);
+
+	ERR_FAIL_COND_V(!named_textures.has(key), RID());
+
+	return named_textures[key].texture;
+}
+
+const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringName &p_context, const StringName &p_texture_name) const {
+	NTKey key(p_context, p_texture_name);
+
+	ERR_FAIL_COND_V(!named_textures.has(key), RD::TextureFormat());
+
+	return named_textures[key].format;
+}
+
+RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
+	NTKey key(p_context, p_texture_name);
+
+	// check if this is a known texture
+	ERR_FAIL_COND_V(!named_textures.has(key), RID());
+	NamedTexture &named_texture = named_textures[key];
+	ERR_FAIL_COND_V(named_texture.texture.is_null(), RID());
+
+	// check if we're in bounds
+	ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID());
+	ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID());
+
+	// if we don't have multiple layers or mipmaps, we can just return our texture as is
+	if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) {
+		return named_texture.texture;
+	}
+
+	// get our index and make sure we have enough entries in our slices vector
+	uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
+	while (named_texture.slices.size() <= int(index)) {
+		named_texture.slices.push_back(RID());
+	}
+
+	// create our slice if we don't have it already
+	if (named_texture.slices[index].is_null()) {
+		named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap);
+
+		Array arr;
+		arr.push_back(p_context);
+		arr.push_back(p_texture_name);
+		arr.push_back(itos(p_layer));
+		arr.push_back(itos(p_mipmap));
+		RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr));
+	}
+
+	// and return our slice
+	return named_texture.slices[index];
+}
+
+Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
+	NTKey key(p_context, p_texture_name);
+
+	// check if this is a known texture
+	ERR_FAIL_COND_V(!named_textures.has(key), Size2i());
+	NamedTexture &named_texture = named_textures[key];
+	ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i());
+
+	// check if we're in bounds
+	ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, Size2i());
+	ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i());
+
+	// get our index
+	uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
+
+	// and return our size
+	return named_texture.sizes[index];
+}
+
+void RenderSceneBuffersRD::clear_context(const StringName &p_context) {
+	Vector<NTKey> to_free; // free these
+
+	// Find all entries for our context, we don't want to free them yet or our loop fails.
+	for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
+		if (E.key.context == p_context) {
+			to_free.push_back(E.key);
+		}
+	}
+
+	// Now free these and remove them from our textures
+	for (NTKey &key : to_free) {
+		free_named_texture(named_textures[key]);
+		named_textures.erase(key);
+	}
+}
+
+// Allocate shared buffers
+void RenderSceneBuffersRD::allocate_blur_textures() {
+	if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0)) {
+		// already allocated...
+		return;
+	}
+
+	uint32_t mipmaps_required = Image::get_image_required_mipmaps(internal_size.x, internal_size.y, Image::FORMAT_RGBAH);
+
+	uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+	if (can_be_storage) {
+		usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT;
+	} else {
+		usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+	}
+
+	create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, internal_size, view_count, mipmaps_required);
+	create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y >> 1), view_count, mipmaps_required - 1);
+
+	// if !can_be_storage we need a half width version
+	if (!can_be_storage) {
+		create_texture(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y), 1, mipmaps_required);
+	}
+
+	// TODO redo this:
+	if (!can_be_storage) {
+		// create 4 weight textures, 2 full size, 2 half size
+
+		RD::TextureFormat tf;
+		tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
+		tf.width = internal_size.x;
+		tf.height = internal_size.y;
+		tf.texture_type = RD::TEXTURE_TYPE_2D;
+		tf.array_layers = 1; // Our DOF effect handles one eye per turn
+		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+		tf.mipmaps = 1;
+		for (uint32_t i = 0; i < 4; i++) {
+			// associated blur texture
+			RID texture;
+			if (i == 1) {
+				texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 0);
+			} else if (i == 2) {
+				texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0);
+			} else if (i == 3) {
+				texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 1);
+			}
+
+			// create weight texture
+			weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+			// create frame buffer
+			Vector<RID> fb;
+			if (i != 0) {
+				fb.push_back(texture);
+			}
+			fb.push_back(weight_buffers[i].weight);
+			weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
+
+			if (i == 1) {
+				// next 2 are half size
+				tf.width = MAX(1u, tf.width >> 1);
+				tf.height = MAX(1u, tf.height >> 1);
+			}
+		}
+	}
+}
+
+// Data buffers
+
+bool RenderSceneBuffersRD::has_custom_data(const StringName &p_name) {
+	return data_buffers.has(p_name);
+}
+
+void RenderSceneBuffersRD::set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data) {
+	if (p_data.is_valid()) {
+		data_buffers[p_name] = p_data;
+	} else if (has_custom_data(p_name)) {
+		data_buffers.erase(p_name);
+	}
+}
+
+Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const StringName &p_name) const {
+	ERR_FAIL_COND_V(!data_buffers.has(p_name), Ref<RenderBufferCustomDataRD>());
+
+	Ref<RenderBufferCustomDataRD> ret = data_buffers[p_name];
+
+	return ret;
+}
+
+// Velocity texture.
+
+void RenderSceneBuffersRD::ensure_velocity() {
+	if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
+		uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+		if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
+			uint32_t msaa_usage_bits = usage_bits | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+			usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+
+			const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
+				RD::TEXTURE_SAMPLES_1,
+				RD::TEXTURE_SAMPLES_2,
+				RD::TEXTURE_SAMPLES_4,
+				RD::TEXTURE_SAMPLES_8,
+			};
+
+			create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, RD::DATA_FORMAT_R16G16_SFLOAT, msaa_usage_bits, ts[msaa_3d]);
+		}
+
+		create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits);
+	}
+}
+
+RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) {
+	if (p_get_msaa) {
+		if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA)) {
+			return RID();
+		} else {
+			return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA);
+		}
+	} else {
+		if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
+			return RID();
+		} else {
+			return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY);
+		}
+	}
+}

+ 256 - 0
servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h

@@ -0,0 +1,256 @@
+/*************************************************************************/
+/*  render_scene_buffers_rd.h                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef RENDER_SCENE_BUFFERS_RD_H
+#define RENDER_SCENE_BUFFERS_RD_H
+
+#include "core/templates/hash_map.h"
+#include "servers/rendering/renderer_rd/effects/vrs.h"
+#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
+#include "servers/rendering/renderer_scene.h"
+#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/storage/render_scene_buffers.h"
+
+// These can be retired in due time
+#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
+#include "servers/rendering/renderer_rd/effects/ss_effects.h"
+#include "servers/rendering/renderer_rd/environment/fog.h"
+
+#define RB_SCOPE_BUFFERS SNAME("render_buffers")
+#define RB_SCOPE_VRS SNAME("VRS")
+
+#define RB_TEXTURE SNAME("texture")
+#define RB_TEX_COLOR SNAME("color")
+#define RB_TEX_COLOR_MSAA SNAME("color_msaa")
+#define RB_TEX_DEPTH SNAME("depth")
+#define RB_TEX_DEPTH_MSAA SNAME("depth_msaa")
+#define RB_TEX_VELOCITY SNAME("velocity")
+#define RB_TEX_VELOCITY_MSAA SNAME("velocity_msaa")
+
+#define RB_TEX_BLUR_0 SNAME("blur_0")
+#define RB_TEX_BLUR_1 SNAME("blur_1")
+#define RB_TEX_HALF_BLUR SNAME("half_blur") // only for raster!
+
+#define RB_TEX_BACK_DEPTH SNAME("back_depth")
+
+class RenderSceneBuffersRD : public RenderSceneBuffers {
+	GDCLASS(RenderSceneBuffersRD, RenderSceneBuffers);
+
+private:
+	bool can_be_storage = true;
+	uint32_t max_cluster_elements = 512;
+	RD::DataFormat base_data_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+	RendererRD::SSEffects *sse = nullptr;
+	RendererRD::VRS *vrs = nullptr;
+	uint64_t auto_exposure_version = 1;
+
+	// Our render target represents our final destination that we display on screen.
+	RID render_target;
+	Size2i target_size = Size2i(0, 0);
+	uint32_t view_count = 1;
+
+	// 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);
+	float fsr_sharpness = 0.2f;
+
+	// Aliassing settings
+	RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
+	RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+	bool use_taa = false;
+	bool use_debanding = false;
+
+	// Named Textures
+
+	struct NTKey {
+		StringName context;
+		StringName buffer_name;
+
+		bool operator==(const NTKey &p_val) const {
+			return (context == p_val.context) && (buffer_name == p_val.buffer_name);
+		}
+
+		static uint32_t hash(const NTKey &p_val) {
+			// FIXME, properly hash two stringnames together
+			uint32_t h = p_val.context.hash();
+			h = hash_murmur3_one_32(p_val.buffer_name.hash(), h);
+			return hash_fmix32(h);
+		}
+
+		NTKey() {}
+		NTKey(const StringName p_context, const StringName p_texture_name) {
+			context = p_context;
+			buffer_name = p_texture_name;
+		}
+	};
+
+	struct NamedTexture {
+		// Cache the data used to create our texture
+		RD::TextureFormat format;
+		bool is_unique; // If marked as unique, we return it into our pool
+
+		// Our texture objects, slices are lazy (i.e. only created when requested).
+		RID texture;
+		Vector<RID> slices;
+		Vector<Size2i> sizes;
+	};
+
+	mutable HashMap<NTKey, NamedTexture, NTKey> named_textures;
+	void update_sizes(NamedTexture &p_named_texture);
+	void free_named_texture(NamedTexture &p_named_texture);
+
+	// Data buffers
+	mutable HashMap<StringName, Ref<RenderBufferCustomDataRD>> data_buffers;
+
+protected:
+	static void _bind_methods();
+
+public:
+	RenderSceneBuffersRD();
+	virtual ~RenderSceneBuffersRD();
+
+	// info from our renderer
+	void set_can_be_storage(const bool p_can_be_storage) { can_be_storage = p_can_be_storage; }
+	void set_max_cluster_elements(const uint32_t p_max_elements) { max_cluster_elements = p_max_elements; }
+	void set_base_data_format(const RD::DataFormat p_base_data_format) { base_data_format = p_base_data_format; }
+	RD::DataFormat get_base_data_format() const { return base_data_format; }
+	void set_sseffects(RendererRD::SSEffects *p_ss_effects) { sse = p_ss_effects; }
+	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 set_fsr_sharpness(float p_fsr_sharpness) override;
+	virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
+	virtual void set_use_debanding(bool p_use_debanding) override;
+
+	// Named Textures
+
+	bool has_texture(const StringName &p_context, const StringName &p_texture_name) const;
+	RID create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples = RD::TEXTURE_SAMPLES_1, const Size2i p_size = Size2i(0, 0), const uint32_t p_layers = 0, const uint32_t p_mipmaps = 1, bool p_unique = true);
+	RID create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view = RD::TextureView(), bool p_unique = true);
+	RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView());
+	RID get_texture(const StringName &p_context, const StringName &p_texture_name) const;
+	const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
+	RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
+	Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
+
+	void clear_context(const StringName &p_context);
+
+	// Allocate shared buffers
+	void allocate_blur_textures();
+
+	// Custom data
+	bool has_custom_data(const StringName &p_name);
+	void set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data);
+	Ref<RenderBufferCustomDataRD> get_custom_data(const StringName &p_name) const;
+
+	// Getters
+
+	_FORCE_INLINE_ RID get_render_target() const { return render_target; }
+	_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_ 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; }
+	_FORCE_INLINE_ bool get_use_taa() const { return use_taa; }
+	_FORCE_INLINE_ bool get_use_debanding() const { return use_debanding; }
+
+	uint64_t get_auto_exposure_version() const { return auto_exposure_version; }
+	void set_auto_exposure_version(const uint64_t p_auto_exposure_version) { auto_exposure_version = p_auto_exposure_version; }
+
+	// For our internal textures we provide some easy access methods.
+
+	_FORCE_INLINE_ RID get_internal_texture() const {
+		return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
+	}
+	_FORCE_INLINE_ RID get_internal_texture(const uint32_t p_layer) {
+		return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
+	}
+
+	_FORCE_INLINE_ RID get_depth_texture() const {
+		return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
+	}
+	_FORCE_INLINE_ RID get_depth_texture(const uint32_t p_layer) {
+		return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0);
+	}
+
+	// back buffer (color)
+	RID get_back_buffer_texture() const { return has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) ? get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) : RID(); } // We (re)use our blur texture here.
+
+	// Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too.
+
+	void ensure_velocity();
+	bool has_velocity_buffer(bool p_has_msaa) { return has_texture(RB_SCOPE_BUFFERS, p_has_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY); }
+	RID get_velocity_buffer(bool p_get_msaa);
+	RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) { return get_texture_slice(RB_SCOPE_BUFFERS, p_get_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY, p_layer, 0); }
+
+	////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// Everything after this needs to be re-evaluated, this is all old implementation
+
+	ClusterBuilderRD *cluster_builder = nullptr;
+
+	struct WeightBuffers {
+		RID weight;
+		RID fb; // FB with both texture and weight writing into one level lower
+	};
+
+	// 2 full size, 2 half size
+	WeightBuffers weight_buffers[4]; // Only used in raster
+
+	struct Luminance {
+		Vector<RID> reduce;
+		RID current;
+
+		// used only on mobile renderer
+		Vector<RID> fb;
+		RID current_fb;
+	} luminance;
+
+	struct SSEffects {
+		RID linear_depth;
+		Vector<RID> linear_depth_slices;
+
+		RID downsample_uniform_set;
+
+		Projection last_frame_projection;
+		Transform3D last_frame_transform;
+
+		RendererRD::SSEffects::SSAORenderBuffers ssao;
+		RendererRD::SSEffects::SSILRenderBuffers ssil;
+	} ss_effects;
+
+	RendererRD::SSEffects::SSRRenderBuffers ssr;
+
+	RID get_ao_texture() const { return ss_effects.ssao.ao_final; }
+	RID get_ssil_texture() const { return ss_effects.ssil.ssil_final; }
+};
+
+#endif // RENDER_SCENE_BUFFERS_RD_H

+ 20 - 0
servers/rendering/renderer_rd/storage_rd/texture_storage.cpp

@@ -2120,6 +2120,7 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
 	if (rt->color.is_valid()) {
 		RD::get_singleton()->free(rt->color);
 	}
+	rt->color_slices.clear(); // these are automatically freed.
 
 	if (rt->color_multisample.is_valid()) {
 		RD::get_singleton()->free(rt->color_multisample);
@@ -2174,6 +2175,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
 		}
 		rd_color_attachment_format.samples = RD::TEXTURE_SAMPLES_1;
 		rd_color_attachment_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+		rd_color_attachment_format.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; // FIXME we need this only when FSR is enabled
 		rd_color_attachment_format.shareable_formats.push_back(rt->color_format);
 		rd_color_attachment_format.shareable_formats.push_back(rt->color_format_srgb);
 		if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) {
@@ -2392,6 +2394,24 @@ RID TextureStorage::render_target_get_rd_texture(RID p_render_target) {
 	return rt->color;
 }
 
+RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+
+	if (rt->view_count == 1) {
+		return rt->color;
+	} else {
+		ERR_FAIL_UNSIGNED_INDEX_V(p_layer, rt->view_count, RID());
+		if (rt->color_slices.size() == 0) {
+			for (uint32_t v = 0; v < rt->view_count; v++) {
+				RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->color, v, 0);
+				rt->color_slices.push_back(slice);
+			}
+		}
+		return rt->color_slices[p_layer];
+	}
+}
+
 RID TextureStorage::render_target_get_rd_backbuffer(RID p_render_target) {
 	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
 	ERR_FAIL_COND_V(!rt, RID());

+ 2 - 0
servers/rendering/renderer_rd/storage_rd/texture_storage.h

@@ -254,6 +254,7 @@ private:
 		uint32_t view_count;
 		RID framebuffer;
 		RID color;
+		Vector<RID> color_slices;
 		RID color_multisample; // Needed when MSAA is enabled.
 
 		RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
@@ -589,6 +590,7 @@ public:
 	Size2 render_target_get_size(RID p_render_target);
 	RID render_target_get_rd_framebuffer(RID p_render_target);
 	RID render_target_get_rd_texture(RID p_render_target);
+	RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer);
 	RID render_target_get_rd_backbuffer(RID p_render_target);
 	RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
 

+ 2 - 2
servers/rendering/renderer_rd/storage_rd/utilities.cpp

@@ -155,8 +155,8 @@ void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance
 		Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base);
 		p_instance->update_dependency(dependency);
 	} else if (GI::get_singleton()->owns_voxel_gi(p_base)) {
-		GI::VoxelGI *gip = GI::get_singleton()->get_voxel_gi(p_base);
-		p_instance->update_dependency(&gip->dependency);
+		Dependency *dependency = GI::get_singleton()->voxel_gi_get_dependency(p_base);
+		p_instance->update_dependency(dependency);
 	} else if (LightStorage::get_singleton()->owns_lightmap(p_base)) {
 		Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base);
 		p_instance->update_dependency(dependency);

+ 4 - 5
servers/rendering/renderer_scene.h

@@ -31,6 +31,7 @@
 #ifndef RENDERER_SCENE_H
 #define RENDERER_SCENE_H
 
+#include "servers/rendering/storage/render_scene_buffers.h"
 #include "servers/rendering_server.h"
 #include "servers/xr/xr_interface.h"
 
@@ -287,9 +288,7 @@ public:
 
 	/* Render Buffers */
 
-	virtual RID render_buffers_create() = 0;
-
-	virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
+	virtual Ref<RenderSceneBuffers> render_buffers_create() = 0;
 
 	virtual void gi_set_use_half_resolution(bool p_enable) = 0;
 
@@ -300,13 +299,13 @@ public:
 
 	virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
 
-	virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
+	virtual void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
 
 	struct RenderInfo {
 		int info[RS::VIEWPORT_RENDER_INFO_TYPE_MAX][RS::VIEWPORT_RENDER_INFO_MAX] = {};
 	};
 
-	virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
+	virtual void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
 
 	virtual void update() = 0;
 	virtual void render_probes() = 0;

+ 5 - 6
servers/rendering/renderer_scene_cull.cpp

@@ -2450,7 +2450,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
 	return animated_material_found;
 }
 
-void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
+void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
 #ifndef _3D_DISABLED
 
 	Camera *camera = camera_owner.get_or_null(p_camera);
@@ -2910,7 +2910,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
 	}
 }
 
-void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
+void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
 	Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it
 
 	Scenario *scenario = scenario_owner.get_or_null(p_scenario);
@@ -3270,8 +3270,6 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
 	for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
 		render_sdfgi_data[i].instances.clear();
 	}
-
-	//	virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
 }
 
 RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
@@ -3295,7 +3293,7 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
 	return RID();
 }
 
-void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
+void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
 #ifndef _3D_DISABLED
 	Scenario *scenario = scenario_owner.get_or_null(p_scenario);
 
@@ -3383,7 +3381,8 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
 		RendererSceneRender::CameraData camera_data;
 		camera_data.set_camera(xform, cm, false, false);
 
-		_render_scene(&camera_data, RID(), environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
+		Ref<RenderSceneBuffers> render_buffers;
+		_render_scene(&camera_data, render_buffers, environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
 
 	} else {
 		//do roughness postprocess step until it believes it's done

+ 4 - 5
servers/rendering/renderer_scene_cull.h

@@ -1055,10 +1055,10 @@ public:
 	_FORCE_INLINE_ bool _visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data);
 
 	bool _render_reflection_probe_step(Instance *p_instance, int p_step);
-	void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
-	void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
+	void _render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
+	void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas);
 
-	void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
+	void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
 	void update_dirty_instances();
 
 	void render_particle_colliders();
@@ -1253,8 +1253,7 @@ public:
 
 	/* Render Buffers */
 
-	PASS0R(RID, render_buffers_create)
-	PASS13(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, bool, uint32_t)
+	PASS0R(Ref<RenderSceneBuffers>, render_buffers_create)
 	PASS1(gi_set_use_half_resolution, bool)
 
 	/* Shadow Atlas */

+ 7 - 7
servers/rendering/renderer_scene_render.h

@@ -36,6 +36,7 @@
 #include "servers/rendering/renderer_geometry_instance.h"
 #include "servers/rendering/renderer_scene.h"
 #include "servers/rendering/storage/environment_storage.h"
+#include "storage/render_scene_buffers.h"
 #include "storage/utilities.h"
 
 class RendererSceneRender {
@@ -68,10 +69,10 @@ public:
 
 	/* SDFGI UPDATE */
 
-	virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
-	virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
-	virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
-	virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0;
+	virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
+	virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const = 0;
+	virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0;
+	virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0;
 
 	/* SKY API */
 
@@ -317,7 +318,7 @@ public:
 		void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect);
 	};
 
-	virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
+	virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
 
 	virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
 	virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
@@ -326,8 +327,7 @@ public:
 	virtual void set_time(double p_time, double p_step) = 0;
 	virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
 
-	virtual RID render_buffers_create() = 0;
-	virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
+	virtual Ref<RenderSceneBuffers> render_buffers_create() = 0;
 	virtual void gi_set_use_half_resolution(bool p_enable) = 0;
 
 	virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;

+ 12 - 7
servers/rendering/renderer_viewport.cpp

@@ -110,8 +110,7 @@ Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports()
 void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
 	if (p_viewport->render_buffers.is_valid()) {
 		if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
-			RSG::scene->free(p_viewport->render_buffers);
-			p_viewport->render_buffers = RID();
+			p_viewport->render_buffers.unref();
 		} else {
 			const float scaling_3d_scale = p_viewport->scaling_3d_scale;
 			RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
@@ -177,7 +176,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;
 
-			RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, 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->get_view_count());
+			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->get_view_count());
 		}
 	}
 }
@@ -784,7 +783,9 @@ void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpn
 	ERR_FAIL_COND(!viewport);
 
 	viewport->fsr_sharpness = p_sharpness;
-	_configure_3d_render_buffers(viewport);
+	if (viewport->render_buffers.is_valid()) {
+		viewport->render_buffers->set_fsr_sharpness(p_sharpness);
+	}
 }
 
 void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
@@ -792,7 +793,9 @@ void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_
 	ERR_FAIL_COND(!viewport);
 
 	viewport->texture_mipmap_bias = p_mipmap_bias;
-	_configure_3d_render_buffers(viewport);
+	if (viewport->render_buffers.is_valid()) {
+		viewport->render_buffers->set_texture_mipmap_bias(p_mipmap_bias);
+	}
 }
 
 void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) {
@@ -1128,7 +1131,9 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb
 		return;
 	}
 	viewport->use_debanding = p_use_debanding;
-	_configure_3d_render_buffers(viewport);
+	if (viewport->render_buffers.is_valid()) {
+		viewport->render_buffers->set_use_debanding(p_use_debanding);
+	}
 }
 
 void RendererViewport::viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) {
@@ -1284,7 +1289,7 @@ bool RendererViewport::free(RID p_rid) {
 		RSG::texture_storage->render_target_free(viewport->render_target);
 		RSG::scene->free(viewport->shadow_atlas);
 		if (viewport->render_buffers.is_valid()) {
-			RSG::scene->free(viewport->render_buffers);
+			viewport->render_buffers.unref();
 		}
 
 		while (viewport->canvas_map.begin()) {

+ 2 - 1
servers/rendering/renderer_viewport.h

@@ -38,6 +38,7 @@
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/rendering_server.h"
 #include "servers/xr/xr_interface.h"
+#include "storage/render_scene_buffers.h"
 
 class RendererViewport {
 public:
@@ -64,7 +65,7 @@ public:
 		RS::ViewportUpdateMode update_mode = RenderingServer::VIEWPORT_UPDATE_WHEN_VISIBLE;
 		RID render_target;
 		RID render_target_texture;
-		RID render_buffers;
+		Ref<RenderSceneBuffers> render_buffers;
 
 		RS::ViewportMSAA msaa_2d = RenderingServer::VIEWPORT_MSAA_DISABLED;
 		RS::ViewportMSAA msaa_3d = RenderingServer::VIEWPORT_MSAA_DISABLED;

+ 26 - 0
servers/rendering/rendering_device.h

@@ -464,6 +464,32 @@ public:
 		Vector<DataFormat> shareable_formats;
 		bool is_resolve_buffer = false;
 
+		bool operator==(const TextureFormat &b) const {
+			if (format != b.format) {
+				return false;
+			} else if (width != b.width) {
+				return false;
+			} else if (height != b.height) {
+				return false;
+			} else if (depth != b.depth) {
+				return false;
+			} else if (array_layers != b.array_layers) {
+				return false;
+			} else if (mipmaps != b.mipmaps) {
+				return false;
+			} else if (texture_type != b.texture_type) {
+				return false;
+			} else if (samples != b.samples) {
+				return false;
+			} else if (usage_bits != b.usage_bits) {
+				return false;
+			} else if (shareable_formats != b.shareable_formats) {
+				return false;
+			} else {
+				return true;
+			}
+		}
+
 		TextureFormat() {
 			format = DATA_FORMAT_R8_UNORM;
 			width = 1;

+ 51 - 0
servers/rendering/storage/render_scene_buffers.cpp

@@ -0,0 +1,51 @@
+/*************************************************************************/
+/*  render_scene_buffers.cpp                                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "render_scene_buffers.h"
+
+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::set_fsr_sharpness(float p_fsr_sharpness) {
+	GDVIRTUAL_CALL(_set_fsr_sharpness, p_fsr_sharpness);
+}
+
+void RenderSceneBuffers::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
+	GDVIRTUAL_CALL(_set_texture_mipmap_bias, p_texture_mipmap_bias);
+}
+
+void RenderSceneBuffers::set_use_debanding(bool p_use_debanding) {
+	GDVIRTUAL_CALL(_set_use_debanding, p_use_debanding);
+}

+ 60 - 0
servers/rendering/storage/render_scene_buffers.h

@@ -0,0 +1,60 @@
+/*************************************************************************/
+/*  render_scene_buffers.h                                               */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef RENDER_SCENE_BUFFERS_H
+#define RENDER_SCENE_BUFFERS_H
+
+#include "core/object/ref_counted.h"
+#include "servers/rendering_server.h"
+
+class RenderSceneBuffers : public RefCounted {
+	GDCLASS(RenderSceneBuffers, RefCounted);
+
+protected:
+	static void _bind_methods();
+
+	GDVIRTUAL10(_configure, RID, Size2i, Size2i, 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)
+
+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);
+
+	// 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);
+	virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias);
+	virtual void set_use_debanding(bool p_use_debanding);
+};
+
+#endif // RENDER_SCENE_BUFFERS_H

+ 0 - 4
servers/xr/xr_interface_extension.cpp

@@ -358,9 +358,5 @@ RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
 RID XRInterfaceExtension::get_render_target_depth(RID p_render_target) {
 	// TODO implement this, the problem is that our depth texture isn't part of our render target as it is used for 3D rendering only
 	// but we don't have access to our render buffers from here....
-	RendererSceneRenderRD * rd_scene = ?????;
-	ERR_FAIL_NULL_V_MSG(rd_scene, RID(), "Renderer scene render not setup");
-
-	return rd_scene->render_buffers_get_depth_texture(????????????);
 }
 */

Some files were not shown because too many files changed in this diff