2
0
Эх сурвалжийг харах

Merge pull request #59984 from BastiaanOlij/more_storage_20220407

More work on splitting up RendererStorage
Clay John 3 жил өмнө
parent
commit
1d2177938d
65 өөрчлөгдсөн 9256 нэмэгдсэн , 8587 устгасан
  1. 26 20
      drivers/gles3/rasterizer_canvas_gles3.cpp
  2. 0 1
      drivers/gles3/rasterizer_canvas_gles3.h
  3. 13 8
      drivers/gles3/rasterizer_gles3.cpp
  4. 6 7
      drivers/gles3/rasterizer_gles3.h
  5. 103 1302
      drivers/gles3/rasterizer_storage_gles3.cpp
  6. 2 250
      drivers/gles3/rasterizer_storage_gles3.h
  7. 0 96
      drivers/gles3/storage/canvas_texture_storage.cpp
  8. 0 87
      drivers/gles3/storage/canvas_texture_storage.h
  9. 4 0
      drivers/gles3/storage/config.cpp
  10. 0 75
      drivers/gles3/storage/decal_atlas_storage.cpp
  11. 0 67
      drivers/gles3/storage/decal_atlas_storage.h
  12. 316 0
      drivers/gles3/storage/light_storage.cpp
  13. 154 0
      drivers/gles3/storage/light_storage.h
  14. 254 0
      drivers/gles3/storage/particles_storage.cpp
  15. 140 0
      drivers/gles3/storage/particles_storage.h
  16. 0 132
      drivers/gles3/storage/render_target_storage.h
  17. 932 0
      drivers/gles3/storage/texture_storage.cpp
  18. 226 2
      drivers/gles3/storage/texture_storage.h
  19. 2 1
      modules/openxr/extensions/openxr_vulkan_extension.cpp
  20. 6 6
      servers/rendering/dummy/rasterizer_dummy.h
  21. 1 185
      servers/rendering/dummy/rasterizer_storage_dummy.h
  22. 0 53
      servers/rendering/dummy/storage/canvas_texture_storage.h
  23. 0 62
      servers/rendering/dummy/storage/decal_atlas_storage.h
  24. 135 0
      servers/rendering/dummy/storage/light_storage.h
  25. 126 0
      servers/rendering/dummy/storage/particles_storage.h
  26. 56 0
      servers/rendering/dummy/storage/texture_storage.h
  27. 8 8
      servers/rendering/renderer_canvas_cull.cpp
  28. 2 1
      servers/rendering/renderer_canvas_render.h
  29. 4 4
      servers/rendering/renderer_compositor.h
  30. 43 36
      servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
  31. 42 36
      servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
  32. 67 58
      servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
  33. 5 5
      servers/rendering/renderer_rd/renderer_compositor_rd.cpp
  34. 6 6
      servers/rendering/renderer_rd/renderer_compositor_rd.h
  35. 58 45
      servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
  36. 0 1
      servers/rendering/renderer_rd/renderer_scene_gi_rd.h
  37. 160 150
      servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
  38. 19 18
      servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
  39. 352 3491
      servers/rendering/renderer_rd/renderer_storage_rd.cpp
  40. 0 928
      servers/rendering/renderer_rd/renderer_storage_rd.h
  41. 0 235
      servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp
  42. 0 90
      servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h
  43. 0 437
      servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp
  44. 0 211
      servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h
  45. 788 0
      servers/rendering/renderer_rd/storage_rd/light_storage.cpp
  46. 370 0
      servers/rendering/renderer_rd/storage_rd/light_storage.h
  47. 200 0
      servers/rendering/renderer_rd/storage_rd/material_storage.cpp
  48. 18 0
      servers/rendering/renderer_rd/storage_rd/material_storage.h
  49. 1897 0
      servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
  50. 565 0
      servers/rendering/renderer_rd/storage_rd/particles_storage.h
  51. 1315 3
      servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
  52. 336 1
      servers/rendering/renderer_rd/storage_rd/texture_storage.h
  53. 99 99
      servers/rendering/renderer_scene_cull.cpp
  54. 0 203
      servers/rendering/renderer_storage.h
  55. 28 27
      servers/rendering/renderer_viewport.cpp
  56. 3 3
      servers/rendering/rendering_server_default.cpp
  57. 29 17
      servers/rendering/rendering_server_default.h
  58. 2 2
      servers/rendering/rendering_server_globals.cpp
  59. 4 4
      servers/rendering/rendering_server_globals.h
  60. 0 51
      servers/rendering/storage/canvas_texture_storage.h
  61. 0 60
      servers/rendering/storage/decal_atlas_storage.h
  62. 139 0
      servers/rendering/storage/light_storage.h
  63. 129 0
      servers/rendering/storage/particles_storage.h
  64. 62 0
      servers/rendering/storage/texture_storage.h
  65. 4 3
      servers/xr/xr_interface_extension.cpp

+ 26 - 20
drivers/gles3/rasterizer_canvas_gles3.cpp

@@ -38,9 +38,9 @@
 
 #include "core/config/project_settings.h"
 #include "servers/rendering/rendering_server_default.h"
-#include "storage/canvas_texture_storage.h"
 #include "storage/config.h"
 #include "storage/material_storage.h"
+#include "storage/texture_storage.h"
 
 #ifndef GLES_OVER_GL
 #define glClearDepth glClearDepthf
@@ -116,9 +116,11 @@ void RasterizerCanvasGLES3::_update_transform_to_mat4(const Transform3D &p_trans
 }
 
 void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
-	storage->frame.current_rt = nullptr;
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
+	texture_storage->frame.current_rt = nullptr;
 
-	storage->_set_current_render_target(p_to_render_target);
+	texture_storage->_set_current_render_target(p_to_render_target);
 
 	Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse();
 
@@ -130,7 +132,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
 		//update canvas state uniform buffer
 		StateBuffer state_buffer;
 
-		Size2i ssize = storage->render_target_get_size(p_to_render_target);
+		Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
 
 		Transform3D screen_transform;
 		screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
@@ -149,11 +151,11 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
 		state_buffer.canvas_modulate[2] = p_modulate.b;
 		state_buffer.canvas_modulate[3] = p_modulate.a;
 
-		Size2 render_target_size = storage->render_target_get_size(p_to_render_target);
+		Size2 render_target_size = texture_storage->render_target_get_size(p_to_render_target);
 		state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
 		state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
 
-		state_buffer.time = storage->frame.time;
+		state_buffer.time = texture_storage->frame.time;
 		state_buffer.use_pixel_snap = p_snap_2d_vertices_to_pixel;
 
 		state_buffer.directional_light_count = 0; //directional_light_count;
@@ -166,7 +168,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
 		state_buffer.screen_to_sdf[0] = 1.0 / state_buffer.sdf_to_screen[0];
 		state_buffer.screen_to_sdf[1] = 1.0 / state_buffer.sdf_to_screen[1];
 
-		Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_to_render_target);
+		Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_to_render_target);
 		Rect2 sdf_tex_rect(sdf_rect.position / canvas_scale, sdf_rect.size / canvas_scale);
 
 		state_buffer.sdf_to_tex[0] = 1.0 / sdf_tex_rect.size.width;
@@ -881,19 +883,21 @@ void RasterizerCanvasGLES3::update() {
 }
 
 void RasterizerCanvasGLES3::canvas_begin() {
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
 	state.using_transparent_rt = false;
 
-	if (storage->frame.current_rt) {
-		storage->bind_framebuffer(storage->frame.current_rt->fbo);
-		state.using_transparent_rt = storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT];
+	if (texture_storage->frame.current_rt) {
+		glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->frame.current_rt->fbo);
+		state.using_transparent_rt = texture_storage->frame.current_rt->flags[GLES3::TextureStorage::RENDER_TARGET_TRANSPARENT];
 	}
 
-	if (storage->frame.current_rt && storage->frame.current_rt->clear_requested) {
-		const Color &col = storage->frame.current_rt->clear_color;
+	if (texture_storage->frame.current_rt && texture_storage->frame.current_rt->clear_requested) {
+		const Color &col = texture_storage->frame.current_rt->clear_color;
 		glClearColor(col.r, col.g, col.b, col.a);
 
 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-		storage->frame.current_rt->clear_requested = false;
+		texture_storage->frame.current_rt->clear_requested = false;
 	}
 
 	reset_canvas();
@@ -934,7 +938,7 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
 
 		ct = t->canvas_texture;
 	} else {
-		ct = GLES3::CanvasTextureStorage::get_singleton()->get_canvas_texture(p_texture);
+		ct = GLES3::TextureStorage::get_singleton()->get_canvas_texture(p_texture);
 	}
 
 	if (!ct) {
@@ -1041,6 +1045,8 @@ void RasterizerCanvasGLES3::_set_uniforms() {
 }
 
 void RasterizerCanvasGLES3::reset_canvas() {
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
 	glDisable(GL_CULL_FACE);
 	glDisable(GL_DEPTH_TEST);
 	glDisable(GL_SCISSOR_TEST);
@@ -1049,7 +1055,7 @@ void RasterizerCanvasGLES3::reset_canvas() {
 
 	// Default to Mix.
 	glBlendEquation(GL_FUNC_ADD);
-	if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) {
+	if (texture_storage->frame.current_rt && texture_storage->frame.current_rt->flags[GLES3::TextureStorage::RENDER_TARGET_TRANSPARENT]) {
 		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 	} else {
 		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
@@ -1255,7 +1261,7 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() {
 }
 
 void RasterizerCanvasGLES3::initialize() {
-	GLES3::CanvasTextureStorage *canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
 	GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
 
 	// quad buffer
@@ -1450,8 +1456,8 @@ void fragment() {
 		material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
 	}
 
-	default_canvas_texture = canvas_texture_storage->canvas_texture_allocate();
-	canvas_texture_storage->canvas_texture_initialize(default_canvas_texture);
+	default_canvas_texture = texture_storage->canvas_texture_allocate();
+	texture_storage->canvas_texture_initialize(default_canvas_texture);
 
 	state.using_light = nullptr;
 	state.using_transparent_rt = false;
@@ -1470,13 +1476,13 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
 }
 
 RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
-	GLES3::CanvasTextureStorage *canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
 	GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
 
 	state.canvas_shader.version_free(state.canvas_shader_default_version);
 	material_storage->material_free(default_canvas_group_material);
 	material_storage->shader_free(default_canvas_group_shader);
-	canvas_texture_storage->canvas_texture_free(default_canvas_texture);
+	texture_storage->canvas_texture_free(default_canvas_texture);
 	singleton = nullptr;
 }
 

+ 0 - 1
drivers/gles3/rasterizer_canvas_gles3.h

@@ -37,7 +37,6 @@
 #include "rasterizer_storage_gles3.h"
 #include "servers/rendering/renderer_canvas_render.h"
 #include "servers/rendering/renderer_compositor.h"
-#include "storage/canvas_texture_storage.h"
 #include "storage/material_storage.h"
 #include "storage/texture_storage.h"
 

+ 13 - 8
drivers/gles3/rasterizer_gles3.cpp

@@ -34,6 +34,7 @@
 
 #include "core/config/project_settings.h"
 #include "core/os/os.h"
+#include "storage/texture_storage.h"
 
 #define _EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
 #define _EXT_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
@@ -87,6 +88,8 @@
 #endif
 
 void RasterizerGLES3::begin_frame(double frame_step) {
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
 	frame++;
 	delta = frame_step;
 
@@ -95,9 +98,9 @@ void RasterizerGLES3::begin_frame(double frame_step) {
 	double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs");
 	time_total = Math::fmod(time_total, time_roll_over);
 
-	storage.frame.time = time_total;
-	storage.frame.count++;
-	storage.frame.delta = frame_step;
+	texture_storage->frame.time = time_total;
+	texture_storage->frame.count++;
+	texture_storage->frame.delta = frame_step;
 
 	storage.update_dirty_resources();
 
@@ -269,9 +272,10 @@ void RasterizerGLES3::prepare_for_blitting_render_targets() {
 }
 
 void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect) {
-	ERR_FAIL_COND(storage.frame.current_rt);
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+	ERR_FAIL_COND(texture_storage->frame.current_rt);
 
-	GLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target);
+	GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
 	ERR_FAIL_COND(!rt);
 
 	// TODO: do we need a keep 3d linear option?
@@ -282,16 +286,17 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
 		glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
 	}
 	glReadBuffer(GL_COLOR_ATTACHMENT0);
-	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
 	glBlitFramebuffer(0, 0, rt->width, rt->height, 0, p_screen_rect.size.y, p_screen_rect.size.x, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
 }
 
 // is this p_screen useless in a multi window environment?
 void RasterizerGLES3::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) {
 	// do this once off for all blits
-	storage.bind_framebuffer_system();
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+	glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
 
-	storage.frame.current_rt = nullptr;
+	texture_storage->frame.current_rt = nullptr;
 
 	for (int i = 0; i < p_amount; i++) {
 		const BlitToScreen &blit = p_render_targets[i];

+ 6 - 7
drivers/gles3/rasterizer_gles3.h

@@ -37,12 +37,11 @@
 #include "rasterizer_scene_gles3.h"
 #include "rasterizer_storage_gles3.h"
 #include "servers/rendering/renderer_compositor.h"
-#include "storage/canvas_texture_storage.h"
 #include "storage/config.h"
-#include "storage/decal_atlas_storage.h"
+#include "storage/light_storage.h"
 #include "storage/material_storage.h"
 #include "storage/mesh_storage.h"
-#include "storage/render_target_storage.h"
+#include "storage/particles_storage.h"
 #include "storage/texture_storage.h"
 
 class RasterizerGLES3 : public RendererCompositor {
@@ -54,11 +53,11 @@ private:
 
 protected:
 	GLES3::Config config;
-	GLES3::CanvasTextureStorage canvas_texture_storage;
 	GLES3::TextureStorage texture_storage;
-	GLES3::DecalAtlasStorage decal_atlas_storage;
 	GLES3::MaterialStorage material_storage;
 	GLES3::MeshStorage mesh_storage;
+	GLES3::ParticlesStorage particles_storage;
+	GLES3::LightStorage light_storage;
 	RasterizerStorageGLES3 storage;
 	RasterizerCanvasGLES3 canvas;
 	RasterizerSceneGLES3 scene;
@@ -66,11 +65,11 @@ protected:
 	void _blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect);
 
 public:
-	RendererCanvasTextureStorage *get_canvas_texture_storage() { return &canvas_texture_storage; }
+	RendererLightStorage *get_light_storage() { return &light_storage; }
 	RendererMaterialStorage *get_material_storage() { return &material_storage; }
 	RendererMeshStorage *get_mesh_storage() { return &mesh_storage; }
+	RendererParticlesStorage *get_particles_storage() { return &particles_storage; }
 	RendererTextureStorage *get_texture_storage() { return &texture_storage; }
-	RendererDecalAtlasStorage *get_decal_atlas_storage() { return &decal_atlas_storage; }
 	RendererStorage *get_storage() { return &storage; }
 	RendererCanvasRender *get_canvas() { return &canvas; }
 	RendererSceneRender *get_scene() { return &scene; }

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 103 - 1302
drivers/gles3/rasterizer_storage_gles3.cpp


+ 2 - 250
drivers/gles3/rasterizer_storage_gles3.h

@@ -40,10 +40,8 @@
 #include "servers/rendering/renderer_storage.h"
 #include "servers/rendering/shader_compiler.h"
 #include "servers/rendering/shader_language.h"
-#include "storage/canvas_texture_storage.h"
 #include "storage/config.h"
 #include "storage/material_storage.h"
-#include "storage/render_target_storage.h"
 #include "storage/texture_storage.h"
 
 // class RasterizerCanvasGLES3;
@@ -54,8 +52,6 @@ public:
 	// RasterizerCanvasGLES3 *canvas;
 	// RasterizerSceneGLES3 *scene;
 
-	static GLuint system_fbo;
-
 	GLES3::Config *config;
 
 	struct Resources {
@@ -118,6 +114,8 @@ public:
 	/////////////////////////////////////////////////////////////////////////////////////////
 
 public:
+	virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
+
 	/* SKY API */
 	// not sure if used in godot 4?
 	struct Sky {
@@ -132,78 +130,6 @@ public:
 	RID sky_create();
 	void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size);
 
-	/* Light API */
-
-	RID directional_light_allocate() override;
-	void directional_light_initialize(RID p_rid) override;
-	RID omni_light_allocate() override;
-	void omni_light_initialize(RID p_rid) override;
-	RID spot_light_allocate() override;
-	void spot_light_initialize(RID p_rid) override;
-	RID reflection_probe_allocate() override;
-	void reflection_probe_initialize(RID p_rid) override;
-
-	void light_set_color(RID p_light, const Color &p_color) override;
-	void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override;
-	void light_set_shadow(RID p_light, bool p_enabled) override;
-	void light_set_projector(RID p_light, RID p_texture) override;
-	void light_set_negative(RID p_light, bool p_enable) override;
-	void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
-	void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
-	void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
-	void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
-	void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
-
-	void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override;
-
-	void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override;
-	void light_directional_set_blend_splits(RID p_light, bool p_enable) override;
-	bool light_directional_get_blend_splits(RID p_light) const override;
-	void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override;
-	RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override;
-
-	RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override;
-	RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override;
-
-	bool light_has_shadow(RID p_light) const override;
-	bool light_has_projector(RID p_light) const override;
-
-	RS::LightType light_get_type(RID p_light) const override;
-	AABB light_get_aabb(RID p_light) const override;
-	float light_get_param(RID p_light, RS::LightParam p_param) override;
-	Color light_get_color(RID p_light) override;
-	RS::LightBakeMode light_get_bake_mode(RID p_light) override;
-	uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
-	uint64_t light_get_version(RID p_light) const override;
-
-	/* PROBE API */
-
-	void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override;
-	void reflection_probe_set_intensity(RID p_probe, float p_intensity) override;
-	void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override;
-	void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
-	void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
-	void reflection_probe_set_max_distance(RID p_probe, float p_distance) override;
-	void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override;
-	void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override;
-	void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override;
-	void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override;
-	void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override;
-	void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override;
-	void reflection_probe_set_resolution(RID p_probe, int p_resolution) override;
-	void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
-	float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
-
-	AABB reflection_probe_get_aabb(RID p_probe) const override;
-	RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
-	uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
-	Vector3 reflection_probe_get_extents(RID p_probe) const override;
-	Vector3 reflection_probe_get_origin_offset(RID p_probe) const override;
-	float reflection_probe_get_origin_max_distance(RID p_probe) const override;
-	bool reflection_probe_renders_shadows(RID p_probe) const override;
-
-	void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
-
 	/* VOXEL GI API */
 
 	RID voxel_gi_allocate() override;
@@ -245,104 +171,10 @@ public:
 
 	uint32_t voxel_gi_get_version(RID p_voxel_gi) override;
 
-	/* LIGHTMAP CAPTURE */
-	RID lightmap_allocate() override;
-	void lightmap_initialize(RID p_rid) override;
-	void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override;
-	void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
-	void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
-	void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
-	PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
-	PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
-	PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
-	PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override;
-	AABB lightmap_get_aabb(RID p_lightmap) const override;
-	void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override;
-	bool lightmap_is_interior(RID p_lightmap) const override;
-	void lightmap_set_probe_capture_update_speed(float p_speed) override;
-	float lightmap_get_probe_capture_update_speed() const override;
-
 	/* OCCLUDER */
 
 	void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices);
 
-	/* PARTICLES */
-
-	RID particles_allocate() override;
-	void particles_initialize(RID p_rid) override;
-	void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
-	void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override;
-	void particles_set_emitting(RID p_particles, bool p_emitting) override;
-	void particles_set_amount(RID p_particles, int p_amount) override;
-	void particles_set_lifetime(RID p_particles, double p_lifetime) override;
-	void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
-	void particles_set_pre_process_time(RID p_particles, double p_time) override;
-	void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
-	void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
-	void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
-	void particles_set_speed_scale(RID p_particles, double p_scale) override;
-	void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override;
-	void particles_set_process_material(RID p_particles, RID p_material) override;
-	RID particles_get_process_material(RID p_particles) const override;
-	void particles_set_fixed_fps(RID p_particles, int p_fps) override;
-	void particles_set_interpolate(RID p_particles, bool p_enable) override;
-	void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
-	void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override;
-	void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override;
-	void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
-
-	void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
-
-	void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
-	void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
-
-	void particles_restart(RID p_particles) override;
-
-	void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override;
-
-	void particles_set_draw_passes(RID p_particles, int p_count) override;
-	void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override;
-
-	void particles_request_process(RID p_particles) override;
-	AABB particles_get_current_aabb(RID p_particles) override;
-	AABB particles_get_aabb(RID p_particles) const override;
-
-	void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
-
-	bool particles_get_emitting(RID p_particles) override;
-	int particles_get_draw_passes(RID p_particles) const override;
-	RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override;
-
-	void particles_add_collision(RID p_particles, RID p_instance) override;
-	void particles_remove_collision(RID p_particles, RID p_instance) override;
-
-	void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
-
-	void update_particles() override;
-	bool particles_is_inactive(RID p_particles) const override;
-
-	/* PARTICLES COLLISION */
-
-	RID particles_collision_allocate() override;
-	void particles_collision_initialize(RID p_rid) override;
-	void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override;
-	void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override;
-	void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override;
-	void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override;
-	void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override;
-	void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override;
-	void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override;
-	void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override;
-	void particles_collision_height_field_update(RID p_particles_collision) override;
-	void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override;
-	AABB particles_collision_get_aabb(RID p_particles_collision) const override;
-	bool particles_collision_is_heightfield(RID p_particles_collision) const override;
-	RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
-
-	RID particles_collision_instance_create(RID p_collision) override;
-	void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override;
-	void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override;
-
 	/* FOG VOLUMES */
 
 	RID fog_volume_allocate() override;
@@ -363,43 +195,6 @@ public:
 	AABB visibility_notifier_get_aabb(RID p_notifier) const override;
 	void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override;
 
-	// RENDER TARGET
-
-	mutable RID_PtrOwner<GLES3::RenderTarget> render_target_owner;
-
-	void _render_target_clear(GLES3::RenderTarget *rt);
-	void _render_target_allocate(GLES3::RenderTarget *rt);
-	void _set_current_render_target(RID p_render_target);
-
-	RID render_target_create() override;
-	void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
-	void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
-	Size2i render_target_get_size(RID p_render_target);
-	RID render_target_get_texture(RID p_render_target) override;
-	void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
-
-	void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override;
-	bool render_target_was_used(RID p_render_target) override;
-	void render_target_clear_used(RID p_render_target);
-	void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa);
-	void render_target_set_use_fxaa(RID p_render_target, bool p_fxaa);
-	void render_target_set_use_debanding(RID p_render_target, bool p_debanding);
-
-	// new
-	void render_target_set_as_unused(RID p_render_target) override {
-		render_target_clear_used(p_render_target);
-	}
-
-	void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
-	bool render_target_is_clear_requested(RID p_render_target) override;
-	Color render_target_get_clear_request_color(RID p_render_target) override;
-	void render_target_disable_clear_request(RID p_render_target) override;
-	void render_target_do_clear_request(RID p_render_target) override;
-
-	void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
-	Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
-	void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
-
 	// access from canvas
 	//	GLES3::RenderTarget * render_target_get(RID p_render_target);
 
@@ -439,24 +234,6 @@ public:
 
 	bool free(RID p_rid) override;
 
-	struct Frame {
-		GLES3::RenderTarget *current_rt;
-
-		// these 2 may have been superseded by the equivalents in the render target.
-		// these may be able to be removed.
-		bool clear_request;
-		Color clear_request_color;
-
-		float time;
-		float delta;
-		uint64_t count;
-
-		Frame() {
-			//			current_rt = nullptr;
-			//			clear_request = false;
-		}
-	} frame;
-
 	void initialize();
 	void finalize();
 
@@ -498,34 +275,9 @@ public:
 		return String();
 	}
 
-	// make access easier to these
-	struct Dimensions {
-		// render target
-		int rt_width;
-		int rt_height;
-
-		// window
-		int win_width;
-		int win_height;
-		Dimensions() {
-			rt_width = 0;
-			rt_height = 0;
-			win_width = 0;
-			win_height = 0;
-		}
-	} _dims;
-
 	void buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target = GL_ARRAY_BUFFER, GLenum p_usage = GL_DYNAMIC_DRAW, bool p_optional_orphan = false) const;
 	bool safe_buffer_sub_data(unsigned int p_total_buffer_size, GLenum p_target, unsigned int p_offset, unsigned int p_data_size, const void *p_data, unsigned int &r_offset_after) const;
 
-	void bind_framebuffer(GLuint framebuffer) {
-		glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
-	}
-
-	void bind_framebuffer_system() {
-		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
-	}
-
 	RasterizerStorageGLES3();
 	~RasterizerStorageGLES3();
 };

+ 0 - 96
drivers/gles3/storage/canvas_texture_storage.cpp

@@ -1,96 +0,0 @@
-/*************************************************************************/
-/*  canvas_texture_storage.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 "canvas_texture_storage.h"
-
-using namespace GLES3;
-
-CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr;
-
-CanvasTextureStorage *CanvasTextureStorage::get_singleton() {
-	return singleton;
-}
-
-CanvasTextureStorage::CanvasTextureStorage() {
-	singleton = this;
-}
-
-CanvasTextureStorage::~CanvasTextureStorage() {
-	singleton = nullptr;
-}
-
-RID CanvasTextureStorage::canvas_texture_allocate() {
-	return canvas_texture_owner.allocate_rid();
-}
-
-void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) {
-	canvas_texture_owner.initialize_rid(p_rid);
-}
-
-void CanvasTextureStorage::canvas_texture_free(RID p_rid) {
-	canvas_texture_owner.free(p_rid);
-}
-
-void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
-	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
-	switch (p_channel) {
-		case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
-			ct->diffuse = p_texture;
-		} break;
-		case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
-			ct->normal_map = p_texture;
-		} break;
-		case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
-			ct->specular = p_texture;
-		} break;
-	}
-}
-
-void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
-	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
-	ct->specular_color.r = p_specular_color.r;
-	ct->specular_color.g = p_specular_color.g;
-	ct->specular_color.b = p_specular_color.b;
-	ct->specular_color.a = p_shininess;
-}
-
-void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
-	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
-	ct->texture_filter = p_filter;
-}
-
-void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
-	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
-	ct->texture_repeat = p_repeat;
-}
-
-#endif // !GLES3_ENABLED

+ 0 - 87
drivers/gles3/storage/canvas_texture_storage.h

@@ -1,87 +0,0 @@
-/*************************************************************************/
-/*  canvas_texture_storage.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 CANVAS_TEXTURE_STORAGE_GLES3_H
-#define CANVAS_TEXTURE_STORAGE_GLES3_H
-
-#ifdef GLES3_ENABLED
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
-
-namespace GLES3 {
-
-struct CanvasTexture {
-	RID diffuse;
-	RID normal_map;
-	RID specular;
-	Color specular_color = Color(1, 1, 1, 1);
-	float shininess = 1.0;
-
-	RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
-	RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
-
-	Size2i size_cache = Size2i(1, 1);
-	bool use_normal_cache = false;
-	bool use_specular_cache = false;
-	bool cleared_cache = true;
-};
-
-class CanvasTextureStorage : public RendererCanvasTextureStorage {
-private:
-	static CanvasTextureStorage *singleton;
-
-	RID_Owner<CanvasTexture, true> canvas_texture_owner;
-
-public:
-	static CanvasTextureStorage *get_singleton();
-
-	CanvasTextureStorage();
-	virtual ~CanvasTextureStorage();
-
-	CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
-	bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
-
-	virtual RID canvas_texture_allocate() override;
-	virtual void canvas_texture_initialize(RID p_rid) override;
-	virtual void canvas_texture_free(RID p_rid) override;
-
-	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
-	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
-
-	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
-	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
-};
-
-} // namespace GLES3
-
-#endif // !GLES3_ENABLED
-
-#endif // !CANVAS_TEXTURE_STORAGE_GLES3_H

+ 4 - 0
drivers/gles3/storage/config.cpp

@@ -40,6 +40,10 @@ Config *Config::singleton = nullptr;
 Config::Config() {
 	singleton = this;
 	should_orphan = true;
+
+	// If this is to early we need to change our code similar to what we're doing in RendererRD,
+	// and instantiate our storage classes when we are ready to do so in the order we want.
+	initialize();
 }
 
 Config::~Config() {

+ 0 - 75
drivers/gles3/storage/decal_atlas_storage.cpp

@@ -1,75 +0,0 @@
-/*************************************************************************/
-/*  decal_atlas_storage.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 "decal_atlas_storage.h"
-
-using namespace GLES3;
-
-RID DecalAtlasStorage::decal_allocate() {
-	return RID();
-}
-
-void DecalAtlasStorage::decal_initialize(RID p_rid) {
-}
-
-void DecalAtlasStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
-}
-
-void DecalAtlasStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
-}
-
-void DecalAtlasStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
-}
-
-void DecalAtlasStorage::decal_set_albedo_mix(RID p_decal, float p_mix) {
-}
-
-void DecalAtlasStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) {
-}
-
-void DecalAtlasStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
-}
-
-void DecalAtlasStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
-}
-
-void DecalAtlasStorage::decal_set_fade(RID p_decal, float p_above, float p_below) {
-}
-
-void DecalAtlasStorage::decal_set_normal_fade(RID p_decal, float p_fade) {
-}
-
-AABB DecalAtlasStorage::decal_get_aabb(RID p_decal) const {
-	return AABB();
-}
-
-#endif // !GLES3_ENABLED

+ 0 - 67
drivers/gles3/storage/decal_atlas_storage.h

@@ -1,67 +0,0 @@
-/*************************************************************************/
-/*  decal_atlas_storage.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 DECAL_ATLAS_STORAGE_GLES3_H
-#define DECAL_ATLAS_STORAGE_GLES3_H
-
-#ifdef GLES3_ENABLED
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/storage/decal_atlas_storage.h"
-
-namespace GLES3 {
-
-class DecalAtlasStorage : public RendererDecalAtlasStorage {
-public:
-	virtual RID decal_allocate() override;
-	virtual void decal_initialize(RID p_rid) override;
-	virtual void decal_free(RID p_rid) override{};
-
-	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
-	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
-	virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
-	virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
-	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
-	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
-	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
-	virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
-	virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
-
-	virtual AABB decal_get_aabb(RID p_decal) const override;
-
-	virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-};
-
-} // namespace GLES3
-
-#endif // !GLES3_ENABLED
-
-#endif // !DECAL_ATLAS_STORAGE_GLES3_H

+ 316 - 0
drivers/gles3/storage/light_storage.cpp

@@ -0,0 +1,316 @@
+/*************************************************************************/
+/*  light_storage.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 "light_storage.h"
+#include "config.h"
+
+using namespace GLES3;
+
+LightStorage *LightStorage::singleton = nullptr;
+
+LightStorage *LightStorage::get_singleton() {
+	return singleton;
+}
+
+LightStorage::LightStorage() {
+	singleton = this;
+}
+
+LightStorage::~LightStorage() {
+	singleton = nullptr;
+}
+
+/* Light API */
+
+RID LightStorage::directional_light_allocate() {
+	return RID();
+}
+
+void LightStorage::directional_light_initialize(RID p_rid) {
+}
+
+RID LightStorage::omni_light_allocate() {
+	return RID();
+}
+
+void LightStorage::omni_light_initialize(RID p_rid) {
+}
+
+RID LightStorage::spot_light_allocate() {
+	return RID();
+}
+
+void LightStorage::spot_light_initialize(RID p_rid) {
+}
+
+void LightStorage::light_free(RID p_rid) {
+}
+
+void LightStorage::light_set_color(RID p_light, const Color &p_color) {
+}
+
+void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
+}
+
+void LightStorage::light_set_shadow(RID p_light, bool p_enabled) {
+}
+
+void LightStorage::light_set_projector(RID p_light, RID p_texture) {
+}
+
+void LightStorage::light_set_negative(RID p_light, bool p_enable) {
+}
+
+void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
+}
+
+void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
+}
+
+void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
+}
+
+void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
+}
+
+void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
+}
+
+void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
+}
+
+void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
+}
+
+void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) {
+}
+
+bool LightStorage::light_directional_get_blend_splits(RID p_light) const {
+	return false;
+}
+
+void LightStorage::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) {
+}
+
+RS::LightDirectionalSkyMode LightStorage::light_directional_get_sky_mode(RID p_light) const {
+	return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
+}
+
+RS::LightDirectionalShadowMode LightStorage::light_directional_get_shadow_mode(RID p_light) {
+	return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+}
+
+RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) {
+	return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
+}
+
+bool LightStorage::light_has_shadow(RID p_light) const {
+	return false;
+}
+
+bool LightStorage::light_has_projector(RID p_light) const {
+	return false;
+}
+
+RS::LightType LightStorage::light_get_type(RID p_light) const {
+	return RS::LIGHT_OMNI;
+}
+
+AABB LightStorage::light_get_aabb(RID p_light) const {
+	return AABB();
+}
+
+float LightStorage::light_get_param(RID p_light, RS::LightParam p_param) {
+	return 0.0;
+}
+
+Color LightStorage::light_get_color(RID p_light) {
+	return Color();
+}
+
+RS::LightBakeMode LightStorage::light_get_bake_mode(RID p_light) {
+	return RS::LIGHT_BAKE_DISABLED;
+}
+
+uint32_t LightStorage::light_get_max_sdfgi_cascade(RID p_light) {
+	return 0;
+}
+
+uint64_t LightStorage::light_get_version(RID p_light) const {
+	return 0;
+}
+
+/* PROBE API */
+
+RID LightStorage::reflection_probe_allocate() {
+	return RID();
+}
+
+void LightStorage::reflection_probe_initialize(RID p_rid) {
+}
+
+void LightStorage::reflection_probe_free(RID p_rid) {
+}
+
+void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
+}
+
+void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
+}
+
+void LightStorage::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
+}
+
+void LightStorage::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
+}
+
+void LightStorage::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
+}
+
+void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
+}
+
+void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+}
+
+void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
+}
+
+void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
+}
+
+void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
+}
+
+void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
+}
+
+void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
+}
+
+void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
+}
+
+AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
+	return AABB();
+}
+
+RS::ReflectionProbeUpdateMode LightStorage::reflection_probe_get_update_mode(RID p_probe) const {
+	return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE;
+}
+
+uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const {
+	return 0;
+}
+
+Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const {
+	return Vector3();
+}
+
+Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const {
+	return Vector3();
+}
+
+float LightStorage::reflection_probe_get_origin_max_distance(RID p_probe) const {
+	return 0.0;
+}
+
+bool LightStorage::reflection_probe_renders_shadows(RID p_probe) const {
+	return false;
+}
+
+void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
+}
+
+float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
+	return 0.0;
+}
+
+/* LIGHTMAP CAPTURE */
+
+RID LightStorage::lightmap_allocate() {
+	return RID();
+}
+
+void LightStorage::lightmap_initialize(RID p_rid) {
+}
+
+void LightStorage::lightmap_free(RID p_rid) {
+}
+
+void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
+}
+
+void LightStorage::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
+}
+
+void LightStorage::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
+}
+
+void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
+}
+
+PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {
+	return PackedVector3Array();
+}
+
+PackedColorArray LightStorage::lightmap_get_probe_capture_sh(RID p_lightmap) const {
+	return PackedColorArray();
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
+	return PackedInt32Array();
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
+	return PackedInt32Array();
+}
+
+AABB LightStorage::lightmap_get_aabb(RID p_lightmap) const {
+	return AABB();
+}
+
+void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
+}
+
+bool LightStorage::lightmap_is_interior(RID p_lightmap) const {
+	return false;
+}
+
+void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) {
+}
+
+float LightStorage::lightmap_get_probe_capture_update_speed() const {
+	return 0;
+}
+
+#endif // !GLES3_ENABLED

+ 154 - 0
drivers/gles3/storage/light_storage.h

@@ -0,0 +1,154 @@
+/*************************************************************************/
+/*  light_storage.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 LIGHT_STORAGE_GLES3_H
+#define LIGHT_STORAGE_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/storage/light_storage.h"
+
+namespace GLES3 {
+
+class LightStorage : public RendererLightStorage {
+private:
+	static LightStorage *singleton;
+
+public:
+	static LightStorage *get_singleton();
+
+	LightStorage();
+	virtual ~LightStorage();
+
+	/* Light API */
+
+	virtual RID directional_light_allocate() override;
+	virtual void directional_light_initialize(RID p_rid) override;
+	virtual RID omni_light_allocate() override;
+	virtual void omni_light_initialize(RID p_rid) override;
+	virtual RID spot_light_allocate() override;
+	virtual void spot_light_initialize(RID p_rid) override;
+
+	virtual void light_free(RID p_rid) override;
+
+	virtual void light_set_color(RID p_light, const Color &p_color) override;
+	virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override;
+	virtual void light_set_shadow(RID p_light, bool p_enabled) override;
+	virtual void light_set_projector(RID p_light, RID p_texture) override;
+	virtual void light_set_negative(RID p_light, bool p_enable) override;
+	virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
+	virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
+	virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
+	virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
+	virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
+
+	virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override;
+
+	virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override;
+	virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) override;
+	virtual bool light_directional_get_blend_splits(RID p_light) const override;
+	virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override;
+	virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override;
+
+	virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override;
+	virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override;
+
+	virtual bool light_has_shadow(RID p_light) const override;
+	virtual bool light_has_projector(RID p_light) const override;
+
+	virtual RS::LightType light_get_type(RID p_light) const override;
+	virtual AABB light_get_aabb(RID p_light) const override;
+	virtual float light_get_param(RID p_light, RS::LightParam p_param) override;
+	virtual Color light_get_color(RID p_light) override;
+	virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override;
+	virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
+	virtual uint64_t light_get_version(RID p_light) const override;
+
+	/* PROBE API */
+
+	virtual RID reflection_probe_allocate() override;
+	virtual void reflection_probe_initialize(RID p_rid) override;
+	virtual void reflection_probe_free(RID p_rid) override;
+
+	virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override;
+	virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override;
+	virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override;
+	virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
+	virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
+	virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override;
+	virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override;
+	virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override;
+	virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override;
+	virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override;
+	virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override;
+	virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override;
+	virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override;
+	virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
+	virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
+
+	virtual AABB reflection_probe_get_aabb(RID p_probe) const override;
+	virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
+	virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
+	virtual Vector3 reflection_probe_get_extents(RID p_probe) const override;
+	virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override;
+	virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override;
+	virtual bool reflection_probe_renders_shadows(RID p_probe) const override;
+
+	/* LIGHTMAP CAPTURE */
+
+	virtual RID lightmap_allocate() override;
+	virtual void lightmap_initialize(RID p_rid) override;
+	virtual void lightmap_free(RID p_rid) override;
+
+	virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override;
+	virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
+	virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
+	virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
+	virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
+	virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
+	virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
+	virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override;
+	virtual AABB lightmap_get_aabb(RID p_lightmap) const override;
+	virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override;
+	virtual bool lightmap_is_interior(RID p_lightmap) const override;
+	virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
+	virtual float lightmap_get_probe_capture_update_speed() const override;
+};
+
+} // namespace GLES3
+
+#endif // !GLES3_ENABLED
+
+#endif // !LIGHT_STORAGE_GLES3_H

+ 254 - 0
drivers/gles3/storage/particles_storage.cpp

@@ -0,0 +1,254 @@
+/*************************************************************************/
+/*  particles_storage.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 "particles_storage.h"
+
+using namespace GLES3;
+
+ParticlesStorage *ParticlesStorage::singleton = nullptr;
+
+ParticlesStorage *ParticlesStorage::get_singleton() {
+	return singleton;
+}
+
+ParticlesStorage::ParticlesStorage() {
+	singleton = this;
+}
+
+ParticlesStorage::~ParticlesStorage() {
+	singleton = nullptr;
+}
+
+/* PARTICLES */
+
+RID ParticlesStorage::particles_allocate() {
+	return RID();
+}
+
+void ParticlesStorage::particles_initialize(RID p_rid) {
+}
+
+void ParticlesStorage::particles_free(RID p_rid) {
+}
+
+void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
+}
+
+void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+}
+
+void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) {
+}
+
+void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
+}
+
+void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
+}
+
+void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) {
+}
+
+void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) {
+}
+
+void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
+}
+
+void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
+}
+
+void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
+}
+
+void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) {
+}
+
+void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
+}
+
+void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
+}
+
+RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
+	return RID();
+}
+
+void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
+}
+
+void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) {
+}
+
+void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) {
+}
+
+void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
+}
+
+void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+}
+
+void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) {
+}
+
+void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
+}
+
+void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
+}
+
+void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
+}
+
+void ParticlesStorage::particles_restart(RID p_particles) {
+}
+
+void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
+}
+
+void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_count) {
+}
+
+void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
+}
+
+void ParticlesStorage::particles_request_process(RID p_particles) {
+}
+
+AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
+	return AABB();
+}
+
+AABB ParticlesStorage::particles_get_aabb(RID p_particles) const {
+	return AABB();
+}
+
+void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
+}
+
+bool ParticlesStorage::particles_get_emitting(RID p_particles) {
+	return false;
+}
+
+int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
+	return 0;
+}
+
+RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
+	return RID();
+}
+
+void ParticlesStorage::particles_add_collision(RID p_particles, RID p_instance) {
+}
+
+void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_instance) {
+}
+
+void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
+}
+
+void ParticlesStorage::update_particles() {
+}
+
+bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
+	return false;
+}
+
+/* PARTICLES COLLISION */
+
+RID ParticlesStorage::particles_collision_allocate() {
+	return RID();
+}
+
+void ParticlesStorage::particles_collision_initialize(RID p_rid) {
+}
+
+void ParticlesStorage::particles_collision_free(RID p_rid) {
+}
+
+void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
+}
+
+void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
+}
+
+void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
+}
+
+void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
+}
+
+void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
+}
+
+void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
+}
+
+void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
+}
+
+void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
+}
+
+void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
+}
+
+void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
+}
+
+AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const {
+	return AABB();
+}
+
+bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const {
+	return false;
+}
+
+RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
+	return RID();
+}
+
+RID ParticlesStorage::particles_collision_instance_create(RID p_collision) {
+	return RID();
+}
+
+void ParticlesStorage::particles_collision_instance_free(RID p_rid) {
+}
+
+void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
+}
+
+void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+}
+
+#endif // GLES3_ENABLED

+ 140 - 0
drivers/gles3/storage/particles_storage.h

@@ -0,0 +1,140 @@
+/*************************************************************************/
+/*  particles_storage.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 PARTICLES_STORAGE_GLES3_H
+#define PARTICLES_STORAGE_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/storage/particles_storage.h"
+
+namespace GLES3 {
+
+class ParticlesStorage : public RendererParticlesStorage {
+private:
+	static ParticlesStorage *singleton;
+
+public:
+	static ParticlesStorage *get_singleton();
+
+	ParticlesStorage();
+	virtual ~ParticlesStorage();
+
+	/* PARTICLES */
+
+	virtual RID particles_allocate() override;
+	virtual void particles_initialize(RID p_rid) override;
+	virtual void particles_free(RID p_rid) override;
+
+	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
+	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override;
+	virtual void particles_set_emitting(RID p_particles, bool p_emitting) override;
+	virtual void particles_set_amount(RID p_particles, int p_amount) override;
+	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
+	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
+	virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
+	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
+	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
+	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
+	virtual void particles_set_speed_scale(RID p_particles, double p_scale) override;
+	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override;
+	virtual void particles_set_process_material(RID p_particles, RID p_material) override;
+	virtual RID particles_get_process_material(RID p_particles) const override;
+	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override;
+	virtual void particles_set_interpolate(RID p_particles, bool p_enable) override;
+	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
+	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override;
+	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override;
+	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
+
+	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
+
+	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
+	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
+
+	virtual void particles_restart(RID p_particles) override;
+
+	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override;
+
+	virtual void particles_set_draw_passes(RID p_particles, int p_count) override;
+	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override;
+
+	virtual void particles_request_process(RID p_particles) override;
+	virtual AABB particles_get_current_aabb(RID p_particles) override;
+	virtual AABB particles_get_aabb(RID p_particles) const override;
+
+	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
+
+	virtual bool particles_get_emitting(RID p_particles) override;
+	virtual int particles_get_draw_passes(RID p_particles) const override;
+	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override;
+
+	virtual void particles_add_collision(RID p_particles, RID p_instance) override;
+	virtual void particles_remove_collision(RID p_particles, RID p_instance) override;
+
+	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
+
+	virtual void update_particles() override;
+	virtual bool particles_is_inactive(RID p_particles) const override;
+
+	/* PARTICLES COLLISION */
+
+	virtual RID particles_collision_allocate() override;
+	virtual void particles_collision_initialize(RID p_rid) override;
+	virtual void particles_collision_free(RID p_rid) override;
+
+	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override;
+	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override;
+	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override;
+	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override;
+	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override;
+	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override;
+	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override;
+	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override;
+	virtual void particles_collision_height_field_update(RID p_particles_collision) override;
+	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override;
+	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
+	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
+	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
+
+	virtual RID particles_collision_instance_create(RID p_collision) override;
+	virtual void particles_collision_instance_free(RID p_rid) override;
+	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override;
+	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override;
+};
+
+} // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // !PARTICLES_STORAGE_GLES3_H

+ 0 - 132
drivers/gles3/storage/render_target_storage.h

@@ -1,132 +0,0 @@
-/*************************************************************************/
-/*  render_target_storage.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_TARGET_STORAGE_GLES3_H
-#define RENDER_TARGET_STORAGE_GLES3_H
-
-#ifdef GLES3_ENABLED
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_storage.h" // included until we move stuff into storage/render_target_storage.h
-// #include "servers/rendering/storage/render_target_storage.h"
-
-// This must come first to avoid windows.h mess
-#include "platform_config.h"
-#ifndef OPENGL_INCLUDE_H
-#include <GLES3/gl3.h>
-#else
-#include OPENGL_INCLUDE_H
-#endif
-
-namespace GLES3 {
-
-// NOTE, this class currently is just a container for the the RenderTarget struct and is not yet implemented further, we'll do that next after we finish with TextureStorage
-
-struct RenderTarget {
-	RID self;
-	GLuint fbo = 0;
-	GLuint color = 0;
-	GLuint depth = 0;
-
-	GLuint multisample_fbo = 0;
-	GLuint multisample_color = 0;
-	GLuint multisample_depth = 0;
-	bool multisample_active = false;
-
-	struct Effect {
-		GLuint fbo = 0;
-		int width = 0;
-		int height = 0;
-
-		GLuint color = 0;
-	};
-
-	Effect copy_screen_effect;
-
-	struct MipMaps {
-		struct Size {
-			GLuint fbo = 0;
-			GLuint color = 0;
-			int width = 0;
-			int height = 0;
-		};
-
-		Vector<Size> sizes;
-		GLuint color = 0;
-		int levels = 0;
-	};
-
-	MipMaps mip_maps[2];
-
-	struct External {
-		GLuint fbo = 0;
-		GLuint color = 0;
-		GLuint depth = 0;
-		RID texture;
-	} external;
-
-	int x = 0;
-	int y = 0;
-	int width = 0;
-	int height = 0;
-
-	bool flags[RendererStorage::RENDER_TARGET_FLAG_MAX] = {};
-
-	// instead of allocating sized render targets immediately,
-	// defer this for faster startup
-	bool allocate_is_dirty = false;
-	bool used_in_frame = false;
-	RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
-
-	bool use_fxaa = false;
-	bool use_debanding = false;
-
-	RID texture;
-
-	bool used_dof_blur_near = false;
-	bool mip_maps_allocated = false;
-
-	Color clear_color = Color(1, 1, 1, 1);
-	bool clear_requested = false;
-
-	RenderTarget() {
-		for (int i = 0; i < RendererStorage::RENDER_TARGET_FLAG_MAX; ++i) {
-			flags[i] = false;
-		}
-		external.fbo = 0;
-	}
-};
-
-} // namespace GLES3
-
-#endif // !GLES3_ENABLED
-
-#endif // !RENDER_TARGET_STORAGE_GLES3_H

+ 932 - 0
drivers/gles3/storage/texture_storage.cpp

@@ -43,6 +43,81 @@ TextureStorage *TextureStorage::get_singleton() {
 
 TextureStorage::TextureStorage() {
 	singleton = this;
+
+	system_fbo = 0;
+
+	frame.count = 0;
+	frame.delta = 0;
+	frame.current_rt = nullptr;
+	frame.clear_request = false;
+
+	Config *config = Config::get_singleton();
+
+	//determine formats for depth textures (or renderbuffers)
+	if (config->support_depth_texture) {
+		// Will use texture for depth
+		// have to manually see if we can create a valid framebuffer texture using UNSIGNED_INT,
+		// as there is no extension to test for this.
+		GLuint fbo;
+		glGenFramebuffers(1, &fbo);
+		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+		GLuint depth;
+		glGenTextures(1, &depth);
+		glBindTexture(GL_TEXTURE_2D, depth);
+		glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config->depth_type, 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, 0);
+
+		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+		glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+		glDeleteFramebuffers(1, &fbo);
+		glBindTexture(GL_TEXTURE_2D, 0);
+		glDeleteTextures(1, &depth);
+
+		if (status != GL_FRAMEBUFFER_COMPLETE) {
+			// If it fails, test to see if it supports a framebuffer texture using UNSIGNED_SHORT
+			// This is needed because many OSX devices don't support either UNSIGNED_INT or UNSIGNED_SHORT
+#ifdef GLES_OVER_GL
+			config->depth_internalformat = GL_DEPTH_COMPONENT16;
+#else
+			// OES_depth_texture extension only specifies GL_DEPTH_COMPONENT.
+			config->depth_internalformat = GL_DEPTH_COMPONENT;
+#endif
+			config->depth_type = GL_UNSIGNED_SHORT;
+
+			glGenFramebuffers(1, &fbo);
+			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+			glGenTextures(1, &depth);
+			glBindTexture(GL_TEXTURE_2D, depth);
+			glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 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, 0);
+
+			status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+			if (status != GL_FRAMEBUFFER_COMPLETE) {
+				//if it fails again depth textures aren't supported, use rgba shadows and renderbuffer for depth
+				config->support_depth_texture = false;
+				config->use_rgba_3d_shadows = true;
+			}
+
+			glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+			glDeleteFramebuffers(1, &fbo);
+			glBindTexture(GL_TEXTURE_2D, 0);
+			glDeleteTextures(1, &depth);
+		}
+	}
 }
 
 TextureStorage::~TextureStorage() {
@@ -65,6 +140,55 @@ bool TextureStorage::can_create_resources_async() const {
 	return false;
 }
 
+/* Canvas Texture API */
+
+RID TextureStorage::canvas_texture_allocate() {
+	return canvas_texture_owner.allocate_rid();
+}
+
+void TextureStorage::canvas_texture_initialize(RID p_rid) {
+	canvas_texture_owner.initialize_rid(p_rid);
+}
+
+void TextureStorage::canvas_texture_free(RID p_rid) {
+	canvas_texture_owner.free(p_rid);
+}
+
+void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
+	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+	switch (p_channel) {
+		case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
+			ct->diffuse = p_texture;
+		} break;
+		case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
+			ct->normal_map = p_texture;
+		} break;
+		case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
+			ct->specular = p_texture;
+		} break;
+	}
+}
+
+void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
+	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+	ct->specular_color.r = p_specular_color.r;
+	ct->specular_color.g = p_specular_color.g;
+	ct->specular_color.b = p_specular_color.b;
+	ct->specular_color.a = p_shininess;
+}
+
+void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
+	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+	ct->texture_filter = p_filter;
+}
+
+void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
+	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+	ct->texture_repeat = p_repeat;
+}
+
+/* Texture API */
+
 static const GLenum _cube_side_enum[6] = {
 	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
 	GL_TEXTURE_CUBE_MAP_POSITIVE_X,
@@ -1208,4 +1332,812 @@ void TextureStorage::textures_keep_original(bool p_enable) {
 	Config::get_singleton()->keep_original_textures = p_enable;
 }
 
+/* DECAL API */
+
+RID TextureStorage::decal_allocate() {
+	return RID();
+}
+
+void TextureStorage::decal_initialize(RID p_rid) {
+}
+
+void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
+}
+
+void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
+}
+
+void TextureStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
+}
+
+void TextureStorage::decal_set_albedo_mix(RID p_decal, float p_mix) {
+}
+
+void TextureStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) {
+}
+
+void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
+}
+
+void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
+}
+
+void TextureStorage::decal_set_fade(RID p_decal, float p_above, float p_below) {
+}
+
+void TextureStorage::decal_set_normal_fade(RID p_decal, float p_fade) {
+}
+
+AABB TextureStorage::decal_get_aabb(RID p_decal) const {
+	return AABB();
+}
+
+/* RENDER TARGET API */
+
+GLuint TextureStorage::system_fbo = 0;
+
+void TextureStorage::_set_current_render_target(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+
+	if (rt) {
+		if (rt->allocate_is_dirty) {
+			rt->allocate_is_dirty = false;
+			_render_target_allocate(rt);
+		}
+
+		frame.current_rt = rt;
+		ERR_FAIL_COND(!rt);
+		frame.clear_request = false;
+
+		glViewport(0, 0, rt->width, rt->height);
+
+		_dims.rt_width = rt->width;
+		_dims.rt_height = rt->height;
+		_dims.win_width = rt->width;
+		_dims.win_height = rt->height;
+
+	} else {
+		frame.current_rt = nullptr;
+		frame.clear_request = false;
+		glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+	}
+}
+
+void TextureStorage::_render_target_allocate(RenderTarget *rt) {
+	Config *config = Config::get_singleton();
+
+	// do not allocate a render target with no size
+	if (rt->width <= 0 || rt->height <= 0) {
+		return;
+	}
+
+	// do not allocate a render target that is attached to the screen
+	if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
+		rt->fbo = system_fbo;
+		return;
+	}
+
+	GLuint color_internal_format;
+	GLuint color_format;
+	GLuint color_type = GL_UNSIGNED_BYTE;
+	Image::Format image_format;
+
+	if (rt->flags[TextureStorage::RENDER_TARGET_TRANSPARENT]) {
+#ifdef GLES_OVER_GL
+		color_internal_format = GL_RGBA8;
+#else
+		color_internal_format = GL_RGBA;
+#endif
+		color_format = GL_RGBA;
+		image_format = Image::FORMAT_RGBA8;
+	} else {
+#ifdef GLES_OVER_GL
+		color_internal_format = GL_RGB8;
+#else
+		color_internal_format = GL_RGB;
+#endif
+		color_format = GL_RGB;
+		image_format = Image::FORMAT_RGB8;
+	}
+
+	rt->used_dof_blur_near = false;
+	rt->mip_maps_allocated = false;
+
+	{
+		/* Front FBO */
+
+		Texture *texture = get_texture(rt->texture);
+		ERR_FAIL_COND(!texture);
+
+		// framebuffer
+		glGenFramebuffers(1, &rt->fbo);
+		glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
+
+		// color
+		glGenTextures(1, &rt->color);
+		glBindTexture(GL_TEXTURE_2D, rt->color);
+
+		glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, nullptr);
+
+		if (texture->flags & TEXTURE_FLAG_FILTER) {
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		} else {
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+
+		// depth
+
+		if (config->support_depth_texture) {
+			glGenTextures(1, &rt->depth);
+			glBindTexture(GL_TEXTURE_2D, rt->depth);
+			glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config->depth_type, 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, rt->depth, 0);
+		} else {
+			glGenRenderbuffers(1, &rt->depth);
+			glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
+
+			glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, rt->width, rt->height);
+
+			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+		}
+
+		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+		if (status != GL_FRAMEBUFFER_COMPLETE) {
+			glDeleteFramebuffers(1, &rt->fbo);
+			if (config->support_depth_texture) {
+				glDeleteTextures(1, &rt->depth);
+			} else {
+				glDeleteRenderbuffers(1, &rt->depth);
+			}
+
+			glDeleteTextures(1, &rt->color);
+			rt->fbo = 0;
+			rt->width = 0;
+			rt->height = 0;
+			rt->color = 0;
+			rt->depth = 0;
+			texture->tex_id = 0;
+			texture->active = false;
+			WARN_PRINT("Could not create framebuffer!!");
+			return;
+		}
+
+		texture->format = image_format;
+		texture->gl_format_cache = color_format;
+		texture->gl_type_cache = GL_UNSIGNED_BYTE;
+		texture->gl_internal_format_cache = color_internal_format;
+		texture->tex_id = rt->color;
+		texture->width = rt->width;
+		texture->alloc_width = rt->width;
+		texture->height = rt->height;
+		texture->alloc_height = rt->height;
+		texture->active = true;
+
+		texture_set_flags(rt->texture, texture->flags);
+	}
+
+	/* BACK FBO */
+	/* For MSAA */
+
+#ifndef JAVASCRIPT_ENABLED
+	if (rt->msaa >= RS::VIEWPORT_MSAA_2X && rt->msaa <= RS::VIEWPORT_MSAA_8X) {
+		rt->multisample_active = true;
+
+		static const int msaa_value[] = { 0, 2, 4, 8, 16 };
+		int msaa = msaa_value[rt->msaa];
+
+		int max_samples = 0;
+		glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+		if (msaa > max_samples) {
+			WARN_PRINT("MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos(max_samples));
+			msaa = max_samples;
+		}
+
+		//regular fbo
+		glGenFramebuffers(1, &rt->multisample_fbo);
+		glBindFramebuffer(GL_FRAMEBUFFER, rt->multisample_fbo);
+
+		glGenRenderbuffers(1, &rt->multisample_depth);
+		glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth);
+		glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config->depth_buffer_internalformat, rt->width, rt->height);
+
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth);
+
+		glGenRenderbuffers(1, &rt->multisample_color);
+		glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_color);
+		glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height);
+
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->multisample_color);
+
+		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+		if (status != GL_FRAMEBUFFER_COMPLETE) {
+			// Delete allocated resources and default to no MSAA
+			WARN_PRINT_ONCE("Cannot allocate back framebuffer for MSAA");
+			printf("err status: %x\n", status);
+			rt->multisample_active = false;
+
+			glDeleteFramebuffers(1, &rt->multisample_fbo);
+			rt->multisample_fbo = 0;
+
+			glDeleteRenderbuffers(1, &rt->multisample_depth);
+			rt->multisample_depth = 0;
+
+			glDeleteRenderbuffers(1, &rt->multisample_color);
+			rt->multisample_color = 0;
+		}
+
+		glBindRenderbuffer(GL_RENDERBUFFER, 0);
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+	} else
+#endif // JAVASCRIPT_ENABLED
+	{
+		rt->multisample_active = false;
+	}
+
+	glClearColor(0, 0, 0, 0);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	// copy texscreen buffers
+	//	if (!(rt->flags[TextureStorage::RENDER_TARGET_NO_SAMPLING])) {
+	if (true) {
+		glGenTextures(1, &rt->copy_screen_effect.color);
+		glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color);
+
+		if (rt->flags[TextureStorage::RENDER_TARGET_TRANSPARENT]) {
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+		} else {
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rt->width, rt->height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+		}
+
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+		glGenFramebuffers(1, &rt->copy_screen_effect.fbo);
+		glBindFramebuffer(GL_FRAMEBUFFER, rt->copy_screen_effect.fbo);
+		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0);
+
+		glClearColor(0, 0, 0, 0);
+		glClear(GL_COLOR_BUFFER_BIT);
+
+		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+		if (status != GL_FRAMEBUFFER_COMPLETE) {
+			_render_target_clear(rt);
+			ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+		}
+	}
+
+	// Allocate mipmap chains for post_process effects
+	//	if (!rt->flags[RendererStorage::RENDER_TARGET_NO_3D] && rt->width >= 2 && rt->height >= 2) {
+	if (rt->width >= 2 && rt->height >= 2) {
+		for (int i = 0; i < 2; i++) {
+			ERR_FAIL_COND(rt->mip_maps[i].sizes.size());
+			int w = rt->width;
+			int h = rt->height;
+
+			if (i > 0) {
+				w >>= 1;
+				h >>= 1;
+			}
+
+			int level = 0;
+			int fb_w = w;
+			int fb_h = h;
+
+			while (true) {
+				RenderTarget::MipMaps::Size mm;
+				mm.width = w;
+				mm.height = h;
+				rt->mip_maps[i].sizes.push_back(mm);
+
+				w >>= 1;
+				h >>= 1;
+
+				if (w < 2 || h < 2) {
+					break;
+				}
+
+				level++;
+			}
+
+			GLsizei width = fb_w;
+			GLsizei height = fb_h;
+
+			if (config->render_to_mipmap_supported) {
+				glGenTextures(1, &rt->mip_maps[i].color);
+				glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color);
+
+				for (int l = 0; l < level + 1; l++) {
+					glTexImage2D(GL_TEXTURE_2D, l, color_internal_format, width, height, 0, color_format, color_type, nullptr);
+					width = MAX(1, (width / 2));
+					height = MAX(1, (height / 2));
+				}
+#ifdef GLES_OVER_GL
+				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
+#endif
+			} else {
+				// Can't render to specific levels of a mipmap in ES 2.0 or Webgl so create a texture for each level
+				for (int l = 0; l < level + 1; l++) {
+					glGenTextures(1, &rt->mip_maps[i].sizes.write[l].color);
+					glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[l].color);
+					glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, width, height, 0, color_format, color_type, nullptr);
+					width = MAX(1, (width / 2));
+					height = MAX(1, (height / 2));
+					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+				}
+			}
+
+			glDisable(GL_SCISSOR_TEST);
+			glColorMask(1, 1, 1, 1);
+			glDepthMask(GL_TRUE);
+
+			for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
+				RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j];
+
+				glGenFramebuffers(1, &mm.fbo);
+				glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo);
+
+				if (config->render_to_mipmap_supported) {
+					glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j);
+				} else {
+					glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color);
+					glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color, 0);
+				}
+
+				bool used_depth = false;
+				if (j == 0 && i == 0) { //use always
+					if (config->support_depth_texture) {
+						glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+					} else {
+						glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+					}
+					used_depth = true;
+				}
+
+				GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+				if (status != GL_FRAMEBUFFER_COMPLETE) {
+					WARN_PRINT_ONCE("Cannot allocate mipmaps for 3D post processing effects");
+					glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+					return;
+				}
+
+				glClearColor(1.0, 0.0, 1.0, 0.0);
+				glClear(GL_COLOR_BUFFER_BIT);
+				if (used_depth) {
+					glClearDepth(1.0);
+					glClear(GL_DEPTH_BUFFER_BIT);
+				}
+			}
+
+			rt->mip_maps[i].levels = level;
+
+			if (config->render_to_mipmap_supported) {
+				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+			}
+		}
+		rt->mip_maps_allocated = true;
+	}
+
+	glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+}
+
+void TextureStorage::_render_target_clear(RenderTarget *rt) {
+	Config *config = Config::get_singleton();
+
+	// there is nothing to clear when DIRECT_TO_SCREEN is used
+	if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
+		return;
+	}
+
+	if (rt->fbo) {
+		glDeleteFramebuffers(1, &rt->fbo);
+		glDeleteTextures(1, &rt->color);
+		rt->fbo = 0;
+	}
+
+	if (rt->external.fbo != 0) {
+		// free this
+		glDeleteFramebuffers(1, &rt->external.fbo);
+
+		// clean up our texture
+		Texture *t = get_texture(rt->external.texture);
+		t->alloc_height = 0;
+		t->alloc_width = 0;
+		t->width = 0;
+		t->height = 0;
+		t->active = false;
+		texture_free(rt->external.texture);
+		memdelete(t);
+
+		rt->external.fbo = 0;
+	}
+
+	if (rt->depth) {
+		if (config->support_depth_texture) {
+			glDeleteTextures(1, &rt->depth);
+		} else {
+			glDeleteRenderbuffers(1, &rt->depth);
+		}
+
+		rt->depth = 0;
+	}
+
+	Texture *tex = get_texture(rt->texture);
+	tex->alloc_height = 0;
+	tex->alloc_width = 0;
+	tex->width = 0;
+	tex->height = 0;
+	tex->active = false;
+
+	if (rt->copy_screen_effect.color) {
+		glDeleteFramebuffers(1, &rt->copy_screen_effect.fbo);
+		rt->copy_screen_effect.fbo = 0;
+
+		glDeleteTextures(1, &rt->copy_screen_effect.color);
+		rt->copy_screen_effect.color = 0;
+	}
+
+	for (int i = 0; i < 2; i++) {
+		if (rt->mip_maps[i].sizes.size()) {
+			for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
+				glDeleteFramebuffers(1, &rt->mip_maps[i].sizes[j].fbo);
+				glDeleteTextures(1, &rt->mip_maps[i].sizes[j].color);
+			}
+
+			glDeleteTextures(1, &rt->mip_maps[i].color);
+			rt->mip_maps[i].sizes.clear();
+			rt->mip_maps[i].levels = 0;
+			rt->mip_maps[i].color = 0;
+		}
+	}
+
+	if (rt->multisample_active) {
+		glDeleteFramebuffers(1, &rt->multisample_fbo);
+		rt->multisample_fbo = 0;
+
+		glDeleteRenderbuffers(1, &rt->multisample_depth);
+		rt->multisample_depth = 0;
+
+		glDeleteRenderbuffers(1, &rt->multisample_color);
+
+		rt->multisample_color = 0;
+	}
+}
+
+RID TextureStorage::render_target_create() {
+	RenderTarget *rt = memnew(RenderTarget);
+	Texture *t = memnew(Texture);
+
+	t->type = RenderingDevice::TEXTURE_TYPE_2D;
+	t->flags = 0;
+	t->width = 0;
+	t->height = 0;
+	t->alloc_height = 0;
+	t->alloc_width = 0;
+	t->format = Image::FORMAT_R8;
+	t->target = GL_TEXTURE_2D;
+	t->gl_format_cache = 0;
+	t->gl_internal_format_cache = 0;
+	t->gl_type_cache = 0;
+	t->data_size = 0;
+	t->total_data_size = 0;
+	t->ignore_mipmaps = false;
+	t->compressed = false;
+	t->mipmaps = 1;
+	t->active = true;
+	t->tex_id = 0;
+	t->render_target = rt;
+
+	rt->texture = make_rid(t);
+	return render_target_owner.make_rid(rt);
+}
+
+void TextureStorage::render_target_free(RID p_rid) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_rid);
+	_render_target_clear(rt);
+
+	Texture *t = get_texture(rt->texture);
+	if (t) {
+		texture_free(rt->texture);
+		memdelete(t);
+	}
+	render_target_owner.free(p_rid);
+	memdelete(rt);
+}
+
+void TextureStorage::render_target_set_position(RID p_render_target, int p_x, int p_y) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	rt->x = p_x;
+	rt->y = p_y;
+}
+
+void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	if (p_width == rt->width && p_height == rt->height) {
+		return;
+	}
+
+	_render_target_clear(rt);
+
+	rt->width = p_width;
+	rt->height = p_height;
+
+	// print_line("render_target_set_size " + itos(p_render_target.get_id()) + ", w " + itos(p_width) + " h " + itos(p_height));
+
+	rt->allocate_is_dirty = true;
+	//_render_target_allocate(rt);
+}
+
+// TODO: convert to Size2i internally
+Size2i TextureStorage::render_target_get_size(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, Size2());
+
+	return Size2i(rt->width, rt->height);
+}
+
+RID TextureStorage::render_target_get_texture(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+
+	if (rt->external.fbo == 0) {
+		return rt->texture;
+	} else {
+		return rt->external.texture;
+	}
+}
+
+void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	Config *config = Config::get_singleton();
+
+	if (p_texture_id == 0) {
+		if (rt->external.fbo != 0) {
+			// free this
+			glDeleteFramebuffers(1, &rt->external.fbo);
+
+			// and this
+			if (rt->external.depth != 0) {
+				glDeleteRenderbuffers(1, &rt->external.depth);
+			}
+
+			// clean up our texture
+			Texture *t = get_texture(rt->external.texture);
+			t->alloc_height = 0;
+			t->alloc_width = 0;
+			t->width = 0;
+			t->height = 0;
+			t->active = false;
+			texture_free(rt->external.texture);
+			memdelete(t);
+
+			rt->external.fbo = 0;
+			rt->external.color = 0;
+			rt->external.depth = 0;
+		}
+	} else {
+		Texture *t;
+
+		if (rt->external.fbo == 0) {
+			// create our fbo
+			glGenFramebuffers(1, &rt->external.fbo);
+			glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
+
+			// allocate a texture
+			t = memnew(Texture);
+
+			t->type = RenderingDevice::TEXTURE_TYPE_2D;
+			t->flags = 0;
+			t->width = 0;
+			t->height = 0;
+			t->alloc_height = 0;
+			t->alloc_width = 0;
+			t->format = Image::FORMAT_RGBA8;
+			t->target = GL_TEXTURE_2D;
+			t->gl_format_cache = 0;
+			t->gl_internal_format_cache = 0;
+			t->gl_type_cache = 0;
+			t->data_size = 0;
+			t->compressed = false;
+			t->srgb = false;
+			t->total_data_size = 0;
+			t->ignore_mipmaps = false;
+			t->mipmaps = 1;
+			t->active = true;
+			t->tex_id = 0;
+			t->render_target = rt;
+
+			rt->external.texture = make_rid(t);
+
+		} else {
+			// bind our frame buffer
+			glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
+
+			// find our texture
+			t = get_texture(rt->external.texture);
+		}
+
+		// set our texture
+		t->tex_id = p_texture_id;
+		rt->external.color = p_texture_id;
+
+		// size shouldn't be different
+		t->width = rt->width;
+		t->height = rt->height;
+		t->alloc_height = rt->width;
+		t->alloc_width = rt->height;
+
+		// Switch our texture on our frame buffer
+		{
+			// set our texture as the destination for our framebuffer
+			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
+
+			// seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :)
+			if (config->support_depth_texture) {
+				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+			} else {
+				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+			}
+		}
+
+		// check status and unbind
+		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+		glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+
+		if (status != GL_FRAMEBUFFER_COMPLETE) {
+			printf("framebuffer fail, status: %x\n", status);
+		}
+
+		ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+	}
+}
+
+void TextureStorage::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	// When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as
+	// those functions change how they operate depending on the value of DIRECT_TO_SCREEN
+	if (p_flag == RENDER_TARGET_DIRECT_TO_SCREEN && p_value != rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
+		_render_target_clear(rt);
+		rt->flags[p_flag] = p_value;
+		_render_target_allocate(rt);
+	}
+
+	rt->flags[p_flag] = p_value;
+
+	switch (p_flag) {
+		case RENDER_TARGET_TRANSPARENT:
+			/*
+		case RENDER_TARGET_HDR:
+		case RENDER_TARGET_NO_3D:
+		case RENDER_TARGET_NO_SAMPLING:
+		case RENDER_TARGET_NO_3D_EFFECTS: */
+			{
+				//must reset for these formats
+				_render_target_clear(rt);
+				_render_target_allocate(rt);
+			}
+			break;
+		default: {
+		}
+	}
+}
+
+bool TextureStorage::render_target_was_used(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, false);
+
+	return rt->used_in_frame;
+}
+
+void TextureStorage::render_target_clear_used(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	rt->used_in_frame = false;
+}
+
+void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	if (rt->msaa == p_msaa) {
+		return;
+	}
+
+	_render_target_clear(rt);
+	rt->msaa = p_msaa;
+	_render_target_allocate(rt);
+}
+
+void TextureStorage::render_target_set_use_fxaa(RID p_render_target, bool p_fxaa) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	rt->use_fxaa = p_fxaa;
+}
+
+void TextureStorage::render_target_set_use_debanding(RID p_render_target, bool p_debanding) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	if (p_debanding) {
+		WARN_PRINT_ONCE("Debanding is not supported in the OpenGL backend. Switch to the Vulkan backend and make sure HDR is enabled.");
+	}
+
+	rt->use_debanding = p_debanding;
+}
+
+void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	rt->clear_requested = true;
+	rt->clear_color = p_clear_color;
+
+	//	ERR_FAIL_COND(!frame.current_rt);
+	//	frame.clear_request = true;
+	//	frame.clear_request_color = p_color;
+}
+
+bool TextureStorage::render_target_is_clear_requested(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, false);
+	return rt->clear_requested;
+}
+Color TextureStorage::render_target_get_clear_request_color(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, Color());
+	return rt->clear_color;
+}
+
+void TextureStorage::render_target_disable_clear_request(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	rt->clear_requested = false;
+}
+
+void TextureStorage::render_target_do_clear_request(RID p_render_target) {
+}
+
+void TextureStorage::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
+}
+
+Rect2i TextureStorage::render_target_get_sdf_rect(RID p_render_target) const {
+	return Rect2i();
+}
+
+void TextureStorage::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
+}
+
 #endif // GLES3_ENABLED

+ 226 - 2
drivers/gles3/storage/texture_storage.h

@@ -33,13 +33,20 @@
 
 #ifdef GLES3_ENABLED
 
-#include "canvas_texture_storage.h"
 #include "config.h"
 #include "core/os/os.h"
 #include "core/templates/rid_owner.h"
-#include "render_target_storage.h"
+#include "servers/rendering/renderer_compositor.h"
 #include "servers/rendering/storage/texture_storage.h"
 
+// This must come first to avoid windows.h mess
+#include "platform_config.h"
+#ifndef OPENGL_INCLUDE_H
+#include <GLES3/gl3.h>
+#else
+#include OPENGL_INCLUDE_H
+#endif
+
 namespace GLES3 {
 
 #define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
@@ -90,6 +97,24 @@ enum OpenGLTextureFlags {
 	TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER
 };
 
+struct CanvasTexture {
+	RID diffuse;
+	RID normal_map;
+	RID specular;
+	Color specular_color = Color(1, 1, 1, 1);
+	float shininess = 1.0;
+
+	RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
+	RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
+
+	Size2i size_cache = Size2i(1, 1);
+	bool use_normal_cache = false;
+	bool use_specular_cache = false;
+	bool cleared_cache = true;
+};
+
+struct RenderTarget;
+
 struct Texture {
 	RID self;
 
@@ -296,6 +321,81 @@ private:
 	RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
 };
 
+struct RenderTarget {
+	RID self;
+	GLuint fbo = 0;
+	GLuint color = 0;
+	GLuint depth = 0;
+
+	GLuint multisample_fbo = 0;
+	GLuint multisample_color = 0;
+	GLuint multisample_depth = 0;
+	bool multisample_active = false;
+
+	struct Effect {
+		GLuint fbo = 0;
+		int width = 0;
+		int height = 0;
+
+		GLuint color = 0;
+	};
+
+	Effect copy_screen_effect;
+
+	struct MipMaps {
+		struct Size {
+			GLuint fbo = 0;
+			GLuint color = 0;
+			int width = 0;
+			int height = 0;
+		};
+
+		Vector<Size> sizes;
+		GLuint color = 0;
+		int levels = 0;
+	};
+
+	MipMaps mip_maps[2];
+
+	struct External {
+		GLuint fbo = 0;
+		GLuint color = 0;
+		GLuint depth = 0;
+		RID texture;
+	} external;
+
+	int x = 0;
+	int y = 0;
+	int width = 0;
+	int height = 0;
+
+	bool flags[RendererTextureStorage::RENDER_TARGET_FLAG_MAX] = {};
+
+	// instead of allocating sized render targets immediately,
+	// defer this for faster startup
+	bool allocate_is_dirty = false;
+	bool used_in_frame = false;
+	RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
+
+	bool use_fxaa = false;
+	bool use_debanding = false;
+
+	RID texture;
+
+	bool used_dof_blur_near = false;
+	bool mip_maps_allocated = false;
+
+	Color clear_color = Color(1, 1, 1, 1);
+	bool clear_requested = false;
+
+	RenderTarget() {
+		for (int i = 0; i < RendererTextureStorage::RENDER_TARGET_FLAG_MAX; ++i) {
+			flags[i] = false;
+		}
+		external.fbo = 0;
+	}
+};
+
 class TextureStorage : public RendererTextureStorage {
 private:
 	static TextureStorage *singleton;
@@ -303,6 +403,12 @@ private:
 	Thread::ID _main_thread_id = 0;
 	bool _is_main_thread();
 
+	/* Canvas Texture API */
+
+	RID_Owner<CanvasTexture, true> canvas_texture_owner;
+
+	/* Texture API */
+
 	mutable RID_PtrOwner<Texture> texture_owner;
 
 	Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const;
@@ -310,12 +416,50 @@ private:
 
 	void texture_set_proxy(RID p_texture, RID p_proxy);
 
+	/* Render Target API */
+
+	mutable RID_PtrOwner<RenderTarget> render_target_owner;
+
+	// make access easier to these
+	struct Dimensions {
+		// render target
+		int rt_width;
+		int rt_height;
+
+		// window
+		int win_width;
+		int win_height;
+		Dimensions() {
+			rt_width = 0;
+			rt_height = 0;
+			win_width = 0;
+			win_height = 0;
+		}
+	} _dims;
+
 public:
 	static TextureStorage *get_singleton();
 
 	TextureStorage();
 	virtual ~TextureStorage();
 
+	/* Canvas Texture API */
+
+	CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
+	bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
+
+	virtual RID canvas_texture_allocate() override;
+	virtual void canvas_texture_initialize(RID p_rid) override;
+	virtual void canvas_texture_free(RID p_rid) override;
+
+	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
+	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
+
+	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
+	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
+
+	/* Texture API */
+
 	Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
 	bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
 	RID make_rid(Texture *p_texture) { return texture_owner.make_rid(p_texture); };
@@ -380,6 +524,86 @@ public:
 	void texture_set_shrink_all_x2_on_set_data(bool p_enable);
 	RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const;
 	void textures_keep_original(bool p_enable);
+
+	/* DECAL API */
+
+	virtual RID decal_allocate() override;
+	virtual void decal_initialize(RID p_rid) override;
+	virtual void decal_free(RID p_rid) override{};
+
+	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
+	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
+	virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
+	virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
+	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
+	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
+	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
+	virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
+	virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
+
+	virtual AABB decal_get_aabb(RID p_decal) const override;
+
+	virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+
+	/* RENDER TARGET API */
+
+	static GLuint system_fbo;
+
+	struct Frame {
+		GLES3::RenderTarget *current_rt;
+
+		// these 2 may have been superseded by the equivalents in the render target.
+		// these may be able to be removed.
+		bool clear_request;
+		Color clear_request_color;
+
+		float time;
+		float delta;
+		uint64_t count;
+
+		Frame() {
+			//			current_rt = nullptr;
+			//			clear_request = false;
+		}
+	} frame;
+
+	RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); };
+	bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); };
+
+	void _render_target_clear(RenderTarget *rt);
+	void _render_target_allocate(RenderTarget *rt);
+	void _set_current_render_target(RID p_render_target);
+
+	virtual RID render_target_create() override;
+	virtual void render_target_free(RID p_rid) override;
+	virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
+	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
+	Size2i render_target_get_size(RID p_render_target);
+	virtual RID render_target_get_texture(RID p_render_target) override;
+	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
+
+	virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override;
+	virtual bool render_target_was_used(RID p_render_target) override;
+	void render_target_clear_used(RID p_render_target);
+	void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa);
+	void render_target_set_use_fxaa(RID p_render_target, bool p_fxaa);
+	void render_target_set_use_debanding(RID p_render_target, bool p_debanding);
+
+	// new
+	void render_target_set_as_unused(RID p_render_target) override {
+		render_target_clear_used(p_render_target);
+	}
+
+	void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
+	bool render_target_is_clear_requested(RID p_render_target) override;
+	Color render_target_get_clear_request_color(RID p_render_target) override;
+	void render_target_disable_clear_request(RID p_render_target) override;
+	void render_target_do_clear_request(RID p_render_target) override;
+
+	void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
+	Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
+	void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
 };
 
 } // namespace GLES3

+ 2 - 1
modules/openxr/extensions/openxr_vulkan_extension.cpp

@@ -34,6 +34,7 @@
 #include "../openxr_api.h"
 #include "../openxr_util.h"
 #include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_server_globals.h"
 #include "servers/rendering_server.h"
 
@@ -439,7 +440,7 @@ bool OpenXRVulkanExtension::copy_render_target_to_image(RID p_from_render_target
 	ERR_FAIL_COND_V(p_from_render_target.is_null(), false);
 	ERR_FAIL_NULL_V(RendererStorageRD::base_singleton, false);
 
-	RID source_image = RendererStorageRD::base_singleton->render_target_get_rd_texture(p_from_render_target);
+	RID source_image = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(p_from_render_target);
 	ERR_FAIL_COND_V(source_image.is_null(), false);
 
 	RID depth_image; // TODO implement

+ 6 - 6
servers/rendering/dummy/rasterizer_dummy.h

@@ -37,10 +37,10 @@
 #include "servers/rendering/dummy/rasterizer_canvas_dummy.h"
 #include "servers/rendering/dummy/rasterizer_scene_dummy.h"
 #include "servers/rendering/dummy/rasterizer_storage_dummy.h"
-#include "servers/rendering/dummy/storage/canvas_texture_storage.h"
-#include "servers/rendering/dummy/storage/decal_atlas_storage.h"
+#include "servers/rendering/dummy/storage/light_storage.h"
 #include "servers/rendering/dummy/storage/material_storage.h"
 #include "servers/rendering/dummy/storage/mesh_storage.h"
+#include "servers/rendering/dummy/storage/particles_storage.h"
 #include "servers/rendering/dummy/storage/texture_storage.h"
 #include "servers/rendering/renderer_compositor.h"
 #include "servers/rendering_server.h"
@@ -52,20 +52,20 @@ private:
 
 protected:
 	RasterizerCanvasDummy canvas;
-	RendererDummy::CanvasTextureStorage canvas_texture_storage;
+	RendererDummy::LightStorage light_storage;
 	RendererDummy::MaterialStorage material_storage;
 	RendererDummy::MeshStorage mesh_storage;
+	RendererDummy::ParticlesStorage particles_storage;
 	RendererDummy::TextureStorage texture_storage;
-	RendererDummy::DecalAtlasStorage decal_atlas_storage;
 	RasterizerStorageDummy storage;
 	RasterizerSceneDummy scene;
 
 public:
-	RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; };
+	RendererLightStorage *get_light_storage() override { return &light_storage; };
 	RendererMaterialStorage *get_material_storage() override { return &material_storage; };
 	RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; };
+	RendererParticlesStorage *get_particles_storage() override { return &particles_storage; };
 	RendererTextureStorage *get_texture_storage() override { return &texture_storage; };
-	RendererDecalAtlasStorage *get_decal_atlas_storage() override { return &decal_atlas_storage; };
 	RendererStorage *get_storage() override { return &storage; }
 	RendererCanvasRender *get_canvas() override { return &canvas; }
 	RendererSceneRender *get_scene() override { return &scene; }

+ 1 - 185
servers/rendering/dummy/rasterizer_storage_dummy.h

@@ -36,76 +36,6 @@
 
 class RasterizerStorageDummy : public RendererStorage {
 public:
-	/* Light API */
-
-	RID directional_light_allocate() override { return RID(); }
-	void directional_light_initialize(RID p_rid) override {}
-	RID omni_light_allocate() override { return RID(); }
-	void omni_light_initialize(RID p_rid) override {}
-	RID spot_light_allocate() override { return RID(); }
-	void spot_light_initialize(RID p_rid) override {}
-	RID reflection_probe_allocate() override { return RID(); }
-	void reflection_probe_initialize(RID p_rid) override {}
-
-	void light_set_color(RID p_light, const Color &p_color) override {}
-	void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
-	void light_set_shadow(RID p_light, bool p_enabled) override {}
-	void light_set_projector(RID p_light, RID p_texture) override {}
-	void light_set_negative(RID p_light, bool p_enable) override {}
-	void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
-	void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}
-	void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
-	void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
-	void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
-
-	void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {}
-
-	void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {}
-	void light_directional_set_blend_splits(RID p_light, bool p_enable) override {}
-	bool light_directional_get_blend_splits(RID p_light) const override { return false; }
-	void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override {}
-	RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; }
-
-	RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
-	RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
-
-	bool light_has_shadow(RID p_light) const override { return false; }
-	bool light_has_projector(RID p_light) const override { return false; }
-
-	RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; }
-	AABB light_get_aabb(RID p_light) const override { return AABB(); }
-	float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; }
-	Color light_get_color(RID p_light) override { return Color(); }
-	RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; }
-	uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
-	uint64_t light_get_version(RID p_light) const override { return 0; }
-
-	/* PROBE API */
-
-	void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {}
-	void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {}
-	void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {}
-	void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {}
-	void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {}
-	void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {}
-	void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {}
-	void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {}
-	void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {}
-	void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {}
-	void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {}
-	void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {}
-	void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {}
-	void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
-	float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
-
-	AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
-	RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
-	uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; }
-	Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); }
-	Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); }
-	float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; }
-	bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
-
 	void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
 
 	/* VOXEL GI API */
@@ -149,105 +79,10 @@ public:
 
 	uint32_t voxel_gi_get_version(RID p_voxel_gi) override { return 0; }
 
-	/* LIGHTMAP CAPTURE */
-	RID lightmap_allocate() override { return RID(); }
-	void lightmap_initialize(RID p_rid) override {}
-	void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {}
-	void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
-	void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
-	void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {}
-	PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
-	PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
-	PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
-	PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); }
-	AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); }
-	void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {}
-	bool lightmap_is_interior(RID p_lightmap) const override { return false; }
-	void lightmap_set_probe_capture_update_speed(float p_speed) override {}
-	float lightmap_get_probe_capture_update_speed() const override { return 0; }
-
 	/* OCCLUDER */
 
 	void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
 
-	/* PARTICLES */
-
-	RID particles_allocate() override { return RID(); }
-	void particles_initialize(RID p_rid) override {}
-	void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {}
-	void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
-	void particles_set_emitting(RID p_particles, bool p_emitting) override {}
-	void particles_set_amount(RID p_particles, int p_amount) override {}
-	void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
-	void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
-	void particles_set_pre_process_time(RID p_particles, double p_time) override {}
-	void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {}
-	void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {}
-	void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
-	void particles_set_speed_scale(RID p_particles, double p_scale) override {}
-	void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
-	void particles_set_process_material(RID p_particles, RID p_material) override {}
-	RID particles_get_process_material(RID p_particles) const override { return RID(); }
-	void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
-	void particles_set_interpolate(RID p_particles, bool p_enable) override {}
-	void particles_set_fractional_delta(RID p_particles, bool p_enable) override {}
-	void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {}
-	void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {}
-	void particles_set_collision_base_size(RID p_particles, real_t p_size) override {}
-
-	void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {}
-
-	void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {}
-	void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {}
-
-	void particles_restart(RID p_particles) override {}
-
-	void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {}
-
-	void particles_set_draw_passes(RID p_particles, int p_count) override {}
-	void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {}
-
-	void particles_request_process(RID p_particles) override {}
-	AABB particles_get_current_aabb(RID p_particles) override { return AABB(); }
-	AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
-
-	void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {}
-
-	bool particles_get_emitting(RID p_particles) override { return false; }
-	int particles_get_draw_passes(RID p_particles) const override { return 0; }
-	RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); }
-
-	void particles_add_collision(RID p_particles, RID p_instance) override {}
-	void particles_remove_collision(RID p_particles, RID p_instance) override {}
-
-	void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {}
-
-	void update_particles() override {}
-
-	/* PARTICLES COLLISION */
-
-	RID particles_collision_allocate() override { return RID(); }
-	void particles_collision_initialize(RID p_rid) override {}
-	void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
-	void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
-	void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {}
-	void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {}
-	void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {}
-	void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {}
-	void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {}
-	void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {}
-	void particles_collision_height_field_update(RID p_particles_collision) override {}
-	void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
-	AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
-	bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
-	RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
-
-	RID particles_collision_instance_create(RID p_collision) override { return RID(); }
-	void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
-	void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
-
-	bool particles_is_inactive(RID p_particles) const override { return false; }
-
 	/* FOG VOLUMES */
 
 	RID fog_volume_allocate() override { return RID(); }
@@ -268,26 +103,7 @@ public:
 	virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
 	virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
 
-	/* RENDER TARGET */
-
-	RID render_target_create() override { return RID(); }
-	void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
-	void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
-	RID render_target_get_texture(RID p_render_target) override { return RID(); }
-	void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
-	void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
-	bool render_target_was_used(RID p_render_target) override { return false; }
-	void render_target_set_as_unused(RID p_render_target) override {}
-
-	void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
-	bool render_target_is_clear_requested(RID p_render_target) override { return false; }
-	Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); }
-	void render_target_disable_clear_request(RID p_render_target) override {}
-	void render_target_do_clear_request(RID p_render_target) override {}
-
-	void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
-	Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
-	void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
+	/* STORAGE */
 
 	RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
 	bool free(RID p_rid) override {

+ 0 - 53
servers/rendering/dummy/storage/canvas_texture_storage.h

@@ -1,53 +0,0 @@
-/*************************************************************************/
-/*  canvas_texture_storage.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 CANVAS_TEXTURE_STORAGE_DUMMY_H
-#define CANVAS_TEXTURE_STORAGE_DUMMY_H
-
-#include "servers/rendering/storage/canvas_texture_storage.h"
-
-namespace RendererDummy {
-
-class CanvasTextureStorage : public RendererCanvasTextureStorage {
-public:
-	virtual RID canvas_texture_allocate() override { return RID(); };
-	virtual void canvas_texture_initialize(RID p_rid) override{};
-	virtual void canvas_texture_free(RID p_rid) override{};
-
-	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override{};
-	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override{};
-
-	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override{};
-	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override{};
-};
-
-} // namespace RendererDummy
-
-#endif // !CANVAS_TEXTURE_STORAGE_DUMMY_H

+ 0 - 62
servers/rendering/dummy/storage/decal_atlas_storage.h

@@ -1,62 +0,0 @@
-/*************************************************************************/
-/*  decal_atlas_storage.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 DECAL_ATLAS_STORAGE_DUMMY_H
-#define DECAL_ATLAS_STORAGE_DUMMY_H
-
-#include "servers/rendering/storage/decal_atlas_storage.h"
-
-namespace RendererDummy {
-
-class DecalAtlasStorage : public RendererDecalAtlasStorage {
-public:
-	virtual RID decal_allocate() override { return RID(); }
-	virtual void decal_initialize(RID p_rid) override {}
-	virtual void decal_free(RID p_rid) override{};
-
-	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
-	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
-	virtual void decal_set_emission_energy(RID p_decal, float p_energy) override {}
-	virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override {}
-	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override {}
-	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {}
-	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {}
-	virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override {}
-	virtual void decal_set_normal_fade(RID p_decal, float p_fade) override {}
-
-	virtual AABB decal_get_aabb(RID p_decal) const override { return AABB(); }
-
-	virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-};
-
-} // namespace RendererDummy
-
-#endif // !DECAL_ATLAS_STORAGE_DUMMY_H

+ 135 - 0
servers/rendering/dummy/storage/light_storage.h

@@ -0,0 +1,135 @@
+/*************************************************************************/
+/*  light_storage.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 LIGHT_STORAGE_DUMMY_H
+#define LIGHT_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/light_storage.h"
+
+namespace RendererDummy {
+
+class LightStorage : public RendererLightStorage {
+public:
+	/* Light API */
+
+	virtual RID directional_light_allocate() override { return RID(); }
+	virtual void directional_light_initialize(RID p_rid) override {}
+	virtual RID omni_light_allocate() override { return RID(); }
+	virtual void omni_light_initialize(RID p_rid) override {}
+	virtual RID spot_light_allocate() override { return RID(); }
+	virtual void spot_light_initialize(RID p_rid) override {}
+
+	virtual void light_free(RID p_rid) override {}
+
+	virtual void light_set_color(RID p_light, const Color &p_color) override {}
+	virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
+	virtual void light_set_shadow(RID p_light, bool p_enabled) override {}
+	virtual void light_set_projector(RID p_light, RID p_texture) override {}
+	virtual void light_set_negative(RID p_light, bool p_enable) override {}
+	virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
+	virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}
+	virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
+	virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
+	virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
+
+	virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {}
+
+	virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {}
+	virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) override {}
+	virtual bool light_directional_get_blend_splits(RID p_light) const override { return false; }
+	virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override {}
+	virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; }
+
+	virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
+	virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
+
+	virtual bool light_has_shadow(RID p_light) const override { return false; }
+	virtual bool light_has_projector(RID p_light) const override { return false; }
+
+	virtual RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; }
+	virtual AABB light_get_aabb(RID p_light) const override { return AABB(); }
+	virtual float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; }
+	virtual Color light_get_color(RID p_light) override { return Color(); }
+	virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; }
+	virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
+	virtual uint64_t light_get_version(RID p_light) const override { return 0; }
+
+	/* PROBE API */
+	virtual RID reflection_probe_allocate() override { return RID(); }
+	virtual void reflection_probe_initialize(RID p_rid) override {}
+	virtual void reflection_probe_free(RID p_rid) override {}
+
+	virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {}
+	virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {}
+	virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {}
+	virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {}
+	virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {}
+	virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {}
+	virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {}
+	virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {}
+	virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {}
+	virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {}
+	virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {}
+	virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {}
+	virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {}
+	virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
+	virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
+
+	virtual AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
+	virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
+	virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; }
+	virtual Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); }
+	virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); }
+	virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; }
+	virtual bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
+
+	/* LIGHTMAP CAPTURE */
+	virtual RID lightmap_allocate() override { return RID(); }
+	virtual void lightmap_initialize(RID p_rid) override {}
+	virtual void lightmap_free(RID p_rid) override {}
+
+	virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {}
+	virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
+	virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
+	virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {}
+	virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
+	virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
+	virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
+	virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); }
+	virtual AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); }
+	virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {}
+	virtual bool lightmap_is_interior(RID p_lightmap) const override { return false; }
+	virtual void lightmap_set_probe_capture_update_speed(float p_speed) override {}
+	virtual float lightmap_get_probe_capture_update_speed() const override { return 0; }
+};
+
+} // namespace RendererDummy
+
+#endif // !LIGHT_STORAGE_DUMMY_H

+ 126 - 0
servers/rendering/dummy/storage/particles_storage.h

@@ -0,0 +1,126 @@
+/*************************************************************************/
+/*  particles_storage.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 PARTICLES_STORAGE_DUMMY_H
+#define PARTICLES_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/particles_storage.h"
+
+namespace RendererDummy {
+
+class ParticlesStorage : public RendererParticlesStorage {
+public:
+	/* PARTICLES */
+
+	virtual RID particles_allocate() override { return RID(); }
+	virtual void particles_initialize(RID p_rid) override {}
+	virtual void particles_free(RID p_rid) override {}
+
+	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {}
+	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
+	virtual void particles_set_emitting(RID p_particles, bool p_emitting) override {}
+	virtual void particles_set_amount(RID p_particles, int p_amount) override {}
+	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
+	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
+	virtual void particles_set_pre_process_time(RID p_particles, double p_time) override {}
+	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {}
+	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {}
+	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
+	virtual void particles_set_speed_scale(RID p_particles, double p_scale) override {}
+	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
+	virtual void particles_set_process_material(RID p_particles, RID p_material) override {}
+	virtual RID particles_get_process_material(RID p_particles) const override { return RID(); }
+	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
+	virtual void particles_set_interpolate(RID p_particles, bool p_enable) override {}
+	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override {}
+	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {}
+	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {}
+	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override {}
+
+	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {}
+
+	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {}
+	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {}
+
+	virtual void particles_restart(RID p_particles) override {}
+
+	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {}
+
+	virtual void particles_set_draw_passes(RID p_particles, int p_count) override {}
+	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {}
+
+	virtual void particles_request_process(RID p_particles) override {}
+	virtual AABB particles_get_current_aabb(RID p_particles) override { return AABB(); }
+	virtual AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
+
+	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {}
+
+	virtual bool particles_get_emitting(RID p_particles) override { return false; }
+	virtual int particles_get_draw_passes(RID p_particles) const override { return 0; }
+	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); }
+
+	virtual void particles_add_collision(RID p_particles, RID p_instance) override {}
+	virtual void particles_remove_collision(RID p_particles, RID p_instance) override {}
+
+	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {}
+
+	virtual void update_particles() override {}
+
+	/* PARTICLES COLLISION */
+
+	virtual RID particles_collision_allocate() override { return RID(); }
+	virtual void particles_collision_initialize(RID p_rid) override {}
+	virtual void particles_collision_free(RID p_rid) override {}
+
+	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
+	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
+	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {}
+	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {}
+	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {}
+	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {}
+	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {}
+	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {}
+	virtual void particles_collision_height_field_update(RID p_particles_collision) override {}
+	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
+	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
+	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
+	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
+
+	virtual RID particles_collision_instance_create(RID p_collision) override { return RID(); }
+	virtual void particles_collision_instance_free(RID p_rid) override {}
+	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
+	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
+
+	virtual bool particles_is_inactive(RID p_particles) const override { return false; }
+};
+
+} // namespace RendererDummy
+
+#endif // !PARTICLES_STORAGE_DUMMY_H

+ 56 - 0
servers/rendering/dummy/storage/texture_storage.h

@@ -52,6 +52,20 @@ public:
 
 	virtual bool can_create_resources_async() const override { return false; }
 
+	/* Canvas Texture API */
+
+	virtual RID canvas_texture_allocate() override { return RID(); };
+	virtual void canvas_texture_initialize(RID p_rid) override{};
+	virtual void canvas_texture_free(RID p_rid) override{};
+
+	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override{};
+	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override{};
+
+	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override{};
+	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override{};
+
+	/* Texture API */
+
 	DummyTexture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
 	bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
 
@@ -109,6 +123,48 @@ public:
 	virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override{};
 
 	virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); };
+
+	/* DECAL API */
+	virtual RID decal_allocate() override { return RID(); }
+	virtual void decal_initialize(RID p_rid) override {}
+	virtual void decal_free(RID p_rid) override{};
+
+	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
+	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
+	virtual void decal_set_emission_energy(RID p_decal, float p_energy) override {}
+	virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override {}
+	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override {}
+	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {}
+	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {}
+	virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override {}
+	virtual void decal_set_normal_fade(RID p_decal, float p_fade) override {}
+
+	virtual AABB decal_get_aabb(RID p_decal) const override { return AABB(); }
+
+	virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+
+	/* RENDER TARGET */
+
+	virtual RID render_target_create() override { return RID(); }
+	virtual void render_target_free(RID p_rid) override {}
+	virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
+	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
+	virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
+	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
+	virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
+	virtual bool render_target_was_used(RID p_render_target) override { return false; }
+	virtual void render_target_set_as_unused(RID p_render_target) override {}
+
+	virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
+	virtual bool render_target_is_clear_requested(RID p_render_target) override { return false; }
+	virtual Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); }
+	virtual void render_target_disable_clear_request(RID p_render_target) override {}
+	virtual void render_target_do_clear_request(RID p_render_target) override {}
+
+	virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
+	virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
+	virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
 };
 
 } // namespace RendererDummy

+ 8 - 8
servers/rendering/renderer_canvas_cull.cpp

@@ -34,7 +34,7 @@
 #include "renderer_viewport.h"
 #include "rendering_server_default.h"
 #include "rendering_server_globals.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
+#include "servers/rendering/storage/texture_storage.h"
 
 static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
 
@@ -1338,7 +1338,7 @@ void RendererCanvasCull::canvas_item_add_particles(RID p_item, RID p_particles,
 	part->texture = p_texture;
 
 	//take the chance and request processing for them, at least once until they become visible again
-	RSG::storage->particles_request_process(p_particles);
+	RSG::particles_storage->particles_request_process(p_particles);
 }
 
 void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture) {
@@ -1851,26 +1851,26 @@ void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) {
 }
 
 RID RendererCanvasCull::canvas_texture_allocate() {
-	return RSG::canvas_texture_storage->canvas_texture_allocate();
+	return RSG::texture_storage->canvas_texture_allocate();
 }
 void RendererCanvasCull::canvas_texture_initialize(RID p_rid) {
-	RSG::canvas_texture_storage->canvas_texture_initialize(p_rid);
+	RSG::texture_storage->canvas_texture_initialize(p_rid);
 }
 
 void RendererCanvasCull::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
-	RSG::canvas_texture_storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture);
+	RSG::texture_storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture);
 }
 
 void RendererCanvasCull::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) {
-	RSG::canvas_texture_storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess);
+	RSG::texture_storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess);
 }
 
 void RendererCanvasCull::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
-	RSG::canvas_texture_storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter);
+	RSG::texture_storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter);
 }
 
 void RendererCanvasCull::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
-	RSG::canvas_texture_storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat);
+	RSG::texture_storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat);
 }
 
 void RendererCanvasCull::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) {

+ 2 - 1
servers/rendering/renderer_canvas_render.h

@@ -32,6 +32,7 @@
 #define RENDERINGSERVERCANVASRENDER_H
 
 #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
 #include "servers/rendering/renderer_storage.h"
 
 class RendererCanvasRender {
@@ -419,7 +420,7 @@ public:
 					case Item::Command::TYPE_PARTICLES: {
 						const Item::CommandParticles *particles_cmd = static_cast<const Item::CommandParticles *>(c);
 						if (particles_cmd->particles.is_valid()) {
-							AABB aabb = RendererStorage::base_singleton->particles_get_aabb(particles_cmd->particles);
+							AABB aabb = RendererRD::ParticlesStorage::get_singleton()->particles_get_aabb(particles_cmd->particles);
 							r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
 						}
 

+ 4 - 4
servers/rendering/renderer_compositor.h

@@ -34,10 +34,10 @@
 #include "servers/rendering/renderer_canvas_render.h"
 #include "servers/rendering/renderer_scene.h"
 #include "servers/rendering/renderer_storage.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
-#include "servers/rendering/storage/decal_atlas_storage.h"
+#include "servers/rendering/storage/light_storage.h"
 #include "servers/rendering/storage/material_storage.h"
 #include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/particles_storage.h"
 #include "servers/rendering/storage/texture_storage.h"
 #include "servers/rendering_server.h"
 
@@ -75,11 +75,11 @@ protected:
 public:
 	static RendererCompositor *create();
 
-	virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0;
+	virtual RendererLightStorage *get_light_storage() = 0;
 	virtual RendererMaterialStorage *get_material_storage() = 0;
 	virtual RendererMeshStorage *get_mesh_storage() = 0;
+	virtual RendererParticlesStorage *get_particles_storage() = 0;
 	virtual RendererTextureStorage *get_texture_storage() = 0;
-	virtual RendererDecalAtlasStorage *get_decal_atlas_storage() = 0;
 	virtual RendererStorage *get_storage() = 0;
 	virtual RendererCanvasRender *get_canvas() = 0;
 	virtual RendererSceneRender *get_scene() = 0;

+ 43 - 36
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp

@@ -30,8 +30,10 @@
 
 #include "render_forward_clustered.h"
 #include "core/config/project_settings.h"
-#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
 #include "servers/rendering/rendering_device.h"
 #include "servers/rendering/rendering_server_default.h"
@@ -839,7 +841,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
 		scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment);
 
 	} else {
-		if (p_render_data->reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+		if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
 			scene_state.ubo.use_ambient_light = false;
 		} else {
 			scene_state.ubo.use_ambient_light = true;
@@ -1230,7 +1232,7 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
 		to_lm = to_lm.inverse().transposed(); //will transform normals
 		RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
 		scene_state.lightmap_ids[i] = p_lightmaps[i];
-		scene_state.lightmap_has_sh[i] = storage->lightmap_uses_spherical_harmonics(lightmap);
+		scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
 
 		scene_state.lightmaps_used++;
 	}
@@ -1338,7 +1340,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
 		color_only_framebuffer = color_framebuffer;
 		depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
 
-		if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+		if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
 			p_render_data->environment = RID(); //no environment on interiors
 			env = nullptr;
 		}
@@ -2025,14 +2027,17 @@ void RenderForwardClustered::_base_uniforms_changed() {
 }
 
 void RenderForwardClustered::_update_render_base_uniform_set() {
-	if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version()) || base_uniform_set_updated) {
+	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+	if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version()) || base_uniform_set_updated) {
 		base_uniform_set_updated = false;
 
 		if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
 			RD::get_singleton()->free(render_base_uniform_set);
 		}
 
-		lightmap_texture_array_version = storage->lightmap_array_get_version();
+		lightmap_texture_array_version = light_storage->lightmap_array_get_version();
 
 		Vector<RD::Uniform> uniforms;
 
@@ -2040,18 +2045,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			Vector<RID> ids;
 			ids.resize(12);
 			RID *ids_ptr = ids.ptrw();
-			ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[3] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[4] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[5] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[6] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[7] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[8] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[0] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[1] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[2] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[3] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[4] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[5] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[6] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[7] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[8] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[9] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[10] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[11] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 
 			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
 
@@ -2073,19 +2078,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RID sampler;
 			switch (decals_get_filter()) {
 				case RS::DECAL_FILTER_NEAREST: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::DECAL_FILTER_LINEAR: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 			}
 
@@ -2100,19 +2105,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RID sampler;
 			switch (light_projectors_get_filter()) {
 				case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
-					sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 			}
 
@@ -2167,7 +2172,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 11;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture();
+			RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
 			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
@@ -2175,7 +2180,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_srgb();
+			RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture_srgb();
 			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
@@ -2209,6 +2214,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 
 RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
 
 	RenderBufferDataForwardClustered *rb = nullptr;
 	if (p_render_data && p_render_data->render_buffers.is_valid()) {
@@ -2298,7 +2304,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
 			if (p_render_data && i < p_render_data->lightmaps->size()) {
 				RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
-				RID texture = storage->lightmap_get_texture(base);
+				RID texture = light_storage->lightmap_get_texture(base);
 				RID rd_texture = texture_storage->texture_get_rd_texture(texture);
 				u.append_id(rd_texture);
 			} else {
@@ -2780,6 +2786,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
 
 void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
 	RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+	RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
 	GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
 
 	if (ginstance->data->dirty_dependencies) {
@@ -2836,10 +2843,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
 		} break;
 #endif
 		case RS::INSTANCE_PARTICLES: {
-			int draw_passes = storage->particles_get_draw_passes(ginstance->data->base);
+			int draw_passes = particles_storage->particles_get_draw_passes(ginstance->data->base);
 
 			for (int j = 0; j < draw_passes; j++) {
-				RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
+				RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
 				if (!mesh.is_valid()) {
 					continue;
 				}
@@ -2855,7 +2862,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
 				}
 			}
 
-			ginstance->instance_count = storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
+			ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
 
 		} break;
 
@@ -2892,10 +2899,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
 		//for particles, stride is the trail size
 		ginstance->base_flags |= (ginstance->trail_steps << INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT);
 
-		if (!storage->particles_is_using_local_coords(ginstance->data->base)) {
+		if (!particles_storage->particles_is_using_local_coords(ginstance->data->base)) {
 			store_transform = false;
 		}
-		ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+		ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
 
 	} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
 		if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {

+ 42 - 36
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

@@ -30,8 +30,10 @@
 
 #include "render_forward_mobile.h"
 #include "core/config/project_settings.h"
-#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_device.h"
 #include "servers/rendering/rendering_server_default.h"
 
@@ -377,7 +379,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
 			if (p_render_data && i < p_render_data->lightmaps->size()) {
 				RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
-				RID texture = storage->lightmap_get_texture(base);
+				RID texture = RendererRD::LightStorage::get_singleton()->lightmap_get_texture(base);
 				RID rd_texture = texture_storage->texture_get_rd_texture(texture);
 				u.append_id(rd_texture);
 			} else {
@@ -465,7 +467,7 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
 		to_lm = to_lm.inverse().transposed(); //will transform normals
 		RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
 		scene_state.lightmap_ids[i] = p_lightmaps[i];
-		scene_state.lightmap_has_sh[i] = storage->lightmap_uses_spherical_harmonics(lightmap);
+		scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
 
 		scene_state.lightmaps_used++;
 	}
@@ -553,7 +555,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 
 		framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
 
-		if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+		if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
 			p_render_data->environment = RID(); //no environment on interiors
 			env = nullptr;
 		}
@@ -1137,14 +1139,17 @@ void RenderForwardMobile::_base_uniforms_changed() {
 }
 
 void RenderForwardMobile::_update_render_base_uniform_set() {
-	if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) {
+	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+	if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version())) {
 		if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
 			RD::get_singleton()->free(render_base_uniform_set);
 		}
 
 		// This is all loaded into set 0
 
-		lightmap_texture_array_version = storage->lightmap_array_get_version();
+		lightmap_texture_array_version = light_storage->lightmap_array_get_version();
 
 		Vector<RD::Uniform> uniforms;
 
@@ -1152,18 +1157,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			Vector<RID> ids;
 			ids.resize(12);
 			RID *ids_ptr = ids.ptrw();
-			ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 
 			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
 
@@ -1185,19 +1190,19 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RID sampler;
 			switch (decals_get_filter()) {
 				case RS::DECAL_FILTER_NEAREST: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::DECAL_FILTER_LINEAR: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 			}
 
@@ -1212,19 +1217,19 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RID sampler;
 			switch (light_projectors_get_filter()) {
 				case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 				case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
-					sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+					sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				} break;
 			}
 
@@ -1279,7 +1284,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 11;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture();
+			RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
 			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
@@ -1287,7 +1292,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_srgb();
+			RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture_srgb();
 			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
@@ -1667,7 +1672,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
 		scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment);
 
 	} else {
-		if (p_render_data->reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+		if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
 			scene_state.ubo.use_ambient_light = false;
 		} else {
 			scene_state.ubo.use_ambient_light = true;
@@ -2449,6 +2454,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
 
 void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
 	RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+	RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
 	GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
 
 	if (ginstance->data->dirty_dependencies) {
@@ -2505,10 +2511,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
 		} break;
 #endif
 		case RS::INSTANCE_PARTICLES: {
-			int draw_passes = storage->particles_get_draw_passes(ginstance->data->base);
+			int draw_passes = particles_storage->particles_get_draw_passes(ginstance->data->base);
 
 			for (int j = 0; j < draw_passes; j++) {
-				RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
+				RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
 				if (!mesh.is_valid()) {
 					continue;
 				}
@@ -2524,7 +2530,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
 				}
 			}
 
-			ginstance->instance_count = storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
+			ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
 
 		} break;
 
@@ -2563,10 +2569,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
 		//for particles, stride is the trail size
 		ginstance->base_flags |= (ginstance->trail_steps << INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT);
 
-		if (!storage->particles_is_using_local_coords(ginstance->data->base)) {
+		if (!particles_storage->particles_is_using_local_coords(ginstance->data->base)) {
 			store_transform = false;
 		}
-		ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+		ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
 
 	} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
 		if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {

+ 67 - 58
servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

@@ -35,9 +35,8 @@
 #include "core/math/math_defs.h"
 #include "core/math/math_funcs.h"
 #include "renderer_compositor_rd.h"
-#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_server_default.h"
 
@@ -364,7 +363,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
 	bool use_normal;
 	bool use_specular;
 
-	bool success = RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
+	bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
 	//something odd happened
 	if (!success) {
 		_bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size);
@@ -401,7 +400,9 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
 
 void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) {
 	//create an empty push constant
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+	RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
 
 	RS::CanvasItemTextureFilter current_filter = default_filter;
 	RS::CanvasItemTextureRepeat current_repeat = default_repeat;
@@ -780,24 +781,24 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
 					}
 				} else if (c->type == Item::Command::TYPE_PARTICLES) {
 					const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
-					ERR_BREAK(storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D);
-					storage->particles_request_process(pt->particles);
+					ERR_BREAK(particles_storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D);
+					particles_storage->particles_request_process(pt->particles);
 
-					if (storage->particles_is_inactive(pt->particles)) {
+					if (particles_storage->particles_is_inactive(pt->particles)) {
 						break;
 					}
 
 					RenderingServerDefault::redraw_request(); // active particles means redraw request
 
 					bool local_coords = true;
-					int dpc = storage->particles_get_draw_passes(pt->particles);
+					int dpc = particles_storage->particles_get_draw_passes(pt->particles);
 					if (dpc == 0) {
 						break; //nothing to draw
 					}
 					uint32_t divisor = 1;
-					instance_count = storage->particles_get_amount(pt->particles, divisor);
+					instance_count = particles_storage->particles_get_amount(pt->particles, divisor);
 
-					RID uniform_set = storage->particles_get_instance_buffer_uniform_set(pt->particles, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
+					RID uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(pt->particles, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
 					RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET);
 
 					push_constant.flags |= divisor;
@@ -806,10 +807,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
 					push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS;
 					push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
 
-					mesh = storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored
+					mesh = particles_storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored
 					texture = pt->texture;
 
-					if (storage->particles_has_collision(pt->particles) && storage->render_target_is_sdf_enabled(p_render_target)) {
+					if (particles_storage->particles_has_collision(pt->particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
 						//pass collision information
 						Transform2D xform;
 						if (local_coords) {
@@ -818,19 +819,19 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
 							xform = p_canvas_transform_inverse;
 						}
 
-						RID sdf_texture = storage->render_target_get_sdf_texture(p_render_target);
+						RID sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target);
 
 						Rect2 to_screen;
 						{
-							Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_render_target);
+							Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_render_target);
 
 							to_screen.size = Vector2(1.0 / sdf_rect.size.width, 1.0 / sdf_rect.size.height);
 							to_screen.position = -sdf_rect.position * to_screen.size;
 						}
 
-						storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
+						particles_storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
 					} else {
-						storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID());
+						particles_storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID());
 					}
 				}
 
@@ -931,6 +932,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
 }
 
 RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, bool p_backbuffer) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	//re create canvas state
 	Vector<RD::Uniform> uniforms;
 
@@ -954,7 +958,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.binding = 3;
-		u.append_id(RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture());
+		u.append_id(RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture());
 		uniforms.push_back(u);
 	}
 
@@ -980,9 +984,9 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		u.binding = 6;
 		RID screen;
 		if (p_backbuffer) {
-			screen = storage->render_target_get_rd_texture(p_to_render_target);
+			screen = texture_storage->render_target_get_rd_texture(p_to_render_target);
 		} else {
-			screen = storage->render_target_get_rd_backbuffer(p_to_render_target);
+			screen = texture_storage->render_target_get_rd_backbuffer(p_to_render_target);
 			if (screen.is_null()) { //unallocated backbuffer
 				screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 			}
@@ -995,7 +999,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.binding = 7;
-		RID sdf = storage->render_target_get_sdf_texture(p_to_render_target);
+		RID sdf = texture_storage->render_target_get_sdf_texture(p_to_render_target);
 		u.append_id(sdf);
 		uniforms.push_back(u);
 	}
@@ -1005,18 +1009,18 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		Vector<RID> ids;
 		ids.resize(12);
 		RID *ids_ptr = ids.ptrw();
-		ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-		ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-		ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-		ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-		ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-		ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-		ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-		ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-		ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-		ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-		ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-		ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+		ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+		ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+		ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+		ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+		ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+		ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+		ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+		ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+		ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+		ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+		ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+		ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 
 		RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 8, ids);
 
@@ -1033,9 +1037,9 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 
 	RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, BASE_UNIFORM_SET);
 	if (p_backbuffer) {
-		storage->render_target_set_backbuffer_uniform_set(p_to_render_target, uniform_set);
+		texture_storage->render_target_set_backbuffer_uniform_set(p_to_render_target, uniform_set);
 	} else {
-		storage->render_target_set_framebuffer_uniform_set(p_to_render_target, uniform_set);
+		texture_storage->render_target_set_framebuffer_uniform_set(p_to_render_target, uniform_set);
 	}
 
 	return uniform_set;
@@ -1043,6 +1047,8 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 
 void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
 	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
 	Item *current_clip = nullptr;
 
 	Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
@@ -1053,21 +1059,21 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
 	Vector<Color> clear_colors;
 
 	if (p_to_backbuffer) {
-		framebuffer = storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target);
-		fb_uniform_set = storage->render_target_get_backbuffer_uniform_set(p_to_render_target);
+		framebuffer = texture_storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target);
+		fb_uniform_set = texture_storage->render_target_get_backbuffer_uniform_set(p_to_render_target);
 	} else {
-		framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target);
+		framebuffer = texture_storage->render_target_get_rd_framebuffer(p_to_render_target);
 
-		if (storage->render_target_is_clear_requested(p_to_render_target)) {
+		if (texture_storage->render_target_is_clear_requested(p_to_render_target)) {
 			clear = true;
-			clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target));
-			storage->render_target_disable_clear_request(p_to_render_target);
+			clear_colors.push_back(texture_storage->render_target_get_clear_request_color(p_to_render_target));
+			texture_storage->render_target_disable_clear_request(p_to_render_target);
 		}
 #ifndef _MSC_VER
 #warning TODO obtain from framebuffer format eventually when this is implemented
 #endif
 
-		fb_uniform_set = storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
+		fb_uniform_set = texture_storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
 	}
 
 	if (fb_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fb_uniform_set)) {
@@ -1136,6 +1142,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
 }
 
 void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
 
@@ -1264,7 +1271,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 			}
 
 			if (clight->texture.is_valid()) {
-				Rect2 atlas_rect = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_rect(clight->texture);
+				Rect2 atlas_rect = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture_rect(clight->texture);
 				state.light_uniforms[index].atlas_rect[0] = atlas_rect.position.x;
 				state.light_uniforms[index].atlas_rect[1] = atlas_rect.position.y;
 				state.light_uniforms[index].atlas_rect[2] = atlas_rect.size.width;
@@ -1294,7 +1301,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 		//update canvas state uniform buffer
 		State::Buffer state_buffer;
 
-		Size2i ssize = storage->render_target_get_size(p_to_render_target);
+		Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
 
 		Transform3D screen_transform;
 		screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
@@ -1313,7 +1320,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 		state_buffer.canvas_modulate[2] = p_modulate.b;
 		state_buffer.canvas_modulate[3] = p_modulate.a;
 
-		Size2 render_target_size = storage->render_target_get_size(p_to_render_target);
+		Size2 render_target_size = texture_storage->render_target_get_size(p_to_render_target);
 		state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
 		state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
 
@@ -1330,7 +1337,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 		state_buffer.screen_to_sdf[0] = 1.0 / state_buffer.sdf_to_screen[0];
 		state_buffer.screen_to_sdf[1] = 1.0 / state_buffer.sdf_to_screen[1];
 
-		Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_to_render_target);
+		Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_to_render_target);
 		Rect2 sdf_tex_rect(sdf_rect.position / canvas_scale, sdf_rect.size / canvas_scale);
 
 		state_buffer.sdf_to_tex[0] = 1.0 / sdf_tex_rect.size.width;
@@ -1420,9 +1427,9 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 				Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
 
 				if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
-					storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
+					texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
 				} else {
-					storage->render_target_clear_back_buffer(p_to_render_target, group_rect, Color(0, 0, 0, 0));
+					texture_storage->render_target_clear_back_buffer(p_to_render_target, group_rect, Color(0, 0, 0, 0));
 				}
 
 				backbuffer_copy = false;
@@ -1442,7 +1449,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 			item_count = 0;
 
 			if (ci->canvas_group->blur_mipmaps) {
-				storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache);
+				texture_storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache);
 			}
 
 			canvas_group_owner = nullptr;
@@ -1457,7 +1464,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 			_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
 			item_count = 0;
 
-			storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
+			texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
 
 			backbuffer_copy = false;
 			material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
@@ -1490,7 +1497,7 @@ RID RendererCanvasRenderRD::light_create() {
 }
 
 void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
-	RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton();
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 
 	CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
 	ERR_FAIL_COND(!cl);
@@ -1498,12 +1505,12 @@ void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
 		return;
 	}
 	if (cl->texture.is_valid()) {
-		decal_atlas_storage->texture_remove_from_decal_atlas(cl->texture);
+		texture_storage->texture_remove_from_decal_atlas(cl->texture);
 	}
 	cl->texture = p_texture;
 
 	if (cl->texture.is_valid()) {
-		decal_atlas_storage->texture_add_to_decal_atlas(cl->texture);
+		texture_storage->texture_add_to_decal_atlas(cl->texture);
 	}
 }
 
@@ -1703,8 +1710,10 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
 }
 
 void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) {
-	RID fb = storage->render_target_get_sdf_framebuffer(p_render_target);
-	Rect2i rect = storage->render_target_get_sdf_rect(p_render_target);
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
+	RID fb = texture_storage->render_target_get_sdf_framebuffer(p_render_target);
+	Rect2i rect = texture_storage->render_target_get_sdf_rect(p_render_target);
 
 	Transform2D to_sdf;
 	to_sdf.elements[0] *= rect.size.width;
@@ -1761,7 +1770,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan
 
 	RD::get_singleton()->draw_list_end();
 
-	storage->render_target_sdf_process(p_render_target); //done rendering, process it
+	texture_storage->render_target_sdf_process(p_render_target); //done rendering, process it
 }
 
 RID RendererCanvasRenderRD::occluder_polygon_create() {
@@ -2258,7 +2267,7 @@ void RendererCanvasRenderRD::update() {
 }
 
 RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
-	RendererRD::CanvasTextureStorage *canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton();
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	storage = p_storage;
 
@@ -2590,8 +2599,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
 		state.default_transforms_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
 	}
 
-	default_canvas_texture = canvas_texture_storage->canvas_texture_allocate();
-	canvas_texture_storage->canvas_texture_initialize(default_canvas_texture);
+	default_canvas_texture = texture_storage->canvas_texture_allocate();
+	texture_storage->canvas_texture_initialize(default_canvas_texture);
 
 	state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
 
@@ -2712,6 +2721,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
 	}
 	RD::get_singleton()->free(state.shadow_texture);
 
-	RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
+	RendererRD::TextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
 	//pipelines don't need freeing, they are all gone after shaders are gone
 }

+ 5 - 5
servers/rendering/renderer_rd/renderer_compositor_rd.cpp

@@ -44,7 +44,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
 	}
 
 	for (int i = 0; i < p_amount; i++) {
-		RID texture = storage->render_target_get_texture(p_render_targets[i].render_target);
+		RID texture = texture_storage->render_target_get_texture(p_render_targets[i].render_target);
 		ERR_CONTINUE(texture.is_null());
 		RID rd_texture = texture_storage->texture_get_rd_texture(texture);
 		ERR_CONTINUE(rd_texture.is_null());
@@ -155,11 +155,11 @@ void RendererCompositorRD::finalize() {
 	memdelete(scene);
 	memdelete(canvas);
 	memdelete(storage);
-	memdelete(decal_atlas_storage);
+	memdelete(particles_storage);
+	memdelete(light_storage);
 	memdelete(mesh_storage);
 	memdelete(material_storage);
 	memdelete(texture_storage);
-	memdelete(canvas_texture_storage);
 
 	//only need to erase these, the rest are erased by cascade
 	blit.shader.version_free(blit.shader_version);
@@ -288,11 +288,11 @@ RendererCompositorRD::RendererCompositorRD() {
 	singleton = this;
 	time = 0;
 
-	canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage);
 	texture_storage = memnew(RendererRD::TextureStorage);
-	decal_atlas_storage = memnew(RendererRD::DecalAtlasStorage);
 	material_storage = memnew(RendererRD::MaterialStorage);
 	mesh_storage = memnew(RendererRD::MeshStorage);
+	light_storage = memnew(RendererRD::LightStorage);
+	particles_storage = memnew(RendererRD::ParticlesStorage);
 	storage = memnew(RendererStorageRD);
 	canvas = memnew(RendererCanvasRenderRD(storage));
 

+ 6 - 6
servers/rendering/renderer_rd/renderer_compositor_rd.h

@@ -39,10 +39,10 @@
 #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h"
 #include "servers/rendering/renderer_rd/renderer_storage_rd.h"
 #include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
 
@@ -50,11 +50,11 @@ class RendererCompositorRD : public RendererCompositor {
 protected:
 	UniformSetCacheRD *uniform_set_cache = nullptr;
 	RendererCanvasRenderRD *canvas = nullptr;
-	RendererRD::CanvasTextureStorage *canvas_texture_storage;
+	RendererRD::LightStorage *light_storage;
 	RendererRD::MaterialStorage *material_storage;
 	RendererRD::MeshStorage *mesh_storage;
+	RendererRD::ParticlesStorage *particles_storage;
 	RendererRD::TextureStorage *texture_storage;
-	RendererRD::DecalAtlasStorage *decal_atlas_storage;
 	RendererStorageRD *storage = nullptr;
 	RendererSceneRenderRD *scene = nullptr;
 
@@ -98,10 +98,10 @@ protected:
 	static uint64_t frame;
 
 public:
-	RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; }
-	RendererDecalAtlasStorage *get_decal_atlas_storage() { return decal_atlas_storage; }
+	RendererLightStorage *get_light_storage() { return light_storage; };
 	RendererMaterialStorage *get_material_storage() { return material_storage; };
 	RendererMeshStorage *get_mesh_storage() { return mesh_storage; };
+	RendererParticlesStorage *get_particles_storage() { return particles_storage; };
 	RendererTextureStorage *get_texture_storage() { return texture_storage; };
 	RendererStorage *get_storage() { return storage; }
 	RendererCanvasRender *get_canvas() { return canvas; }

+ 58 - 45
servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp

@@ -32,6 +32,8 @@
 
 #include "core/config/project_settings.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"
 #include "servers/rendering/rendering_server_default.h"
 
 const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF);
@@ -41,6 +43,8 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF
 
 void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) {
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	storage = p_gi->storage;
 	gi = p_gi;
 	num_cascades = p_env->sdfgi_cascades;
@@ -387,7 +391,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
 			RD::Uniform u;
 			u.binding = 2;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 		}
 		{
@@ -669,7 +673,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 6;
-			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 		}
 
@@ -949,7 +953,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env,
 						RD::Uniform u;
 						u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 						u.binding = 1;
-						u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+						u.append_id(RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 						uniforms.push_back(u);
 					}
 
@@ -1110,6 +1114,7 @@ void RendererSceneGIRD::SDFGI::update_cascades() {
 
 void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) {
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 
 	if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) {
 		Vector<RD::Uniform> uniforms;
@@ -1176,7 +1181,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
 			RD::Uniform u;
 			u.binding = 8;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 		}
 		{
@@ -1245,11 +1250,13 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
 	RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_width, p_height, 1);
 	RD::get_singleton()->compute_list_end();
 
-	Size2 rtsize = storage->render_target_get_size(p_render_target);
-	storage->get_effects()->copy_to_fb_rect(p_texture, storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
+	Size2 rtsize = texture_storage->render_target_get_size(p_render_target);
+	storage->get_effects()->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
 }
 
 void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	SDFGIShader::DebugProbesPushConstant push_constant;
 
 	for (int i = 0; i < 4; i++) {
@@ -1296,7 +1303,7 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
 			RD::Uniform u;
 			u.binding = 3;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 		}
 		{
@@ -1458,7 +1465,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
 			RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j));
 			ERR_CONTINUE(!li);
 
-			if (storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
+			if (RSG::light_storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
 				continue;
 			}
 
@@ -1468,14 +1475,14 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
 			lights[idx].direction[0] = dir.x;
 			lights[idx].direction[1] = dir.y;
 			lights[idx].direction[2] = dir.z;
-			Color color = storage->light_get_color(li->light);
+			Color color = RSG::light_storage->light_get_color(li->light);
 			color = color.srgb_to_linear();
 			lights[idx].color[0] = color.r;
 			lights[idx].color[1] = color.g;
 			lights[idx].color[2] = color.b;
 			lights[idx].type = RS::LIGHT_DIRECTIONAL;
-			lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
-			lights[idx].has_shadow = storage->light_has_shadow(li->light);
+			lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+			lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
 
 			idx++;
 		}
@@ -1492,7 +1499,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
 			RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]);
 			ERR_CONTINUE(!li);
 
-			uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
+			uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
 			if (i > max_sdfgi_cascade) {
 				continue;
 			}
@@ -1513,18 +1520,18 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
 			lights[idx].position[0] = pos.x;
 			lights[idx].position[1] = pos.y;
 			lights[idx].position[2] = pos.z;
-			Color color = storage->light_get_color(li->light);
+			Color color = RSG::light_storage->light_get_color(li->light);
 			color = color.srgb_to_linear();
 			lights[idx].color[0] = color.r;
 			lights[idx].color[1] = color.g;
 			lights[idx].color[2] = color.b;
-			lights[idx].type = storage->light_get_type(li->light);
-			lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
-			lights[idx].has_shadow = storage->light_has_shadow(li->light);
-			lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
-			lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
-			lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
-			lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+			lights[idx].type = RSG::light_storage->light_get_type(li->light);
+			lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+			lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
+			lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
+			lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
+			lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+			lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
 
 			idx++;
 		}
@@ -1928,7 +1935,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
 				RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_positional_light_cull_result[i][j]);
 				ERR_CONTINUE(!li);
 
-				uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
+				uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
 				if (p_cascade_indices[i] > max_sdfgi_cascade) {
 					continue;
 				}
@@ -1937,7 +1944,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
 					continue;
 				}
 
-				lights[idx].type = storage->light_get_type(li->light);
+				lights[idx].type = RSG::light_storage->light_get_type(li->light);
 
 				Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
 				if (lights[idx].type == RS::LIGHT_DIRECTIONAL) {
@@ -1952,17 +1959,17 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
 				lights[idx].position[0] = pos.x;
 				lights[idx].position[1] = pos.y;
 				lights[idx].position[2] = pos.z;
-				Color color = storage->light_get_color(li->light);
+				Color color = RSG::light_storage->light_get_color(li->light);
 				color = color.srgb_to_linear();
 				lights[idx].color[0] = color.r;
 				lights[idx].color[1] = color.g;
 				lights[idx].color[2] = color.b;
-				lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
-				lights[idx].has_shadow = storage->light_has_shadow(li->light);
-				lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
-				lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
-				lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
-				lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+				lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+				lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
+				lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
+				lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
+				lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+				lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
 
 				idx++;
 			}
@@ -2019,6 +2026,8 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
 // VoxelGIInstance
 
 void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	uint32_t data_version = storage->voxel_gi_get_data_version(probe);
 
 	// (RE)CREATE IF NEEDED
@@ -2111,7 +2120,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
 					RD::Uniform u;
 					u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 					u.binding = 10;
-					u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+					u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 					uniforms.push_back(u);
 				}
 
@@ -2265,7 +2274,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
 								RD::Uniform u;
 								u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 								u.binding = 10;
-								u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+								u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 								uniforms.push_back(u);
 							}
 							{
@@ -2334,7 +2343,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
 							RD::Uniform u;
 							u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 							u.binding = 10;
-							u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+							u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 							uniforms.push_back(u);
 						}
 
@@ -2387,22 +2396,22 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
 				RID light_instance = p_light_instances[i];
 				RID light = p_scene_render->light_instance_get_base_light(light_instance);
 
-				l.type = storage->light_get_type(light);
-				if (l.type == RS::LIGHT_DIRECTIONAL && storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
+				l.type = RSG::light_storage->light_get_type(light);
+				if (l.type == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
 					light_count--;
 					continue;
 				}
 
-				l.attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
-				l.energy = storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
-				l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
-				Color color = storage->light_get_color(light).srgb_to_linear();
+				l.attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
+				l.energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+				l.radius = to_cell.basis.xform(Vector3(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
+				Color color = RSG::light_storage->light_get_color(light).srgb_to_linear();
 				l.color[0] = color.r;
 				l.color[1] = color.g;
 				l.color[2] = color.b;
 
-				l.cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
-				l.inv_spot_attenuation = 1.0f / storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+				l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+				l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
 
 				Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance);
 
@@ -2417,7 +2426,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
 				l.direction[1] = dir.y;
 				l.direction[2] = dir.z;
 
-				l.has_shadow = storage->light_has_shadow(light);
+				l.has_shadow = RSG::light_storage->light_has_shadow(light);
 			}
 
 			RD::get_singleton()->buffer_update(gi->voxel_gi_lights_uniform, 0, sizeof(VoxelGILight) * light_count, gi->voxel_gi_lights);
@@ -2722,6 +2731,8 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
 }
 
 void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	if (mipmaps.size() == 0) {
 		return;
 	}
@@ -2770,7 +2781,7 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 		u.binding = 3;
-		u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+		u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 		uniforms.push_back(u);
 	}
 
@@ -2811,6 +2822,7 @@ RendererSceneGIRD::~RendererSceneGIRD() {
 
 void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 
 	storage = p_storage;
 
@@ -2936,7 +2948,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 				u.binding = 1;
-				u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+				u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 				uniforms.push_back(u);
 			}
 
@@ -3129,6 +3141,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
 
 void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 
 	RD::get_singleton()->draw_command_begin_label("GI Render");
 
@@ -3254,14 +3267,14 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 6;
-			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 7;
-			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 		}
 

+ 0 - 1
servers/rendering/renderer_rd/renderer_scene_gi_rd.h

@@ -45,7 +45,6 @@
 #include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/voxel_gi.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/rendering/rendering_device.h"
 

+ 160 - 150
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -33,7 +33,6 @@
 #include "core/config/project_settings.h"
 #include "core/os/os.h"
 #include "renderer_compositor_rd.h"
-#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_server_default.h"
@@ -690,7 +689,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_needs_redraw(RID p_instanc
 		return true;
 	}
 
-	if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
+	if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
 		return true;
 	}
 
@@ -714,12 +713,12 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
 
 	RD::get_singleton()->draw_command_begin_label("Reflection probe render");
 
-	if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
+	if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
 		WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings.");
 		reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count);
 	}
 
-	if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) {
+	if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) {
 		// Invalidate reflection atlas, need to regenerate
 		RD::get_singleton()->free(atlas->reflection);
 		atlas->reflection = RID();
@@ -736,7 +735,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
 
 	if (atlas->reflection.is_null()) {
 		int mipmaps = MIN(sky.roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1);
-		mipmaps = storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
+		mipmaps = RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
 		{
 			//reflection atlas was unused, create:
 			RD::TextureFormat tf;
@@ -760,7 +759,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
 		}
 		atlas->reflections.resize(atlas->count);
 		for (int i = 0; i < atlas->count; i++) {
-			atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
+			atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
 			for (int j = 0; j < 6; j++) {
 				atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer);
 			}
@@ -828,7 +827,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
 		return false;
 	}
 
-	if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
+	if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
 		// Using real time reflections, all roughness is done in one step
 		atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(storage, false);
 		rpi->rendering = false;
@@ -1346,7 +1345,7 @@ int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance
 	LightInstance *light_instance = light_instance_owner.get_or_null(p_light_intance);
 	ERR_FAIL_COND_V(!light_instance, 0);
 
-	switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
+	switch (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light)) {
 		case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
 			break; //none
 		case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
@@ -1408,7 +1407,7 @@ RID RendererSceneRenderRD::light_instance_create(RID p_light) {
 
 	light_instance->self = li;
 	light_instance->light = p_light;
-	light_instance->light_type = storage->light_get_type(p_light);
+	light_instance->light_type = RSG::light_storage->light_get_type(p_light);
 	if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) {
 		light_instance->forward_id = _allocate_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT);
 	}
@@ -2557,7 +2556,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
 		tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
 		tonemap.view_count = p_render_data->view_count;
 
-		storage->get_effects()->tonemapper(rb->internal_texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+		storage->get_effects()->tonemapper(rb->internal_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
 
 		RD::get_singleton()->draw_command_end_label();
 	}
@@ -2570,7 +2569,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
 		RD::get_singleton()->draw_command_end_label();
 	}
 
-	storage->render_target_disable_clear_request(rb->render_target);
+	texture_storage->render_target_disable_clear_request(rb->render_target);
 }
 
 void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
@@ -2647,7 +2646,8 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_
 	RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
 	ERR_FAIL_COND(!rb);
 
-	storage->render_target_disable_clear_request(rb->render_target);
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	texture_storage->render_target_disable_clear_request(rb->render_target);
 }
 
 void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
@@ -2665,64 +2665,64 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
 				shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
 			}
 
-			Size2 rtsize = storage->render_target_get_size(rb->render_target);
-			effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+			Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+			effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
 		}
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) {
 		if (directional_shadow_get_texture().is_valid()) {
 			RID shadow_atlas_texture = directional_shadow_get_texture();
-			Size2 rtsize = storage->render_target_get_size(rb->render_target);
+			Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
 
-			effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+			effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
 		}
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DECAL_ATLAS) {
-		RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture();
+		RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
 
 		if (decal_atlas.is_valid()) {
-			Size2 rtsize = storage->render_target_get_size(rb->render_target);
+			Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
 
-			effects->copy_to_fb_rect(decal_atlas, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
+			effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
 		}
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) {
 		if (rb->luminance.current.is_valid()) {
-			Size2 rtsize = storage->render_target_get_size(rb->render_target);
+			Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
 
-			effects->copy_to_fb_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
+			effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
 		}
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ss_effects.ssao.ao_final.is_valid()) {
-		Size2 rtsize = storage->render_target_get_size(rb->render_target);
-		effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+		Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+		effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb->ss_effects.ssil.ssil_final.is_valid()) {
-		Size2 rtsize = storage->render_target_get_size(rb->render_target);
-		effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
+		Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+		effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) {
-		Size2 rtsize = storage->render_target_get_size(rb->render_target);
-		effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
+		Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+		effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->ambient_buffer.is_valid()) {
-		Size2 rtsize = storage->render_target_get_size(rb->render_target);
+		Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
 		RID ambient_texture = rb->ambient_buffer;
 		RID reflection_texture = rb->reflection_buffer;
-		effects->copy_to_fb_rect(ambient_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
+		effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) {
 		if (p_occlusion_buffer.is_valid()) {
-			Size2 rtsize = storage->render_target_get_size(rb->render_target);
-			effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
+			Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+			effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
 		}
 	}
 }
@@ -2943,6 +2943,9 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
 }
 
 void RendererSceneRenderRD::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_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, 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");
 
 	if (!_render_buffers_can_be_storage()) {
@@ -2952,7 +2955,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
 
 	if (p_width != p_internal_width) {
 		float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
-		storage->sampler_rd_configure_custom(fsr_mipmap_bias);
+		material_storage->sampler_rd_configure_custom(fsr_mipmap_bias);
 		update_uniform_sets();
 	}
 
@@ -3040,11 +3043,11 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
 		rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
 	}
 
-	RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
+	RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target);
 	rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count);
 
 	if (is_clustered_enabled()) {
-		rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
+		rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
 	}
 }
 
@@ -3189,6 +3192,7 @@ RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_g
 }
 
 void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
+	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
 	cluster.reflection_count = 0;
 
 	for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) {
@@ -3223,30 +3227,30 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
 
 		Cluster::ReflectionData &reflection_ubo = cluster.reflections[i];
 
-		Vector3 extents = storage->reflection_probe_get_extents(base_probe);
+		Vector3 extents = light_storage->reflection_probe_get_extents(base_probe);
 
-		rpi->cull_mask = storage->reflection_probe_get_cull_mask(base_probe);
+		rpi->cull_mask = light_storage->reflection_probe_get_cull_mask(base_probe);
 
 		reflection_ubo.box_extents[0] = extents.x;
 		reflection_ubo.box_extents[1] = extents.y;
 		reflection_ubo.box_extents[2] = extents.z;
 		reflection_ubo.index = rpi->atlas_index;
 
-		Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe);
+		Vector3 origin_offset = light_storage->reflection_probe_get_origin_offset(base_probe);
 
 		reflection_ubo.box_offset[0] = origin_offset.x;
 		reflection_ubo.box_offset[1] = origin_offset.y;
 		reflection_ubo.box_offset[2] = origin_offset.z;
-		reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe);
+		reflection_ubo.mask = light_storage->reflection_probe_get_cull_mask(base_probe);
 
-		reflection_ubo.intensity = storage->reflection_probe_get_intensity(base_probe);
-		reflection_ubo.ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe);
+		reflection_ubo.intensity = light_storage->reflection_probe_get_intensity(base_probe);
+		reflection_ubo.ambient_mode = light_storage->reflection_probe_get_ambient_mode(base_probe);
 
-		reflection_ubo.exterior = !storage->reflection_probe_is_interior(base_probe);
-		reflection_ubo.box_project = storage->reflection_probe_is_box_projection(base_probe);
+		reflection_ubo.exterior = !light_storage->reflection_probe_is_interior(base_probe);
+		reflection_ubo.box_project = light_storage->reflection_probe_is_box_projection(base_probe);
 
-		Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).srgb_to_linear();
-		float interior_ambient_energy = storage->reflection_probe_get_ambient_color_energy(base_probe);
+		Color ambient_linear = light_storage->reflection_probe_get_ambient_color(base_probe).srgb_to_linear();
+		float interior_ambient_energy = light_storage->reflection_probe_get_ambient_color_energy(base_probe);
 		reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
 		reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
 		reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
@@ -3268,7 +3272,8 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
 }
 
 void RendererSceneRenderRD::_setup_lights(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) {
-	RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton();
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
 
 	Transform3D inverse_transform = p_camera_transform.affine_inverse();
 
@@ -3291,10 +3296,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 
 		ERR_CONTINUE(base.is_null());
 
-		RS::LightType type = storage->light_get_type(base);
+		RS::LightType type = light_storage->light_get_type(base);
 		switch (type) {
 			case RS::LIGHT_DIRECTIONAL: {
-				if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_get_sky_mode(base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
+				if (r_directional_light_count >= cluster.max_directional_lights || light_storage->light_directional_get_sky_mode(base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
 					continue;
 				}
 
@@ -3308,19 +3313,19 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 				light_data.direction[1] = direction.y;
 				light_data.direction[2] = direction.z;
 
-				float sign = storage->light_is_negative(base) ? -1 : 1;
+				float sign = light_storage->light_is_negative(base) ? -1 : 1;
 
-				light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
+				light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
 
-				Color linear_col = storage->light_get_color(base).srgb_to_linear();
+				Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
 				light_data.color[0] = linear_col.r;
 				light_data.color[1] = linear_col.g;
 				light_data.color[2] = linear_col.b;
 
-				light_data.specular = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
-				light_data.mask = storage->light_get_cull_mask(base);
+				light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
+				light_data.mask = light_storage->light_get_cull_mask(base);
 
-				float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+				float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
 
 				light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset
 
@@ -3328,15 +3333,15 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 					WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
 				}
 
-				light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base);
+				light_data.shadow_enabled = p_using_shadows && light_storage->light_has_shadow(base);
 
-				float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+				float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
 				if (angular_diameter > 0.0) {
 					// I know tan(0) is 0, but let's not risk it with numerical precision.
 					// technically this will keep expanding until reaching the sun, but all we care
 					// is expand until we reach the radius of the near plane (there can't be more occluders than that)
 					angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
-					if (storage->light_has_shadow(base)) {
+					if (light_storage->light_has_shadow(base)) {
 						r_directional_light_soft_shadows = true;
 					}
 				} else {
@@ -3344,10 +3349,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 				}
 
 				if (light_data.shadow_enabled) {
-					RS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
+					RS::LightDirectionalShadowMode smode = light_storage->light_directional_get_shadow_mode(base);
 
 					int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
-					light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && storage->light_directional_get_blend_splits(base);
+					light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light_storage->light_directional_get_blend_splits(base);
 					for (int j = 0; j < 4; j++) {
 						Rect2 atlas_rect = li->shadow_transform[j].atlas_rect;
 						CameraMatrix matrix = li->shadow_transform[j].camera;
@@ -3363,9 +3368,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 						CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
 						light_data.shadow_split_offsets[j] = split;
 						float bias_scale = li->shadow_transform[j].bias_scale;
-						light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
-						light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
-						light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale;
+						light_data.shadow_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
+						light_data.shadow_normal_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
+						light_data.shadow_transmittance_bias[j] = light_storage->light_get_transmittance_bias(base) * bias_scale;
 						light_data.shadow_z_range[j] = li->shadow_transform[j].farplane;
 						light_data.shadow_range_begin[j] = li->shadow_transform[j].range_begin;
 						RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]);
@@ -3392,14 +3397,14 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 						}
 					}
 
-					float fade_start = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
+					float fade_start = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
 					light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
 					light_data.fade_to = -light_data.shadow_split_offsets[3];
-					light_data.shadow_volumetric_fog_fade = 1.0 / storage->light_get_shadow_volumetric_fog_fade(base);
+					light_data.shadow_volumetric_fog_fade = 1.0 / light_storage->light_get_shadow_volumetric_fog_fade(base);
 
-					light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+					light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
 					light_data.softshadow_angle = angular_diameter;
-					light_data.bake_mode = storage->light_get_bake_mode(base);
+					light_data.bake_mode = light_storage->light_get_bake_mode(base);
 
 					if (angular_diameter <= 0.0) {
 						light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF
@@ -3415,9 +3420,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 
 				const real_t distance = camera_plane.distance_to(li->transform.origin);
 
-				if (storage->light_is_distance_fade_enabled(li->light)) {
-					const float fade_begin = storage->light_get_distance_fade_begin(li->light);
-					const float fade_length = storage->light_get_distance_fade_length(li->light);
+				if (light_storage->light_is_distance_fade_enabled(li->light)) {
+					const float fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+					const float fade_length = light_storage->light_get_distance_fade_length(li->light);
 
 					if (distance > fade_begin) {
 						if (distance > fade_begin + fade_length) {
@@ -3438,9 +3443,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 
 				const real_t distance = camera_plane.distance_to(li->transform.origin);
 
-				if (storage->light_is_distance_fade_enabled(li->light)) {
-					const float fade_begin = storage->light_get_distance_fade_begin(li->light);
-					const float fade_length = storage->light_get_distance_fade_length(li->light);
+				if (light_storage->light_is_distance_fade_enabled(li->light)) {
+					const float fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+					const float fade_length = light_storage->light_get_distance_fade_length(li->light);
 
 					if (distance > fade_begin) {
 						if (distance > fade_begin + fade_length) {
@@ -3490,10 +3495,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 
 		Transform3D light_transform = li->transform;
 
-		float sign = storage->light_is_negative(base) ? -1 : 1;
-		Color linear_col = storage->light_get_color(base).srgb_to_linear();
+		float sign = light_storage->light_is_negative(base) ? -1 : 1;
+		Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
 
-		light_data.attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION);
+		light_data.attenuation = light_storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION);
 
 		// Reuse fade begin, fade length and distance for shadow LOD determination later.
 		float fade_begin = 0.0;
@@ -3501,9 +3506,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 		real_t distance = 0.0;
 
 		float fade = 1.0;
-		if (storage->light_is_distance_fade_enabled(li->light)) {
-			fade_begin = storage->light_get_distance_fade_begin(li->light);
-			fade_length = storage->light_get_distance_fade_length(li->light);
+		if (light_storage->light_is_distance_fade_enabled(li->light)) {
+			fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+			fade_length = light_storage->light_get_distance_fade_length(li->light);
 			distance = camera_plane.distance_to(li->transform.origin);
 
 			if (distance > fade_begin) {
@@ -3512,15 +3517,15 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 			}
 		}
 
-		float energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
+		float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
 
 		light_data.color[0] = linear_col.r * energy;
 		light_data.color[1] = linear_col.g * energy;
 		light_data.color[2] = linear_col.b * energy;
-		light_data.specular_amount = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
-		light_data.bake_mode = storage->light_get_bake_mode(base);
+		light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
+		light_data.bake_mode = light_storage->light_get_bake_mode(base);
 
-		float radius = MAX(0.001, storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
+		float radius = MAX(0.001, light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
 		light_data.inv_radius = 1.0 / radius;
 
 		Vector3 pos = inverse_transform.xform(light_transform.origin);
@@ -3535,25 +3540,25 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 		light_data.direction[1] = direction.y;
 		light_data.direction[2] = direction.z;
 
-		float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+		float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
 
 		light_data.size = size;
 
-		light_data.inv_spot_attenuation = 1.0f / storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
-		float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
+		light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+		float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
 		light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle));
 
-		light_data.mask = storage->light_get_cull_mask(base);
+		light_data.mask = light_storage->light_get_cull_mask(base);
 
 		light_data.atlas_rect[0] = 0;
 		light_data.atlas_rect[1] = 0;
 		light_data.atlas_rect[2] = 0;
 		light_data.atlas_rect[3] = 0;
 
-		RID projector = storage->light_get_projector(base);
+		RID projector = light_storage->light_get_projector(base);
 
 		if (projector.is_valid()) {
-			Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(projector);
+			Rect2 rect = texture_storage->decal_atlas_get_texture_rect(projector);
 
 			if (type == RS::LIGHT_SPOT) {
 				light_data.projector_rect[0] = rect.position.x;
@@ -3576,8 +3581,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 		const bool needs_shadow = shadow_atlas && shadow_atlas->shadow_owners.has(li->self);
 
 		bool in_shadow_range = true;
-		if (needs_shadow && storage->light_is_distance_fade_enabled(li->light)) {
-			if (distance > storage->light_get_distance_fade_shadow(li->light)) {
+		if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) {
+			if (distance > light_storage->light_get_distance_fade_shadow(li->light)) {
 				// Out of range, don't draw shadows to improve performance.
 				in_shadow_range = false;
 			}
@@ -3589,15 +3594,15 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 			light_data.shadow_enabled = true;
 
 			float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
-			light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
+			light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
 
 			if (type == RS::LIGHT_SPOT) {
-				light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0;
+				light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0;
 			} else { //omni
-				light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS);
+				light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS);
 			}
 
-			light_data.transmittance_bias = storage->light_get_transmittance_bias(base);
+			light_data.transmittance_bias = light_storage->light_get_transmittance_bias(base);
 
 			Vector2i omni_offset;
 			Rect2 rect = light_instance_get_shadow_atlas_rect(li->self, p_shadow_atlas, omni_offset);
@@ -3607,8 +3612,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 			light_data.atlas_rect[2] = rect.size.width;
 			light_data.atlas_rect[3] = rect.size.height;
 
-			light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
-			light_data.shadow_volumetric_fog_fade = 1.0 / storage->light_get_shadow_volumetric_fog_fade(base);
+			light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+			light_data.shadow_volumetric_fog_fade = 1.0 / light_storage->light_get_shadow_volumetric_fog_fade(base);
 
 			if (type == RS::LIGHT_OMNI) {
 				Transform3D proj = (inverse_transform * light_transform).inverse();
@@ -3645,7 +3650,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 			light_data.shadow_enabled = false;
 		}
 
-		li->cull_mask = storage->light_get_cull_mask(base);
+		li->cull_mask = light_storage->light_get_cull_mask(base);
 
 		if (current_cluster_builder != nullptr) {
 			current_cluster_builder->add_light(type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
@@ -3669,7 +3674,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 }
 
 void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) {
-	RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton();
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 
 	Transform3D uv_xform;
 	uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
@@ -3694,9 +3699,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 
 		real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
 
-		if (decal_atlas_storage->decal_is_distance_fade_enabled(decal)) {
-			float fade_begin = decal_atlas_storage->decal_get_distance_fade_begin(decal);
-			float fade_length = decal_atlas_storage->decal_get_distance_fade_length(decal);
+		if (texture_storage->decal_is_distance_fade_enabled(decal)) {
+			float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
+			float fade_length = texture_storage->decal_get_distance_fade_length(decal);
 
 			if (distance > fade_begin) {
 				if (distance > fade_begin + fade_length) {
@@ -3724,15 +3729,15 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 			_map_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id, i);
 		}
 
-		di->cull_mask = decal_atlas_storage->decal_get_cull_mask(decal);
+		di->cull_mask = texture_storage->decal_get_cull_mask(decal);
 
 		Transform3D xform = di->transform;
 		float fade = 1.0;
 
-		if (decal_atlas_storage->decal_is_distance_fade_enabled(decal)) {
+		if (texture_storage->decal_is_distance_fade_enabled(decal)) {
 			real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
-			float fade_begin = decal_atlas_storage->decal_get_distance_fade_begin(decal);
-			float fade_length = decal_atlas_storage->decal_get_distance_fade_length(decal);
+			float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
+			float fade_length = texture_storage->decal_get_distance_fade_length(decal);
 
 			if (distance > fade_begin) {
 				fade = 1.0 - (distance - fade_begin) / fade_length;
@@ -3741,7 +3746,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 
 		Cluster::DecalData &dd = cluster.decals[i];
 
-		Vector3 decal_extents = decal_atlas_storage->decal_get_extents(decal);
+		Vector3 decal_extents = texture_storage->decal_get_extents(decal);
 
 		Transform3D scale_xform;
 		scale_xform.basis.scale(decal_extents);
@@ -3754,12 +3759,12 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 		dd.normal[0] = normal.x;
 		dd.normal[1] = normal.y;
 		dd.normal[2] = normal.z;
-		dd.normal_fade = decal_atlas_storage->decal_get_normal_fade(decal);
+		dd.normal_fade = texture_storage->decal_get_normal_fade(decal);
 
-		RID albedo_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
-		RID emission_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
+		RID albedo_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
+		RID emission_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
 		if (albedo_tex.is_valid()) {
-			Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(albedo_tex);
+			Rect2 rect = texture_storage->decal_atlas_get_texture_rect(albedo_tex);
 			dd.albedo_rect[0] = rect.position.x;
 			dd.albedo_rect[1] = rect.position.y;
 			dd.albedo_rect[2] = rect.size.x;
@@ -3774,10 +3779,10 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 			dd.albedo_rect[3] = 0;
 		}
 
-		RID normal_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
+		RID normal_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
 
 		if (normal_tex.is_valid()) {
-			Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(normal_tex);
+			Rect2 rect = texture_storage->decal_atlas_get_texture_rect(normal_tex);
 			dd.normal_rect[0] = rect.position.x;
 			dd.normal_rect[1] = rect.position.y;
 			dd.normal_rect[2] = rect.size.x;
@@ -3792,9 +3797,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 			dd.normal_rect[3] = 0;
 		}
 
-		RID orm_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
+		RID orm_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
 		if (orm_tex.is_valid()) {
-			Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(orm_tex);
+			Rect2 rect = texture_storage->decal_atlas_get_texture_rect(orm_tex);
 			dd.orm_rect[0] = rect.position.x;
 			dd.orm_rect[1] = rect.position.y;
 			dd.orm_rect[2] = rect.size.x;
@@ -3807,7 +3812,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 		}
 
 		if (emission_tex.is_valid()) {
-			Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(emission_tex);
+			Rect2 rect = texture_storage->decal_atlas_get_texture_rect(emission_tex);
 			dd.emission_rect[0] = rect.position.x;
 			dd.emission_rect[1] = rect.position.y;
 			dd.emission_rect[2] = rect.size.x;
@@ -3819,16 +3824,16 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 			dd.emission_rect[3] = 0;
 		}
 
-		Color modulate = decal_atlas_storage->decal_get_modulate(decal);
+		Color modulate = texture_storage->decal_get_modulate(decal);
 		dd.modulate[0] = modulate.r;
 		dd.modulate[1] = modulate.g;
 		dd.modulate[2] = modulate.b;
 		dd.modulate[3] = modulate.a * fade;
-		dd.emission_energy = decal_atlas_storage->decal_get_emission_energy(decal) * fade;
-		dd.albedo_mix = decal_atlas_storage->decal_get_albedo_mix(decal);
-		dd.mask = decal_atlas_storage->decal_get_cull_mask(decal);
-		dd.upper_fade = decal_atlas_storage->decal_get_upper_fade(decal);
-		dd.lower_fade = decal_atlas_storage->decal_get_lower_fade(decal);
+		dd.emission_energy = texture_storage->decal_get_emission_energy(decal) * fade;
+		dd.albedo_mix = texture_storage->decal_get_albedo_mix(decal);
+		dd.mask = texture_storage->decal_get_cull_mask(decal);
+		dd.upper_fade = texture_storage->decal_get_upper_fade(decal);
+		dd.lower_fade = texture_storage->decal_get_lower_fade(decal);
 
 		if (current_cluster_builder != nullptr) {
 			current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents);
@@ -4438,7 +4443,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 7;
-			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4500,7 +4505,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 13;
-			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4809,6 +4814,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo
 
 void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer) {
 	// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
+	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
 
 	if (p_render_data->render_buffers.is_valid() && p_use_gi) {
 		RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
@@ -4828,9 +4834,9 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
 		for (int i = 0; i < render_state.render_shadow_count; i++) {
 			LightInstance *li = light_instance_owner.get_or_null(render_state.render_shadows[i].light);
 
-			if (storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) {
+			if (light_storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) {
 				render_state.directional_shadows.push_back(i);
-			} else if (storage->light_get_type(li->light) == RS::LIGHT_OMNI && storage->light_omni_get_shadow_mode(li->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+			} else if (light_storage->light_get_type(li->light) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(li->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
 				render_state.cube_shadows.push_back(i);
 			} else {
 				render_state.shadows.push_back(i);
@@ -4940,7 +4946,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
 	bool using_shadows = true;
 
 	if (p_render_data->reflection_probe.is_valid()) {
-		if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+		if (!RSG::light_storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
 			using_shadows = false;
 		}
 	} else {
@@ -4974,6 +4980,8 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
 }
 
 void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &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_effects, 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) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
 	// getting this here now so we can direct call a bunch of things more easily
 	RenderBuffers *rb = nullptr;
 	if (p_render_buffers.is_valid()) {
@@ -5052,7 +5060,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
 
 	Color clear_color;
 	if (p_render_buffers.is_valid()) {
-		clear_color = storage->render_target_get_clear_request_color(rb->render_target);
+		clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target);
 	} else {
 		clear_color = storage->get_default_clear_color();
 	}
@@ -5171,7 +5179,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
 	CameraMatrix light_projection;
 	Transform3D light_transform;
 
-	if (storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
+	if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
 		//set pssm stuff
 		if (light_instance->last_scene_shadow_pass != scene_pass) {
 			light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
@@ -5179,13 +5187,13 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
 			light_instance->last_scene_shadow_pass = scene_pass;
 		}
 
-		use_pancake = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
+		use_pancake = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
 		light_projection = light_instance->shadow_transform[p_pass].camera;
 		light_transform = light_instance->shadow_transform[p_pass].transform;
 
 		atlas_rect = light_instance->directional_rect;
 
-		if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
+		if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
 			atlas_rect.size.width /= 2;
 			atlas_rect.size.height /= 2;
 
@@ -5196,7 +5204,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
 			} else if (p_pass == 3) {
 				atlas_rect.position += atlas_rect.size;
 			}
-		} else if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
+		} else if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
 			atlas_rect.size.height /= 2;
 
 			if (p_pass == 0) {
@@ -5210,7 +5218,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
 		light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
 		light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size;
 
-		zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
+		zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
 
 		render_fb = directional_shadow.fb;
 		render_texture = RID();
@@ -5244,13 +5252,13 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
 		atlas_rect.size.width = shadow_size;
 		atlas_rect.size.height = shadow_size;
 
-		zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
+		zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
 
-		if (storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) {
+		if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) {
 			bool wrap = (shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision == 0;
 			dual_paraboloid_offset = wrap ? Vector2i(1 - shadow_atlas->quadrants[quadrant].subdivision, 1) : Vector2i(1, 0);
 
-			if (storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+			if (RSG::light_storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
 				ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2);
 
 				render_fb = cubemap->side_fb[p_pass];
@@ -5285,7 +5293,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
 				flip_y = true;
 			}
 
-		} else if (storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) {
+		} else if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) {
 			light_projection = light_instance->shadow_transform[0].camera;
 			light_transform = light_instance->shadow_transform[0].transform;
 
@@ -5324,8 +5332,10 @@ void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform,
 }
 
 void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
-	ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
-	Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
+	RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
+
+	ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider));
+	Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
 	CameraMatrix cm;
 	cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0);
 
@@ -5335,7 +5345,7 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
 	Transform3D cam_xform;
 	cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_axis(Vector3::AXIS_Y), -p_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
 
-	RID fb = storage->particles_collision_get_heightfield_framebuffer(p_collider);
+	RID fb = particles_storage->particles_collision_get_heightfield_framebuffer(p_collider);
 
 	_render_particle_collider_heightfield(fb, cam_xform, cm, p_instances);
 }
@@ -5741,18 +5751,18 @@ void fog() {
 				Vector<RID> ids;
 				ids.resize(12);
 				RID *ids_ptr = ids.ptrw();
-				ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-				ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-				ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-				ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-				ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-				ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-				ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-				ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-				ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-				ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-				ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-				ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+				ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+				ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+				ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+				ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+				ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+				ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+				ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+				ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+				ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+				ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+				ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+				ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 
 				RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
 				uniforms.push_back(u);

+ 19 - 18
servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp

@@ -927,18 +927,18 @@ void sky() {
 			Vector<RID> ids;
 			ids.resize(12);
 			RID *ids_ptr = ids.ptrw();
-			ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
-			ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-			ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 
 			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 0, ids);
 
@@ -1086,6 +1086,7 @@ RendererSceneSkyRD::~RendererSceneSkyRD() {
 }
 
 void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &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);
 
@@ -1181,8 +1182,8 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
 
 				ERR_CONTINUE(base.is_null());
 
-				RS::LightType type = storage->light_get_type(base);
-				if (type == RS::LIGHT_DIRECTIONAL && storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) {
+				RS::LightType type = light_storage->light_get_type(base);
+				if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) {
 					SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count];
 					Transform3D light_transform = li->transform;
 					Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
@@ -1191,17 +1192,17 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
 					sky_light_data.direction[1] = world_direction.y;
 					sky_light_data.direction[2] = world_direction.z;
 
-					float sign = storage->light_is_negative(base) ? -1 : 1;
-					sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
+					float sign = light_storage->light_is_negative(base) ? -1 : 1;
+					sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
 
-					Color linear_col = storage->light_get_color(base).srgb_to_linear();
+					Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
 					sky_light_data.color[0] = linear_col.r;
 					sky_light_data.color[1] = linear_col.g;
 					sky_light_data.color[2] = linear_col.b;
 
 					sky_light_data.enabled = true;
 
-					float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+					float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
 					if (angular_diameter > 0.0) {
 						// I know tan(0) is 0, but let's not risk it with numerical precision.
 						// technically this will keep expanding until reaching the sun, but all we care

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 352 - 3491
servers/rendering/renderer_rd/renderer_storage_rd.cpp


+ 0 - 928
servers/rendering/renderer_rd/renderer_storage_rd.h

@@ -36,9 +36,6 @@
 #include "core/templates/rid_owner.h"
 #include "servers/rendering/renderer_compositor.h"
 #include "servers/rendering/renderer_rd/effects_rd.h"
-#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h"
 #include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
 #include "servers/rendering/renderer_scene_render.h"
@@ -126,363 +123,6 @@ public:
 	}
 
 private:
-	/* TEXTURE API */
-
-	RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
-	RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
-
-	/* PARTICLES */
-
-	struct ParticleData {
-		float xform[16];
-		float velocity[3];
-		uint32_t active;
-		float color[4];
-		float custom[3];
-		float lifetime;
-	};
-
-	struct ParticlesFrameParams {
-		enum {
-			MAX_ATTRACTORS = 32,
-			MAX_COLLIDERS = 32,
-			MAX_3D_TEXTURES = 7
-		};
-
-		enum AttractorType {
-			ATTRACTOR_TYPE_SPHERE,
-			ATTRACTOR_TYPE_BOX,
-			ATTRACTOR_TYPE_VECTOR_FIELD,
-		};
-
-		struct Attractor {
-			float transform[16];
-			float extents[3]; //exents or radius
-			uint32_t type;
-
-			uint32_t texture_index; //texture index for vector field
-			float strength;
-			float attenuation;
-			float directionality;
-		};
-
-		enum CollisionType {
-			COLLISION_TYPE_SPHERE,
-			COLLISION_TYPE_BOX,
-			COLLISION_TYPE_SDF,
-			COLLISION_TYPE_HEIGHT_FIELD,
-			COLLISION_TYPE_2D_SDF,
-
-		};
-
-		struct Collider {
-			float transform[16];
-			float extents[3]; //exents or radius
-			uint32_t type;
-
-			uint32_t texture_index; //texture index for vector field
-			real_t scale;
-			uint32_t pad[2];
-		};
-
-		uint32_t emitting;
-		float system_phase;
-		float prev_system_phase;
-		uint32_t cycle;
-
-		real_t explosiveness;
-		real_t randomness;
-		float time;
-		float delta;
-
-		uint32_t frame;
-		uint32_t pad0;
-		uint32_t pad1;
-		uint32_t pad2;
-
-		uint32_t random_seed;
-		uint32_t attractor_count;
-		uint32_t collider_count;
-		float particle_size;
-
-		float emission_transform[16];
-
-		Attractor attractors[MAX_ATTRACTORS];
-		Collider colliders[MAX_COLLIDERS];
-	};
-
-	struct ParticleEmissionBufferData {
-	};
-
-	struct ParticleEmissionBuffer {
-		struct Data {
-			float xform[16];
-			float velocity[3];
-			uint32_t flags;
-			float color[4];
-			float custom[4];
-		};
-
-		int32_t particle_count;
-		int32_t particle_max;
-		uint32_t pad1;
-		uint32_t pad2;
-		Data data[1]; //its 2020 and empty arrays are still non standard in C++
-	};
-
-	struct Particles {
-		RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
-		bool inactive = true;
-		double inactive_time = 0.0;
-		bool emitting = false;
-		bool one_shot = false;
-		int amount = 0;
-		double lifetime = 1.0;
-		double pre_process_time = 0.0;
-		real_t explosiveness = 0.0;
-		real_t randomness = 0.0;
-		bool restart_request = false;
-		AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
-		bool use_local_coords = true;
-		bool has_collision_cache = false;
-
-		bool has_sdf_collision = false;
-		Transform2D sdf_collision_transform;
-		Rect2 sdf_collision_to_screen;
-		RID sdf_collision_texture;
-
-		RID process_material;
-		uint32_t frame_counter = 0;
-		RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
-
-		RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
-
-		Vector<RID> draw_passes;
-		Vector<Transform3D> trail_bind_poses;
-		bool trail_bind_poses_dirty = false;
-		RID trail_bind_pose_buffer;
-		RID trail_bind_pose_uniform_set;
-
-		RID particle_buffer;
-		RID particle_instance_buffer;
-		RID frame_params_buffer;
-
-		uint32_t userdata_count = 0;
-
-		RID particles_material_uniform_set;
-		RID particles_copy_uniform_set;
-		RID particles_transforms_buffer_uniform_set;
-		RID collision_textures_uniform_set;
-
-		RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
-		uint32_t collision_3d_textures_used = 0;
-		RID collision_heightmap_texture;
-
-		RID particles_sort_buffer;
-		RID particles_sort_uniform_set;
-
-		bool dirty = false;
-		Particles *update_list = nullptr;
-
-		RID sub_emitter;
-
-		double phase = 0.0;
-		double prev_phase = 0.0;
-		uint64_t prev_ticks = 0;
-		uint32_t random_seed = 0;
-
-		uint32_t cycle_number = 0;
-
-		double speed_scale = 1.0;
-
-		int fixed_fps = 30;
-		bool interpolate = true;
-		bool fractional_delta = false;
-		double frame_remainder = 0;
-		real_t collision_base_size = 0.01;
-
-		bool clear = true;
-
-		bool force_sub_emit = false;
-
-		Transform3D emission_transform;
-
-		Vector<uint8_t> emission_buffer_data;
-
-		ParticleEmissionBuffer *emission_buffer = nullptr;
-		RID emission_storage_buffer;
-
-		Set<RID> collisions;
-
-		Dependency dependency;
-
-		double trail_length = 1.0;
-		bool trails_enabled = false;
-		LocalVector<ParticlesFrameParams> frame_history;
-		LocalVector<ParticlesFrameParams> trail_params;
-
-		Particles() {
-		}
-	};
-
-	void _particles_process(Particles *p_particles, double p_delta);
-	void _particles_allocate_emission_buffer(Particles *particles);
-	void _particles_free_data(Particles *particles);
-	void _particles_update_buffers(Particles *particles);
-
-	struct ParticlesShader {
-		struct PushConstant {
-			float lifetime;
-			uint32_t clear;
-			uint32_t total_particles;
-			uint32_t trail_size;
-
-			uint32_t use_fractional_delta;
-			uint32_t sub_emitter_mode;
-			uint32_t can_emit;
-			uint32_t trail_pass;
-		};
-
-		ParticlesShaderRD shader;
-		ShaderCompiler compiler;
-
-		RID default_shader;
-		RID default_material;
-		RID default_shader_rd;
-
-		RID base_uniform_set;
-
-		struct CopyPushConstant {
-			float sort_direction[3];
-			uint32_t total_particles;
-
-			uint32_t trail_size;
-			uint32_t trail_total;
-			float frame_delta;
-			float frame_remainder;
-
-			float align_up[3];
-			uint32_t align_mode;
-
-			uint32_t order_by_lifetime;
-			uint32_t lifetime_split;
-			uint32_t lifetime_reverse;
-			uint32_t copy_mode_2d;
-
-			float inv_emission_transform[16];
-		};
-
-		enum {
-			MAX_USERDATAS = 6
-		};
-		enum {
-			COPY_MODE_FILL_INSTANCES,
-			COPY_MODE_FILL_SORT_BUFFER,
-			COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER,
-			COPY_MODE_MAX,
-		};
-
-		ParticlesCopyShaderRD copy_shader;
-		RID copy_shader_version;
-		RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)];
-
-		LocalVector<float> pose_update_buffer;
-
-	} particles_shader;
-
-	Particles *particle_update_list = nullptr;
-
-	struct ParticlesShaderData : public RendererRD::ShaderData {
-		bool valid;
-		RID version;
-		bool uses_collision = false;
-
-		//PipelineCacheRD pipelines[SKY_VERSION_MAX];
-		Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
-		Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
-
-		Vector<uint32_t> ubo_offsets;
-		uint32_t ubo_size;
-
-		String path;
-		String code;
-		Map<StringName, Map<int, RID>> default_texture_params;
-
-		RID pipeline;
-
-		bool uses_time = false;
-
-		bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {};
-		uint32_t userdata_count = 0;
-
-		virtual void set_code(const String &p_Code);
-		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
-		virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
-		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
-		virtual bool is_param_texture(const StringName &p_param) const;
-		virtual bool is_animated() const;
-		virtual bool casts_shadows() const;
-		virtual Variant get_default_parameter(const StringName &p_parameter) const;
-		virtual RS::ShaderNativeSourceCode get_native_source_code() const;
-
-		ParticlesShaderData();
-		virtual ~ParticlesShaderData();
-	};
-
-	RendererRD::ShaderData *_create_particles_shader_func();
-	static RendererRD::ShaderData *_create_particles_shader_funcs() {
-		return base_singleton->_create_particles_shader_func();
-	}
-
-	struct ParticlesMaterialData : public RendererRD::MaterialData {
-		ParticlesShaderData *shader_data = nullptr;
-		RID uniform_set;
-
-		virtual void set_render_priority(int p_priority) {}
-		virtual void set_next_pass(RID p_pass) {}
-		virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
-		virtual ~ParticlesMaterialData();
-	};
-
-	RendererRD::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
-	static RendererRD::MaterialData *_create_particles_material_funcs(RendererRD::ShaderData *p_shader) {
-		return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
-	}
-
-	void update_particles();
-
-	mutable RID_Owner<Particles, true> particles_owner;
-
-	/* Particles Collision */
-
-	struct ParticlesCollision {
-		RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
-		uint32_t cull_mask = 0xFFFFFFFF;
-		float radius = 1.0;
-		Vector3 extents = Vector3(1, 1, 1);
-		float attractor_strength = 1.0;
-		float attractor_attenuation = 1.0;
-		float attractor_directionality = 0.0;
-		RID field_texture;
-		RID heightfield_texture;
-		RID heightfield_fb;
-		Size2i heightfield_fb_size;
-
-		RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
-
-		Dependency dependency;
-	};
-
-	mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
-
-	struct ParticlesCollisionInstance {
-		RID collision;
-		Transform3D transform;
-		bool active = false;
-	};
-
-	mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
-
 	/* FOG VOLUMES */
 
 	struct FogVolume {
@@ -507,57 +147,6 @@ private:
 
 	mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
 
-	/* LIGHT */
-
-	struct Light {
-		RS::LightType type;
-		float param[RS::LIGHT_PARAM_MAX];
-		Color color = Color(1, 1, 1, 1);
-		RID projector;
-		bool shadow = false;
-		bool negative = false;
-		bool reverse_cull = false;
-		RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
-		uint32_t max_sdfgi_cascade = 2;
-		uint32_t cull_mask = 0xFFFFFFFF;
-		bool distance_fade = false;
-		real_t distance_fade_begin = 40.0;
-		real_t distance_fade_shadow = 50.0;
-		real_t distance_fade_length = 10.0;
-		RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
-		RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
-		bool directional_blend_splits = false;
-		RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
-		uint64_t version = 0;
-
-		Dependency dependency;
-	};
-
-	mutable RID_Owner<Light, true> light_owner;
-
-	/* REFLECTION PROBE */
-
-	struct ReflectionProbe {
-		RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
-		int resolution = 256;
-		float intensity = 1.0;
-		RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
-		Color ambient_color;
-		float ambient_color_energy = 1.0;
-		float max_distance = 0;
-		Vector3 extents = Vector3(1, 1, 1);
-		Vector3 origin_offset;
-		bool interior = false;
-		bool box_projection = false;
-		bool enable_shadows = false;
-		uint32_t cull_mask = (1 << 20) - 1;
-		float mesh_lod_threshold = 0.01;
-
-		Dependency dependency;
-	};
-
-	mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
-
 	/* VOXEL GI */
 
 	struct VoxelGI {
@@ -594,116 +183,6 @@ private:
 
 	mutable RID_Owner<VoxelGI, true> voxel_gi_owner;
 
-	/* REFLECTION PROBE */
-
-	struct Lightmap {
-		RID light_texture;
-		bool uses_spherical_harmonics = false;
-		bool interior = false;
-		AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
-		int32_t array_index = -1; //unassigned
-		PackedVector3Array points;
-		PackedColorArray point_sh;
-		PackedInt32Array tetrahedra;
-		PackedInt32Array bsp_tree;
-
-		struct BSP {
-			static const int32_t EMPTY_LEAF = INT32_MIN;
-			float plane[4];
-			int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
-		};
-
-		Dependency dependency;
-	};
-
-	bool using_lightmap_array; //high end uses this
-	/* for high end */
-
-	Vector<RID> lightmap_textures;
-
-	uint64_t lightmap_array_version = 0;
-
-	mutable RID_Owner<Lightmap, true> lightmap_owner;
-
-	float lightmap_probe_capture_update_speed = 4;
-
-	/* RENDER TARGET */
-
-	struct RenderTarget {
-		Size2i size;
-		uint32_t view_count;
-		RID framebuffer;
-		RID color;
-
-		//used for retrieving from CPU
-		RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
-		RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
-		Image::Format image_format = Image::FORMAT_L8;
-
-		bool flags[RENDER_TARGET_FLAG_MAX];
-
-		bool sdf_enabled = false;
-
-		RID backbuffer; //used for effects
-		RID backbuffer_fb;
-		RID backbuffer_mipmap0;
-
-		Vector<RID> backbuffer_mipmaps;
-
-		RID framebuffer_uniform_set;
-		RID backbuffer_uniform_set;
-
-		RID sdf_buffer_write;
-		RID sdf_buffer_write_fb;
-		RID sdf_buffer_process[2];
-		RID sdf_buffer_read;
-		RID sdf_buffer_process_uniform_sets[2];
-		RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
-		RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
-		Size2i process_size;
-
-		//texture generated for this owner (nor RD).
-		RID texture;
-		bool was_used;
-
-		//clear request
-		bool clear_requested;
-		Color clear_color;
-	};
-
-	mutable RID_Owner<RenderTarget> render_target_owner;
-
-	void _clear_render_target(RenderTarget *rt);
-	void _update_render_target(RenderTarget *rt);
-	void _create_render_target_backbuffer(RenderTarget *rt);
-	void _render_target_allocate_sdf(RenderTarget *rt);
-	void _render_target_clear_sdf(RenderTarget *rt);
-	Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
-
-	struct RenderTargetSDF {
-		enum {
-			SHADER_LOAD,
-			SHADER_LOAD_SHRINK,
-			SHADER_PROCESS,
-			SHADER_PROCESS_OPTIMIZED,
-			SHADER_STORE,
-			SHADER_STORE_SHRINK,
-			SHADER_MAX
-		};
-
-		struct PushConstant {
-			int32_t size[2];
-			int32_t stride;
-			int32_t shift;
-			int32_t base_size[2];
-			int32_t pad[2];
-		};
-
-		CanvasSdfShaderRD shader;
-		RID shader_version;
-		RID pipelines[SHADER_MAX];
-	} rt_sdf;
-
 	/* EFFECTS */
 
 	EffectsRD *effects = nullptr;
@@ -711,185 +190,6 @@ private:
 public:
 	//internal usage
 
-	_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
-		return default_rd_samplers[p_filter][p_repeat];
-	}
-	_FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
-		return custom_rd_samplers[p_filter][p_repeat];
-	}
-
-	void sampler_rd_configure_custom(float mipmap_bias);
-
-	void sampler_rd_set_default(float p_mipmap_bias);
-
-	/* Light API */
-
-	void _light_initialize(RID p_rid, RS::LightType p_type);
-
-	RID directional_light_allocate();
-	void directional_light_initialize(RID p_light);
-
-	RID omni_light_allocate();
-	void omni_light_initialize(RID p_light);
-
-	RID spot_light_allocate();
-	void spot_light_initialize(RID p_light);
-
-	void light_set_color(RID p_light, const Color &p_color);
-	void light_set_param(RID p_light, RS::LightParam p_param, float p_value);
-	void light_set_shadow(RID p_light, bool p_enabled);
-	void light_set_projector(RID p_light, RID p_texture);
-	void light_set_negative(RID p_light, bool p_enable);
-	void light_set_cull_mask(RID p_light, uint32_t p_mask);
-	void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length);
-	void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled);
-	void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode);
-	void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade);
-
-	void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode);
-
-	void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode);
-	void light_directional_set_blend_splits(RID p_light, bool p_enable);
-	bool light_directional_get_blend_splits(RID p_light) const;
-	void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode);
-	RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const;
-
-	RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
-	RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
-
-	_FORCE_INLINE_ RS::LightType light_get_type(RID p_light) const {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
-		return light->type;
-	}
-	AABB light_get_aabb(RID p_light) const;
-
-	_FORCE_INLINE_ float light_get_param(RID p_light, RS::LightParam p_param) {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, 0);
-
-		return light->param[p_param];
-	}
-
-	_FORCE_INLINE_ RID light_get_projector(RID p_light) {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, RID());
-
-		return light->projector;
-	}
-
-	_FORCE_INLINE_ Color light_get_color(RID p_light) {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, Color());
-
-		return light->color;
-	}
-
-	_FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, 0);
-
-		return light->cull_mask;
-	}
-
-	_FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) {
-		const Light *light = light_owner.get_or_null(p_light);
-		return light->distance_fade;
-	}
-
-	_FORCE_INLINE_ float light_get_distance_fade_begin(RID p_light) {
-		const Light *light = light_owner.get_or_null(p_light);
-		return light->distance_fade_begin;
-	}
-
-	_FORCE_INLINE_ float light_get_distance_fade_shadow(RID p_light) {
-		const Light *light = light_owner.get_or_null(p_light);
-		return light->distance_fade_shadow;
-	}
-
-	_FORCE_INLINE_ float light_get_distance_fade_length(RID p_light) {
-		const Light *light = light_owner.get_or_null(p_light);
-		return light->distance_fade_length;
-	}
-
-	_FORCE_INLINE_ bool light_has_shadow(RID p_light) const {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
-		return light->shadow;
-	}
-
-	_FORCE_INLINE_ bool light_has_projector(RID p_light) const {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
-		return light_owner.owns(light->projector);
-	}
-
-	_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
-		return light->negative;
-	}
-
-	_FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, 0.0);
-
-		return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
-	}
-
-	_FORCE_INLINE_ float light_get_shadow_volumetric_fog_fade(RID p_light) const {
-		const Light *light = light_owner.get_or_null(p_light);
-		ERR_FAIL_COND_V(!light, 0.0);
-
-		return light->param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE];
-	}
-
-	RS::LightBakeMode light_get_bake_mode(RID p_light);
-	uint32_t light_get_max_sdfgi_cascade(RID p_light);
-	uint64_t light_get_version(RID p_light) const;
-
-	/* PROBE API */
-
-	RID reflection_probe_allocate();
-	void reflection_probe_initialize(RID p_reflection_probe);
-
-	void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode);
-	void reflection_probe_set_intensity(RID p_probe, float p_intensity);
-	void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode);
-	void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color);
-	void reflection_probe_set_ambient_energy(RID p_probe, float p_energy);
-	void reflection_probe_set_max_distance(RID p_probe, float p_distance);
-	void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents);
-	void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset);
-	void reflection_probe_set_as_interior(RID p_probe, bool p_enable);
-	void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
-	void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
-	void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
-	void reflection_probe_set_resolution(RID p_probe, int p_resolution);
-	void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio);
-
-	AABB reflection_probe_get_aabb(RID p_probe) const;
-	RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
-	uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
-	Vector3 reflection_probe_get_extents(RID p_probe) const;
-	Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
-	float reflection_probe_get_origin_max_distance(RID p_probe) const;
-	float reflection_probe_get_mesh_lod_threshold(RID p_probe) const;
-
-	int reflection_probe_get_resolution(RID p_probe) const;
-	bool reflection_probe_renders_shadows(RID p_probe) const;
-
-	float reflection_probe_get_intensity(RID p_probe) const;
-	bool reflection_probe_is_interior(RID p_probe) const;
-	bool reflection_probe_is_box_projection(RID p_probe) const;
-	RS::ReflectionProbeAmbientMode reflection_probe_get_ambient_mode(RID p_probe) const;
-	Color reflection_probe_get_ambient_color(RID p_probe) const;
-	float reflection_probe_get_ambient_color_energy(RID p_probe) const;
-
 	void base_update_dependency(RID p_base, DependencyTracker *p_instance);
 
 	/* VOXEL GI API */
@@ -940,187 +240,6 @@ public:
 
 	RID voxel_gi_get_sdf_texture(RID p_voxel_gi);
 
-	/* LIGHTMAP CAPTURE */
-
-	RID lightmap_allocate();
-	void lightmap_initialize(RID p_lightmap);
-
-	virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics);
-	virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds);
-	virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior);
-	virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree);
-	virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const;
-	virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const;
-	virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const;
-	virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const;
-	virtual AABB lightmap_get_aabb(RID p_lightmap) const;
-	virtual bool lightmap_is_interior(RID p_lightmap) const;
-	virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh);
-	virtual void lightmap_set_probe_capture_update_speed(float p_speed);
-	_FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const {
-		return lightmap_probe_capture_update_speed;
-	}
-	_FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const {
-		const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
-		ERR_FAIL_COND_V(!lm, RID());
-		return lm->light_texture;
-	}
-	_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
-		ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
-		const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
-		return lm->array_index;
-	}
-	_FORCE_INLINE_ bool lightmap_uses_spherical_harmonics(RID p_lightmap) const {
-		ERR_FAIL_COND_V(!using_lightmap_array, false); //only for arrays
-		const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
-		return lm->uses_spherical_harmonics;
-	}
-	_FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
-		ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
-		return lightmap_array_version;
-	}
-
-	_FORCE_INLINE_ int lightmap_array_get_size() const {
-		ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
-		return lightmap_textures.size();
-	}
-
-	_FORCE_INLINE_ const Vector<RID> &lightmap_array_get_textures() const {
-		ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays
-		return lightmap_textures;
-	}
-
-	/* PARTICLES */
-
-	RID particles_allocate();
-	void particles_initialize(RID p_particles_collision);
-
-	void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode);
-	void particles_set_emitting(RID p_particles, bool p_emitting);
-	void particles_set_amount(RID p_particles, int p_amount);
-	void particles_set_lifetime(RID p_particles, double p_lifetime);
-	void particles_set_one_shot(RID p_particles, bool p_one_shot);
-	void particles_set_pre_process_time(RID p_particles, double p_time);
-	void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio);
-	void particles_set_randomness_ratio(RID p_particles, real_t p_ratio);
-	void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb);
-	void particles_set_speed_scale(RID p_particles, double p_scale);
-	void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
-	void particles_set_process_material(RID p_particles, RID p_material);
-	RID particles_get_process_material(RID p_particles) const;
-
-	void particles_set_fixed_fps(RID p_particles, int p_fps);
-	void particles_set_interpolate(RID p_particles, bool p_enable);
-	void particles_set_fractional_delta(RID p_particles, bool p_enable);
-	void particles_set_collision_base_size(RID p_particles, real_t p_size);
-	void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align);
-
-	void particles_set_trails(RID p_particles, bool p_enable, double p_length);
-	void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses);
-
-	void particles_restart(RID p_particles);
-	void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
-
-	void particles_set_subemitter(RID p_particles, RID p_subemitter_particles);
-
-	void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order);
-
-	void particles_set_draw_passes(RID p_particles, int p_count);
-	void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh);
-
-	void particles_request_process(RID p_particles);
-	AABB particles_get_current_aabb(RID p_particles);
-	AABB particles_get_aabb(RID p_particles) const;
-
-	void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform);
-
-	bool particles_get_emitting(RID p_particles);
-	int particles_get_draw_passes(RID p_particles) const;
-	RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const;
-
-	void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis);
-
-	virtual bool particles_is_inactive(RID p_particles) const;
-
-	_FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
-		Particles *particles = particles_owner.get_or_null(p_particles);
-		ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D);
-		return particles->mode;
-	}
-
-	_FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) {
-		Particles *particles = particles_owner.get_or_null(p_particles);
-		ERR_FAIL_COND_V(!particles, 0);
-
-		if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
-			r_trail_divisor = particles->trail_bind_poses.size();
-		} else {
-			r_trail_divisor = 1;
-		}
-
-		return particles->amount * r_trail_divisor;
-	}
-
-	_FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
-		Particles *particles = particles_owner.get_or_null(p_particles);
-		ERR_FAIL_COND_V(!particles, 0);
-
-		return particles->has_collision_cache;
-	}
-
-	_FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
-		Particles *particles = particles_owner.get_or_null(p_particles);
-		ERR_FAIL_COND_V(!particles, false);
-
-		return particles->use_local_coords;
-	}
-
-	_FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) {
-		Particles *particles = particles_owner.get_or_null(p_particles);
-		ERR_FAIL_COND_V(!particles, RID());
-		if (particles->particles_transforms_buffer_uniform_set.is_null()) {
-			_particles_update_buffers(particles);
-
-			Vector<RD::Uniform> uniforms;
-
-			{
-				RD::Uniform u;
-				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-				u.binding = 0;
-				u.append_id(particles->particle_instance_buffer);
-				uniforms.push_back(u);
-			}
-
-			particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
-		}
-
-		return particles->particles_transforms_buffer_uniform_set;
-	}
-
-	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance);
-	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance);
-	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture);
-
-	/* PARTICLES COLLISION */
-
-	RID particles_collision_allocate();
-	void particles_collision_initialize(RID p_particles_collision);
-
-	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type);
-	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask);
-	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius); //for spheres
-	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents); //for non-spheres
-	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength);
-	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality);
-	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve);
-	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture); //for SDF and vector field, heightfield is dynamic
-	virtual void particles_collision_height_field_update(RID p_particles_collision); //for SDF and vector field
-	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution); //for SDF and vector field
-	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const;
-	virtual Vector3 particles_collision_get_extents(RID p_particles_collision) const;
-	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
-	RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
-
 	/* FOG VOLUMES */
 
 	virtual RID fog_volume_allocate();
@@ -1144,53 +263,6 @@ public:
 	virtual AABB visibility_notifier_get_aabb(RID p_notifier) const;
 	virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred);
 
-	//used from 2D and 3D
-	virtual RID particles_collision_instance_create(RID p_collision);
-	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform);
-	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active);
-
-	/* RENDER TARGET API */
-
-	RID render_target_create();
-	void render_target_set_position(RID p_render_target, int p_x, int p_y);
-	void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count);
-	RID render_target_get_texture(RID p_render_target);
-	void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
-	void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
-	bool render_target_was_used(RID p_render_target);
-	void render_target_set_as_unused(RID p_render_target);
-	void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
-	void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
-	void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
-
-	RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
-
-	virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color);
-	virtual bool render_target_is_clear_requested(RID p_render_target);
-	virtual Color render_target_get_clear_request_color(RID p_render_target);
-	virtual void render_target_disable_clear_request(RID p_render_target);
-	virtual void render_target_do_clear_request(RID p_render_target);
-
-	virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale);
-	RID render_target_get_sdf_texture(RID p_render_target);
-	RID render_target_get_sdf_framebuffer(RID p_render_target);
-	void render_target_sdf_process(RID p_render_target);
-	virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const;
-	void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled);
-	bool render_target_is_sdf_enabled(RID p_render_target) const;
-
-	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_backbuffer(RID p_render_target);
-	RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
-
-	RID render_target_get_framebuffer_uniform_set(RID p_render_target);
-	RID render_target_get_backbuffer_uniform_set(RID p_render_target);
-
-	void render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set);
-	void render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set);
-
 	RS::InstanceType get_base_type(RID p_rid) const;
 
 	bool free(RID p_rid);

+ 0 - 235
servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp

@@ -1,235 +0,0 @@
-/*************************************************************************/
-/*  canvas_texture_storage.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 "canvas_texture_storage.h"
-#include "texture_storage.h"
-
-// Until we move things into their own storage classes, also include our old class
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-
-using namespace RendererRD;
-
-///////////////////////////////////////////////////////////////////////////
-// CanvasTexture
-
-void CanvasTexture::clear_sets() {
-	if (cleared_cache) {
-		return;
-	}
-	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
-		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
-			if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) {
-				RD::get_singleton()->free(uniform_sets[i][j]);
-				uniform_sets[i][j] = RID();
-			}
-		}
-	}
-	cleared_cache = true;
-}
-
-CanvasTexture::~CanvasTexture() {
-	clear_sets();
-}
-
-///////////////////////////////////////////////////////////////////////////
-// CanvasTextureStorage
-
-CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr;
-
-CanvasTextureStorage *CanvasTextureStorage::get_singleton() {
-	return singleton;
-}
-
-CanvasTextureStorage::CanvasTextureStorage() {
-	singleton = this;
-}
-
-CanvasTextureStorage::~CanvasTextureStorage() {
-	singleton = nullptr;
-}
-
-RID CanvasTextureStorage::canvas_texture_allocate() {
-	return canvas_texture_owner.allocate_rid();
-}
-
-void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) {
-	canvas_texture_owner.initialize_rid(p_rid);
-}
-
-void CanvasTextureStorage::canvas_texture_free(RID p_rid) {
-	canvas_texture_owner.free(p_rid);
-}
-
-void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
-	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
-	ERR_FAIL_NULL(ct);
-
-	switch (p_channel) {
-		case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
-			ct->diffuse = p_texture;
-		} break;
-		case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
-			ct->normal_map = p_texture;
-		} break;
-		case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
-			ct->specular = p_texture;
-		} break;
-	}
-
-	ct->clear_sets();
-}
-
-void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
-	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
-	ERR_FAIL_NULL(ct);
-
-	ct->specular_color.r = p_specular_color.r;
-	ct->specular_color.g = p_specular_color.g;
-	ct->specular_color.b = p_specular_color.b;
-	ct->specular_color.a = p_shininess;
-	ct->clear_sets();
-}
-
-void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
-	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
-	ERR_FAIL_NULL(ct);
-
-	ct->texture_filter = p_filter;
-	ct->clear_sets();
-}
-
-void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
-	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
-	ERR_FAIL_NULL(ct);
-	ct->texture_repeat = p_repeat;
-	ct->clear_sets();
-}
-
-bool CanvasTextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
-	RendererStorageRD *storage = RendererStorageRD::base_singleton;
-
-	CanvasTexture *ct = nullptr;
-	TextureStorage *texture_storage = TextureStorage::get_singleton();
-	Texture *t = texture_storage->get_texture(p_texture);
-
-	// TODO once we have our texture storage split off we'll look into moving this code into canvas_texture
-
-	if (t) {
-		//regular texture
-		if (!t->canvas_texture) {
-			t->canvas_texture = memnew(CanvasTexture);
-			t->canvas_texture->diffuse = p_texture;
-		}
-
-		ct = t->canvas_texture;
-	} else {
-		ct = get_canvas_texture(p_texture);
-	}
-
-	if (!ct) {
-		return false; //invalid texture RID
-	}
-
-	RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter;
-	ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false);
-
-	RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
-	ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
-
-	RID uniform_set = ct->uniform_sets[filter][repeat];
-	if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
-		//create and update
-		Vector<RD::Uniform> uniforms;
-		{ //diffuse
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			u.binding = 0;
-
-			t = texture_storage->get_texture(ct->diffuse);
-			if (!t) {
-				u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
-				ct->size_cache = Size2i(1, 1);
-			} else {
-				u.append_id(t->rd_texture);
-				ct->size_cache = Size2i(t->width_2d, t->height_2d);
-			}
-			uniforms.push_back(u);
-		}
-		{ //normal
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			u.binding = 1;
-
-			t = texture_storage->get_texture(ct->normal_map);
-			if (!t) {
-				u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
-				ct->use_normal_cache = false;
-			} else {
-				u.append_id(t->rd_texture);
-				ct->use_normal_cache = true;
-			}
-			uniforms.push_back(u);
-		}
-		{ //specular
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			u.binding = 2;
-
-			t = texture_storage->get_texture(ct->specular);
-			if (!t) {
-				u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
-				ct->use_specular_cache = false;
-			} else {
-				u.append_id(t->rd_texture);
-				ct->use_specular_cache = true;
-			}
-			uniforms.push_back(u);
-		}
-		{ //sampler
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.binding = 3;
-			u.append_id(storage->sampler_rd_get_default(filter, repeat));
-			uniforms.push_back(u);
-		}
-
-		uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
-		ct->uniform_sets[filter][repeat] = uniform_set;
-		ct->cleared_cache = false;
-	}
-
-	r_uniform_set = uniform_set;
-	r_size = ct->size_cache;
-	r_specular_shininess = ct->specular_color;
-	r_use_normal = ct->use_normal_cache;
-	r_use_specular = ct->use_specular_cache;
-
-	return true;
-}

+ 0 - 90
servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h

@@ -1,90 +0,0 @@
-/*************************************************************************/
-/*  canvas_texture_storage.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 CANVAS_TEXTURE_STORAGE_RD_H
-#define CANVAS_TEXTURE_STORAGE_RD_H
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
-
-namespace RendererRD {
-
-class CanvasTexture {
-public:
-	RID diffuse;
-	RID normal_map;
-	RID specular;
-	Color specular_color = Color(1, 1, 1, 1);
-	float shininess = 1.0;
-
-	RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
-	RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
-	RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
-
-	Size2i size_cache = Size2i(1, 1);
-	bool use_normal_cache = false;
-	bool use_specular_cache = false;
-	bool cleared_cache = true;
-
-	void clear_sets();
-	~CanvasTexture();
-};
-
-class CanvasTextureStorage : public RendererCanvasTextureStorage {
-private:
-	static CanvasTextureStorage *singleton;
-
-	RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner;
-
-public:
-	static CanvasTextureStorage *get_singleton();
-
-	CanvasTextureStorage();
-	virtual ~CanvasTextureStorage();
-
-	CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
-	bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
-
-	virtual RID canvas_texture_allocate() override;
-	virtual void canvas_texture_initialize(RID p_rid) override;
-	virtual void canvas_texture_free(RID p_rid) override;
-
-	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
-	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
-
-	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
-	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
-
-	bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);
-};
-
-} // namespace RendererRD
-
-#endif // !CANVAS_TEXTURE_STORAGE_RD_H

+ 0 - 437
servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp

@@ -1,437 +0,0 @@
-/*************************************************************************/
-/*  decal_atlas_storage.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 "decal_atlas_storage.h"
-#include "texture_storage.h"
-
-// Should be able to remove this once we move effects into their own file and include the correct effects
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-
-using namespace RendererRD;
-
-DecalAtlasStorage *DecalAtlasStorage::singleton = nullptr;
-
-DecalAtlasStorage *DecalAtlasStorage::get_singleton() {
-	return singleton;
-}
-
-DecalAtlasStorage::DecalAtlasStorage() {
-	singleton = this;
-
-	{ // default atlas texture
-		RD::TextureFormat tformat;
-		tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
-		tformat.width = 4;
-		tformat.height = 4;
-		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
-		tformat.texture_type = RD::TEXTURE_TYPE_2D;
-
-		Vector<uint8_t> pv;
-		pv.resize(16 * 4);
-
-		for (int i = 0; i < 16; i++) {
-			pv.set(i * 4 + 0, 0);
-			pv.set(i * 4 + 1, 0);
-			pv.set(i * 4 + 2, 0);
-			pv.set(i * 4 + 3, 255);
-		}
-
-		{
-			//take the chance and initialize decal atlas to something
-			Vector<Vector<uint8_t>> vpv;
-			vpv.push_back(pv);
-			decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
-			decal_atlas.texture_srgb = decal_atlas.texture;
-		}
-	}
-}
-
-DecalAtlasStorage::~DecalAtlasStorage() {
-	if (decal_atlas.textures.size()) {
-		ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas.");
-	}
-
-	if (decal_atlas.texture.is_valid()) {
-		RD::get_singleton()->free(decal_atlas.texture);
-	}
-
-	singleton = nullptr;
-}
-
-RID DecalAtlasStorage::decal_atlas_get_texture() const {
-	return decal_atlas.texture;
-}
-
-RID DecalAtlasStorage::decal_atlas_get_texture_srgb() const {
-	return decal_atlas.texture_srgb;
-}
-
-RID DecalAtlasStorage::decal_allocate() {
-	return decal_owner.allocate_rid();
-}
-
-void DecalAtlasStorage::decal_initialize(RID p_decal) {
-	decal_owner.initialize_rid(p_decal, Decal());
-}
-
-void DecalAtlasStorage::decal_free(RID p_rid) {
-	Decal *decal = decal_owner.get_or_null(p_rid);
-	for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) {
-		if (decal->textures[i].is_valid() && TextureStorage::get_singleton()->owns_texture(decal->textures[i])) {
-			texture_remove_from_decal_atlas(decal->textures[i]);
-		}
-	}
-	decal->dependency.deleted_notify(p_rid);
-	decal_owner.free(p_rid);
-}
-
-void DecalAtlasStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND(!decal);
-	decal->extents = p_extents;
-	decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
-}
-
-void DecalAtlasStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND(!decal);
-	ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX);
-
-	if (decal->textures[p_type] == p_texture) {
-		return;
-	}
-
-	ERR_FAIL_COND(p_texture.is_valid() && !TextureStorage::get_singleton()->owns_texture(p_texture));
-
-	if (decal->textures[p_type].is_valid() && TextureStorage::get_singleton()->owns_texture(decal->textures[p_type])) {
-		texture_remove_from_decal_atlas(decal->textures[p_type]);
-	}
-
-	decal->textures[p_type] = p_texture;
-
-	if (decal->textures[p_type].is_valid()) {
-		texture_add_to_decal_atlas(decal->textures[p_type]);
-	}
-
-	decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_DECAL);
-}
-
-void DecalAtlasStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND(!decal);
-	decal->emission_energy = p_energy;
-}
-
-void DecalAtlasStorage::decal_set_albedo_mix(RID p_decal, float p_mix) {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND(!decal);
-	decal->albedo_mix = p_mix;
-}
-
-void DecalAtlasStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND(!decal);
-	decal->modulate = p_modulate;
-}
-
-void DecalAtlasStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND(!decal);
-	decal->cull_mask = p_layers;
-	decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
-}
-
-void DecalAtlasStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND(!decal);
-	decal->distance_fade = p_enabled;
-	decal->distance_fade_begin = p_begin;
-	decal->distance_fade_length = p_length;
-}
-
-void DecalAtlasStorage::decal_set_fade(RID p_decal, float p_above, float p_below) {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND(!decal);
-	decal->upper_fade = p_above;
-	decal->lower_fade = p_below;
-}
-
-void DecalAtlasStorage::decal_set_normal_fade(RID p_decal, float p_fade) {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND(!decal);
-	decal->normal_fade = p_fade;
-}
-
-void DecalAtlasStorage::decal_atlas_mark_dirty_on_texture(RID p_texture) {
-	if (decal_atlas.textures.has(p_texture)) {
-		//belongs to decal atlas..
-
-		decal_atlas.dirty = true; //mark it dirty since it was most likely modified
-	}
-}
-
-void DecalAtlasStorage::decal_atlas_remove_texture(RID p_texture) {
-	if (decal_atlas.textures.has(p_texture)) {
-		decal_atlas.textures.erase(p_texture);
-		//there is not much a point of making it dirty, just let it be.
-	}
-}
-
-AABB DecalAtlasStorage::decal_get_aabb(RID p_decal) const {
-	Decal *decal = decal_owner.get_or_null(p_decal);
-	ERR_FAIL_COND_V(!decal, AABB());
-
-	return AABB(-decal->extents, decal->extents * 2.0);
-}
-
-void DecalAtlasStorage::update_decal_atlas() {
-	EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
-
-	if (!decal_atlas.dirty) {
-		return; //nothing to do
-	}
-
-	decal_atlas.dirty = false;
-
-	if (decal_atlas.texture.is_valid()) {
-		RD::get_singleton()->free(decal_atlas.texture);
-		decal_atlas.texture = RID();
-		decal_atlas.texture_srgb = RID();
-		decal_atlas.texture_mipmaps.clear();
-	}
-
-	int border = 1 << decal_atlas.mipmaps;
-
-	if (decal_atlas.textures.size()) {
-		//generate atlas
-		Vector<DecalAtlas::SortItem> itemsv;
-		itemsv.resize(decal_atlas.textures.size());
-		int base_size = 8;
-		const RID *K = nullptr;
-
-		int idx = 0;
-		while ((K = decal_atlas.textures.next(K))) {
-			DecalAtlas::SortItem &si = itemsv.write[idx];
-
-			Texture *src_tex = TextureStorage::get_singleton()->get_texture(*K);
-
-			si.size.width = (src_tex->width / border) + 1;
-			si.size.height = (src_tex->height / border) + 1;
-			si.pixel_size = Size2i(src_tex->width, src_tex->height);
-
-			if (base_size < si.size.width) {
-				base_size = nearest_power_of_2_templated(si.size.width);
-			}
-
-			si.texture = *K;
-			idx++;
-		}
-
-		//sort items by size
-		itemsv.sort();
-
-		//attempt to create atlas
-		int item_count = itemsv.size();
-		DecalAtlas::SortItem *items = itemsv.ptrw();
-
-		int atlas_height = 0;
-
-		while (true) {
-			Vector<int> v_offsetsv;
-			v_offsetsv.resize(base_size);
-
-			int *v_offsets = v_offsetsv.ptrw();
-			memset(v_offsets, 0, sizeof(int) * base_size);
-
-			int max_height = 0;
-
-			for (int i = 0; i < item_count; i++) {
-				//best fit
-				DecalAtlas::SortItem &si = items[i];
-				int best_idx = -1;
-				int best_height = 0x7FFFFFFF;
-				for (int j = 0; j <= base_size - si.size.width; j++) {
-					int height = 0;
-					for (int k = 0; k < si.size.width; k++) {
-						int h = v_offsets[k + j];
-						if (h > height) {
-							height = h;
-							if (height > best_height) {
-								break; //already bad
-							}
-						}
-					}
-
-					if (height < best_height) {
-						best_height = height;
-						best_idx = j;
-					}
-				}
-
-				//update
-				for (int k = 0; k < si.size.width; k++) {
-					v_offsets[k + best_idx] = best_height + si.size.height;
-				}
-
-				si.pos.x = best_idx;
-				si.pos.y = best_height;
-
-				if (si.pos.y + si.size.height > max_height) {
-					max_height = si.pos.y + si.size.height;
-				}
-			}
-
-			if (max_height <= base_size * 2) {
-				atlas_height = max_height;
-				break; //good ratio, break;
-			}
-
-			base_size *= 2;
-		}
-
-		decal_atlas.size.width = base_size * border;
-		decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border);
-
-		for (int i = 0; i < item_count; i++) {
-			DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture);
-			t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2);
-			t->uv_rect.size = items[i].pixel_size;
-
-			t->uv_rect.position /= Size2(decal_atlas.size);
-			t->uv_rect.size /= Size2(decal_atlas.size);
-		}
-	} else {
-		//use border as size, so it at least has enough mipmaps
-		decal_atlas.size.width = border;
-		decal_atlas.size.height = border;
-	}
-
-	//blit textures
-
-	RD::TextureFormat tformat;
-	tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
-	tformat.width = decal_atlas.size.width;
-	tformat.height = decal_atlas.size.height;
-	tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
-	tformat.texture_type = RD::TEXTURE_TYPE_2D;
-	tformat.mipmaps = decal_atlas.mipmaps;
-	tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM);
-	tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB);
-
-	decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
-	RD::get_singleton()->texture_clear(decal_atlas.texture, Color(0, 0, 0, 0), 0, decal_atlas.mipmaps, 0, 1);
-
-	{
-		//create the framebuffer
-
-		Size2i s = decal_atlas.size;
-
-		for (int i = 0; i < decal_atlas.mipmaps; i++) {
-			DecalAtlas::MipMap mm;
-			mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i);
-			Vector<RID> fb;
-			fb.push_back(mm.texture);
-			mm.fb = RD::get_singleton()->framebuffer_create(fb);
-			mm.size = s;
-			decal_atlas.texture_mipmaps.push_back(mm);
-
-			s.width = MAX(1, s.width >> 1);
-			s.height = MAX(1, s.height >> 1);
-		}
-		{
-			//create the SRGB variant
-			RD::TextureView rd_view;
-			rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB;
-			decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture);
-		}
-	}
-
-	RID prev_texture;
-	for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) {
-		const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i];
-
-		Color clear_color(0, 0, 0, 0);
-
-		if (decal_atlas.textures.size()) {
-			if (i == 0) {
-				Vector<Color> cc;
-				cc.push_back(clear_color);
-
-				RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
-
-				const RID *K = nullptr;
-				while ((K = decal_atlas.textures.next(K))) {
-					DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
-					Texture *src_tex = TextureStorage::get_singleton()->get_texture(*K);
-					effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
-				}
-
-				RD::get_singleton()->draw_list_end();
-
-				prev_texture = mm.texture;
-			} else {
-				effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
-				prev_texture = mm.texture;
-			}
-		} else {
-			RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1);
-		}
-	}
-}
-
-void DecalAtlasStorage::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
-	if (!decal_atlas.textures.has(p_texture)) {
-		DecalAtlas::Texture t;
-		t.users = 1;
-		t.panorama_to_dp_users = p_panorama_to_dp ? 1 : 0;
-		decal_atlas.textures[p_texture] = t;
-		decal_atlas.dirty = true;
-	} else {
-		DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
-		t->users++;
-		if (p_panorama_to_dp) {
-			t->panorama_to_dp_users++;
-		}
-	}
-}
-
-void DecalAtlasStorage::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
-	DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
-	ERR_FAIL_COND(!t);
-	t->users--;
-	if (p_panorama_to_dp) {
-		ERR_FAIL_COND(t->panorama_to_dp_users == 0);
-		t->panorama_to_dp_users--;
-	}
-	if (t->users == 0) {
-		decal_atlas.textures.erase(p_texture);
-		//do not mark it dirty, there is no need to since it remains working
-	}
-}

+ 0 - 211
servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h

@@ -1,211 +0,0 @@
-/*************************************************************************/
-/*  decal_atlas_storage.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 DECAL_ATLAS_STORAGE_RD_H
-#define DECAL_ATLAS_STORAGE_RD_H
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/renderer_storage.h"
-#include "servers/rendering/storage/decal_atlas_storage.h"
-
-namespace RendererRD {
-
-struct DecalAtlas {
-	struct Texture {
-		int panorama_to_dp_users;
-		int users;
-		Rect2 uv_rect;
-	};
-
-	struct SortItem {
-		RID texture;
-		Size2i pixel_size;
-		Size2i size;
-		Point2i pos;
-
-		bool operator<(const SortItem &p_item) const {
-			//sort larger to smaller
-			if (size.height == p_item.size.height) {
-				return size.width > p_item.size.width;
-			} else {
-				return size.height > p_item.size.height;
-			}
-		}
-	};
-
-	HashMap<RID, Texture> textures;
-	bool dirty = true;
-	int mipmaps = 5;
-
-	RID texture;
-	RID texture_srgb;
-	struct MipMap {
-		RID fb;
-		RID texture;
-		Size2i size;
-	};
-	Vector<MipMap> texture_mipmaps;
-
-	Size2i size;
-};
-
-struct Decal {
-	Vector3 extents = Vector3(1, 1, 1);
-	RID textures[RS::DECAL_TEXTURE_MAX];
-	float emission_energy = 1.0;
-	float albedo_mix = 1.0;
-	Color modulate = Color(1, 1, 1, 1);
-	uint32_t cull_mask = (1 << 20) - 1;
-	float upper_fade = 0.3;
-	float lower_fade = 0.3;
-	bool distance_fade = false;
-	float distance_fade_begin = 10;
-	float distance_fade_length = 1;
-	float normal_fade = 0.0;
-
-	RendererStorage::Dependency dependency;
-};
-
-class DecalAtlasStorage : public RendererDecalAtlasStorage {
-private:
-	static DecalAtlasStorage *singleton;
-
-	DecalAtlas decal_atlas;
-
-	mutable RID_Owner<Decal, true> decal_owner;
-
-public:
-	static DecalAtlasStorage *get_singleton();
-
-	void update_decal_atlas();
-
-	DecalAtlasStorage();
-	virtual ~DecalAtlasStorage();
-
-	Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); };
-	bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); };
-
-	RID decal_atlas_get_texture() const;
-	RID decal_atlas_get_texture_srgb() const;
-	_FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
-		DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
-		if (!t) {
-			return Rect2();
-		}
-
-		return t->uv_rect;
-	}
-
-	virtual RID decal_allocate() override;
-	virtual void decal_initialize(RID p_decal) override;
-	virtual void decal_free(RID p_rid) override;
-
-	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
-	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
-	virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
-	virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
-	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
-	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
-	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
-	virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
-	virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
-
-	void decal_atlas_mark_dirty_on_texture(RID p_texture);
-	void decal_atlas_remove_texture(RID p_texture);
-
-	virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
-	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
-
-	_FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->extents;
-	}
-
-	_FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->textures[p_texture];
-	}
-
-	_FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->modulate;
-	}
-
-	_FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->emission_energy;
-	}
-
-	_FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->albedo_mix;
-	}
-
-	_FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->cull_mask;
-	}
-
-	_FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->upper_fade;
-	}
-
-	_FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->lower_fade;
-	}
-
-	_FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->normal_fade;
-	}
-
-	_FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->distance_fade;
-	}
-
-	_FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->distance_fade_begin;
-	}
-
-	_FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
-		const Decal *decal = decal_owner.get_or_null(p_decal);
-		return decal->distance_fade_length;
-	}
-
-	virtual AABB decal_get_aabb(RID p_decal) const override;
-};
-
-} // namespace RendererRD
-
-#endif // !DECAL_ATLAS_STORAGE_RD_H

+ 788 - 0
servers/rendering/renderer_rd/storage_rd/light_storage.cpp

@@ -0,0 +1,788 @@
+/*************************************************************************/
+/*  light_storage.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 "light_storage.h"
+#include "core/config/project_settings.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+LightStorage *LightStorage::singleton = nullptr;
+
+LightStorage *LightStorage::get_singleton() {
+	return singleton;
+}
+
+LightStorage::LightStorage() {
+	singleton = this;
+
+	TextureStorage *texture_storage = TextureStorage::get_singleton();
+
+	using_lightmap_array = true; // high end
+	if (using_lightmap_array) {
+		uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
+
+		if (textures_per_stage <= 256) {
+			lightmap_textures.resize(32);
+		} else {
+			lightmap_textures.resize(1024);
+		}
+
+		for (int i = 0; i < lightmap_textures.size(); i++) {
+			lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+		}
+	}
+
+	lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");
+}
+
+LightStorage::~LightStorage() {
+	singleton = nullptr;
+}
+
+/* LIGHT */
+
+void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
+	Light light;
+	light.type = p_type;
+
+	light.param[RS::LIGHT_PARAM_ENERGY] = 1.0;
+	light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
+	light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
+	light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
+	light.param[RS::LIGHT_PARAM_SIZE] = 0.0;
+	light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0;
+	light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
+	light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0;
+	light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
+	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
+	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
+	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
+	light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
+	light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
+	light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
+	light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
+	light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
+	light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
+	light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
+
+	light_owner.initialize_rid(p_light, light);
+}
+
+RID LightStorage::directional_light_allocate() {
+	return light_owner.allocate_rid();
+}
+
+void LightStorage::directional_light_initialize(RID p_light) {
+	_light_initialize(p_light, RS::LIGHT_DIRECTIONAL);
+}
+
+RID LightStorage::omni_light_allocate() {
+	return light_owner.allocate_rid();
+}
+
+void LightStorage::omni_light_initialize(RID p_light) {
+	_light_initialize(p_light, RS::LIGHT_OMNI);
+}
+
+RID LightStorage::spot_light_allocate() {
+	return light_owner.allocate_rid();
+}
+
+void LightStorage::spot_light_initialize(RID p_light) {
+	_light_initialize(p_light, RS::LIGHT_SPOT);
+}
+
+void LightStorage::light_free(RID p_rid) {
+	light_set_projector(p_rid, RID()); //clear projector
+
+	// delete the texture
+	Light *light = light_owner.get_or_null(p_rid);
+	light->dependency.deleted_notify(p_rid);
+	light_owner.free(p_rid);
+}
+
+void LightStorage::light_set_color(RID p_light, const Color &p_color) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->color = p_color;
+}
+
+void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+	ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);
+
+	if (light->param[p_param] == p_value) {
+		return;
+	}
+
+	switch (p_param) {
+		case RS::LIGHT_PARAM_RANGE:
+		case RS::LIGHT_PARAM_SPOT_ANGLE:
+		case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
+		case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
+		case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
+		case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
+		case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
+		case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
+		case RS::LIGHT_PARAM_SHADOW_BIAS: {
+			light->version++;
+			light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+		} break;
+		case RS::LIGHT_PARAM_SIZE: {
+			if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {
+				//changing from no size to size and the opposite
+				light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+			}
+		} break;
+		default: {
+		}
+	}
+
+	light->param[p_param] = p_value;
+}
+
+void LightStorage::light_set_shadow(RID p_light, bool p_enabled) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+	light->shadow = p_enabled;
+
+	light->version++;
+	light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_projector(RID p_light, RID p_texture) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	if (light->projector == p_texture) {
+		return;
+	}
+
+	if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
+		texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+	}
+
+	light->projector = p_texture;
+
+	if (light->type != RS::LIGHT_DIRECTIONAL) {
+		if (light->projector.is_valid()) {
+			texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+		}
+		light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+	}
+}
+
+void LightStorage::light_set_negative(RID p_light, bool p_enable) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->negative = p_enable;
+}
+
+void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->cull_mask = p_mask;
+
+	light->version++;
+	light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->distance_fade = p_enabled;
+	light->distance_fade_begin = p_begin;
+	light->distance_fade_shadow = p_shadow;
+	light->distance_fade_length = p_length;
+}
+
+void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->reverse_cull = p_enabled;
+
+	light->version++;
+	light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->bake_mode = p_bake_mode;
+
+	light->version++;
+	light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->max_sdfgi_cascade = p_cascade;
+
+	light->version++;
+	light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->omni_shadow_mode = p_mode;
+
+	light->version++;
+	light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) {
+	const Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE);
+
+	return light->omni_shadow_mode;
+}
+
+void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->directional_shadow_mode = p_mode;
+	light->version++;
+	light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->directional_blend_splits = p_enable;
+	light->version++;
+	light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+bool LightStorage::light_directional_get_blend_splits(RID p_light) const {
+	const Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND_V(!light, false);
+
+	return light->directional_blend_splits;
+}
+
+void LightStorage::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) {
+	Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->directional_sky_mode = p_mode;
+}
+
+RS::LightDirectionalSkyMode LightStorage::light_directional_get_sky_mode(RID p_light) const {
+	const Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY);
+
+	return light->directional_sky_mode;
+}
+
+RS::LightDirectionalShadowMode LightStorage::light_directional_get_shadow_mode(RID p_light) {
+	const Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
+
+	return light->directional_shadow_mode;
+}
+
+uint32_t LightStorage::light_get_max_sdfgi_cascade(RID p_light) {
+	const Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND_V(!light, 0);
+
+	return light->max_sdfgi_cascade;
+}
+
+RS::LightBakeMode LightStorage::light_get_bake_mode(RID p_light) {
+	const Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED);
+
+	return light->bake_mode;
+}
+
+uint64_t LightStorage::light_get_version(RID p_light) const {
+	const Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND_V(!light, 0);
+
+	return light->version;
+}
+
+AABB LightStorage::light_get_aabb(RID p_light) const {
+	const Light *light = light_owner.get_or_null(p_light);
+	ERR_FAIL_COND_V(!light, AABB());
+
+	switch (light->type) {
+		case RS::LIGHT_SPOT: {
+			float len = light->param[RS::LIGHT_PARAM_RANGE];
+			float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
+			return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
+		};
+		case RS::LIGHT_OMNI: {
+			float r = light->param[RS::LIGHT_PARAM_RANGE];
+			return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
+		};
+		case RS::LIGHT_DIRECTIONAL: {
+			return AABB();
+		};
+	}
+
+	ERR_FAIL_V(AABB());
+}
+
+/* REFLECTION PROBE */
+
+RID LightStorage::reflection_probe_allocate() {
+	return reflection_probe_owner.allocate_rid();
+}
+
+void LightStorage::reflection_probe_initialize(RID p_reflection_probe) {
+	reflection_probe_owner.initialize_rid(p_reflection_probe, ReflectionProbe());
+}
+
+void LightStorage::reflection_probe_free(RID p_rid) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
+	reflection_probe->dependency.deleted_notify(p_rid);
+	reflection_probe_owner.free(p_rid);
+};
+
+void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->update_mode = p_mode;
+	reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->intensity = p_intensity;
+}
+
+void LightStorage::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->ambient_mode = p_mode;
+}
+
+void LightStorage::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->ambient_color = p_color;
+}
+
+void LightStorage::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->ambient_color_energy = p_energy;
+}
+
+void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->max_distance = p_distance;
+
+	reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	if (reflection_probe->extents == p_extents) {
+		return;
+	}
+	reflection_probe->extents = p_extents;
+	reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->origin_offset = p_offset;
+	reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->interior = p_enable;
+	reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->box_projection = p_enable;
+}
+
+void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->enable_shadows = p_enable;
+	reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->cull_mask = p_layers;
+	reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+	ERR_FAIL_COND(p_resolution < 32);
+
+	reflection_probe->resolution = p_resolution;
+}
+
+void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
+	ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->mesh_lod_threshold = p_ratio;
+
+	reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, AABB());
+
+	AABB aabb;
+	aabb.position = -reflection_probe->extents;
+	aabb.size = reflection_probe->extents * 2.0;
+
+	return aabb;
+}
+
+RS::ReflectionProbeUpdateMode LightStorage::reflection_probe_get_update_mode(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS);
+
+	return reflection_probe->update_mode;
+}
+
+uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->cull_mask;
+}
+
+Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+	return reflection_probe->extents;
+}
+
+Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+	return reflection_probe->origin_offset;
+}
+
+bool LightStorage::reflection_probe_renders_shadows(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, false);
+
+	return reflection_probe->enable_shadows;
+}
+
+float LightStorage::reflection_probe_get_origin_max_distance(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->max_distance;
+}
+
+float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->mesh_lod_threshold;
+}
+
+int LightStorage::reflection_probe_get_resolution(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->resolution;
+}
+
+float LightStorage::reflection_probe_get_intensity(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->intensity;
+}
+
+bool LightStorage::reflection_probe_is_interior(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, false);
+
+	return reflection_probe->interior;
+}
+
+bool LightStorage::reflection_probe_is_box_projection(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, false);
+
+	return reflection_probe->box_projection;
+}
+
+RS::ReflectionProbeAmbientMode LightStorage::reflection_probe_get_ambient_mode(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED);
+	return reflection_probe->ambient_mode;
+}
+
+Color LightStorage::reflection_probe_get_ambient_color(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, Color());
+
+	return reflection_probe->ambient_color;
+}
+float LightStorage::reflection_probe_get_ambient_color_energy(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->ambient_color_energy;
+}
+
+/* LIGHTMAP API */
+
+RID LightStorage::lightmap_allocate() {
+	return lightmap_owner.allocate_rid();
+}
+
+void LightStorage::lightmap_initialize(RID p_lightmap) {
+	lightmap_owner.initialize_rid(p_lightmap, Lightmap());
+}
+
+void LightStorage::lightmap_free(RID p_rid) {
+	lightmap_set_textures(p_rid, RID(), false);
+	Lightmap *lightmap = lightmap_owner.get_or_null(p_rid);
+	lightmap->dependency.deleted_notify(p_rid);
+	lightmap_owner.free(p_rid);
+}
+
+void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
+	Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND(!lm);
+
+	lightmap_array_version++;
+
+	//erase lightmap users
+	if (lm->light_texture.is_valid()) {
+		RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture);
+		if (t) {
+			t->lightmap_users.erase(p_lightmap);
+		}
+	}
+
+	RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light);
+	lm->light_texture = p_light;
+	lm->uses_spherical_harmonics = p_uses_spherical_haromics;
+
+	RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+	if (!t) {
+		if (using_lightmap_array) {
+			if (lm->array_index >= 0) {
+				lightmap_textures.write[lm->array_index] = default_2d_array;
+				lm->array_index = -1;
+			}
+		}
+
+		return;
+	}
+
+	t->lightmap_users.insert(p_lightmap);
+
+	if (using_lightmap_array) {
+		if (lm->array_index < 0) {
+			//not in array, try to put in array
+			for (int i = 0; i < lightmap_textures.size(); i++) {
+				if (lightmap_textures[i] == default_2d_array) {
+					lm->array_index = i;
+					break;
+				}
+			}
+		}
+		ERR_FAIL_COND_MSG(lm->array_index < 0, "Maximum amount of lightmaps in use (" + itos(lightmap_textures.size()) + ") has been exceeded, lightmap will nod display properly.");
+
+		lightmap_textures.write[lm->array_index] = t->rd_texture;
+	}
+}
+
+void LightStorage::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
+	Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND(!lm);
+	lm->bounds = p_bounds;
+}
+
+void LightStorage::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
+	Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND(!lm);
+	lm->interior = p_interior;
+}
+
+void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
+	Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND(!lm);
+
+	if (p_points.size()) {
+		ERR_FAIL_COND(p_points.size() * 9 != p_point_sh.size());
+		ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
+		ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
+	}
+
+	lm->points = p_points;
+	lm->bsp_tree = p_bsp_tree;
+	lm->point_sh = p_point_sh;
+	lm->tetrahedra = p_tetrahedra;
+}
+
+PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {
+	Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND_V(!lm, PackedVector3Array());
+
+	return lm->points;
+}
+
+PackedColorArray LightStorage::lightmap_get_probe_capture_sh(RID p_lightmap) const {
+	Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND_V(!lm, PackedColorArray());
+	return lm->point_sh;
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
+	Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND_V(!lm, PackedInt32Array());
+	return lm->tetrahedra;
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
+	Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND_V(!lm, PackedInt32Array());
+	return lm->bsp_tree;
+}
+
+void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) {
+	lightmap_probe_capture_update_speed = p_speed;
+}
+
+void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
+	Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND(!lm);
+
+	for (int i = 0; i < 9; i++) {
+		r_sh[i] = Color(0, 0, 0, 0);
+	}
+
+	if (!lm->points.size() || !lm->bsp_tree.size() || !lm->tetrahedra.size()) {
+		return;
+	}
+
+	static_assert(sizeof(Lightmap::BSP) == 24);
+
+	const Lightmap::BSP *bsp = (const Lightmap::BSP *)lm->bsp_tree.ptr();
+	int32_t node = 0;
+	while (node >= 0) {
+		if (Plane(bsp[node].plane[0], bsp[node].plane[1], bsp[node].plane[2], bsp[node].plane[3]).is_point_over(p_point)) {
+#ifdef DEBUG_ENABLED
+			ERR_FAIL_COND(bsp[node].over >= 0 && bsp[node].over < node);
+#endif
+
+			node = bsp[node].over;
+		} else {
+#ifdef DEBUG_ENABLED
+			ERR_FAIL_COND(bsp[node].under >= 0 && bsp[node].under < node);
+#endif
+			node = bsp[node].under;
+		}
+	}
+
+	if (node == Lightmap::BSP::EMPTY_LEAF) {
+		return; //nothing could be done
+	}
+
+	node = ABS(node) - 1;
+
+	uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4];
+	Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] };
+	const Color *sh_colors[4]{ &lm->point_sh[tetrahedron[0] * 9], &lm->point_sh[tetrahedron[1] * 9], &lm->point_sh[tetrahedron[2] * 9], &lm->point_sh[tetrahedron[3] * 9] };
+	Color barycentric = Geometry3D::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point);
+
+	for (int i = 0; i < 4; i++) {
+		float c = CLAMP(barycentric[i], 0.0, 1.0);
+		for (int j = 0; j < 9; j++) {
+			r_sh[j] += sh_colors[i][j] * c;
+		}
+	}
+}
+
+bool LightStorage::lightmap_is_interior(RID p_lightmap) const {
+	const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND_V(!lm, false);
+	return lm->interior;
+}
+
+AABB LightStorage::lightmap_get_aabb(RID p_lightmap) const {
+	const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+	ERR_FAIL_COND_V(!lm, AABB());
+	return lm->bounds;
+}

+ 370 - 0
servers/rendering/renderer_rd/storage_rd/light_storage.h

@@ -0,0 +1,370 @@
+/*************************************************************************/
+/*  light_storage.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 LIGHT_STORAGE_RD_H
+#define LIGHT_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/storage/light_storage.h"
+
+namespace RendererRD {
+
+/* LIGHT */
+
+struct Light {
+	RS::LightType type;
+	float param[RS::LIGHT_PARAM_MAX];
+	Color color = Color(1, 1, 1, 1);
+	RID projector;
+	bool shadow = false;
+	bool negative = false;
+	bool reverse_cull = false;
+	RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
+	uint32_t max_sdfgi_cascade = 2;
+	uint32_t cull_mask = 0xFFFFFFFF;
+	bool distance_fade = false;
+	real_t distance_fade_begin = 40.0;
+	real_t distance_fade_shadow = 50.0;
+	real_t distance_fade_length = 10.0;
+	RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
+	RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+	bool directional_blend_splits = false;
+	RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
+	uint64_t version = 0;
+
+	RendererStorage::Dependency dependency;
+};
+
+/* REFLECTION PROBE */
+
+struct ReflectionProbe {
+	RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
+	int resolution = 256;
+	float intensity = 1.0;
+	RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
+	Color ambient_color;
+	float ambient_color_energy = 1.0;
+	float max_distance = 0;
+	Vector3 extents = Vector3(1, 1, 1);
+	Vector3 origin_offset;
+	bool interior = false;
+	bool box_projection = false;
+	bool enable_shadows = false;
+	uint32_t cull_mask = (1 << 20) - 1;
+	float mesh_lod_threshold = 0.01;
+
+	RendererStorage::Dependency dependency;
+};
+
+/* LIGHTMAP */
+
+struct Lightmap {
+	RID light_texture;
+	bool uses_spherical_harmonics = false;
+	bool interior = false;
+	AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
+	int32_t array_index = -1; //unassigned
+	PackedVector3Array points;
+	PackedColorArray point_sh;
+	PackedInt32Array tetrahedra;
+	PackedInt32Array bsp_tree;
+
+	struct BSP {
+		static const int32_t EMPTY_LEAF = INT32_MIN;
+		float plane[4];
+		int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
+	};
+
+	RendererStorage::Dependency dependency;
+};
+
+class LightStorage : public RendererLightStorage {
+private:
+	static LightStorage *singleton;
+
+	/* LIGHT */
+	mutable RID_Owner<Light, true> light_owner;
+
+	/* REFLECTION PROBE */
+	mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
+
+	/* LIGHTMAP */
+
+	bool using_lightmap_array;
+	Vector<RID> lightmap_textures;
+	uint64_t lightmap_array_version = 0;
+	float lightmap_probe_capture_update_speed = 4;
+
+	mutable RID_Owner<Lightmap, true> lightmap_owner;
+
+public:
+	static LightStorage *get_singleton();
+
+	LightStorage();
+	virtual ~LightStorage();
+
+	/* LIGHT */
+
+	Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); };
+	bool owns_light(RID p_rid) { return light_owner.owns(p_rid); };
+
+	void _light_initialize(RID p_rid, RS::LightType p_type);
+
+	virtual RID directional_light_allocate() override;
+	virtual void directional_light_initialize(RID p_light) override;
+
+	virtual RID omni_light_allocate() override;
+	virtual void omni_light_initialize(RID p_light) override;
+
+	virtual RID spot_light_allocate() override;
+	virtual void spot_light_initialize(RID p_light) override;
+
+	virtual void light_free(RID p_rid) override;
+
+	virtual void light_set_color(RID p_light, const Color &p_color) override;
+	virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override;
+	virtual void light_set_shadow(RID p_light, bool p_enabled) override;
+	virtual void light_set_projector(RID p_light, RID p_texture) override;
+	virtual void light_set_negative(RID p_light, bool p_enable) override;
+	virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
+	virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
+	virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
+	virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
+	virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
+
+	virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override;
+
+	virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override;
+	virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) override;
+	virtual bool light_directional_get_blend_splits(RID p_light) const override;
+	virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override;
+	virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override;
+
+	virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override;
+	virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override;
+
+	virtual RS::LightType light_get_type(RID p_light) const override {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+		return light->type;
+	}
+	virtual AABB light_get_aabb(RID p_light) const override;
+
+	virtual float light_get_param(RID p_light, RS::LightParam p_param) override {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, 0);
+
+		return light->param[p_param];
+	}
+
+	_FORCE_INLINE_ RID light_get_projector(RID p_light) {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, RID());
+
+		return light->projector;
+	}
+
+	virtual Color light_get_color(RID p_light) override {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, Color());
+
+		return light->color;
+	}
+
+	_FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, 0);
+
+		return light->cull_mask;
+	}
+
+	_FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) {
+		const Light *light = light_owner.get_or_null(p_light);
+		return light->distance_fade;
+	}
+
+	_FORCE_INLINE_ float light_get_distance_fade_begin(RID p_light) {
+		const Light *light = light_owner.get_or_null(p_light);
+		return light->distance_fade_begin;
+	}
+
+	_FORCE_INLINE_ float light_get_distance_fade_shadow(RID p_light) {
+		const Light *light = light_owner.get_or_null(p_light);
+		return light->distance_fade_shadow;
+	}
+
+	_FORCE_INLINE_ float light_get_distance_fade_length(RID p_light) {
+		const Light *light = light_owner.get_or_null(p_light);
+		return light->distance_fade_length;
+	}
+
+	virtual bool light_has_shadow(RID p_light) const override {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+		return light->shadow;
+	}
+
+	virtual bool light_has_projector(RID p_light) const override {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+		return light_owner.owns(light->projector);
+	}
+
+	_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+		return light->negative;
+	}
+
+	_FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, 0.0);
+
+		return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
+	}
+
+	_FORCE_INLINE_ float light_get_shadow_volumetric_fog_fade(RID p_light) const {
+		const Light *light = light_owner.get_or_null(p_light);
+		ERR_FAIL_COND_V(!light, 0.0);
+
+		return light->param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE];
+	}
+
+	virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override;
+	virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
+	virtual uint64_t light_get_version(RID p_light) const override;
+
+	/* REFLECTION PROBE */
+
+	ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); };
+	bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); };
+
+	virtual RID reflection_probe_allocate() override;
+	virtual void reflection_probe_initialize(RID p_reflection_probe) override;
+	virtual void reflection_probe_free(RID p_rid) override;
+
+	virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override;
+	virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override;
+	virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override;
+	virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
+	virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
+	virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override;
+	virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override;
+	virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override;
+	virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override;
+	virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override;
+	virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override;
+	virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override;
+	virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override;
+	virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
+
+	virtual AABB reflection_probe_get_aabb(RID p_probe) const override;
+	virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
+	virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
+	virtual Vector3 reflection_probe_get_extents(RID p_probe) const override;
+	virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override;
+	virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override;
+	virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
+
+	int reflection_probe_get_resolution(RID p_probe) const;
+	virtual bool reflection_probe_renders_shadows(RID p_probe) const override;
+
+	float reflection_probe_get_intensity(RID p_probe) const;
+	bool reflection_probe_is_interior(RID p_probe) const;
+	bool reflection_probe_is_box_projection(RID p_probe) const;
+	RS::ReflectionProbeAmbientMode reflection_probe_get_ambient_mode(RID p_probe) const;
+	Color reflection_probe_get_ambient_color(RID p_probe) const;
+	float reflection_probe_get_ambient_color_energy(RID p_probe) const;
+
+	/* LIGHTMAP */
+
+	Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
+	bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); };
+
+	virtual RID lightmap_allocate() override;
+	virtual void lightmap_initialize(RID p_lightmap) override;
+	virtual void lightmap_free(RID p_rid) override;
+
+	virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override;
+	virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
+	virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
+	virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
+	virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
+	virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
+	virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
+	virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override;
+	virtual AABB lightmap_get_aabb(RID p_lightmap) const override;
+	virtual bool lightmap_is_interior(RID p_lightmap) const override;
+	virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override;
+	virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
+
+	virtual float lightmap_get_probe_capture_update_speed() const override {
+		return lightmap_probe_capture_update_speed;
+	}
+	_FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const {
+		const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+		ERR_FAIL_COND_V(!lm, RID());
+		return lm->light_texture;
+	}
+	_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
+		ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
+		const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+		return lm->array_index;
+	}
+	_FORCE_INLINE_ bool lightmap_uses_spherical_harmonics(RID p_lightmap) const {
+		ERR_FAIL_COND_V(!using_lightmap_array, false); //only for arrays
+		const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+		return lm->uses_spherical_harmonics;
+	}
+	_FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
+		ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
+		return lightmap_array_version;
+	}
+
+	_FORCE_INLINE_ int lightmap_array_get_size() const {
+		ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
+		return lightmap_textures.size();
+	}
+
+	_FORCE_INLINE_ const Vector<RID> &lightmap_array_get_textures() const {
+		ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays
+		return lightmap_textures;
+	}
+};
+
+} // namespace RendererRD
+
+#endif // !LIGHT_STORAGE_RD_H

+ 200 - 0
servers/rendering/renderer_rd/storage_rd/material_storage.cpp

@@ -1298,6 +1298,94 @@ MaterialStorage *MaterialStorage::get_singleton() {
 MaterialStorage::MaterialStorage() {
 	singleton = this;
 
+	//default samplers
+	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+			RD::SamplerState sampler_state;
+			switch (i) {
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+					sampler_state.max_lod = 0;
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+					sampler_state.max_lod = 0;
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+					} else {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+					}
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+					} else {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+					}
+
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+					} else {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+					}
+					sampler_state.use_anisotropy = true;
+					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+					} else {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+					}
+					sampler_state.use_anisotropy = true;
+					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+
+				} break;
+				default: {
+				}
+			}
+			switch (j) {
+				case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
+					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
+					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
+					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+				} break;
+				default: {
+				}
+			}
+
+			default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
+		}
+	}
+
+	//custom sampler
+	sampler_rd_configure_custom(0.0f);
+
 	for (int i = 0; i < SHADER_TYPE_MAX; i++) {
 		shader_data_request_func[i] = nullptr;
 	}
@@ -1319,9 +1407,121 @@ MaterialStorage::~MaterialStorage() {
 	memdelete_arr(global_variables.buffer_dirty_regions);
 	RD::get_singleton()->free(global_variables.buffer);
 
+	//def samplers
+	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+			RD::get_singleton()->free(default_rd_samplers[i][j]);
+		}
+	}
+
+	//custom samplers
+	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+		for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+			if (custom_rd_samplers[i][j].is_valid()) {
+				RD::get_singleton()->free(custom_rd_samplers[i][j]);
+			}
+		}
+	}
+
 	singleton = nullptr;
 }
 
+/* Samplers */
+
+void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) {
+	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+			RD::SamplerState sampler_state;
+			switch (i) {
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+					sampler_state.max_lod = 0;
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+					sampler_state.max_lod = 0;
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+					} else {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+					}
+					sampler_state.lod_bias = p_mipmap_bias;
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+					} else {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+					}
+					sampler_state.lod_bias = p_mipmap_bias;
+
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+					} else {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+					}
+					sampler_state.lod_bias = p_mipmap_bias;
+					sampler_state.use_anisotropy = true;
+					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
+					sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+					sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+					if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+					} else {
+						sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+					}
+					sampler_state.lod_bias = p_mipmap_bias;
+					sampler_state.use_anisotropy = true;
+					sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+
+				} break;
+				default: {
+				}
+			}
+			switch (j) {
+				case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
+					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
+					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
+					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
+				} break;
+				case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+					sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+					sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+					sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+				} break;
+				default: {
+				}
+			}
+
+			if (custom_rd_samplers[i][j].is_valid()) {
+				RD::get_singleton()->free(custom_rd_samplers[i][j]);
+			}
+
+			custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
+		}
+	}
+}
+
 /* GLOBAL VARIABLE API */
 
 int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {

+ 18 - 0
servers/rendering/renderer_rd/storage_rd/material_storage.h

@@ -195,6 +195,11 @@ private:
 	friend struct MaterialData;
 	static MaterialStorage *singleton;
 
+	/* Samplers */
+
+	RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+	RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+
 	/* GLOBAL VARIABLE API */
 
 	GlobalVariables global_variables;
@@ -222,6 +227,19 @@ public:
 	MaterialStorage();
 	virtual ~MaterialStorage();
 
+	/* Samplers */
+
+	_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
+		return default_rd_samplers[p_filter][p_repeat];
+	}
+	_FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
+		return custom_rd_samplers[p_filter][p_repeat];
+	}
+
+	void sampler_rd_configure_custom(float mipmap_bias);
+
+	// void sampler_rd_set_default(float p_mipmap_bias);
+
 	/* GLOBAL VARIABLE API */
 
 	void _update_global_variables();

+ 1897 - 0
servers/rendering/renderer_rd/storage_rd/particles_storage.cpp

@@ -0,0 +1,1897 @@
+/*************************************************************************/
+/*  particles_storage.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 "particles_storage.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/rendering_server_globals.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+ParticlesStorage *ParticlesStorage::singleton = nullptr;
+
+ParticlesStorage *ParticlesStorage::get_singleton() {
+	return singleton;
+}
+
+ParticlesStorage::ParticlesStorage() {
+	singleton = this;
+
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+	/* Particles */
+
+	{
+		// Initialize particles
+		Vector<String> particles_modes;
+		particles_modes.push_back("");
+		particles_shader.shader.initialize(particles_modes, String());
+	}
+	MaterialStorage::get_singleton()->shader_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
+	MaterialStorage::get_singleton()->material_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
+
+	{
+		ShaderCompiler::DefaultIdentifierActions actions;
+
+		actions.renames["COLOR"] = "PARTICLE.color";
+		actions.renames["VELOCITY"] = "PARTICLE.velocity";
+		//actions.renames["MASS"] = "mass"; ?
+		actions.renames["ACTIVE"] = "particle_active";
+		actions.renames["RESTART"] = "restart";
+		actions.renames["CUSTOM"] = "PARTICLE.custom";
+		for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+			String udname = "USERDATA" + itos(i + 1);
+			actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1);
+			actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n";
+		}
+		actions.renames["TRANSFORM"] = "PARTICLE.xform";
+		actions.renames["TIME"] = "frame_history.data[0].time";
+		actions.renames["PI"] = _MKSTR(Math_PI);
+		actions.renames["TAU"] = _MKSTR(Math_TAU);
+		actions.renames["E"] = _MKSTR(Math_E);
+		actions.renames["LIFETIME"] = "params.lifetime";
+		actions.renames["DELTA"] = "local_delta";
+		actions.renames["NUMBER"] = "particle_number";
+		actions.renames["INDEX"] = "index";
+		//actions.renames["GRAVITY"] = "current_gravity";
+		actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform";
+		actions.renames["RANDOM_SEED"] = "FRAME.random_seed";
+		actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION";
+		actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE";
+		actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY";
+		actions.renames["FLAG_EMIT_COLOR"] = "EMISSION_FLAG_HAS_COLOR";
+		actions.renames["FLAG_EMIT_CUSTOM"] = "EMISSION_FLAG_HAS_CUSTOM";
+		actions.renames["RESTART_POSITION"] = "restart_position";
+		actions.renames["RESTART_ROT_SCALE"] = "restart_rotation_scale";
+		actions.renames["RESTART_VELOCITY"] = "restart_velocity";
+		actions.renames["RESTART_COLOR"] = "restart_color";
+		actions.renames["RESTART_CUSTOM"] = "restart_custom";
+		actions.renames["emit_subparticle"] = "emit_subparticle";
+		actions.renames["COLLIDED"] = "collided";
+		actions.renames["COLLISION_NORMAL"] = "collision_normal";
+		actions.renames["COLLISION_DEPTH"] = "collision_depth";
+		actions.renames["ATTRACTOR_FORCE"] = "attractor_force";
+
+		actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n";
+		actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n";
+		actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
+		actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n";
+
+		actions.sampler_array_name = "material_samplers";
+		actions.base_texture_binding_index = 1;
+		actions.texture_layout_set = 3;
+		actions.base_uniform_string = "material.";
+		actions.base_varying_index = 10;
+
+		actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+		actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
+		actions.global_buffer_array_variable = "global_variables.data";
+
+		particles_shader.compiler.initialize(actions);
+	}
+
+	{
+		// default material and shader for particles shader
+		particles_shader.default_shader = material_storage->shader_allocate();
+		material_storage->shader_initialize(particles_shader.default_shader);
+		material_storage->shader_set_code(particles_shader.default_shader, R"(
+// Default particles shader.
+
+shader_type particles;
+
+void process() {
+	COLOR = vec4(1.0);
+}
+)");
+		particles_shader.default_material = material_storage->material_allocate();
+		material_storage->material_initialize(particles_shader.default_material);
+		material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
+
+		ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+		particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
+
+		Vector<RD::Uniform> uniforms;
+
+		{
+			Vector<RID> ids;
+			ids.resize(12);
+			RID *ids_ptr = ids.ptrw();
+			ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+			ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+			ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+			uniforms.push_back(u);
+		}
+
+		{
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+			u.binding = 2;
+			u.append_id(material_storage->global_variables_get_storage_buffer());
+			uniforms.push_back(u);
+		}
+
+		particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0);
+	}
+
+	{
+		Vector<String> copy_modes;
+		for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
+			if (i == 0) {
+				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n");
+				copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n");
+				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n");
+			} else {
+				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USERDATA_COUNT " + itos(i) + "\n");
+				copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
+				copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
+			}
+		}
+
+		particles_shader.copy_shader.initialize(copy_modes);
+
+		particles_shader.copy_shader_version = particles_shader.copy_shader.version_create();
+
+		for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
+			for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) {
+				particles_shader.copy_pipelines[i * ParticlesShader::COPY_MODE_MAX + j] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j));
+			}
+		}
+	}
+}
+
+ParticlesStorage::~ParticlesStorage() {
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+	particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
+
+	material_storage->material_free(particles_shader.default_material);
+	material_storage->shader_free(particles_shader.default_shader);
+
+	singleton = nullptr;
+}
+
+/* PARTICLES */
+
+RID ParticlesStorage::particles_allocate() {
+	return particles_owner.allocate_rid();
+}
+
+void ParticlesStorage::particles_initialize(RID p_rid) {
+	particles_owner.initialize_rid(p_rid, Particles());
+}
+
+void ParticlesStorage::particles_free(RID p_rid) {
+	update_particles();
+	Particles *particles = particles_owner.get_or_null(p_rid);
+	particles->dependency.deleted_notify(p_rid);
+	_particles_free_data(particles);
+	particles_owner.free(p_rid);
+}
+
+void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	if (particles->mode == p_mode) {
+		return;
+	}
+
+	_particles_free_data(particles);
+
+	particles->mode = p_mode;
+}
+
+void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->emitting = p_emitting;
+}
+
+bool ParticlesStorage::particles_get_emitting(RID p_particles) {
+	ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND_V(!particles, false);
+
+	return particles->emitting;
+}
+
+void ParticlesStorage::_particles_free_data(Particles *particles) {
+	if (particles->particle_buffer.is_valid()) {
+		RD::get_singleton()->free(particles->particle_buffer);
+		particles->particle_buffer = RID();
+		RD::get_singleton()->free(particles->particle_instance_buffer);
+		particles->particle_instance_buffer = RID();
+	}
+
+	particles->userdata_count = 0;
+
+	if (particles->frame_params_buffer.is_valid()) {
+		RD::get_singleton()->free(particles->frame_params_buffer);
+		particles->frame_params_buffer = RID();
+	}
+	particles->particles_transforms_buffer_uniform_set = RID();
+
+	if (RD::get_singleton()->uniform_set_is_valid(particles->trail_bind_pose_uniform_set)) {
+		RD::get_singleton()->free(particles->trail_bind_pose_uniform_set);
+	}
+	particles->trail_bind_pose_uniform_set = RID();
+
+	if (particles->trail_bind_pose_buffer.is_valid()) {
+		RD::get_singleton()->free(particles->trail_bind_pose_buffer);
+		particles->trail_bind_pose_buffer = RID();
+	}
+	if (RD::get_singleton()->uniform_set_is_valid(particles->collision_textures_uniform_set)) {
+		RD::get_singleton()->free(particles->collision_textures_uniform_set);
+	}
+	particles->collision_textures_uniform_set = RID();
+
+	if (particles->particles_sort_buffer.is_valid()) {
+		RD::get_singleton()->free(particles->particles_sort_buffer);
+		particles->particles_sort_buffer = RID();
+		particles->particles_sort_uniform_set = RID();
+	}
+
+	if (particles->emission_buffer != nullptr) {
+		particles->emission_buffer = nullptr;
+		particles->emission_buffer_data.clear();
+		RD::get_singleton()->free(particles->emission_storage_buffer);
+		particles->emission_storage_buffer = RID();
+	}
+
+	if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
+		//will need to be re-created
+		RD::get_singleton()->free(particles->particles_material_uniform_set);
+	}
+	particles->particles_material_uniform_set = RID();
+}
+
+void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	if (particles->amount == p_amount) {
+		return;
+	}
+
+	_particles_free_data(particles);
+
+	particles->amount = p_amount;
+
+	particles->prev_ticks = 0;
+	particles->phase = 0;
+	particles->prev_phase = 0;
+	particles->clear = true;
+
+	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	particles->lifetime = p_lifetime;
+}
+
+void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	particles->one_shot = p_one_shot;
+}
+
+void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	particles->pre_process_time = p_time;
+}
+void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	particles->explosiveness = p_ratio;
+}
+void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	particles->randomness = p_ratio;
+}
+
+void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	particles->custom_aabb = p_aabb;
+	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->speed_scale = p_scale;
+}
+void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->use_local_coords = p_enable;
+	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->fixed_fps = p_fps;
+
+	_particles_free_data(particles);
+
+	particles->prev_ticks = 0;
+	particles->phase = 0;
+	particles->prev_phase = 0;
+	particles->clear = true;
+
+	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->interpolate = p_enable;
+}
+
+void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->fractional_delta = p_enable;
+}
+
+void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	ERR_FAIL_COND(p_length < 0.1);
+	p_length = MIN(10.0, p_length);
+
+	particles->trails_enabled = p_enable;
+	particles->trail_length = p_length;
+
+	_particles_free_data(particles);
+
+	particles->prev_ticks = 0;
+	particles->phase = 0;
+	particles->prev_phase = 0;
+	particles->clear = true;
+
+	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) {
+		_particles_free_data(particles);
+
+		particles->prev_ticks = 0;
+		particles->phase = 0;
+		particles->prev_phase = 0;
+		particles->clear = true;
+	}
+	particles->trail_bind_poses = p_bind_poses;
+	particles->trail_bind_poses_dirty = true;
+
+	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->collision_base_size = p_size;
+}
+
+void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->transform_align = p_transform_align;
+}
+
+void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->process_material = p_material;
+	particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
+}
+
+RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND_V(!particles, RID());
+
+	return particles->process_material;
+}
+
+void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->draw_order = p_order;
+}
+
+void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_passes) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->draw_passes.resize(p_passes);
+}
+
+void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
+	particles->draw_passes.write[p_pass] = p_mesh;
+}
+
+void ParticlesStorage::particles_restart(RID p_particles) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->restart_request = true;
+}
+
+void ParticlesStorage::_particles_allocate_emission_buffer(Particles *particles) {
+	ERR_FAIL_COND(particles->emission_buffer != nullptr);
+
+	particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4);
+	memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size());
+	particles->emission_buffer = reinterpret_cast<ParticleEmissionBuffer *>(particles->emission_buffer_data.ptrw());
+	particles->emission_buffer->particle_max = particles->amount;
+
+	particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data);
+
+	if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
+		//will need to be re-created
+		RD::get_singleton()->free(particles->particles_material_uniform_set);
+		particles->particles_material_uniform_set = RID();
+	}
+}
+
+void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	ERR_FAIL_COND(p_particles == p_subemitter_particles);
+
+	particles->sub_emitter = p_subemitter_particles;
+
+	if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
+		RD::get_singleton()->free(particles->particles_material_uniform_set);
+		particles->particles_material_uniform_set = RID(); //clear and force to re create sub emitting
+	}
+}
+
+void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	ERR_FAIL_COND(particles->amount == 0);
+
+	if (particles->emitting) {
+		particles->clear = true;
+		particles->emitting = false;
+	}
+
+	if (particles->emission_buffer == nullptr) {
+		_particles_allocate_emission_buffer(particles);
+	}
+
+	if (particles->inactive) {
+		//in case it was inactive, make active again
+		particles->inactive = false;
+		particles->inactive_time = 0;
+	}
+
+	int32_t idx = particles->emission_buffer->particle_count;
+	if (idx < particles->emission_buffer->particle_max) {
+		RendererStorageRD::store_transform(p_transform, particles->emission_buffer->data[idx].xform);
+
+		particles->emission_buffer->data[idx].velocity[0] = p_velocity.x;
+		particles->emission_buffer->data[idx].velocity[1] = p_velocity.y;
+		particles->emission_buffer->data[idx].velocity[2] = p_velocity.z;
+
+		particles->emission_buffer->data[idx].custom[0] = p_custom.r;
+		particles->emission_buffer->data[idx].custom[1] = p_custom.g;
+		particles->emission_buffer->data[idx].custom[2] = p_custom.b;
+		particles->emission_buffer->data[idx].custom[3] = p_custom.a;
+
+		particles->emission_buffer->data[idx].color[0] = p_color.r;
+		particles->emission_buffer->data[idx].color[1] = p_color.g;
+		particles->emission_buffer->data[idx].color[2] = p_color.b;
+		particles->emission_buffer->data[idx].color[3] = p_color.a;
+
+		particles->emission_buffer->data[idx].flags = p_emit_flags;
+		particles->emission_buffer->particle_count++;
+	}
+}
+
+void ParticlesStorage::particles_request_process(RID p_particles) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	if (!particles->dirty) {
+		particles->dirty = true;
+		particles->update_list = particle_update_list;
+		particle_update_list = particles;
+	}
+}
+
+AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
+	if (RSG::threaded) {
+		WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
+	}
+
+	const Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND_V(!particles, AABB());
+
+	int total_amount = particles->amount;
+	if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+		total_amount *= particles->trail_bind_poses.size();
+	}
+
+	Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(particles->particle_buffer);
+	ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleData)), AABB());
+
+	Transform3D inv = particles->emission_transform.affine_inverse();
+
+	AABB aabb;
+	if (buffer.size()) {
+		bool first = true;
+
+		const uint8_t *data_ptr = (const uint8_t *)buffer.ptr();
+		uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * particles->userdata_count;
+
+		for (int i = 0; i < total_amount; i++) {
+			const ParticleData &particle_data = *(const ParticleData *)&data_ptr[particle_data_size * i];
+			if (particle_data.active) {
+				Vector3 pos = Vector3(particle_data.xform[12], particle_data.xform[13], particle_data.xform[14]);
+				if (!particles->use_local_coords) {
+					pos = inv.xform(pos);
+				}
+				if (first) {
+					aabb.position = pos;
+					first = false;
+				} else {
+					aabb.expand_to(pos);
+				}
+			}
+		}
+	}
+
+	float longest_axis_size = 0;
+	for (int i = 0; i < particles->draw_passes.size(); i++) {
+		if (particles->draw_passes[i].is_valid()) {
+			AABB maabb = MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID());
+			longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size);
+		}
+	}
+
+	aabb.grow_by(longest_axis_size);
+
+	return aabb;
+}
+
+AABB ParticlesStorage::particles_get_aabb(RID p_particles) const {
+	const Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND_V(!particles, AABB());
+
+	return particles->custom_aabb;
+}
+
+void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	particles->emission_transform = p_transform;
+}
+
+int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
+	const Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND_V(!particles, 0);
+
+	return particles->draw_passes.size();
+}
+
+RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
+	const Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND_V(!particles, RID());
+	ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
+
+	return particles->draw_passes[p_pass];
+}
+
+void ParticlesStorage::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	particles->collisions.insert(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	particles->collisions.erase(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+	particles->has_sdf_collision = p_enable;
+	particles->sdf_collision_transform = p_xform;
+	particles->sdf_collision_to_screen = p_to_screen;
+	particles->sdf_collision_texture = p_texture;
+}
+
+void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta) {
+	TextureStorage *texture_storage = TextureStorage::get_singleton();
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+	if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) {
+		Vector<RD::Uniform> uniforms;
+
+		{
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+			u.binding = 0;
+			u.append_id(p_particles->frame_params_buffer);
+			uniforms.push_back(u);
+		}
+		{
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+			u.binding = 1;
+			u.append_id(p_particles->particle_buffer);
+			uniforms.push_back(u);
+		}
+
+		{
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+			u.binding = 2;
+			if (p_particles->emission_storage_buffer.is_valid()) {
+				u.append_id(p_particles->emission_storage_buffer);
+			} else {
+				u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer());
+			}
+			uniforms.push_back(u);
+		}
+		{
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+			u.binding = 3;
+			Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
+			if (sub_emitter) {
+				if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer
+					_particles_allocate_emission_buffer(sub_emitter);
+				}
+				u.append_id(sub_emitter->emission_storage_buffer);
+			} else {
+				u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer());
+			}
+			uniforms.push_back(u);
+		}
+
+		p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1);
+	}
+
+	double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
+
+	//move back history (if there is any)
+	for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) {
+		p_particles->frame_history[i] = p_particles->frame_history[i - 1];
+	}
+	//update current frame
+	ParticlesFrameParams &frame_params = p_particles->frame_history[0];
+
+	if (p_particles->clear) {
+		p_particles->cycle_number = 0;
+		p_particles->random_seed = Math::rand();
+	} else if (new_phase < p_particles->phase) {
+		if (p_particles->one_shot) {
+			p_particles->emitting = false;
+		}
+		p_particles->cycle_number++;
+	}
+
+	frame_params.emitting = p_particles->emitting;
+	frame_params.system_phase = new_phase;
+	frame_params.prev_system_phase = p_particles->phase;
+
+	p_particles->phase = new_phase;
+
+	frame_params.time = RendererCompositorRD::singleton->get_total_time();
+	frame_params.delta = p_delta * p_particles->speed_scale;
+	frame_params.random_seed = p_particles->random_seed;
+	frame_params.explosiveness = p_particles->explosiveness;
+	frame_params.randomness = p_particles->randomness;
+
+	if (p_particles->use_local_coords) {
+		RendererStorageRD::store_transform(Transform3D(), frame_params.emission_transform);
+	} else {
+		RendererStorageRD::store_transform(p_particles->emission_transform, frame_params.emission_transform);
+	}
+
+	frame_params.cycle = p_particles->cycle_number;
+	frame_params.frame = p_particles->frame_counter++;
+	frame_params.pad0 = 0;
+	frame_params.pad1 = 0;
+	frame_params.pad2 = 0;
+
+	{ //collision and attractors
+
+		frame_params.collider_count = 0;
+		frame_params.attractor_count = 0;
+		frame_params.particle_size = p_particles->collision_base_size;
+
+		RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
+		RID collision_heightmap_texture;
+
+		Transform3D to_particles;
+		if (p_particles->use_local_coords) {
+			to_particles = p_particles->emission_transform.affine_inverse();
+		}
+
+		if (p_particles->has_sdf_collision && RD::get_singleton()->texture_is_valid(p_particles->sdf_collision_texture)) {
+			//2D collision
+
+			Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
+			Transform2D revert = xform.affine_inverse();
+			frame_params.collider_count = 1;
+			frame_params.colliders[0].transform[0] = xform.elements[0][0];
+			frame_params.colliders[0].transform[1] = xform.elements[0][1];
+			frame_params.colliders[0].transform[2] = 0;
+			frame_params.colliders[0].transform[3] = xform.elements[2][0];
+
+			frame_params.colliders[0].transform[4] = xform.elements[1][0];
+			frame_params.colliders[0].transform[5] = xform.elements[1][1];
+			frame_params.colliders[0].transform[6] = 0;
+			frame_params.colliders[0].transform[7] = xform.elements[2][1];
+
+			frame_params.colliders[0].transform[8] = revert.elements[0][0];
+			frame_params.colliders[0].transform[9] = revert.elements[0][1];
+			frame_params.colliders[0].transform[10] = 0;
+			frame_params.colliders[0].transform[11] = revert.elements[2][0];
+
+			frame_params.colliders[0].transform[12] = revert.elements[1][0];
+			frame_params.colliders[0].transform[13] = revert.elements[1][1];
+			frame_params.colliders[0].transform[14] = 0;
+			frame_params.colliders[0].transform[15] = revert.elements[2][1];
+
+			frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x;
+			frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y;
+			frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x;
+			frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y;
+			frame_params.colliders[0].texture_index = 0;
+			frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF;
+
+			collision_heightmap_texture = p_particles->sdf_collision_texture;
+
+			//replace in all other history frames where used because parameters are no longer valid if screen moves
+			for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) {
+				if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) {
+					p_particles->frame_history[i].colliders[0] = frame_params.colliders[0];
+				}
+			}
+		}
+
+		uint32_t collision_3d_textures_used = 0;
+		for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
+			ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get());
+			if (!pci || !pci->active) {
+				continue;
+			}
+			ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision);
+			ERR_CONTINUE(!pc);
+
+			Transform3D to_collider = pci->transform;
+			if (p_particles->use_local_coords) {
+				to_collider = to_particles * to_collider;
+			}
+			Vector3 scale = to_collider.basis.get_scale();
+			to_collider.basis.orthonormalize();
+
+			if (pc->type <= RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) {
+				//attractor
+				if (frame_params.attractor_count >= ParticlesFrameParams::MAX_ATTRACTORS) {
+					continue;
+				}
+
+				ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count];
+
+				RendererStorageRD::store_transform(to_collider, attr.transform);
+				attr.strength = pc->attractor_strength;
+				attr.attenuation = pc->attractor_attenuation;
+				attr.directionality = pc->attractor_directionality;
+
+				switch (pc->type) {
+					case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: {
+						attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_SPHERE;
+						float radius = pc->radius;
+						radius *= (scale.x + scale.y + scale.z) / 3.0;
+						attr.extents[0] = radius;
+						attr.extents[1] = radius;
+						attr.extents[2] = radius;
+					} break;
+					case RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT: {
+						attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_BOX;
+						Vector3 extents = pc->extents * scale;
+						attr.extents[0] = extents.x;
+						attr.extents[1] = extents.y;
+						attr.extents[2] = extents.z;
+					} break;
+					case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: {
+						if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
+							continue;
+						}
+						attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_VECTOR_FIELD;
+						Vector3 extents = pc->extents * scale;
+						attr.extents[0] = extents.x;
+						attr.extents[1] = extents.y;
+						attr.extents[2] = extents.z;
+						attr.texture_index = collision_3d_textures_used;
+
+						collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
+						collision_3d_textures_used++;
+					} break;
+					default: {
+					}
+				}
+
+				frame_params.attractor_count++;
+			} else {
+				//collider
+				if (frame_params.collider_count >= ParticlesFrameParams::MAX_COLLIDERS) {
+					continue;
+				}
+
+				ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count];
+
+				RendererStorageRD::store_transform(to_collider, col.transform);
+				switch (pc->type) {
+					case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+						col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE;
+						float radius = pc->radius;
+						radius *= (scale.x + scale.y + scale.z) / 3.0;
+						col.extents[0] = radius;
+						col.extents[1] = radius;
+						col.extents[2] = radius;
+					} break;
+					case RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE: {
+						col.type = ParticlesFrameParams::COLLISION_TYPE_BOX;
+						Vector3 extents = pc->extents * scale;
+						col.extents[0] = extents.x;
+						col.extents[1] = extents.y;
+						col.extents[2] = extents.z;
+					} break;
+					case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: {
+						if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
+							continue;
+						}
+						col.type = ParticlesFrameParams::COLLISION_TYPE_SDF;
+						Vector3 extents = pc->extents * scale;
+						col.extents[0] = extents.x;
+						col.extents[1] = extents.y;
+						col.extents[2] = extents.z;
+						col.texture_index = collision_3d_textures_used;
+						col.scale = (scale.x + scale.y + scale.z) * 0.333333333333; //non uniform scale non supported
+
+						collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
+						collision_3d_textures_used++;
+					} break;
+					case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: {
+						if (collision_heightmap_texture != RID()) { //already taken
+							continue;
+						}
+
+						col.type = ParticlesFrameParams::COLLISION_TYPE_HEIGHT_FIELD;
+						Vector3 extents = pc->extents * scale;
+						col.extents[0] = extents.x;
+						col.extents[1] = extents.y;
+						col.extents[2] = extents.z;
+						collision_heightmap_texture = pc->heightfield_texture;
+					} break;
+					default: {
+					}
+				}
+
+				frame_params.collider_count++;
+			}
+		}
+
+		bool different = false;
+		if (collision_3d_textures_used == p_particles->collision_3d_textures_used) {
+			for (int i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
+				if (p_particles->collision_3d_textures[i] != collision_3d_textures[i]) {
+					different = true;
+					break;
+				}
+			}
+		}
+
+		if (collision_heightmap_texture != p_particles->collision_heightmap_texture) {
+			different = true;
+		}
+
+		bool uniform_set_valid = RD::get_singleton()->uniform_set_is_valid(p_particles->collision_textures_uniform_set);
+
+		if (different || !uniform_set_valid) {
+			if (uniform_set_valid) {
+				RD::get_singleton()->free(p_particles->collision_textures_uniform_set);
+			}
+
+			Vector<RD::Uniform> uniforms;
+
+			{
+				RD::Uniform u;
+				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+				u.binding = 0;
+				for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
+					RID rd_tex;
+					if (i < collision_3d_textures_used) {
+						Texture *t = TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]);
+						if (t && t->type == Texture::TYPE_3D) {
+							rd_tex = t->rd_texture;
+						}
+					}
+
+					if (rd_tex == RID()) {
+						rd_tex = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+					}
+					u.append_id(rd_tex);
+				}
+				uniforms.push_back(u);
+			}
+			{
+				RD::Uniform u;
+				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+				u.binding = 1;
+				if (collision_heightmap_texture.is_valid()) {
+					u.append_id(collision_heightmap_texture);
+				} else {
+					u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK));
+				}
+				uniforms.push_back(u);
+			}
+			p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2);
+		}
+	}
+
+	ParticlesShader::PushConstant push_constant;
+
+	int process_amount = p_particles->amount;
+
+	if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
+		process_amount *= p_particles->trail_bind_poses.size();
+	}
+	push_constant.clear = p_particles->clear;
+	push_constant.total_particles = p_particles->amount;
+	push_constant.lifetime = p_particles->lifetime;
+	push_constant.trail_size = p_particles->trail_params.size();
+	push_constant.use_fractional_delta = p_particles->fractional_delta;
+	push_constant.sub_emitter_mode = !p_particles->emitting && p_particles->emission_buffer && (p_particles->emission_buffer->particle_count > 0 || p_particles->force_sub_emit);
+	push_constant.trail_pass = false;
+
+	p_particles->force_sub_emit = false; //reset
+
+	Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
+
+	if (sub_emitter && sub_emitter->emission_storage_buffer.is_valid()) {
+		//	print_line("updating subemitter buffer");
+		int32_t zero[4] = { 0, sub_emitter->amount, 0, 0 };
+		RD::get_singleton()->buffer_update(sub_emitter->emission_storage_buffer, 0, sizeof(uint32_t) * 4, zero);
+		push_constant.can_emit = true;
+
+		if (sub_emitter->emitting) {
+			sub_emitter->emitting = false;
+			sub_emitter->clear = true; //will need to clear if it was emitting, sorry
+		}
+		//make sure the sub emitter processes particles too
+		sub_emitter->inactive = false;
+		sub_emitter->inactive_time = 0;
+
+		sub_emitter->force_sub_emit = true;
+
+	} else {
+		push_constant.can_emit = false;
+	}
+
+	if (p_particles->emission_buffer && p_particles->emission_buffer->particle_count) {
+		RD::get_singleton()->buffer_update(p_particles->emission_storage_buffer, 0, sizeof(uint32_t) * 4 + sizeof(ParticleEmissionBuffer::Data) * p_particles->emission_buffer->particle_count, p_particles->emission_buffer);
+		p_particles->emission_buffer->particle_count = 0;
+	}
+
+	p_particles->clear = false;
+
+	if (p_particles->trail_params.size() > 1) {
+		//fill the trail params
+		for (uint32_t i = 0; i < p_particles->trail_params.size(); i++) {
+			uint32_t src_idx = i * p_particles->frame_history.size() / p_particles->trail_params.size();
+			p_particles->trail_params[i] = p_particles->frame_history[src_idx];
+		}
+	} else {
+		p_particles->trail_params[0] = p_particles->frame_history[0];
+	}
+
+	RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
+
+	ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES));
+	if (!m) {
+		m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+	}
+
+	ERR_FAIL_COND(!m);
+
+	p_particles->has_collision_cache = m->shader_data->uses_collision;
+
+	//todo should maybe compute all particle systems together?
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles_shader.base_uniform_set, 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, 1);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, 2);
+
+	if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) {
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3);
+	}
+
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
+
+	if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
+		//trails requires two passes in order to catch particle starts
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount / p_particles->trail_bind_poses.size(), 1, 1);
+
+		RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+		push_constant.trail_pass = true;
+		RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount - p_particles->amount, 1, 1);
+	} else {
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount, 1, 1);
+	}
+
+	RD::get_singleton()->compute_list_end();
+}
+
+void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+	Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND(!particles);
+
+	if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+		return;
+	}
+
+	if (particles->particle_buffer.is_null()) {
+		return; //particles have not processed yet
+	}
+
+	bool do_sort = particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH;
+
+	//copy to sort buffer
+	if (do_sort && particles->particles_sort_buffer == RID()) {
+		uint32_t size = particles->amount;
+		if (size & 1) {
+			size++; //make multiple of 16
+		}
+		size *= sizeof(float) * 2;
+		particles->particles_sort_buffer = RD::get_singleton()->storage_buffer_create(size);
+
+		{
+			Vector<RD::Uniform> uniforms;
+
+			{
+				RD::Uniform u;
+				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+				u.binding = 0;
+				u.append_id(particles->particles_sort_buffer);
+				uniforms.push_back(u);
+			}
+
+			particles->particles_sort_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, ParticlesShader::COPY_MODE_FILL_SORT_BUFFER), 1);
+		}
+	}
+
+	ParticlesShader::CopyPushConstant copy_push_constant;
+
+	if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+		int fixed_fps = 60.0;
+		if (particles->fixed_fps > 0) {
+			fixed_fps = particles->fixed_fps;
+		}
+
+		copy_push_constant.trail_size = particles->trail_bind_poses.size();
+		copy_push_constant.trail_total = particles->frame_history.size();
+		copy_push_constant.frame_delta = 1.0 / fixed_fps;
+	} else {
+		copy_push_constant.trail_size = 1;
+		copy_push_constant.trail_total = 1;
+		copy_push_constant.frame_delta = 0.0;
+	}
+
+	copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
+	copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+	copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+
+	copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
+	copy_push_constant.total_particles = particles->amount;
+	copy_push_constant.copy_mode_2d = false;
+
+	Vector3 axis = -p_axis; // cameras look to z negative
+
+	if (particles->use_local_coords) {
+		axis = particles->emission_transform.basis.xform_inv(axis).normalized();
+	}
+
+	copy_push_constant.sort_direction[0] = axis.x;
+	copy_push_constant.sort_direction[1] = axis.y;
+	copy_push_constant.sort_direction[2] = axis.z;
+
+	copy_push_constant.align_up[0] = p_up_axis.x;
+	copy_push_constant.align_up[1] = p_up_axis.y;
+	copy_push_constant.align_up[2] = p_up_axis.z;
+
+	copy_push_constant.align_mode = particles->transform_align;
+
+	if (do_sort) {
+		RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
+		RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
+
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
+
+		RD::get_singleton()->compute_list_end();
+		RendererStorageRD::base_singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
+	}
+
+	copy_push_constant.total_particles *= copy_push_constant.total_particles;
+
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES;
+	copy_pipeline += particles->userdata_count * ParticlesShader::COPY_MODE_MAX;
+	copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[copy_pipeline]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
+	if (do_sort) {
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
+	}
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
+
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
+
+	RD::get_singleton()->compute_list_dispatch_threads(compute_list, copy_push_constant.total_particles, 1, 1);
+
+	RD::get_singleton()->compute_list_end();
+}
+
+void ParticlesStorage::_particles_update_buffers(Particles *particles) {
+	uint32_t userdata_count = 0;
+
+	const Material *material = MaterialStorage::get_singleton()->get_material(particles->process_material);
+	if (material && material->shader && material->shader->data) {
+		const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data);
+		userdata_count = shader_data->userdata_count;
+	}
+
+	if (userdata_count != particles->userdata_count) {
+		// Mismatch userdata, re-create buffers.
+		_particles_free_data(particles);
+	}
+
+	if (particles->amount > 0 && particles->particle_buffer.is_null()) {
+		int total_amount = particles->amount;
+		if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+			total_amount *= particles->trail_bind_poses.size();
+		}
+
+		uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3;
+
+		particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount);
+
+		particles->userdata_count = userdata_count;
+
+		particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount);
+		//needs to clear it
+
+		{
+			Vector<RD::Uniform> uniforms;
+
+			{
+				RD::Uniform u;
+				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+				u.binding = 1;
+				u.append_id(particles->particle_buffer);
+				uniforms.push_back(u);
+			}
+			{
+				RD::Uniform u;
+				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+				u.binding = 2;
+				u.append_id(particles->particle_instance_buffer);
+				uniforms.push_back(u);
+			}
+
+			particles->particles_copy_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 0);
+		}
+	}
+}
+void ParticlesStorage::update_particles() {
+	while (particle_update_list) {
+		//use transform feedback to process particles
+
+		Particles *particles = particle_update_list;
+
+		//take and remove
+		particle_update_list = particles->update_list;
+		particles->update_list = nullptr;
+		particles->dirty = false;
+
+		_particles_update_buffers(particles);
+
+		if (particles->restart_request) {
+			particles->prev_ticks = 0;
+			particles->phase = 0;
+			particles->prev_phase = 0;
+			particles->clear = true;
+			particles->restart_request = false;
+		}
+
+		if (particles->inactive && !particles->emitting) {
+			//go next
+			continue;
+		}
+
+		if (particles->emitting) {
+			if (particles->inactive) {
+				//restart system from scratch
+				particles->prev_ticks = 0;
+				particles->phase = 0;
+				particles->prev_phase = 0;
+				particles->clear = true;
+			}
+			particles->inactive = false;
+			particles->inactive_time = 0;
+		} else {
+			particles->inactive_time += particles->speed_scale * RendererCompositorRD::singleton->get_frame_delta_time();
+			if (particles->inactive_time > particles->lifetime * 1.2) {
+				particles->inactive = true;
+				continue;
+			}
+		}
+
+#ifndef _MSC_VER
+#warning Should use display refresh rate for all this
+#endif
+
+		float screen_hz = 60;
+
+		int fixed_fps = 0;
+		if (particles->fixed_fps > 0) {
+			fixed_fps = particles->fixed_fps;
+		} else if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+			fixed_fps = screen_hz;
+		}
+		{
+			//update trails
+			int history_size = 1;
+			int trail_steps = 1;
+			if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+				history_size = MAX(1, int(particles->trail_length * fixed_fps));
+				trail_steps = particles->trail_bind_poses.size();
+			}
+
+			if (uint32_t(history_size) != particles->frame_history.size()) {
+				particles->frame_history.resize(history_size);
+				memset(particles->frame_history.ptr(), 0, sizeof(ParticlesFrameParams) * history_size);
+			}
+
+			if (uint32_t(trail_steps) != particles->trail_params.size() || particles->frame_params_buffer.is_null()) {
+				particles->trail_params.resize(trail_steps);
+				if (particles->frame_params_buffer.is_valid()) {
+					RD::get_singleton()->free(particles->frame_params_buffer);
+				}
+				particles->frame_params_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticlesFrameParams) * trail_steps);
+			}
+
+			if (particles->trail_bind_poses.size() > 1 && particles->trail_bind_pose_buffer.is_null()) {
+				particles->trail_bind_pose_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 16 * particles->trail_bind_poses.size());
+				particles->trail_bind_poses_dirty = true;
+			}
+
+			if (particles->trail_bind_pose_uniform_set.is_null()) {
+				Vector<RD::Uniform> uniforms;
+				{
+					RD::Uniform u;
+					u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+					u.binding = 0;
+					if (particles->trail_bind_pose_buffer.is_valid()) {
+						u.append_id(particles->trail_bind_pose_buffer);
+					} else {
+						u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer());
+					}
+					uniforms.push_back(u);
+				}
+
+				particles->trail_bind_pose_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 2);
+			}
+
+			if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses_dirty) {
+				if (particles_shader.pose_update_buffer.size() < uint32_t(particles->trail_bind_poses.size()) * 16) {
+					particles_shader.pose_update_buffer.resize(particles->trail_bind_poses.size() * 16);
+				}
+
+				for (int i = 0; i < particles->trail_bind_poses.size(); i++) {
+					RendererStorageRD::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]);
+				}
+
+				RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr());
+			}
+		}
+
+		bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
+
+		if (particles->clear && particles->pre_process_time > 0.0) {
+			double frame_time;
+			if (fixed_fps > 0) {
+				frame_time = 1.0 / fixed_fps;
+			} else {
+				frame_time = 1.0 / 30.0;
+			}
+
+			double todo = particles->pre_process_time;
+
+			while (todo >= 0) {
+				_particles_process(particles, frame_time);
+				todo -= frame_time;
+			}
+		}
+
+		if (fixed_fps > 0) {
+			double frame_time;
+			double decr;
+			if (zero_time_scale) {
+				frame_time = 0.0;
+				decr = 1.0 / fixed_fps;
+			} else {
+				frame_time = 1.0 / fixed_fps;
+				decr = frame_time;
+			}
+			double delta = RendererCompositorRD::singleton->get_frame_delta_time();
+			if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
+				delta = 0.1;
+			} else if (delta <= 0.0) { //unlikely but..
+				delta = 0.001;
+			}
+			double todo = particles->frame_remainder + delta;
+
+			while (todo >= frame_time) {
+				_particles_process(particles, frame_time);
+				todo -= decr;
+			}
+
+			particles->frame_remainder = todo;
+
+		} else {
+			if (zero_time_scale) {
+				_particles_process(particles, 0.0);
+			} else {
+				_particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time());
+			}
+		}
+
+		//copy particles to instance buffer
+
+		if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+			//does not need view dependent operation, do copy here
+			ParticlesShader::CopyPushConstant copy_push_constant;
+
+			int total_amount = particles->amount;
+			if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+				total_amount *= particles->trail_bind_poses.size();
+			}
+
+			// Affect 2D only.
+			if (particles->use_local_coords) {
+				// In local mode, particle positions are calculated locally (relative to the node position)
+				// and they're also drawn locally.
+				// It works as expected, so we just pass an identity transform.
+				RendererStorageRD::store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
+			} else {
+				// In global mode, particle positions are calculated globally (relative to the canvas origin)
+				// but they're drawn locally.
+				// So, we need to pass the inverse of the emission transform to bring the
+				// particles to local coordinates before drawing.
+				Transform3D inv = particles->emission_transform.affine_inverse();
+				RendererStorageRD::store_transform(inv, copy_push_constant.inv_emission_transform);
+			}
+
+			copy_push_constant.total_particles = total_amount;
+			copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
+			copy_push_constant.align_mode = particles->transform_align;
+			copy_push_constant.align_up[0] = 0;
+			copy_push_constant.align_up[1] = 0;
+			copy_push_constant.align_up[2] = 0;
+
+			if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+				copy_push_constant.trail_size = particles->trail_bind_poses.size();
+				copy_push_constant.trail_total = particles->frame_history.size();
+				copy_push_constant.frame_delta = 1.0 / fixed_fps;
+			} else {
+				copy_push_constant.trail_size = 1;
+				copy_push_constant.trail_total = 1;
+				copy_push_constant.frame_delta = 0.0;
+			}
+
+			copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
+			copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+			copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+
+			RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+			copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
+			RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
+			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
+			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
+			RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
+
+			RD::get_singleton()->compute_list_dispatch_threads(compute_list, total_amount, 1, 1);
+
+			RD::get_singleton()->compute_list_end();
+		}
+
+		particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+	}
+}
+
+bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
+	ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
+	const Particles *particles = particles_owner.get_or_null(p_particles);
+	ERR_FAIL_COND_V(!particles, false);
+	return !particles->emitting && particles->inactive;
+}
+
+/* Particles SHADER */
+
+void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
+	ParticlesStorage *particles_storage = ParticlesStorage::get_singleton();
+	//compile
+
+	code = p_code;
+	valid = false;
+	ubo_size = 0;
+	uniforms.clear();
+	uses_collision = false;
+
+	if (code.is_empty()) {
+		return; //just invalid, but no error
+	}
+
+	ShaderCompiler::GeneratedCode gen_code;
+	ShaderCompiler::IdentifierActions actions;
+	actions.entry_point_stages["start"] = ShaderCompiler::STAGE_COMPUTE;
+	actions.entry_point_stages["process"] = ShaderCompiler::STAGE_COMPUTE;
+
+	/*
+	uses_time = false;
+
+	actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
+	actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
+
+	actions.usage_flag_pointers["TIME"] = &uses_time;
+*/
+
+	actions.usage_flag_pointers["COLLIDED"] = &uses_collision;
+
+	userdata_count = 0;
+	for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+		userdatas_used[i] = false;
+		actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i];
+	}
+
+	actions.uniforms = &uniforms;
+
+	Error err = particles_storage->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
+	ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+
+	if (version.is_null()) {
+		version = particles_storage->particles_shader.shader.version_create();
+	}
+
+	for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+		if (userdatas_used[i]) {
+			userdata_count++;
+		}
+	}
+
+	particles_storage->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
+	ERR_FAIL_COND(!particles_storage->particles_shader.shader.version_is_valid(version));
+
+	ubo_size = gen_code.uniform_total_size;
+	ubo_offsets = gen_code.uniform_offsets;
+	texture_uniforms = gen_code.texture_uniforms;
+
+	//update pipelines
+
+	pipeline = RD::get_singleton()->compute_pipeline_create(particles_storage->particles_shader.shader.version_get_shader(version, 0));
+
+	valid = true;
+}
+
+void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+	if (!p_texture.is_valid()) {
+		if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+			default_texture_params[p_name].erase(p_index);
+
+			if (default_texture_params[p_name].is_empty()) {
+				default_texture_params.erase(p_name);
+			}
+		}
+	} else {
+		if (!default_texture_params.has(p_name)) {
+			default_texture_params[p_name] = Map<int, RID>();
+		}
+		default_texture_params[p_name][p_index] = p_texture;
+	}
+}
+
+void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+	Map<int, StringName> order;
+
+	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+		if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+			continue;
+		}
+
+		if (E.value.texture_order >= 0) {
+			order[E.value.texture_order + 100000] = E.key;
+		} else {
+			order[E.value.order] = E.key;
+		}
+	}
+
+	for (const KeyValue<int, StringName> &E : order) {
+		PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+		pi.name = E.value;
+		p_param_list->push_back(pi);
+	}
+}
+
+void ParticlesStorage::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+		if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+			continue;
+		}
+
+		RendererMaterialStorage::InstanceShaderParam p;
+		p.info = ShaderLanguage::uniform_to_property_info(E.value);
+		p.info.name = E.key; //supply name
+		p.index = E.value.instance_index;
+		p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
+		p_param_list->push_back(p);
+	}
+}
+
+bool ParticlesStorage::ParticlesShaderData::is_param_texture(const StringName &p_param) const {
+	if (!uniforms.has(p_param)) {
+		return false;
+	}
+
+	return uniforms[p_param].texture_order >= 0;
+}
+
+bool ParticlesStorage::ParticlesShaderData::is_animated() const {
+	return false;
+}
+
+bool ParticlesStorage::ParticlesShaderData::casts_shadows() const {
+	return false;
+}
+
+Variant ParticlesStorage::ParticlesShaderData::get_default_parameter(const StringName &p_parameter) const {
+	if (uniforms.has(p_parameter)) {
+		ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+		Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+		return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+	}
+	return Variant();
+}
+
+RS::ShaderNativeSourceCode ParticlesStorage::ParticlesShaderData::get_native_source_code() const {
+	return ParticlesStorage::get_singleton()->particles_shader.shader.version_get_native_source_code(version);
+}
+
+ParticlesStorage::ParticlesShaderData::ParticlesShaderData() {
+	valid = false;
+}
+
+ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() {
+	//pipeline variants will clear themselves if shader is gone
+	if (version.is_valid()) {
+		ParticlesStorage::get_singleton()->particles_shader.shader.version_free(version);
+	}
+}
+
+ShaderData *ParticlesStorage::_create_particles_shader_func() {
+	ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
+	return shader_data;
+}
+
+bool ParticlesStorage::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+	return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3);
+}
+
+ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() {
+	free_parameters_uniform_set(uniform_set);
+}
+
+MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) {
+	ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
+	material_data->shader_data = p_shader;
+	//update will happen later anyway so do nothing.
+	return material_data;
+}
+////////
+
+/* PARTICLES COLLISION API */
+
+RID ParticlesStorage::particles_collision_allocate() {
+	return particles_collision_owner.allocate_rid();
+}
+void ParticlesStorage::particles_collision_initialize(RID p_rid) {
+	particles_collision_owner.initialize_rid(p_rid, ParticlesCollision());
+}
+
+void ParticlesStorage::particles_collision_free(RID p_rid) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid);
+
+	if (particles_collision->heightfield_texture.is_valid()) {
+		RD::get_singleton()->free(particles_collision->heightfield_texture);
+	}
+	particles_collision->dependency.deleted_notify(p_rid);
+	particles_collision_owner.free(p_rid);
+}
+
+RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND_V(!particles_collision, RID());
+	ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID());
+
+	if (particles_collision->heightfield_texture == RID()) {
+		//create
+		int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 };
+		Size2i size;
+		if (particles_collision->extents.x > particles_collision->extents.z) {
+			size.x = resolutions[particles_collision->heightfield_resolution];
+			size.y = int32_t(particles_collision->extents.z / particles_collision->extents.x * size.x);
+		} else {
+			size.y = resolutions[particles_collision->heightfield_resolution];
+			size.x = int32_t(particles_collision->extents.x / particles_collision->extents.z * size.y);
+		}
+
+		RD::TextureFormat tf;
+		tf.format = RD::DATA_FORMAT_D32_SFLOAT;
+		tf.width = size.x;
+		tf.height = size.y;
+		tf.texture_type = RD::TEXTURE_TYPE_2D;
+		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+		particles_collision->heightfield_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+		Vector<RID> fb_tex;
+		fb_tex.push_back(particles_collision->heightfield_texture);
+		particles_collision->heightfield_fb = RD::get_singleton()->framebuffer_create(fb_tex);
+		particles_collision->heightfield_fb_size = size;
+	}
+
+	return particles_collision->heightfield_fb;
+}
+
+void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+
+	if (p_type == particles_collision->type) {
+		return;
+	}
+
+	if (particles_collision->heightfield_texture.is_valid()) {
+		RD::get_singleton()->free(particles_collision->heightfield_texture);
+		particles_collision->heightfield_texture = RID();
+	}
+	particles_collision->type = p_type;
+	particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+	particles_collision->cull_mask = p_cull_mask;
+}
+
+void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+
+	particles_collision->radius = p_radius;
+	particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+
+	particles_collision->extents = p_extents;
+	particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+
+	particles_collision->attractor_strength = p_strength;
+}
+
+void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+
+	particles_collision->attractor_directionality = p_directionality;
+}
+
+void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+
+	particles_collision->attractor_attenuation = p_curve;
+}
+
+void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+
+	particles_collision->field_texture = p_texture;
+}
+
+void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+	particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND(!particles_collision);
+	ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
+
+	if (particles_collision->heightfield_resolution == p_resolution) {
+		return;
+	}
+
+	particles_collision->heightfield_resolution = p_resolution;
+
+	if (particles_collision->heightfield_texture.is_valid()) {
+		RD::get_singleton()->free(particles_collision->heightfield_texture);
+		particles_collision->heightfield_texture = RID();
+	}
+}
+
+AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const {
+	ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND_V(!particles_collision, AABB());
+
+	switch (particles_collision->type) {
+		case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT:
+		case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+			AABB aabb;
+			aabb.position = -Vector3(1, 1, 1) * particles_collision->radius;
+			aabb.size = Vector3(2, 2, 2) * particles_collision->radius;
+			return aabb;
+		}
+		default: {
+			AABB aabb;
+			aabb.position = -particles_collision->extents;
+			aabb.size = particles_collision->extents * 2;
+			return aabb;
+		}
+	}
+
+	return AABB();
+}
+
+Vector3 ParticlesStorage::particles_collision_get_extents(RID p_particles_collision) const {
+	const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND_V(!particles_collision, Vector3());
+	return particles_collision->extents;
+}
+
+bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const {
+	const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+	ERR_FAIL_COND_V(!particles_collision, false);
+	return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
+}
+
+RID ParticlesStorage::particles_collision_instance_create(RID p_collision) {
+	ParticlesCollisionInstance pci;
+	pci.collision = p_collision;
+	return particles_collision_instance_owner.make_rid(pci);
+}
+
+void ParticlesStorage::particles_collision_instance_free(RID p_rid) {
+	particles_collision_instance_owner.free(p_rid);
+}
+
+void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
+	ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+	ERR_FAIL_COND(!pci);
+	pci->transform = p_transform;
+}
+
+void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+	ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+	ERR_FAIL_COND(!pci);
+	pci->active = p_active;
+}

+ 565 - 0
servers/rendering/renderer_rd/storage_rd/particles_storage.h

@@ -0,0 +1,565 @@
+/*************************************************************************/
+/*  particles_storage.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 PARTICLES_STORAGE_RD_H
+#define PARTICLES_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/shader_compiler.h"
+#include "servers/rendering/storage/particles_storage.h"
+
+namespace RendererRD {
+
+/* PARTICLES */
+
+struct ParticleData {
+	float xform[16];
+	float velocity[3];
+	uint32_t active;
+	float color[4];
+	float custom[3];
+	float lifetime;
+};
+
+struct ParticlesFrameParams {
+	enum {
+		MAX_ATTRACTORS = 32,
+		MAX_COLLIDERS = 32,
+		MAX_3D_TEXTURES = 7
+	};
+
+	enum AttractorType {
+		ATTRACTOR_TYPE_SPHERE,
+		ATTRACTOR_TYPE_BOX,
+		ATTRACTOR_TYPE_VECTOR_FIELD,
+	};
+
+	struct Attractor {
+		float transform[16];
+		float extents[3]; //exents or radius
+		uint32_t type;
+
+		uint32_t texture_index; //texture index for vector field
+		float strength;
+		float attenuation;
+		float directionality;
+	};
+
+	enum CollisionType {
+		COLLISION_TYPE_SPHERE,
+		COLLISION_TYPE_BOX,
+		COLLISION_TYPE_SDF,
+		COLLISION_TYPE_HEIGHT_FIELD,
+		COLLISION_TYPE_2D_SDF,
+
+	};
+
+	struct Collider {
+		float transform[16];
+		float extents[3]; //exents or radius
+		uint32_t type;
+
+		uint32_t texture_index; //texture index for vector field
+		real_t scale;
+		uint32_t pad[2];
+	};
+
+	uint32_t emitting;
+	float system_phase;
+	float prev_system_phase;
+	uint32_t cycle;
+
+	real_t explosiveness;
+	real_t randomness;
+	float time;
+	float delta;
+
+	uint32_t frame;
+	uint32_t pad0;
+	uint32_t pad1;
+	uint32_t pad2;
+
+	uint32_t random_seed;
+	uint32_t attractor_count;
+	uint32_t collider_count;
+	float particle_size;
+
+	float emission_transform[16];
+
+	Attractor attractors[MAX_ATTRACTORS];
+	Collider colliders[MAX_COLLIDERS];
+};
+
+struct ParticleEmissionBufferData {
+};
+
+struct ParticleEmissionBuffer {
+	struct Data {
+		float xform[16];
+		float velocity[3];
+		uint32_t flags;
+		float color[4];
+		float custom[4];
+	};
+
+	int32_t particle_count;
+	int32_t particle_max;
+	uint32_t pad1;
+	uint32_t pad2;
+	Data data[1]; //its 2020 and empty arrays are still non standard in C++
+};
+
+struct Particles {
+	RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
+	bool inactive = true;
+	double inactive_time = 0.0;
+	bool emitting = false;
+	bool one_shot = false;
+	int amount = 0;
+	double lifetime = 1.0;
+	double pre_process_time = 0.0;
+	real_t explosiveness = 0.0;
+	real_t randomness = 0.0;
+	bool restart_request = false;
+	AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
+	bool use_local_coords = true;
+	bool has_collision_cache = false;
+
+	bool has_sdf_collision = false;
+	Transform2D sdf_collision_transform;
+	Rect2 sdf_collision_to_screen;
+	RID sdf_collision_texture;
+
+	RID process_material;
+	uint32_t frame_counter = 0;
+	RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
+
+	RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
+
+	Vector<RID> draw_passes;
+	Vector<Transform3D> trail_bind_poses;
+	bool trail_bind_poses_dirty = false;
+	RID trail_bind_pose_buffer;
+	RID trail_bind_pose_uniform_set;
+
+	RID particle_buffer;
+	RID particle_instance_buffer;
+	RID frame_params_buffer;
+
+	uint32_t userdata_count = 0;
+
+	RID particles_material_uniform_set;
+	RID particles_copy_uniform_set;
+	RID particles_transforms_buffer_uniform_set;
+	RID collision_textures_uniform_set;
+
+	RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
+	uint32_t collision_3d_textures_used = 0;
+	RID collision_heightmap_texture;
+
+	RID particles_sort_buffer;
+	RID particles_sort_uniform_set;
+
+	bool dirty = false;
+	Particles *update_list = nullptr;
+
+	RID sub_emitter;
+
+	double phase = 0.0;
+	double prev_phase = 0.0;
+	uint64_t prev_ticks = 0;
+	uint32_t random_seed = 0;
+
+	uint32_t cycle_number = 0;
+
+	double speed_scale = 1.0;
+
+	int fixed_fps = 30;
+	bool interpolate = true;
+	bool fractional_delta = false;
+	double frame_remainder = 0;
+	real_t collision_base_size = 0.01;
+
+	bool clear = true;
+
+	bool force_sub_emit = false;
+
+	Transform3D emission_transform;
+
+	Vector<uint8_t> emission_buffer_data;
+
+	ParticleEmissionBuffer *emission_buffer = nullptr;
+	RID emission_storage_buffer;
+
+	Set<RID> collisions;
+
+	RendererStorage::Dependency dependency;
+
+	double trail_length = 1.0;
+	bool trails_enabled = false;
+	LocalVector<ParticlesFrameParams> frame_history;
+	LocalVector<ParticlesFrameParams> trail_params;
+
+	Particles() {
+	}
+};
+
+/* Particles Collision */
+
+struct ParticlesCollision {
+	RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
+	uint32_t cull_mask = 0xFFFFFFFF;
+	float radius = 1.0;
+	Vector3 extents = Vector3(1, 1, 1);
+	float attractor_strength = 1.0;
+	float attractor_attenuation = 1.0;
+	float attractor_directionality = 0.0;
+	RID field_texture;
+	RID heightfield_texture;
+	RID heightfield_fb;
+	Size2i heightfield_fb_size;
+
+	RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
+
+	RendererStorage::Dependency dependency;
+};
+
+struct ParticlesCollisionInstance {
+	RID collision;
+	Transform3D transform;
+	bool active = false;
+};
+
+class ParticlesStorage : public RendererParticlesStorage {
+private:
+	static ParticlesStorage *singleton;
+
+	/* PARTICLES */
+
+	void _particles_process(Particles *p_particles, double p_delta);
+	void _particles_allocate_emission_buffer(Particles *particles);
+	void _particles_free_data(Particles *particles);
+	void _particles_update_buffers(Particles *particles);
+
+	struct ParticlesShader {
+		struct PushConstant {
+			float lifetime;
+			uint32_t clear;
+			uint32_t total_particles;
+			uint32_t trail_size;
+
+			uint32_t use_fractional_delta;
+			uint32_t sub_emitter_mode;
+			uint32_t can_emit;
+			uint32_t trail_pass;
+		};
+
+		ParticlesShaderRD shader;
+		ShaderCompiler compiler;
+
+		RID default_shader;
+		RID default_material;
+		RID default_shader_rd;
+
+		RID base_uniform_set;
+
+		struct CopyPushConstant {
+			float sort_direction[3];
+			uint32_t total_particles;
+
+			uint32_t trail_size;
+			uint32_t trail_total;
+			float frame_delta;
+			float frame_remainder;
+
+			float align_up[3];
+			uint32_t align_mode;
+
+			uint32_t order_by_lifetime;
+			uint32_t lifetime_split;
+			uint32_t lifetime_reverse;
+			uint32_t copy_mode_2d;
+
+			float inv_emission_transform[16];
+		};
+
+		enum {
+			MAX_USERDATAS = 6
+		};
+		enum {
+			COPY_MODE_FILL_INSTANCES,
+			COPY_MODE_FILL_SORT_BUFFER,
+			COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER,
+			COPY_MODE_MAX,
+		};
+
+		ParticlesCopyShaderRD copy_shader;
+		RID copy_shader_version;
+		RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)];
+
+		LocalVector<float> pose_update_buffer;
+
+	} particles_shader;
+
+	Particles *particle_update_list = nullptr;
+
+	mutable RID_Owner<Particles, true> particles_owner;
+
+	/* Particle Shader */
+
+	struct ParticlesShaderData : public ShaderData {
+		bool valid;
+		RID version;
+		bool uses_collision = false;
+
+		//PipelineCacheRD pipelines[SKY_VERSION_MAX];
+		Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+		Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+		Vector<uint32_t> ubo_offsets;
+		uint32_t ubo_size;
+
+		String path;
+		String code;
+		Map<StringName, Map<int, RID>> default_texture_params;
+
+		RID pipeline;
+
+		bool uses_time = false;
+
+		bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {};
+		uint32_t userdata_count = 0;
+
+		virtual void set_code(const String &p_Code);
+		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
+		virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
+		virtual bool is_param_texture(const StringName &p_param) const;
+		virtual bool is_animated() const;
+		virtual bool casts_shadows() const;
+		virtual Variant get_default_parameter(const StringName &p_parameter) const;
+		virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
+		ParticlesShaderData();
+		virtual ~ParticlesShaderData();
+	};
+
+	ShaderData *_create_particles_shader_func();
+	static ShaderData *_create_particles_shader_funcs() {
+		return ParticlesStorage::get_singleton()->_create_particles_shader_func();
+	}
+
+	struct ParticlesMaterialData : public MaterialData {
+		ParticlesShaderData *shader_data = nullptr;
+		RID uniform_set;
+
+		virtual void set_render_priority(int p_priority) {}
+		virtual void set_next_pass(RID p_pass) {}
+		virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+		virtual ~ParticlesMaterialData();
+	};
+
+	MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
+	static MaterialData *_create_particles_material_funcs(ShaderData *p_shader) {
+		return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
+	}
+
+	/* Particles Collision */
+
+	mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
+
+	mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+
+public:
+	static ParticlesStorage *get_singleton();
+
+	ParticlesStorage();
+	virtual ~ParticlesStorage();
+
+	/* PARTICLES */
+
+	Particles *get_particles(RID p_rid) { return particles_owner.get_or_null(p_rid); }
+	bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
+
+	virtual RID particles_allocate() override;
+	virtual void particles_initialize(RID p_particles_collision) override;
+	virtual void particles_free(RID p_rid) override;
+
+	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
+	virtual void particles_set_emitting(RID p_particles, bool p_emitting) override;
+	virtual void particles_set_amount(RID p_particles, int p_amount) override;
+	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
+	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
+	virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
+	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
+	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
+	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
+	virtual void particles_set_speed_scale(RID p_particles, double p_scale) override;
+	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override;
+	virtual void particles_set_process_material(RID p_particles, RID p_material) override;
+	virtual RID particles_get_process_material(RID p_particles) const override;
+
+	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override;
+	virtual void particles_set_interpolate(RID p_particles, bool p_enable) override;
+	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
+	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
+	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
+
+	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
+	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
+
+	virtual void particles_restart(RID p_particles) override;
+	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override;
+
+	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override;
+
+	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override;
+
+	virtual void particles_set_draw_passes(RID p_particles, int p_count) override;
+	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override;
+
+	virtual void particles_request_process(RID p_particles) override;
+	virtual AABB particles_get_current_aabb(RID p_particles) override;
+	virtual AABB particles_get_aabb(RID p_particles) const override;
+
+	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
+
+	virtual bool particles_get_emitting(RID p_particles) override;
+	virtual int particles_get_draw_passes(RID p_particles) const override;
+	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override;
+
+	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override;
+
+	virtual bool particles_is_inactive(RID p_particles) const override;
+
+	_FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
+		Particles *particles = particles_owner.get_or_null(p_particles);
+		ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D);
+		return particles->mode;
+	}
+
+	_FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) {
+		Particles *particles = particles_owner.get_or_null(p_particles);
+		ERR_FAIL_COND_V(!particles, 0);
+
+		if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+			r_trail_divisor = particles->trail_bind_poses.size();
+		} else {
+			r_trail_divisor = 1;
+		}
+
+		return particles->amount * r_trail_divisor;
+	}
+
+	_FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
+		Particles *particles = particles_owner.get_or_null(p_particles);
+		ERR_FAIL_COND_V(!particles, 0);
+
+		return particles->has_collision_cache;
+	}
+
+	_FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
+		Particles *particles = particles_owner.get_or_null(p_particles);
+		ERR_FAIL_COND_V(!particles, false);
+
+		return particles->use_local_coords;
+	}
+
+	_FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) {
+		Particles *particles = particles_owner.get_or_null(p_particles);
+		ERR_FAIL_COND_V(!particles, RID());
+		if (particles->particles_transforms_buffer_uniform_set.is_null()) {
+			_particles_update_buffers(particles);
+
+			Vector<RD::Uniform> uniforms;
+
+			{
+				RD::Uniform u;
+				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+				u.binding = 0;
+				u.append_id(particles->particle_instance_buffer);
+				uniforms.push_back(u);
+			}
+
+			particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+		}
+
+		return particles->particles_transforms_buffer_uniform_set;
+	}
+
+	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override;
+	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override;
+	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
+
+	virtual void update_particles() override;
+
+	/* Particles Collision */
+
+	ParticlesCollision *get_particles_collision(RID p_rid) { return particles_collision_owner.get_or_null(p_rid); }
+	bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); }
+
+	virtual RID particles_collision_allocate() override;
+	virtual void particles_collision_initialize(RID p_particles_collision) override;
+	virtual void particles_collision_free(RID p_rid) override;
+
+	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override;
+	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override;
+	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override; //for spheres
+	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override; //for non-spheres
+	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override;
+	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override;
+	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override;
+	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override; //for SDF and vector field, heightfield is dynamic
+	virtual void particles_collision_height_field_update(RID p_particles_collision) override; //for SDF and vector field
+	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override; //for SDF and vector field
+	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
+	Vector3 particles_collision_get_extents(RID p_particles_collision) const;
+	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
+	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
+
+	//used from 2D and 3D
+	ParticlesCollisionInstance *get_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.get_or_null(p_rid); }
+	bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); }
+
+	virtual RID particles_collision_instance_create(RID p_collision) override;
+	virtual void particles_collision_instance_free(RID p_rid) override;
+	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override;
+	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override;
+};
+
+} // namespace RendererRD
+
+#endif // !PARTICLES_STORAGE_RD_H

+ 1315 - 3
servers/rendering/renderer_rd/storage_rd/texture_storage.cpp

@@ -29,10 +29,33 @@
 /*************************************************************************/
 
 #include "texture_storage.h"
-#include "decal_atlas_storage.h"
+
+#include "../renderer_storage_rd.h"
 
 using namespace RendererRD;
 
+///////////////////////////////////////////////////////////////////////////
+// CanvasTexture
+
+void CanvasTexture::clear_sets() {
+	if (cleared_cache) {
+		return;
+	}
+	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+			if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) {
+				RD::get_singleton()->free(uniform_sets[i][j]);
+				uniform_sets[i][j] = RID();
+			}
+		}
+	}
+	cleared_cache = true;
+}
+
+CanvasTexture::~CanvasTexture() {
+	clear_sets();
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Texture
 
@@ -315,9 +338,64 @@ TextureStorage::TextureStorage() {
 			default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
 		}
 	}
+
+	{ // default atlas texture
+		RD::TextureFormat tformat;
+		tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+		tformat.width = 4;
+		tformat.height = 4;
+		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+		tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+		Vector<uint8_t> pv;
+		pv.resize(16 * 4);
+
+		for (int i = 0; i < 16; i++) {
+			pv.set(i * 4 + 0, 0);
+			pv.set(i * 4 + 1, 0);
+			pv.set(i * 4 + 2, 0);
+			pv.set(i * 4 + 3, 255);
+		}
+
+		{
+			//take the chance and initialize decal atlas to something
+			Vector<Vector<uint8_t>> vpv;
+			vpv.push_back(pv);
+			decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+			decal_atlas.texture_srgb = decal_atlas.texture;
+		}
+	}
+
+	{
+		Vector<String> sdf_modes;
+		sdf_modes.push_back("\n#define MODE_LOAD\n");
+		sdf_modes.push_back("\n#define MODE_LOAD_SHRINK\n");
+		sdf_modes.push_back("\n#define MODE_PROCESS\n");
+		sdf_modes.push_back("\n#define MODE_PROCESS_OPTIMIZED\n");
+		sdf_modes.push_back("\n#define MODE_STORE\n");
+		sdf_modes.push_back("\n#define MODE_STORE_SHRINK\n");
+
+		rt_sdf.shader.initialize(sdf_modes);
+
+		rt_sdf.shader_version = rt_sdf.shader.version_create();
+
+		for (int i = 0; i < RenderTargetSDF::SHADER_MAX; i++) {
+			rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i));
+		}
+	}
 }
 
 TextureStorage::~TextureStorage() {
+	rt_sdf.shader.version_free(rt_sdf.shader_version);
+
+	if (decal_atlas.textures.size()) {
+		ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas.");
+	}
+
+	if (decal_atlas.texture.is_valid()) {
+		RD::get_singleton()->free(decal_atlas.texture);
+	}
+
 	//def textures
 	for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) {
 		if (default_rd_textures[i].is_valid()) {
@@ -332,6 +410,168 @@ bool TextureStorage::can_create_resources_async() const {
 	return true;
 }
 
+/* Canvas Texture API */
+
+RID TextureStorage::canvas_texture_allocate() {
+	return canvas_texture_owner.allocate_rid();
+}
+
+void TextureStorage::canvas_texture_initialize(RID p_rid) {
+	canvas_texture_owner.initialize_rid(p_rid);
+}
+
+void TextureStorage::canvas_texture_free(RID p_rid) {
+	canvas_texture_owner.free(p_rid);
+}
+
+void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
+	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+	ERR_FAIL_NULL(ct);
+
+	switch (p_channel) {
+		case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
+			ct->diffuse = p_texture;
+		} break;
+		case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
+			ct->normal_map = p_texture;
+		} break;
+		case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
+			ct->specular = p_texture;
+		} break;
+	}
+
+	ct->clear_sets();
+}
+
+void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
+	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+	ERR_FAIL_NULL(ct);
+
+	ct->specular_color.r = p_specular_color.r;
+	ct->specular_color.g = p_specular_color.g;
+	ct->specular_color.b = p_specular_color.b;
+	ct->specular_color.a = p_shininess;
+	ct->clear_sets();
+}
+
+void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
+	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+	ERR_FAIL_NULL(ct);
+
+	ct->texture_filter = p_filter;
+	ct->clear_sets();
+}
+
+void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
+	CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+	ERR_FAIL_NULL(ct);
+	ct->texture_repeat = p_repeat;
+	ct->clear_sets();
+}
+
+bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+	CanvasTexture *ct = nullptr;
+	Texture *t = get_texture(p_texture);
+
+	// TODO once we have our texture storage split off we'll look into moving this code into canvas_texture
+
+	if (t) {
+		//regular texture
+		if (!t->canvas_texture) {
+			t->canvas_texture = memnew(CanvasTexture);
+			t->canvas_texture->diffuse = p_texture;
+		}
+
+		ct = t->canvas_texture;
+	} else {
+		ct = get_canvas_texture(p_texture);
+	}
+
+	if (!ct) {
+		return false; //invalid texture RID
+	}
+
+	RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter;
+	ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false);
+
+	RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
+	ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
+
+	RID uniform_set = ct->uniform_sets[filter][repeat];
+	if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+		//create and update
+		Vector<RD::Uniform> uniforms;
+		{ //diffuse
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+			u.binding = 0;
+
+			t = get_texture(ct->diffuse);
+			if (!t) {
+				u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+				ct->size_cache = Size2i(1, 1);
+			} else {
+				u.append_id(t->rd_texture);
+				ct->size_cache = Size2i(t->width_2d, t->height_2d);
+			}
+			uniforms.push_back(u);
+		}
+		{ //normal
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+			u.binding = 1;
+
+			t = get_texture(ct->normal_map);
+			if (!t) {
+				u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
+				ct->use_normal_cache = false;
+			} else {
+				u.append_id(t->rd_texture);
+				ct->use_normal_cache = true;
+			}
+			uniforms.push_back(u);
+		}
+		{ //specular
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+			u.binding = 2;
+
+			t = get_texture(ct->specular);
+			if (!t) {
+				u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+				ct->use_specular_cache = false;
+			} else {
+				u.append_id(t->rd_texture);
+				ct->use_specular_cache = true;
+			}
+			uniforms.push_back(u);
+		}
+		{ //sampler
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+			u.binding = 3;
+			u.append_id(material_storage->sampler_rd_get_default(filter, repeat));
+			uniforms.push_back(u);
+		}
+
+		uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
+		ct->uniform_sets[filter][repeat] = uniform_set;
+		ct->cleared_cache = false;
+	}
+
+	r_uniform_set = uniform_set;
+	r_size = ct->size_cache;
+	r_specular_shininess = ct->specular_color;
+	r_use_normal = ct->use_normal_cache;
+	r_use_specular = ct->use_specular_cache;
+
+	return true;
+}
+
+/* Texture API */
+
 RID TextureStorage::texture_allocate() {
 	return texture_owner.allocate_rid();
 }
@@ -350,7 +590,7 @@ void TextureStorage::texture_free(RID p_texture) {
 		}
 	}
 
-	DecalAtlasStorage::get_singleton()->decal_atlas_remove_texture(p_texture);
+	decal_atlas_remove_texture(p_texture);
 
 	for (int i = 0; i < t->proxies.size(); i++) {
 		Texture *p = texture_owner.get_or_null(t->proxies[i]);
@@ -949,7 +1189,7 @@ void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
 	//delete last, so proxies can be updated
 	texture_owner.free(p_by_texture);
 
-	DecalAtlasStorage::get_singleton()->decal_atlas_mark_dirty_on_texture(p_texture);
+	decal_atlas_mark_dirty_on_texture(p_texture);
 }
 
 void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) {
@@ -1438,3 +1678,1075 @@ Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, T
 
 	return image;
 }
+
+/* DECAL API */
+
+RID TextureStorage::decal_atlas_get_texture() const {
+	return decal_atlas.texture;
+}
+
+RID TextureStorage::decal_atlas_get_texture_srgb() const {
+	return decal_atlas.texture_srgb;
+}
+
+RID TextureStorage::decal_allocate() {
+	return decal_owner.allocate_rid();
+}
+
+void TextureStorage::decal_initialize(RID p_decal) {
+	decal_owner.initialize_rid(p_decal, Decal());
+}
+
+void TextureStorage::decal_free(RID p_rid) {
+	Decal *decal = decal_owner.get_or_null(p_rid);
+	for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) {
+		if (decal->textures[i].is_valid() && owns_texture(decal->textures[i])) {
+			texture_remove_from_decal_atlas(decal->textures[i]);
+		}
+	}
+	decal->dependency.deleted_notify(p_rid);
+	decal_owner.free(p_rid);
+}
+
+void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND(!decal);
+	decal->extents = p_extents;
+	decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND(!decal);
+	ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX);
+
+	if (decal->textures[p_type] == p_texture) {
+		return;
+	}
+
+	ERR_FAIL_COND(p_texture.is_valid() && !owns_texture(p_texture));
+
+	if (decal->textures[p_type].is_valid() && owns_texture(decal->textures[p_type])) {
+		texture_remove_from_decal_atlas(decal->textures[p_type]);
+	}
+
+	decal->textures[p_type] = p_texture;
+
+	if (decal->textures[p_type].is_valid()) {
+		texture_add_to_decal_atlas(decal->textures[p_type]);
+	}
+
+	decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_DECAL);
+}
+
+void TextureStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND(!decal);
+	decal->emission_energy = p_energy;
+}
+
+void TextureStorage::decal_set_albedo_mix(RID p_decal, float p_mix) {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND(!decal);
+	decal->albedo_mix = p_mix;
+}
+
+void TextureStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND(!decal);
+	decal->modulate = p_modulate;
+}
+
+void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND(!decal);
+	decal->cull_mask = p_layers;
+	decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND(!decal);
+	decal->distance_fade = p_enabled;
+	decal->distance_fade_begin = p_begin;
+	decal->distance_fade_length = p_length;
+}
+
+void TextureStorage::decal_set_fade(RID p_decal, float p_above, float p_below) {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND(!decal);
+	decal->upper_fade = p_above;
+	decal->lower_fade = p_below;
+}
+
+void TextureStorage::decal_set_normal_fade(RID p_decal, float p_fade) {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND(!decal);
+	decal->normal_fade = p_fade;
+}
+
+void TextureStorage::decal_atlas_mark_dirty_on_texture(RID p_texture) {
+	if (decal_atlas.textures.has(p_texture)) {
+		//belongs to decal atlas..
+
+		decal_atlas.dirty = true; //mark it dirty since it was most likely modified
+	}
+}
+
+void TextureStorage::decal_atlas_remove_texture(RID p_texture) {
+	if (decal_atlas.textures.has(p_texture)) {
+		decal_atlas.textures.erase(p_texture);
+		//there is not much a point of making it dirty, just let it be.
+	}
+}
+
+AABB TextureStorage::decal_get_aabb(RID p_decal) const {
+	Decal *decal = decal_owner.get_or_null(p_decal);
+	ERR_FAIL_COND_V(!decal, AABB());
+
+	return AABB(-decal->extents, decal->extents * 2.0);
+}
+
+void TextureStorage::update_decal_atlas() {
+	EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
+	ERR_FAIL_NULL(effects);
+
+	if (!decal_atlas.dirty) {
+		return; //nothing to do
+	}
+
+	decal_atlas.dirty = false;
+
+	if (decal_atlas.texture.is_valid()) {
+		RD::get_singleton()->free(decal_atlas.texture);
+		decal_atlas.texture = RID();
+		decal_atlas.texture_srgb = RID();
+		decal_atlas.texture_mipmaps.clear();
+	}
+
+	int border = 1 << decal_atlas.mipmaps;
+
+	if (decal_atlas.textures.size()) {
+		//generate atlas
+		Vector<DecalAtlas::SortItem> itemsv;
+		itemsv.resize(decal_atlas.textures.size());
+		int base_size = 8;
+		const RID *K = nullptr;
+
+		int idx = 0;
+		while ((K = decal_atlas.textures.next(K))) {
+			DecalAtlas::SortItem &si = itemsv.write[idx];
+
+			Texture *src_tex = get_texture(*K);
+
+			si.size.width = (src_tex->width / border) + 1;
+			si.size.height = (src_tex->height / border) + 1;
+			si.pixel_size = Size2i(src_tex->width, src_tex->height);
+
+			if (base_size < si.size.width) {
+				base_size = nearest_power_of_2_templated(si.size.width);
+			}
+
+			si.texture = *K;
+			idx++;
+		}
+
+		//sort items by size
+		itemsv.sort();
+
+		//attempt to create atlas
+		int item_count = itemsv.size();
+		DecalAtlas::SortItem *items = itemsv.ptrw();
+
+		int atlas_height = 0;
+
+		while (true) {
+			Vector<int> v_offsetsv;
+			v_offsetsv.resize(base_size);
+
+			int *v_offsets = v_offsetsv.ptrw();
+			memset(v_offsets, 0, sizeof(int) * base_size);
+
+			int max_height = 0;
+
+			for (int i = 0; i < item_count; i++) {
+				//best fit
+				DecalAtlas::SortItem &si = items[i];
+				int best_idx = -1;
+				int best_height = 0x7FFFFFFF;
+				for (int j = 0; j <= base_size - si.size.width; j++) {
+					int height = 0;
+					for (int k = 0; k < si.size.width; k++) {
+						int h = v_offsets[k + j];
+						if (h > height) {
+							height = h;
+							if (height > best_height) {
+								break; //already bad
+							}
+						}
+					}
+
+					if (height < best_height) {
+						best_height = height;
+						best_idx = j;
+					}
+				}
+
+				//update
+				for (int k = 0; k < si.size.width; k++) {
+					v_offsets[k + best_idx] = best_height + si.size.height;
+				}
+
+				si.pos.x = best_idx;
+				si.pos.y = best_height;
+
+				if (si.pos.y + si.size.height > max_height) {
+					max_height = si.pos.y + si.size.height;
+				}
+			}
+
+			if (max_height <= base_size * 2) {
+				atlas_height = max_height;
+				break; //good ratio, break;
+			}
+
+			base_size *= 2;
+		}
+
+		decal_atlas.size.width = base_size * border;
+		decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border);
+
+		for (int i = 0; i < item_count; i++) {
+			DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture);
+			t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2);
+			t->uv_rect.size = items[i].pixel_size;
+
+			t->uv_rect.position /= Size2(decal_atlas.size);
+			t->uv_rect.size /= Size2(decal_atlas.size);
+		}
+	} else {
+		//use border as size, so it at least has enough mipmaps
+		decal_atlas.size.width = border;
+		decal_atlas.size.height = border;
+	}
+
+	//blit textures
+
+	RD::TextureFormat tformat;
+	tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+	tformat.width = decal_atlas.size.width;
+	tformat.height = decal_atlas.size.height;
+	tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+	tformat.texture_type = RD::TEXTURE_TYPE_2D;
+	tformat.mipmaps = decal_atlas.mipmaps;
+	tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM);
+	tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB);
+
+	decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+	RD::get_singleton()->texture_clear(decal_atlas.texture, Color(0, 0, 0, 0), 0, decal_atlas.mipmaps, 0, 1);
+
+	{
+		//create the framebuffer
+
+		Size2i s = decal_atlas.size;
+
+		for (int i = 0; i < decal_atlas.mipmaps; i++) {
+			DecalAtlas::MipMap mm;
+			mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i);
+			Vector<RID> fb;
+			fb.push_back(mm.texture);
+			mm.fb = RD::get_singleton()->framebuffer_create(fb);
+			mm.size = s;
+			decal_atlas.texture_mipmaps.push_back(mm);
+
+			s.width = MAX(1, s.width >> 1);
+			s.height = MAX(1, s.height >> 1);
+		}
+		{
+			//create the SRGB variant
+			RD::TextureView rd_view;
+			rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+			decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture);
+		}
+	}
+
+	RID prev_texture;
+	for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) {
+		const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i];
+
+		Color clear_color(0, 0, 0, 0);
+
+		if (decal_atlas.textures.size()) {
+			if (i == 0) {
+				Vector<Color> cc;
+				cc.push_back(clear_color);
+
+				RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
+
+				const RID *K = nullptr;
+				while ((K = decal_atlas.textures.next(K))) {
+					DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
+					Texture *src_tex = get_texture(*K);
+					effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
+				}
+
+				RD::get_singleton()->draw_list_end();
+
+				prev_texture = mm.texture;
+			} else {
+				effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
+				prev_texture = mm.texture;
+			}
+		} else {
+			RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1);
+		}
+	}
+}
+
+void TextureStorage::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
+	if (!decal_atlas.textures.has(p_texture)) {
+		DecalAtlas::Texture t;
+		t.users = 1;
+		t.panorama_to_dp_users = p_panorama_to_dp ? 1 : 0;
+		decal_atlas.textures[p_texture] = t;
+		decal_atlas.dirty = true;
+	} else {
+		DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+		t->users++;
+		if (p_panorama_to_dp) {
+			t->panorama_to_dp_users++;
+		}
+	}
+}
+
+void TextureStorage::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
+	DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+	ERR_FAIL_COND(!t);
+	t->users--;
+	if (p_panorama_to_dp) {
+		ERR_FAIL_COND(t->panorama_to_dp_users == 0);
+		t->panorama_to_dp_users--;
+	}
+	if (t->users == 0) {
+		decal_atlas.textures.erase(p_texture);
+		//do not mark it dirty, there is no need to since it remains working
+	}
+}
+
+/* RENDER TARGET API */
+
+void TextureStorage::_clear_render_target(RenderTarget *rt) {
+	//free in reverse dependency order
+	if (rt->framebuffer.is_valid()) {
+		RD::get_singleton()->free(rt->framebuffer);
+		rt->framebuffer_uniform_set = RID(); //chain deleted
+	}
+
+	if (rt->color.is_valid()) {
+		RD::get_singleton()->free(rt->color);
+	}
+
+	if (rt->backbuffer.is_valid()) {
+		RD::get_singleton()->free(rt->backbuffer);
+		rt->backbuffer = RID();
+		rt->backbuffer_mipmaps.clear();
+		rt->backbuffer_uniform_set = RID(); //chain deleted
+	}
+
+	_render_target_clear_sdf(rt);
+
+	rt->framebuffer = RID();
+	rt->color = RID();
+}
+
+void TextureStorage::_update_render_target(RenderTarget *rt) {
+	if (rt->texture.is_null()) {
+		//create a placeholder until updated
+		rt->texture = texture_allocate();
+		texture_2d_placeholder_initialize(rt->texture);
+		Texture *tex = get_texture(rt->texture);
+		tex->is_render_target = true;
+	}
+
+	_clear_render_target(rt);
+
+	if (rt->size.width == 0 || rt->size.height == 0) {
+		return;
+	}
+	//until we implement support for HDR monitors (and render target is attached to screen), this is enough.
+	rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+	rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+	rt->image_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
+
+	RD::TextureFormat rd_format;
+	RD::TextureView rd_view;
+	{ //attempt register
+		rd_format.format = rt->color_format;
+		rd_format.width = rt->size.width;
+		rd_format.height = rt->size.height;
+		rd_format.depth = 1;
+		rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
+		rd_format.mipmaps = 1;
+		if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
+			rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+		} else {
+			rd_format.texture_type = RD::TEXTURE_TYPE_2D;
+		}
+		rd_format.samples = RD::TEXTURE_SAMPLES_1;
+		rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+		rd_format.shareable_formats.push_back(rt->color_format);
+		rd_format.shareable_formats.push_back(rt->color_format_srgb);
+	}
+
+	rt->color = RD::get_singleton()->texture_create(rd_format, rd_view);
+	ERR_FAIL_COND(rt->color.is_null());
+
+	Vector<RID> fb_textures;
+	fb_textures.push_back(rt->color);
+	rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
+	if (rt->framebuffer.is_null()) {
+		_clear_render_target(rt);
+		ERR_FAIL_COND(rt->framebuffer.is_null());
+	}
+
+	{ //update texture
+
+		Texture *tex = get_texture(rt->texture);
+
+		//free existing textures
+		if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
+			RD::get_singleton()->free(tex->rd_texture);
+		}
+		if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
+			RD::get_singleton()->free(tex->rd_texture_srgb);
+		}
+
+		tex->rd_texture = RID();
+		tex->rd_texture_srgb = RID();
+
+		//create shared textures to the color buffer,
+		//so transparent can be supported
+		RD::TextureView view;
+		view.format_override = rt->color_format;
+		if (!rt->flags[RENDER_TARGET_TRANSPARENT]) {
+			view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		}
+		tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color);
+		if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
+			view.format_override = rt->color_format_srgb;
+			tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color);
+		}
+		tex->rd_view = view;
+		tex->width = rt->size.width;
+		tex->height = rt->size.height;
+		tex->width_2d = rt->size.width;
+		tex->height_2d = rt->size.height;
+		tex->rd_format = rt->color_format;
+		tex->rd_format_srgb = rt->color_format_srgb;
+		tex->format = rt->image_format;
+
+		Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
+		for (int i = 0; i < proxies.size(); i++) {
+			texture_proxy_update(proxies[i], rt->texture);
+		}
+	}
+}
+
+void TextureStorage::_create_render_target_backbuffer(RenderTarget *rt) {
+	ERR_FAIL_COND(rt->backbuffer.is_valid());
+
+	uint32_t mipmaps_required = Image::get_image_required_mipmaps(rt->size.width, rt->size.height, Image::FORMAT_RGBA8);
+	RD::TextureFormat tf;
+	tf.format = rt->color_format;
+	tf.width = rt->size.width;
+	tf.height = rt->size.height;
+	tf.texture_type = RD::TEXTURE_TYPE_2D;
+	tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+	tf.mipmaps = mipmaps_required;
+
+	rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+	RD::get_singleton()->set_resource_name(rt->backbuffer, "Render Target Back Buffer");
+	rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
+	RD::get_singleton()->set_resource_name(rt->backbuffer_mipmap0, "Back Buffer slice mipmap 0");
+
+	{
+		Vector<RID> fb_tex;
+		fb_tex.push_back(rt->backbuffer_mipmap0);
+		rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(fb_tex);
+	}
+
+	if (rt->framebuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->framebuffer_uniform_set)) {
+		//the new one will require the backbuffer.
+		RD::get_singleton()->free(rt->framebuffer_uniform_set);
+		rt->framebuffer_uniform_set = RID();
+	}
+	//create mipmaps
+	for (uint32_t i = 1; i < mipmaps_required; i++) {
+		RID mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i);
+		RD::get_singleton()->set_resource_name(mipmap, "Back Buffer slice mip: " + itos(i));
+
+		rt->backbuffer_mipmaps.push_back(mipmap);
+	}
+}
+
+RID TextureStorage::render_target_create() {
+	RenderTarget render_target;
+
+	render_target.was_used = false;
+	render_target.clear_requested = false;
+
+	for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
+		render_target.flags[i] = false;
+	}
+	_update_render_target(&render_target);
+	return render_target_owner.make_rid(render_target);
+}
+
+void TextureStorage::render_target_free(RID p_rid) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_rid);
+
+	_clear_render_target(rt);
+
+	if (rt->texture.is_valid()) {
+		Texture *tex = get_texture(rt->texture);
+		tex->is_render_target = false;
+		texture_free(rt->texture);
+	}
+
+	render_target_owner.free(p_rid);
+}
+
+void TextureStorage::render_target_set_position(RID p_render_target, int p_x, int p_y) {
+	//unused for this render target
+}
+
+void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	if (rt->size.x != p_width || rt->size.y != p_height || rt->view_count != p_view_count) {
+		rt->size.x = p_width;
+		rt->size.y = p_height;
+		rt->view_count = p_view_count;
+		_update_render_target(rt);
+	}
+}
+
+RID TextureStorage::render_target_get_texture(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+
+	return rt->texture;
+}
+
+void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
+}
+
+void TextureStorage::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	rt->flags[p_flag] = p_value;
+	_update_render_target(rt);
+}
+
+bool TextureStorage::render_target_was_used(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, false);
+	return rt->was_used;
+}
+
+void TextureStorage::render_target_set_as_unused(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	rt->was_used = false;
+}
+
+Size2 TextureStorage::render_target_get_size(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, Size2());
+
+	return rt->size;
+}
+
+RID TextureStorage::render_target_get_rd_framebuffer(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+
+	return rt->framebuffer;
+}
+
+RID TextureStorage::render_target_get_rd_texture(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+
+	return rt->color;
+}
+
+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());
+	return rt->backbuffer;
+}
+
+RID TextureStorage::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+
+	if (!rt->backbuffer.is_valid()) {
+		_create_render_target_backbuffer(rt);
+	}
+
+	return rt->backbuffer_fb;
+}
+
+void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	rt->clear_requested = true;
+	rt->clear_color = p_clear_color;
+}
+
+bool TextureStorage::render_target_is_clear_requested(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, false);
+	return rt->clear_requested;
+}
+
+Color TextureStorage::render_target_get_clear_request_color(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, Color());
+	return rt->clear_color;
+}
+
+void TextureStorage::render_target_disable_clear_request(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	rt->clear_requested = false;
+}
+
+void TextureStorage::render_target_do_clear_request(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	if (!rt->clear_requested) {
+		return;
+	}
+	Vector<Color> clear_colors;
+	clear_colors.push_back(rt->clear_color);
+	RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
+	RD::get_singleton()->draw_list_end();
+	rt->clear_requested = false;
+}
+
+void TextureStorage::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) {
+		return;
+	}
+
+	rt->sdf_oversize = p_size;
+	rt->sdf_scale = p_scale;
+
+	_render_target_clear_sdf(rt);
+}
+
+Rect2i TextureStorage::_render_target_get_sdf_rect(const RenderTarget *rt) const {
+	Size2i margin;
+	int scale;
+	switch (rt->sdf_oversize) {
+		case RS::VIEWPORT_SDF_OVERSIZE_100_PERCENT: {
+			scale = 100;
+		} break;
+		case RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT: {
+			scale = 120;
+		} break;
+		case RS::VIEWPORT_SDF_OVERSIZE_150_PERCENT: {
+			scale = 150;
+		} break;
+		case RS::VIEWPORT_SDF_OVERSIZE_200_PERCENT: {
+			scale = 200;
+		} break;
+		default: {
+		}
+	}
+
+	margin = (rt->size * scale / 100) - rt->size;
+
+	Rect2i r(Vector2i(), rt->size);
+	r.position -= margin;
+	r.size += margin * 2;
+
+	return r;
+}
+
+Rect2i TextureStorage::render_target_get_sdf_rect(RID p_render_target) const {
+	const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, Rect2i());
+
+	return _render_target_get_sdf_rect(rt);
+}
+
+void TextureStorage::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	rt->sdf_enabled = p_enabled;
+}
+
+bool TextureStorage::render_target_is_sdf_enabled(RID p_render_target) const {
+	const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, false);
+
+	return rt->sdf_enabled;
+}
+
+RID TextureStorage::render_target_get_sdf_texture(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+	if (rt->sdf_buffer_read.is_null()) {
+		// no texture, create a dummy one for the 2D uniform set
+		RD::TextureFormat tformat;
+		tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+		tformat.width = 4;
+		tformat.height = 4;
+		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+		tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+		Vector<uint8_t> pv;
+		pv.resize(16 * 4);
+		memset(pv.ptrw(), 0, 16 * 4);
+		Vector<Vector<uint8_t>> vpv;
+
+		rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+	}
+
+	return rt->sdf_buffer_read;
+}
+
+void TextureStorage::_render_target_allocate_sdf(RenderTarget *rt) {
+	ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_valid());
+	if (rt->sdf_buffer_read.is_valid()) {
+		RD::get_singleton()->free(rt->sdf_buffer_read);
+		rt->sdf_buffer_read = RID();
+	}
+
+	Size2i size = _render_target_get_sdf_rect(rt).size;
+
+	RD::TextureFormat tformat;
+	tformat.format = RD::DATA_FORMAT_R8_UNORM;
+	tformat.width = size.width;
+	tformat.height = size.height;
+	tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+	tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+	rt->sdf_buffer_write = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+	{
+		Vector<RID> write_fb;
+		write_fb.push_back(rt->sdf_buffer_write);
+		rt->sdf_buffer_write_fb = RD::get_singleton()->framebuffer_create(write_fb);
+	}
+
+	int scale;
+	switch (rt->sdf_scale) {
+		case RS::VIEWPORT_SDF_SCALE_100_PERCENT: {
+			scale = 100;
+		} break;
+		case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
+			scale = 50;
+		} break;
+		case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
+			scale = 25;
+		} break;
+		default: {
+			scale = 100;
+		} break;
+	}
+
+	rt->process_size = size * scale / 100;
+	rt->process_size.x = MAX(rt->process_size.x, 1);
+	rt->process_size.y = MAX(rt->process_size.y, 1);
+
+	tformat.format = RD::DATA_FORMAT_R16G16_SINT;
+	tformat.width = rt->process_size.width;
+	tformat.height = rt->process_size.height;
+	tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+
+	rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+	rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+	tformat.format = RD::DATA_FORMAT_R16_SNORM;
+	tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+	rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+	{
+		Vector<RD::Uniform> uniforms;
+		{
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+			u.binding = 1;
+			u.append_id(rt->sdf_buffer_write);
+			uniforms.push_back(u);
+		}
+		{
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+			u.binding = 2;
+			u.append_id(rt->sdf_buffer_read);
+			uniforms.push_back(u);
+		}
+		{
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+			u.binding = 3;
+			u.append_id(rt->sdf_buffer_process[0]);
+			uniforms.push_back(u);
+		}
+		{
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+			u.binding = 4;
+			u.append_id(rt->sdf_buffer_process[1]);
+			uniforms.push_back(u);
+		}
+
+		rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
+		RID aux2 = uniforms.write[2].get_id(0);
+		RID aux3 = uniforms.write[3].get_id(0);
+		uniforms.write[2].set_id(0, aux3);
+		uniforms.write[3].set_id(0, aux2);
+		rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
+	}
+}
+
+void TextureStorage::_render_target_clear_sdf(RenderTarget *rt) {
+	if (rt->sdf_buffer_read.is_valid()) {
+		RD::get_singleton()->free(rt->sdf_buffer_read);
+		rt->sdf_buffer_read = RID();
+	}
+	if (rt->sdf_buffer_write_fb.is_valid()) {
+		RD::get_singleton()->free(rt->sdf_buffer_write);
+		RD::get_singleton()->free(rt->sdf_buffer_process[0]);
+		RD::get_singleton()->free(rt->sdf_buffer_process[1]);
+		rt->sdf_buffer_write = RID();
+		rt->sdf_buffer_write_fb = RID();
+		rt->sdf_buffer_process[0] = RID();
+		rt->sdf_buffer_process[1] = RID();
+		rt->sdf_buffer_process_uniform_sets[0] = RID();
+		rt->sdf_buffer_process_uniform_sets[1] = RID();
+	}
+}
+
+RID TextureStorage::render_target_get_sdf_framebuffer(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+
+	if (rt->sdf_buffer_write_fb.is_null()) {
+		_render_target_allocate_sdf(rt);
+	}
+
+	return rt->sdf_buffer_write_fb;
+}
+void TextureStorage::render_target_sdf_process(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null());
+
+	RenderTargetSDF::PushConstant push_constant;
+
+	Rect2i r = _render_target_get_sdf_rect(rt);
+
+	push_constant.size[0] = r.size.width;
+	push_constant.size[1] = r.size.height;
+	push_constant.stride = 0;
+	push_constant.shift = 0;
+	push_constant.base_size[0] = r.size.width;
+	push_constant.base_size[1] = r.size.height;
+
+	bool shrink = false;
+
+	switch (rt->sdf_scale) {
+		case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
+			push_constant.size[0] >>= 1;
+			push_constant.size[1] >>= 1;
+			push_constant.shift = 1;
+			shrink = true;
+		} break;
+		case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
+			push_constant.size[0] >>= 2;
+			push_constant.size[1] >>= 2;
+			push_constant.shift = 2;
+			shrink = true;
+		} break;
+		default: {
+		};
+	}
+
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+	/* Load */
+
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_LOAD_SHRINK : RenderTargetSDF::SHADER_LOAD]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[1], 0); //fill [0]
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+
+	RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
+
+	/* Process */
+
+	int stride = nearest_power_of_2_templated(MAX(push_constant.size[0], push_constant.size[1]) / 2);
+
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[RenderTargetSDF::SHADER_PROCESS]);
+
+	RD::get_singleton()->compute_list_add_barrier(compute_list);
+	bool swap = false;
+
+	//jumpflood
+	while (stride > 0) {
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
+		push_constant.stride = stride;
+		RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+		RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
+		stride /= 2;
+		swap = !swap;
+		RD::get_singleton()->compute_list_add_barrier(compute_list);
+	}
+
+	/* Store */
+
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_STORE_SHRINK : RenderTargetSDF::SHADER_STORE]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+	RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
+
+	RD::get_singleton()->compute_list_end();
+}
+
+void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) {
+	EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
+	ERR_FAIL_NULL(effects);
+
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	if (!rt->backbuffer.is_valid()) {
+		_create_render_target_backbuffer(rt);
+	}
+
+	Rect2i region;
+	if (p_region == Rect2i()) {
+		region.size = rt->size;
+	} else {
+		region = Rect2i(Size2i(), rt->size).intersection(p_region);
+		if (region.size == Size2i()) {
+			return; //nothing to do
+		}
+	}
+
+	//single texture copy for backbuffer
+	//RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
+	effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+
+	if (!p_gen_mipmaps) {
+		return;
+	}
+	RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps");
+	//then mipmap blur
+	RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
+
+	for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
+		region.position.x >>= 1;
+		region.position.y >>= 1;
+		region.size.x = MAX(1, region.size.x >> 1);
+		region.size.y = MAX(1, region.size.y >> 1);
+
+		RID mipmap = rt->backbuffer_mipmaps[i];
+		effects->gaussian_blur(prev_texture, mipmap, region, true);
+		prev_texture = mipmap;
+	}
+	RD::get_singleton()->draw_command_end_label();
+}
+
+void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
+	ERR_FAIL_NULL(effects);
+
+	if (!rt->backbuffer.is_valid()) {
+		_create_render_target_backbuffer(rt);
+	}
+
+	Rect2i region;
+	if (p_region == Rect2i()) {
+		region.size = rt->size;
+	} else {
+		region = Rect2i(Size2i(), rt->size).intersection(p_region);
+		if (region.size == Size2i()) {
+			return; //nothing to do
+		}
+	}
+
+	//single texture copy for backbuffer
+	effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+}
+
+void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+
+	EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
+	ERR_FAIL_NULL(effects);
+
+	if (!rt->backbuffer.is_valid()) {
+		_create_render_target_backbuffer(rt);
+	}
+
+	Rect2i region;
+	if (p_region == Rect2i()) {
+		region.size = rt->size;
+	} else {
+		region = Rect2i(Size2i(), rt->size).intersection(p_region);
+		if (region.size == Size2i()) {
+			return; //nothing to do
+		}
+	}
+	RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps2");
+	//then mipmap blur
+	RID prev_texture = rt->backbuffer_mipmap0;
+
+	for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
+		region.position.x >>= 1;
+		region.position.y >>= 1;
+		region.size.x = MAX(1, region.size.x >> 1);
+		region.size.y = MAX(1, region.size.y >> 1);
+
+		RID mipmap = rt->backbuffer_mipmaps[i];
+		effects->gaussian_blur(prev_texture, mipmap, region, true);
+		prev_texture = mipmap;
+	}
+	RD::get_singleton()->draw_command_end_label();
+}
+
+RID TextureStorage::render_target_get_framebuffer_uniform_set(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+	return rt->framebuffer_uniform_set;
+}
+RID TextureStorage::render_target_get_backbuffer_uniform_set(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
+	return rt->backbuffer_uniform_set;
+}
+
+void TextureStorage::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	rt->framebuffer_uniform_set = p_uniform_set;
+}
+
+void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
+	RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+	ERR_FAIL_COND(!rt);
+	rt->backbuffer_uniform_set = p_uniform_set;
+}

+ 336 - 1
servers/rendering/renderer_rd/storage_rd/texture_storage.h

@@ -31,8 +31,9 @@
 #ifndef TEXTURE_STORAGE_RD_H
 #define TEXTURE_STORAGE_RD_H
 
-#include "canvas_texture_storage.h"
 #include "core/templates/rid_owner.h"
+#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
+#include "servers/rendering/renderer_storage.h"
 #include "servers/rendering/storage/texture_storage.h"
 
 namespace RendererRD {
@@ -54,6 +55,27 @@ enum DefaultRDTexture {
 	DEFAULT_RD_TEXTURE_MAX
 };
 
+class CanvasTexture {
+public:
+	RID diffuse;
+	RID normal_map;
+	RID specular;
+	Color specular_color = Color(1, 1, 1, 1);
+	float shininess = 1.0;
+
+	RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
+	RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
+	RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+
+	Size2i size_cache = Size2i(1, 1);
+	bool use_normal_cache = false;
+	bool use_specular_cache = false;
+	bool cleared_cache = true;
+
+	void clear_sets();
+	~CanvasTexture();
+};
+
 class Texture {
 public:
 	enum Type {
@@ -118,10 +140,138 @@ public:
 	void cleanup();
 };
 
+struct DecalAtlas {
+	struct Texture {
+		int panorama_to_dp_users;
+		int users;
+		Rect2 uv_rect;
+	};
+
+	struct SortItem {
+		RID texture;
+		Size2i pixel_size;
+		Size2i size;
+		Point2i pos;
+
+		bool operator<(const SortItem &p_item) const {
+			//sort larger to smaller
+			if (size.height == p_item.size.height) {
+				return size.width > p_item.size.width;
+			} else {
+				return size.height > p_item.size.height;
+			}
+		}
+	};
+
+	HashMap<RID, Texture> textures;
+	bool dirty = true;
+	int mipmaps = 5;
+
+	RID texture;
+	RID texture_srgb;
+	struct MipMap {
+		RID fb;
+		RID texture;
+		Size2i size;
+	};
+	Vector<MipMap> texture_mipmaps;
+
+	Size2i size;
+};
+
+struct Decal {
+	Vector3 extents = Vector3(1, 1, 1);
+	RID textures[RS::DECAL_TEXTURE_MAX];
+	float emission_energy = 1.0;
+	float albedo_mix = 1.0;
+	Color modulate = Color(1, 1, 1, 1);
+	uint32_t cull_mask = (1 << 20) - 1;
+	float upper_fade = 0.3;
+	float lower_fade = 0.3;
+	bool distance_fade = false;
+	float distance_fade_begin = 10;
+	float distance_fade_length = 1;
+	float normal_fade = 0.0;
+
+	RendererStorage::Dependency dependency;
+};
+
+struct RenderTarget {
+	Size2i size;
+	uint32_t view_count;
+	RID framebuffer;
+	RID color;
+
+	//used for retrieving from CPU
+	RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+	RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+	Image::Format image_format = Image::FORMAT_L8;
+
+	bool flags[RendererTextureStorage::RENDER_TARGET_FLAG_MAX];
+
+	bool sdf_enabled = false;
+
+	RID backbuffer; //used for effects
+	RID backbuffer_fb;
+	RID backbuffer_mipmap0;
+
+	Vector<RID> backbuffer_mipmaps;
+
+	RID framebuffer_uniform_set;
+	RID backbuffer_uniform_set;
+
+	RID sdf_buffer_write;
+	RID sdf_buffer_write_fb;
+	RID sdf_buffer_process[2];
+	RID sdf_buffer_read;
+	RID sdf_buffer_process_uniform_sets[2];
+	RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
+	RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
+	Size2i process_size;
+
+	//texture generated for this owner (nor RD).
+	RID texture;
+	bool was_used;
+
+	//clear request
+	bool clear_requested;
+	Color clear_color;
+};
+
+struct RenderTargetSDF {
+	enum {
+		SHADER_LOAD,
+		SHADER_LOAD_SHRINK,
+		SHADER_PROCESS,
+		SHADER_PROCESS_OPTIMIZED,
+		SHADER_STORE,
+		SHADER_STORE_SHRINK,
+		SHADER_MAX
+	};
+
+	struct PushConstant {
+		int32_t size[2];
+		int32_t stride;
+		int32_t shift;
+		int32_t base_size[2];
+		int32_t pad[2];
+	};
+
+	CanvasSdfShaderRD shader;
+	RID shader_version;
+	RID pipelines[SHADER_MAX];
+};
+
 class TextureStorage : public RendererTextureStorage {
 private:
 	static TextureStorage *singleton;
 
+	/* Canvas Texture API */
+
+	RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner;
+
+	/* Texture API */
+
 	//textures can be created from threads, so this RID_Owner is thread safe
 	mutable RID_Owner<Texture, true> texture_owner;
 
@@ -145,6 +295,25 @@ private:
 	Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format);
 	void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0, bool p_immediate = false);
 
+	/* DECAL API */
+
+	DecalAtlas decal_atlas;
+
+	mutable RID_Owner<Decal, true> decal_owner;
+
+	/* RENDER TARGET API */
+
+	mutable RID_Owner<RenderTarget> render_target_owner;
+
+	void _clear_render_target(RenderTarget *rt);
+	void _update_render_target(RenderTarget *rt);
+	void _create_render_target_backbuffer(RenderTarget *rt);
+	void _render_target_allocate_sdf(RenderTarget *rt);
+	void _render_target_clear_sdf(RenderTarget *rt);
+	Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
+
+	RenderTargetSDF rt_sdf;
+
 public:
 	static TextureStorage *get_singleton();
 
@@ -157,6 +326,25 @@ public:
 	TextureStorage();
 	virtual ~TextureStorage();
 
+	/* Canvas Texture API */
+
+	CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
+	bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
+
+	virtual RID canvas_texture_allocate() override;
+	virtual void canvas_texture_initialize(RID p_rid) override;
+	virtual void canvas_texture_free(RID p_rid) override;
+
+	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
+	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
+
+	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
+	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
+
+	bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);
+
+	/* Texture API */
+
 	Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
 	bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
 
@@ -224,6 +412,153 @@ public:
 		}
 		return Size2i(tex->width_2d, tex->height_2d);
 	}
+
+	/* DECAL API */
+
+	void update_decal_atlas();
+
+	Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); };
+	bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); };
+
+	RID decal_atlas_get_texture() const;
+	RID decal_atlas_get_texture_srgb() const;
+	_FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
+		DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+		if (!t) {
+			return Rect2();
+		}
+
+		return t->uv_rect;
+	}
+
+	virtual RID decal_allocate() override;
+	virtual void decal_initialize(RID p_decal) override;
+	virtual void decal_free(RID p_rid) override;
+
+	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
+	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
+	virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
+	virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
+	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
+	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
+	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
+	virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
+	virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
+
+	void decal_atlas_mark_dirty_on_texture(RID p_texture);
+	void decal_atlas_remove_texture(RID p_texture);
+
+	virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
+	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
+
+	_FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->extents;
+	}
+
+	_FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->textures[p_texture];
+	}
+
+	_FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->modulate;
+	}
+
+	_FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->emission_energy;
+	}
+
+	_FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->albedo_mix;
+	}
+
+	_FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->cull_mask;
+	}
+
+	_FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->upper_fade;
+	}
+
+	_FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->lower_fade;
+	}
+
+	_FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->normal_fade;
+	}
+
+	_FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->distance_fade;
+	}
+
+	_FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->distance_fade_begin;
+	}
+
+	_FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
+		const Decal *decal = decal_owner.get_or_null(p_decal);
+		return decal->distance_fade_length;
+	}
+
+	virtual AABB decal_get_aabb(RID p_decal) const override;
+
+	/* RENDER TARGET API */
+
+	RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); };
+	bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); };
+
+	virtual RID render_target_create() override;
+	virtual void render_target_free(RID p_rid) override;
+
+	virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
+	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
+	virtual RID render_target_get_texture(RID p_render_target) override;
+	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
+	virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override;
+	virtual bool render_target_was_used(RID p_render_target) override;
+	virtual void render_target_set_as_unused(RID p_render_target) override;
+
+	void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
+	void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
+	void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
+	RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
+
+	virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
+	virtual bool render_target_is_clear_requested(RID p_render_target) override;
+	virtual Color render_target_get_clear_request_color(RID p_render_target) override;
+	virtual void render_target_disable_clear_request(RID p_render_target) override;
+	virtual void render_target_do_clear_request(RID p_render_target) override;
+
+	virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
+	RID render_target_get_sdf_texture(RID p_render_target);
+	RID render_target_get_sdf_framebuffer(RID p_render_target);
+	void render_target_sdf_process(RID p_render_target);
+	virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
+	virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
+	bool render_target_is_sdf_enabled(RID p_render_target) const;
+
+	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_backbuffer(RID p_render_target);
+	RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
+
+	RID render_target_get_framebuffer_uniform_set(RID p_render_target);
+	RID render_target_get_backbuffer_uniform_set(RID p_render_target);
+
+	void render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set);
+	void render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set);
 };
 
 } // namespace RendererRD

+ 99 - 99
servers/rendering/renderer_scene_cull.cpp

@@ -228,7 +228,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
 		voxel_gi->lights.insert(A);
 	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
 		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
-		RSG::storage->particles_add_collision(A->base, collision->instance);
+		RSG::particles_storage->particles_add_collision(A->base, collision->instance);
 	}
 }
 
@@ -344,7 +344,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
 		voxel_gi->lights.erase(A);
 	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
 		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
-		RSG::storage->particles_remove_collision(A->base, collision->instance);
+		RSG::particles_storage->particles_remove_collision(A->base, collision->instance);
 	}
 }
 
@@ -521,7 +521,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
 			case RS::INSTANCE_LIGHT: {
 				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
 
-				if (scenario && instance->visible && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+				if (scenario && instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
 					scenario->dynamic_lights.erase(light->instance);
 				}
 
@@ -619,7 +619,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
 			case RS::INSTANCE_LIGHT: {
 				InstanceLightData *light = memnew(InstanceLightData);
 
-				if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
+				if (scenario && RSG::light_storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
 					light->D = scenario->directional_lights.push_back(instance);
 				}
 
@@ -659,8 +659,8 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
 			} break;
 			case RS::INSTANCE_PARTICLES_COLLISION: {
 				InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData);
-				collision->instance = RSG::storage->particles_collision_instance_create(p_base);
-				RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible);
+				collision->instance = RSG::particles_storage->particles_collision_instance_create(p_base);
+				RSG::particles_storage->particles_collision_instance_set_active(collision->instance, instance->visible);
 				instance->base_data = collision;
 			} break;
 			case RS::INSTANCE_FOG_VOLUME: {
@@ -801,7 +801,7 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
 			case RS::INSTANCE_LIGHT: {
 				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
 
-				if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
+				if (RSG::light_storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
 					light->D = scenario->directional_lights.push_back(instance);
 				}
 			} break;
@@ -930,7 +930,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
 
 	if (instance->base_type == RS::INSTANCE_LIGHT) {
 		InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
-		if (instance->scenario && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+		if (instance->scenario && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
 			if (p_visible) {
 				instance->scenario->dynamic_lights.push_back(light->instance);
 			} else {
@@ -941,7 +941,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
 
 	if (instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
 		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
-		RSG::storage->particles_collision_instance_set_active(collision->instance, p_visible);
+		RSG::particles_storage->particles_collision_instance_set_active(collision->instance, p_visible);
 	}
 
 	if (instance->base_type == RS::INSTANCE_FOG_VOLUME) {
@@ -1490,8 +1490,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 		scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb));
 		light->shadow_dirty = true;
 
-		RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base);
-		if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {
+		RS::LightBakeMode bake_mode = RSG::light_storage->light_get_bake_mode(p_instance->base);
+		if (RSG::light_storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {
 			if (p_instance->visible && p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
 				p_instance->scenario->dynamic_lights.erase(light->instance);
 			}
@@ -1503,7 +1503,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 			}
 		}
 
-		uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base);
+		uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(p_instance->base);
 		if (light->max_sdfgi_cascade != max_sdfgi_cascade) {
 			light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario
 		}
@@ -1529,15 +1529,15 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 
 		scene_render->voxel_gi_instance_set_transform_to_data(voxel_gi->probe_instance, p_instance->transform);
 	} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
-		RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
+		RSG::particles_storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
 	} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
 		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(p_instance->base_data);
 
 		//remove materials no longer used and un-own them
-		if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) {
+		if (RSG::particles_storage->particles_collision_is_heightfield(p_instance->base)) {
 			heightfield_particle_colliders_update_list.insert(p_instance);
 		}
-		RSG::storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);
+		RSG::particles_storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);
 	} else if (p_instance->base_type == RS::INSTANCE_FOG_VOLUME) {
 		InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(p_instance->base_data);
 		scene_render->fog_volume_instance_set_transform(volume->instance, p_instance->transform);
@@ -1646,8 +1646,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 			case RS::INSTANCE_LIGHT: {
 				InstanceLightData *light_data = static_cast<InstanceLightData *>(p_instance->base_data);
 				idata.instance_data_rid = light_data->instance.get_id();
-				light_data->uses_projector = RSG::storage->light_has_projector(p_instance->base);
-				light_data->uses_softshadow = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE) > CMP_EPSILON;
+				light_data->uses_projector = RSG::light_storage->light_has_projector(p_instance->base);
+				light_data->uses_softshadow = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE) > CMP_EPSILON;
 
 			} break;
 			case RS::INSTANCE_REFLECTION_PROBE: {
@@ -1740,7 +1740,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 		pair.pair_mask |= RS::INSTANCE_GEOMETRY_MASK;
 		pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
 
-		if (RSG::storage->light_get_bake_mode(p_instance->base) == RS::LIGHT_BAKE_DYNAMIC) {
+		if (RSG::light_storage->light_get_bake_mode(p_instance->base) == RS::LIGHT_BAKE_DYNAMIC) {
 			pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI);
 			pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
 		}
@@ -1864,12 +1864,12 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
 			if (p_instance->custom_aabb) {
 				new_aabb = *p_instance->custom_aabb;
 			} else {
-				new_aabb = RSG::storage->particles_get_aabb(p_instance->base);
+				new_aabb = RSG::particles_storage->particles_get_aabb(p_instance->base);
 			}
 
 		} break;
 		case RenderingServer::INSTANCE_PARTICLES_COLLISION: {
-			new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
+			new_aabb = RSG::particles_storage->particles_collision_get_aabb(p_instance->base);
 
 		} break;
 		case RenderingServer::INSTANCE_FOG_VOLUME: {
@@ -1879,15 +1879,15 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
 			new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
 		} break;
 		case RenderingServer::INSTANCE_LIGHT: {
-			new_aabb = RSG::storage->light_get_aabb(p_instance->base);
+			new_aabb = RSG::light_storage->light_get_aabb(p_instance->base);
 
 		} break;
 		case RenderingServer::INSTANCE_REFLECTION_PROBE: {
-			new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
+			new_aabb = RSG::light_storage->reflection_probe_get_aabb(p_instance->base);
 
 		} break;
 		case RenderingServer::INSTANCE_DECAL: {
-			new_aabb = RSG::decal_atlas_storage->decal_get_aabb(p_instance->base);
+			new_aabb = RSG::texture_storage->decal_get_aabb(p_instance->base);
 
 		} break;
 		case RenderingServer::INSTANCE_VOXEL_GI: {
@@ -1895,7 +1895,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
 
 		} break;
 		case RenderingServer::INSTANCE_LIGHTMAP: {
-			new_aabb = RSG::storage->lightmap_get_aabb(p_instance->base);
+			new_aabb = RSG::light_storage->lightmap_get_aabb(p_instance->base);
 
 		} break;
 		default: {
@@ -1923,7 +1923,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
 	for (Set<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
 		Instance *lightmap = E->get();
 
-		bool interior = RSG::storage->lightmap_is_interior(lightmap->base);
+		bool interior = RSG::light_storage->lightmap_is_interior(lightmap->base);
 
 		if (inside && !interior) {
 			continue; //we are inside, ignore exteriors
@@ -1934,13 +1934,13 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
 
 		Vector3 lm_pos = to_bounds.xform(center);
 
-		AABB bounds = RSG::storage->lightmap_get_aabb(lightmap->base);
+		AABB bounds = RSG::light_storage->lightmap_get_aabb(lightmap->base);
 		if (!bounds.has_point(lm_pos)) {
 			continue; //not in this lightmap
 		}
 
 		Color sh[9];
-		RSG::storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);
+		RSG::light_storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);
 
 		//rotate it
 		Basis rot = lightmap->transform.basis.orthonormalized();
@@ -1997,19 +1997,19 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
 	light_transform.orthonormalize(); //scale does not count on lights
 
 	real_t max_distance = p_cam_projection.get_z_far();
-	real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
+	real_t shadow_max = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
 	if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
 		max_distance = MIN(shadow_max, max_distance);
 	}
 	max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
 	real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
 
-	real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+	real_t pancake_size = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
 
 	real_t range = max_distance - min_distance;
 
 	int splits = 0;
-	switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
+	switch (RSG::light_storage->light_directional_get_shadow_mode(p_instance->base)) {
 		case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
 			splits = 1;
 			break;
@@ -2025,14 +2025,14 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
 
 	distances[0] = min_distance;
 	for (int i = 0; i < splits; i++) {
-		distances[i + 1] = min_distance + RSG::storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
+		distances[i + 1] = min_distance + RSG::light_storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
 	};
 
 	distances[splits] = max_distance;
 
 	real_t texture_size = scene_render->get_directional_light_shadow_size(light->instance);
 
-	bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
+	bool overlap = RSG::light_storage->light_directional_get_blend_splits(p_instance->base);
 
 	cull.shadow_count = p_shadow_index + 1;
 	cull.shadows[p_shadow_index].cascade_count = splits;
@@ -2139,7 +2139,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
 			z_min_cam = z_vec.dot(center) - radius;
 
 			{
-				float soft_shadow_angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);
+				float soft_shadow_angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);
 
 				if (soft_shadow_angle > 0.0) {
 					float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;
@@ -2215,11 +2215,11 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
 
 	bool animated_material_found = false;
 
-	switch (RSG::storage->light_get_type(p_instance->base)) {
+	switch (RSG::light_storage->light_get_type(p_instance->base)) {
 		case RS::LIGHT_DIRECTIONAL: {
 		} break;
 		case RS::LIGHT_OMNI: {
-			RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base);
+			RS::LightOmniShadowMode shadow_mode = RSG::light_storage->light_omni_get_shadow_mode(p_instance->base);
 
 			if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !scene_render->light_instances_can_render_shadow_cube()) {
 				if (max_shadows_used + 2 > MAX_UPDATE_SHADOWS) {
@@ -2229,7 +2229,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
 					//using this one ensures that raster deferred will have it
 					RENDER_TIMESTAMP("Cull OmniLight3D Shadow Paraboloid, Half " + itos(i));
 
-					real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+					real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
 
 					real_t z = i == 0 ? -1 : 1;
 					Vector<Plane> planes;
@@ -2290,7 +2290,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
 					return true;
 				}
 
-				real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+				real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
 				CameraMatrix cm;
 				cm.set_perspective(90, 1, radius * 0.005f, radius);
 
@@ -2374,8 +2374,8 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
 				return true;
 			}
 
-			real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
-			real_t angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+			real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+			real_t angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
 
 			CameraMatrix cm;
 			cm.set_perspective(angle * 2.0, 1.0, 0.005f * radius, radius);
@@ -2623,7 +2623,7 @@ void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_d
 
 void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to) {
 	uint64_t frame_number = RSG::rasterizer->get_frame_number();
-	float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
+	float lightmap_probe_update_speed = RSG::light_storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
 
 	uint32_t sdfgi_last_light_index = 0xFFFFFFFF;
 	uint32_t sdfgi_last_light_cascade = 0xFFFFFFFF;
@@ -2654,7 +2654,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
 				if (base_type == RS::INSTANCE_LIGHT) {
 					cull_result.lights.push_back(idata.instance);
 					cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));
-					if (cull_data.shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
+					if (cull_data.shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(idata.base_rid)) {
 						scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
 					}
 
@@ -2714,14 +2714,14 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
 						mesh_visible = true;
 					} else if (base_type == RS::INSTANCE_PARTICLES) {
 						//particles visible? process them
-						if (RSG::storage->particles_is_inactive(idata.base_rid)) {
+						if (RSG::particles_storage->particles_is_inactive(idata.base_rid)) {
 							//but if nothing is going on, don't do it.
 							keep = false;
 						} else {
 							cull_data.cull->lock.lock();
-							RSG::storage->particles_request_process(idata.base_rid);
+							RSG::particles_storage->particles_request_process(idata.base_rid);
 							cull_data.cull->lock.unlock();
-							RSG::storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());
+							RSG::particles_storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());
 							//particles visible? request redraw
 							RenderingServerDefault::redraw_request();
 						}
@@ -2948,7 +2948,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
 			//check shadow..
 
 			if (light) {
-				if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->base) && !(RSG::storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_get_sky_mode(E->base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY)) {
+				if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(E->base) && !(RSG::light_storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(E->base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY)) {
 					lights_with_shadow.push_back(E);
 				}
 				//add to list
@@ -3070,7 +3070,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
 		for (uint32_t i = 0; i < (uint32_t)scene_cull_result.lights.size(); i++) {
 			Instance *ins = scene_cull_result.lights[i];
 
-			if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
+			if (!p_shadow_atlas.is_valid() || !RSG::light_storage->light_has_shadow(ins->base)) {
 				continue;
 			}
 
@@ -3087,9 +3087,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
 				// near plane half width and height
 				Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();
 
-				switch (RSG::storage->light_get_type(ins->base)) {
+				switch (RSG::light_storage->light_get_type(ins->base)) {
 					case RS::LIGHT_OMNI: {
-						float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
+						float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
 
 						//get two points parallel to near plane
 						Vector3 points[2] = {
@@ -3112,8 +3112,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
 						coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);
 					} break;
 					case RS::LIGHT_SPOT: {
-						float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
-						float angle = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+						float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
+						float angle = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
 
 						float w = radius * Math::sin(Math::deg2rad(angle));
 						float d = radius * Math::cos(Math::deg2rad(angle));
@@ -3303,11 +3303,11 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
 			Vector3(0, -1, 0)
 		};
 
-		Vector3 extents = RSG::storage->reflection_probe_get_extents(p_instance->base);
-		Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base);
-		float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base);
+		Vector3 extents = RSG::light_storage->reflection_probe_get_extents(p_instance->base);
+		Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base);
+		float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base);
 		float size = scene_render->reflection_atlas_get_size(scenario->reflection_atlas);
-		float mesh_lod_threshold = RSG::storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size;
+		float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size;
 
 		Vector3 edge = view_normals[p_step] * extents;
 		float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit
@@ -3325,7 +3325,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
 
 		RID shadow_atlas;
 
-		bool use_shadows = RSG::storage->reflection_probe_renders_shadows(p_instance->base);
+		bool use_shadows = RSG::light_storage->reflection_probe_renders_shadows(p_instance->base);
 		if (use_shadows) {
 			shadow_atlas = scenario->reflection_probe_shadow_atlas;
 		}
@@ -3341,7 +3341,7 @@ 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::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);
+		_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);
 
 	} else {
 		//do roughness postprocess step until it believes it's done
@@ -3363,7 +3363,7 @@ void RendererSceneCull::render_probes() {
 		SelfList<InstanceReflectionProbeData> *next = ref_probe->next();
 		RID base = ref_probe->self()->owner->base;
 
-		switch (RSG::storage->reflection_probe_get_update_mode(base)) {
+		switch (RSG::light_storage->reflection_probe_get_update_mode(base)) {
 			case RS::REFLECTION_PROBE_UPDATE_ONCE: {
 				if (busy) { //already rendering something
 					break;
@@ -3432,16 +3432,16 @@ void RendererSceneCull::render_probes() {
 
 					if (
 							instance_caches[idx] != instance_light->instance ||
-							cache->has_shadow != RSG::storage->light_has_shadow(instance->base) ||
-							cache->type != RSG::storage->light_get_type(instance->base) ||
+							cache->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||
+							cache->type != RSG::light_storage->light_get_type(instance->base) ||
 							cache->transform != instance->transform ||
-							cache->color != RSG::storage->light_get_color(instance->base) ||
-							cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
-							cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
-							cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
-							cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
-							cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
-							cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {
+							cache->color != RSG::light_storage->light_get_color(instance->base) ||
+							cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+							cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
+							cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
+							cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
+							cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
+							cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {
 						cache_dirty = true;
 					}
 				}
@@ -3463,17 +3463,17 @@ void RendererSceneCull::render_probes() {
 
 					if (
 							instance_caches[idx] != instance_light->instance ||
-							cache->has_shadow != RSG::storage->light_has_shadow(instance->base) ||
-							cache->type != RSG::storage->light_get_type(instance->base) ||
+							cache->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||
+							cache->type != RSG::light_storage->light_get_type(instance->base) ||
 							cache->transform != instance->transform ||
-							cache->color != RSG::storage->light_get_color(instance->base) ||
-							cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
-							cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
-							cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
-							cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
-							cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
-							cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||
-							cache->sky_mode != RSG::storage->light_directional_get_sky_mode(instance->base)) {
+							cache->color != RSG::light_storage->light_get_color(instance->base) ||
+							cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+							cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
+							cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
+							cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
+							cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
+							cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||
+							cache->sky_mode != RSG::light_storage->light_directional_get_sky_mode(instance->base)) {
 						cache_dirty = true;
 					}
 				}
@@ -3509,16 +3509,16 @@ void RendererSceneCull::render_probes() {
 					InstanceVoxelGIData::LightCache *cache = &caches[idx];
 
 					instance_caches[idx] = instance_light->instance;
-					cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
-					cache->type = RSG::storage->light_get_type(instance->base);
+					cache->has_shadow = RSG::light_storage->light_has_shadow(instance->base);
+					cache->type = RSG::light_storage->light_get_type(instance->base);
 					cache->transform = instance->transform;
-					cache->color = RSG::storage->light_get_color(instance->base);
-					cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
-					cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
-					cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
-					cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
-					cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
-					cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+					cache->color = RSG::light_storage->light_get_color(instance->base);
+					cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+					cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+					cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
+					cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
+					cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+					cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
 
 					idx++;
 				}
@@ -3531,17 +3531,17 @@ void RendererSceneCull::render_probes() {
 					InstanceVoxelGIData::LightCache *cache = &caches[idx];
 
 					instance_caches[idx] = instance_light->instance;
-					cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
-					cache->type = RSG::storage->light_get_type(instance->base);
+					cache->has_shadow = RSG::light_storage->light_has_shadow(instance->base);
+					cache->type = RSG::light_storage->light_get_type(instance->base);
 					cache->transform = instance->transform;
-					cache->color = RSG::storage->light_get_color(instance->base);
-					cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
-					cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
-					cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
-					cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
-					cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
-					cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
-					cache->sky_mode = RSG::storage->light_directional_get_sky_mode(instance->base);
+					cache->color = RSG::light_storage->light_get_color(instance->base);
+					cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+					cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+					cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
+					cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
+					cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+					cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+					cache->sky_mode = RSG::light_storage->light_directional_get_sky_mode(instance->base);
 
 					idx++;
 				}
@@ -3592,7 +3592,7 @@ void RendererSceneCull::render_particle_colliders() {
 	while (heightfield_particle_colliders_update_list.front()) {
 		Instance *hfpc = heightfield_particle_colliders_update_list.front()->get();
 
-		if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) {
+		if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::particles_storage->particles_collision_is_heightfield(hfpc->base)) {
 			//update heightfield
 			instance_cull_result.clear();
 			scene_cull_result.geometry_instances.clear();
@@ -3686,7 +3686,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 		if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
 			// update the process material dependency
 
-			RID particle_material = RSG::storage->particles_get_process_material(p_instance->base);
+			RID particle_material = RSG::particles_storage->particles_get_process_material(p_instance->base);
 			if (particle_material.is_valid()) {
 				RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);
 			}
@@ -3776,10 +3776,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 				} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
 					bool cast_shadows = false;
 
-					int dp = RSG::storage->particles_get_draw_passes(p_instance->base);
+					int dp = RSG::particles_storage->particles_get_draw_passes(p_instance->base);
 
 					for (int i = 0; i < dp; i++) {
-						RID mesh = RSG::storage->particles_get_draw_pass_mesh(p_instance->base, i);
+						RID mesh = RSG::particles_storage->particles_get_draw_pass_mesh(p_instance->base, i);
 						if (!mesh.is_valid()) {
 							continue;
 						}

+ 0 - 203
servers/rendering/renderer_storage.h

@@ -119,80 +119,6 @@ public:
 		Set<Dependency *> dependencies;
 	};
 
-	/* Light API */
-
-	virtual RID directional_light_allocate() = 0;
-	virtual void directional_light_initialize(RID p_rid) = 0;
-
-	virtual RID omni_light_allocate() = 0;
-	virtual void omni_light_initialize(RID p_rid) = 0;
-
-	virtual RID spot_light_allocate() = 0;
-	virtual void spot_light_initialize(RID p_rid) = 0;
-
-	virtual void light_set_color(RID p_light, const Color &p_color) = 0;
-	virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0;
-	virtual void light_set_shadow(RID p_light, bool p_enabled) = 0;
-	virtual void light_set_projector(RID p_light, RID p_texture) = 0;
-	virtual void light_set_negative(RID p_light, bool p_enable) = 0;
-	virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
-	virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
-	virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
-	virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0;
-	virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
-
-	virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0;
-
-	virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0;
-	virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
-	virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
-	virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) = 0;
-	virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const = 0;
-
-	virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
-	virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0;
-
-	virtual bool light_has_shadow(RID p_light) const = 0;
-
-	virtual bool light_has_projector(RID p_light) const = 0;
-
-	virtual RS::LightType light_get_type(RID p_light) const = 0;
-	virtual AABB light_get_aabb(RID p_light) const = 0;
-	virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0;
-	virtual Color light_get_color(RID p_light) = 0;
-	virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0;
-	virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0;
-	virtual uint64_t light_get_version(RID p_light) const = 0;
-
-	/* PROBE API */
-
-	virtual RID reflection_probe_allocate() = 0;
-	virtual void reflection_probe_initialize(RID p_rid) = 0;
-
-	virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0;
-	virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
-	virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0;
-	virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) = 0;
-	virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0;
-	virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0;
-	virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0;
-	virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0;
-	virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0;
-	virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0;
-	virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0;
-	virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
-	virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
-	virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) = 0;
-
-	virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0;
-	virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0;
-	virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0;
-	virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0;
-	virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0;
-	virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0;
-	virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
-	virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0;
-
 	virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
 
 	/* VOXEL GI API */
@@ -237,103 +163,6 @@ public:
 
 	virtual uint32_t voxel_gi_get_version(RID p_probe) = 0;
 
-	/* LIGHTMAP  */
-
-	virtual RID lightmap_allocate() = 0;
-	virtual void lightmap_initialize(RID p_rid) = 0;
-
-	virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0;
-	virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
-	virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0;
-	virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0;
-	virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0;
-	virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0;
-	virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0;
-	virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0;
-	virtual AABB lightmap_get_aabb(RID p_lightmap) const = 0;
-	virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) = 0;
-	virtual bool lightmap_is_interior(RID p_lightmap) const = 0;
-	virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0;
-	virtual float lightmap_get_probe_capture_update_speed() const = 0;
-
-	/* PARTICLES */
-
-	virtual RID particles_allocate() = 0;
-	virtual void particles_initialize(RID p_rid) = 0;
-	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 0;
-
-	virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0;
-	virtual bool particles_get_emitting(RID p_particles) = 0;
-
-	virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
-	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
-	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
-	virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
-	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0;
-	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) = 0;
-	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
-	virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0;
-	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
-	virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
-	virtual RID particles_get_process_material(RID p_particles) const = 0;
-	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
-	virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0;
-	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
-	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0;
-
-	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
-
-	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0;
-	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
-
-	virtual void particles_restart(RID p_particles) = 0;
-	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0;
-	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0;
-
-	virtual bool particles_is_inactive(RID p_particles) const = 0;
-
-	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0;
-
-	virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
-	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0;
-
-	virtual void particles_request_process(RID p_particles) = 0;
-	virtual AABB particles_get_current_aabb(RID p_particles) = 0;
-	virtual AABB particles_get_aabb(RID p_particles) const = 0;
-
-	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0;
-
-	virtual int particles_get_draw_passes(RID p_particles) const = 0;
-	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
-
-	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) = 0;
-
-	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
-	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
-
-	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0;
-
-	virtual void update_particles() = 0;
-
-	/* PARTICLES COLLISION */
-
-	virtual RID particles_collision_allocate() = 0;
-	virtual void particles_collision_initialize(RID p_rid) = 0;
-
-	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0;
-	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
-	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres
-	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres
-	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0;
-	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
-	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0;
-	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic
-	virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field
-	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
-	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0;
-	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
-	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
-
 	/* FOG VOLUMES */
 
 	virtual RID fog_volume_allocate() = 0;
@@ -355,38 +184,6 @@ public:
 	virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
 	virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0;
 
-	//used from 2D and 3D
-	virtual RID particles_collision_instance_create(RID p_collision) = 0;
-	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
-	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
-
-	/* RENDER TARGET */
-
-	enum RenderTargetFlags {
-		RENDER_TARGET_TRANSPARENT,
-		RENDER_TARGET_DIRECT_TO_SCREEN,
-		RENDER_TARGET_FLAG_MAX
-	};
-
-	virtual RID render_target_create() = 0;
-	virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
-	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0;
-	virtual RID render_target_get_texture(RID p_render_target) = 0;
-	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
-	virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
-	virtual bool render_target_was_used(RID p_render_target) = 0;
-	virtual void render_target_set_as_unused(RID p_render_target) = 0;
-
-	virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0;
-	virtual bool render_target_is_clear_requested(RID p_render_target) = 0;
-	virtual Color render_target_get_clear_request_color(RID p_render_target) = 0;
-	virtual void render_target_disable_clear_request(RID p_render_target) = 0;
-	virtual void render_target_do_clear_request(RID p_render_target) = 0;
-
-	virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
-	virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
-	virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
-
 	virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
 	virtual bool free(RID p_rid) = 0;
 

+ 28 - 27
servers/rendering/renderer_viewport.cpp

@@ -34,6 +34,7 @@
 #include "renderer_canvas_cull.h"
 #include "renderer_scene_cull.h"
 #include "rendering_server_globals.h"
+#include "storage/texture_storage.h"
 
 static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport, RendererCanvasCull::Canvas *p_canvas, RendererViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {
 	Transform2D xf = p_viewport->global_transform;
@@ -222,7 +223,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
 		_configure_3d_render_buffers(p_viewport);
 	}
 
-	RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
+	RSG::texture_storage->render_target_request_clear(p_viewport->render_target, bgcolor);
 
 	if (!scenario_draw_canvas_bg && can_draw_3d) {
 		_draw_3d(p_viewport);
@@ -243,7 +244,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
 		if (p_viewport->sdf_active) {
 			//process SDF
 
-			Rect2 sdf_rect = RSG::storage->render_target_get_sdf_rect(p_viewport->render_target);
+			Rect2 sdf_rect = RSG::texture_storage->render_target_get_sdf_rect(p_viewport->render_target);
 
 			RendererCanvasRender::LightOccluderInstance *occluders = nullptr;
 
@@ -266,11 +267,11 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
 			}
 
 			RSG::canvas_render->render_sdf(p_viewport->render_target, occluders);
-			RSG::storage->render_target_mark_sdf_enabled(p_viewport->render_target, true);
+			RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, true);
 
 			p_viewport->sdf_active = false; // if used, gets set active again
 		} else {
-			RSG::storage->render_target_mark_sdf_enabled(p_viewport->render_target, false);
+			RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, false);
 		}
 
 		Rect2 shadow_rect;
@@ -529,9 +530,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
 		}
 	}
 
-	if (RSG::storage->render_target_is_clear_requested(p_viewport->render_target)) {
+	if (RSG::texture_storage->render_target_is_clear_requested(p_viewport->render_target)) {
 		//was never cleared in the end, force clear it
-		RSG::storage->render_target_do_clear_request(p_viewport->render_target);
+		RSG::texture_storage->render_target_do_clear_request(p_viewport->render_target);
 	}
 
 	if (p_viewport->measure_render_time) {
@@ -595,7 +596,7 @@ void RendererViewport::draw_viewports() {
 				vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size);
 				vp->size = xr_size;
 				uint32_t view_count = xr_interface->get_view_count();
-				RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
+				RSG::texture_storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
 
 				// Inform xr interface we're about to render its viewport, if this returns false we don't render
 				visible = xr_interface->pre_draw_viewport(vp->render_target);
@@ -610,7 +611,7 @@ void RendererViewport::draw_viewports() {
 			visible = true;
 		}
 
-		if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::storage->render_target_was_used(vp->render_target)) {
+		if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::texture_storage->render_target_was_used(vp->render_target)) {
 			visible = true;
 		}
 
@@ -641,11 +642,11 @@ void RendererViewport::draw_viewports() {
 
 		RENDER_TIMESTAMP("> Render Viewport " + itos(i));
 
-		RSG::storage->render_target_set_as_unused(vp->render_target);
+		RSG::texture_storage->render_target_set_as_unused(vp->render_target);
 		if (vp->use_xr && xr_interface.is_valid()) {
 			// check for an external texture destination (disabled for now, not yet supported)
-			// RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
-			RSG::storage->render_target_set_external_texture(vp->render_target, 0);
+			// RSG::texture_storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
+			RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
 
 			// render...
 			RSG::scene->set_debug_draw_mode(vp->debug_draw);
@@ -667,7 +668,7 @@ void RendererViewport::draw_viewports() {
 				}
 			}
 		} else {
-			RSG::storage->render_target_set_external_texture(vp->render_target, 0);
+			RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
 
 			RSG::scene->set_debug_draw_mode(vp->debug_draw);
 
@@ -726,7 +727,7 @@ void RendererViewport::viewport_initialize(RID p_rid) {
 	viewport_owner.initialize_rid(p_rid);
 	Viewport *viewport = viewport_owner.get_or_null(p_rid);
 	viewport->self = p_rid;
-	viewport->render_target = RSG::storage->render_target_create();
+	viewport->render_target = RSG::texture_storage->render_target_create();
 	viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
 	viewport->viewport_render_direct_to_screen = false;
 
@@ -808,7 +809,7 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig
 	viewport->size = Size2(p_width, p_height);
 
 	uint32_t view_count = viewport->get_view_count();
-	RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
+	RSG::texture_storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
 	_configure_3d_render_buffers(viewport);
 
 	viewport->occlusion_buffer_dirty = true;
@@ -849,8 +850,8 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
 		// If using OpenGL we can optimize this operation by rendering directly to system_fbo
 		// instead of rendering to fbo and copying to system_fbo after
 		if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
-			RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
-			RSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
+			RSG::texture_storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
+			RSG::texture_storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
 		}
 
 		viewport->viewport_to_screen_rect = p_rect;
@@ -858,8 +859,8 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
 	} else {
 		// if render_direct_to_screen was used, reset size and position
 		if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
-			RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
-			RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+			RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
+			RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
 		}
 
 		viewport->viewport_to_screen_rect = Rect2();
@@ -877,17 +878,17 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
 
 	// if disabled, reset render_target size and position
 	if (!p_enable) {
-		RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
-		RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+		RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
+		RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
 	}
 
-	RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
+	RSG::texture_storage->render_target_set_flag(viewport->render_target, RendererTextureStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
 	viewport->viewport_render_direct_to_screen = p_enable;
 
 	// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
 	if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
-		RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
-		RSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
+		RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
+		RSG::texture_storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
 	}
 }
 
@@ -902,7 +903,7 @@ RID RendererViewport::viewport_get_texture(RID p_viewport) const {
 	const Viewport *viewport = viewport_owner.get_or_null(p_viewport);
 	ERR_FAIL_COND_V(!viewport, RID());
 
-	return RSG::storage->render_target_get_texture(viewport->render_target);
+	return RSG::texture_storage->render_target_get_texture(viewport->render_target);
 }
 
 RID RendererViewport::viewport_get_occluder_debug_texture(RID p_viewport) const {
@@ -995,7 +996,7 @@ void RendererViewport::viewport_set_transparent_background(RID p_viewport, bool
 	Viewport *viewport = viewport_owner.get_or_null(p_viewport);
 	ERR_FAIL_COND(!viewport);
 
-	RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_TRANSPARENT, p_enabled);
+	RSG::texture_storage->render_target_set_flag(viewport->render_target, RendererTextureStorage::RENDER_TARGET_TRANSPARENT, p_enabled);
 	viewport->transparent_bg = p_enabled;
 }
 
@@ -1178,14 +1179,14 @@ void RendererViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::V
 	Viewport *viewport = viewport_owner.get_or_null(p_viewport);
 	ERR_FAIL_COND(!viewport);
 
-	RSG::storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
+	RSG::texture_storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
 }
 
 bool RendererViewport::free(RID p_rid) {
 	if (viewport_owner.owns(p_rid)) {
 		Viewport *viewport = viewport_owner.get_or_null(p_rid);
 
-		RSG::storage->free(viewport->render_target);
+		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);

+ 3 - 3
servers/rendering/rendering_server_default.cpp

@@ -84,7 +84,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
 
 	frame_setup_time = double(OS::get_singleton()->get_ticks_usec() - time_usec) / 1000.0;
 
-	RSG::storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered
+	RSG::particles_storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered
 
 	RSG::scene->render_probes();
 
@@ -398,10 +398,10 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
 	RendererSceneCull *sr = memnew(RendererSceneCull);
 	RSG::scene = sr;
 	RSG::rasterizer = RendererCompositor::create();
-	RSG::canvas_texture_storage = RSG::rasterizer->get_canvas_texture_storage();
-	RSG::decal_atlas_storage = RSG::rasterizer->get_decal_atlas_storage();
+	RSG::light_storage = RSG::rasterizer->get_light_storage();
 	RSG::material_storage = RSG::rasterizer->get_material_storage();
 	RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
+	RSG::particles_storage = RSG::rasterizer->get_particles_storage();
 	RSG::texture_storage = RSG::rasterizer->get_texture_storage();
 	RSG::storage = RSG::rasterizer->get_storage();
 	RSG::canvas_render = RSG::rasterizer->get_canvas();

+ 29 - 17
servers/rendering/rendering_server_default.h

@@ -351,8 +351,8 @@ public:
 #undef ServerName
 #undef server_name
 
-#define ServerName RendererStorage
-#define server_name RSG::storage
+#define ServerName RendererLightStorage
+#define server_name RSG::light_storage
 
 	FUNCRIDSPLIT(directional_light)
 	FUNCRIDSPLIT(omni_light)
@@ -394,13 +394,27 @@ public:
 	FUNC2(reflection_probe_set_resolution, RID, int)
 	FUNC2(reflection_probe_set_mesh_lod_threshold, RID, float)
 
+	/* LIGHTMAP */
+
+	FUNCRIDSPLIT(lightmap)
+
+	FUNC3(lightmap_set_textures, RID, RID, bool)
+	FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
+	FUNC2(lightmap_set_probe_interior, RID, bool)
+	FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
+	FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
+	FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
+	FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
+	FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
+	FUNC1(lightmap_set_probe_capture_update_speed, float)
+
 	/* DECAL API */
 
 #undef ServerName
 #undef server_name
 
-#define ServerName RendererDecalAtlasStorage
-#define server_name RSG::decal_atlas_storage
+#define ServerName RendererTextureStorage
+#define server_name RSG::texture_storage
 
 	FUNCRIDSPLIT(decal)
 
@@ -443,21 +457,13 @@ public:
 	FUNC2(voxel_gi_set_interior, RID, bool)
 	FUNC2(voxel_gi_set_use_two_bounces, RID, bool)
 
-	/* LIGHTMAP */
-
-	FUNCRIDSPLIT(lightmap)
+	/* PARTICLES */
 
-	FUNC3(lightmap_set_textures, RID, RID, bool)
-	FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
-	FUNC2(lightmap_set_probe_interior, RID, bool)
-	FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
-	FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
-	FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
-	FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
-	FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
-	FUNC1(lightmap_set_probe_capture_update_speed, float)
+#undef ServerName
+#undef server_name
 
-	/* PARTICLES */
+#define ServerName RendererParticlesStorage
+#define server_name RSG::particles_storage
 
 	FUNCRIDSPLIT(particles)
 
@@ -514,6 +520,12 @@ public:
 
 	/* FOG VOLUME */
 
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererStorage
+#define server_name RSG::storage
+
 	FUNCRIDSPLIT(fog_volume)
 
 	FUNC2(fog_volume_set_shape, RID, FogVolumeShape)

+ 2 - 2
servers/rendering/rendering_server_globals.cpp

@@ -32,10 +32,10 @@
 
 bool RenderingServerGlobals::threaded = false;
 
-RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr;
-RendererDecalAtlasStorage *RenderingServerGlobals::decal_atlas_storage = nullptr;
+RendererLightStorage *RenderingServerGlobals::light_storage = nullptr;
 RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr;
 RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr;
+RendererParticlesStorage *RenderingServerGlobals::particles_storage = nullptr;
 RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr;
 RendererStorage *RenderingServerGlobals::storage = nullptr;
 RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;

+ 4 - 4
servers/rendering/rendering_server_globals.h

@@ -34,10 +34,10 @@
 #include "servers/rendering/renderer_canvas_cull.h"
 #include "servers/rendering/renderer_canvas_render.h"
 #include "servers/rendering/renderer_scene.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
-#include "servers/rendering/storage/decal_atlas_storage.h"
+#include "servers/rendering/storage/light_storage.h"
 #include "servers/rendering/storage/material_storage.h"
 #include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/particles_storage.h"
 #include "servers/rendering/storage/texture_storage.h"
 
 class RendererCanvasCull;
@@ -48,11 +48,11 @@ class RenderingServerGlobals {
 public:
 	static bool threaded;
 
-	static RendererCanvasTextureStorage *canvas_texture_storage;
+	static RendererLightStorage *light_storage;
 	static RendererMaterialStorage *material_storage;
 	static RendererMeshStorage *mesh_storage;
+	static RendererParticlesStorage *particles_storage;
 	static RendererTextureStorage *texture_storage;
-	static RendererDecalAtlasStorage *decal_atlas_storage;
 	static RendererStorage *storage;
 	static RendererCanvasRender *canvas_render;
 	static RendererCompositor *rasterizer;

+ 0 - 51
servers/rendering/storage/canvas_texture_storage.h

@@ -1,51 +0,0 @@
-/*************************************************************************/
-/*  canvas_texture_storage.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 CANVAS_TEXTURE_STORAGE_H
-#define CANVAS_TEXTURE_STORAGE_H
-
-#include "servers/rendering_server.h"
-
-class RendererCanvasTextureStorage {
-public:
-	virtual ~RendererCanvasTextureStorage(){};
-
-	virtual RID canvas_texture_allocate() = 0;
-	virtual void canvas_texture_initialize(RID p_rid) = 0;
-	virtual void canvas_texture_free(RID p_rid) = 0;
-
-	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0;
-	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0;
-
-	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0;
-	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0;
-};
-
-#endif // !CANVAS_TEXTURE_STORAGE_H

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

@@ -1,60 +0,0 @@
-/*************************************************************************/
-/*  decal_atlas_storage.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 DECAL_ATLAS_STORAGE_H
-#define DECAL_ATLAS_STORAGE_H
-
-#include "servers/rendering_server.h"
-
-class RendererDecalAtlasStorage {
-public:
-	virtual ~RendererDecalAtlasStorage(){};
-
-	virtual RID decal_allocate() = 0;
-	virtual void decal_initialize(RID p_rid) = 0;
-	virtual void decal_free(RID p_rid) = 0;
-
-	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0;
-	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0;
-	virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0;
-	virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0;
-	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0;
-	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0;
-	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0;
-	virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0;
-	virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0;
-
-	virtual AABB decal_get_aabb(RID p_decal) const = 0;
-
-	virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
-	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
-};
-
-#endif // !DECAL_ATLAS_STORAGE_H

+ 139 - 0
servers/rendering/storage/light_storage.h

@@ -0,0 +1,139 @@
+/*************************************************************************/
+/*  light_storage.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 LIGHT_STORAGE_H
+#define LIGHT_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererLightStorage {
+public:
+	virtual ~RendererLightStorage() {}
+
+	/* Light API */
+
+	virtual RID directional_light_allocate() = 0;
+	virtual void directional_light_initialize(RID p_rid) = 0;
+
+	virtual RID omni_light_allocate() = 0;
+	virtual void omni_light_initialize(RID p_rid) = 0;
+
+	virtual RID spot_light_allocate() = 0;
+	virtual void spot_light_initialize(RID p_rid) = 0;
+
+	virtual void light_free(RID p_rid) = 0;
+
+	virtual void light_set_color(RID p_light, const Color &p_color) = 0;
+	virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0;
+	virtual void light_set_shadow(RID p_light, bool p_enabled) = 0;
+	virtual void light_set_projector(RID p_light, RID p_texture) = 0;
+	virtual void light_set_negative(RID p_light, bool p_enable) = 0;
+	virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
+	virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
+	virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
+	virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0;
+	virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
+
+	virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0;
+
+	virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0;
+	virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
+	virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
+	virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) = 0;
+	virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const = 0;
+
+	virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
+	virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0;
+
+	virtual bool light_has_shadow(RID p_light) const = 0;
+
+	virtual bool light_has_projector(RID p_light) const = 0;
+
+	virtual RS::LightType light_get_type(RID p_light) const = 0;
+	virtual AABB light_get_aabb(RID p_light) const = 0;
+	virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0;
+	virtual Color light_get_color(RID p_light) = 0;
+	virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0;
+	virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0;
+	virtual uint64_t light_get_version(RID p_light) const = 0;
+
+	/* PROBE API */
+
+	virtual RID reflection_probe_allocate() = 0;
+	virtual void reflection_probe_initialize(RID p_rid) = 0;
+	virtual void reflection_probe_free(RID p_rid) = 0;
+
+	virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0;
+	virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
+	virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0;
+	virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) = 0;
+	virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0;
+	virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0;
+	virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0;
+	virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0;
+	virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0;
+	virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0;
+	virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0;
+	virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
+	virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
+	virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) = 0;
+
+	virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0;
+	virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0;
+	virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0;
+	virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0;
+	virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0;
+	virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0;
+	virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
+	virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0;
+
+	/* LIGHTMAP  */
+
+	virtual RID lightmap_allocate() = 0;
+	virtual void lightmap_initialize(RID p_rid) = 0;
+	virtual void lightmap_free(RID p_rid) = 0;
+
+	virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0;
+	virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
+	virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0;
+	virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0;
+	virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0;
+	virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0;
+	virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0;
+	virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0;
+	virtual AABB lightmap_get_aabb(RID p_lightmap) const = 0;
+	virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) = 0;
+	virtual bool lightmap_is_interior(RID p_lightmap) const = 0;
+	virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0;
+	virtual float lightmap_get_probe_capture_update_speed() const = 0;
+};
+
+#endif // !LIGHT_STORAGE_H

+ 129 - 0
servers/rendering/storage/particles_storage.h

@@ -0,0 +1,129 @@
+/*************************************************************************/
+/*  particles_storage.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 PARTICLES_STORAGE_H
+#define PARTICLES_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererParticlesStorage {
+public:
+	virtual ~RendererParticlesStorage() {}
+
+	/* PARTICLES */
+
+	virtual RID particles_allocate() = 0;
+	virtual void particles_initialize(RID p_rid) = 0;
+	virtual void particles_free(RID p_rid) = 0;
+
+	virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 0;
+
+	virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0;
+	virtual bool particles_get_emitting(RID p_particles) = 0;
+
+	virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
+	virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
+	virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
+	virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
+	virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0;
+	virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) = 0;
+	virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
+	virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0;
+	virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
+	virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
+	virtual RID particles_get_process_material(RID p_particles) const = 0;
+	virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
+	virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0;
+	virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
+	virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0;
+
+	virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
+
+	virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0;
+	virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
+
+	virtual void particles_restart(RID p_particles) = 0;
+	virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0;
+	virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0;
+
+	virtual bool particles_is_inactive(RID p_particles) const = 0;
+
+	virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0;
+
+	virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
+	virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0;
+
+	virtual void particles_request_process(RID p_particles) = 0;
+	virtual AABB particles_get_current_aabb(RID p_particles) = 0;
+	virtual AABB particles_get_aabb(RID p_particles) const = 0;
+
+	virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0;
+
+	virtual int particles_get_draw_passes(RID p_particles) const = 0;
+	virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
+
+	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) = 0;
+
+	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
+	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
+
+	virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0;
+
+	virtual void update_particles() = 0;
+
+	/* PARTICLES COLLISION */
+
+	virtual RID particles_collision_allocate() = 0;
+	virtual void particles_collision_initialize(RID p_rid) = 0;
+	virtual void particles_collision_free(RID p_rid) = 0;
+
+	virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0;
+	virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
+	virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres
+	virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres
+	virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0;
+	virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
+	virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0;
+	virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic
+	virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field
+	virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
+	virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0;
+	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
+	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
+
+	//used from 2D and 3D
+	virtual RID particles_collision_instance_create(RID p_collision) = 0;
+	virtual void particles_collision_instance_free(RID p_rid) = 0;
+	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
+	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
+};
+
+#endif // !PARTICLES_STORAGE_H

+ 62 - 0
servers/rendering/storage/texture_storage.h

@@ -35,6 +35,19 @@
 
 class RendererTextureStorage {
 public:
+	/* Canvas Texture API */
+
+	virtual RID canvas_texture_allocate() = 0;
+	virtual void canvas_texture_initialize(RID p_rid) = 0;
+	virtual void canvas_texture_free(RID p_rid) = 0;
+
+	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0;
+	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0;
+
+	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0;
+	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0;
+
+	/* Texture API */
 	virtual bool can_create_resources_async() const = 0;
 
 	virtual ~RendererTextureStorage(){};
@@ -75,6 +88,55 @@ public:
 	virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0;
 
 	virtual Size2 texture_size_with_proxy(RID p_proxy) = 0;
+
+	/* Decal API */
+	virtual RID decal_allocate() = 0;
+	virtual void decal_initialize(RID p_rid) = 0;
+	virtual void decal_free(RID p_rid) = 0;
+
+	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0;
+	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0;
+	virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0;
+	virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0;
+	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0;
+	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0;
+	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0;
+	virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0;
+	virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0;
+
+	virtual AABB decal_get_aabb(RID p_decal) const = 0;
+
+	virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
+	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
+
+	/* RENDER TARGET */
+
+	enum RenderTargetFlags {
+		RENDER_TARGET_TRANSPARENT,
+		RENDER_TARGET_DIRECT_TO_SCREEN,
+		RENDER_TARGET_FLAG_MAX
+	};
+
+	virtual RID render_target_create() = 0;
+	virtual void render_target_free(RID p_rid) = 0;
+
+	virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
+	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0;
+	virtual RID render_target_get_texture(RID p_render_target) = 0;
+	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
+	virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
+	virtual bool render_target_was_used(RID p_render_target) = 0;
+	virtual void render_target_set_as_unused(RID p_render_target) = 0;
+
+	virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0;
+	virtual bool render_target_is_clear_requested(RID p_render_target) = 0;
+	virtual Color render_target_get_clear_request_color(RID p_render_target) = 0;
+	virtual void render_target_disable_clear_request(RID p_render_target) = 0;
+	virtual void render_target_do_clear_request(RID p_render_target) = 0;
+
+	virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
+	virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
+	virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
 };
 
 #endif // !TEXTURE_STORAGE_H

+ 4 - 3
servers/xr/xr_interface_extension.cpp

@@ -30,6 +30,7 @@
 
 #include "xr_interface_extension.h"
 #include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/renderer_storage.h"
 #include "servers/rendering/rendering_server_globals.h"
 
@@ -339,10 +340,10 @@ void XRInterfaceExtension::notification(int p_what) {
 RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
 	// In due time this will need to be enhance to return the correct INTERNAL RID for the chosen rendering engine.
 	// So once a GLES driver is implemented we'll return that and the implemented plugin needs to handle this correctly too.
-	RendererStorageRD *rd_storage = RendererStorageRD::base_singleton;
-	ERR_FAIL_NULL_V_MSG(rd_storage, RID(), "Renderer storage not setup");
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	ERR_FAIL_NULL_V_MSG(texture_storage, RID(), "Texture storage not setup");
 
-	return rd_storage->render_target_get_rd_texture(p_render_target);
+	return texture_storage->render_target_get_rd_texture(p_render_target);
 }
 
 /*

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно