Explorar el Código

Merge pull request #59062 from BastiaanOlij/storagerd_texture

Rémi Verschelde hace 3 años
padre
commit
f995f47965
Se han modificado 55 ficheros con 5134 adiciones y 3543 borrados
  1. 1 0
      drivers/gles3/SCsub
  2. 22 16
      drivers/gles3/rasterizer_canvas_gles3.cpp
  3. 5 1
      drivers/gles3/rasterizer_canvas_gles3.h
  4. 9 9
      drivers/gles3/rasterizer_gles3.cpp
  5. 9 0
      drivers/gles3/rasterizer_gles3.h
  6. 0 1213
      drivers/gles3/rasterizer_storage_gles3.cpp
  7. 14 462
      drivers/gles3/rasterizer_storage_gles3.h
  8. 5 0
      drivers/gles3/storage/SCsub
  9. 96 0
      drivers/gles3/storage/canvas_texture_storage.cpp
  10. 87 0
      drivers/gles3/storage/canvas_texture_storage.h
  11. 156 0
      drivers/gles3/storage/config.cpp
  12. 113 0
      drivers/gles3/storage/config.h
  13. 132 0
      drivers/gles3/storage/render_target_storage.h
  14. 1211 0
      drivers/gles3/storage/texture_storage.cpp
  15. 389 0
      drivers/gles3/storage/texture_storage.h
  16. 1 1
      platform/javascript/display_server_javascript.cpp
  17. 1 1
      scene/resources/texture.cpp
  18. 1 1
      servers/display_server_headless.h
  19. 1 0
      servers/rendering/SCsub
  20. 63 0
      servers/rendering/dummy/rasterizer_canvas_dummy.h
  21. 99 0
      servers/rendering/dummy/rasterizer_dummy.h
  22. 217 0
      servers/rendering/dummy/rasterizer_scene_dummy.h
  23. 11 339
      servers/rendering/dummy/rasterizer_storage_dummy.h
  24. 53 0
      servers/rendering/dummy/storage/canvas_texture_storage.h
  25. 116 0
      servers/rendering/dummy/storage/texture_storage.h
  26. 7 6
      servers/rendering/renderer_canvas_cull.cpp
  27. 4 0
      servers/rendering/renderer_compositor.h
  28. 1 0
      servers/rendering/renderer_rd/SCsub
  29. 24 24
      servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
  30. 9 9
      servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
  31. 7 5
      servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
  32. 4 0
      servers/rendering/renderer_rd/renderer_canvas_render_rd.h
  33. 9 5
      servers/rendering/renderer_rd/renderer_compositor_rd.cpp
  34. 6 0
      servers/rendering/renderer_rd/renderer_compositor_rd.h
  35. 27 18
      servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
  36. 1 0
      servers/rendering/renderer_rd/renderer_scene_gi_rd.h
  37. 18 17
      servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
  38. 2 0
      servers/rendering/renderer_rd/renderer_scene_render_rd.h
  39. 13 9
      servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
  40. 3 1104
      servers/rendering/renderer_rd/renderer_storage_rd.cpp
  41. 10 208
      servers/rendering/renderer_rd/renderer_storage_rd.h
  42. 5 0
      servers/rendering/renderer_rd/storage_rd/SCsub
  43. 235 0
      servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp
  44. 90 0
      servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h
  45. 1420 0
      servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
  46. 230 0
      servers/rendering/renderer_rd/storage_rd/texture_storage.h
  47. 3 53
      servers/rendering/renderer_storage.h
  48. 1 1
      servers/rendering/renderer_viewport.cpp
  49. 2 0
      servers/rendering/rendering_server_default.cpp
  50. 49 41
      servers/rendering/rendering_server_default.h
  51. 2 0
      servers/rendering/rendering_server_globals.cpp
  52. 4 0
      servers/rendering/rendering_server_globals.h
  53. 5 0
      servers/rendering/storage/SCsub
  54. 51 0
      servers/rendering/storage/canvas_texture_storage.h
  55. 80 0
      servers/rendering/storage/texture_storage.h

+ 1 - 0
drivers/gles3/SCsub

@@ -5,3 +5,4 @@ Import("env")
 env.add_source_files(env.drivers_sources, "*.cpp")
 
 SConscript("shaders/SCsub")
+SConscript("storage/SCsub")

+ 22 - 16
drivers/gles3/rasterizer_canvas_gles3.cpp

@@ -38,6 +38,8 @@
 
 #include "core/config/project_settings.h"
 #include "servers/rendering/rendering_server_default.h"
+#include "storage/canvas_texture_storage.h"
+#include "storage/config.h"
 
 #ifndef GLES_OVER_GL
 #define glClearDepth glClearDepthf
@@ -260,7 +262,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
 				for (int ti = 0; ti < tc; i++) {
 					glActiveTexture(GL_TEXTURE0 + ti);
 
-					RasterizerStorageGLES3::Texture *t = storage->texture_owner.get_or_null(textures[ti].second);
+					GLES3::Texture *t = texture_storage->get_texture(textures[ti].second);
 
 					if (!t) {
 						switch (texture_uniforms[i].hint) {
@@ -915,20 +917,20 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
 	state.end_batch = true;
 	_render_batch(r_index);
 
-	RasterizerStorageGLES3::CanvasTexture *ct = nullptr;
+	GLES3::CanvasTexture *ct = nullptr;
 
-	RasterizerStorageGLES3::Texture *t = storage->texture_owner.get_or_null(p_texture);
+	GLES3::Texture *t = texture_storage->get_texture(p_texture);
 
 	if (t) {
 		//regular texture
 		if (!t->canvas_texture) {
-			t->canvas_texture = memnew(RasterizerStorageGLES3::CanvasTexture);
+			t->canvas_texture = memnew(GLES3::CanvasTexture);
 			t->canvas_texture->diffuse = p_texture;
 		}
 
 		ct = t->canvas_texture;
 	} else {
-		ct = storage->canvas_texture_owner.get_or_null(p_texture);
+		ct = GLES3::CanvasTextureStorage::get_singleton()->get_canvas_texture(p_texture);
 	}
 
 	if (!ct) {
@@ -943,7 +945,7 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
 	RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
 	ERR_FAIL_COND(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
 
-	RasterizerStorageGLES3::Texture *texture = storage->texture_owner.get_or_null(ct->diffuse);
+	GLES3::Texture *texture = texture_storage->get_texture(ct->diffuse);
 
 	if (!texture) {
 		state.current_tex = RID();
@@ -967,18 +969,18 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
 		texture->GLSetRepeat(GL_TEXTURE_2D, repeat);
 	}
 
-	RasterizerStorageGLES3::Texture *normal_map = storage->texture_owner.get_or_null(ct->normal_map);
+	GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map);
 
 	if (!normal_map) {
 		state.current_normal = RID();
 		ct->use_normal_cache = false;
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+		glActiveTexture(GL_TEXTURE0 + GLES3::Config::get_singleton()->max_texture_image_units - 6);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
 
 	} else {
 		normal_map = normal_map->get_ptr();
 
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+		glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 6);
 		glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
 		state.current_normal = ct->normal_map;
 		ct->use_normal_cache = true;
@@ -986,18 +988,18 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
 		texture->GLSetRepeat(GL_TEXTURE_2D, repeat);
 	}
 
-	RasterizerStorageGLES3::Texture *specular_map = storage->texture_owner.get_or_null(ct->specular);
+	GLES3::Texture *specular_map = texture_storage->get_texture(ct->specular);
 
 	if (!specular_map) {
 		state.current_specular = RID();
 		ct->use_specular_cache = false;
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
+		glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7);
 		glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
 
 	} else {
 		specular_map = specular_map->get_ptr();
 
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
+		glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7);
 		glBindTexture(GL_TEXTURE_2D, specular_map->tex_id);
 		state.current_specular = ct->specular;
 		ct->use_specular_cache = true;
@@ -1249,6 +1251,10 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() {
 }
 
 void RasterizerCanvasGLES3::initialize() {
+	// !BAS! shouldn't we be obtaining storage here as well?
+	canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+	texture_storage = GLES3::TextureStorage::get_singleton();
+
 	// quad buffer
 	{
 		glGenBuffers(1, &data.canvas_quad_vertices);
@@ -1408,7 +1414,7 @@ void RasterizerCanvasGLES3::initialize() {
 	state.canvas_shader_default_version = state.canvas_shader.version_create();
 	state.canvas_shader.version_bind_shader(state.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD);
 
-	//state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows);
+	//state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config->use_rgba_2d_shadows);
 
 	//state.canvas_shader.bind();
 
@@ -1441,8 +1447,8 @@ void fragment() {
 		storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
 	}
 
-	default_canvas_texture = storage->canvas_texture_allocate();
-	storage->canvas_texture_initialize(default_canvas_texture);
+	default_canvas_texture = canvas_texture_storage->canvas_texture_allocate();
+	canvas_texture_storage->canvas_texture_initialize(default_canvas_texture);
 
 	state.using_light = nullptr;
 	state.using_transparent_rt = false;
@@ -1456,7 +1462,7 @@ RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
 	state.canvas_shader.version_free(state.canvas_shader_default_version);
 	storage->free(default_canvas_group_material);
 	storage->free(default_canvas_group_shader);
-	storage->free(default_canvas_texture);
+	canvas_texture_storage->canvas_texture_free(default_canvas_texture);
 }
 
 void RasterizerCanvasGLES3::finalize() {

+ 5 - 1
drivers/gles3/rasterizer_canvas_gles3.h

@@ -37,6 +37,8 @@
 #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/texture_storage.h"
 
 #include "shaders/canvas.glsl.gen.h"
 
@@ -184,7 +186,7 @@ public:
 		RID current_tex = RID();
 		RID current_normal = RID();
 		RID current_specular = RID();
-		RasterizerStorageGLES3::Texture *current_tex_ptr;
+		GLES3::Texture *current_tex_ptr;
 		RID current_shader_version = RID();
 		RS::PrimitiveType current_primitive = RS::PRIMITIVE_MAX;
 		uint32_t current_primitive_points = 0;
@@ -217,6 +219,8 @@ public:
 
 	RasterizerSceneGLES3 *scene_render;
 
+	GLES3::CanvasTextureStorage *canvas_texture_storage;
+	GLES3::TextureStorage *texture_storage;
 	RasterizerStorageGLES3 *storage;
 
 	void _set_uniforms();

+ 9 - 9
drivers/gles3/rasterizer_gles3.cpp

@@ -195,7 +195,7 @@ typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userP
 void RasterizerGLES3::initialize() {
 	print_verbose("Using OpenGL video driver");
 
-	storage._main_thread_id = Thread::get_caller_id();
+	texture_storage.set_main_thread_id(Thread::get_caller_id());
 
 #ifdef GLAD_ENABLED
 	if (!gladLoadGL()) {
@@ -271,7 +271,7 @@ 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);
 
-	RasterizerStorageGLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target);
+	GLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target);
 	ERR_FAIL_COND(!rt);
 
 	// TODO: do we need a keep 3d linear option?
@@ -324,10 +324,10 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
 
 	canvas.canvas_begin();
 
-	RID texture = storage.texture_create();
-	//storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0);
-	storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D);
-	storage.texture_set_data(texture, p_image);
+	RID texture = texture_storage.texture_create();
+	//texture_storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0);
+	texture_storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D);
+	texture_storage.texture_set_data(texture, p_image);
 
 	Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());
 	Rect2 screenrect;
@@ -349,13 +349,13 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
 		screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor();
 	}
 
-	RasterizerStorageGLES3::Texture *t = storage.texture_owner.get_or_null(texture);
-	glActiveTexture(GL_TEXTURE0 + storage.config.max_texture_image_units - 1);
+	GLES3::Texture *t = texture_storage.get_texture(texture);
+	glActiveTexture(GL_TEXTURE0 + config.max_texture_image_units - 1);
 	glBindTexture(GL_TEXTURE_2D, t->tex_id);
 	glBindTexture(GL_TEXTURE_2D, 0);
 	canvas.canvas_end();
 
-	storage.free(texture);
+	texture_storage.texture_free(texture);
 
 	end_frame(true);
 }

+ 9 - 0
drivers/gles3/rasterizer_gles3.h

@@ -37,6 +37,10 @@
 #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/render_target_storage.h"
+#include "storage/texture_storage.h"
 
 class RasterizerGLES3 : public RendererCompositor {
 private:
@@ -46,6 +50,9 @@ private:
 	double time_total = 0.0;
 
 protected:
+	GLES3::Config config;
+	GLES3::CanvasTextureStorage canvas_texture_storage;
+	GLES3::TextureStorage texture_storage;
 	RasterizerStorageGLES3 storage;
 	RasterizerCanvasGLES3 canvas;
 	RasterizerSceneGLES3 scene;
@@ -53,6 +60,8 @@ 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; }
+	RendererTextureStorage *get_texture_storage() { return &texture_storage; }
 	RendererStorage *get_storage() { return &storage; }
 	RendererCanvasRender *get_canvas() { return &canvas; }
 	RendererSceneRender *get_scene() { return &scene; }

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 1213
drivers/gles3/rasterizer_storage_gles3.cpp


+ 14 - 462
drivers/gles3/rasterizer_storage_gles3.h

@@ -40,6 +40,10 @@
 #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/render_target_storage.h"
+#include "storage/texture_storage.h"
 
 #include "shaders/copy.glsl.gen.h"
 
@@ -47,66 +51,13 @@ class RasterizerCanvasGLES3;
 class RasterizerSceneGLES3;
 
 class RasterizerStorageGLES3 : public RendererStorage {
-	friend class RasterizerGLES3;
-
-	Thread::ID _main_thread_id = 0;
-	bool _is_main_thread();
-
 public:
 	RasterizerCanvasGLES3 *canvas;
 	RasterizerSceneGLES3 *scene;
 
 	static GLuint system_fbo;
 
-	struct Config {
-		bool shrink_textures_x2;
-		bool use_fast_texture_filter;
-		bool use_skeleton_software;
-
-		int max_vertex_texture_image_units;
-		int max_texture_image_units;
-		int max_texture_size;
-
-		// TODO implement wireframe in OpenGL
-		// bool generate_wireframes;
-
-		Set<String> extensions;
-
-		bool float_texture_supported;
-		bool s3tc_supported;
-		bool latc_supported;
-		bool rgtc_supported;
-		bool bptc_supported;
-		bool etc_supported;
-		bool etc2_supported;
-		bool srgb_decode_supported;
-
-		bool keep_original_textures;
-
-		bool force_vertex_shading;
-
-		bool use_rgba_2d_shadows;
-		bool use_rgba_3d_shadows;
-
-		bool support_32_bits_indices;
-		bool support_write_depth;
-		bool support_half_float_vertices;
-		bool support_npot_repeat_mipmap;
-		bool support_depth_texture;
-		bool support_depth_cubemaps;
-
-		bool support_shadow_cubemaps;
-
-		bool render_to_mipmap_supported;
-
-		GLuint depth_internalformat;
-		GLuint depth_type;
-		GLuint depth_buffer_internalformat;
-
-		// in some cases the legacy render didn't orphan. We will mark these
-		// so the user can switch orphaning off for them.
-		bool should_orphan;
-	} config;
+	GLES3::Config *config;
 
 	struct Resources {
 		GLuint white_tex;
@@ -180,334 +131,7 @@ public:
 	//////////////////////////////////API////////////////////////////////////////////////////
 	/////////////////////////////////////////////////////////////////////////////////////////
 
-	bool can_create_resources_async() const override;
-
-	// TEXTURE API
-
-	enum OpenGLTextureFlags {
-		TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available
-		TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping
-		TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter
-		TEXTURE_FLAG_ANISOTROPIC_FILTER = 8,
-		TEXTURE_FLAG_CONVERT_TO_LINEAR = 16,
-		TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored
-		TEXTURE_FLAG_USED_FOR_STREAMING = 2048,
-		TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER
-	};
-
-	/* CANVAS TEXTURE API (2D) */
-
-	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;
-	};
-
-	RID_Owner<CanvasTexture, true> canvas_texture_owner;
-
-	struct RenderTarget;
-
-	struct Texture {
-		RID self;
-
-		Texture *proxy;
-		Set<Texture *> proxy_owners;
-
-		String path;
-		uint32_t flags;
-		int width, height, depth;
-		int alloc_width, alloc_height;
-		Image::Format format;
-		RenderingDevice::TextureType type;
-
-		GLenum target;
-		GLenum gl_format_cache;
-		GLenum gl_internal_format_cache;
-		GLenum gl_type_cache;
-
-		int data_size;
-		int total_data_size;
-		bool ignore_mipmaps;
-
-		bool compressed;
-
-		bool srgb;
-
-		int mipmaps;
-
-		bool resize_to_po2;
-
-		bool active;
-		GLenum tex_id;
-
-		uint16_t stored_cube_sides;
-
-		RenderTarget *render_target;
-
-		Vector<Ref<Image>> images;
-
-		bool redraw_if_visible;
-
-		RS::TextureDetectCallback detect_3d;
-		void *detect_3d_ud;
-
-		RS::TextureDetectCallback detect_srgb;
-		void *detect_srgb_ud;
-
-		RS::TextureDetectCallback detect_normal;
-		void *detect_normal_ud;
-
-		CanvasTexture *canvas_texture = nullptr;
-
-		// some silly opengl shenanigans where
-		// texture coords start from bottom left, means we need to draw render target textures upside down
-		// to be compatible with vulkan etc.
-		bool is_upside_down() const {
-			if (proxy) {
-				return proxy->is_upside_down();
-			}
-
-			return render_target != nullptr;
-		}
-
-		Texture() {
-			create();
-		}
-
-		_ALWAYS_INLINE_ Texture *get_ptr() {
-			if (proxy) {
-				return proxy; //->get_ptr(); only one level of indirection, else not inlining possible.
-			} else {
-				return this;
-			}
-		}
-
-		~Texture() {
-			destroy();
-
-			if (tex_id != 0) {
-				glDeleteTextures(1, &tex_id);
-			}
-		}
-
-		void copy_from(const Texture &o) {
-			proxy = o.proxy;
-			flags = o.flags;
-			width = o.width;
-			height = o.height;
-			alloc_width = o.alloc_width;
-			alloc_height = o.alloc_height;
-			format = o.format;
-			type = o.type;
-			target = o.target;
-			data_size = o.data_size;
-			total_data_size = o.total_data_size;
-			ignore_mipmaps = o.ignore_mipmaps;
-			compressed = o.compressed;
-			mipmaps = o.mipmaps;
-			resize_to_po2 = o.resize_to_po2;
-			active = o.active;
-			tex_id = o.tex_id;
-			stored_cube_sides = o.stored_cube_sides;
-			render_target = o.render_target;
-			redraw_if_visible = o.redraw_if_visible;
-			detect_3d = o.detect_3d;
-			detect_3d_ud = o.detect_3d_ud;
-			detect_srgb = o.detect_srgb;
-			detect_srgb_ud = o.detect_srgb_ud;
-			detect_normal = o.detect_normal;
-			detect_normal_ud = o.detect_normal_ud;
-
-			images.clear();
-		}
-
-		void create() {
-			proxy = nullptr;
-			flags = 0;
-			width = 0;
-			height = 0;
-			alloc_width = 0;
-			alloc_height = 0;
-			format = Image::FORMAT_L8;
-			type = RenderingDevice::TEXTURE_TYPE_2D;
-			target = 0;
-			data_size = 0;
-			total_data_size = 0;
-			ignore_mipmaps = false;
-			compressed = false;
-			mipmaps = 0;
-			resize_to_po2 = false;
-			active = false;
-			tex_id = 0;
-			stored_cube_sides = 0;
-			render_target = nullptr;
-			redraw_if_visible = false;
-			detect_3d = nullptr;
-			detect_3d_ud = nullptr;
-			detect_srgb = nullptr;
-			detect_srgb_ud = nullptr;
-			detect_normal = nullptr;
-			detect_normal_ud = nullptr;
-		}
-		void destroy() {
-			images.clear();
-
-			for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) {
-				E->get()->proxy = nullptr;
-			}
-
-			if (proxy) {
-				proxy->proxy_owners.erase(this);
-			}
-		}
-
-		// texture state
-		void GLSetFilter(GLenum p_target, RS::CanvasItemTextureFilter p_filter) {
-			if (p_filter == state_filter) {
-				return;
-			}
-			state_filter = p_filter;
-			GLint pmin = GL_LINEAR; // param min
-			GLint pmag = GL_LINEAR; // param mag
-			switch (state_filter) {
-				default: {
-				} break;
-				case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
-					pmin = GL_LINEAR_MIPMAP_LINEAR;
-					pmag = GL_LINEAR;
-				} break;
-				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
-					pmin = GL_NEAREST;
-					pmag = GL_NEAREST;
-				} break;
-				case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
-					pmin = GL_NEAREST_MIPMAP_NEAREST;
-					pmag = GL_NEAREST;
-				} break;
-			}
-			glTexParameteri(p_target, GL_TEXTURE_MIN_FILTER, pmin);
-			glTexParameteri(p_target, GL_TEXTURE_MAG_FILTER, pmag);
-		}
-		void GLSetRepeat(GLenum p_target, RS::CanvasItemTextureRepeat p_repeat) {
-			if (p_repeat == state_repeat) {
-				return;
-			}
-			state_repeat = p_repeat;
-			GLint prep = GL_CLAMP_TO_EDGE; // parameter repeat
-			switch (state_repeat) {
-				default: {
-				} break;
-				case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
-					prep = GL_REPEAT;
-				} break;
-				case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
-					prep = GL_MIRRORED_REPEAT;
-				} break;
-			}
-			glTexParameteri(p_target, GL_TEXTURE_WRAP_S, prep);
-			glTexParameteri(p_target, GL_TEXTURE_WRAP_T, prep);
-		}
-
-	private:
-		RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
-		RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
-	};
-
-	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;
-
-	void _texture_set_state_from_flags(Texture *p_tex);
-
-	// new
-	RID texture_allocate() override;
-	void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
-	void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
-	void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
-	void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
-
-	void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
-	void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {}
-	void texture_proxy_update(RID p_proxy, RID p_base) override {}
-
-	void texture_2d_placeholder_initialize(RID p_texture) override;
-	void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
-	void texture_3d_placeholder_initialize(RID p_texture) override;
-
-	Ref<Image> texture_2d_get(RID p_texture) const override;
-	Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
-	Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
-
-	void texture_replace(RID p_texture, RID p_by_texture) override;
-	//void texture_set_size_override(RID p_texture, int p_width, int p_height) 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 {}
-
-	// old
-	uint32_t texture_get_width(RID p_texture) const;
-	uint32_t texture_get_height(RID p_texture) const;
-
-private:
-	RID texture_create();
-
-	//void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT);
-	void _texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT);
-
-	void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
-	void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0);
-	//Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const;
-	void texture_set_flags(RID p_texture, uint32_t p_flags);
-	uint32_t texture_get_flags(RID p_texture) const;
-	Image::Format texture_get_format(RID p_texture) const;
-	RenderingDevice::TextureType texture_get_type(RID p_texture) const;
-	uint32_t texture_get_texid(RID p_texture) const;
-	uint32_t texture_get_depth(RID p_texture) const;
-	void texture_set_size_override(RID p_texture, int p_width, int p_height) override;
-
-	void texture_bind(RID p_texture, uint32_t p_texture_no);
-
-	void texture_set_path(RID p_texture, const String &p_path) override;
-	String texture_get_path(RID p_texture) const override;
-
-	void texture_set_shrink_all_x2_on_set_data(bool p_enable);
-
-	void texture_debug_usage(List<RS::TextureInfo> *r_info) override;
-
-	RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const;
-
-	void textures_keep_original(bool p_enable);
-
-	void texture_set_proxy(RID p_texture, RID p_proxy);
-	Size2 texture_size_with_proxy(RID p_texture) override;
-
-	void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
-	void texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata);
-	void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
-	void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {}
-
-	void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override;
-
 public:
-	RID canvas_texture_allocate() override;
-	void canvas_texture_initialize(RID p_rid) override;
-
-	void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
-	void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) override;
-
-	void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) override;
-	void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) override;
-
 	/* SKY API */
 	// not sure if used in godot 4?
 	struct Sky {
@@ -971,6 +595,9 @@ public:
 
 	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;
@@ -1151,85 +778,10 @@ public:
 
 	// RENDER TARGET
 
-	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[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 < RENDER_TARGET_FLAG_MAX; ++i) {
-				flags[i] = false;
-			}
-			external.fbo = 0;
-		}
-	};
-
-	mutable RID_PtrOwner<RenderTarget> render_target_owner;
+	mutable RID_PtrOwner<GLES3::RenderTarget> render_target_owner;
 
-	void _render_target_clear(RenderTarget *rt);
-	void _render_target_allocate(RenderTarget *rt);
+	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;
@@ -1262,7 +814,7 @@ public:
 	void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
 
 	// access from canvas
-	//	RenderTarget * render_target_get(RID p_render_target);
+	//	GLES3::RenderTarget * render_target_get(RID p_render_target);
 
 	/* CANVAS SHADOW */
 
@@ -1301,7 +853,7 @@ public:
 	bool free(RID p_rid) override;
 
 	struct Frame {
-		RenderTarget *current_rt;
+		GLES3::RenderTarget *current_rt;
 
 		// these 2 may have been superseded by the equivalents in the render target.
 		// these may be able to be removed.
@@ -1408,7 +960,7 @@ inline bool RasterizerStorageGLES3::safe_buffer_sub_data(unsigned int p_total_bu
 inline void RasterizerStorageGLES3::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, GLenum p_usage, bool p_optional_orphan) const {
 	// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
 	// Was previously #ifndef GLES_OVER_GL however this causes stalls on desktop mac also (and possibly other)
-	if (!p_optional_orphan || (config.should_orphan)) {
+	if (!p_optional_orphan || (config->should_orphan)) {
 		glBufferData(p_target, p_buffer_size, nullptr, p_usage);
 #ifdef RASTERIZER_EXTRA_CHECKS
 		// fill with garbage off the end of the array

+ 5 - 0
drivers/gles3/storage/SCsub

@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.drivers_sources, "*.cpp")

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

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

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

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

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

@@ -0,0 +1,156 @@
+/*************************************************************************/
+/*  config.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 "config.h"
+#include "core/templates/vector.h"
+
+using namespace GLES3;
+
+Config *Config::singleton = nullptr;
+
+Config::Config() {
+	singleton = this;
+	should_orphan = true;
+}
+
+Config::~Config() {
+	singleton = nullptr;
+}
+
+void Config::initialize() {
+	{
+		const GLubyte *extension_string = glGetString(GL_EXTENSIONS);
+
+		Vector<String> exts = String((const char *)extension_string).split(" ");
+
+		for (int i = 0; i < exts.size(); i++) {
+			extensions.insert(exts[i]);
+		}
+	}
+
+	keep_original_textures = true; // false
+	shrink_textures_x2 = false;
+	depth_internalformat = GL_DEPTH_COMPONENT;
+	depth_type = GL_UNSIGNED_INT;
+
+#ifdef GLES_OVER_GL
+	float_texture_supported = true;
+	s3tc_supported = true;
+	etc_supported = false;
+	support_npot_repeat_mipmap = true;
+	depth_buffer_internalformat = GL_DEPTH_COMPONENT24;
+#else
+	float_texture_supported = extensions.has("GL_ARB_texture_float") || extensions.has("GL_OES_texture_float");
+	s3tc_supported = extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc");
+	etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || extensions.has("WEBGL_compressed_texture_etc1");
+	support_npot_repeat_mipmap = extensions.has("GL_OES_texture_npot");
+
+#ifdef JAVASCRIPT_ENABLED
+	// RenderBuffer internal format must be 16 bits in WebGL,
+	// but depth_texture should default to 32 always
+	// if the implementation doesn't support 32, it should just quietly use 16 instead
+	// https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/
+	depth_buffer_internalformat = GL_DEPTH_COMPONENT16;
+	depth_type = GL_UNSIGNED_INT;
+#else
+	// on mobile check for 24 bit depth support for RenderBufferStorage
+	if (extensions.has("GL_OES_depth24")) {
+		depth_buffer_internalformat = _DEPTH_COMPONENT24_OES;
+		depth_type = GL_UNSIGNED_INT;
+	} else {
+		depth_buffer_internalformat = GL_DEPTH_COMPONENT16;
+		depth_type = GL_UNSIGNED_SHORT;
+	}
+#endif
+#endif
+
+#ifdef GLES_OVER_GL
+	//TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps
+	render_to_mipmap_supported = false;
+#else
+	//check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms
+	render_to_mipmap_supported = extensions.has("GL_OES_fbo_render_mipmap") && extensions.has("GL_EXT_texture_lod");
+#endif
+
+#ifdef GLES_OVER_GL
+	use_rgba_2d_shadows = false;
+	support_depth_texture = true;
+	use_rgba_3d_shadows = false;
+	support_depth_cubemaps = true;
+#else
+	use_rgba_2d_shadows = !(float_texture_supported && extensions.has("GL_EXT_texture_rg"));
+	support_depth_texture = extensions.has("GL_OES_depth_texture") || extensions.has("WEBGL_depth_texture");
+	use_rgba_3d_shadows = !support_depth_texture;
+	support_depth_cubemaps = extensions.has("GL_OES_depth_texture_cube_map");
+#endif
+
+#ifdef GLES_OVER_GL
+	support_32_bits_indices = true;
+#else
+	support_32_bits_indices = extensions.has("GL_OES_element_index_uint");
+#endif
+
+#ifdef GLES_OVER_GL
+	support_write_depth = true;
+#elif defined(JAVASCRIPT_ENABLED)
+	support_write_depth = false;
+#else
+	support_write_depth = extensions.has("GL_EXT_frag_depth");
+#endif
+
+	support_half_float_vertices = true;
+//every platform should support this except web, iOS has issues with their support, so add option to disable
+#ifdef JAVASCRIPT_ENABLED
+	support_half_float_vertices = false;
+#endif
+	bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float");
+	if (disable_half_float) {
+		support_half_float_vertices = false;
+	}
+
+	etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
+	latc_supported = extensions.has("GL_EXT_texture_compression_latc");
+	bptc_supported = extensions.has("GL_ARB_texture_compression_bptc");
+	rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc");
+	bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc");
+	srgb_decode_supported = extensions.has("GL_EXT_texture_sRGB_decode");
+
+	glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);
+	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_image_units);
+	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
+
+	force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
+	use_fast_texture_filter = false; //GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter");
+	// should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers");
+}
+
+#endif // GLES3_ENABLED

+ 113 - 0
drivers/gles3/storage/config.h

@@ -0,0 +1,113 @@
+/*************************************************************************/
+/*  config.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 CONFIG_GLES3_H
+#define CONFIG_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/string/ustring.h"
+#include "core/templates/set.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 {
+
+class Config {
+private:
+	static Config *singleton;
+
+public:
+	bool shrink_textures_x2;
+	bool use_fast_texture_filter;
+	bool use_skeleton_software;
+
+	int max_vertex_texture_image_units;
+	int max_texture_image_units;
+	int max_texture_size;
+
+	// TODO implement wireframe in OpenGL
+	// bool generate_wireframes;
+
+	Set<String> extensions;
+
+	bool float_texture_supported;
+	bool s3tc_supported;
+	bool latc_supported;
+	bool rgtc_supported;
+	bool bptc_supported;
+	bool etc_supported;
+	bool etc2_supported;
+	bool srgb_decode_supported;
+
+	bool keep_original_textures;
+
+	bool force_vertex_shading;
+
+	bool use_rgba_2d_shadows;
+	bool use_rgba_3d_shadows;
+
+	bool support_32_bits_indices;
+	bool support_write_depth;
+	bool support_half_float_vertices;
+	bool support_npot_repeat_mipmap;
+	bool support_depth_texture;
+	bool support_depth_cubemaps;
+
+	bool support_shadow_cubemaps;
+
+	bool render_to_mipmap_supported;
+
+	GLuint depth_internalformat;
+	GLuint depth_type;
+	GLuint depth_buffer_internalformat;
+
+	// in some cases the legacy render didn't orphan. We will mark these
+	// so the user can switch orphaning off for them.
+	bool should_orphan = true;
+
+	static Config *get_singleton() { return singleton; };
+
+	Config();
+	~Config();
+	void initialize();
+};
+
+} // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // !CONFIG_GLES3_H

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

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

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

@@ -0,0 +1,1211 @@
+/*************************************************************************/
+/*  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 "texture_storage.h"
+#include "config.h"
+
+using namespace GLES3;
+
+TextureStorage *TextureStorage::singleton = nullptr;
+
+TextureStorage *TextureStorage::get_singleton() {
+	return singleton;
+}
+
+TextureStorage::TextureStorage() {
+	singleton = this;
+}
+
+TextureStorage::~TextureStorage() {
+	singleton = nullptr;
+}
+
+void TextureStorage::set_main_thread_id(Thread::ID p_id) {
+	_main_thread_id = p_id;
+}
+
+bool TextureStorage::_is_main_thread() {
+	//#if defined DEBUG_ENABLED && defined TOOLS_ENABLED
+	// must be called from main thread in OpenGL
+	bool is_main_thread = _main_thread_id == Thread::get_caller_id();
+	//#endif
+	return is_main_thread;
+}
+
+bool TextureStorage::can_create_resources_async() const {
+	return false;
+}
+
+static const GLenum _cube_side_enum[6] = {
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+	GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+	GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
+	GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+};
+
+Ref<Image> TextureStorage::_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 {
+	Config *config = Config::get_singleton();
+	r_gl_format = 0;
+	Ref<Image> image = p_image;
+	r_compressed = false;
+	r_real_format = p_format;
+
+	bool need_decompress = false;
+
+	switch (p_format) {
+		case Image::FORMAT_L8: {
+#ifdef GLES_OVER_GL
+			r_gl_internal_format = GL_R8;
+			r_gl_format = GL_RED;
+			r_gl_type = GL_UNSIGNED_BYTE;
+#else
+			r_gl_internal_format = GL_LUMINANCE;
+			r_gl_format = GL_LUMINANCE;
+			r_gl_type = GL_UNSIGNED_BYTE;
+#endif
+		} break;
+		case Image::FORMAT_LA8: {
+#ifdef GLES_OVER_GL
+			r_gl_internal_format = GL_RG8;
+			r_gl_format = GL_RG;
+			r_gl_type = GL_UNSIGNED_BYTE;
+#else
+			r_gl_internal_format = GL_LUMINANCE_ALPHA;
+			r_gl_format = GL_LUMINANCE_ALPHA;
+			r_gl_type = GL_UNSIGNED_BYTE;
+#endif
+		} break;
+		case Image::FORMAT_R8: {
+			r_gl_internal_format = GL_R8;
+			r_gl_format = GL_RED;
+			r_gl_type = GL_UNSIGNED_BYTE;
+
+		} break;
+		case Image::FORMAT_RG8: {
+			r_gl_internal_format = GL_RG8;
+			r_gl_format = GL_RG;
+			r_gl_type = GL_UNSIGNED_BYTE;
+
+		} break;
+		case Image::FORMAT_RGB8: {
+			r_gl_internal_format = GL_RGB8;
+			r_gl_format = GL_RGB;
+			r_gl_type = GL_UNSIGNED_BYTE;
+			//r_srgb = true;
+
+		} break;
+		case Image::FORMAT_RGBA8: {
+			r_gl_format = GL_RGBA;
+			r_gl_internal_format = GL_RGBA8;
+			r_gl_type = GL_UNSIGNED_BYTE;
+			//r_srgb = true;
+
+		} break;
+		case Image::FORMAT_RGBA4444: {
+			r_gl_internal_format = GL_RGBA4;
+			r_gl_format = GL_RGBA;
+			r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4;
+
+		} break;
+			//case Image::FORMAT_RGBA5551: {
+			//	r_gl_internal_format = GL_RGB5_A1;
+			//	r_gl_format = GL_RGBA;
+			//	r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1;
+			//
+			//} break;
+		case Image::FORMAT_RF: {
+			r_gl_internal_format = GL_R32F;
+			r_gl_format = GL_RED;
+			r_gl_type = GL_FLOAT;
+
+		} break;
+		case Image::FORMAT_RGF: {
+			r_gl_internal_format = GL_RG32F;
+			r_gl_format = GL_RG;
+			r_gl_type = GL_FLOAT;
+
+		} break;
+		case Image::FORMAT_RGBF: {
+			r_gl_internal_format = GL_RGB32F;
+			r_gl_format = GL_RGB;
+			r_gl_type = GL_FLOAT;
+
+		} break;
+		case Image::FORMAT_RGBAF: {
+			r_gl_internal_format = GL_RGBA32F;
+			r_gl_format = GL_RGBA;
+			r_gl_type = GL_FLOAT;
+
+		} break;
+		case Image::FORMAT_RH: {
+			r_gl_internal_format = GL_R16F;
+			r_gl_format = GL_RED;
+			r_gl_type = GL_HALF_FLOAT;
+		} break;
+		case Image::FORMAT_RGH: {
+			r_gl_internal_format = GL_RG16F;
+			r_gl_format = GL_RG;
+			r_gl_type = GL_HALF_FLOAT;
+
+		} break;
+		case Image::FORMAT_RGBH: {
+			r_gl_internal_format = GL_RGB16F;
+			r_gl_format = GL_RGB;
+			r_gl_type = GL_HALF_FLOAT;
+
+		} break;
+		case Image::FORMAT_RGBAH: {
+			r_gl_internal_format = GL_RGBA16F;
+			r_gl_format = GL_RGBA;
+			r_gl_type = GL_HALF_FLOAT;
+
+		} break;
+		case Image::FORMAT_RGBE9995: {
+			r_gl_internal_format = GL_RGB9_E5;
+			r_gl_format = GL_RGB;
+			r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV;
+
+		} break;
+		case Image::FORMAT_DXT1: {
+			if (config->s3tc_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+				r_gl_format = GL_RGBA;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+				//r_srgb = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_DXT3: {
+			if (config->s3tc_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+				r_gl_format = GL_RGBA;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+				//r_srgb = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_DXT5: {
+			if (config->s3tc_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+				r_gl_format = GL_RGBA;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+				//r_srgb = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_RGTC_R: {
+			if (config->rgtc_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT;
+				r_gl_format = GL_RGBA;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_RGTC_RG: {
+			if (config->rgtc_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT;
+				r_gl_format = GL_RGBA;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_BPTC_RGBA: {
+			if (config->bptc_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RGBA_BPTC_UNORM;
+				r_gl_format = GL_RGBA;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+				//r_srgb = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_BPTC_RGBF: {
+			if (config->bptc_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
+				r_gl_format = GL_RGB;
+				r_gl_type = GL_FLOAT;
+				r_compressed = true;
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_BPTC_RGBFU: {
+			if (config->bptc_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
+				r_gl_format = GL_RGB;
+				r_gl_type = GL_FLOAT;
+				r_compressed = true;
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_ETC: {
+			if (config->etc_supported) {
+				r_gl_internal_format = _EXT_ETC1_RGB8_OES;
+				r_gl_format = GL_RGBA;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+
+			} else {
+				need_decompress = true;
+			}
+
+		} break;
+		/*
+		case Image::FORMAT_ETC2_R11: {
+			if (config->etc2_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_R11_EAC;
+				r_gl_format = GL_RED;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_ETC2_R11S: {
+			if (config->etc2_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC;
+				r_gl_format = GL_RED;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_ETC2_RG11: {
+			if (config->etc2_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC;
+				r_gl_format = GL_RG;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_ETC2_RG11S: {
+			if (config->etc2_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC;
+				r_gl_format = GL_RG;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_ETC2_RGB8: {
+			if (config->etc2_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RGB8_ETC2;
+				r_gl_format = GL_RGB;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+				//r_srgb = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_ETC2_RGBA8: {
+			if (config->etc2_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RGBA8_ETC2_EAC;
+				r_gl_format = GL_RGBA;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+				//r_srgb = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		case Image::FORMAT_ETC2_RGB8A1: {
+			if (config->etc2_supported) {
+				r_gl_internal_format = _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
+				r_gl_format = GL_RGBA;
+				r_gl_type = GL_UNSIGNED_BYTE;
+				r_compressed = true;
+				//r_srgb = true;
+
+			} else {
+				need_decompress = true;
+			}
+		} break;
+		*/
+		default: {
+			ERR_FAIL_V(Ref<Image>());
+		}
+	}
+
+	if (need_decompress || p_force_decompress) {
+		if (!image.is_null()) {
+			image = image->duplicate();
+			image->decompress();
+			ERR_FAIL_COND_V(image->is_compressed(), image);
+			switch (image->get_format()) {
+				case Image::FORMAT_RGB8: {
+					r_gl_format = GL_RGB;
+					r_gl_internal_format = GL_RGB;
+					r_gl_type = GL_UNSIGNED_BYTE;
+					r_real_format = Image::FORMAT_RGB8;
+					r_compressed = false;
+				} break;
+				case Image::FORMAT_RGBA8: {
+					r_gl_format = GL_RGBA;
+					r_gl_internal_format = GL_RGBA;
+					r_gl_type = GL_UNSIGNED_BYTE;
+					r_real_format = Image::FORMAT_RGBA8;
+					r_compressed = false;
+				} break;
+				default: {
+					image->convert(Image::FORMAT_RGBA8);
+					r_gl_format = GL_RGBA;
+					r_gl_internal_format = GL_RGBA;
+					r_gl_type = GL_UNSIGNED_BYTE;
+					r_real_format = Image::FORMAT_RGBA8;
+					r_compressed = false;
+
+				} break;
+			}
+		}
+
+		return image;
+	}
+
+	return p_image;
+}
+
+void TextureStorage::_texture_set_state_from_flags(Texture *p_tex) {
+	// Config *config = Config::get_singleton();
+
+	if ((p_tex->flags & TEXTURE_FLAG_MIPMAPS) && !p_tex->ignore_mipmaps) {
+		if (p_tex->flags & TEXTURE_FLAG_FILTER) {
+			// these do not exactly correspond ...
+			p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS);
+			//texture->glTexParam_MinFilter(texture->target, config->use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR);
+		} else {
+			p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
+			//texture->glTexParam_MinFilter(texture->target, config->use_fast_texture_filter ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR);
+		}
+	} else {
+		if (p_tex->flags & TEXTURE_FLAG_FILTER) {
+			p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
+			//texture->glTexParam_MinFilter(texture->target, GL_LINEAR);
+		} else {
+			p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
+			//texture->glTexParam_MinFilter(texture->target, GL_NEAREST);
+		}
+	}
+
+	if (((p_tex->flags & TEXTURE_FLAG_REPEAT) || (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT)) && p_tex->target != GL_TEXTURE_CUBE_MAP) {
+		if (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT) {
+			p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
+		} else {
+			p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+		}
+	} else {
+		p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+	}
+}
+
+void TextureStorage::_texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags) {
+	//	GLenum format;
+	//	GLenum internal_format;
+	//	GLenum type;
+
+	//	bool compressed = false;
+
+	// Config *config = Config::get_singleton();
+
+	if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
+		p_flags &= ~TEXTURE_FLAG_MIPMAPS; // no mipies for video
+	}
+
+	Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!texture);
+	texture->width = p_width;
+	texture->height = p_height;
+	texture->format = p_format;
+	texture->flags = p_flags;
+	texture->stored_cube_sides = 0;
+	texture->type = p_type;
+
+	switch (p_type) {
+		case RenderingDevice::TEXTURE_TYPE_2D: {
+			texture->target = GL_TEXTURE_2D;
+			texture->images.resize(1);
+		} break;
+			//		case RenderingDevice::TEXTURE_TYPE_EXTERNAL: {
+			//#ifdef ANDROID_ENABLED
+			//			texture->target = _GL_TEXTURE_EXTERNAL_OES;
+			//#else
+			//			texture->target = GL_TEXTURE_2D;
+			//#endif
+			//			texture->images.resize(0);
+			//		} break;
+		case RenderingDevice::TEXTURE_TYPE_CUBE: {
+			texture->target = GL_TEXTURE_CUBE_MAP;
+			texture->images.resize(6);
+		} break;
+		case RenderingDevice::TEXTURE_TYPE_2D_ARRAY:
+		case RenderingDevice::TEXTURE_TYPE_3D: {
+			texture->target = GL_TEXTURE_3D;
+			ERR_PRINT("3D textures and Texture Arrays are not supported in OpenGL. Please switch to the Vulkan backend.");
+			return;
+		} break;
+		default: {
+			ERR_PRINT("Unknown texture type!");
+			return;
+		}
+	}
+
+#if 0
+	//		if (p_type != RS::TEXTURE_TYPE_EXTERNAL) {
+	if (p_type == RenderingDevice::TEXTURE_TYPE_2D) {
+		texture->alloc_width = texture->width;
+		texture->alloc_height = texture->height;
+		texture->resize_to_po2 = false;
+		if (!config->support_npot_repeat_mipmap) {
+			int po2_width = next_power_of_2(p_width);
+			int po2_height = next_power_of_2(p_height);
+
+			bool is_po2 = p_width == po2_width && p_height == po2_height;
+
+			if (!is_po2 && (p_flags & TEXTURE_FLAG_REPEAT || p_flags & TEXTURE_FLAG_MIPMAPS)) {
+				if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
+					//not supported
+					ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled.");
+					texture->flags &= ~(TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS);
+				} else {
+					texture->alloc_height = po2_height;
+					texture->alloc_width = po2_width;
+					texture->resize_to_po2 = true;
+				}
+			}
+		}
+
+		GLenum format;
+		GLenum internal_format;
+		GLenum type;
+		bool compressed = false;
+
+		Image::Format real_format;
+		_get_gl_image_and_format(Ref<Image>(),
+				texture->format,
+				texture->flags,
+				real_format,
+				format,
+				internal_format,
+				type,
+				compressed,
+				texture->resize_to_po2);
+
+		texture->gl_format_cache = format;
+		texture->gl_type_cache = type;
+		texture->gl_internal_format_cache = internal_format;
+		texture->data_size = 0;
+		texture->mipmaps = 1;
+
+		texture->compressed = compressed;
+	}
+#endif
+
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(texture->target, texture->tex_id);
+
+	//	if (p_type == RS::TEXTURE_TYPE_EXTERNAL) {
+	//		glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	//		glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	//		glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	//		glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	//	} else if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
+	//		//prealloc if video
+	//		glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL);
+	//	}
+
+	texture->active = true;
+}
+
+RID TextureStorage::texture_create() {
+	ERR_FAIL_COND_V(!_is_main_thread(), RID());
+
+	Texture *texture = memnew(Texture);
+	ERR_FAIL_COND_V(!texture, RID());
+	glGenTextures(1, &texture->tex_id);
+	texture->active = false;
+	texture->total_data_size = 0;
+
+	return texture_owner.make_rid(texture);
+}
+
+RID TextureStorage::texture_allocate() {
+	RID id = texture_create();
+	ERR_FAIL_COND_V(id == RID(), id);
+	return id;
+}
+
+void TextureStorage::texture_free(RID p_rid) {
+	Texture *t = texture_owner.get_or_null(p_rid);
+
+	// can't free a render target texture
+	ERR_FAIL_COND(t->render_target);
+	if (t->canvas_texture) {
+		memdelete(t->canvas_texture);
+	}
+
+	// info.texture_mem -= t->total_data_size; // TODO make this work again!!
+	texture_owner.free(p_rid);
+	memdelete(t);
+}
+
+void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+
+	int w = p_image->get_width();
+	int h = p_image->get_height();
+
+	_texture_allocate_internal(p_texture, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0);
+	texture_set_data(p_texture, p_image);
+}
+
+void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
+}
+
+void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
+}
+
+void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
+	texture_set_proxy(p_texture, p_base);
+}
+
+//RID TextureStorage::texture_2d_create(const Ref<Image> &p_image) {
+//	RID id = texture_create();
+//	ERR_FAIL_COND_V(id == RID(), id);
+
+//	int w = p_image->get_width();
+//	int h = p_image->get_height();
+
+//	texture_allocate(id, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0);
+
+//	texture_set_data(id, p_image);
+
+//	return id;
+//}
+
+//RID TextureStorage::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
+//	return RID();
+//}
+
+//void TextureStorage::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) {
+//	// only 1 layer so far
+//	texture_set_data(p_texture, p_image);
+//}
+
+void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) {
+	// only 1 layer so far
+	texture_set_data(p_texture, p_image);
+}
+
+void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
+}
+
+void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) {
+}
+
+void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
+}
+
+Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND_V(!tex, Ref<Image>());
+
+	/*
+#ifdef TOOLS_ENABLED
+	if (tex->image_cache_2d.is_valid()) {
+		return tex->image_cache_2d;
+	}
+#endif
+	Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
+	ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
+	Ref<Image> image;
+	image.instance();
+	image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+	ERR_FAIL_COND_V(image->empty(), Ref<Image>());
+	if (tex->format != tex->validated_format) {
+		image->convert(tex->format);
+	}
+
+#ifdef TOOLS_ENABLED
+	if (Engine::get_singleton()->is_editor_hint()) {
+		tex->image_cache_2d = image;
+	}
+#endif
+*/
+	ERR_FAIL_COND_V(!tex->images.size(), Ref<Image>());
+
+	return tex->images[0];
+
+	//	return image;
+
+	//	return Ref<Image>();
+}
+
+void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
+	Texture *tex_to = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex_to);
+	Texture *tex_from = texture_owner.get_or_null(p_by_texture);
+	ERR_FAIL_COND(!tex_from);
+
+	tex_to->destroy();
+	tex_to->copy_from(*tex_from);
+
+	// copy image data and upload to GL
+	tex_to->images.resize(tex_from->images.size());
+
+	for (int n = 0; n < tex_from->images.size(); n++) {
+		texture_set_data(p_texture, tex_from->images[n], n);
+	}
+
+	texture_free(p_by_texture);
+}
+
+void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND(!texture);
+	ERR_FAIL_COND(texture->render_target);
+
+	ERR_FAIL_COND(p_width <= 0 || p_width > 16384);
+	ERR_FAIL_COND(p_height <= 0 || p_height > 16384);
+	//real texture size is in alloc width and height
+	texture->width = p_width;
+	texture->height = p_height;
+}
+
+void TextureStorage::texture_set_path(RID p_texture, const String &p_path) {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!texture);
+
+	texture->path = p_path;
+}
+
+String TextureStorage::texture_get_path(RID p_texture) const {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND_V(!texture, "");
+
+	return texture->path;
+}
+
+void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!texture);
+
+	texture->detect_3d = p_callback;
+	texture->detect_3d_ud = p_userdata;
+}
+
+void TextureStorage::texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!texture);
+
+	texture->detect_srgb = p_callback;
+	texture->detect_srgb_ud = p_userdata;
+}
+
+void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!texture);
+
+	texture->detect_normal = p_callback;
+	texture->detect_normal_ud = p_userdata;
+}
+
+void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
+	List<RID> textures;
+	texture_owner.get_owned_list(&textures);
+
+	for (List<RID>::Element *E = textures.front(); E; E = E->next()) {
+		Texture *t = texture_owner.get_or_null(E->get());
+		if (!t) {
+			continue;
+		}
+		RS::TextureInfo tinfo;
+		tinfo.path = t->path;
+		tinfo.format = t->format;
+		tinfo.width = t->alloc_width;
+		tinfo.height = t->alloc_height;
+		tinfo.depth = 0;
+		tinfo.bytes = t->total_data_size;
+		r_info->push_back(tinfo);
+	}
+}
+
+void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!texture);
+
+	texture->redraw_if_visible = p_enable;
+}
+
+Size2 TextureStorage::texture_size_with_proxy(RID p_texture) {
+	const Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND_V(!texture, Size2());
+	if (texture->proxy) {
+		return Size2(texture->proxy->width, texture->proxy->height);
+	} else {
+		return Size2(texture->width, texture->height);
+	}
+}
+
+// example use in 3.2
+// VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid);
+
+// p_proxy is the source (pre-existing) texture?
+// and p_texture is the one that is being made into a proxy?
+//This naming is confusing. Comments!!!
+
+// The naming of the parameters seemed to be reversed?
+// The p_proxy is the source texture
+// and p_texture is actually the proxy????
+
+void TextureStorage::texture_set_proxy(RID p_texture, RID p_proxy) {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!texture);
+
+	if (texture->proxy) {
+		texture->proxy->proxy_owners.erase(texture);
+		texture->proxy = nullptr;
+	}
+
+	if (p_proxy.is_valid()) {
+		Texture *proxy = texture_owner.get_or_null(p_proxy);
+		ERR_FAIL_COND(!proxy);
+		ERR_FAIL_COND(proxy == texture);
+		proxy->proxy_owners.insert(texture);
+		texture->proxy = proxy;
+	}
+}
+
+void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) {
+	Config *config = Config::get_singleton();
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND(!_is_main_thread());
+
+	ERR_FAIL_COND(!texture);
+	if (texture->target == GL_TEXTURE_3D) {
+		// Target is set to a 3D texture or array texture, exit early to avoid spamming errors
+		return;
+	}
+	ERR_FAIL_COND(!texture->active);
+	ERR_FAIL_COND(texture->render_target);
+	ERR_FAIL_COND(p_image.is_null());
+	ERR_FAIL_COND(texture->format != p_image->get_format());
+
+	ERR_FAIL_COND(!p_image->get_width());
+	ERR_FAIL_COND(!p_image->get_height());
+
+	//	ERR_FAIL_COND(texture->type == RS::TEXTURE_TYPE_EXTERNAL);
+
+	GLenum type;
+	GLenum format;
+	GLenum internal_format;
+	bool compressed = false;
+
+	if (config->keep_original_textures && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) {
+		texture->images.write[p_layer] = p_image;
+	}
+
+	// print_line("texture_set_data width " + itos (p_image->get_width()) + " height " + itos(p_image->get_height()));
+
+	Image::Format real_format;
+	Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2);
+
+	if (texture->resize_to_po2) {
+		if (p_image->is_compressed()) {
+			ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage.");
+		}
+
+		if (img == p_image) {
+			img = img->duplicate();
+		}
+		img->resize_to_po2(false);
+	}
+
+	if (config->shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) {
+		texture->alloc_height = MAX(1, texture->alloc_height / 2);
+		texture->alloc_width = MAX(1, texture->alloc_width / 2);
+
+		if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) {
+			img->shrink_x2();
+		} else if (img->get_format() <= Image::FORMAT_RGBA8) {
+			img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR);
+		}
+	}
+
+	GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D;
+
+	texture->data_size = img->get_data().size();
+	Vector<uint8_t> read = img->get_data();
+
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(texture->target, texture->tex_id);
+
+	texture->ignore_mipmaps = compressed && !img->has_mipmaps();
+
+	// set filtering and repeat state
+	_texture_set_state_from_flags(texture);
+
+	//set swizle for older format compatibility
+#ifdef GLES_OVER_GL
+	switch (texture->format) {
+		case Image::FORMAT_L8: {
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED);
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED);
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ONE);
+
+		} break;
+		case Image::FORMAT_LA8: {
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED);
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED);
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_GREEN);
+		} break;
+		default: {
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
+			glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
+
+		} break;
+	}
+#endif
+
+	int mipmaps = ((texture->flags & TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1;
+
+	int w = img->get_width();
+	int h = img->get_height();
+
+	int tsize = 0;
+
+	for (int i = 0; i < mipmaps; i++) {
+		int size, ofs;
+		img->get_mipmap_offset_and_size(i, ofs, size);
+
+		if (compressed) {
+			glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+			int bw = w;
+			int bh = h;
+
+			glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
+		} else {
+			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+			if (texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
+				glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]);
+			} else {
+				glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
+			}
+		}
+
+		tsize += size;
+
+		w = MAX(1, w >> 1);
+		h = MAX(1, h >> 1);
+	}
+
+	// info.texture_mem -= texture->total_data_size; // TODO make this work again!!
+	texture->total_data_size = tsize;
+	// info.texture_mem += texture->total_data_size; // TODO make this work again!!
+
+	// printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem);
+
+	texture->stored_cube_sides |= (1 << p_layer);
+
+	if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != RenderingDevice::TEXTURE_TYPE_CUBE || texture->stored_cube_sides == (1 << 6) - 1)) {
+		//generate mipmaps if they were requested and the image does not contain them
+		glGenerateMipmap(texture->target);
+	}
+
+	texture->mipmaps = mipmaps;
+}
+
+void TextureStorage::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) {
+	// TODO
+	ERR_PRINT("Not implemented (ask Karroffel to do it :p)");
+}
+
+/*
+Ref<Image> TextureStorage::texture_get_data(RID p_texture, int p_layer) const {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND_V(!texture, Ref<Image>());
+	ERR_FAIL_COND_V(!texture->active, Ref<Image>());
+	ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>());
+
+	if (texture->type == RS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) {
+		return texture->images[p_layer];
+	}
+
+#ifdef GLES_OVER_GL
+
+	Image::Format real_format;
+	GLenum gl_format;
+	GLenum gl_internal_format;
+	GLenum gl_type;
+	bool compressed;
+	_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, false);
+
+	PoolVector<uint8_t> data;
+
+	int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1);
+
+	data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
+	PoolVector<uint8_t>::Write wb = data.write();
+
+	glActiveTexture(GL_TEXTURE0);
+
+	glBindTexture(texture->target, texture->tex_id);
+
+	glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+
+	for (int i = 0; i < texture->mipmaps; i++) {
+		int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i);
+
+		if (texture->compressed) {
+			glPixelStorei(GL_PACK_ALIGNMENT, 4);
+			glGetCompressedTexImage(texture->target, i, &wb[ofs]);
+		} else {
+			glPixelStorei(GL_PACK_ALIGNMENT, 1);
+			glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]);
+		}
+	}
+
+	wb.release();
+
+	data.resize(data_size);
+
+	Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, real_format, data));
+
+	return Ref<Image>(img);
+#else
+
+	Image::Format real_format;
+	GLenum gl_format;
+	GLenum gl_internal_format;
+	GLenum gl_type;
+	bool compressed;
+	_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, texture->resize_to_po2);
+
+	PoolVector<uint8_t> data;
+
+	int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
+
+	data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
+	PoolVector<uint8_t>::Write wb = data.write();
+
+	GLuint temp_framebuffer;
+	glGenFramebuffers(1, &temp_framebuffer);
+
+	GLuint temp_color_texture;
+	glGenTextures(1, &temp_color_texture);
+
+	glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer);
+
+	glBindTexture(GL_TEXTURE_2D, temp_color_texture);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0);
+
+	glDepthMask(GL_FALSE);
+	glDisable(GL_DEPTH_TEST);
+	glDisable(GL_CULL_FACE);
+	glDisable(GL_BLEND);
+	glDepthFunc(GL_LEQUAL);
+	glColorMask(1, 1, 1, 1);
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(GL_TEXTURE_2D, texture->tex_id);
+
+	glViewport(0, 0, texture->alloc_width, texture->alloc_height);
+
+	shaders.copy.bind();
+
+	glClearColor(0.0, 0.0, 0.0, 0.0);
+	glClear(GL_COLOR_BUFFER_BIT);
+	bind_quad_array();
+	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+	glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]);
+
+	glDeleteTextures(1, &temp_color_texture);
+
+	glBindFramebuffer(GL_FRAMEBUFFER, 0);
+	glDeleteFramebuffers(1, &temp_framebuffer);
+
+	wb.release();
+
+	data.resize(data_size);
+
+	Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data));
+	if (!texture->compressed) {
+		img->convert(real_format);
+	}
+
+	return Ref<Image>(img);
+
+#endif
+}
+*/
+
+void TextureStorage::texture_set_flags(RID p_texture, uint32_t p_flags) {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!texture);
+
+	bool had_mipmaps = texture->flags & TEXTURE_FLAG_MIPMAPS;
+
+	texture->flags = p_flags;
+
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(texture->target, texture->tex_id);
+
+	// set filtering and repeat state
+	_texture_set_state_from_flags(texture);
+
+	if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) {
+		if (!had_mipmaps && texture->mipmaps == 1) {
+			glGenerateMipmap(texture->target);
+		}
+	}
+}
+
+uint32_t TextureStorage::texture_get_flags(RID p_texture) const {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND_V(!texture, 0);
+
+	return texture->flags;
+}
+
+Image::Format TextureStorage::texture_get_format(RID p_texture) const {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND_V(!texture, Image::FORMAT_L8);
+
+	return texture->format;
+}
+
+RenderingDevice::TextureType TextureStorage::texture_get_type(RID p_texture) const {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND_V(!texture, RenderingDevice::TEXTURE_TYPE_2D);
+
+	return texture->type;
+}
+
+uint32_t TextureStorage::texture_get_texid(RID p_texture) const {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND_V(!texture, 0);
+
+	return texture->tex_id;
+}
+
+uint32_t TextureStorage::texture_get_width(RID p_texture) const {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND_V(!texture, 0);
+
+	return texture->width;
+}
+
+uint32_t TextureStorage::texture_get_height(RID p_texture) const {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND_V(!texture, 0);
+
+	return texture->height;
+}
+
+uint32_t TextureStorage::texture_get_depth(RID p_texture) const {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND_V(!texture, 0);
+
+	return texture->depth;
+}
+
+void TextureStorage::texture_bind(RID p_texture, uint32_t p_texture_no) {
+	Texture *texture = texture_owner.get_or_null(p_texture);
+
+	ERR_FAIL_COND(!texture);
+
+	glActiveTexture(GL_TEXTURE0 + p_texture_no);
+	glBindTexture(texture->target, texture->tex_id);
+}
+
+void TextureStorage::texture_set_shrink_all_x2_on_set_data(bool p_enable) {
+	Config::get_singleton()->shrink_textures_x2 = p_enable;
+}
+
+RID TextureStorage::texture_create_radiance_cubemap(RID p_source, int p_resolution) const {
+	return RID();
+}
+
+void TextureStorage::textures_keep_original(bool p_enable) {
+	Config::get_singleton()->keep_original_textures = p_enable;
+}
+
+#endif // GLES3_ENABLED

