Browse Source

Extract Decal and Decal atlas from Storage class

Bastiaan Olij 3 years ago
parent
commit
0fe06e9467
27 changed files with 1001 additions and 686 deletions
  1. 3 0
      drivers/gles3/rasterizer_gles3.h
  2. 0 40
      drivers/gles3/rasterizer_storage_gles3.cpp
  3. 0 19
      drivers/gles3/rasterizer_storage_gles3.h
  4. 75 0
      drivers/gles3/storage/decal_atlas_storage.cpp
  5. 67 0
      drivers/gles3/storage/decal_atlas_storage.h
  6. 3 0
      servers/rendering/dummy/rasterizer_dummy.h
  7. 0 19
      servers/rendering/dummy/rasterizer_storage_dummy.h
  8. 62 0
      servers/rendering/dummy/storage/decal_atlas_storage.h
  9. 2 0
      servers/rendering/renderer_compositor.h
  10. 3 2
      servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
  11. 3 2
      servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
  12. 7 4
      servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
  13. 2 0
      servers/rendering/renderer_rd/renderer_compositor_rd.cpp
  14. 5 2
      servers/rendering/renderer_rd/renderer_compositor_rd.h
  15. 30 25
      servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
  16. 10 387
      servers/rendering/renderer_rd/renderer_storage_rd.cpp
  17. 0 159
      servers/rendering/renderer_rd/renderer_storage_rd.h
  18. 437 0
      servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp
  19. 211 0
      servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h
  20. 3 5
      servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
  21. 1 1
      servers/rendering/renderer_scene_cull.cpp
  22. 0 21
      servers/rendering/renderer_storage.h
  23. 1 0
      servers/rendering/rendering_server_default.cpp
  24. 13 0
      servers/rendering/rendering_server_default.h
  25. 1 0
      servers/rendering/rendering_server_globals.cpp
  26. 2 0
      servers/rendering/rendering_server_globals.h
  27. 60 0
      servers/rendering/storage/decal_atlas_storage.h

+ 3 - 0
drivers/gles3/rasterizer_gles3.h

@@ -39,6 +39,7 @@
 #include "servers/rendering/renderer_compositor.h"
 #include "storage/canvas_texture_storage.h"
 #include "storage/config.h"
+#include "storage/decal_atlas_storage.h"
 #include "storage/render_target_storage.h"
 #include "storage/texture_storage.h"
 
@@ -53,6 +54,7 @@ protected:
 	GLES3::Config config;
 	GLES3::CanvasTextureStorage canvas_texture_storage;
 	GLES3::TextureStorage texture_storage;
+	GLES3::DecalAtlasStorage decal_atlas_storage;
 	RasterizerStorageGLES3 storage;
 	RasterizerCanvasGLES3 canvas;
 	RasterizerSceneGLES3 scene;
@@ -62,6 +64,7 @@ protected:
 public:
 	RendererCanvasTextureStorage *get_canvas_texture_storage() { return &canvas_texture_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; }

+ 0 - 40
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -1202,46 +1202,6 @@ void RasterizerStorageGLES3::base_update_dependency(RID p_base, DependencyTracke
 void RasterizerStorageGLES3::skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) {
 }
 
-/* DECAL API */
-
-RID RasterizerStorageGLES3::decal_allocate() {
-	return RID();
-}
-
-void RasterizerStorageGLES3::decal_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
-}
-
-void RasterizerStorageGLES3::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
-}
-
-void RasterizerStorageGLES3::decal_set_emission_energy(RID p_decal, float p_energy) {
-}
-
-void RasterizerStorageGLES3::decal_set_albedo_mix(RID p_decal, float p_mix) {
-}
-
-void RasterizerStorageGLES3::decal_set_modulate(RID p_decal, const Color &p_modulate) {
-}
-
-void RasterizerStorageGLES3::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
-}
-
-void RasterizerStorageGLES3::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
-}
-
-void RasterizerStorageGLES3::decal_set_fade(RID p_decal, float p_above, float p_below) {
-}
-
-void RasterizerStorageGLES3::decal_set_normal_fade(RID p_decal, float p_fade) {
-}
-
-AABB RasterizerStorageGLES3::decal_get_aabb(RID p_decal) const {
-	return AABB();
-}
-
 /* VOXEL GI API */
 
 RID RasterizerStorageGLES3::voxel_gi_allocate() {

+ 0 - 19
drivers/gles3/rasterizer_storage_gles3.h

@@ -579,25 +579,6 @@ public:
 	void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
 	void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override;
 
-	/* DECAL API */
-
-	RID decal_allocate() override;
-	void decal_initialize(RID p_rid) override;
-	void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
-	void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
-	void decal_set_emission_energy(RID p_decal, float p_energy) override;
-	void decal_set_albedo_mix(RID p_decal, float p_mix) override;
-	void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
-	void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
-	void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
-	void decal_set_fade(RID p_decal, float p_above, float p_below) override;
-	void decal_set_normal_fade(RID p_decal, float p_fade) override;
-
-	AABB decal_get_aabb(RID p_decal) const override;
-
-	void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-	void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-
 	/* VOXEL GI API */
 
 	RID voxel_gi_allocate() override;

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

@@ -0,0 +1,75 @@
+/*************************************************************************/
+/*  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

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

@@ -0,0 +1,67 @@
+/*************************************************************************/
+/*  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

+ 3 - 0
servers/rendering/dummy/rasterizer_dummy.h

@@ -38,6 +38,7 @@
 #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/texture_storage.h"
 #include "servers/rendering/renderer_compositor.h"
 #include "servers/rendering_server.h"
@@ -51,12 +52,14 @@ protected:
 	RasterizerCanvasDummy canvas;
 	RendererDummy::CanvasTextureStorage canvas_texture_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; };
 	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; }

+ 0 - 19
servers/rendering/dummy/rasterizer_storage_dummy.h

@@ -214,25 +214,6 @@ public:
 	void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
 	void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
 
-	/* DECAL API */
-
-	RID decal_allocate() override { return RID(); }
-	void decal_initialize(RID p_rid) override {}
-	void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
-	void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
-	void decal_set_emission_energy(RID p_decal, float p_energy) override {}
-	void decal_set_albedo_mix(RID p_decal, float p_mix) override {}
-	void decal_set_modulate(RID p_decal, const Color &p_modulate) override {}
-	void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {}
-	void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {}
-	void decal_set_fade(RID p_decal, float p_above, float p_below) override {}
-	void decal_set_normal_fade(RID p_decal, float p_fade) override {}
-
-	AABB decal_get_aabb(RID p_decal) const override { return AABB(); }
-
-	void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-	void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-
 	/* VOXEL GI API */
 
 	RID voxel_gi_allocate() override { return RID(); }

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

@@ -0,0 +1,62 @@
+/*************************************************************************/
+/*  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

+ 2 - 0
servers/rendering/renderer_compositor.h

@@ -35,6 +35,7 @@
 #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/texture_storage.h"
 #include "servers/rendering_server.h"
 
@@ -74,6 +75,7 @@ public:
 
 	virtual RendererCanvasTextureStorage *get_canvas_texture_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;

+ 3 - 2
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp

@@ -30,6 +30,7 @@
 
 #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/uniform_set_cache_rd.h"
 #include "servers/rendering/rendering_device.h"
 #include "servers/rendering/rendering_server_default.h"
@@ -2140,7 +2141,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 11;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID decal_atlas = storage->decal_atlas_get_texture();
+			RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture();
 			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
@@ -2148,7 +2149,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID decal_atlas = storage->decal_atlas_get_texture_srgb();
+			RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_srgb();
 			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}

+ 3 - 2
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

@@ -30,6 +30,7 @@
 
 #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/rendering_device.h"
 #include "servers/rendering/rendering_server_default.h"
 
@@ -1275,7 +1276,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 11;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID decal_atlas = storage->decal_atlas_get_texture();
+			RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture();
 			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
@@ -1283,7 +1284,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID decal_atlas = storage->decal_atlas_get_texture_srgb();
+			RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_srgb();
 			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}

+ 7 - 4
servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

@@ -35,6 +35,7 @@
 #include "core/math/math_defs.h"
 #include "core/math/math_funcs.h"
 #include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
 #include "servers/rendering/rendering_server_default.h"
 
 void RendererCanvasRenderRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
@@ -947,7 +948,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(storage->decal_atlas_get_texture());
+		u.append_id(RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture());
 		uniforms.push_back(u);
 	}
 
@@ -1253,7 +1254,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 			}
 
 			if (clight->texture.is_valid()) {
-				Rect2 atlas_rect = storage->decal_atlas_get_texture_rect(clight->texture);
+				Rect2 atlas_rect = RendererRD::DecalAtlasStorage::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;
@@ -1479,18 +1480,20 @@ RID RendererCanvasRenderRD::light_create() {
 }
 
 void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
+	RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton();
+
 	CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
 	ERR_FAIL_COND(!cl);
 	if (cl->texture == p_texture) {
 		return;
 	}
 	if (cl->texture.is_valid()) {
-		storage->texture_remove_from_decal_atlas(cl->texture);
+		decal_atlas_storage->texture_remove_from_decal_atlas(cl->texture);
 	}
 	cl->texture = p_texture;
 
 	if (cl->texture.is_valid()) {
-		storage->texture_add_to_decal_atlas(cl->texture);
+		decal_atlas_storage->texture_add_to_decal_atlas(cl->texture);
 	}
 }
 

+ 2 - 0
servers/rendering/renderer_rd/renderer_compositor_rd.cpp

@@ -155,6 +155,7 @@ void RendererCompositorRD::finalize() {
 	memdelete(scene);
 	memdelete(canvas);
 	memdelete(storage);
+	memdelete(decal_atlas_storage);
 	memdelete(texture_storage);
 	memdelete(canvas_texture_storage);
 
@@ -287,6 +288,7 @@ RendererCompositorRD::RendererCompositorRD() {
 
 	canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage);
 	texture_storage = memnew(RendererRD::TextureStorage);
+	decal_atlas_storage = memnew(RendererRD::DecalAtlasStorage);
 	storage = memnew(RendererStorageRD);
 	canvas = memnew(RendererCanvasRenderRD(storage));
 

+ 5 - 2
servers/rendering/renderer_rd/renderer_compositor_rd.h

@@ -40,6 +40,7 @@
 #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/texture_storage.h"
 #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
 
@@ -49,6 +50,7 @@ protected:
 	RendererCanvasRenderRD *canvas;
 	RendererRD::CanvasTextureStorage *canvas_texture_storage;
 	RendererRD::TextureStorage *texture_storage;
+	RendererRD::DecalAtlasStorage *decal_atlas_storage;
 	RendererStorageRD *storage;
 	RendererSceneRenderRD *scene;
 
@@ -92,8 +94,9 @@ protected:
 	static uint64_t frame;
 
 public:
-	RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; };
-	RendererTextureStorage *get_texture_storage() { return texture_storage; };
+	RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_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; }

+ 30 - 25
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -33,6 +33,7 @@
 #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/rendering_server_default.h"
 
 void get_vogel_disk(float *r_kernel, int p_sample_count) {
@@ -2674,7 +2675,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DECAL_ATLAS) {
-		RID decal_atlas = storage->decal_atlas_get_texture();
+		RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture();
 
 		if (decal_atlas.is_valid()) {
 			Size2 rtsize = storage->render_target_get_size(rb->render_target);
@@ -3262,6 +3263,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();
+
 	Transform3D inverse_transform = p_camera_transform.affine_inverse();
 
 	r_directional_light_count = 0;
@@ -3545,7 +3548,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 		RID projector = storage->light_get_projector(base);
 
 		if (projector.is_valid()) {
-			Rect2 rect = storage->decal_atlas_get_texture_rect(projector);
+			Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(projector);
 
 			if (type == RS::LIGHT_SPOT) {
 				light_data.projector_rect[0] = rect.position.x;
@@ -3661,6 +3664,8 @@ 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();
+
 	Transform3D uv_xform;
 	uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
 	uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
@@ -3684,9 +3689,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 
 		real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
 
-		if (storage->decal_is_distance_fade_enabled(decal)) {
-			float fade_begin = storage->decal_get_distance_fade_begin(decal);
-			float fade_length = storage->decal_get_distance_fade_length(decal);
+		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 (distance > fade_begin) {
 				if (distance > fade_begin + fade_length) {
@@ -3714,15 +3719,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 = storage->decal_get_cull_mask(decal);
+		di->cull_mask = decal_atlas_storage->decal_get_cull_mask(decal);
 
 		Transform3D xform = di->transform;
 		float fade = 1.0;
 
-		if (storage->decal_is_distance_fade_enabled(decal)) {
+		if (decal_atlas_storage->decal_is_distance_fade_enabled(decal)) {
 			real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
-			float fade_begin = storage->decal_get_distance_fade_begin(decal);
-			float fade_length = storage->decal_get_distance_fade_length(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 (distance > fade_begin) {
 				fade = 1.0 - (distance - fade_begin) / fade_length;
@@ -3731,7 +3736,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 
 		Cluster::DecalData &dd = cluster.decals[i];
 
-		Vector3 decal_extents = storage->decal_get_extents(decal);
+		Vector3 decal_extents = decal_atlas_storage->decal_get_extents(decal);
 
 		Transform3D scale_xform;
 		scale_xform.basis.scale(decal_extents);
@@ -3744,12 +3749,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 = storage->decal_get_normal_fade(decal);
+		dd.normal_fade = decal_atlas_storage->decal_get_normal_fade(decal);
 
-		RID albedo_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
-		RID emission_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
+		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);
 		if (albedo_tex.is_valid()) {
-			Rect2 rect = storage->decal_atlas_get_texture_rect(albedo_tex);
+			Rect2 rect = decal_atlas_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;
@@ -3764,10 +3769,10 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 			dd.albedo_rect[3] = 0;
 		}
 
-		RID normal_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
+		RID normal_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
 
 		if (normal_tex.is_valid()) {
-			Rect2 rect = storage->decal_atlas_get_texture_rect(normal_tex);
+			Rect2 rect = decal_atlas_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;
@@ -3782,9 +3787,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 			dd.normal_rect[3] = 0;
 		}
 
-		RID orm_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
+		RID orm_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
 		if (orm_tex.is_valid()) {
-			Rect2 rect = storage->decal_atlas_get_texture_rect(orm_tex);
+			Rect2 rect = decal_atlas_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;
@@ -3797,7 +3802,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 		}
 
 		if (emission_tex.is_valid()) {
-			Rect2 rect = storage->decal_atlas_get_texture_rect(emission_tex);
+			Rect2 rect = decal_atlas_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;
@@ -3809,16 +3814,16 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
 			dd.emission_rect[3] = 0;
 		}
 
-		Color modulate = storage->decal_get_modulate(decal);
+		Color modulate = decal_atlas_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 = storage->decal_get_emission_energy(decal) * fade;
-		dd.albedo_mix = storage->decal_get_albedo_mix(decal);
-		dd.mask = storage->decal_get_cull_mask(decal);
-		dd.upper_fade = storage->decal_get_upper_fade(decal);
-		dd.lower_fade = storage->decal_get_lower_fade(decal);
+		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);
 
 		if (current_cluster_builder != nullptr) {
 			current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents);

+ 10 - 387
servers/rendering/renderer_rd/renderer_storage_rd.cpp

@@ -36,6 +36,7 @@
 #include "core/math/math_defs.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/texture_storage.h"
 #include "servers/rendering/rendering_server_globals.h"
 #include "servers/rendering/shader_language.h"
@@ -5315,6 +5316,7 @@ void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
 }
 
 void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) {
+	RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton();
 	Light *light = light_owner.get_or_null(p_light);
 	ERR_FAIL_COND(!light);
 
@@ -5323,14 +5325,14 @@ void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) {
 	}
 
 	if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
-		texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+		decal_atlas_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_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+			decal_atlas_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
 		}
 		light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
 	}
@@ -5727,97 +5729,6 @@ float RendererStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe)
 	return reflection_probe->ambient_color_energy;
 }
 
-RID RendererStorageRD::decal_allocate() {
-	return decal_owner.allocate_rid();
-}
-void RendererStorageRD::decal_initialize(RID p_decal) {
-	decal_owner.initialize_rid(p_decal, Decal());
-}
-
-void RendererStorageRD::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(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::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() && !RendererRD::TextureStorage::get_singleton()->owns_texture(p_texture));
-
-	if (decal->textures[p_type].is_valid() && RendererRD::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(DEPENDENCY_CHANGED_DECAL);
-}
-
-void RendererStorageRD::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 RendererStorageRD::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 RendererStorageRD::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 RendererStorageRD::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(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::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 RendererStorageRD::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 RendererStorageRD::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;
-}
-
-AABB RendererStorageRD::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);
-}
-
 RID RendererStorageRD::voxel_gi_allocate() {
 	return voxel_gi_owner.allocate_rid();
 }
@@ -7030,8 +6941,8 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
 	} else if (reflection_probe_owner.owns(p_base)) {
 		ReflectionProbe *rp = reflection_probe_owner.get_or_null(p_base);
 		p_instance->update_dependency(&rp->dependency);
-	} else if (decal_owner.owns(p_base)) {
-		Decal *decal = decal_owner.get_or_null(p_base);
+	} else if (RendererRD::DecalAtlasStorage::get_singleton()->owns_decal(p_base)) {
+		RendererRD::Decal *decal = RendererRD::DecalAtlasStorage::get_singleton()->get_decal(p_base);
 		p_instance->update_dependency(&decal->dependency);
 	} else if (voxel_gi_owner.owns(p_base)) {
 		VoxelGI *gip = voxel_gi_owner.get_or_null(p_base);
@@ -7074,7 +6985,7 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
 	if (reflection_probe_owner.owns(p_rid)) {
 		return RS::INSTANCE_REFLECTION_PROBE;
 	}
-	if (decal_owner.owns(p_rid)) {
+	if (RendererRD::DecalAtlasStorage::get_singleton()->owns_decal(p_rid)) {
 		return RS::INSTANCE_DECAL;
 	}
 	if (voxel_gi_owner.owns(p_rid)) {
@@ -7102,252 +7013,6 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
 	return RS::INSTANCE_NONE;
 }
 
-void RendererStorageRD::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.
-	}
-}
-
-void RendererStorageRD::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 RendererStorageRD::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 RendererStorageRD::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
-	}
-}
-
-RID RendererStorageRD::decal_atlas_get_texture() const {
-	return decal_atlas.texture;
-}
-
-RID RendererStorageRD::decal_atlas_get_texture_srgb() const {
-	return decal_atlas.texture_srgb;
-}
-
-void RendererStorageRD::_update_decal_atlas() {
-	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];
-
-			RendererRD::Texture *src_tex = RendererRD::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);
-					RendererRD::Texture *src_tex = RendererRD::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);
-		}
-	}
-}
-
 int32_t RendererStorageRD::_global_variable_allocate(uint32_t p_elements) {
 	int32_t idx = 0;
 	while (idx + p_elements <= global_variables.buffer_size) {
@@ -8017,7 +7682,7 @@ void RendererStorageRD::update_dirty_resources() {
 	_update_queued_materials();
 	_update_dirty_multimeshes();
 	_update_dirty_skeletons();
-	_update_decal_atlas();
+	RendererRD::DecalAtlasStorage::get_singleton()->update_decal_atlas();
 }
 
 bool RendererStorageRD::has_os_feature(const String &p_feature) const {
@@ -8103,15 +7768,8 @@ bool RendererStorageRD::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);
-	} else if (decal_owner.owns(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() && RendererRD::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);
+	} else if (RendererRD::DecalAtlasStorage::get_singleton()->owns_decal(p_rid)) {
+		RendererRD::DecalAtlasStorage::get_singleton()->decal_free(p_rid);
 	} else if (voxel_gi_owner.owns(p_rid)) {
 		voxel_gi_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
 		VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_rid);
@@ -8259,33 +7917,6 @@ RendererStorageRD::RendererStorageRD() {
 	memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
 	global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
 
-	{ // 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;
-		}
-	}
-
 	//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++) {
@@ -8737,14 +8368,6 @@ RendererStorageRD::~RendererStorageRD() {
 
 	RD::get_singleton()->free(default_rd_storage_buffer);
 
-	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);
-	}
-
 	if (effects) {
 		memdelete(effects);
 		effects = nullptr;

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

@@ -205,50 +205,6 @@ private:
 	RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
 	RID default_rd_storage_buffer;
 
-	/* DECAL ATLAS */
-
-	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;
-
-	} decal_atlas;
-
-	void _update_decal_atlas();
-
 	/* SHADER */
 
 	struct Material;