+ 389 - 0
drivers/gles3/storage/texture_storage.h

@@ -0,0 +1,389 @@
+/*************************************************************************/
+/*  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 TEXTURE_STORAGE_GLES3_H
+#define TEXTURE_STORAGE_GLES3_H
+
+#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/storage/texture_storage.h"
+
+namespace GLES3 {
+
+#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+
+#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB
+#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD
+#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#define _EXT_ETC1_RGB8_OES 0x8D64
+
+#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+
+#define _GL_TEXTURE_EXTERNAL_OES 0x8D65
+
+#ifdef GLES_OVER_GL
+#define _GL_HALF_FLOAT_OES 0x140B
+#else
+#define _GL_HALF_FLOAT_OES 0x8D61
+#endif
+
+#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+
+#define _RED_OES 0x1903
+
+#define _DEPTH_COMPONENT24_OES 0x81A6
+
+#ifndef GLES_OVER_GL
+#define glClearDepth glClearDepthf
+#endif //!GLES_OVER_GL
+
+enum OpenGLTextureFlags {
+	TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available
+	TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping
+	TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter
+	TEXTURE_FLAG_ANISOTROPIC_FILTER = 8,
+	TEXTURE_FLAG_CONVERT_TO_LINEAR = 16,
+	TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored
+	TEXTURE_FLAG_USED_FOR_STREAMING = 2048,
+	TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER
+};
+
+struct Texture {
+	RID self;
+
+	Texture *proxy;
+	Set<Texture *> proxy_owners;
+
+	String path;
+	uint32_t flags;
+	int width, height, depth;
+	int alloc_width, alloc_height;
+	Image::Format format;
+	RenderingDevice::TextureType type;
+
+	GLenum target;
+	GLenum gl_format_cache;
+	GLenum gl_internal_format_cache;
+	GLenum gl_type_cache;
+
+	int data_size;
+	int total_data_size;
+	bool ignore_mipmaps;
+
+	bool compressed;
+
+	bool srgb;
+
+	int mipmaps;
+
+	bool resize_to_po2;
+
+	bool active;
+	GLenum tex_id;
+
+	uint16_t stored_cube_sides;
+
+	RenderTarget *render_target;
+
+	Vector<Ref<Image>> images;
+
+	bool redraw_if_visible;
+
+	RS::TextureDetectCallback detect_3d;
+	void *detect_3d_ud;
+
+	RS::TextureDetectCallback detect_srgb;
+	void *detect_srgb_ud;
+
+	RS::TextureDetectCallback detect_normal;
+	void *detect_normal_ud;
+
+	CanvasTexture *canvas_texture = nullptr;
+
+	// some silly opengl shenanigans where
+	// texture coords start from bottom left, means we need to draw render target textures upside down
+	// to be compatible with vulkan etc.
+	bool is_upside_down() const {
+		if (proxy) {
+			return proxy->is_upside_down();
+		}
+
+		return render_target != nullptr;
+	}
+
+	Texture() {
+		create();
+	}
+
+	_ALWAYS_INLINE_ Texture *get_ptr() {
+		if (proxy) {
+			return proxy; //->get_ptr(); only one level of indirection, else not inlining possible.
+		} else {
+			return this;
+		}
+	}
+
+	~Texture() {
+		destroy();
+
+		if (tex_id != 0) {
+			glDeleteTextures(1, &tex_id);
+		}
+	}
+
+	void copy_from(const Texture &o) {
+		proxy = o.proxy;
+		flags = o.flags;
+		width = o.width;
+		height = o.height;
+		alloc_width = o.alloc_width;
+		alloc_height = o.alloc_height;
+		format = o.format;
+		type = o.type;
+		target = o.target;
+		data_size = o.data_size;
+		total_data_size = o.total_data_size;
+		ignore_mipmaps = o.ignore_mipmaps;
+		compressed = o.compressed;
+		mipmaps = o.mipmaps;
+		resize_to_po2 = o.resize_to_po2;
+		active = o.active;
+		tex_id = o.tex_id;
+		stored_cube_sides = o.stored_cube_sides;
+		render_target = o.render_target;
+		redraw_if_visible = o.redraw_if_visible;
+		detect_3d = o.detect_3d;
+		detect_3d_ud = o.detect_3d_ud;
+		detect_srgb = o.detect_srgb;
+		detect_srgb_ud = o.detect_srgb_ud;
+		detect_normal = o.detect_normal;
+		detect_normal_ud = o.detect_normal_ud;
+
+		images.clear();
+	}
+
+	void create() {
+		proxy = nullptr;
+		flags = 0;
+		width = 0;
+		height = 0;
+		alloc_width = 0;
+		alloc_height = 0;
+		format = Image::FORMAT_L8;
+		type = RenderingDevice::TEXTURE_TYPE_2D;
+		target = 0;
+		data_size = 0;
+		total_data_size = 0;
+		ignore_mipmaps = false;
+		compressed = false;
+		mipmaps = 0;
+		resize_to_po2 = false;
+		active = false;
+		tex_id = 0;
+		stored_cube_sides = 0;
+		render_target = nullptr;
+		redraw_if_visible = false;
+		detect_3d = nullptr;
+		detect_3d_ud = nullptr;
+		detect_srgb = nullptr;
+		detect_srgb_ud = nullptr;
+		detect_normal = nullptr;
+		detect_normal_ud = nullptr;
+	}
+	void destroy() {
+		images.clear();
+
+		for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) {
+			E->get()->proxy = nullptr;
+		}
+
+		if (proxy) {
+			proxy->proxy_owners.erase(this);
+		}
+	}
+
+	// texture state
+	void GLSetFilter(GLenum p_target, RS::CanvasItemTextureFilter p_filter) {
+		if (p_filter == state_filter) {
+			return;
+		}
+		state_filter = p_filter;
+		GLint pmin = GL_LINEAR; // param min
+		GLint pmag = GL_LINEAR; // param mag
+		switch (state_filter) {
+			default: {
+			} break;
+			case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+				pmin = GL_LINEAR_MIPMAP_LINEAR;
+				pmag = GL_LINEAR;
+			} break;
+			case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+				pmin = GL_NEAREST;
+				pmag = GL_NEAREST;
+			} break;
+			case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+				pmin = GL_NEAREST_MIPMAP_NEAREST;
+				pmag = GL_NEAREST;
+			} break;
+		}
+		glTexParameteri(p_target, GL_TEXTURE_MIN_FILTER, pmin);
+		glTexParameteri(p_target, GL_TEXTURE_MAG_FILTER, pmag);
+	}
+	void GLSetRepeat(GLenum p_target, RS::CanvasItemTextureRepeat p_repeat) {
+		if (p_repeat == state_repeat) {
+			return;
+		}
+		state_repeat = p_repeat;
+		GLint prep = GL_CLAMP_TO_EDGE; // parameter repeat
+		switch (state_repeat) {
+			default: {
+			} break;
+			case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+				prep = GL_REPEAT;
+			} break;
+			case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+				prep = GL_MIRRORED_REPEAT;
+			} break;
+		}
+		glTexParameteri(p_target, GL_TEXTURE_WRAP_S, prep);
+		glTexParameteri(p_target, GL_TEXTURE_WRAP_T, prep);
+	}
+
+private:
+	RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
+	RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
+};
+
+class TextureStorage : public RendererTextureStorage {
+private:
+	static TextureStorage *singleton;
+
+	Thread::ID _main_thread_id = 0;
+	bool _is_main_thread();
+
+	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;
+	void _texture_set_state_from_flags(Texture *p_tex);
+
+	void texture_set_proxy(RID p_texture, RID p_proxy);
+
+public:
+	static TextureStorage *get_singleton();
+
+	TextureStorage();
+	virtual ~TextureStorage();
+
+	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); };
+
+	void set_main_thread_id(Thread::ID p_id);
+
+	virtual bool can_create_resources_async() const override;
+
+	RID texture_create();
+	void _texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT);
+
+	virtual RID texture_allocate() override;
+	virtual void texture_free(RID p_rid) override;
+
+	virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
+	virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
+	virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
+	virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
+
+	virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
+	virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{};
+	virtual void texture_proxy_update(RID p_proxy, RID p_base) override{};
+
+	//these two APIs can be used together or in combination with the others.
+	virtual void texture_2d_placeholder_initialize(RID p_texture) override;
+	virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
+	virtual void texture_3d_placeholder_initialize(RID p_texture) override;
+
+	virtual Ref<Image> texture_2d_get(RID p_texture) const override;
+	virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); };
+	virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); };
+
+	virtual void texture_replace(RID p_texture, RID p_by_texture) override;
+	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override;
+
+	virtual void texture_set_path(RID p_texture, const String &p_path) override;
+	virtual String texture_get_path(RID p_texture) const override;
+
+	virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
+	void texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata);
+	virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
+	virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{};
+
+	virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override;
+
+	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;
+
+	void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
+	void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0);
+	//Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const;
+	void texture_set_flags(RID p_texture, uint32_t p_flags);
+	uint32_t texture_get_flags(RID p_texture) const;
+	Image::Format texture_get_format(RID p_texture) const;
+	RenderingDevice::TextureType texture_get_type(RID p_texture) const;
+	uint32_t texture_get_texid(RID p_texture) const;
+	uint32_t texture_get_width(RID p_texture) const;
+	uint32_t texture_get_height(RID p_texture) const;
+	uint32_t texture_get_depth(RID p_texture) const;
+	void texture_bind(RID p_texture, uint32_t p_texture_no);
+	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);
+};
+
+} // namespace GLES3
+
+#endif // !GLES3_ENABLED
+
+#endif // !TEXTURE_STORAGE_GLES3_H

+ 1 - 1
platform/javascript/display_server_javascript.cpp

@@ -34,7 +34,7 @@
 #include "drivers/gles3/rasterizer_gles3.h"
 #endif
 #include "platform/javascript/os_javascript.h"
-#include "servers/rendering/rasterizer_dummy.h"
+#include "servers/rendering/dummy/rasterizer_dummy.h"
 
 #include <emscripten.h>
 #include <png.h>

+ 1 - 1
scene/resources/texture.cpp

@@ -212,7 +212,7 @@ void ImageTexture::update(const Ref<Image> &p_image) {
 	ERR_FAIL_COND_MSG(mipmaps != p_image->has_mipmaps(),
 			"The new image mipmaps configuration must match the texture's image mipmaps configuration");
 
-	RenderingServer::get_singleton()->texture_2d_update(texture, p_image);
+	RS::get_singleton()->texture_2d_update(texture, p_image);
 
 	notify_property_list_changed();
 	emit_changed();

+ 1 - 1
servers/display_server_headless.h

@@ -33,7 +33,7 @@
 
 #include "servers/display_server.h"
 
-#include "servers/rendering/rasterizer_dummy.h"
+#include "servers/rendering/dummy/rasterizer_dummy.h"
 
 class DisplayServerHeadless : public DisplayServer {
 private:

+ 1 - 0
servers/rendering/SCsub

@@ -5,3 +5,4 @@ Import("env")
 env.add_source_files(env.servers_sources, "*.cpp")
 
 SConscript("renderer_rd/SCsub")
+SConscript("storage/SCsub")

+ 63 - 0
servers/rendering/dummy/rasterizer_canvas_dummy.h

@@ -0,0 +1,63 @@
+/*************************************************************************/
+/*  rasterizer_canvas_dummy.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 RASTERIZER_CANVAS_DUMMY_H
+#define RASTERIZER_CANVAS_DUMMY_H
+
+#include "servers/rendering/renderer_canvas_render.h"
+
+class RasterizerCanvasDummy : public RendererCanvasRender {
+public:
+	PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; }
+	void free_polygon(PolygonID p_polygon) override {}
+
+	void 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) override {}
+	void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {}
+
+	RID light_create() override { return RID(); }
+	void light_set_texture(RID p_rid, RID p_texture) override {}
+	void light_set_use_shadow(RID p_rid, bool p_enable) override {}
+	void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {}
+	void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {}
+
+	void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {}
+	RID occluder_polygon_create() override { return RID(); }
+	void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {}
+	void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {}
+	void set_shadow_texture_size(int p_size) override {}
+
+	bool free(RID p_rid) override { return true; }
+	void update() override {}
+
+	RasterizerCanvasDummy() {}
+	~RasterizerCanvasDummy() {}
+};
+
+#endif // !RASTERIZER_CANVAS_DUMMY_H

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

@@ -0,0 +1,99 @@
+/*************************************************************************/
+/*  rasterizer_dummy.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 RASTERIZER_DUMMY_H
+#define RASTERIZER_DUMMY_H
+
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "scene/resources/mesh.h"
+#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/texture_storage.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering_server.h"
+
+class RasterizerDummy : public RendererCompositor {
+private:
+	uint64_t frame = 1;
+	double delta = 0;
+
+protected:
+	RasterizerCanvasDummy canvas;
+	RendererDummy::CanvasTextureStorage canvas_texture_storage;
+	RendererDummy::TextureStorage texture_storage;
+	RasterizerStorageDummy storage;
+	RasterizerSceneDummy scene;
+
+public:
+	RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; };
+	RendererTextureStorage *get_texture_storage() override { return &texture_storage; };
+	RendererStorage *get_storage() override { return &storage; }
+	RendererCanvasRender *get_canvas() override { return &canvas; }
+	RendererSceneRender *get_scene() override { return &scene; }
+
+	void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {}
+
+	void initialize() override {}
+	void begin_frame(double frame_step) override {
+		frame++;
+		delta = frame_step;
+	}
+
+	void prepare_for_blitting_render_targets() override {}
+	void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {}
+
+	void end_frame(bool p_swap_buffers) override {
+		if (p_swap_buffers) {
+			DisplayServer::get_singleton()->swap_buffers();
+		}
+	}
+
+	void finalize() override {}
+
+	static RendererCompositor *_create_current() {
+		return memnew(RasterizerDummy);
+	}
+
+	static void make_current() {
+		_create_func = _create_current;
+	}
+
+	bool is_low_end() const override { return true; }
+	uint64_t get_frame_number() const override { return frame; }
+	double get_frame_delta_time() const override { return delta; }
+
+	RasterizerDummy() {}
+	~RasterizerDummy() {}
+};
+
+#endif // RASTERIZER_DUMMY_H

+ 217 - 0
servers/rendering/dummy/rasterizer_scene_dummy.h

@@ -0,0 +1,217 @@
+/*************************************************************************/
+/*  rasterizer_scene_dummy.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 RASTERIZER_SCENE_DUMMY_H
+#define RASTERIZER_SCENE_DUMMY_H
+
+#include "servers/rendering/renderer_scene_render.h"
+
+class RasterizerSceneDummy : public RendererSceneRender {
+public:
+	GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
+	void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
+	void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
+	void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {}
+	void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
+	void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
+	void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
+	void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {}
+	void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {}
+	void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+	void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+	void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {}
+	void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
+	void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
+	void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+	void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
+	void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
+	void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}
+
+	uint32_t geometry_instance_get_pair_mask() override { return 0; }
+	void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
+	void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
+	void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
+	void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
+	void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {}
+
+	void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
+
+	/* SHADOW ATLAS API */
+
+	RID shadow_atlas_create() override { return RID(); }
+	void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {}
+	void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {}
+	bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; }
+
+	void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {}
+	int get_directional_light_shadow_size(RID p_light_intance) override { return 0; }
+	void set_directional_shadow_count(int p_count) override {}
+
+	/* SDFGI UPDATE */
+
+	void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
+	int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
+	AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
+	uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
+
+	/* SKY API */
+
+	RID sky_allocate() override { return RID(); }
+	void sky_initialize(RID p_rid) override {}
+	void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {}
+	void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {}
+	void sky_set_material(RID p_sky, RID p_material) override {}
+	Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
+
+	/* ENVIRONMENT API */
+
+	RID environment_allocate() override { return RID(); }
+	void environment_initialize(RID p_rid) override {}
+	void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {}
+	void environment_set_sky(RID p_env, RID p_sky) override {}
+	void environment_set_sky_custom_fov(RID p_env, float p_scale) override {}
+	void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {}
+	void environment_set_bg_color(RID p_env, const Color &p_color) override {}
+	void environment_set_bg_energy(RID p_env, float p_energy) override {}
+	void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
+	void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {}
+
+	void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {}
+	void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
+	void environment_glow_set_use_high_quality(bool p_enable) override {}
+
+	void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {}
+	void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
+	void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {}
+	void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
+	void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {}
+	void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
+
+	void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
+
+	void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
+	void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
+	void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {}
+
+	void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {}
+
+	void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}
+
+	void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
+	void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {}
+	void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
+	void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
+
+	Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
+
+	bool is_environment(RID p_env) const override { return false; }
+	RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; }
+	int environment_get_canvas_max_layer(RID p_env) const override { return 0; }
+
+	RID camera_effects_allocate() override { return RID(); }
+	void camera_effects_initialize(RID p_rid) override {}
+	void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {}
+	void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {}
+
+	void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {}
+	void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {}
+
+	void shadows_quality_set(RS::ShadowQuality p_quality) override {}
+	void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {}
+
+	RID light_instance_create(RID p_light) override { return RID(); }
+	void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {}
+	void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
+	void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
+	void light_instance_mark_visible(RID p_light_instance) override {}
+
+	RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); }
+	void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {}
+	void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {}
+	RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); }
+	Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); }
+
+	RID reflection_atlas_create() override { return RID(); }
+	int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
+	void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
+
+	RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
+	void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {}
+	void reflection_probe_release_atlas_index(RID p_instance) override {}
+	bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
+	bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
+	bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; }
+	bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; }
+
+	RID decal_instance_create(RID p_decal) override { return RID(); }
+	void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
+
+	RID lightmap_instance_create(RID p_lightmap) override { return RID(); }
+	void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {}
+
+	RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); }
+	void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {}
+	bool voxel_gi_needs_update(RID p_probe) const override { return false; }
+	void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {}
+
+	void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
+
+	void 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 = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
+	void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
+	void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
+
+	void set_scene_pass(uint64_t p_pass) override {}
+	void set_time(double p_time, double p_step) override {}
+	void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
+
+	RID render_buffers_create() override { return RID(); }
+	void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
+	void gi_set_use_half_resolution(bool p_enable) override {}
+
+	void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
+	bool screen_space_roughness_limiter_is_active() const override { return false; }
+
+	void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
+	void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
+
+	TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
+
+	bool free(RID p_rid) override { return false; }
+	void update() override {}
+	void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
+
+	virtual void decals_set_filter(RS::DecalFilter p_filter) override {}
+	virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {}
+
+	RasterizerSceneDummy() {}
+	~RasterizerSceneDummy() {}
+};
+
+#endif // !RASTERIZER_SCENE_DUMMY_H