@@ -952,27 +908,6 @@ private:
 
 	mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
 
-	/* DECAL */
-
-	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;
-
-		Dependency dependency;
-	};
-
-	mutable RID_Owner<Decal, true> decal_owner;
-
 	/* VOXEL GI */
 
 	struct VoxelGI {
@@ -1190,17 +1125,6 @@ private:
 	EffectsRD *effects = nullptr;
 
 public:
-	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;
-	}
-
 	//internal usage
 
 	_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
@@ -1791,89 +1715,6 @@ public:
 	void base_update_dependency(RID p_base, DependencyTracker *p_instance);
 	void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance);
 
-	/* DECAL API */
-
-	RID decal_allocate();
-	void decal_initialize(RID p_decal);
-
-	virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents);
-	virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture);
-	virtual void decal_set_emission_energy(RID p_decal, float p_energy);
-	virtual void decal_set_albedo_mix(RID p_decal, float p_mix);
-	virtual void decal_set_modulate(RID p_decal, const Color &p_modulate);
-	virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers);
-	virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length);
-	virtual void decal_set_fade(RID p_decal, float p_above, float p_below);
-	virtual void decal_set_normal_fade(RID p_decal, float p_fade);
-
-	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);
-	virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false);
-
-	_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;
-
 	/* VOXEL GI API */
 
 	RID voxel_gi_allocate();

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