+ 11 - 339
servers/rendering/rasterizer_dummy.h → servers/rendering/dummy/rasterizer_storage_dummy.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  rasterizer_dummy.h                                                   */
+/*  rasterizer_storage_dummy.h                                           */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,265 +28,14 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef RASTERIZER_DUMMY_H
-#define RASTERIZER_DUMMY_H
+#ifndef RASTERIZER_STORAGE_DUMMY_H
+#define RASTERIZER_STORAGE_DUMMY_H
 
-#include "core/templates/rid_owner.h"
-#include "core/templates/self_list.h"
-#include "scene/resources/mesh.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_scene_render.h"
-#include "servers/rendering_server.h"
-
-class RasterizerSceneDummy : public RendererSceneRender {
-public:
-	GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
-	void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
-	void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
-	void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {}
-	void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
-	void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
-	void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
-	void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {}
-	void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {}
-	void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {}
-	void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {}
-	void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {}
-	void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
-	void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
-	void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
-	void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
-	void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
-	void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}
-
-	uint32_t geometry_instance_get_pair_mask() override { return 0; }
-	void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
-	void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
-	void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
-	void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
-	void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {}
-
-	void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
-
-	/* SHADOW ATLAS API */
-
-	RID shadow_atlas_create() override { return RID(); }
-	void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {}
-	void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {}
-	bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; }
-
-	void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {}
-	int get_directional_light_shadow_size(RID p_light_intance) override { return 0; }
-	void set_directional_shadow_count(int p_count) override {}
-
-	/* SDFGI UPDATE */
-
-	void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
-	int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
-	AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
-	uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
-
-	/* SKY API */
-
-	RID sky_allocate() override { return RID(); }
-	void sky_initialize(RID p_rid) override {}
-	void sky_set_radiance_size(RID p_sky, int p_radiance_size) override {}
-	void sky_set_mode(RID p_sky, RS::SkyMode p_samples) override {}
-	void sky_set_material(RID p_sky, RID p_material) override {}
-	Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
-
-	/* ENVIRONMENT API */
-
-	RID environment_allocate() override { return RID(); }
-	void environment_initialize(RID p_rid) override {}
-	void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {}
-	void environment_set_sky(RID p_env, RID p_sky) override {}
-	void environment_set_sky_custom_fov(RID p_env, float p_scale) override {}
-	void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {}
-	void environment_set_bg_color(RID p_env, const Color &p_color) override {}
-	void environment_set_bg_energy(RID p_env, float p_energy) override {}
-	void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
-	void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {}
-
-	void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {}
-	void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
-	void environment_glow_set_use_high_quality(bool p_enable) override {}
-
-	void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {}
-	void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
-	void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {}
-	void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
-	void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {}
-	void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
-
-	void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
-
-	void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
-	void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
-	void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {}
-
-	void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {}
-
-	void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}
-
-	void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
-	void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {}
-	void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
-	void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
-
-	Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
-
-	bool is_environment(RID p_env) const override { return false; }
-	RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; }
-	int environment_get_canvas_max_layer(RID p_env) const override { return 0; }
-
-	RID camera_effects_allocate() override { return RID(); }
-	void camera_effects_initialize(RID p_rid) override {}
-	void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {}
-	void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {}
-
-	void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {}
-	void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {}
-
-	void shadows_quality_set(RS::ShadowQuality p_quality) override {}
-	void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {}
-
-	RID light_instance_create(RID p_light) override { return RID(); }
-	void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {}
-	void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
-	void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
-	void light_instance_mark_visible(RID p_light_instance) override {}
-
-	RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); }
-	void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {}
-	void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {}
-	RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); }
-	Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); }
-
-	RID reflection_atlas_create() override { return RID(); }
-	int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
-	void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
-
-	RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
-	void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {}
-	void reflection_probe_release_atlas_index(RID p_instance) override {}
-	bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
-	bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
-	bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; }
-	bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; }
-
-	RID decal_instance_create(RID p_decal) override { return RID(); }
-	void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
-
-	RID lightmap_instance_create(RID p_lightmap) override { return RID(); }
-	void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {}
-
-	RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); }
-	void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {}
-	bool voxel_gi_needs_update(RID p_probe) const override { return false; }
-	void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {}
-
-	void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
-
-	void 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 = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
-	void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
-	void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
-
-	void set_scene_pass(uint64_t p_pass) override {}
-	void set_time(double p_time, double p_step) override {}
-	void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
-
-	RID render_buffers_create() override { return RID(); }
-	void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
-	void gi_set_use_half_resolution(bool p_enable) override {}
-
-	void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
-	bool screen_space_roughness_limiter_is_active() const override { return false; }
-
-	void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
-	void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
-
-	TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
-
-	bool free(RID p_rid) override { return false; }
-	void update() override {}
-	void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
-
-	virtual void decals_set_filter(RS::DecalFilter p_filter) override {}
-	virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {}
-
-	RasterizerSceneDummy() {}
-	~RasterizerSceneDummy() {}
-};
+#include "servers/rendering/renderer_storage.h"
+#include "storage/texture_storage.h"
 
 class RasterizerStorageDummy : public RendererStorage {
 public:
-	bool can_create_resources_async() const override { return false; }
-
-	/* TEXTURE API */
-	struct DummyTexture {
-		Ref<Image> image;
-	};
-	mutable RID_PtrOwner<DummyTexture> texture_owner;
-
-	RID texture_allocate() override {
-		DummyTexture *texture = memnew(DummyTexture);
-		ERR_FAIL_COND_V(!texture, RID());
-		return texture_owner.make_rid(texture);
-	}
-	void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override {
-		DummyTexture *t = texture_owner.get_or_null(p_texture);
-		ERR_FAIL_COND(!t);
-		t->image = p_image->duplicate();
-	}
-
-	void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {}
-	void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
-	void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {}
-	void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {}
-	void texture_proxy_initialize(RID p_texture, RID p_base) override {}
-	void texture_proxy_update(RID p_proxy, RID p_base) override {}
-
-	void texture_2d_placeholder_initialize(RID p_texture) override {}
-	void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override {}
-	void texture_3d_placeholder_initialize(RID p_texture) override {}
-
-	Ref<Image> texture_2d_get(RID p_texture) const override {
-		DummyTexture *t = texture_owner.get_or_null(p_texture);
-		ERR_FAIL_COND_V(!t, Ref<Image>());
-		return t->image;
-	}
-
-	Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
-	Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
-
-	void texture_replace(RID p_texture, RID p_by_texture) override { free(p_by_texture); }
-	void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
-
-	void texture_set_path(RID p_texture, const String &p_path) override {}
-	String texture_get_path(RID p_texture) const override { return String(); }
-
-	void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {}
-	void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override {}
-	void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {}
-
-	void texture_debug_usage(List<RS::TextureInfo> *r_info) override {}
-	void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {}
-	Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }
-
-	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 {}
-
-	/* CANVAS TEXTURE API */
-
-	RID canvas_texture_allocate() override { return RID(); }
-	void canvas_texture_initialize(RID p_rid) override {}
-	void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override {}
-	void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override {}
-
-	void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override {}
-	void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override {}
-
 	/* SHADER API */
 
 	RID shader_allocate() override { return RID(); }
@@ -481,6 +230,9 @@ public:
 
 	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(); }
@@ -682,11 +434,8 @@ public:
 
 	RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
 	bool free(RID p_rid) override {
-		if (texture_owner.owns(p_rid)) {
-			// delete the texture
-			DummyTexture *texture = texture_owner.get_or_null(p_rid);
-			texture_owner.free(p_rid);
-			memdelete(texture);
+		if (RendererDummy::TextureStorage::get_singleton()->owns_texture(p_rid)) {
+			RendererDummy::TextureStorage::get_singleton()->texture_free(p_rid);
 			return true;
 		}
 		return false;
@@ -721,81 +470,4 @@ public:
 	~RasterizerStorageDummy() {}
 };
 
-class RasterizerCanvasDummy : public RendererCanvasRender {
-public:
-	PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; }
-	void free_polygon(PolygonID p_polygon) override {}
-
-	void 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) override {}
-	void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {}
-
-	RID light_create() override { return RID(); }
-	void light_set_texture(RID p_rid, RID p_texture) override {}
-	void light_set_use_shadow(RID p_rid, bool p_enable) override {}
-	void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {}
-	void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {}
-
-	void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {}
-	RID occluder_polygon_create() override { return RID(); }
-	void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) override {}
-	void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {}
-	void set_shadow_texture_size(int p_size) override {}
-
-	bool free(RID p_rid) override { return true; }
-	void update() override {}
-
-	RasterizerCanvasDummy() {}
-	~RasterizerCanvasDummy() {}
-};
-
-class RasterizerDummy : public RendererCompositor {
-private:
-	uint64_t frame = 1;
-	double delta = 0;
-
-protected:
-	RasterizerCanvasDummy canvas;
-	RasterizerStorageDummy storage;
-	RasterizerSceneDummy scene;
-
-public:
-	RendererStorage *get_storage() override { return &storage; }
-	RendererCanvasRender *get_canvas() override { return &canvas; }
-	RendererSceneRender *get_scene() override { return &scene; }
-
-	void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override {}
-
-	void initialize() override {}
-	void begin_frame(double frame_step) override {
-		frame++;
-		delta = frame_step;
-	}
-
-	void prepare_for_blitting_render_targets() override {}
-	void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {}
-
-	void end_frame(bool p_swap_buffers) override {
-		if (p_swap_buffers) {
-			DisplayServer::get_singleton()->swap_buffers();
-		}
-	}
-
-	void finalize() override {}
-
-	static RendererCompositor *_create_current() {
-		return memnew(RasterizerDummy);
-	}
-
-	static void make_current() {
-		_create_func = _create_current;
-	}
-
-	bool is_low_end() const override { return true; }
-	uint64_t get_frame_number() const override { return frame; }
-	double get_frame_delta_time() const override { return delta; }
-
-	RasterizerDummy() {}
-	~RasterizerDummy() {}
-};
-
-#endif // RASTERIZER_DUMMY_H
+#endif // !RASTERIZER_STORAGE_DUMMY_H

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

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

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

@@ -0,0 +1,116 @@
+/*************************************************************************/
+/*  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 TEXTURE_STORAGE_DUMMY_H
+#define TEXTURE_STORAGE_DUMMY_H
+
+#include "servers/rendering/rendering_server_globals.h"
+#include "servers/rendering/storage/texture_storage.h"
+
+namespace RendererDummy {
+
+class TextureStorage : public RendererTextureStorage {
+private:
+	struct DummyTexture {
+		Ref<Image> image;
+	};
+	mutable RID_PtrOwner<DummyTexture> texture_owner;
+
+public:
+	static TextureStorage *get_singleton() {
+		// Here we cheat until we can retire RasterizerStorageDummy::free()
+
+		return (TextureStorage *)RSG::texture_storage;
+	};
+
+	virtual bool can_create_resources_async() const override { return false; }
+
+	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); };
+
+	virtual RID texture_allocate() override {
+		DummyTexture *texture = memnew(DummyTexture);
+		ERR_FAIL_COND_V(!texture, RID());
+		return texture_owner.make_rid(texture);
+	};
+
+	virtual void texture_free(RID p_rid) override {
+		// delete the texture
+		DummyTexture *texture = texture_owner.get_or_null(p_rid);
+		texture_owner.free(p_rid);
+		memdelete(texture);
+	};
+
+	virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override {
+		DummyTexture *t = texture_owner.get_or_null(p_texture);
+		ERR_FAIL_COND(!t);
+		t->image = p_image->duplicate();
+	};
+	virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override{};
+	virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override{};
+	virtual void texture_proxy_initialize(RID p_texture, RID p_base) override{}; //all slices, then all the mipmaps, must be coherent
+
+	virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override{};
+	virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{};
+	virtual void texture_proxy_update(RID p_proxy, RID p_base) override{};
+
+	//these two APIs can be used together or in combination with the others.
+	virtual void texture_2d_placeholder_initialize(RID p_texture) override{};
+	virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override{};
+	virtual void texture_3d_placeholder_initialize(RID p_texture) override{};
+
+	virtual Ref<Image> texture_2d_get(RID p_texture) const override {
+		DummyTexture *t = texture_owner.get_or_null(p_texture);
+		ERR_FAIL_COND_V(!t, Ref<Image>());
+		return t->image;
+	};
+	virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); };
+	virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); };
+
+	virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); };
+	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override{};
+
+	virtual void texture_set_path(RID p_texture, const String &p_path) override{};
+	virtual String texture_get_path(RID p_texture) const override { return String(); };
+
+	virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{};
+	virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{};
+	virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{};
+
+	virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override{};
+
+	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(); };
+};
+
+} // namespace RendererDummy
+
+#endif // !TEXTURE_STORAGE_DUMMY_H

+ 7 - 6
servers/rendering/renderer_canvas_cull.cpp

@@ -34,6 +34,7 @@
 #include "renderer_viewport.h"
 #include "rendering_server_default.h"
 #include "rendering_server_globals.h"
+#include "servers/rendering/storage/canvas_texture_storage.h"
 
 static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
 
@@ -1530,26 +1531,26 @@ void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) {
 }
 
 RID RendererCanvasCull::canvas_texture_allocate() {
-	return RSG::storage->canvas_texture_allocate();
+	return RSG::canvas_texture_storage->canvas_texture_allocate();
 }
 void RendererCanvasCull::canvas_texture_initialize(RID p_rid) {
-	RSG::storage->canvas_texture_initialize(p_rid);
+	RSG::canvas_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::storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture);
+	RSG::canvas_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::storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess);
+	RSG::canvas_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::storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter);
+	RSG::canvas_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::storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat);
+	RSG::canvas_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) {

+ 4 - 0
servers/rendering/renderer_compositor.h

@@ -34,6 +34,8 @@
 #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/texture_storage.h"
 #include "servers/rendering_server.h"
 
 class RendererSceneRender;
@@ -70,6 +72,8 @@ protected:
 public:
 	static RendererCompositor *create();
 
+	virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0;
+	virtual RendererTextureStorage *get_texture_storage() = 0;
 	virtual RendererStorage *get_storage() = 0;
 	virtual RendererCanvasRender *get_canvas() = 0;
 	virtual RendererSceneRender *get_scene() = 0;

+ 1 - 0
servers/rendering/renderer_rd/SCsub

@@ -7,3 +7,4 @@ env.add_source_files(env.servers_sources, "*.cpp")
 SConscript("forward_clustered/SCsub")
 SConscript("forward_mobile/SCsub")
 SConscript("shaders/SCsub")
+SConscript("storage_rd/SCsub")

+ 24 - 24
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp

@@ -2213,7 +2213,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		if (p_radiance_texture.is_valid()) {
 			radiance_texture = p_radiance_texture;
 		} else {
-			radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+			radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
 		}
 		RD::Uniform u;
 		u.binding = 2;
@@ -2230,7 +2230,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		if (ref_texture.is_valid()) {
 			u.append_id(ref_texture);
 		} else {
-			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+			u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
 		}
 		uniforms.push_back(u);
 	}
@@ -2244,7 +2244,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
 		}
 		if (!texture.is_valid()) {
-			texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+			texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 		}
 		u.append_id(texture);
 		uniforms.push_back(u);
@@ -2256,7 +2256,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
 			u.append_id(directional_shadow_get_texture());
 		} else {
-			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+			u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
 		}
 		uniforms.push_back(u);
 	}
@@ -2265,12 +2265,12 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		u.binding = 6;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 
-		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+		RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
 		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 rd_texture = storage->texture_get_rd_texture(texture);
+				RID rd_texture = texture_storage->texture_get_rd_texture(texture);
 				u.append_id(rd_texture);
 			} else {
 				u.append_id(default_tex);
@@ -2283,7 +2283,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		RD::Uniform u;
 		u.binding = 7;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+		RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
 			if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) {
 				RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]);
@@ -2313,7 +2313,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		u.binding = 9;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
-		RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+		RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 		u.append_id(texture);
 		uniforms.push_back(u);
 	}
@@ -2322,7 +2322,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		u.binding = 10;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
-		RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+		RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
 		u.append_id(texture);
 		uniforms.push_back(u);
 	}
@@ -2332,7 +2332,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			RD::Uniform u;
 			u.binding = 11;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL);
+			RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL);
 			u.append_id(texture);
 			uniforms.push_back(u);
 		}
@@ -2342,7 +2342,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID();
-			RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+			RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
 			u.append_id(texture);
 			uniforms.push_back(u);
 		}
@@ -2352,7 +2352,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.binding = 13;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID();
-			RID texture = ambient_buffer.is_valid() ? ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+			RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
 			u.append_id(texture);
 			uniforms.push_back(u);
 		}
@@ -2362,7 +2362,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.binding = 14;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID();
-			RID texture = reflection_buffer.is_valid() ? reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+			RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
 			u.append_id(texture);
 			uniforms.push_back(u);
 		}
@@ -2374,7 +2374,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
 				t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers);
 			} else {
-				t = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+				t = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
 			}
 			u.append_id(t);
 			uniforms.push_back(u);
@@ -2386,7 +2386,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
 				u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers));
 			} else {
-				u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 			}
 			uniforms.push_back(u);
 		}
@@ -2405,10 +2405,10 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) {
 				vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers);
 				if (vfog.is_null()) {
-					vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+					vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 				}
 			} else {
-				vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+				vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 			}
 			u.append_id(vfog);
 			uniforms.push_back(u);
@@ -2418,7 +2418,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.binding = 19;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID();
-			RID texture = ssil.is_valid() ? ssil : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+			RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
 			u.append_id(texture);
 			uniforms.push_back(u);
 		}
@@ -2446,7 +2446,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 	}
 	{
 		// No radiance texture.
-		RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+		RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
 		RD::Uniform u;
 		u.binding = 2;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
@@ -2456,7 +2456,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 
 	{
 		// No reflection atlas.
-		RID ref_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+		RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
 		RD::Uniform u;
 		u.binding = 3;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
@@ -2469,7 +2469,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		RD::Uniform u;
 		u.binding = 4;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+		RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 		u.append_id(texture);
 		uniforms.push_back(u);
 	}
@@ -2479,7 +2479,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		RD::Uniform u;
 		u.binding = 5;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+		RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 		u.append_id(texture);
 		uniforms.push_back(u);
 	}
@@ -2490,7 +2490,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		u.binding = 6;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 
-		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+		RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
 		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
 			u.append_id(default_tex);
 		}
@@ -2504,7 +2504,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		u.binding = 7;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 
-		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+		RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
 			u.append_id(default_tex);
 		}

+ 9 - 9
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

@@ -315,7 +315,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		if (p_radiance_texture.is_valid()) {
 			radiance_texture = p_radiance_texture;
 		} else {
-			radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+			radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
 		}
 		RD::Uniform u;
 		u.binding = 2;
@@ -332,7 +332,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		if (ref_texture.is_valid()) {
 			u.append_id(ref_texture);
 		} else {
-			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+			u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
 		}
 		uniforms.push_back(u);
 	}
@@ -346,7 +346,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 			texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
 		}
 		if (!texture.is_valid()) {
-			texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+			texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 		}
 		u.append_id(texture);
 		uniforms.push_back(u);
@@ -358,7 +358,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
 			u.append_id(directional_shadow_get_texture());
 		} else {
-			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+			u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
 		}
 		uniforms.push_back(u);
 	}
@@ -369,12 +369,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		u.binding = 6;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 
-		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+		RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
 		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 rd_texture = storage->texture_get_rd_texture(texture);
+				RID rd_texture = texture_storage->texture_get_rd_texture(texture);
 				u.append_id(rd_texture);
 			} else {
 				u.append_id(default_tex);
@@ -390,7 +390,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		u.binding = 7;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
-		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+		RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
 			if (i < (int)p_voxel_gi_instances.size()) {
 				RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]);
@@ -421,7 +421,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		u.binding = 9;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
-		RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+		RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 		u.append_id(texture);
 		uniforms.push_back(u);
 	}
@@ -430,7 +430,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		u.binding = 10;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
-		RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+		RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
 		u.append_id(texture);
 		uniforms.push_back(u);
 	}

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

@@ -358,7 +358,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
 	bool use_normal;
 	bool use_specular;
 
-	bool success = storage->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 = canvas_texture_storage->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);
@@ -977,7 +977,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		} else {
 			screen = storage->render_target_get_rd_backbuffer(p_to_render_target);
 			if (screen.is_null()) { //unallocated backbuffer
-				screen = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+				screen = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 			}
 		}
 		u.append_id(screen);
@@ -2245,6 +2245,8 @@ void RendererCanvasRenderRD::update() {
 }
 
 RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
+	canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton();
+	texture_storage = RendererRD::TextureStorage::get_singleton();
 	storage = p_storage;
 
 	{ //create default samplers
@@ -2575,8 +2577,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 = storage->canvas_texture_allocate();
-	storage->canvas_texture_initialize(default_canvas_texture);
+	default_canvas_texture = canvas_texture_storage->canvas_texture_allocate();
+	canvas_texture_storage->canvas_texture_initialize(default_canvas_texture);
 
 	state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
 
@@ -2696,6 +2698,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
 	}
 	RD::get_singleton()->free(state.shadow_texture);
 
-	storage->free(default_canvas_texture);
+	canvas_texture_storage->canvas_texture_free(default_canvas_texture);
 	//pipelines don't need freeing, they are all gone after shaders are gone
 }

+ 4 - 0
servers/rendering/renderer_rd/renderer_canvas_render_rd.h

@@ -37,10 +37,14 @@
 #include "servers/rendering/renderer_rd/renderer_storage_rd.h"
 #include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_device.h"
 #include "servers/rendering/shader_compiler.h"
 
 class RendererCanvasRenderRD : public RendererCanvasRender {
+	RendererRD::CanvasTextureStorage *canvas_texture_storage;
+	RendererRD::TextureStorage *texture_storage;
 	RendererStorageRD *storage;
 
 	enum {

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

@@ -46,7 +46,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);
 		ERR_CONTINUE(texture.is_null());
-		RID rd_texture = storage->texture_get_rd_texture(texture);
+		RID rd_texture = texture_storage->texture_get_rd_texture(texture);
 		ERR_CONTINUE(rd_texture.is_null());
 
 		// TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in.
@@ -155,6 +155,8 @@ void RendererCompositorRD::finalize() {
 	memdelete(scene);
 	memdelete(canvas);
 	memdelete(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);
@@ -165,9 +167,9 @@ void RendererCompositorRD::finalize() {
 void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
 	RD::get_singleton()->prepare_screen_for_drawing();
 
-	RID texture = storage->texture_allocate();
-	storage->texture_2d_initialize(texture, p_image);
-	RID rd_texture = storage->texture_get_rd_texture(texture);
+	RID texture = texture_storage->texture_allocate();
+	texture_storage->texture_2d_initialize(texture, p_image);
+	RID rd_texture = texture_storage->texture_get_rd_texture(texture);
 
 	RID uset;
 	{
@@ -235,7 +237,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
 
 	RD::get_singleton()->swap_buffers();
 
-	storage->free(texture);
+	texture_storage->texture_free(texture);
 }
 
 RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
@@ -283,6 +285,8 @@ RendererCompositorRD::RendererCompositorRD() {
 	singleton = this;
 	time = 0;
 
+	canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage);
+	texture_storage = memnew(RendererRD::TextureStorage);
 	storage = memnew(RendererStorageRD);
 	canvas = memnew(RendererCanvasRenderRD(storage));
 

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

@@ -39,12 +39,16 @@
 #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/texture_storage.h"
 #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
 
 class RendererCompositorRD : public RendererCompositor {
 protected:
 	UniformSetCacheRD *uniform_set_cache;
 	RendererCanvasRenderRD *canvas;
+	RendererRD::CanvasTextureStorage *canvas_texture_storage;
+	RendererRD::TextureStorage *texture_storage;
 	RendererStorageRD *storage;
 	RendererSceneRenderRD *scene;
 
@@ -88,6 +92,8 @@ protected:
 	static uint64_t frame;
 
 public:
+	RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; };
+	RendererTextureStorage *get_texture_storage() { return texture_storage; };
 	RendererStorage *get_storage() { return storage; }
 	RendererCanvasRender *get_canvas() { return canvas; }
 	RendererSceneRender *get_scene() { return scene; }

+ 27 - 18
servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp

@@ -40,6 +40,7 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF
 // SDFGI
 
 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();
 	storage = p_gi->storage;
 	gi = p_gi;
 	num_cascades = p_env->sdfgi_cascades;
@@ -377,7 +378,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
 				if (j < cascades.size()) {
 					u.append_id(cascades[j].sdf_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -620,7 +621,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
 				if (j < cascades.size()) {
 					u.append_id(cascades[j].sdf_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -633,7 +634,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
 				if (j < cascades.size()) {
 					u.append_id(cascades[j].light_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -646,7 +647,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
 				if (j < cascades.size()) {
 					u.append_id(cascades[j].light_aniso_0_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -659,7 +660,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
 				if (j < cascades.size()) {
 					u.append_id(cascades[j].light_aniso_1_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -1108,6 +1109,8 @@ 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();
+
 	if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) {
 		Vector<RD::Uniform> uniforms;
 		{
@@ -1118,7 +1121,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
 				if (i < cascades.size()) {
 					u.append_id(cascades[i].sdf_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -1131,7 +1134,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
 				if (i < cascades.size()) {
 					u.append_id(cascades[i].light_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -1144,7 +1147,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
 				if (i < cascades.size()) {
 					u.append_id(cascades[i].light_aniso_0_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -1157,7 +1160,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
 				if (i < cascades.size()) {
 					u.append_id(cascades[i].light_aniso_1_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -2807,6 +2810,8 @@ RendererSceneGIRD::~RendererSceneGIRD() {
 }
 
 void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
 	storage = p_storage;
 
 	/* GI */