@@ -0,0 +1,437 @@
+/*************************************************************************/
+/*  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
+	}
+}

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

@@ -0,0 +1,211 @@
+/*************************************************************************/
+/*  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

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

@@ -29,9 +29,7 @@
 /*************************************************************************/
 
 #include "texture_storage.h"
-
-// only include until we have DecalStorage sorted
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "decal_atlas_storage.h"
 
 using namespace RendererRD;
 
@@ -332,7 +330,7 @@ void TextureStorage::texture_free(RID p_texture) {
 		}
 	}
 
-	RendererStorageRD::base_singleton->decal_atlas_remove_texture(p_texture);
+	DecalAtlasStorage::get_singleton()->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]);
@@ -931,7 +929,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);
 
-	RendererStorageRD::base_singleton->decal_atlas_mark_dirty_on_texture(p_texture);
+	DecalAtlasStorage::get_singleton()->decal_atlas_mark_dirty_on_texture(p_texture);
 }
 
 void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) {

+ 1 - 1
servers/rendering/renderer_scene_cull.cpp

@@ -1887,7 +1887,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
 
 		} break;
 		case RenderingServer::INSTANCE_DECAL: {
-			new_aabb = RSG::storage->decal_get_aabb(p_instance->base);
+			new_aabb = RSG::decal_atlas_storage->decal_get_aabb(p_instance->base);
 
 		} break;
 		case RenderingServer::INSTANCE_VOXEL_GI: {

+ 0 - 21
servers/rendering/renderer_storage.h

@@ -54,7 +54,6 @@ public:
 
 	struct DependencyTracker;
 
-protected:
 	struct Dependency {
 		void changed_notify(DependencyChangedNotification p_notification);
 		void deleted_notify(const RID &p_rid);
@@ -327,26 +326,6 @@ public:
 	virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
 	virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
 
-	/* DECAL API */
-
-	virtual RID decal_allocate() = 0;
-	virtual void decal_initialize(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;
-
 	/* VOXEL GI API */
 
 	virtual RID voxel_gi_allocate() = 0;

+ 1 - 0
servers/rendering/rendering_server_default.cpp

@@ -399,6 +399,7 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
 	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::texture_storage = RSG::rasterizer->get_texture_storage();
 	RSG::storage = RSG::rasterizer->get_storage();
 	RSG::canvas_render = RSG::rasterizer->get_canvas();

+ 13 - 0
servers/rendering/rendering_server_default.h

@@ -385,6 +385,12 @@ public:
 
 	/* DECAL API */
 
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererDecalAtlasStorage
+#define server_name RSG::decal_atlas_storage
+
 	FUNCRIDSPLIT(decal)
 
 	FUNC2(decal_set_extents, RID, const Vector3 &)
@@ -399,6 +405,13 @@ public:
 
 	/* BAKED LIGHT API */
 
+//from now on, calls forwarded to this singleton
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererStorage
+#define server_name RSG::storage
+
 	FUNCRIDSPLIT(voxel_gi)
 
 	FUNC8(voxel_gi_allocate_data, RID, const Transform3D &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)

+ 1 - 0
servers/rendering/rendering_server_globals.cpp

@@ -33,6 +33,7 @@
 bool RenderingServerGlobals::threaded = false;
 
 RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr;
+RendererDecalAtlasStorage *RenderingServerGlobals::decal_atlas_storage = nullptr;
 RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr;
 RendererStorage *RenderingServerGlobals::storage = nullptr;
 RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;

+ 2 - 0
servers/rendering/rendering_server_globals.h

@@ -35,6 +35,7 @@
 #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/texture_storage.h"
 
 class RendererCanvasCull;
@@ -47,6 +48,7 @@ public:
 
 	static RendererCanvasTextureStorage *canvas_texture_storage;
 	static RendererTextureStorage *texture_storage;
+	static RendererDecalAtlasStorage *decal_atlas_storage;
 	static RendererStorage *storage;
 	static RendererCanvasRender *canvas_render;
 	static RendererCompositor *rasterizer;

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

@@ -0,0 +1,60 @@
+/*************************************************************************/
+/*  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