@@ -2924,7 +2929,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 0;
-				u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE));
 				uniforms.push_back(u);
 			}
 			{
@@ -3023,6 +3028,8 @@ RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironme
 }
 
 void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
 	r_voxel_gi_instances_used = 0;
 
 	// feels a little dirty to use our container this way but....
@@ -3085,7 +3092,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
 		}
 
 		if (texture == RID()) {
-			texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+			texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		}
 
 		if (texture != rb->gi.voxel_gi_textures[i]) {
@@ -3121,6 +3128,8 @@ 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();
+
 	RD::get_singleton()->draw_command_begin_label("GI Render");
 
 	RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
@@ -3186,7 +3195,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
 				if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
 					u.append_id(rb->sdfgi->cascades[j].sdf_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -3199,7 +3208,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
 				if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
 					u.append_id(rb->sdfgi->cascades[j].light_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -3212,7 +3221,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
 				if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
 					u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -3225,7 +3234,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
 				if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
 					u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex);
 				} else {
-					u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+					u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 				}
 			}
 			uniforms.push_back(u);
@@ -3237,7 +3246,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
 			if (rb->sdfgi) {
 				u.append_id(rb->sdfgi->occlusion_texture);
 			} else {
-				u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 			}
 			uniforms.push_back(u);
 		}
@@ -3279,7 +3288,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
 			if (rb->sdfgi) {
 				u.append_id(rb->sdfgi->lightprobe_texture);
 			} else {
-				u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
 			}
 			uniforms.push_back(u);
 		}
@@ -3301,7 +3310,7 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 14;
-			RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+			RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
 			u.append_id(buffer);
 			uniforms.push_back(u);
 		}

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

@@ -45,6 +45,7 @@
 #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"
 

+ 18 - 17
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -2490,7 +2490,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
 			tonemap.exposure_texture = rb->luminance.current;
 			tonemap.auto_exposure_grey = env->auto_exp_scale;
 		} else {
-			tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+			tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 		}
 
 		if (can_use_effects && env && env->glow_enabled) {
@@ -2506,15 +2506,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
 			tonemap.glow_texture = rb->blur[1].texture;
 			if (env->glow_map.is_valid()) {
 				tonemap.glow_map_strength = env->glow_map_strength;
-				tonemap.glow_map = storage->texture_get_rd_texture(env->glow_map);
+				tonemap.glow_map = texture_storage->texture_get_rd_texture(env->glow_map);
 			} else {
 				tonemap.glow_map_strength = 0.0f;
-				tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+				tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 			}
 
 		} else {
-			tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
-			tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+			tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+			tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 		}
 
 		if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
@@ -2536,7 +2536,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
 
 		tonemap.use_color_correction = false;
 		tonemap.use_1d_color_correction = false;
-		tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+		tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 
 		if (can_use_effects && env) {
 			tonemap.use_bcs = env->adjustments_enabled;
@@ -2546,7 +2546,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
 			if (env->adjustments_enabled && env->color_correction.is_valid()) {
 				tonemap.use_color_correction = true;
 				tonemap.use_1d_color_correction = env->use_1d_color_correction;
-				tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction);
+				tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction);
 			}
 		}
 
@@ -2606,14 +2606,14 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
 	}
 
 	tonemap.use_glow = false;
-	tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
-	tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+	tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+	tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 	tonemap.use_auto_exposure = false;
-	tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+	tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 
 	tonemap.use_color_correction = false;
 	tonemap.use_1d_color_correction = false;
-	tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+	tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 
 	if (can_use_effects && env) {
 		tonemap.use_bcs = env->adjustments_enabled;
@@ -2623,7 +2623,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
 		if (env->adjustments_enabled && env->color_correction.is_valid()) {
 			tonemap.use_color_correction = true;
 			tonemap.use_1d_color_correction = env->use_1d_color_correction;
-			tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction);
+			tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction);
 		}
 	}
 
@@ -2656,7 +2656,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
 			RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
 
 			if (shadow_atlas_texture.is_null()) {
-				shadow_atlas_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+				shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
 			}
 
 			Size2 rtsize = storage->render_target_get_size(rb->render_target);
@@ -2716,7 +2716,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
 	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(storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
+			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);
 		}
 	}
 }
@@ -4364,7 +4364,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			u.binding = 1;
 			ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
 			if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) {
-				u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
 			} else {
 				u.append_id(shadow_atlas->depth);
 			}
@@ -4380,7 +4380,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			if (directional_shadow.depth.is_valid()) {
 				u.append_id(directional_shadow.depth);
 			} else {
-				u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
 			}
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
@@ -4545,7 +4545,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 19;
-			RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+			RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
 			RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID();
 			u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture);
 			uniforms.push_back(u);
@@ -5600,6 +5600,7 @@ uint32_t RendererSceneRenderRD::get_max_elements() const {
 }
 
 RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
+	texture_storage = RendererRD::TextureStorage::get_singleton();
 	storage = p_storage;
 	singleton = this;
 }

+ 2 - 0
servers/rendering/renderer_rd/renderer_scene_render_rd.h

@@ -41,6 +41,7 @@
 #include "servers/rendering/renderer_rd/renderer_storage_rd.h"
 #include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/renderer_scene.h"
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/rendering/rendering_device.h"
@@ -92,6 +93,7 @@ class RendererSceneRenderRD : public RendererSceneRender {
 	friend RendererSceneGIRD;
 
 protected:
+	RendererRD::TextureStorage *texture_storage;
 	RendererStorageRD *storage;
 	double time;
 	double time_step = 0;

+ 13 - 9
servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp

@@ -33,6 +33,7 @@
 #include "core/math/math_defs.h"
 #include "renderer_scene_render_rd.h"
 #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_server_default.h"
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -621,6 +622,8 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) {
 }
 
 RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
 	if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) {
 		return texture_uniform_sets[p_version];
 	}
@@ -632,7 +635,7 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
 		if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) {
 			u.append_id(radiance);
 		} else {
-			u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+			u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
 		}
 		uniforms.push_back(u);
 	}
@@ -648,9 +651,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
 			}
 		} else {
 			if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
-				u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
 			} else {
-				u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
 			}
 		}
 		uniforms.push_back(u);
@@ -667,9 +670,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
 			}
 		} else {
 			if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
-				u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
 			} else {
-				u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+				u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
 			}
 		}
 		uniforms.push_back(u);
@@ -793,6 +796,7 @@ RendererSceneSkyRD::RendererSceneSkyRD() {
 }
 
 void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	storage = p_storage;
 
 	{
@@ -972,7 +976,7 @@ void sky() {
 			RD::Uniform u;
 			u.binding = 0;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			RID vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+			RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 			u.append_id(vfog);
 			uniforms.push_back(u);
 		}
@@ -1006,21 +1010,21 @@ void sky() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 0;
-			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+			u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 1;
-			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+			u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 2;
-			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+			u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
 			uniforms.push_back(u);
 		}
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 3 - 1104
servers/rendering/renderer_rd/renderer_storage_rd.cpp


+ 10 - 208
servers/rendering/renderer_rd/renderer_storage_rd.h

@@ -41,9 +41,12 @@
 #include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
 #include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/rendering/rendering_device.h"
 #include "servers/rendering/shader_compiler.h"
+
 class RendererStorageRD : public RendererStorage {
 public:
 	static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
@@ -179,22 +182,6 @@ public:
 	typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
 	static void _material_uniform_set_erased(void *p_material);
 
-	enum DefaultRDTexture {
-		DEFAULT_RD_TEXTURE_WHITE,
-		DEFAULT_RD_TEXTURE_BLACK,
-		DEFAULT_RD_TEXTURE_NORMAL,
-		DEFAULT_RD_TEXTURE_ANISO,
-		DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
-		DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
-		DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
-		DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
-		DEFAULT_RD_TEXTURE_3D_WHITE,
-		DEFAULT_RD_TEXTURE_3D_BLACK,
-		DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
-		DEFAULT_RD_TEXTURE_2D_UINT,
-		DEFAULT_RD_TEXTURE_MAX
-	};
-
 	enum DefaultRDBuffer {
 		DEFAULT_RD_BUFFER_VERTEX,
 		DEFAULT_RD_BUFFER_NORMAL,
@@ -212,113 +199,8 @@ public:
 	};
 
 private:
-	/* CANVAS TEXTURE API (2D) */
-
-	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;
-		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();
-	};
-
-	RID_Owner<CanvasTexture, true> canvas_texture_owner;
-
 	/* TEXTURE API */
-	struct Texture {
-		enum Type {
-			TYPE_2D,
-			TYPE_LAYERED,
-			TYPE_3D
-		};
-
-		Type type;
-		RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
-
-		RenderingDevice::TextureType rd_type;
-		RID rd_texture;
-		RID rd_texture_srgb;
-		RenderingDevice::DataFormat rd_format;
-		RenderingDevice::DataFormat rd_format_srgb;
 
-		RD::TextureView rd_view;
-
-		Image::Format format;
-		Image::Format validated_format;
-
-		int width;
-		int height;
-		int depth;
-		int layers;
-		int mipmaps;
-
-		int height_2d;
-		int width_2d;
-
-		struct BufferSlice3D {
-			Size2i size;
-			uint32_t offset = 0;
-			uint32_t buffer_size = 0;
-		};
-		Vector<BufferSlice3D> buffer_slices_3d;
-		uint32_t buffer_size_3d = 0;
-
-		bool is_render_target;
-		bool is_proxy;
-
-		Ref<Image> image_cache_2d;
-		String path;
-
-		RID proxy_to;
-		Vector<RID> proxies;
-		Set<RID> lightmap_users;
-
-		RS::TextureDetectCallback detect_3d_callback = nullptr;
-		void *detect_3d_callback_ud = nullptr;
-
-		RS::TextureDetectCallback detect_normal_callback = nullptr;
-		void *detect_normal_callback_ud = nullptr;
-
-		RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
-		void *detect_roughness_callback_ud = nullptr;
-
-		CanvasTexture *canvas_texture = nullptr;
-	};
-
-	struct TextureToRDFormat {
-		RD::DataFormat format;
-		RD::DataFormat format_srgb;
-		RD::TextureSwizzle swizzle_r;
-		RD::TextureSwizzle swizzle_g;
-		RD::TextureSwizzle swizzle_b;
-		RD::TextureSwizzle swizzle_a;
-		TextureToRDFormat() {
-			format = RD::DATA_FORMAT_MAX;
-			format_srgb = RD::DATA_FORMAT_MAX;
-			swizzle_r = RD::TEXTURE_SWIZZLE_R;
-			swizzle_g = RD::TEXTURE_SWIZZLE_G;
-			swizzle_b = RD::TEXTURE_SWIZZLE_B;
-			swizzle_a = RD::TEXTURE_SWIZZLE_A;
-		}
-	};
-
-	//textures can be created from threads, so this RID_Owner is thread safe
-	mutable RID_Owner<Texture, true> texture_owner;
-
-	Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format);
-
-	RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
 	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];
 	RID default_rd_storage_buffer;
@@ -1308,52 +1190,6 @@ private:
 	EffectsRD *effects = nullptr;
 
 public:
-	virtual bool can_create_resources_async() const;
-
-	/* TEXTURE API */
-
-	virtual RID texture_allocate();
-
-	virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image);
-	virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type);
-	virtual void texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent
-	virtual void texture_proxy_initialize(RID p_texture, RID p_base);
-
-	virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate);
-
-	virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
-	virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data);
-	virtual void texture_proxy_update(RID p_texture, RID p_proxy_to);
-
-	//these two APIs can be used together or in combination with the others.
-	virtual void texture_2d_placeholder_initialize(RID p_texture);
-	virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type);
-	virtual void texture_3d_placeholder_initialize(RID p_texture);
-
-	virtual Ref<Image> texture_2d_get(RID p_texture) const;
-	virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const;
-	virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const;
-
-	virtual void texture_replace(RID p_texture, RID p_by_texture);
-	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height);
-
-	virtual void texture_set_path(RID p_texture, const String &p_path);
-	virtual String texture_get_path(RID p_texture) const;
-
-	virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata);
-	virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata);
-	virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata);
-
-	virtual void texture_debug_usage(List<RS::TextureInfo> *r_info);
-
-	virtual void texture_set_proxy(RID p_proxy, RID p_base);
-	virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable);
-
-	virtual Size2 texture_size_with_proxy(RID p_proxy);
-
-	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);
-
 	RID decal_atlas_get_texture() const;
 	RID decal_atlas_get_texture_srgb() const;
 	_FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
@@ -1367,33 +1203,6 @@ public:
 
 	//internal usage
 
-	_FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
-		if (p_texture.is_null()) {
-			return RID();
-		}
-		Texture *tex = texture_owner.get_or_null(p_texture);
-
-		if (!tex) {
-			return RID();
-		}
-		return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
-	}
-
-	_FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) {
-		if (p_texture.is_null()) {
-			return Size2i();
-		}
-		Texture *tex = texture_owner.get_or_null(p_texture);
-
-		if (!tex) {
-			return Size2i();
-		}
-		return Size2i(tex->width_2d, tex->height_2d);
-	}
-
-	_FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
-		return default_rd_textures[p_texture];
-	}
 	_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
 		return default_rd_samplers[p_filter][p_repeat];
 	}
@@ -1405,19 +1214,6 @@ public:
 
 	void sampler_rd_set_default(float p_mipmap_bias);
 
-	/* CANVAS TEXTURE API */
-
-	RID canvas_texture_allocate();
-	void canvas_texture_initialize(RID p_canvas_texture);
-
-	virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture);
-	virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess);
-
-	virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter);
-	virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat);
-
-	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);
-
 	/* SHADER API */
 
 	RID shader_allocate();
@@ -1926,7 +1722,7 @@ public:
 		const Light *light = light_owner.get_or_null(p_light);
 		ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
 
-		return texture_owner.owns(light->projector);
+		return light_owner.owns(light->projector);
 	}
 
 	_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
@@ -2010,6 +1806,12 @@ public:
 	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;

+ 5 - 0
servers/rendering/renderer_rd/storage_rd/SCsub

@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")

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

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

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

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

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

@@ -0,0 +1,1420 @@
+/*************************************************************************/
+/*  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 "texture_storage.h"
+
+// only include until we have DecalStorage sorted
+#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+
+using namespace RendererRD;
+
+///////////////////////////////////////////////////////////////////////////
+// Texture
+
+void Texture::cleanup() {
+	if (RD::get_singleton()->texture_is_valid(rd_texture_srgb)) {
+		//erase this first, as it's a dependency of the one below
+		RD::get_singleton()->free(rd_texture_srgb);
+	}
+	if (RD::get_singleton()->texture_is_valid(rd_texture)) {
+		RD::get_singleton()->free(rd_texture);
+	}
+	if (canvas_texture) {
+		memdelete(canvas_texture);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////
+// TextureStorage
+
+TextureStorage *TextureStorage::singleton = nullptr;
+
+TextureStorage *TextureStorage::get_singleton() {
+	return singleton;
+}
+
+TextureStorage::TextureStorage() {
+	singleton = this;
+
+	{ //create default textures
+
+		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, 255);
+			pv.set(i * 4 + 1, 255);
+			pv.set(i * 4 + 2, 255);
+			pv.set(i * 4 + 3, 255);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			vpv.push_back(pv);
+			default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+
+		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);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			vpv.push_back(pv);
+			default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+
+		for (int i = 0; i < 16; i++) {
+			pv.set(i * 4 + 0, 128);
+			pv.set(i * 4 + 1, 128);
+			pv.set(i * 4 + 2, 255);
+			pv.set(i * 4 + 3, 255);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			vpv.push_back(pv);
+			default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+
+		for (int i = 0; i < 16; i++) {
+			pv.set(i * 4 + 0, 255);
+			pv.set(i * 4 + 1, 128);
+			pv.set(i * 4 + 2, 255);
+			pv.set(i * 4 + 3, 255);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			vpv.push_back(pv);
+			default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+
+		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, 0);
+		}
+
+		default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv);
+
+		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, 0);
+		}
+
+		{
+			tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
+			Vector<Vector<uint8_t>> vpv;
+			vpv.push_back(pv);
+			default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+	}
+
+	{ //create default cubemap
+
+		RD::TextureFormat tformat;
+		tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+		tformat.width = 4;
+		tformat.height = 4;
+		tformat.array_layers = 6;
+		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+		tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+
+		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, 0);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			for (int i = 0; i < 6; i++) {
+				vpv.push_back(pv);
+			}
+			default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+	}
+
+	{ //create default cubemap array
+
+		RD::TextureFormat tformat;
+		tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+		tformat.width = 4;
+		tformat.height = 4;
+		tformat.array_layers = 6;
+		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+		tformat.texture_type = RD::TEXTURE_TYPE_CUBE;
+
+		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, 0);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			for (int i = 0; i < 6; i++) {
+				vpv.push_back(pv);
+			}
+			default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+	}
+
+	{ //create default cubemap white array
+
+		RD::TextureFormat tformat;
+		tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+		tformat.width = 4;
+		tformat.height = 4;
+		tformat.array_layers = 6;
+		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+		tformat.texture_type = RD::TEXTURE_TYPE_CUBE;
+
+		Vector<uint8_t> pv;
+		pv.resize(16 * 4);
+		for (int i = 0; i < 16; i++) {
+			pv.set(i * 4 + 0, 255);
+			pv.set(i * 4 + 1, 255);
+			pv.set(i * 4 + 2, 255);
+			pv.set(i * 4 + 3, 255);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			for (int i = 0; i < 6; i++) {
+				vpv.push_back(pv);
+			}
+			default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+	}
+
+	{ //create default 3D
+
+		RD::TextureFormat tformat;
+		tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+		tformat.width = 4;
+		tformat.height = 4;
+		tformat.depth = 4;
+		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+		tformat.texture_type = RD::TEXTURE_TYPE_3D;
+
+		Vector<uint8_t> pv;
+		pv.resize(64 * 4);
+		for (int i = 0; i < 64; i++) {
+			pv.set(i * 4 + 0, 0);
+			pv.set(i * 4 + 1, 0);
+			pv.set(i * 4 + 2, 0);
+			pv.set(i * 4 + 3, 0);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			vpv.push_back(pv);
+			default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+		for (int i = 0; i < 64; i++) {
+			pv.set(i * 4 + 0, 255);
+			pv.set(i * 4 + 1, 255);
+			pv.set(i * 4 + 2, 255);
+			pv.set(i * 4 + 3, 255);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			vpv.push_back(pv);
+			default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+	}
+
+	{ //create default array
+
+		RD::TextureFormat tformat;
+		tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+		tformat.width = 4;
+		tformat.height = 4;
+		tformat.array_layers = 1;
+		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+		tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+
+		Vector<uint8_t> pv;
+		pv.resize(16 * 4);
+		for (int i = 0; i < 16; i++) {
+			pv.set(i * 4 + 0, 255);
+			pv.set(i * 4 + 1, 255);
+			pv.set(i * 4 + 2, 255);
+			pv.set(i * 4 + 3, 255);
+		}
+
+		{
+			Vector<Vector<uint8_t>> vpv;
+			vpv.push_back(pv);
+			default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+		}
+	}
+}
+
+TextureStorage::~TextureStorage() {
+	singleton = nullptr;
+
+	//def textures
+	for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) {
+		texture_free(default_rd_textures[i]);
+	}
+}
+
+bool TextureStorage::can_create_resources_async() const {
+	return true;
+}
+
+RID TextureStorage::texture_allocate() {
+	return texture_owner.allocate_rid();
+}
+
+void TextureStorage::texture_free(RID p_texture) {
+	Texture *t = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!t);
+	ERR_FAIL_COND(t->is_render_target);
+
+	t->cleanup();
+
+	if (t->is_proxy && t->proxy_to.is_valid()) {
+		Texture *proxy_to = texture_owner.get_or_null(t->proxy_to);
+		if (proxy_to) {
+			proxy_to->proxies.erase(p_texture);
+		}
+	}
+
+	RendererStorageRD::base_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]);
+		ERR_CONTINUE(!p);
+		p->proxy_to = RID();
+		p->rd_texture = RID();
+		p->rd_texture_srgb = RID();
+	}
+
+	texture_owner.free(p_texture);
+}
+
+void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
+	TextureToRDFormat ret_format;
+	Ref<Image> image = _validate_texture_format(p_image, ret_format);
+
+	Texture texture;
+
+	texture.type = Texture::TYPE_2D;
+
+	texture.width = p_image->get_width();
+	texture.height = p_image->get_height();
+	texture.layers = 1;
+	texture.mipmaps = p_image->get_mipmap_count() + 1;
+	texture.depth = 1;
+	texture.format = p_image->get_format();
+	texture.validated_format = image->get_format();
+
+	texture.rd_type = RD::TEXTURE_TYPE_2D;
+	texture.rd_format = ret_format.format;
+	texture.rd_format_srgb = ret_format.format_srgb;
+
+	RD::TextureFormat rd_format;
+	RD::TextureView rd_view;
+	{ //attempt register
+		rd_format.format = texture.rd_format;
+		rd_format.width = texture.width;
+		rd_format.height = texture.height;
+		rd_format.depth = 1;
+		rd_format.array_layers = 1;
+		rd_format.mipmaps = texture.mipmaps;
+		rd_format.texture_type = texture.rd_type;
+		rd_format.samples = RD::TEXTURE_SAMPLES_1;
+		rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+		if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+			rd_format.shareable_formats.push_back(texture.rd_format);
+			rd_format.shareable_formats.push_back(texture.rd_format_srgb);
+		}
+	}
+	{
+		rd_view.swizzle_r = ret_format.swizzle_r;
+		rd_view.swizzle_g = ret_format.swizzle_g;
+		rd_view.swizzle_b = ret_format.swizzle_b;
+		rd_view.swizzle_a = ret_format.swizzle_a;
+	}
+	Vector<uint8_t> data = image->get_data(); //use image data
+	Vector<Vector<uint8_t>> data_slices;
+	data_slices.push_back(data);
+	texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
+	ERR_FAIL_COND(texture.rd_texture.is_null());
+	if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+		rd_view.format_override = texture.rd_format_srgb;
+		texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
+		if (texture.rd_texture_srgb.is_null()) {
+			RD::get_singleton()->free(texture.rd_texture);
+			ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
+		}
+	}
+
+	//used for 2D, overridable
+	texture.width_2d = texture.width;
+	texture.height_2d = texture.height;
+	texture.is_render_target = false;
+	texture.rd_view = rd_view;
+	texture.is_proxy = false;
+
+	texture_owner.initialize_rid(p_texture, texture);
+}
+
+void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
+	ERR_FAIL_COND(p_layers.size() == 0);
+
+	ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6);
+	ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0));
+
+	TextureToRDFormat ret_format;
+	Vector<Ref<Image>> images;
+	{
+		int valid_width = 0;
+		int valid_height = 0;
+		bool valid_mipmaps = false;
+		Image::Format valid_format = Image::FORMAT_MAX;
+
+		for (int i = 0; i < p_layers.size(); i++) {
+			ERR_FAIL_COND(p_layers[i]->is_empty());
+
+			if (i == 0) {
+				valid_width = p_layers[i]->get_width();
+				valid_height = p_layers[i]->get_height();
+				valid_format = p_layers[i]->get_format();
+				valid_mipmaps = p_layers[i]->has_mipmaps();
+			} else {
+				ERR_FAIL_COND(p_layers[i]->get_width() != valid_width);
+				ERR_FAIL_COND(p_layers[i]->get_height() != valid_height);
+				ERR_FAIL_COND(p_layers[i]->get_format() != valid_format);
+				ERR_FAIL_COND(p_layers[i]->has_mipmaps() != valid_mipmaps);
+			}
+
+			images.push_back(_validate_texture_format(p_layers[i], ret_format));
+		}
+	}
+
+	Texture texture;
+
+	texture.type = Texture::TYPE_LAYERED;
+	texture.layered_type = p_layered_type;
+
+	texture.width = p_layers[0]->get_width();
+	texture.height = p_layers[0]->get_height();
+	texture.layers = p_layers.size();
+	texture.mipmaps = p_layers[0]->get_mipmap_count() + 1;
+	texture.depth = 1;
+	texture.format = p_layers[0]->get_format();
+	texture.validated_format = images[0]->get_format();
+
+	switch (p_layered_type) {
+		case RS::TEXTURE_LAYERED_2D_ARRAY: {
+			texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY;
+		} break;
+		case RS::TEXTURE_LAYERED_CUBEMAP: {
+			texture.rd_type = RD::TEXTURE_TYPE_CUBE;
+		} break;
+		case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: {
+			texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+		} break;
+	}
+
+	texture.rd_format = ret_format.format;
+	texture.rd_format_srgb = ret_format.format_srgb;
+
+	RD::TextureFormat rd_format;
+	RD::TextureView rd_view;
+	{ //attempt register
+		rd_format.format = texture.rd_format;
+		rd_format.width = texture.width;
+		rd_format.height = texture.height;
+		rd_format.depth = 1;
+		rd_format.array_layers = texture.layers;
+		rd_format.mipmaps = texture.mipmaps;
+		rd_format.texture_type = texture.rd_type;
+		rd_format.samples = RD::TEXTURE_SAMPLES_1;
+		rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+		if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+			rd_format.shareable_formats.push_back(texture.rd_format);
+			rd_format.shareable_formats.push_back(texture.rd_format_srgb);
+		}
+	}
+	{
+		rd_view.swizzle_r = ret_format.swizzle_r;
+		rd_view.swizzle_g = ret_format.swizzle_g;
+		rd_view.swizzle_b = ret_format.swizzle_b;
+		rd_view.swizzle_a = ret_format.swizzle_a;
+	}
+	Vector<Vector<uint8_t>> data_slices;
+	for (int i = 0; i < images.size(); i++) {
+		Vector<uint8_t> data = images[i]->get_data(); //use image data
+		data_slices.push_back(data);
+	}
+	texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
+	ERR_FAIL_COND(texture.rd_texture.is_null());
+	if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+		rd_view.format_override = texture.rd_format_srgb;
+		texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
+		if (texture.rd_texture_srgb.is_null()) {
+			RD::get_singleton()->free(texture.rd_texture);
+			ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
+		}
+	}
+
+	//used for 2D, overridable
+	texture.width_2d = texture.width;
+	texture.height_2d = texture.height;
+	texture.is_render_target = false;
+	texture.rd_view = rd_view;
+	texture.is_proxy = false;
+
+	texture_owner.initialize_rid(p_texture, texture);
+}
+
+void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
+	ERR_FAIL_COND(p_data.size() == 0);
+
+	Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data);
+	if (verr != Image::VALIDATE_3D_OK) {
+		ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr));
+	}
+
+	TextureToRDFormat ret_format;
+	Image::Format validated_format = Image::FORMAT_MAX;
+	Vector<uint8_t> all_data;
+	uint32_t mipmap_count = 0;
+	Vector<Texture::BufferSlice3D> slices;
+	{
+		Vector<Ref<Image>> images;
+		uint32_t all_data_size = 0;
+		images.resize(p_data.size());
+		for (int i = 0; i < p_data.size(); i++) {
+			TextureToRDFormat f;
+			images.write[i] = _validate_texture_format(p_data[i], f);
+			if (i == 0) {
+				ret_format = f;
+				validated_format = images[0]->get_format();
+			}
+
+			all_data_size += images[i]->get_data().size();
+		}
+
+		all_data.resize(all_data_size); //consolidate all data here
+		uint32_t offset = 0;
+		Size2i prev_size;
+		for (int i = 0; i < p_data.size(); i++) {
+			uint32_t s = images[i]->get_data().size();
+
+			memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s);
+			{
+				Texture::BufferSlice3D slice;
+				slice.size.width = images[i]->get_width();
+				slice.size.height = images[i]->get_height();
+				slice.offset = offset;
+				slice.buffer_size = s;
+				slices.push_back(slice);
+			}
+			offset += s;
+
+			Size2i img_size(images[i]->get_width(), images[i]->get_height());
+			if (img_size != prev_size) {
+				mipmap_count++;
+			}
+			prev_size = img_size;
+		}
+	}
+
+	Texture texture;
+
+	texture.type = Texture::TYPE_3D;
+	texture.width = p_width;
+	texture.height = p_height;
+	texture.depth = p_depth;
+	texture.mipmaps = mipmap_count;
+	texture.format = p_data[0]->get_format();
+	texture.validated_format = validated_format;
+
+	texture.buffer_size_3d = all_data.size();
+	texture.buffer_slices_3d = slices;
+
+	texture.rd_type = RD::TEXTURE_TYPE_3D;
+	texture.rd_format = ret_format.format;
+	texture.rd_format_srgb = ret_format.format_srgb;
+
+	RD::TextureFormat rd_format;
+	RD::TextureView rd_view;
+	{ //attempt register
+		rd_format.format = texture.rd_format;
+		rd_format.width = texture.width;
+		rd_format.height = texture.height;
+		rd_format.depth = texture.depth;
+		rd_format.array_layers = 1;
+		rd_format.mipmaps = texture.mipmaps;
+		rd_format.texture_type = texture.rd_type;
+		rd_format.samples = RD::TEXTURE_SAMPLES_1;
+		rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+		if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+			rd_format.shareable_formats.push_back(texture.rd_format);
+			rd_format.shareable_formats.push_back(texture.rd_format_srgb);
+		}
+	}
+	{
+		rd_view.swizzle_r = ret_format.swizzle_r;
+		rd_view.swizzle_g = ret_format.swizzle_g;
+		rd_view.swizzle_b = ret_format.swizzle_b;
+		rd_view.swizzle_a = ret_format.swizzle_a;
+	}
+	Vector<Vector<uint8_t>> data_slices;
+	data_slices.push_back(all_data); //one slice
+
+	texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
+	ERR_FAIL_COND(texture.rd_texture.is_null());
+	if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+		rd_view.format_override = texture.rd_format_srgb;
+		texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
+		if (texture.rd_texture_srgb.is_null()) {
+			RD::get_singleton()->free(texture.rd_texture);
+			ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
+		}
+	}
+
+	//used for 2D, overridable
+	texture.width_2d = texture.width;
+	texture.height_2d = texture.height;
+	texture.is_render_target = false;
+	texture.rd_view = rd_view;
+	texture.is_proxy = false;
+
+	texture_owner.initialize_rid(p_texture, texture);
+}
+
+void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
+	Texture *tex = texture_owner.get_or_null(p_base);
+	ERR_FAIL_COND(!tex);
+	Texture proxy_tex = *tex;
+
+	proxy_tex.rd_view.format_override = tex->rd_format;
+	proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture);
+	if (proxy_tex.rd_texture_srgb.is_valid()) {
+		proxy_tex.rd_view.format_override = tex->rd_format_srgb;
+		proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture);
+	}
+	proxy_tex.proxy_to = p_base;
+	proxy_tex.is_render_target = false;
+	proxy_tex.is_proxy = true;
+	proxy_tex.proxies.clear();
+
+	texture_owner.initialize_rid(p_texture, proxy_tex);
+
+	tex->proxies.push_back(p_texture);
+}
+
+void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) {
+	ERR_FAIL_COND(p_image.is_null() || p_image->is_empty());
+
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+	ERR_FAIL_COND(tex->is_render_target);
+	ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height);
+	ERR_FAIL_COND(p_image->get_format() != tex->format);
+
+	if (tex->type == Texture::TYPE_LAYERED) {
+		ERR_FAIL_INDEX(p_layer, tex->layers);
+	}
+
+#ifdef TOOLS_ENABLED
+	tex->image_cache_2d.unref();
+#endif
+	TextureToRDFormat f;
+	Ref<Image> validated = _validate_texture_format(p_image, f);
+
+	RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data());
+}
+
+void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) {
+	_texture_2d_update(p_texture, p_image, p_layer, false);
+}
+
+void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+	ERR_FAIL_COND(tex->type != Texture::TYPE_3D);
+
+	Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data);
+	if (verr != Image::VALIDATE_3D_OK) {
+		ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr));
+	}
+
+	Vector<uint8_t> all_data;
+	{
+		Vector<Ref<Image>> images;
+		uint32_t all_data_size = 0;
+		images.resize(p_data.size());
+		for (int i = 0; i < p_data.size(); i++) {
+			Ref<Image> image = p_data[i];
+			if (image->get_format() != tex->validated_format) {
+				image = image->duplicate();
+				image->convert(tex->validated_format);
+			}
+			all_data_size += images[i]->get_data().size();
+			images.push_back(image);
+		}
+
+		all_data.resize(all_data_size); //consolidate all data here
+		uint32_t offset = 0;
+
+		for (int i = 0; i < p_data.size(); i++) {
+			uint32_t s = images[i]->get_data().size();
+			memcpy(&all_data.write[offset], images[i]->get_data().ptr(), s);
+			offset += s;
+		}
+	}
+
+	RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data);
+}
+
+void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+	ERR_FAIL_COND(!tex->is_proxy);
+	Texture *proxy_to = texture_owner.get_or_null(p_proxy_to);
+	ERR_FAIL_COND(!proxy_to);
+	ERR_FAIL_COND(proxy_to->is_proxy);
+
+	if (tex->proxy_to.is_valid()) {
+		//unlink proxy
+		if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
+			RD::get_singleton()->free(tex->rd_texture);
+			tex->rd_texture = RID();
+		}
+		if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
+			RD::get_singleton()->free(tex->rd_texture_srgb);
+			tex->rd_texture_srgb = RID();
+		}
+		Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to);
+		ERR_FAIL_COND(!prev_tex);
+		prev_tex->proxies.erase(p_texture);
+	}
+
+	*tex = *proxy_to;
+
+	tex->proxy_to = p_proxy_to;
+	tex->is_render_target = false;
+	tex->is_proxy = true;
+	tex->proxies.clear();
+	proxy_to->proxies.push_back(p_texture);
+
+	tex->rd_view.format_override = tex->rd_format;
+	tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture);
+	if (tex->rd_texture_srgb.is_valid()) {
+		tex->rd_view.format_override = tex->rd_format_srgb;
+		tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture);
+	}
+}
+
+//these two APIs can be used together or in combination with the others.
+void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
+	//this could be better optimized to reuse an existing image , done this way
+	//for now to get it working
+	Ref<Image> image;
+	image.instantiate();
+	image->create(4, 4, false, Image::FORMAT_RGBA8);
+	image->fill(Color(1, 0, 1, 1));
+
+	texture_2d_initialize(p_texture, image);
+}
+
+void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) {
+	//this could be better optimized to reuse an existing image , done this way
+	//for now to get it working
+	Ref<Image> image;
+	image.instantiate();
+	image->create(4, 4, false, Image::FORMAT_RGBA8);
+	image->fill(Color(1, 0, 1, 1));
+
+	Vector<Ref<Image>> images;
+	if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
+		images.push_back(image);
+	} else {
+		//cube
+		for (int i = 0; i < 6; i++) {
+			images.push_back(image);
+		}
+	}
+
+	texture_2d_layered_initialize(p_texture, images, p_layered_type);
+}
+
+void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
+	//this could be better optimized to reuse an existing image , done this way
+	//for now to get it working
+	Ref<Image> image;
+	image.instantiate();
+	image->create(4, 4, false, Image::FORMAT_RGBA8);
+	image->fill(Color(1, 0, 1, 1));
+
+	Vector<Ref<Image>> images;
+	//cube
+	for (int i = 0; i < 4; i++) {
+		images.push_back(image);
+	}
+
+	texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
+}
+
+Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND_V(!tex, Ref<Image>());
+
+#ifdef TOOLS_ENABLED
+	if (tex->image_cache_2d.is_valid() && !tex->is_render_target) {
+		return tex->image_cache_2d;
+	}
+#endif
+	Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
+	ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
+	Ref<Image> image;
+	image.instantiate();
+	image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+	ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
+	if (tex->format != tex->validated_format) {
+		image->convert(tex->format);
+	}
+
+#ifdef TOOLS_ENABLED
+	if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) {
+		tex->image_cache_2d = image;
+	}
+#endif
+
+	return image;
+}
+
+Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) const {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND_V(!tex, Ref<Image>());
+
+	Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer);
+	ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
+	Ref<Image> image;
+	image.instantiate();
+	image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+	ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
+	if (tex->format != tex->validated_format) {
+		image->convert(tex->format);
+	}
+
+	return image;
+}
+
+Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>());
+	ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>());
+
+	Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
+
+	ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>());
+
+	Vector<Ref<Image>> ret;
+
+	for (int i = 0; i < tex->buffer_slices_3d.size(); i++) {
+		const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i];
+		ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>());
+		ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>());
+		Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size);
+
+		Ref<Image> img;
+		img.instantiate();
+		img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region);
+		ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>());
+		if (tex->format != tex->validated_format) {
+			img->convert(tex->format);
+		}
+
+		ret.push_back(img);
+	}
+
+	return ret;
+}
+
+void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+	ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy
+	Texture *by_tex = texture_owner.get_or_null(p_by_texture);
+	ERR_FAIL_COND(!by_tex);
+	ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy
+
+	if (tex == by_tex) {
+		return;
+	}
+
+	if (tex->rd_texture_srgb.is_valid()) {
+		RD::get_singleton()->free(tex->rd_texture_srgb);
+	}
+	RD::get_singleton()->free(tex->rd_texture);
+
+	if (tex->canvas_texture) {
+		memdelete(tex->canvas_texture);
+		tex->canvas_texture = nullptr;
+	}
+
+	Vector<RID> proxies_to_update = tex->proxies;
+	Vector<RID> proxies_to_redirect = by_tex->proxies;
+
+	*tex = *by_tex;
+
+	tex->proxies = proxies_to_update; //restore proxies, so they can be updated
+
+	if (tex->canvas_texture) {
+		tex->canvas_texture->diffuse = p_texture; //update
+	}
+
+	for (int i = 0; i < proxies_to_update.size(); i++) {
+		texture_proxy_update(proxies_to_update[i], p_texture);
+	}
+	for (int i = 0; i < proxies_to_redirect.size(); i++) {
+		texture_proxy_update(proxies_to_redirect[i], p_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);
+}
+
+void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+	ERR_FAIL_COND(tex->type != Texture::TYPE_2D);
+
+	tex->width_2d = p_width;
+	tex->height_2d = p_height;
+}
+
+void TextureStorage::texture_set_path(RID p_texture, const String &p_path) {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+
+	tex->path = p_path;
+}
+
+String TextureStorage::texture_get_path(RID p_texture) const {
+	RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND_V(!tex, String());
+
+	return tex->path;
+}
+
+void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+
+	tex->detect_3d_callback_ud = p_userdata;
+	tex->detect_3d_callback = p_callback;
+}
+
+void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+
+	tex->detect_normal_callback_ud = p_userdata;
+	tex->detect_normal_callback = p_callback;
+}
+
+void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) {
+	Texture *tex = texture_owner.get_or_null(p_texture);
+	ERR_FAIL_COND(!tex);
+
+	tex->detect_roughness_callback_ud = p_userdata;
+	tex->detect_roughness_callback = p_callback;
+}
+
+void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
+}
+
+void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
+}
+
+Size2 TextureStorage::texture_size_with_proxy(RID p_proxy) {
+	return texture_2d_get_size(p_proxy);
+}
+
+Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) {
+	Ref<Image> image = p_image->duplicate();
+
+	switch (p_image->get_format()) {
+		case Image::FORMAT_L8: {
+			r_format.format = RD::DATA_FORMAT_R8_UNORM;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break; //luminance
+		case Image::FORMAT_LA8: {
+			r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G;
+		} break; //luminance-alpha
+		case Image::FORMAT_R8: {
+			r_format.format = RD::DATA_FORMAT_R8_UNORM;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break;
+		case Image::FORMAT_RG8: {
+			r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break;
+		case Image::FORMAT_RGB8: {
+			//this format is not mandatory for specification, check if supported first
+			if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+		} break;
+		case Image::FORMAT_RGBA8: {
+			r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+			r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+		} break;
+		case Image::FORMAT_RGBA4444: {
+			r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+		} break;
+		case Image::FORMAT_RGB565: {
+			r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+		} break;
+		case Image::FORMAT_RF: {
+			r_format.format = RD::DATA_FORMAT_R32_SFLOAT;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break; //float
+		case Image::FORMAT_RGF: {
+			r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break;
+		case Image::FORMAT_RGBF: {
+			//this format is not mandatory for specification, check if supported first
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+				image->convert(Image::FORMAT_RGBAF);
+			}
+
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break;
+		case Image::FORMAT_RGBAF: {
+			r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+		} break;
+		case Image::FORMAT_RH: {
+			r_format.format = RD::DATA_FORMAT_R16_SFLOAT;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+		} break; //half float
+		case Image::FORMAT_RGH: {
+			r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+		} break;
+		case Image::FORMAT_RGBH: {
+			//this format is not mandatory for specification, check if supported first
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+				image->convert(Image::FORMAT_RGBAH);
+			}
+
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break;
+		case Image::FORMAT_RGBAH: {
+			r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+		} break;
+		case Image::FORMAT_RGBE9995: {
+			r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
+#ifndef _MSC_VER
+#warning TODO need to make a function in Image to swap bits for this
+#endif
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY;
+		} break;
+		case Image::FORMAT_DXT1: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK;
+				r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+		} break; //s3tc bc1
+		case Image::FORMAT_DXT3: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK;
+				r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+		} break; //bc2
+		case Image::FORMAT_DXT5: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
+				r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+		} break; //bc3
+		case Image::FORMAT_RGTC_R: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8_UNORM;
+				image->decompress();
+				image->convert(Image::FORMAT_R8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+		} break;
+		case Image::FORMAT_RGTC_RG: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
+				image->decompress();
+				image->convert(Image::FORMAT_RG8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+		} break;
+		case Image::FORMAT_BPTC_RGBA: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK;
+				r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+
+		} break; //btpc bc7
+		case Image::FORMAT_BPTC_RGBF: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBAH);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break; //float bc6h
+		case Image::FORMAT_BPTC_RGBFU: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBAH);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break; //unsigned float bc6hu
+		case Image::FORMAT_ETC2_R11: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8_UNORM;
+				image->decompress();
+				image->convert(Image::FORMAT_R8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+		} break; //etc2
+		case Image::FORMAT_ETC2_R11S: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8_SNORM;
+				image->decompress();
+				image->convert(Image::FORMAT_R8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break; //signed: {} break; NOT srgb.
+		case Image::FORMAT_ETC2_RG11: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8_UNORM;
+				image->decompress();
+				image->convert(Image::FORMAT_RG8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break;
+		case Image::FORMAT_ETC2_RG11S: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8_SNORM;
+				image->decompress();
+				image->convert(Image::FORMAT_RG8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break;
+		case Image::FORMAT_ETC:
+		case Image::FORMAT_ETC2_RGB8: {
+			//ETC2 is backwards compatible with ETC1, and all modern platforms support it
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
+				r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+
+		} break;
+		case Image::FORMAT_ETC2_RGBA8: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
+				r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+		} break;
+		case Image::FORMAT_ETC2_RGB8A1: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
+				r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
+		} break;
+		case Image::FORMAT_ETC2_RA_AS_RG: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
+				r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break;
+		case Image::FORMAT_DXT5_RA_AS_RG: {
+			if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
+				r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
+				r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK;
+			} else {
+				//not supported, reconvert
+				r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+				r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+				image->decompress();
+				image->convert(Image::FORMAT_RGBA8);
+			}
+			r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A;
+			r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO;
+			r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+		} break;
+
+		default: {
+		}
+	}
+
+	return image;
+}

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

@@ -0,0 +1,230 @@
+/*************************************************************************/
+/*  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 TEXTURE_STORAGE_RD_H
+#define TEXTURE_STORAGE_RD_H
+
+#include "canvas_texture_storage.h"
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/storage/texture_storage.h"
+
+namespace RendererRD {
+
+enum DefaultRDTexture {
+	DEFAULT_RD_TEXTURE_WHITE,
+	DEFAULT_RD_TEXTURE_BLACK,
+	DEFAULT_RD_TEXTURE_NORMAL,
+	DEFAULT_RD_TEXTURE_ANISO,
+	DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
+	DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
+	DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
+	DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
+	DEFAULT_RD_TEXTURE_3D_WHITE,
+	DEFAULT_RD_TEXTURE_3D_BLACK,
+	DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
+	DEFAULT_RD_TEXTURE_2D_UINT,
+	DEFAULT_RD_TEXTURE_MAX
+};
+
+class Texture {
+public:
+	enum Type {
+		TYPE_2D,
+		TYPE_LAYERED,
+		TYPE_3D
+	};
+
+	Type type;
+	RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
+
+	RenderingDevice::TextureType rd_type;
+	RID rd_texture;
+	RID rd_texture_srgb;
+	RenderingDevice::DataFormat rd_format;
+	RenderingDevice::DataFormat rd_format_srgb;
+
+	RD::TextureView rd_view;
+
+	Image::Format format;
+	Image::Format validated_format;
+
+	int width;
+	int height;
+	int depth;
+	int layers;
+	int mipmaps;
+
+	int height_2d;
+	int width_2d;
+
+	struct BufferSlice3D {
+		Size2i size;
+		uint32_t offset = 0;
+		uint32_t buffer_size = 0;
+	};
+	Vector<BufferSlice3D> buffer_slices_3d;
+	uint32_t buffer_size_3d = 0;
+
+	bool is_render_target;
+	bool is_proxy;
+
+	Ref<Image> image_cache_2d;
+	String path;
+
+	RID proxy_to;
+	Vector<RID> proxies;
+
+	Set<RID> lightmap_users;
+
+	RS::TextureDetectCallback detect_3d_callback = nullptr;
+	void *detect_3d_callback_ud = nullptr;
+
+	RS::TextureDetectCallback detect_normal_callback = nullptr;
+	void *detect_normal_callback_ud = nullptr;
+
+	RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
+	void *detect_roughness_callback_ud = nullptr;
+
+	CanvasTexture *canvas_texture = nullptr;
+
+	void cleanup();
+};
+
+class TextureStorage : public RendererTextureStorage {
+private:
+	static TextureStorage *singleton;
+
+	//textures can be created from threads, so this RID_Owner is thread safe
+	mutable RID_Owner<Texture, true> texture_owner;
+
+	struct TextureToRDFormat {
+		RD::DataFormat format;
+		RD::DataFormat format_srgb;
+		RD::TextureSwizzle swizzle_r;
+		RD::TextureSwizzle swizzle_g;
+		RD::TextureSwizzle swizzle_b;
+		RD::TextureSwizzle swizzle_a;
+		TextureToRDFormat() {
+			format = RD::DATA_FORMAT_MAX;
+			format_srgb = RD::DATA_FORMAT_MAX;
+			swizzle_r = RD::TEXTURE_SWIZZLE_R;
+			swizzle_g = RD::TEXTURE_SWIZZLE_G;
+			swizzle_b = RD::TEXTURE_SWIZZLE_B;
+			swizzle_a = RD::TEXTURE_SWIZZLE_A;
+		}
+	};
+
+	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);
+
+public:
+	static TextureStorage *get_singleton();
+
+	RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
+
+	_FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
+		return default_rd_textures[p_texture];
+	}
+
+	TextureStorage();
+	virtual ~TextureStorage();
+
+	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); };
+
+	virtual bool can_create_resources_async() const override;
+
+	virtual RID texture_allocate() override;
+	virtual void texture_free(RID p_rid) override;
+
+	virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
+	virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
+	virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
+	virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
+
+	virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
+	virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
+	virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
+
+	//these two APIs can be used together or in combination with the others.
+	virtual void texture_2d_placeholder_initialize(RID p_texture) override;
+	virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
+	virtual void texture_3d_placeholder_initialize(RID p_texture) override;
+
+	virtual Ref<Image> texture_2d_get(RID p_texture) const override;
+	virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override;
+	virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override;
+
+	virtual void texture_replace(RID p_texture, RID p_by_texture) override;
+	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override;
+
+	virtual void texture_set_path(RID p_texture, const String &p_path) override;
+	virtual String texture_get_path(RID p_texture) const override;
+
+	virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
+	virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
+	virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override;
+
+	virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override;
+
+	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;
+
+	//internal usage
+
+	_FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
+		if (p_texture.is_null()) {
+			return RID();
+		}
+		RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+
+		if (!tex) {
+			return RID();
+		}
+		return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
+	}
+
+	_FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) {
+		if (p_texture.is_null()) {
+			return Size2i();
+		}
+		RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+
+		if (!tex) {
+			return Size2i();
+		}
+		return Size2i(tex->width_2d, tex->height_2d);
+	}
+};
+
+} // namespace RendererRD
+
+#endif // !_TEXTURE_STORAGE_RD_H

+ 3 - 53
servers/rendering/renderer_storage.h

@@ -121,59 +121,6 @@ public:
 		Set<Dependency *> dependencies;
 	};
 
-	virtual bool can_create_resources_async() const = 0;
-	/* TEXTURE API */
-
-	virtual RID texture_allocate() = 0;
-
-	virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0;
-	virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0;
-	virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
-	virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
-
-	virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
-	virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
-	virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;
-
-	//these two APIs can be used together or in combination with the others.
-	virtual void texture_2d_placeholder_initialize(RID p_texture) = 0;
-	virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0;
-	virtual void texture_3d_placeholder_initialize(RID p_texture) = 0;
-
-	virtual Ref<Image> texture_2d_get(RID p_texture) const = 0;
-	virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0;
-	virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0;
-
-	virtual void texture_replace(RID p_texture, RID p_by_texture) = 0;
-	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0;
-
-	virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
-	virtual String texture_get_path(RID p_texture) const = 0;
-
-	virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0;
-	virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0;
-	virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0;
-
-	virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0;
-
-	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;
-
-	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;
-
-	/* CANVAS TEXTURE API */
-
-	virtual RID canvas_texture_allocate() = 0;
-	virtual void canvas_texture_initialize(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;
-
 	/* SHADER API */
 
 	virtual RID shader_allocate() = 0;
@@ -397,6 +344,9 @@ public:
 
 	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 - 1
servers/rendering/renderer_viewport.cpp

@@ -293,7 +293,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
 				RendererCanvasRender::Light *cl = F->get();
 				if (cl->enabled && cl->texture.is_valid()) {
 					//not super efficient..
-					Size2 tsize = RSG::storage->texture_size_with_proxy(cl->texture);
+					Size2 tsize = RSG::texture_storage->texture_size_with_proxy(cl->texture);
 					tsize *= cl->scale;
 
 					Vector2 offset = tsize / 2.0;

+ 2 - 0
servers/rendering/rendering_server_default.cpp

@@ -398,6 +398,8 @@ 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::texture_storage = RSG::rasterizer->get_texture_storage();
 	RSG::storage = RSG::rasterizer->get_storage();
 	RSG::canvas_render = RSG::rasterizer->get_canvas();
 	sr->set_scene_render(RSG::rasterizer->get_scene());

+ 49 - 41
servers/rendering/rendering_server_default.h

@@ -126,54 +126,53 @@ public:
 
 #include "servers/server_wrap_mt_common.h"
 
-//from now on, calls forwarded to this singleton
-#define ServerName RendererStorage
-#define server_name RSG::storage
-
 	/* TEXTURE API */
 
-#define FUNCRIDTEX0(m_type)                                                                           \
-	virtual RID m_type##_create() override {                                                          \
-		RID ret = RSG::storage->texture_allocate();                                                   \
-		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
-			RSG::storage->m_type##_initialize(ret);                                                   \
-		} else {                                                                                      \
-			command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret);             \
-		}                                                                                             \
-		return ret;                                                                                   \
+#define ServerName RendererTextureStorage
+#define server_name RSG::texture_storage
+
+#define FUNCRIDTEX0(m_type)                                                                                   \
+	virtual RID m_type##_create() override {                                                                  \
+		RID ret = RSG::texture_storage->texture_allocate();                                                   \
+		if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \
+			RSG::texture_storage->m_type##_initialize(ret);                                                   \
+		} else {                                                                                              \
+			command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret);      \
+		}                                                                                                     \
+		return ret;                                                                                           \
 	}
 
-#define FUNCRIDTEX1(m_type, m_type1)                                                                  \
-	virtual RID m_type##_create(m_type1 p1) override {                                                \
-		RID ret = RSG::storage->texture_allocate();                                                   \
-		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
-			RSG::storage->m_type##_initialize(ret, p1);                                               \
-		} else {                                                                                      \
-			command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1);         \
-		}                                                                                             \
-		return ret;                                                                                   \
+#define FUNCRIDTEX1(m_type, m_type1)                                                                          \
+	virtual RID m_type##_create(m_type1 p1) override {                                                        \
+		RID ret = RSG::texture_storage->texture_allocate();                                                   \
+		if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \
+			RSG::texture_storage->m_type##_initialize(ret, p1);                                               \
+		} else {                                                                                              \
+			command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1);  \
+		}                                                                                                     \
+		return ret;                                                                                           \
 	}
 
-#define FUNCRIDTEX2(m_type, m_type1, m_type2)                                                         \
-	virtual RID m_type##_create(m_type1 p1, m_type2 p2) override {                                    \
-		RID ret = RSG::storage->texture_allocate();                                                   \
-		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) { \
-			RSG::storage->m_type##_initialize(ret, p1, p2);                                           \
-		} else {                                                                                      \
-			command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2);     \
-		}                                                                                             \
-		return ret;                                                                                   \
+#define FUNCRIDTEX2(m_type, m_type1, m_type2)                                                                    \
+	virtual RID m_type##_create(m_type1 p1, m_type2 p2) override {                                               \
+		RID ret = RSG::texture_storage->texture_allocate();                                                      \
+		if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) {    \
+			RSG::texture_storage->m_type##_initialize(ret, p1, p2);                                              \
+		} else {                                                                                                 \
+			command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2); \
+		}                                                                                                        \
+		return ret;                                                                                              \
 	}
 
-#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6)                                  \
-	virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \
-		RID ret = RSG::storage->texture_allocate();                                                                \
-		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) {              \
-			RSG::storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6);                                        \
-		} else {                                                                                                   \
-			command_queue.push(RSG::storage, &RendererStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6);  \
-		}                                                                                                          \
-		return ret;                                                                                                \
+#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6)                                                \
+	virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override {               \
+		RID ret = RSG::texture_storage->texture_allocate();                                                                      \
+		if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) {                    \
+			RSG::texture_storage->m_type##_initialize(ret, p1, p2, p3, p4, p5, p6);                                              \
+		} else {                                                                                                                 \
+			command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5, p6); \
+		}                                                                                                                        \
+		return ret;                                                                                                              \
 	}
 
 	//these go pass-through, as they can be called from any thread
@@ -214,6 +213,13 @@ public:
 
 	FUNC2(texture_set_force_redraw_if_visible, RID, bool)
 
+//from now on, calls forwarded to this singleton
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererStorage
+#define server_name RSG::storage
+
 	/* SHADER API */
 
 	FUNCRIDSPLIT(shader)
@@ -246,7 +252,9 @@ public:
 	virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override {
 		RID mesh = RSG::storage->mesh_allocate();
 
-		if (Thread::get_caller_id() == server_thread || RSG::storage->can_create_resources_async()) {
+		// TODO once we have RSG::mesh_storage, add can_create_resources_async and call here instead of texture_storage!!
+
+		if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) {
 			if (Thread::get_caller_id() == server_thread) {
 				command_queue.flush_if_pending();
 			}

+ 2 - 0
servers/rendering/rendering_server_globals.cpp

@@ -32,6 +32,8 @@
 
 bool RenderingServerGlobals::threaded = false;
 
+RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr;
+RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr;
 RendererStorage *RenderingServerGlobals::storage = nullptr;
 RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;
 RendererCompositor *RenderingServerGlobals::rasterizer = nullptr;

+ 4 - 0
servers/rendering/rendering_server_globals.h

@@ -34,6 +34,8 @@
 #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/texture_storage.h"
 
 class RendererCanvasCull;
 class RendererViewport;
@@ -43,6 +45,8 @@ class RenderingServerGlobals {
 public:
 	static bool threaded;
 
+	static RendererCanvasTextureStorage *canvas_texture_storage;
+	static RendererTextureStorage *texture_storage;
 	static RendererStorage *storage;
 	static RendererCanvasRender *canvas_render;
 	static RendererCompositor *rasterizer;

+ 5 - 0
servers/rendering/storage/SCsub

@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")

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

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

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

@@ -0,0 +1,80 @@
+/*************************************************************************/
+/*  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 TEXTURE_STORAGE_H
+#define TEXTURE_STORAGE_H
+
+#include "servers/rendering_server.h"
+
+class RendererTextureStorage {
+public:
+	virtual bool can_create_resources_async() const = 0;
+
+	virtual ~RendererTextureStorage(){};
+
+	virtual RID texture_allocate() = 0;
+	virtual void texture_free(RID p_rid) = 0;
+
+	virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0;
+	virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0;
+	virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
+	virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
+
+	virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
+	virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
+	virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;
+
+	//these two APIs can be used together or in combination with the others.
+	virtual void texture_2d_placeholder_initialize(RID p_texture) = 0;
+	virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0;
+	virtual void texture_3d_placeholder_initialize(RID p_texture) = 0;
+
+	virtual Ref<Image> texture_2d_get(RID p_texture) const = 0;
+	virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0;
+	virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0;
+
+	virtual void texture_replace(RID p_texture, RID p_by_texture) = 0;
+	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0;
+
+	virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
+	virtual String texture_get_path(RID p_texture) const = 0;
+
+	virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0;
+	virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0;
+	virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0;
+
+	virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0;
+
+	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;
+};
+
+#endif // !TEXTURE_STORAGE_H

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio