Browse Source

Merge pull request #59385 from BastiaanOlij/extract_shader_storage

Rémi Verschelde 3 years ago
parent
commit
155a94fabe
38 changed files with 4537 additions and 3375 deletions
  1. 29 13
      drivers/gles3/rasterizer_canvas_gles3.cpp
  2. 5 2
      drivers/gles3/rasterizer_canvas_gles3.h
  3. 2 2
      drivers/gles3/rasterizer_gles3.cpp
  4. 3 0
      drivers/gles3/rasterizer_gles3.h
  5. 11 861
      drivers/gles3/rasterizer_storage_gles3.cpp
  6. 6 264
      drivers/gles3/rasterizer_storage_gles3.h
  7. 913 0
      drivers/gles3/storage/material_storage.cpp
  8. 338 0
      drivers/gles3/storage/material_storage.h
  9. 3 0
      servers/rendering/dummy/rasterizer_dummy.h
  10. 2 51
      servers/rendering/dummy/rasterizer_storage_dummy.h
  11. 95 0
      servers/rendering/dummy/storage/material_storage.h
  12. 2 0
      servers/rendering/renderer_compositor.h
  13. 18 13
      servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
  14. 28 24
      servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
  15. 7 7
      servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
  16. 17 13
      servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
  17. 28 24
      servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
  18. 7 7
      servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
  19. 44 37
      servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
  20. 12 16
      servers/rendering/renderer_rd/renderer_canvas_render_rd.h
  21. 2 0
      servers/rendering/renderer_rd/renderer_compositor_rd.cpp
  22. 4 1
      servers/rendering/renderer_rd/renderer_compositor_rd.h
  23. 34 33
      servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
  24. 7 9
      servers/rendering/renderer_rd/renderer_scene_render_rd.h
  25. 54 35
      servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
  26. 7 7
      servers/rendering/renderer_rd/renderer_scene_sky_rd.h
  27. 0 1619
      servers/rendering/renderer_rd/renderer_storage_rd.cpp
  28. 9 245
      servers/rendering/renderer_rd/renderer_storage_rd.h
  29. 2392 0
      servers/rendering/renderer_rd/storage_rd/material_storage.cpp
  30. 315 0
      servers/rendering/renderer_rd/storage_rd/material_storage.h
  31. 1 1
      servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
  32. 24 24
      servers/rendering/renderer_scene_cull.cpp
  33. 0 60
      servers/rendering/renderer_storage.h
  34. 1 0
      servers/rendering/rendering_server_default.cpp
  35. 13 7
      servers/rendering/rendering_server_default.h
  36. 1 0
      servers/rendering/rendering_server_globals.cpp
  37. 2 0
      servers/rendering/rendering_server_globals.h
  38. 101 0
      servers/rendering/storage/material_storage.h

+ 29 - 13
drivers/gles3/rasterizer_canvas_gles3.cpp

@@ -40,6 +40,7 @@
 #include "servers/rendering/rendering_server_default.h"
 #include "storage/canvas_texture_storage.h"
 #include "storage/config.h"
+#include "storage/material_storage.h"
 
 #ifndef GLES_OVER_GL
 #define glClearDepth glClearDepthf
@@ -212,6 +213,8 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
 }
 
 void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+	GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
 	Item *current_clip = nullptr;
 
 	Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
@@ -228,14 +231,14 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
 		Item *ci = items[i];
 
 		RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
-		RasterizerStorageGLES3::Material *material_ptr = storage->material_owner.get_or_null(material);
+		GLES3::Material *material_ptr = material_storage->get_material(material);
 
 		if (material.is_null() && ci->canvas_group != nullptr) {
 			material = default_canvas_group_material;
 		}
 
 		if (material != prev_material) {
-			RasterizerStorageGLES3::Shader *shader_ptr = nullptr;
+			GLES3::Shader *shader_ptr = nullptr;
 
 			if (material_ptr) {
 				shader_ptr = material_ptr->shader;
@@ -906,6 +909,8 @@ void RasterizerCanvasGLES3::canvas_end() {
 }
 
 void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, RID &r_last_texture, Size2 &r_texpixel_size) {
+	GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
 	if (p_texture == RID()) {
 		p_texture = default_canvas_texture;
 	}
@@ -1251,9 +1256,8 @@ 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();
+	GLES3::CanvasTextureStorage *canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+	GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
 
 	// quad buffer
 	{
@@ -1423,10 +1427,10 @@ void RasterizerCanvasGLES3::initialize() {
 	//state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/quality/2d/use_pixel_snap", false));
 
 	{
-		default_canvas_group_shader = storage->shader_allocate();
-		storage->shader_initialize(default_canvas_group_shader);
+		default_canvas_group_shader = material_storage->shader_allocate();
+		material_storage->shader_initialize(default_canvas_group_shader);
 
-		storage->shader_set_code(default_canvas_group_shader, R"(
+		material_storage->shader_set_code(default_canvas_group_shader, R"(
 // Default CanvasGroup shader.
 
 shader_type canvas_item;
@@ -1441,10 +1445,10 @@ void fragment() {
 	COLOR *= c;
 }
 )");
-		default_canvas_group_material = storage->material_allocate();
-		storage->material_initialize(default_canvas_group_material);
+		default_canvas_group_material = material_storage->material_allocate();
+		material_storage->material_initialize(default_canvas_group_material);
 
-		storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
+		material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
 	}
 
 	default_canvas_texture = canvas_texture_storage->canvas_texture_allocate();
@@ -1456,13 +1460,25 @@ void fragment() {
 	state.current_shader_version = state.canvas_shader_default_version;
 }
 
+RasterizerCanvasGLES3 *RasterizerCanvasGLES3::singleton = nullptr;
+
+RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() {
+	return singleton;
+}
+
 RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
+	singleton = this;
 }
+
 RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
+	GLES3::CanvasTextureStorage *canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+	GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+
 	state.canvas_shader.version_free(state.canvas_shader_default_version);
-	storage->free(default_canvas_group_material);
-	storage->free(default_canvas_group_shader);
+	material_storage->material_free(default_canvas_group_material);
+	material_storage->shader_free(default_canvas_group_shader);
 	canvas_texture_storage->canvas_texture_free(default_canvas_texture);
+	singleton = nullptr;
 }
 
 void RasterizerCanvasGLES3::finalize() {

+ 5 - 2
drivers/gles3/rasterizer_canvas_gles3.h

@@ -38,6 +38,7 @@
 #include "servers/rendering/renderer_canvas_render.h"
 #include "servers/rendering/renderer_compositor.h"
 #include "storage/canvas_texture_storage.h"
+#include "storage/material_storage.h"
 #include "storage/texture_storage.h"
 
 #include "shaders/canvas.glsl.gen.h"
@@ -45,6 +46,8 @@
 class RasterizerSceneGLES3;
 
 class RasterizerCanvasGLES3 : public RendererCanvasRender {
+	static RasterizerCanvasGLES3 *singleton;
+
 	_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
 	_FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3);
 
@@ -219,8 +222,6 @@ public:
 
 	RasterizerSceneGLES3 *scene_render;
 
-	GLES3::CanvasTextureStorage *canvas_texture_storage;
-	GLES3::TextureStorage *texture_storage;
 	RasterizerStorageGLES3 *storage;
 
 	void _set_uniforms();
@@ -277,6 +278,8 @@ public:
 
 	void initialize();
 	void finalize();
+
+	static RasterizerCanvasGLES3 *get_singleton();
 	RasterizerCanvasGLES3();
 	~RasterizerCanvasGLES3();
 };

+ 2 - 2
drivers/gles3/rasterizer_gles3.cpp

@@ -260,9 +260,9 @@ void RasterizerGLES3::initialize() {
 RasterizerGLES3::RasterizerGLES3() {
 	canvas.storage = &storage;
 	canvas.scene_render = &scene;
-	storage.canvas = &canvas;
+	//storage.canvas = &canvas;
 	//scene.storage = &storage;
-	storage.scene = &scene;
+	//storage.scene = &scene;
 }
 
 void RasterizerGLES3::prepare_for_blitting_render_targets() {

+ 3 - 0
drivers/gles3/rasterizer_gles3.h

@@ -40,6 +40,7 @@
 #include "storage/canvas_texture_storage.h"
 #include "storage/config.h"
 #include "storage/decal_atlas_storage.h"
+#include "storage/material_storage.h"
 #include "storage/render_target_storage.h"
 #include "storage/texture_storage.h"
 
@@ -55,6 +56,7 @@ protected:
 	GLES3::CanvasTextureStorage canvas_texture_storage;
 	GLES3::TextureStorage texture_storage;
 	GLES3::DecalAtlasStorage decal_atlas_storage;
+	GLES3::MaterialStorage material_storage;
 	RasterizerStorageGLES3 storage;
 	RasterizerCanvasGLES3 canvas;
 	RasterizerSceneGLES3 scene;
@@ -63,6 +65,7 @@ protected:
 
 public:
 	RendererCanvasTextureStorage *get_canvas_texture_storage() { return &canvas_texture_storage; }
+	RendererMaterialStorage *get_material_storage() { return &material_storage; }
 	RendererTextureStorage *get_texture_storage() { return &texture_storage; }
 	RendererDecalAtlasStorage *get_decal_atlas_storage() { return &decal_atlas_storage; }
 	RendererStorage *get_storage() { return &storage; }

+ 11 - 861
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -34,7 +34,7 @@
 
 #include "core/config/project_settings.h"
 #include "core/math/transform_3d.h"
-#include "rasterizer_canvas_gles3.h"
+// #include "rasterizer_canvas_gles3.h"
 #include "rasterizer_scene_gles3.h"
 #include "servers/rendering/shader_language.h"
 
@@ -58,755 +58,6 @@ RID RasterizerStorageGLES3::sky_create() {
 void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size) {
 }
 
-/* SHADER API */
-
-RID RasterizerStorageGLES3::shader_allocate() {
-	Shader *shader = memnew(Shader);
-	shader->mode = RS::SHADER_CANVAS_ITEM;
-	//shader->shader = &scene->state.scene_shader;
-	RID rid = shader_owner.make_rid(shader);
-	_shader_make_dirty(shader);
-	shader->self = rid;
-
-	return rid;
-}
-
-void RasterizerStorageGLES3::shader_initialize(RID p_rid) {
-	// noop
-}
-
-//RID RasterizerStorageGLES3::shader_create() {
-//	Shader *shader = memnew(Shader);
-//	shader->mode = RS::SHADER_SPATIAL;
-//	shader->shader = &scene->state.scene_shader;
-//	RID rid = shader_owner.make_rid(shader);
-//	_shader_make_dirty(shader);
-//	shader->self = rid;
-
-//	return rid;
-//}
-
-void RasterizerStorageGLES3::_shader_make_dirty(Shader *p_shader) {
-	if (p_shader->dirty_list.in_list()) {
-		return;
-	}
-
-	_shader_dirty_list.add(&p_shader->dirty_list);
-}
-
-void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String &p_code) {
-	Shader *shader = shader_owner.get_or_null(p_shader);
-	ERR_FAIL_COND(!shader);
-
-	shader->code = p_code;
-
-	String mode_string = ShaderLanguage::get_shader_type(p_code);
-	RS::ShaderMode mode;
-
-	if (mode_string == "canvas_item") {
-		mode = RS::SHADER_CANVAS_ITEM;
-	} else if (mode_string == "particles") {
-		mode = RS::SHADER_PARTICLES;
-	} else if (mode_string == "sky") {
-		mode = RS::SHADER_SKY;
-	} else if (mode_string == "spatial") {
-		mode = RS::SHADER_SPATIAL;
-	} else {
-		mode = RS::SHADER_MAX;
-		ERR_PRINT("shader type " + mode_string + " not supported in OpenGL renderer");
-	}
-
-	if (shader->version.is_valid() && mode != shader->mode) {
-		shader->shader->version_free(shader->version);
-		shader->version = RID();
-	}
-
-	shader->mode = mode;
-
-	// TODO handle all shader types
-	if (mode == RS::SHADER_CANVAS_ITEM) {
-		shader->shader = &canvas->state.canvas_shader;
-
-	} else if (mode == RS::SHADER_SPATIAL) {
-		//shader->shader = &scene->state.scene_shader;
-	} else if (mode == RS::SHADER_PARTICLES) {
-	} else if (mode == RS::SHADER_SKY) {
-	} else {
-		return;
-	}
-
-	if (shader->version.is_null() && shader->shader) {
-		shader->version = shader->shader->version_create();
-	}
-
-	_shader_make_dirty(shader);
-}
-
-String RasterizerStorageGLES3::shader_get_code(RID p_shader) const {
-	const Shader *shader = shader_owner.get_or_null(p_shader);
-	ERR_FAIL_COND_V(!shader, "");
-
-	return shader->code;
-}
-
-void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
-	_shader_dirty_list.remove(&p_shader->dirty_list);
-
-	p_shader->valid = false;
-
-	p_shader->uniforms.clear();
-
-	if (p_shader->code.is_empty()) {
-		return; //just invalid, but no error
-	}
-
-	ShaderCompiler::GeneratedCode gen_code;
-	ShaderCompiler::IdentifierActions *actions = nullptr;
-
-	switch (p_shader->mode) {
-		case RS::SHADER_CANVAS_ITEM: {
-			p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL;
-			p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX;
-
-			p_shader->canvas_item.uses_screen_texture = false;
-			p_shader->canvas_item.uses_screen_uv = false;
-			p_shader->canvas_item.uses_time = false;
-			p_shader->canvas_item.uses_modulate = false;
-			p_shader->canvas_item.uses_color = false;
-			p_shader->canvas_item.uses_vertex = false;
-
-			p_shader->canvas_item.uses_model_matrix = false;
-			p_shader->canvas_item.uses_extra_matrix = false;
-			p_shader->canvas_item.uses_projection_matrix = false;
-			p_shader->canvas_item.uses_instance_custom = false;
-
-			shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD);
-			shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX);
-			shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
-			shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL);
-			shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA);
-
-			shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
-			shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
-
-			shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv;
-			shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv;
-			shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture;
-			shaders.actions_canvas.usage_flag_pointers["TIME"] = &p_shader->canvas_item.uses_time;
-			shaders.actions_canvas.usage_flag_pointers["MODULATE"] = &p_shader->canvas_item.uses_modulate;
-			shaders.actions_canvas.usage_flag_pointers["COLOR"] = &p_shader->canvas_item.uses_color;
-
-			shaders.actions_canvas.usage_flag_pointers["VERTEX"] = &p_shader->canvas_item.uses_vertex;
-
-			shaders.actions_canvas.usage_flag_pointers["MODEL_MATRIX"] = &p_shader->canvas_item.uses_model_matrix;
-			shaders.actions_canvas.usage_flag_pointers["EXTRA_MATRIX"] = &p_shader->canvas_item.uses_extra_matrix;
-			shaders.actions_canvas.usage_flag_pointers["PROJECTION_MATRIX"] = &p_shader->canvas_item.uses_projection_matrix;
-			shaders.actions_canvas.usage_flag_pointers["INSTANCE_CUSTOM"] = &p_shader->canvas_item.uses_instance_custom;
-
-			actions = &shaders.actions_canvas;
-			actions->uniforms = &p_shader->uniforms;
-		} break;
-
-		case RS::SHADER_SPATIAL: {
-			// TODO remove once 3D is added back
-			return;
-			p_shader->spatial.blend_mode = Shader::Spatial::BLEND_MODE_MIX;
-			p_shader->spatial.depth_draw_mode = Shader::Spatial::DEPTH_DRAW_OPAQUE;
-			p_shader->spatial.cull_mode = Shader::Spatial::CULL_MODE_BACK;
-			p_shader->spatial.uses_alpha = false;
-			p_shader->spatial.uses_alpha_scissor = false;
-			p_shader->spatial.uses_discard = false;
-			p_shader->spatial.unshaded = false;
-			p_shader->spatial.no_depth_test = false;
-			p_shader->spatial.uses_sss = false;
-			p_shader->spatial.uses_time = false;
-			p_shader->spatial.uses_vertex_lighting = false;
-			p_shader->spatial.uses_screen_texture = false;
-			p_shader->spatial.uses_depth_texture = false;
-			p_shader->spatial.uses_vertex = false;
-			p_shader->spatial.uses_tangent = false;
-			p_shader->spatial.uses_ensure_correct_normals = false;
-			p_shader->spatial.writes_modelview_or_projection = false;
-			p_shader->spatial.uses_world_coordinates = false;
-
-			shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD);
-			shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX);
-			shaders.actions_scene.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_SUB);
-			shaders.actions_scene.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MUL);
-
-			shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_OPAQUE);
-			shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALWAYS);
-			shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_NEVER);
-			shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS);
-
-			shaders.actions_scene.render_mode_values["cull_front"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_FRONT);
-			shaders.actions_scene.render_mode_values["cull_back"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_BACK);
-			shaders.actions_scene.render_mode_values["cull_disabled"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_DISABLED);
-
-			shaders.actions_scene.render_mode_flags["unshaded"] = &p_shader->spatial.unshaded;
-			shaders.actions_scene.render_mode_flags["depth_test_disable"] = &p_shader->spatial.no_depth_test;
-
-			shaders.actions_scene.render_mode_flags["vertex_lighting"] = &p_shader->spatial.uses_vertex_lighting;
-
-			shaders.actions_scene.render_mode_flags["world_vertex_coords"] = &p_shader->spatial.uses_world_coordinates;
-
-			shaders.actions_scene.render_mode_flags["ensure_correct_normals"] = &p_shader->spatial.uses_ensure_correct_normals;
-
-			shaders.actions_scene.usage_flag_pointers["ALPHA"] = &p_shader->spatial.uses_alpha;
-			shaders.actions_scene.usage_flag_pointers["ALPHA_SCISSOR"] = &p_shader->spatial.uses_alpha_scissor;
-
-			shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss;
-			shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard;
-			shaders.actions_scene.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->spatial.uses_screen_texture;
-			shaders.actions_scene.usage_flag_pointers["DEPTH_TEXTURE"] = &p_shader->spatial.uses_depth_texture;
-			shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time;
-
-			// Use of any of these BUILTINS indicate the need for transformed tangents.
-			// This is needed to know when to transform tangents in software skinning.
-			shaders.actions_scene.usage_flag_pointers["TANGENT"] = &p_shader->spatial.uses_tangent;
-			shaders.actions_scene.usage_flag_pointers["NORMALMAP"] = &p_shader->spatial.uses_tangent;
-
-			shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
-			shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
-			shaders.actions_scene.write_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex;
-
-			actions = &shaders.actions_scene;
-			actions->uniforms = &p_shader->uniforms;
-		} break;
-
-		default: {
-			return;
-		} break;
-	}
-
-	Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code);
-	if (err != OK) {
-		return;
-	}
-
-	Vector<StringName> texture_uniform_names;
-	for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
-		texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
-	}
-
-	p_shader->shader->version_set_code(p_shader->version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
-
-	p_shader->texture_uniforms = gen_code.texture_uniforms;
-
-	p_shader->uses_vertex_time = gen_code.uses_vertex_time;
-	p_shader->uses_fragment_time = gen_code.uses_fragment_time;
-
-	for (SelfList<Material> *E = p_shader->materials.first(); E; E = E->next()) {
-		_material_make_dirty(E->self());
-	}
-
-	p_shader->valid = true;
-}
-
-void RasterizerStorageGLES3::update_dirty_shaders() {
-	while (_shader_dirty_list.first()) {
-		_update_shader(_shader_dirty_list.first()->self());
-	}
-}
-
-void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
-	Shader *shader = shader_owner.get_or_null(p_shader);
-	ERR_FAIL_COND(!shader);
-
-	if (shader->dirty_list.in_list()) {
-		_update_shader(shader);
-	}
-
-	Map<int, StringName> order;
-
-	for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
-		if (E->get().texture_order >= 0) {
-			order[E->get().texture_order + 100000] = E->key();
-		} else {
-			order[E->get().order] = E->key();
-		}
-	}
-
-	for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
-		PropertyInfo pi;
-		ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[E->get()];
-
-		pi.name = E->get();
-
-		switch (u.type) {
-			case ShaderLanguage::TYPE_VOID: {
-				pi.type = Variant::NIL;
-			} break;
-
-			case ShaderLanguage::TYPE_BOOL: {
-				pi.type = Variant::BOOL;
-			} break;
-
-			// bool vectors
-			case ShaderLanguage::TYPE_BVEC2: {
-				pi.type = Variant::INT;
-				pi.hint = PROPERTY_HINT_FLAGS;
-				pi.hint_string = "x,y";
-			} break;
-			case ShaderLanguage::TYPE_BVEC3: {
-				pi.type = Variant::INT;
-				pi.hint = PROPERTY_HINT_FLAGS;
-				pi.hint_string = "x,y,z";
-			} break;
-			case ShaderLanguage::TYPE_BVEC4: {
-				pi.type = Variant::INT;
-				pi.hint = PROPERTY_HINT_FLAGS;
-				pi.hint_string = "x,y,z,w";
-			} break;
-
-				// int stuff
-			case ShaderLanguage::TYPE_UINT:
-			case ShaderLanguage::TYPE_INT: {
-				pi.type = Variant::INT;
-
-				if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
-					pi.hint = PROPERTY_HINT_RANGE;
-					pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
-				}
-			} break;
-
-			case ShaderLanguage::TYPE_IVEC2:
-			case ShaderLanguage::TYPE_UVEC2:
-			case ShaderLanguage::TYPE_IVEC3:
-			case ShaderLanguage::TYPE_UVEC3:
-			case ShaderLanguage::TYPE_IVEC4:
-			case ShaderLanguage::TYPE_UVEC4: {
-				// not sure what this should be in godot 4
-				//				pi.type = Variant::POOL_INT_ARRAY;
-				pi.type = Variant::PACKED_INT32_ARRAY;
-			} break;
-
-			case ShaderLanguage::TYPE_FLOAT: {
-				pi.type = Variant::FLOAT;
-				if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
-					pi.hint = PROPERTY_HINT_RANGE;
-					pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
-				}
-			} break;
-
-			case ShaderLanguage::TYPE_VEC2: {
-				pi.type = Variant::VECTOR2;
-			} break;
-			case ShaderLanguage::TYPE_VEC3: {
-				pi.type = Variant::VECTOR3;
-			} break;
-
-			case ShaderLanguage::TYPE_VEC4: {
-				if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
-					pi.type = Variant::COLOR;
-				} else {
-					pi.type = Variant::PLANE;
-				}
-			} break;
-
-			case ShaderLanguage::TYPE_MAT2: {
-				pi.type = Variant::TRANSFORM2D;
-			} break;
-
-			case ShaderLanguage::TYPE_MAT3: {
-				pi.type = Variant::BASIS;
-			} break;
-
-			case ShaderLanguage::TYPE_MAT4: {
-				pi.type = Variant::TRANSFORM3D;
-			} break;
-
-			case ShaderLanguage::TYPE_SAMPLER2D:
-				//			case ShaderLanguage::TYPE_SAMPLEREXT:
-			case ShaderLanguage::TYPE_ISAMPLER2D:
-			case ShaderLanguage::TYPE_USAMPLER2D: {
-				pi.type = Variant::OBJECT;
-				pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
-				pi.hint_string = "Texture";
-			} break;
-
-			case ShaderLanguage::TYPE_SAMPLERCUBE: {
-				pi.type = Variant::OBJECT;
-				pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
-				pi.hint_string = "CubeMap";
-			} break;
-
-			case ShaderLanguage::TYPE_SAMPLER2DARRAY:
-			case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
-			case ShaderLanguage::TYPE_USAMPLER2DARRAY:
-			case ShaderLanguage::TYPE_SAMPLER3D:
-			case ShaderLanguage::TYPE_ISAMPLER3D:
-			case ShaderLanguage::TYPE_USAMPLER3D: {
-				// Not implemented in OpenGL
-			} break;
-				// new for godot 4
-			case ShaderLanguage::TYPE_SAMPLERCUBEARRAY:
-			case ShaderLanguage::TYPE_STRUCT:
-			case ShaderLanguage::TYPE_MAX: {
-			} break;
-		}
-
-		p_param_list->push_back(pi);
-	}
-}
-
-void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
-	Shader *shader = shader_owner.get_or_null(p_shader);
-	ERR_FAIL_COND(!shader);
-	ERR_FAIL_COND(p_texture.is_valid() && !GLES3::TextureStorage::get_singleton()->owns_texture(p_texture));
-
-	if (!p_texture.is_valid()) {
-		if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
-			shader->default_textures[p_name].erase(p_index);
-
-			if (shader->default_textures[p_name].is_empty()) {
-				shader->default_textures.erase(p_name);
-			}
-		}
-	} else {
-		if (!shader->default_textures.has(p_name)) {
-			shader->default_textures[p_name] = Map<int, RID>();
-		}
-		shader->default_textures[p_name][p_index] = p_texture;
-	}
-
-	_shader_make_dirty(shader);
-}
-
-RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
-	const Shader *shader = shader_owner.get_or_null(p_shader);
-	ERR_FAIL_COND_V(!shader, RID());
-
-	if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
-		return shader->default_textures[p_name][p_index];
-	}
-
-	return RID();
-}
-
-/* COMMON MATERIAL API */
-
-void RasterizerStorageGLES3::_material_make_dirty(Material *p_material) const {
-	if (p_material->dirty_list.in_list()) {
-		return;
-	}
-
-	_material_dirty_list.add(&p_material->dirty_list);
-}
-
-RID RasterizerStorageGLES3::material_allocate() {
-	Material *material = memnew(Material);
-	return material_owner.make_rid(material);
-}
-
-void RasterizerStorageGLES3::material_initialize(RID p_rid) {
-}
-
-//RID RasterizerStorageGLES3::material_create() {
-//	Material *material = memnew(Material);
-
-//	return material_owner.make_rid(material);
-//}
-
-void RasterizerStorageGLES3::material_set_shader(RID p_material, RID p_shader) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND(!material);
-
-	Shader *shader = shader_owner.get_or_null(p_shader);
-
-	if (material->shader) {
-		// if a shader is present, remove the old shader
-		material->shader->materials.remove(&material->list);
-	}
-
-	material->shader = shader;
-
-	if (shader) {
-		shader->materials.add(&material->list);
-	}
-
-	_material_make_dirty(material);
-}
-
-RID RasterizerStorageGLES3::material_get_shader(RID p_material) const {
-	const Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND_V(!material, RID());
-
-	if (material->shader) {
-		return material->shader->self;
-	}
-
-	return RID();
-}
-
-void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND(!material);
-
-	if (p_value.get_type() == Variant::NIL) {
-		material->params.erase(p_param);
-	} else {
-		material->params[p_param] = p_value;
-	}
-
-	_material_make_dirty(material);
-}
-
-Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName &p_param) const {
-	const Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND_V(!material, RID());
-
-	if (material->params.has(p_param)) {
-		return material->params[p_param];
-	}
-
-	return material_get_param_default(p_material, p_param);
-}
-
-Variant RasterizerStorageGLES3::material_get_param_default(RID p_material, const StringName &p_param) const {
-	const Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND_V(!material, Variant());
-
-	if (material->shader) {
-		if (material->shader->uniforms.has(p_param)) {
-			ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param];
-			Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
-			return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
-		}
-	}
-	return Variant();
-}
-
-void RasterizerStorageGLES3::material_set_line_width(RID p_material, float p_width) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND(!material);
-
-	material->line_width = p_width;
-}
-
-void RasterizerStorageGLES3::material_set_next_pass(RID p_material, RID p_next_material) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND(!material);
-
-	material->next_pass = p_next_material;
-}
-
-bool RasterizerStorageGLES3::material_is_animated(RID p_material) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND_V(!material, false);
-	if (material->dirty_list.in_list()) {
-		_update_material(material);
-	}
-
-	bool animated = material->is_animated_cache;
-	if (!animated && material->next_pass.is_valid()) {
-		animated = material_is_animated(material->next_pass);
-	}
-	return animated;
-}
-
-bool RasterizerStorageGLES3::material_casts_shadows(RID p_material) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND_V(!material, false);
-	if (material->dirty_list.in_list()) {
-		_update_material(material);
-	}
-
-	bool casts_shadows = material->can_cast_shadow_cache;
-
-	if (!casts_shadows && material->next_pass.is_valid()) {
-		casts_shadows = material_casts_shadows(material->next_pass);
-	}
-
-	return casts_shadows;
-}
-
-bool RasterizerStorageGLES3::material_uses_tangents(RID p_material) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND_V(!material, false);
-
-	if (!material->shader) {
-		return false;
-	}
-
-	if (material->shader->dirty_list.in_list()) {
-		_update_shader(material->shader);
-	}
-
-	return material->shader->spatial.uses_tangent;
-}
-
-bool RasterizerStorageGLES3::material_uses_ensure_correct_normals(RID p_material) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND_V(!material, false);
-
-	if (!material->shader) {
-		return false;
-	}
-
-	if (material->shader->dirty_list.in_list()) {
-		_update_shader(material->shader);
-	}
-
-	return material->shader->spatial.uses_ensure_correct_normals;
-}
-
-void RasterizerStorageGLES3::material_add_instance_owner(RID p_material, DependencyTracker *p_instance) {
-	/*
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND(!material);
-
-	Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
-	if (E) {
-		E->get()++;
-	} else {
-		material->instance_owners[p_instance] = 1;
-	}
-*/
-}
-
-void RasterizerStorageGLES3::material_remove_instance_owner(RID p_material, DependencyTracker *p_instance) {
-	/*
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND(!material);
-
-	Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
-	ERR_FAIL_COND(!E);
-
-	E->get()--;
-
-	if (E->get() == 0) {
-		material->instance_owners.erase(E);
-	}
-*/
-}
-
-void RasterizerStorageGLES3::material_set_render_priority(RID p_material, int priority) {
-	ERR_FAIL_COND(priority < RS::MATERIAL_RENDER_PRIORITY_MIN);
-	ERR_FAIL_COND(priority > RS::MATERIAL_RENDER_PRIORITY_MAX);
-
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND(!material);
-
-	material->render_priority = priority;
-}
-
-void RasterizerStorageGLES3::_update_material(Material *p_material) {
-	if (p_material->dirty_list.in_list()) {
-		_material_dirty_list.remove(&p_material->dirty_list);
-	}
-
-	if (p_material->shader && p_material->shader->dirty_list.in_list()) {
-		_update_shader(p_material->shader);
-	}
-
-	if (p_material->shader && !p_material->shader->valid) {
-		return;
-	}
-
-	{
-		bool can_cast_shadow = false;
-		bool is_animated = false;
-
-		if (p_material->shader && p_material->shader->mode == RS::SHADER_SPATIAL) {
-			if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
-					(!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
-				can_cast_shadow = true;
-			}
-
-			if (p_material->shader->spatial.uses_discard && p_material->shader->uses_fragment_time) {
-				is_animated = true;
-			}
-
-			if (p_material->shader->spatial.uses_vertex && p_material->shader->uses_vertex_time) {
-				is_animated = true;
-			}
-
-			if (can_cast_shadow != p_material->can_cast_shadow_cache || is_animated != p_material->is_animated_cache) {
-				p_material->can_cast_shadow_cache = can_cast_shadow;
-				p_material->is_animated_cache = is_animated;
-
-				/*
-				for (Map<Geometry *, int>::Element *E = p_material->geometry_owners.front(); E; E = E->next()) {
-					E->key()->material_changed_notify();
-				}
-
-				for (Map<InstanceBaseDependency *, int>::Element *E = p_material->instance_owners.front(); E; E = E->next()) {
-					E->key()->base_changed(false, true);
-				}
-				*/
-			}
-		}
-	}
-
-	// uniforms and other things will be set in the use_material method in ShaderGLES3
-
-	if (p_material->shader && p_material->shader->texture_uniforms.size() > 0) {
-		p_material->textures.resize(p_material->shader->texture_uniforms.size());
-
-		for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_material->shader->uniforms.front(); E; E = E->next()) {
-			if (E->get().texture_order < 0) {
-				continue; // not a texture, does not go here
-			}
-
-			RID texture;
-
-			Map<StringName, Variant>::Element *V = p_material->params.find(E->key());
-
-			if (V) {
-				texture = V->get();
-			}
-
-			if (!texture.is_valid()) {
-				Map<StringName, Map<int, RID>>::Element *W = p_material->shader->default_textures.find(E->key());
-
-				// TODO: make texture uniform array properly works with GLES3
-				if (W && W->get().has(0)) {
-					texture = W->get()[0];
-				}
-			}
-
-			p_material->textures.write[E->get().texture_order] = Pair<StringName, RID>(E->key(), texture);
-		}
-	} else {
-		p_material->textures.clear();
-	}
-}
-/*
-void RasterizerStorageGLES3::_material_add_geometry(RID p_material, Geometry *p_geometry) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND(!material);
-
-	Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
-
-	if (I) {
-		I->get()++;
-	} else {
-		material->geometry_owners[p_geometry] = 1;
-	}
-}
-
-void RasterizerStorageGLES3::_material_remove_geometry(RID p_material, Geometry *p_geometry) {
-	Material *material = material_owner.get_or_null(p_material);
-	ERR_FAIL_COND(!material);
-
-	Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
-	ERR_FAIL_COND(!I);
-
-	I->get()--;
-
-	if (I->get() == 0) {
-		material->geometry_owners.erase(I);
-	}
-}
-*/
-void RasterizerStorageGLES3::update_dirty_materials() {
-	while (_material_dirty_list.first()) {
-		Material *material = _material_dirty_list.first()->self();
-		_update_material(material);
-	}
-}
-
 /* MESH API */
 
 RID RasterizerStorageGLES3::mesh_allocate() {
@@ -1489,6 +740,10 @@ void RasterizerStorageGLES3::particles_set_canvas_sdf_collision(RID p_particles,
 void RasterizerStorageGLES3::update_particles() {
 }
 
+bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const {
+	return false;
+}
+
 /* PARTICLES COLLISION */
 
 RID RasterizerStorageGLES3::particles_collision_allocate() {
@@ -1595,52 +850,6 @@ AABB RasterizerStorageGLES3::visibility_notifier_get_aabb(RID p_notifier) const
 void RasterizerStorageGLES3::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
 }
 
-/* GLOBAL VARIABLES */
-
-void RasterizerStorageGLES3::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
-}
-
-void RasterizerStorageGLES3::global_variable_remove(const StringName &p_name) {
-}
-
-Vector<StringName> RasterizerStorageGLES3::global_variable_get_list() const {
-	return Vector<StringName>();
-}
-
-void RasterizerStorageGLES3::global_variable_set(const StringName &p_name, const Variant &p_value) {
-}
-
-void RasterizerStorageGLES3::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
-}
-
-Variant RasterizerStorageGLES3::global_variable_get(const StringName &p_name) const {
-	return Variant();
-}
-
-RS::GlobalVariableType RasterizerStorageGLES3::global_variable_get_type(const StringName &p_name) const {
-	return RS::GLOBAL_VAR_TYPE_MAX;
-}
-
-void RasterizerStorageGLES3::global_variables_load_settings(bool p_load_textures) {
-}
-
-void RasterizerStorageGLES3::global_variables_clear() {
-}
-
-int32_t RasterizerStorageGLES3::global_variables_instance_allocate(RID p_instance) {
-	return 0;
-}
-
-void RasterizerStorageGLES3::global_variables_instance_free(RID p_instance) {
-}
-
-void RasterizerStorageGLES3::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
-}
-
-bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const {
-	return false;
-}
-
 /* RENDER TARGET */
 
 void RasterizerStorageGLES3::_set_current_render_target(RID p_render_target) {
@@ -2594,63 +1803,12 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
 		memdelete(sky);
 
 		return true;
-	} else if (shader_owner.owns(p_rid)) {
-		Shader *shader = shader_owner.get_or_null(p_rid);
-
-		if (shader->shader && shader->version.is_valid()) {
-			shader->shader->version_free(shader->version);
-		}
-
-		if (shader->dirty_list.in_list()) {
-			_shader_dirty_list.remove(&shader->dirty_list);
-		}
-
-		while (shader->materials.first()) {
-			Material *m = shader->materials.first()->self();
-
-			m->shader = nullptr;
-			_material_make_dirty(m);
-
-			shader->materials.remove(shader->materials.first());
-		}
-
-		shader_owner.free(p_rid);
-		memdelete(shader);
-
+	} else if (GLES3::MaterialStorage::get_singleton()->owns_shader(p_rid)) {
+		GLES3::MaterialStorage::get_singleton()->shader_free(p_rid);
 		return true;
-	} else if (material_owner.owns(p_rid)) {
-		Material *m = material_owner.get_or_null(p_rid);
-
-		if (m->shader) {
-			m->shader->materials.remove(&m->list);
-		}
-
-		/*
-		for (Map<Geometry *, int>::Element *E = m->geometry_owners.front(); E; E = E->next()) {
-			Geometry *g = E->key();
-			g->material = RID();
-		}
-
-		for (Map<InstanceBaseDependency *, int>::Element *E = m->instance_owners.front(); E; E = E->next()) {
-			InstanceBaseDependency *ins = E->key();
-
-			if (ins->material_override == p_rid) {
-				ins->material_override = RID();
-			}
-
-			for (int i = 0; i < ins->materials.size(); i++) {
-				if (ins->materials[i] == p_rid) {
-					ins->materials.write[i] = RID();
-				}
-			}
-		}
-*/
-
-		material_owner.free(p_rid);
-		memdelete(m);
-
+	} else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) {
+		GLES3::MaterialStorage::get_singleton()->material_free(p_rid);
 		return true;
-
 	} else {
 		return false;
 	}
@@ -2975,13 +2133,6 @@ void RasterizerStorageGLES3::initialize() {
 	// OR max_vertex_texture_image_units is zero
 	config->use_skeleton_software = (config->float_texture_supported == false) || (config->max_vertex_texture_image_units == 0);
 
-	shaders.copy.initialize();
-	shaders.copy_version = shaders.copy.version_create(); //TODO
-	shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION);
-	//shaders.cubemap_filter.init();
-	//bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
-	//shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq);
-
 	{
 		// quad for copying stuff
 
@@ -3139,8 +2290,8 @@ uint64_t RasterizerStorageGLES3::get_rendering_info(RS::RenderingInfo p_info) {
 }
 
 void RasterizerStorageGLES3::update_dirty_resources() {
-	update_dirty_shaders();
-	update_dirty_materials();
+	GLES3::MaterialStorage::get_singleton()->update_dirty_shaders();
+	GLES3::MaterialStorage::get_singleton()->update_dirty_materials();
 	//	update_dirty_skeletons();
 	//	update_dirty_multimeshes();
 }
@@ -3150,7 +2301,6 @@ RasterizerStorageGLES3::RasterizerStorageGLES3() {
 }
 
 RasterizerStorageGLES3::~RasterizerStorageGLES3() {
-	shaders.copy.version_free(shaders.copy_version);
 }
 
 #endif // GLES3_ENABLED

+ 6 - 264
drivers/gles3/rasterizer_storage_gles3.h

@@ -42,18 +42,17 @@
 #include "servers/rendering/shader_language.h"
 #include "storage/canvas_texture_storage.h"
 #include "storage/config.h"
+#include "storage/material_storage.h"
 #include "storage/render_target_storage.h"
 #include "storage/texture_storage.h"
 
-#include "shaders/copy.glsl.gen.h"
-
-class RasterizerCanvasGLES3;
-class RasterizerSceneGLES3;
+// class RasterizerCanvasGLES3;
+// class RasterizerSceneGLES3;
 
 class RasterizerStorageGLES3 : public RendererStorage {
 public:
-	RasterizerCanvasGLES3 *canvas;
-	RasterizerSceneGLES3 *scene;
+	// RasterizerCanvasGLES3 *canvas;
+	// RasterizerSceneGLES3 *scene;
 
 	static GLuint system_fbo;
 
@@ -79,19 +78,6 @@ public:
 
 	} resources;
 
-	mutable struct Shaders {
-		ShaderCompiler compiler;
-
-		CopyShaderGLES3 copy;
-		RID copy_version;
-		//CubemapFilterShaderGLES3 cubemap_filter;
-
-		ShaderCompiler::IdentifierActions actions_canvas;
-		ShaderCompiler::IdentifierActions actions_scene;
-		ShaderCompiler::IdentifierActions actions_particles;
-
-	} shaders;
-
 	struct Info {
 		uint64_t texture_mem = 0;
 		uint64_t vertex_mem = 0;
@@ -146,231 +132,6 @@ public:
 	RID sky_create();
 	void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size);
 
-	// SHADER API
-
-	struct Material;
-
-	struct Shader {
-		RID self;
-
-		RS::ShaderMode mode;
-		ShaderGLES3 *shader;
-		String code;
-		SelfList<Material>::List materials;
-
-		Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
-
-		RID version;
-
-		SelfList<Shader> dirty_list;
-
-		Map<StringName, Map<int, RID>> default_textures;
-
-		Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
-
-		bool valid;
-
-		String path;
-
-		uint32_t index;
-		uint64_t last_pass;
-
-		struct CanvasItem {
-			enum BlendMode {
-				BLEND_MODE_MIX,
-				BLEND_MODE_ADD,
-				BLEND_MODE_SUB,
-				BLEND_MODE_MUL,
-				BLEND_MODE_PMALPHA,
-			};
-
-			int blend_mode;
-
-			enum LightMode {
-				LIGHT_MODE_NORMAL,
-				LIGHT_MODE_UNSHADED,
-				LIGHT_MODE_LIGHT_ONLY
-			};
-
-			int light_mode;
-
-			bool uses_screen_texture;
-			bool uses_screen_uv;
-			bool uses_time;
-			bool uses_modulate;
-			bool uses_color;
-			bool uses_vertex;
-
-			// all these should disable item joining if used in a custom shader
-			bool uses_model_matrix;
-			bool uses_extra_matrix;
-			bool uses_projection_matrix;
-			bool uses_instance_custom;
-
-		} canvas_item;
-
-		struct Spatial {
-			enum BlendMode {
-				BLEND_MODE_MIX,
-				BLEND_MODE_ADD,
-				BLEND_MODE_SUB,
-				BLEND_MODE_MUL,
-			};
-
-			int blend_mode;
-
-			enum DepthDrawMode {
-				DEPTH_DRAW_OPAQUE,
-				DEPTH_DRAW_ALWAYS,
-				DEPTH_DRAW_NEVER,
-				DEPTH_DRAW_ALPHA_PREPASS,
-			};
-
-			int depth_draw_mode;
-
-			enum CullMode {
-				CULL_MODE_FRONT,
-				CULL_MODE_BACK,
-				CULL_MODE_DISABLED,
-			};
-
-			int cull_mode;
-
-			bool uses_alpha;
-			bool uses_alpha_scissor;
-			bool unshaded;
-			bool no_depth_test;
-			bool uses_vertex;
-			bool uses_discard;
-			bool uses_sss;
-			bool uses_screen_texture;
-			bool uses_depth_texture;
-			bool uses_time;
-			bool uses_tangent;
-			bool uses_ensure_correct_normals;
-			bool writes_modelview_or_projection;
-			bool uses_vertex_lighting;
-			bool uses_world_coordinates;
-
-		} spatial;
-
-		struct Particles {
-		} particles;
-
-		bool uses_vertex_time;
-		bool uses_fragment_time;
-
-		Shader() :
-				dirty_list(this) {
-			shader = nullptr;
-			valid = false;
-			version = RID();
-			last_pass = 0;
-		}
-	};
-
-	mutable RID_PtrOwner<Shader> shader_owner;
-	mutable SelfList<Shader>::List _shader_dirty_list;
-
-	void _shader_make_dirty(Shader *p_shader);
-
-	RID shader_allocate() override;
-	void shader_initialize(RID p_rid) override;
-
-	//RID shader_create() override;
-
-	void shader_set_code(RID p_shader, const String &p_code) override;
-	String shader_get_code(RID p_shader) const override;
-	void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
-
-	void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
-	RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
-
-	RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
-
-	void _update_shader(Shader *p_shader) const;
-	void update_dirty_shaders();
-
-	// new
-	Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
-
-	// COMMON MATERIAL API
-
-	struct Material {
-		RID self;
-		Shader *shader;
-		Map<StringName, Variant> params;
-		SelfList<Material> list;
-		SelfList<Material> dirty_list;
-		Vector<Pair<StringName, RID>> textures;
-		float line_width;
-		int render_priority;
-
-		RID next_pass;
-
-		uint32_t index;
-		uint64_t last_pass;
-
-		//		Map<Geometry *, int> geometry_owners;
-		//		Map<InstanceBaseDependency *, int> instance_owners;
-
-		bool can_cast_shadow_cache;
-		bool is_animated_cache;
-
-		Material() :
-				list(this),
-				dirty_list(this) {
-			can_cast_shadow_cache = false;
-			is_animated_cache = false;
-			shader = nullptr;
-			line_width = 1.0;
-			last_pass = 0;
-			render_priority = 0;
-		}
-	};
-
-	mutable SelfList<Material>::List _material_dirty_list;
-	void _material_make_dirty(Material *p_material) const;
-
-	//	void _material_add_geometry(RID p_material, Geometry *p_geometry);
-	//	void _material_remove_geometry(RID p_material, Geometry *p_geometry);
-
-	void _update_material(Material *p_material);
-
-	mutable RID_PtrOwner<Material> material_owner;
-
-	// new
-	void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
-	void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
-
-	// old
-	RID material_allocate() override;
-	void material_initialize(RID p_rid) override;
-
-	//RID material_create() override;
-
-	void material_set_shader(RID p_material, RID p_shader) override;
-	RID material_get_shader(RID p_material) const;
-
-	void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
-	Variant material_get_param(RID p_material, const StringName &p_param) const override;
-	Variant material_get_param_default(RID p_material, const StringName &p_param) const;
-
-	void material_set_line_width(RID p_material, float p_width);
-	void material_set_next_pass(RID p_material, RID p_next_material) override;
-
-	bool material_is_animated(RID p_material) override;
-	bool material_casts_shadows(RID p_material) override;
-	bool material_uses_tangents(RID p_material);
-	bool material_uses_ensure_correct_normals(RID p_material);
-
-	void material_add_instance_owner(RID p_material, DependencyTracker *p_instance);
-	void material_remove_instance_owner(RID p_material, DependencyTracker *p_instance);
-
-	void material_set_render_priority(RID p_material, int priority) override;
-
-	void update_dirty_materials();
-
 	/* MESH API */
 
 	RID mesh_allocate() override;
@@ -694,6 +455,7 @@ public:
 	void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
 
 	void update_particles() override;
+	bool particles_is_inactive(RID p_particles) const override;
 
 	/* PARTICLES COLLISION */
 
@@ -737,26 +499,6 @@ public:
 	AABB visibility_notifier_get_aabb(RID p_notifier) const override;
 	void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override;
 
-	/* GLOBAL VARIABLES */
-
-	void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
-	void global_variable_remove(const StringName &p_name) override;
-	Vector<StringName> global_variable_get_list() const override;
-
-	void global_variable_set(const StringName &p_name, const Variant &p_value) override;
-	void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
-	Variant global_variable_get(const StringName &p_name) const override;
-	RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
-
-	void global_variables_load_settings(bool p_load_textures = true) override;
-	void global_variables_clear() override;
-
-	int32_t global_variables_instance_allocate(RID p_instance) override;
-	void global_variables_instance_free(RID p_instance) override;
-	void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
-
-	bool particles_is_inactive(RID p_particles) const override;
-
 	// RENDER TARGET
 
 	mutable RID_PtrOwner<GLES3::RenderTarget> render_target_owner;

+ 913 - 0
drivers/gles3/storage/material_storage.cpp

@@ -0,0 +1,913 @@
+/*************************************************************************/
+/*  material_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 "material_storage.h"
+#include "config.h"
+#include "texture_storage.h"
+
+#include "drivers/gles3/rasterizer_canvas_gles3.h"
+
+using namespace GLES3;
+
+MaterialStorage *MaterialStorage::singleton = nullptr;
+
+MaterialStorage *MaterialStorage::get_singleton() {
+	return singleton;
+}
+
+MaterialStorage::MaterialStorage() {
+	singleton = this;
+
+	shaders.copy.initialize();
+	shaders.copy_version = shaders.copy.version_create(); //TODO
+	shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION);
+	//shaders.cubemap_filter.init();
+	//bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
+	//shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq);
+}
+
+MaterialStorage::~MaterialStorage() {
+	shaders.copy.version_free(shaders.copy_version);
+
+	singleton = nullptr;
+}
+
+/* GLOBAL VARIABLE API */
+
+void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
+}
+
+void MaterialStorage::global_variable_remove(const StringName &p_name) {
+}
+
+Vector<StringName> MaterialStorage::global_variable_get_list() const {
+	return Vector<StringName>();
+}
+
+void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
+}
+
+void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
+}
+
+Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+	return Variant();
+}
+
+RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+	return RS::GLOBAL_VAR_TYPE_MAX;
+}
+
+void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+}
+
+void MaterialStorage::global_variables_clear() {
+}
+
+int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
+	return 0;
+}
+
+void MaterialStorage::global_variables_instance_free(RID p_instance) {
+}
+
+void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+}
+
+/* SHADER API */
+
+void MaterialStorage::_shader_make_dirty(Shader *p_shader) {
+	if (p_shader->dirty_list.in_list()) {
+		return;
+	}
+
+	_shader_dirty_list.add(&p_shader->dirty_list);
+}
+
+RID MaterialStorage::shader_allocate() {
+	Shader *shader = memnew(Shader);
+	shader->mode = RS::SHADER_CANVAS_ITEM;
+	//shader->shader = &scene->state.scene_shader;
+	RID rid = shader_owner.make_rid(shader);
+	_shader_make_dirty(shader);
+	shader->self = rid;
+
+	return rid;
+}
+
+void MaterialStorage::shader_initialize(RID p_rid) {
+	// noop
+}
+
+//RID MaterialStorage::shader_create() {
+//	Shader *shader = memnew(Shader);
+//	shader->mode = RS::SHADER_SPATIAL;
+//	shader->shader = &scene->state.scene_shader;
+//	RID rid = shader_owner.make_rid(shader);
+//	_shader_make_dirty(shader);
+//	shader->self = rid;
+
+//	return rid;
+//}
+
+void MaterialStorage::shader_free(RID p_rid) {
+	Shader *shader = shader_owner.get_or_null(p_rid);
+
+	if (shader->shader && shader->version.is_valid()) {
+		shader->shader->version_free(shader->version);
+	}
+
+	if (shader->dirty_list.in_list()) {
+		_shader_dirty_list.remove(&shader->dirty_list);
+	}
+
+	while (shader->materials.first()) {
+		Material *m = shader->materials.first()->self();
+
+		m->shader = nullptr;
+		_material_make_dirty(m);
+
+		shader->materials.remove(shader->materials.first());
+	}
+
+	shader_owner.free(p_rid);
+	memdelete(shader);
+}
+
+void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND(!shader);
+
+	shader->code = p_code;
+
+	String mode_string = ShaderLanguage::get_shader_type(p_code);
+	RS::ShaderMode mode;
+
+	if (mode_string == "canvas_item") {
+		mode = RS::SHADER_CANVAS_ITEM;
+	} else if (mode_string == "particles") {
+		mode = RS::SHADER_PARTICLES;
+	} else if (mode_string == "sky") {
+		mode = RS::SHADER_SKY;
+	} else if (mode_string == "spatial") {
+		mode = RS::SHADER_SPATIAL;
+	} else {
+		mode = RS::SHADER_MAX;
+		ERR_PRINT("shader type " + mode_string + " not supported in OpenGL renderer");
+	}
+
+	if (shader->version.is_valid() && mode != shader->mode) {
+		shader->shader->version_free(shader->version);
+		shader->version = RID();
+	}
+
+	shader->mode = mode;
+
+	// TODO handle all shader types
+	if (mode == RS::SHADER_CANVAS_ITEM) {
+		shader->shader = &RasterizerCanvasGLES3::get_singleton()->state.canvas_shader;
+	} else if (mode == RS::SHADER_SPATIAL) {
+		//shader->shader = &scene->state.scene_shader;
+	} else if (mode == RS::SHADER_PARTICLES) {
+	} else if (mode == RS::SHADER_SKY) {
+	} else {
+		return;
+	}
+
+	if (shader->version.is_null() && shader->shader) {
+		shader->version = shader->shader->version_create();
+	}
+
+	_shader_make_dirty(shader);
+}
+
+String MaterialStorage::shader_get_code(RID p_shader) const {
+	const Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND_V(!shader, "");
+
+	return shader->code;
+}
+
+void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND(!shader);
+
+	if (shader->dirty_list.in_list()) {
+		_update_shader(shader);
+	}
+
+	Map<int, StringName> order;
+
+	for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) {
+		if (E->get().texture_order >= 0) {
+			order[E->get().texture_order + 100000] = E->key();
+		} else {
+			order[E->get().order] = E->key();
+		}
+	}
+
+	for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
+		PropertyInfo pi;
+		ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[E->get()];
+
+		pi.name = E->get();
+
+		switch (u.type) {
+			case ShaderLanguage::TYPE_VOID: {
+				pi.type = Variant::NIL;
+			} break;
+
+			case ShaderLanguage::TYPE_BOOL: {
+				pi.type = Variant::BOOL;
+			} break;
+
+			// bool vectors
+			case ShaderLanguage::TYPE_BVEC2: {
+				pi.type = Variant::INT;
+				pi.hint = PROPERTY_HINT_FLAGS;
+				pi.hint_string = "x,y";
+			} break;
+			case ShaderLanguage::TYPE_BVEC3: {
+				pi.type = Variant::INT;
+				pi.hint = PROPERTY_HINT_FLAGS;
+				pi.hint_string = "x,y,z";
+			} break;
+			case ShaderLanguage::TYPE_BVEC4: {
+				pi.type = Variant::INT;
+				pi.hint = PROPERTY_HINT_FLAGS;
+				pi.hint_string = "x,y,z,w";
+			} break;
+
+				// int stuff
+			case ShaderLanguage::TYPE_UINT:
+			case ShaderLanguage::TYPE_INT: {
+				pi.type = Variant::INT;
+
+				if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+					pi.hint = PROPERTY_HINT_RANGE;
+					pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
+				}
+			} break;
+
+			case ShaderLanguage::TYPE_IVEC2:
+			case ShaderLanguage::TYPE_UVEC2:
+			case ShaderLanguage::TYPE_IVEC3:
+			case ShaderLanguage::TYPE_UVEC3:
+			case ShaderLanguage::TYPE_IVEC4:
+			case ShaderLanguage::TYPE_UVEC4: {
+				// not sure what this should be in godot 4
+				//				pi.type = Variant::POOL_INT_ARRAY;
+				pi.type = Variant::PACKED_INT32_ARRAY;
+			} break;
+
+			case ShaderLanguage::TYPE_FLOAT: {
+				pi.type = Variant::FLOAT;
+				if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+					pi.hint = PROPERTY_HINT_RANGE;
+					pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]);
+				}
+			} break;
+
+			case ShaderLanguage::TYPE_VEC2: {
+				pi.type = Variant::VECTOR2;
+			} break;
+			case ShaderLanguage::TYPE_VEC3: {
+				pi.type = Variant::VECTOR3;
+			} break;
+
+			case ShaderLanguage::TYPE_VEC4: {
+				if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+					pi.type = Variant::COLOR;
+				} else {
+					pi.type = Variant::PLANE;
+				}
+			} break;
+
+			case ShaderLanguage::TYPE_MAT2: {
+				pi.type = Variant::TRANSFORM2D;
+			} break;
+
+			case ShaderLanguage::TYPE_MAT3: {
+				pi.type = Variant::BASIS;
+			} break;
+
+			case ShaderLanguage::TYPE_MAT4: {
+				pi.type = Variant::TRANSFORM3D;
+			} break;
+
+			case ShaderLanguage::TYPE_SAMPLER2D:
+				//			case ShaderLanguage::TYPE_SAMPLEREXT:
+			case ShaderLanguage::TYPE_ISAMPLER2D:
+			case ShaderLanguage::TYPE_USAMPLER2D: {
+				pi.type = Variant::OBJECT;
+				pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+				pi.hint_string = "Texture";
+			} break;
+
+			case ShaderLanguage::TYPE_SAMPLERCUBE: {
+				pi.type = Variant::OBJECT;
+				pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+				pi.hint_string = "CubeMap";
+			} break;
+
+			case ShaderLanguage::TYPE_SAMPLER2DARRAY:
+			case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+			case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+			case ShaderLanguage::TYPE_SAMPLER3D:
+			case ShaderLanguage::TYPE_ISAMPLER3D:
+			case ShaderLanguage::TYPE_USAMPLER3D: {
+				// Not implemented in OpenGL
+			} break;
+				// new for godot 4
+			case ShaderLanguage::TYPE_SAMPLERCUBEARRAY:
+			case ShaderLanguage::TYPE_STRUCT:
+			case ShaderLanguage::TYPE_MAX: {
+			} break;
+		}
+
+		p_param_list->push_back(pi);
+	}
+}
+
+void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND(!shader);
+	ERR_FAIL_COND(p_texture.is_valid() && !TextureStorage::get_singleton()->owns_texture(p_texture));
+
+	if (!p_texture.is_valid()) {
+		if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
+			shader->default_textures[p_name].erase(p_index);
+
+			if (shader->default_textures[p_name].is_empty()) {
+				shader->default_textures.erase(p_name);
+			}
+		}
+	} else {
+		if (!shader->default_textures.has(p_name)) {
+			shader->default_textures[p_name] = Map<int, RID>();
+		}
+		shader->default_textures[p_name][p_index] = p_texture;
+	}
+
+	_shader_make_dirty(shader);
+}
+
+RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
+	const Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND_V(!shader, RID());
+
+	if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
+		return shader->default_textures[p_name][p_index];
+	}
+
+	return RID();
+}
+
+void MaterialStorage::_update_shader(Shader *p_shader) const {
+	_shader_dirty_list.remove(&p_shader->dirty_list);
+
+	p_shader->valid = false;
+
+	p_shader->uniforms.clear();
+
+	if (p_shader->code.is_empty()) {
+		return; //just invalid, but no error
+	}
+
+	ShaderCompiler::GeneratedCode gen_code;
+	ShaderCompiler::IdentifierActions *actions = nullptr;
+
+	switch (p_shader->mode) {
+		case RS::SHADER_CANVAS_ITEM: {
+			p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL;
+			p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX;
+
+			p_shader->canvas_item.uses_screen_texture = false;
+			p_shader->canvas_item.uses_screen_uv = false;
+			p_shader->canvas_item.uses_time = false;
+			p_shader->canvas_item.uses_modulate = false;
+			p_shader->canvas_item.uses_color = false;
+			p_shader->canvas_item.uses_vertex = false;
+
+			p_shader->canvas_item.uses_model_matrix = false;
+			p_shader->canvas_item.uses_extra_matrix = false;
+			p_shader->canvas_item.uses_projection_matrix = false;
+			p_shader->canvas_item.uses_instance_custom = false;
+
+			shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD);
+			shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX);
+			shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
+			shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL);
+			shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA);
+
+			shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
+			shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
+
+			shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv;
+			shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv;
+			shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture;
+			shaders.actions_canvas.usage_flag_pointers["TIME"] = &p_shader->canvas_item.uses_time;
+			shaders.actions_canvas.usage_flag_pointers["MODULATE"] = &p_shader->canvas_item.uses_modulate;
+			shaders.actions_canvas.usage_flag_pointers["COLOR"] = &p_shader->canvas_item.uses_color;
+
+			shaders.actions_canvas.usage_flag_pointers["VERTEX"] = &p_shader->canvas_item.uses_vertex;
+
+			shaders.actions_canvas.usage_flag_pointers["MODEL_MATRIX"] = &p_shader->canvas_item.uses_model_matrix;
+			shaders.actions_canvas.usage_flag_pointers["EXTRA_MATRIX"] = &p_shader->canvas_item.uses_extra_matrix;
+			shaders.actions_canvas.usage_flag_pointers["PROJECTION_MATRIX"] = &p_shader->canvas_item.uses_projection_matrix;
+			shaders.actions_canvas.usage_flag_pointers["INSTANCE_CUSTOM"] = &p_shader->canvas_item.uses_instance_custom;
+
+			actions = &shaders.actions_canvas;
+			actions->uniforms = &p_shader->uniforms;
+		} break;
+
+		case RS::SHADER_SPATIAL: {
+			// TODO remove once 3D is added back
+			return;
+			p_shader->spatial.blend_mode = Shader::Spatial::BLEND_MODE_MIX;
+			p_shader->spatial.depth_draw_mode = Shader::Spatial::DEPTH_DRAW_OPAQUE;
+			p_shader->spatial.cull_mode = Shader::Spatial::CULL_MODE_BACK;
+			p_shader->spatial.uses_alpha = false;
+			p_shader->spatial.uses_alpha_scissor = false;
+			p_shader->spatial.uses_discard = false;
+			p_shader->spatial.unshaded = false;
+			p_shader->spatial.no_depth_test = false;
+			p_shader->spatial.uses_sss = false;
+			p_shader->spatial.uses_time = false;
+			p_shader->spatial.uses_vertex_lighting = false;
+			p_shader->spatial.uses_screen_texture = false;
+			p_shader->spatial.uses_depth_texture = false;
+			p_shader->spatial.uses_vertex = false;
+			p_shader->spatial.uses_tangent = false;
+			p_shader->spatial.uses_ensure_correct_normals = false;
+			p_shader->spatial.writes_modelview_or_projection = false;
+			p_shader->spatial.uses_world_coordinates = false;
+
+			shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD);
+			shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX);
+			shaders.actions_scene.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_SUB);
+			shaders.actions_scene.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MUL);
+
+			shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_OPAQUE);
+			shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALWAYS);
+			shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_NEVER);
+			shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS);
+
+			shaders.actions_scene.render_mode_values["cull_front"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_FRONT);
+			shaders.actions_scene.render_mode_values["cull_back"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_BACK);
+			shaders.actions_scene.render_mode_values["cull_disabled"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_DISABLED);
+
+			shaders.actions_scene.render_mode_flags["unshaded"] = &p_shader->spatial.unshaded;
+			shaders.actions_scene.render_mode_flags["depth_test_disable"] = &p_shader->spatial.no_depth_test;
+
+			shaders.actions_scene.render_mode_flags["vertex_lighting"] = &p_shader->spatial.uses_vertex_lighting;
+
+			shaders.actions_scene.render_mode_flags["world_vertex_coords"] = &p_shader->spatial.uses_world_coordinates;
+
+			shaders.actions_scene.render_mode_flags["ensure_correct_normals"] = &p_shader->spatial.uses_ensure_correct_normals;
+
+			shaders.actions_scene.usage_flag_pointers["ALPHA"] = &p_shader->spatial.uses_alpha;
+			shaders.actions_scene.usage_flag_pointers["ALPHA_SCISSOR"] = &p_shader->spatial.uses_alpha_scissor;
+
+			shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss;
+			shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard;
+			shaders.actions_scene.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->spatial.uses_screen_texture;
+			shaders.actions_scene.usage_flag_pointers["DEPTH_TEXTURE"] = &p_shader->spatial.uses_depth_texture;
+			shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time;
+
+			// Use of any of these BUILTINS indicate the need for transformed tangents.
+			// This is needed to know when to transform tangents in software skinning.
+			shaders.actions_scene.usage_flag_pointers["TANGENT"] = &p_shader->spatial.uses_tangent;
+			shaders.actions_scene.usage_flag_pointers["NORMALMAP"] = &p_shader->spatial.uses_tangent;
+
+			shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
+			shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
+			shaders.actions_scene.write_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex;
+
+			actions = &shaders.actions_scene;
+			actions->uniforms = &p_shader->uniforms;
+		} break;
+
+		default: {
+			return;
+		} break;
+	}
+
+	Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code);
+	if (err != OK) {
+		return;
+	}
+
+	Vector<StringName> texture_uniform_names;
+	for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
+		texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
+	}
+
+	p_shader->shader->version_set_code(p_shader->version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+
+	p_shader->texture_uniforms = gen_code.texture_uniforms;
+
+	p_shader->uses_vertex_time = gen_code.uses_vertex_time;
+	p_shader->uses_fragment_time = gen_code.uses_fragment_time;
+
+	for (SelfList<Material> *E = p_shader->materials.first(); E; E = E->next()) {
+		_material_make_dirty(E->self());
+	}
+
+	p_shader->valid = true;
+}
+
+void MaterialStorage::update_dirty_shaders() {
+	while (_shader_dirty_list.first()) {
+		_update_shader(_shader_dirty_list.first()->self());
+	}
+}
+
+/* MATERIAL API */
+
+void MaterialStorage::_material_make_dirty(Material *p_material) const {
+	if (p_material->dirty_list.in_list()) {
+		return;
+	}
+
+	_material_dirty_list.add(&p_material->dirty_list);
+}
+
+void MaterialStorage::_update_material(Material *p_material) {
+	if (p_material->dirty_list.in_list()) {
+		_material_dirty_list.remove(&p_material->dirty_list);
+	}
+
+	if (p_material->shader && p_material->shader->dirty_list.in_list()) {
+		_update_shader(p_material->shader);
+	}
+
+	if (p_material->shader && !p_material->shader->valid) {
+		return;
+	}
+
+	{
+		bool can_cast_shadow = false;
+		bool is_animated = false;
+
+		if (p_material->shader && p_material->shader->mode == RS::SHADER_SPATIAL) {
+			if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
+					(!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
+				can_cast_shadow = true;
+			}
+
+			if (p_material->shader->spatial.uses_discard && p_material->shader->uses_fragment_time) {
+				is_animated = true;
+			}
+
+			if (p_material->shader->spatial.uses_vertex && p_material->shader->uses_vertex_time) {
+				is_animated = true;
+			}
+
+			if (can_cast_shadow != p_material->can_cast_shadow_cache || is_animated != p_material->is_animated_cache) {
+				p_material->can_cast_shadow_cache = can_cast_shadow;
+				p_material->is_animated_cache = is_animated;
+
+				/*
+				for (Map<Geometry *, int>::Element *E = p_material->geometry_owners.front(); E; E = E->next()) {
+					E->key()->material_changed_notify();
+				}
+
+				for (Map<InstanceBaseDependency *, int>::Element *E = p_material->instance_owners.front(); E; E = E->next()) {
+					E->key()->base_changed(false, true);
+				}
+				*/
+			}
+		}
+	}
+
+	// uniforms and other things will be set in the use_material method in ShaderGLES3
+
+	if (p_material->shader && p_material->shader->texture_uniforms.size() > 0) {
+		p_material->textures.resize(p_material->shader->texture_uniforms.size());
+
+		for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_material->shader->uniforms.front(); E; E = E->next()) {
+			if (E->get().texture_order < 0) {
+				continue; // not a texture, does not go here
+			}
+
+			RID texture;
+
+			Map<StringName, Variant>::Element *V = p_material->params.find(E->key());
+
+			if (V) {
+				texture = V->get();
+			}
+
+			if (!texture.is_valid()) {
+				Map<StringName, Map<int, RID>>::Element *W = p_material->shader->default_textures.find(E->key());
+
+				// TODO: make texture uniform array properly works with GLES3
+				if (W && W->get().has(0)) {
+					texture = W->get()[0];
+				}
+			}
+
+			p_material->textures.write[E->get().texture_order] = Pair<StringName, RID>(E->key(), texture);
+		}
+	} else {
+		p_material->textures.clear();
+	}
+}
+
+RID MaterialStorage::material_allocate() {
+	Material *material = memnew(Material);
+	return material_owner.make_rid(material);
+}
+
+void MaterialStorage::material_initialize(RID p_rid) {
+}
+
+//RID MaterialStorage::material_create() {
+//	Material *material = memnew(Material);
+
+//	return material_owner.make_rid(material);
+//}
+
+void MaterialStorage::material_free(RID p_rid) {
+	Material *m = material_owner.get_or_null(p_rid);
+
+	if (m->shader) {
+		m->shader->materials.remove(&m->list);
+	}
+
+	/*
+	for (Map<Geometry *, int>::Element *E = m->geometry_owners.front(); E; E = E->next()) {
+		Geometry *g = E->key();
+		g->material = RID();
+	}
+
+	for (Map<InstanceBaseDependency *, int>::Element *E = m->instance_owners.front(); E; E = E->next()) {
+		InstanceBaseDependency *ins = E->key();
+
+		if (ins->material_override == p_rid) {
+			ins->material_override = RID();
+		}
+
+		for (int i = 0; i < ins->materials.size(); i++) {
+			if (ins->materials[i] == p_rid) {
+				ins->materials.write[i] = RID();
+			}
+		}
+	}
+*/
+
+	material_owner.free(p_rid);
+	memdelete(m);
+}
+
+void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	Shader *shader = get_shader(p_shader);
+
+	if (material->shader) {
+		// if a shader is present, remove the old shader
+		material->shader->materials.remove(&material->list);
+	}
+
+	material->shader = shader;
+
+	if (shader) {
+		shader->materials.add(&material->list);
+	}
+
+	_material_make_dirty(material);
+}
+
+void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	if (p_value.get_type() == Variant::NIL) {
+		material->params.erase(p_param);
+	} else {
+		material->params[p_param] = p_value;
+	}
+
+	_material_make_dirty(material);
+}
+
+Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const {
+	const Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, RID());
+
+	if (material->params.has(p_param)) {
+		return material->params[p_param];
+	}
+
+	return material_get_param_default(p_material, p_param);
+}
+
+void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	material->next_pass = p_next_material;
+}
+
+void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
+	ERR_FAIL_COND(priority < RS::MATERIAL_RENDER_PRIORITY_MIN);
+	ERR_FAIL_COND(priority > RS::MATERIAL_RENDER_PRIORITY_MAX);
+
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	material->render_priority = priority;
+}
+
+bool MaterialStorage::material_is_animated(RID p_material) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, false);
+	if (material->dirty_list.in_list()) {
+		_update_material(material);
+	}
+
+	bool animated = material->is_animated_cache;
+	if (!animated && material->next_pass.is_valid()) {
+		animated = material_is_animated(material->next_pass);
+	}
+	return animated;
+}
+
+bool MaterialStorage::material_casts_shadows(RID p_material) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, false);
+	if (material->dirty_list.in_list()) {
+		_update_material(material);
+	}
+
+	bool casts_shadows = material->can_cast_shadow_cache;
+
+	if (!casts_shadows && material->next_pass.is_valid()) {
+		casts_shadows = material_casts_shadows(material->next_pass);
+	}
+
+	return casts_shadows;
+}
+
+Variant MaterialStorage::material_get_param_default(RID p_material, const StringName &p_param) const {
+	const Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, Variant());
+
+	if (material->shader) {
+		if (material->shader->uniforms.has(p_param)) {
+			ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param];
+			Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+			return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
+		}
+	}
+	return Variant();
+}
+
+void MaterialStorage::update_dirty_materials() {
+	while (_material_dirty_list.first()) {
+		Material *material = _material_dirty_list.first()->self();
+		_update_material(material);
+	}
+}
+
+/* are these still used? */
+RID MaterialStorage::material_get_shader(RID p_material) const {
+	const Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, RID());
+
+	if (material->shader) {
+		return material->shader->self;
+	}
+
+	return RID();
+}
+
+void MaterialStorage::material_set_line_width(RID p_material, float p_width) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	material->line_width = p_width;
+}
+
+bool MaterialStorage::material_uses_tangents(RID p_material) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, false);
+
+	if (!material->shader) {
+		return false;
+	}
+
+	if (material->shader->dirty_list.in_list()) {
+		_update_shader(material->shader);
+	}
+
+	return material->shader->spatial.uses_tangent;
+}
+
+bool MaterialStorage::material_uses_ensure_correct_normals(RID p_material) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, false);
+
+	if (!material->shader) {
+		return false;
+	}
+
+	if (material->shader->dirty_list.in_list()) {
+		_update_shader(material->shader);
+	}
+
+	return material->shader->spatial.uses_ensure_correct_normals;
+}
+
+void MaterialStorage::material_add_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+	/*
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
+	if (E) {
+		E->get()++;
+	} else {
+		material->instance_owners[p_instance] = 1;
+	}
+*/
+}
+
+void MaterialStorage::material_remove_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+	/*
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
+	ERR_FAIL_COND(!E);
+
+	E->get()--;
+
+	if (E->get() == 0) {
+		material->instance_owners.erase(E);
+	}
+*/
+}
+
+/*
+void MaterialStorage::_material_add_geometry(RID p_material, Geometry *p_geometry) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
+
+	if (I) {
+		I->get()++;
+	} else {
+		material->geometry_owners[p_geometry] = 1;
+	}
+}
+
+void MaterialStorage::_material_remove_geometry(RID p_material, Geometry *p_geometry) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
+	ERR_FAIL_COND(!I);
+
+	I->get()--;
+
+	if (I->get() == 0) {
+		material->geometry_owners.erase(I);
+	}
+}
+*/
+
+#endif // !GLES3_ENABLED

+ 338 - 0
drivers/gles3/storage/material_storage.h

@@ -0,0 +1,338 @@
+/*************************************************************************/
+/*  material_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 MATERIAL_STORAGE_GLES3_H
+#define MATERIAL_STORAGE_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/shader_compiler.h"
+#include "servers/rendering/shader_language.h"
+#include "servers/rendering/storage/material_storage.h"
+
+#include "drivers/gles3/shaders/copy.glsl.gen.h"
+
+namespace GLES3 {
+
+/* SHADER Structs */
+
+struct Shaders {
+	ShaderCompiler compiler;
+
+	CopyShaderGLES3 copy;
+	RID copy_version;
+	//CubemapFilterShaderGLES3 cubemap_filter;
+
+	ShaderCompiler::IdentifierActions actions_canvas;
+	ShaderCompiler::IdentifierActions actions_scene;
+	ShaderCompiler::IdentifierActions actions_particles;
+};
+
+struct Material;
+
+struct Shader {
+	RID self;
+
+	RS::ShaderMode mode;
+	ShaderGLES3 *shader;
+	String code;
+	SelfList<Material>::List materials;
+
+	Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+
+	RID version;
+
+	SelfList<Shader> dirty_list;
+
+	Map<StringName, Map<int, RID>> default_textures;
+
+	Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+	bool valid;
+
+	String path;
+
+	uint32_t index;
+	uint64_t last_pass;
+
+	struct CanvasItem {
+		enum BlendMode {
+			BLEND_MODE_MIX,
+			BLEND_MODE_ADD,
+			BLEND_MODE_SUB,
+			BLEND_MODE_MUL,
+			BLEND_MODE_PMALPHA,
+		};
+
+		int blend_mode;
+
+		enum LightMode {
+			LIGHT_MODE_NORMAL,
+			LIGHT_MODE_UNSHADED,
+			LIGHT_MODE_LIGHT_ONLY
+		};
+
+		int light_mode;
+
+		bool uses_screen_texture;
+		bool uses_screen_uv;
+		bool uses_time;
+		bool uses_modulate;
+		bool uses_color;
+		bool uses_vertex;
+
+		// all these should disable item joining if used in a custom shader
+		bool uses_model_matrix;
+		bool uses_extra_matrix;
+		bool uses_projection_matrix;
+		bool uses_instance_custom;
+
+	} canvas_item;
+
+	struct Spatial {
+		enum BlendMode {
+			BLEND_MODE_MIX,
+			BLEND_MODE_ADD,
+			BLEND_MODE_SUB,
+			BLEND_MODE_MUL,
+		};
+
+		int blend_mode;
+
+		enum DepthDrawMode {
+			DEPTH_DRAW_OPAQUE,
+			DEPTH_DRAW_ALWAYS,
+			DEPTH_DRAW_NEVER,
+			DEPTH_DRAW_ALPHA_PREPASS,
+		};
+
+		int depth_draw_mode;
+
+		enum CullMode {
+			CULL_MODE_FRONT,
+			CULL_MODE_BACK,
+			CULL_MODE_DISABLED,
+		};
+
+		int cull_mode;
+
+		bool uses_alpha;
+		bool uses_alpha_scissor;
+		bool unshaded;
+		bool no_depth_test;
+		bool uses_vertex;
+		bool uses_discard;
+		bool uses_sss;
+		bool uses_screen_texture;
+		bool uses_depth_texture;
+		bool uses_time;
+		bool uses_tangent;
+		bool uses_ensure_correct_normals;
+		bool writes_modelview_or_projection;
+		bool uses_vertex_lighting;
+		bool uses_world_coordinates;
+
+	} spatial;
+
+	struct Particles {
+	} particles;
+
+	bool uses_vertex_time;
+	bool uses_fragment_time;
+
+	Shader() :
+			dirty_list(this) {
+		shader = nullptr;
+		valid = false;
+		version = RID();
+		last_pass = 0;
+	}
+};
+
+/* MATERIAL Structs */
+
+struct Material {
+	RID self;
+	Shader *shader;
+	Map<StringName, Variant> params;
+	SelfList<Material> list;
+	SelfList<Material> dirty_list;
+	Vector<Pair<StringName, RID>> textures;
+	float line_width;
+	int render_priority;
+
+	RID next_pass;
+
+	uint32_t index;
+	uint64_t last_pass;
+
+	//		Map<Geometry *, int> geometry_owners;
+	//		Map<InstanceBaseDependency *, int> instance_owners;
+
+	bool can_cast_shadow_cache;
+	bool is_animated_cache;
+
+	Material() :
+			list(this),
+			dirty_list(this) {
+		can_cast_shadow_cache = false;
+		is_animated_cache = false;
+		shader = nullptr;
+		line_width = 1.0;
+		last_pass = 0;
+		render_priority = 0;
+	}
+};
+
+class MaterialStorage : public RendererMaterialStorage {
+private:
+	static MaterialStorage *singleton;
+
+	/* SHADER API */
+
+	mutable Shaders shaders;
+
+	mutable RID_PtrOwner<Shader> shader_owner;
+	mutable SelfList<Shader>::List _shader_dirty_list;
+
+	/* MATERIAL API */
+
+	mutable SelfList<Material>::List _material_dirty_list;
+	mutable RID_PtrOwner<Material> material_owner;
+
+public:
+	static MaterialStorage *get_singleton();
+
+	MaterialStorage();
+	virtual ~MaterialStorage();
+
+	/* GLOBAL VARIABLE API */
+
+	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
+	virtual void global_variable_remove(const StringName &p_name) override;
+	virtual Vector<StringName> global_variable_get_list() const override;
+
+	virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
+	virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
+	virtual Variant global_variable_get(const StringName &p_name) const override;
+	virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
+
+	virtual void global_variables_load_settings(bool p_load_textures = true) override;
+	virtual void global_variables_clear() override;
+
+	virtual int32_t global_variables_instance_allocate(RID p_instance) override;
+	virtual void global_variables_instance_free(RID p_instance) override;
+	virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+
+	/* SHADER API */
+
+	Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); };
+	bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
+
+	void _shader_make_dirty(Shader *p_shader);
+
+	virtual RID shader_allocate() override;
+	virtual void shader_initialize(RID p_rid) override;
+	virtual void shader_free(RID p_rid) override;
+
+	//RID shader_create() override;
+
+	virtual void shader_set_code(RID p_shader, const String &p_code) override;
+	virtual String shader_get_code(RID p_shader) const override;
+	virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
+
+	virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
+	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
+
+	virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
+
+	void _update_shader(Shader *p_shader) const;
+	void update_dirty_shaders();
+
+	// new
+	Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
+
+	/* MATERIAL API */
+
+	Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
+	bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
+
+	void _material_make_dirty(Material *p_material) const;
+
+	//	void _material_add_geometry(RID p_material, Geometry *p_geometry);
+	//	void _material_remove_geometry(RID p_material, Geometry *p_geometry);
+
+	void _update_material(Material *p_material);
+
+	// new
+	virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
+	virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override {}
+
+	// old
+	virtual RID material_allocate() override;
+	virtual void material_initialize(RID p_rid) override;
+
+	virtual void material_free(RID p_rid) override;
+
+	//RID material_create() override;
+
+	virtual void material_set_shader(RID p_material, RID p_shader) override;
+	virtual RID material_get_shader(RID p_material) const;
+
+	virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
+	virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;
+	virtual Variant material_get_param_default(RID p_material, const StringName &p_param) const;
+
+	void material_set_line_width(RID p_material, float p_width);
+	virtual void material_set_next_pass(RID p_material, RID p_next_material) override;
+
+	virtual bool material_is_animated(RID p_material) override;
+	virtual bool material_casts_shadows(RID p_material) override;
+	bool material_uses_tangents(RID p_material);
+	bool material_uses_ensure_correct_normals(RID p_material);
+
+	void material_add_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance);
+	void material_remove_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance);
+
+	void material_set_render_priority(RID p_material, int priority) override;
+
+	void update_dirty_materials();
+};
+
+} // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // !MATERIAL_STORAGE_GLES3_H

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

@@ -39,6 +39,7 @@
 #include "servers/rendering/dummy/rasterizer_storage_dummy.h"
 #include "servers/rendering/dummy/storage/canvas_texture_storage.h"
 #include "servers/rendering/dummy/storage/decal_atlas_storage.h"
+#include "servers/rendering/dummy/storage/material_storage.h"
 #include "servers/rendering/dummy/storage/texture_storage.h"
 #include "servers/rendering/renderer_compositor.h"
 #include "servers/rendering_server.h"
@@ -51,6 +52,7 @@ private:
 protected:
 	RasterizerCanvasDummy canvas;
 	RendererDummy::CanvasTextureStorage canvas_texture_storage;
+	RendererDummy::MaterialStorage material_storage;
 	RendererDummy::TextureStorage texture_storage;
 	RendererDummy::DecalAtlasStorage decal_atlas_storage;
 	RasterizerStorageDummy storage;
@@ -58,6 +60,7 @@ protected:
 
 public:
 	RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; };
+	RendererMaterialStorage *get_material_storage() override { return &material_storage; };
 	RendererTextureStorage *get_texture_storage() override { return &texture_storage; };
 	RendererDecalAtlasStorage *get_decal_atlas_storage() override { return &decal_atlas_storage; };
 	RendererStorage *get_storage() override { return &storage; }

+ 2 - 51
servers/rendering/dummy/rasterizer_storage_dummy.h

@@ -36,37 +36,6 @@
 
 class RasterizerStorageDummy : public RendererStorage {
 public:
-	/* SHADER API */
-
-	RID shader_allocate() override { return RID(); }
-	void shader_initialize(RID p_rid) override {}
-	void shader_set_code(RID p_shader, const String &p_code) override {}
-	String shader_get_code(RID p_shader) const override { return ""; }
-	void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
-
-	void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
-	RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
-	Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
-
-	RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
-
-	/* COMMON MATERIAL API */
-
-	RID material_allocate() override { return RID(); }
-	void material_initialize(RID p_rid) override {}
-	void material_set_render_priority(RID p_material, int priority) override {}
-	void material_set_shader(RID p_shader_material, RID p_shader) override {}
-
-	void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {}
-	Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); }
-
-	void material_set_next_pass(RID p_material, RID p_next_material) override {}
-
-	bool material_is_animated(RID p_material) override { return false; }
-	bool material_casts_shadows(RID p_material) override { return false; }
-	void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
-	void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
-
 	/* MESH API */
 
 	RID mesh_allocate() override { return RID(); }
@@ -352,6 +321,8 @@ public:
 	void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
 	void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
 
+	bool particles_is_inactive(RID p_particles) const override { return false; }
+
 	/* FOG VOLUMES */
 
 	RID fog_volume_allocate() override { return RID(); }
@@ -372,26 +343,6 @@ public:
 	virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
 	virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
 
-	/* GLOBAL VARIABLES */
-
-	void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {}
-	void global_variable_remove(const StringName &p_name) override {}
-	Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); }
-
-	void global_variable_set(const StringName &p_name, const Variant &p_value) override {}
-	void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {}
-	Variant global_variable_get(const StringName &p_name) const override { return Variant(); }
-	RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
-
-	void global_variables_load_settings(bool p_load_textures = true) override {}
-	void global_variables_clear() override {}
-
-	int32_t global_variables_instance_allocate(RID p_instance) override { return 0; }
-	void global_variables_instance_free(RID p_instance) override {}
-	void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
-
-	bool particles_is_inactive(RID p_particles) const override { return false; }
-
 	/* RENDER TARGET */
 
 	RID render_target_create() override { return RID(); }

+ 95 - 0
servers/rendering/dummy/storage/material_storage.h

@@ -0,0 +1,95 @@
+/*************************************************************************/
+/*  material_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 MATERIAL_STORAGE_DUMMY_H
+#define MATERIAL_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/material_storage.h"
+
+namespace RendererDummy {
+
+class MaterialStorage : public RendererMaterialStorage {
+public:
+	/* GLOBAL VARIABLE API */
+
+	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {}
+	virtual void global_variable_remove(const StringName &p_name) override {}
+	virtual Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); }
+
+	virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override {}
+	virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {}
+	virtual Variant global_variable_get(const StringName &p_name) const override { return Variant(); }
+	virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
+
+	virtual void global_variables_load_settings(bool p_load_textures = true) override {}
+	virtual void global_variables_clear() override {}
+
+	virtual int32_t global_variables_instance_allocate(RID p_instance) override { return 0; }
+	virtual void global_variables_instance_free(RID p_instance) override {}
+	virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
+
+	/* SHADER API */
+
+	virtual RID shader_allocate() override { return RID(); }
+	virtual void shader_initialize(RID p_rid) override {}
+	virtual void shader_free(RID p_rid) override{};
+
+	virtual void shader_set_code(RID p_shader, const String &p_code) override {}
+	virtual String shader_get_code(RID p_shader) const override { return ""; }
+	virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
+
+	virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
+	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
+	virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
+
+	virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
+
+	/* MATERIAL API */
+	virtual RID material_allocate() override { return RID(); }
+	virtual void material_initialize(RID p_rid) override {}
+	virtual void material_free(RID p_rid) override{};
+
+	virtual void material_set_render_priority(RID p_material, int priority) override {}
+	virtual void material_set_shader(RID p_shader_material, RID p_shader) override {}
+
+	virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override {}
+	virtual Variant material_get_param(RID p_material, const StringName &p_param) const override { return Variant(); }
+
+	virtual void material_set_next_pass(RID p_material, RID p_next_material) override {}
+
+	virtual bool material_is_animated(RID p_material) override { return false; }
+	virtual bool material_casts_shadows(RID p_material) override { return false; }
+	virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
+	virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override {}
+};
+
+} // namespace RendererDummy
+
+#endif // !MATERIAL_STORAGE_DUMMY_H

+ 2 - 0
servers/rendering/renderer_compositor.h

@@ -36,6 +36,7 @@
 #include "servers/rendering/renderer_storage.h"
 #include "servers/rendering/storage/canvas_texture_storage.h"
 #include "servers/rendering/storage/decal_atlas_storage.h"
+#include "servers/rendering/storage/material_storage.h"
 #include "servers/rendering/storage/texture_storage.h"
 #include "servers/rendering_server.h"
 
@@ -74,6 +75,7 @@ public:
 	static RendererCompositor *create();
 
 	virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0;
+	virtual RendererMaterialStorage *get_material_storage() = 0;
 	virtual RendererTextureStorage *get_texture_storage() = 0;
 	virtual RendererDecalAtlasStorage *get_decal_atlas_storage() = 0;
 	virtual RendererStorage *get_storage() = 0;

+ 18 - 13
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp

@@ -1368,7 +1368,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
 				clear_color.b *= bg_energy;
 				if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
 					draw_sky_fog_only = true;
-					storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+					RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
 				}
 			} break;
 			case RS::ENV_BG_COLOR: {
@@ -1378,7 +1378,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
 				clear_color.b *= bg_energy;
 				if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
 					draw_sky_fog_only = true;
-					storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+					RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
 				}
 			} break;
 			case RS::ENV_BG_SKY: {
@@ -2165,7 +2165,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 14;
-			u.append_id(storage->global_variables_get_storage_buffer());
+			u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -2182,6 +2182,8 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 }
 
 RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
 	RenderBufferDataForwardClustered *rb = nullptr;
 	if (p_render_data && p_render_data->render_buffers.is_valid()) {
 		rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
@@ -2429,6 +2431,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 }
 
 RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	Vector<RD::Uniform> uniforms;
 
 	{
@@ -2633,7 +2636,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
 	void *surface_shadow = nullptr;
 	if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) {
 		flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
-		material_shadow = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+		material_shadow = (SceneShaderForwardClustered::MaterialData *)RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
 
 		RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
 
@@ -2688,23 +2691,25 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
 
 void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
 	SceneShaderForwardClustered::MaterialData *material = p_material;
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 
-	_geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+	_geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh);
 
 	while (material->next_pass.is_valid()) {
 		RID next_pass = material->next_pass;
-		material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+		material = (SceneShaderForwardClustered::MaterialData *)material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D);
 		if (!material || !material->shader_data->valid) {
 			break;
 		}
 		if (ginstance->data->dirty_dependencies) {
-			storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+			material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
 		}
-		_geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+		_geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh);
 	}
 }
 
 void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	RID m_src;
 
 	m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
@@ -2712,7 +2717,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
 	SceneShaderForwardClustered::MaterialData *material = nullptr;
 
 	if (m_src.is_valid()) {
-		material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+		material = (SceneShaderForwardClustered::MaterialData *)material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D);
 		if (!material || !material->shader_data->valid) {
 			material = nullptr;
 		}
@@ -2720,10 +2725,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
 
 	if (material) {
 		if (ginstance->data->dirty_dependencies) {
-			storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+			material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
 		}
 	} else {
-		material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+		material = (SceneShaderForwardClustered::MaterialData *)material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
 		m_src = scene_shader.default_material;
 	}
 
@@ -2734,10 +2739,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
 	if (ginstance->data->material_overlay.is_valid()) {
 		m_src = ginstance->data->material_overlay;
 
-		material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+		material = (SceneShaderForwardClustered::MaterialData *)material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D);
 		if (material && material->shader_data->valid) {
 			if (ginstance->data->dirty_dependencies) {
-				storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+				material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
 			}
 
 			_geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);

+ 28 - 24
servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp

@@ -33,6 +33,7 @@
 #include "core/math/math_defs.h"
 #include "render_forward_clustered.h"
 #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
 
 using namespace RendererSceneRenderImplementation;
 
@@ -384,13 +385,13 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo>
 	}
 }
 
-void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
 	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
 		if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
 			continue;
 		}
 
-		RendererStorage::InstanceShaderParam p;
+		RendererMaterialStorage::InstanceShaderParam p;
 		p.info = ShaderLanguage::uniform_to_property_info(E.value);
 		p.info.name = E.key; //supply name
 		p.index = E.value.instance_index;
@@ -445,7 +446,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() {
 	}
 }
 
-RendererStorageRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
+RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
 	ShaderData *shader_data = memnew(ShaderData);
 	singleton->shader_list.add(&shader_data->shader_list_element);
 	return shader_data;
@@ -469,7 +470,7 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() {
 	free_parameters_uniform_set(uniform_set);
 }
 
-RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
 	MaterialData *material_data = memnew(MaterialData);
 	material_data->shader_data = p_shader;
 	//update will happen later anyway so do nothing.
@@ -484,17 +485,20 @@ SceneShaderForwardClustered::SceneShaderForwardClustered() {
 }
 
 SceneShaderForwardClustered::~SceneShaderForwardClustered() {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	RD::get_singleton()->free(default_vec4_xform_buffer);
 	RD::get_singleton()->free(shadow_sampler);
 
-	storage->free(overdraw_material_shader);
-	storage->free(default_shader);
+	material_storage->shader_free(overdraw_material_shader);
+	material_storage->shader_free(default_shader);
 
-	storage->free(overdraw_material);
-	storage->free(default_material);
+	material_storage->material_free(overdraw_material);
+	material_storage->material_free(default_material);
 }
 
 void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	storage = p_storage;
 
 	{
@@ -524,8 +528,8 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
 		}
 	}
 
-	storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
-	storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs);
+	material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
+	material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
 
 	{
 		//shader compiler
@@ -710,9 +714,9 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
 
 	{
 		//default material and shader
-		default_shader = storage->shader_allocate();
-		storage->shader_initialize(default_shader);
-		storage->shader_set_code(default_shader, R"(
+		default_shader = material_storage->shader_allocate();
+		material_storage->shader_initialize(default_shader);
+		material_storage->shader_set_code(default_shader, R"(
 // Default 3D material shader (clustered).
 
 shader_type spatial;
@@ -727,11 +731,11 @@ void fragment() {
 	METALLIC = 0.2;
 }
 )");
-		default_material = storage->material_allocate();
-		storage->material_initialize(default_material);
-		storage->material_set_shader(default_material, default_shader);
+		default_material = material_storage->material_allocate();
+		material_storage->material_initialize(default_material);
+		material_storage->material_set_shader(default_material, default_shader);
 
-		MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+		MaterialData *md = (MaterialData *)material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D);
 		default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
 		default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF);
 
@@ -740,10 +744,10 @@ void fragment() {
 	}
 
 	{
-		overdraw_material_shader = storage->shader_allocate();
-		storage->shader_initialize(overdraw_material_shader);
+		overdraw_material_shader = material_storage->shader_allocate();
+		material_storage->shader_initialize(overdraw_material_shader);
 		// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
-		storage->shader_set_code(overdraw_material_shader, R"(
+		material_storage->shader_set_code(overdraw_material_shader, R"(
 // 3D editor Overdraw debug draw mode shader (clustered).
 
 shader_type spatial;
@@ -755,11 +759,11 @@ void fragment() {
 	ALPHA = 0.1;
 }
 )");
-		overdraw_material = storage->material_allocate();
-		storage->material_initialize(overdraw_material);
-		storage->material_set_shader(overdraw_material, overdraw_material_shader);
+		overdraw_material = material_storage->material_allocate();
+		material_storage->material_initialize(overdraw_material);
+		material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
 
-		MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+		MaterialData *md = (MaterialData *)material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D);
 		overdraw_material_shader_ptr = md->shader_data;
 		overdraw_material_uniform_set = md->uniform_set;
 	}

+ 7 - 7
servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h

@@ -93,7 +93,7 @@ public:
 		SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3,
 	};
 
-	struct ShaderData : public RendererStorageRD::ShaderData {
+	struct ShaderData : public RendererRD::ShaderData {
 		enum BlendMode { //used internally
 			BLEND_MODE_MIX,
 			BLEND_MODE_ADD,
@@ -180,7 +180,7 @@ public:
 		virtual void set_code(const String &p_Code);
 		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
 		virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
-		void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+		void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
 
 		virtual bool is_param_texture(const StringName &p_param) const;
 		virtual bool is_animated() const;
@@ -195,12 +195,12 @@ public:
 
 	SelfList<ShaderData>::List shader_list;
 
-	RendererStorageRD::ShaderData *_create_shader_func();
-	static RendererStorageRD::ShaderData *_create_shader_funcs() {
+	RendererRD::ShaderData *_create_shader_func();
+	static RendererRD::ShaderData *_create_shader_funcs() {
 		return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func();
 	}
 
-	struct MaterialData : public RendererStorageRD::MaterialData {
+	struct MaterialData : public RendererRD::MaterialData {
 		ShaderData *shader_data;
 		RID uniform_set;
 		uint64_t last_pass = 0;
@@ -213,8 +213,8 @@ public:
 		virtual ~MaterialData();
 	};
 
-	RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
-	static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+	RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
+	static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
 		return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
 	}
 

+ 17 - 13
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

@@ -290,6 +290,8 @@ bool RenderForwardMobile::_render_buffers_can_be_storage() {
 }
 
 RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
 	//there should always be enough uniform buffers for render passes, otherwise bugs
 	ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
 
@@ -593,7 +595,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 				/*
 				if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
 					draw_sky_fog_only = true;
-					storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+					RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
 				}
 				*/
 			} break;
@@ -605,7 +607,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 				/*
 				if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
 					draw_sky_fog_only = true;
-					storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+					RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
 				}
 				*/
 			} break;
@@ -1300,7 +1302,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 14;
-			u.append_id(storage->global_variables_get_storage_buffer());
+			u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -2326,7 +2328,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
 	void *surface_shadow = nullptr;
 	if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) {
 		flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
-		material_shadow = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+		material_shadow = (SceneShaderForwardMobile::MaterialData *)RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
 
 		RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
 
@@ -2379,23 +2381,25 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
 
 void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
 	SceneShaderForwardMobile::MaterialData *material = p_material;
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 
-	_geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+	_geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh);
 
 	while (material->next_pass.is_valid()) {
 		RID next_pass = material->next_pass;
-		material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+		material = (SceneShaderForwardMobile::MaterialData *)material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D);
 		if (!material || !material->shader_data->valid) {
 			break;
 		}
 		if (ginstance->data->dirty_dependencies) {
-			storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+			material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
 		}
-		_geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+		_geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh);
 	}
 }
 
 void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	RID m_src;
 
 	m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
@@ -2403,7 +2407,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
 	SceneShaderForwardMobile::MaterialData *material = nullptr;
 
 	if (m_src.is_valid()) {
-		material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+		material = (SceneShaderForwardMobile::MaterialData *)material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D);
 		if (!material || !material->shader_data->valid) {
 			material = nullptr;
 		}
@@ -2411,10 +2415,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
 
 	if (material) {
 		if (ginstance->data->dirty_dependencies) {
-			storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+			material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
 		}
 	} else {
-		material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+		material = (SceneShaderForwardMobile::MaterialData *)material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
 		m_src = scene_shader.default_material;
 	}
 
@@ -2425,10 +2429,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
 	if (ginstance->data->material_overlay.is_valid()) {
 		m_src = ginstance->data->material_overlay;
 
-		material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+		material = (SceneShaderForwardMobile::MaterialData *)material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D);
 		if (material && material->shader_data->valid) {
 			if (ginstance->data->dirty_dependencies) {
-				storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+				material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
 			}
 
 			_geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);

+ 28 - 24
servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp

@@ -33,6 +33,7 @@
 #include "core/math/math_defs.h"
 #include "render_forward_mobile.h"
 #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
 
 using namespace RendererSceneRenderImplementation;
 
@@ -366,13 +367,13 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_
 	}
 }
 
-void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
 	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
 		if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
 			continue;
 		}
 
-		RendererStorage::InstanceShaderParam p;
+		RendererMaterialStorage::InstanceShaderParam p;
 		p.info = ShaderLanguage::uniform_to_property_info(E.value);
 		p.info.name = E.key; //supply name
 		p.index = E.value.instance_index;
@@ -427,7 +428,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() {
 	}
 }
 
-RendererStorageRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
+RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
 	ShaderData *shader_data = memnew(ShaderData);
 	singleton->shader_list.add(&shader_data->shader_list_element);
 	return shader_data;
@@ -451,7 +452,7 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() {
 	free_parameters_uniform_set(uniform_set);
 }
 
-RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
 	MaterialData *material_data = memnew(MaterialData);
 	material_data->shader_data = p_shader;
 	//update will happen later anyway so do nothing.
@@ -469,6 +470,7 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
 
 void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) {
 	storage = p_storage;
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 
 	/* SCENE SHADER */
 
@@ -494,8 +496,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
 		}
 	}
 
-	storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
-	storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs);
+	material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
+	material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
 
 	{
 		//shader compiler
@@ -677,9 +679,9 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
 
 	{
 		//default material and shader
-		default_shader = storage->shader_allocate();
-		storage->shader_initialize(default_shader);
-		storage->shader_set_code(default_shader, R"(
+		default_shader = material_storage->shader_allocate();
+		material_storage->shader_initialize(default_shader);
+		material_storage->shader_set_code(default_shader, R"(
 // Default 3D material shader (mobile).
 
 shader_type spatial;
@@ -694,11 +696,11 @@ void fragment() {
 	METALLIC = 0.2;
 }
 )");
-		default_material = storage->material_allocate();
-		storage->material_initialize(default_material);
-		storage->material_set_shader(default_material, default_shader);
+		default_material = material_storage->material_allocate();
+		material_storage->material_initialize(default_material);
+		material_storage->material_set_shader(default_material, default_shader);
 
-		MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+		MaterialData *md = (MaterialData *)material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D);
 		default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
 
 		default_material_shader_ptr = md->shader_data;
@@ -706,10 +708,10 @@ void fragment() {
 	}
 
 	{
-		overdraw_material_shader = storage->shader_allocate();
-		storage->shader_initialize(overdraw_material_shader);
+		overdraw_material_shader = material_storage->shader_allocate();
+		material_storage->shader_initialize(overdraw_material_shader);
 		// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
-		storage->shader_set_code(overdraw_material_shader, R"(
+		material_storage->shader_set_code(overdraw_material_shader, R"(
 // 3D editor Overdraw debug draw mode shader (mobile).
 
 shader_type spatial;
@@ -721,11 +723,11 @@ void fragment() {
 	ALPHA = 0.1;
 }
 )");
-		overdraw_material = storage->material_allocate();
-		storage->material_initialize(overdraw_material);
-		storage->material_set_shader(overdraw_material, overdraw_material_shader);
+		overdraw_material = material_storage->material_allocate();
+		material_storage->material_initialize(overdraw_material);
+		material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
 
-		MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+		MaterialData *md = (MaterialData *)material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D);
 		overdraw_material_shader_ptr = md->shader_data;
 		overdraw_material_uniform_set = md->uniform_set;
 	}
@@ -765,12 +767,14 @@ void SceneShaderForwardMobile::set_default_specialization_constants(const Vector
 }
 
 SceneShaderForwardMobile::~SceneShaderForwardMobile() {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	RD::get_singleton()->free(default_vec4_xform_buffer);
 	RD::get_singleton()->free(shadow_sampler);
 
-	storage->free(overdraw_material_shader);
-	storage->free(default_shader);
+	material_storage->shader_free(overdraw_material_shader);
+	material_storage->shader_free(default_shader);
 
-	storage->free(overdraw_material);
-	storage->free(default_material);
+	material_storage->material_free(overdraw_material);
+	material_storage->material_free(default_material);
 }

+ 7 - 7
servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h

@@ -57,7 +57,7 @@ public:
 		SHADER_VERSION_MAX
 	};
 
-	struct ShaderData : public RendererStorageRD::ShaderData {
+	struct ShaderData : public RendererRD::ShaderData {
 		enum BlendMode { //used internally
 			BLEND_MODE_MIX,
 			BLEND_MODE_ADD,
@@ -143,7 +143,7 @@ public:
 		virtual void set_code(const String &p_Code);
 		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
 		virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
-		void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+		void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
 
 		virtual bool is_param_texture(const StringName &p_param) const;
 		virtual bool is_animated() const;
@@ -157,12 +157,12 @@ public:
 		virtual ~ShaderData();
 	};
 
-	RendererStorageRD::ShaderData *_create_shader_func();
-	static RendererStorageRD::ShaderData *_create_shader_funcs() {
+	RendererRD::ShaderData *_create_shader_func();
+	static RendererRD::ShaderData *_create_shader_funcs() {
 		return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func();
 	}
 
-	struct MaterialData : public RendererStorageRD::MaterialData {
+	struct MaterialData : public RendererRD::MaterialData {
 		ShaderData *shader_data;
 		RID uniform_set;
 		uint64_t last_pass = 0;
@@ -177,8 +177,8 @@ public:
 
 	SelfList<ShaderData>::List shader_list;
 
-	RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
-	static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+	RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
+	static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
 		return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
 	}
 

+ 44 - 37
servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

@@ -35,7 +35,10 @@
 #include "core/math/math_defs.h"
 #include "core/math/math_funcs.h"
 #include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_server_default.h"
 
 void RendererCanvasRenderRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
@@ -359,7 +362,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
 	bool use_normal;
 	bool 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);
+	bool success = RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
 	//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);
@@ -978,7 +981,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 = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+				screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
 			}
 		}
 		u.append_id(screen);
@@ -1021,7 +1024,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 		u.binding = 9;
-		u.append_id(storage->global_variables_get_storage_buffer());
+		u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
 		uniforms.push_back(u);
 	}
 
@@ -1036,6 +1039,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 }
 
 void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	Item *current_clip = nullptr;
 
 	Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
@@ -1100,9 +1104,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
 		}
 
 		if (material != prev_material) {
-			MaterialData *material_data = nullptr;
+			CanvasMaterialData *material_data = nullptr;
 			if (material.is_valid()) {
-				material_data = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D);
+				material_data = (CanvasMaterialData *)material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D);
 			}
 
 			if (material_data) {
@@ -1129,6 +1133,8 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
 }
 
 void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	r_sdf_used = false;
 	int item_count = 0;
 
@@ -1364,7 +1370,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 		RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
 
 		if (material.is_valid()) {
-			MaterialData *md = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D);
+			CanvasMaterialData *md = (CanvasMaterialData *)material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D);
 			if (md && md->shader_data->valid) {
 				if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
 					if (!material_screen_texture_found) {
@@ -1938,7 +1944,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::
 	oc->cull_mode = p_mode;
 }
 
-void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
+void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
 	//compile
 
 	code = p_code;
@@ -2120,7 +2126,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
 	valid = true;
 }
 
-void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
 	if (!p_texture.is_valid()) {
 		if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
 			default_texture_params[p_name].erase(p_index);
@@ -2137,7 +2143,7 @@ void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringN
 	}
 }
 
-void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
 	Map<int, StringName> order;
 
 	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -2158,13 +2164,13 @@ void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_pa
 	}
 }
 
-void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
 	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
 		if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
 			continue;
 		}
 
-		RendererStorage::InstanceShaderParam p;
+		RendererMaterialStorage::InstanceShaderParam p;
 		p.info = ShaderLanguage::uniform_to_property_info(E.value);
 		p.info.name = E.key; //supply name
 		p.index = E.value.instance_index;
@@ -2173,7 +2179,7 @@ void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererSt
 	}
 }
 
-bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_param) const {
+bool RendererCanvasRenderRD::CanvasShaderData::is_param_texture(const StringName &p_param) const {
 	if (!uniforms.has(p_param)) {
 		return false;
 	}
@@ -2181,15 +2187,15 @@ bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_pa
 	return uniforms[p_param].texture_order >= 0;
 }
 
-bool RendererCanvasRenderRD::ShaderData::is_animated() const {
+bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const {
 	return false;
 }
 
-bool RendererCanvasRenderRD::ShaderData::casts_shadows() const {
+bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const {
 	return false;
 }
 
-Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
+Variant RendererCanvasRenderRD::CanvasShaderData::get_default_parameter(const StringName &p_parameter) const {
 	if (uniforms.has(p_parameter)) {
 		ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
 		Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
@@ -2198,18 +2204,18 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa
 	return Variant();
 }
 
-RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const {
+RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const {
 	RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
 	return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version);
 }
 
-RendererCanvasRenderRD::ShaderData::ShaderData() {
+RendererCanvasRenderRD::CanvasShaderData::CanvasShaderData() {
 	valid = false;
 	uses_screen_texture = false;
 	uses_sdf = false;
 }
 
-RendererCanvasRenderRD::ShaderData::~ShaderData() {
+RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() {
 	RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
 	ERR_FAIL_COND(!canvas_singleton);
 	//pipeline variants will clear themselves if shader is gone
@@ -2218,23 +2224,23 @@ RendererCanvasRenderRD::ShaderData::~ShaderData() {
 	}
 }
 
-RendererStorageRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
-	ShaderData *shader_data = memnew(ShaderData);
+RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
+	CanvasShaderData *shader_data = memnew(CanvasShaderData);
 	return shader_data;
 }
 
-bool RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
 	RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
 
 	return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET);
 }
 
-RendererCanvasRenderRD::MaterialData::~MaterialData() {
+RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() {
 	free_parameters_uniform_set(uniform_set);
 }
 
-RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) {
-	MaterialData *material_data = memnew(MaterialData);
+RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
+	CanvasMaterialData *material_data = memnew(CanvasMaterialData);
 	material_data->shader_data = p_shader;
 	//update will happen later anyway so do nothing.
 	return material_data;
@@ -2248,8 +2254,8 @@ void RendererCanvasRenderRD::update() {
 }
 
 RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
-	canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton();
-	texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::CanvasTextureStorage *canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	storage = p_storage;
 
 	{ //create default samplers
@@ -2586,16 +2592,16 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
 	state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
 
 	//create functions for shader and material
-	storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_shader_funcs);
-	storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_material_funcs);
+	material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs);
+	material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs);
 
 	state.time = 0;
 
 	{
-		default_canvas_group_shader = storage->shader_allocate();
-		storage->shader_initialize(default_canvas_group_shader);
+		default_canvas_group_shader = material_storage->shader_allocate();
+		material_storage->shader_initialize(default_canvas_group_shader);
 
-		storage->shader_set_code(default_canvas_group_shader, R"(
+		material_storage->shader_set_code(default_canvas_group_shader, R"(
 // Default CanvasGroup shader.
 
 shader_type canvas_item;
@@ -2610,10 +2616,10 @@ void fragment() {
 	COLOR *= c;
 }
 )");
-		default_canvas_group_material = storage->material_allocate();
-		storage->material_initialize(default_canvas_group_material);
+		default_canvas_group_material = material_storage->material_allocate();
+		material_storage->material_initialize(default_canvas_group_material);
 
-		storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
+		material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
 	}
 
 	static_assert(sizeof(PushConstant) == 128);
@@ -2661,10 +2667,11 @@ void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) {
 }
 
 RendererCanvasRenderRD::~RendererCanvasRenderRD() {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	//canvas state
 
-	storage->free(default_canvas_group_material);
-	storage->free(default_canvas_group_shader);
+	material_storage->material_free(default_canvas_group_material);
+	material_storage->shader_free(default_canvas_group_shader);
 
 	{
 		if (state.canvas_state_buffer.is_valid()) {
@@ -2701,6 +2708,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
 	}
 	RD::get_singleton()->free(state.shadow_texture);
 
-	canvas_texture_storage->canvas_texture_free(default_canvas_texture);
+	RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
 	//pipelines don't need freeing, they are all gone after shaders are gone
 }

+ 12 - 16
servers/rendering/renderer_rd/renderer_canvas_render_rd.h

@@ -37,14 +37,10 @@
 #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 {
@@ -155,7 +151,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 		ShaderCompiler compiler;
 	} shader;
 
-	struct ShaderData : public RendererStorageRD::ShaderData {
+	struct CanvasShaderData : public RendererRD::ShaderData {
 		enum BlendMode { //used internally
 			BLEND_MODE_MIX,
 			BLEND_MODE_ADD,
@@ -186,7 +182,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 		virtual void set_code(const String &p_Code);
 		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
 		virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
-		virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
 
 		virtual bool is_param_texture(const StringName &p_param) const;
 		virtual bool is_animated() const;
@@ -194,28 +190,28 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 		virtual Variant get_default_parameter(const StringName &p_parameter) const;
 		virtual RS::ShaderNativeSourceCode get_native_source_code() const;
 
-		ShaderData();
-		virtual ~ShaderData();
+		CanvasShaderData();
+		virtual ~CanvasShaderData();
 	};
 
-	RendererStorageRD::ShaderData *_create_shader_func();
-	static RendererStorageRD::ShaderData *_create_shader_funcs() {
+	RendererRD::ShaderData *_create_shader_func();
+	static RendererRD::ShaderData *_create_shader_funcs() {
 		return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func();
 	}
 
-	struct MaterialData : public RendererStorageRD::MaterialData {
-		ShaderData *shader_data;
+	struct CanvasMaterialData : public RendererRD::MaterialData {
+		CanvasShaderData *shader_data;
 		RID uniform_set;
 
 		virtual void set_render_priority(int p_priority) {}
 		virtual void set_next_pass(RID p_pass) {}
 		virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
-		virtual ~MaterialData();
+		virtual ~CanvasMaterialData();
 	};
 
-	RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
-	static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
-		return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
+	RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader);
+	static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+		return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader));
 	}
 
 	/**************************/

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

@@ -156,6 +156,7 @@ void RendererCompositorRD::finalize() {
 	memdelete(canvas);
 	memdelete(storage);
 	memdelete(decal_atlas_storage);
+	memdelete(material_storage);
 	memdelete(texture_storage);
 	memdelete(canvas_texture_storage);
 
@@ -289,6 +290,7 @@ RendererCompositorRD::RendererCompositorRD() {
 	canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage);
 	texture_storage = memnew(RendererRD::TextureStorage);
 	decal_atlas_storage = memnew(RendererRD::DecalAtlasStorage);
+	material_storage = memnew(RendererRD::MaterialStorage);
 	storage = memnew(RendererStorageRD);
 	canvas = memnew(RendererCanvasRenderRD(storage));
 

+ 4 - 1
servers/rendering/renderer_rd/renderer_compositor_rd.h

@@ -41,6 +41,7 @@
 #include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
 #include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
 
@@ -49,6 +50,7 @@ protected:
 	UniformSetCacheRD *uniform_set_cache;
 	RendererCanvasRenderRD *canvas;
 	RendererRD::CanvasTextureStorage *canvas_texture_storage;
+	RendererRD::MaterialStorage *material_storage;
 	RendererRD::TextureStorage *texture_storage;
 	RendererRD::DecalAtlasStorage *decal_atlas_storage;
 	RendererStorageRD *storage;
@@ -95,8 +97,9 @@ protected:
 
 public:
 	RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; }
-	RendererTextureStorage *get_texture_storage() { return texture_storage; }
 	RendererDecalAtlasStorage *get_decal_atlas_storage() { return decal_atlas_storage; }
+	RendererMaterialStorage *get_material_storage() { return material_storage; };
+	RendererTextureStorage *get_texture_storage() { return texture_storage; };
 	RendererStorage *get_storage() { return storage; }
 	RendererCanvasRender *get_canvas() { return canvas; }
 	RendererSceneRender *get_scene() { return scene; }

+ 34 - 33
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -34,6 +34,8 @@
 #include "core/os/os.h"
 #include "renderer_compositor_rd.h"
 #include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_server_default.h"
 
 void get_vogel_disk(float *r_kernel, int p_sample_count) {
@@ -2359,6 +2361,7 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
 }
 
 void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
 	ERR_FAIL_COND(!rb);
 
@@ -2571,6 +2574,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
 }
 
 void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	RD::get_singleton()->draw_command_begin_label("Post Process Subpass");
 
 	RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
@@ -2647,6 +2651,7 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_
 }
 
 void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	EffectsRD *effects = storage->get_effects();
 
 	RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
@@ -3920,13 +3925,13 @@ void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_
 	}
 }
 
-void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
 	for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
 		if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
 			continue;
 		}
 
-		RendererStorage::InstanceShaderParam p;
+		RendererMaterialStorage::InstanceShaderParam p;
 		p.info = ShaderLanguage::uniform_to_property_info(E->get());
 		p.info.name = E->key(); //supply name
 		p.index = E->get().instance_index;
@@ -3994,23 +3999,23 @@ RendererSceneRenderRD::FogMaterialData::~FogMaterialData() {
 	free_parameters_uniform_set(uniform_set);
 }
 
-RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
+RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
 	FogShaderData *shader_data = memnew(FogShaderData);
 	return shader_data;
 }
 
-RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
+RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
 	return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func();
 };
 
-RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
 	FogMaterialData *material_data = memnew(FogMaterialData);
 	material_data->shader_data = p_shader;
 	//update will happen later anyway so do nothing.
 	return material_data;
 }
 
-RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) {
 	return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
 };
 
@@ -4068,6 +4073,9 @@ Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vecto
 }
 
 void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
 	RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
 	ERR_FAIL_COND(!rb);
@@ -4268,7 +4276,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			FogMaterialData *material = nullptr;
 
 			if (fog_material.is_valid()) {
-				material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+				material = (FogMaterialData *)material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG);
 				if (!material || !material->shader_data->valid) {
 					material = nullptr;
 				}
@@ -4276,7 +4284,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 
 			if (!material) {
 				fog_material = volumetric_fog.default_material;
-				material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+				material = (FogMaterialData *)material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG);
 			}
 
 			ERR_FAIL_COND(!material);
@@ -5605,12 +5613,13 @@ uint32_t RendererSceneRenderRD::get_max_elements() const {
 }
 
 RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
-	texture_storage = RendererRD::TextureStorage::get_singleton();
 	storage = p_storage;
 	singleton = this;
 }
 
 void RendererSceneRenderRD::init() {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	max_cluster_elements = get_max_elements();
 
 	directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
@@ -5667,8 +5676,8 @@ void RendererSceneRenderRD::init() {
 			volumetric_fog_modes.push_back("");
 			volumetric_fog.shader.initialize(volumetric_fog_modes);
 
-			storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
-			storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
+			material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
+			material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
 			volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
 		}
 
@@ -5707,9 +5716,9 @@ void RendererSceneRenderRD::init() {
 
 		{
 			// default material and shader for fog shader
-			volumetric_fog.default_shader = storage->shader_allocate();
-			storage->shader_initialize(volumetric_fog.default_shader);
-			storage->shader_set_code(volumetric_fog.default_shader, R"(
+			volumetric_fog.default_shader = material_storage->shader_allocate();
+			material_storage->shader_initialize(volumetric_fog.default_shader);
+			material_storage->shader_set_code(volumetric_fog.default_shader, R"(
 // Default fog shader.
 
 shader_type fog;
@@ -5719,11 +5728,11 @@ void fog() {
 	ALBEDO = vec3(1.0);
 }
 )");
-			volumetric_fog.default_material = storage->material_allocate();
-			storage->material_initialize(volumetric_fog.default_material);
-			storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
+			volumetric_fog.default_material = material_storage->material_allocate();
+			material_storage->material_initialize(volumetric_fog.default_material);
+			material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
 
-			FogMaterialData *md = (FogMaterialData *)storage->material_get_data(volumetric_fog.default_material, RendererStorageRD::SHADER_TYPE_FOG);
+			FogMaterialData *md = (FogMaterialData *)material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG);
 			volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
 
 			Vector<RD::Uniform> uniforms;
@@ -5753,7 +5762,7 @@ void fog() {
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 2;
-				u.append_id(storage->global_variables_get_storage_buffer());
+				u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
 				uniforms.push_back(u);
 			}
 
@@ -5822,6 +5831,8 @@ void fog() {
 }
 
 RendererSceneRenderRD::~RendererSceneRenderRD() {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
 	for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
 		RD::get_singleton()->free(E.value.cubemap);
 	}
@@ -5838,20 +5849,10 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
 		volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
 		RD::get_singleton()->free(volumetric_fog.volume_ubo);
 		RD::get_singleton()->free(volumetric_fog.params_ubo);
-		storage->free(volumetric_fog.default_shader);
-		storage->free(volumetric_fog.default_material);
-	}
-
-	RendererSceneSkyRD::SkyMaterialData *md = (RendererSceneSkyRD::SkyMaterialData *)storage->material_get_data(sky.sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
-	sky.sky_shader.shader.version_free(md->shader_data->version);
-	RD::get_singleton()->free(sky.sky_scene_state.directional_light_buffer);
-	RD::get_singleton()->free(sky.sky_scene_state.uniform_buffer);
-	memdelete_arr(sky.sky_scene_state.directional_lights);
-	memdelete_arr(sky.sky_scene_state.last_frame_directional_lights);
-	storage->free(sky.sky_shader.default_shader);
-	storage->free(sky.sky_shader.default_material);
-	storage->free(sky.sky_scene_state.fog_shader);
-	storage->free(sky.sky_scene_state.fog_material);
+		material_storage->shader_free(volumetric_fog.default_shader);
+		material_storage->material_free(volumetric_fog.default_material);
+	}
+
 	memdelete_arr(directional_penumbra_shadow_kernel);
 	memdelete_arr(directional_soft_shadow_kernel);
 	memdelete_arr(penumbra_shadow_kernel);

+ 7 - 9
servers/rendering/renderer_rd/renderer_scene_render_rd.h

@@ -41,7 +41,6 @@
 #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"
@@ -93,7 +92,6 @@ class RendererSceneRenderRD : public RendererSceneRender {
 	friend RendererSceneGIRD;
 
 protected:
-	RendererRD::TextureStorage *texture_storage;
 	RendererStorageRD *storage;
 	double time;
 	double time_step = 0;
@@ -909,7 +907,7 @@ private:
 	void _volumetric_fog_erase(RenderBuffers *rb);
 	void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
 
-	struct FogShaderData : public RendererStorageRD::ShaderData {
+	struct FogShaderData : public RendererRD::ShaderData {
 		bool valid;
 		RID version;
 
@@ -929,7 +927,7 @@ private:
 		virtual void set_code(const String &p_Code);
 		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
 		virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
-		virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
 		virtual bool is_param_texture(const StringName &p_param) const;
 		virtual bool is_animated() const;
 		virtual bool casts_shadows() const;
@@ -939,7 +937,7 @@ private:
 		virtual ~FogShaderData();
 	};
 
-	struct FogMaterialData : public RendererStorageRD::MaterialData {
+	struct FogMaterialData : public RendererRD::MaterialData {
 		FogShaderData *shader_data;
 		RID uniform_set;
 		bool uniform_set_updated;
@@ -950,11 +948,11 @@ private:
 		virtual ~FogMaterialData();
 	};
 
-	RendererStorageRD::ShaderData *_create_fog_shader_func();
-	static RendererStorageRD::ShaderData *_create_fog_shader_funcs();
+	RendererRD::ShaderData *_create_fog_shader_func();
+	static RendererRD::ShaderData *_create_fog_shader_funcs();
 
-	RendererStorageRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
-	static RendererStorageRD::MaterialData *_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader);
+	RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
+	static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader);
 
 	RID shadow_sampler;
 

+ 54 - 35
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/material_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/rendering_server_default.h"
 
@@ -177,13 +178,13 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par
 	}
 }
 
-void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
 	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
 		if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
 			continue;
 		}
 
-		RendererStorage::InstanceShaderParam p;
+		RendererMaterialStorage::InstanceShaderParam p;
 		p.info = ShaderLanguage::uniform_to_property_info(E.value);
 		p.info.name = E.key; //supply name
 		p.index = E.value.instance_index;
@@ -767,24 +768,24 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage,
 ////////////////////////////////////////////////////////////////////////////////
 // RendererSceneSkyRD
 
-RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
+RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
 	SkyShaderData *shader_data = memnew(SkyShaderData);
 	return shader_data;
 }
 
-RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
+RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
 	// !BAS! Why isn't _create_sky_shader_func not just static too?
 	return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func();
 };
 
-RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
 	SkyMaterialData *material_data = memnew(SkyMaterialData);
 	material_data->shader_data = p_shader;
 	//update will happen later anyway so do nothing.
 	return material_data;
 }
 
-RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) {
 	// !BAS! same here, we could just make _create_sky_material_func static?
 	return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
 };
@@ -797,6 +798,7 @@ RendererSceneSkyRD::RendererSceneSkyRD() {
 
 void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	storage = p_storage;
 
 	{
@@ -833,8 +835,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
 	}
 
 	// register our shader funds
-	storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
-	storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
+	material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
+	material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
 
 	{
 		ShaderCompiler::DefaultIdentifierActions actions;
@@ -896,10 +898,10 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
 
 	{
 		// default material and shader for sky shader
-		sky_shader.default_shader = storage->shader_allocate();
-		storage->shader_initialize(sky_shader.default_shader);
+		sky_shader.default_shader = material_storage->shader_allocate();
+		material_storage->shader_initialize(sky_shader.default_shader);
 
-		storage->shader_set_code(sky_shader.default_shader, R"(
+		material_storage->shader_set_code(sky_shader.default_shader, R"(
 // Default sky shader.
 
 shader_type sky;
@@ -909,12 +911,12 @@ void sky() {
 }
 )");
 
-		sky_shader.default_material = storage->material_allocate();
-		storage->material_initialize(sky_shader.default_material);
+		sky_shader.default_material = material_storage->material_allocate();
+		material_storage->material_initialize(sky_shader.default_material);
 
-		storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
+		material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
 
-		SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
+		SkyMaterialData *md = (SkyMaterialData *)material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY);
 		sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND);
 
 		sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO));
@@ -947,7 +949,7 @@ void sky() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 1;
-			u.append_id(storage->global_variables_get_storage_buffer());
+			u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -986,10 +988,10 @@ void sky() {
 
 	{
 		// Need defaults for using fog with clear color
-		sky_scene_state.fog_shader = storage->shader_allocate();
-		storage->shader_initialize(sky_scene_state.fog_shader);
+		sky_scene_state.fog_shader = material_storage->shader_allocate();
+		material_storage->shader_initialize(sky_scene_state.fog_shader);
 
-		storage->shader_set_code(sky_scene_state.fog_shader, R"(
+		material_storage->shader_set_code(sky_scene_state.fog_shader, R"(
 // Default clear color sky shader.
 
 shader_type sky;
@@ -1000,10 +1002,10 @@ void sky() {
 	COLOR = clear_color.rgb;
 }
 )");
-		sky_scene_state.fog_material = storage->material_allocate();
-		storage->material_initialize(sky_scene_state.fog_material);
+		sky_scene_state.fog_material = material_storage->material_allocate();
+		material_storage->material_initialize(sky_scene_state.fog_material);
 
-		storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
+		material_storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
 
 		Vector<RD::Uniform> uniforms;
 		{
@@ -1054,7 +1056,19 @@ void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
 }
 
 RendererSceneSkyRD::~RendererSceneSkyRD() {
-	// TODO cleanup anything created in init...
+	// cleanup anything created in init...
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+	SkyMaterialData *md = (SkyMaterialData *)material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY);
+	sky_shader.shader.version_free(md->shader_data->version);
+	RD::get_singleton()->free(sky_scene_state.directional_light_buffer);
+	RD::get_singleton()->free(sky_scene_state.uniform_buffer);
+	memdelete_arr(sky_scene_state.directional_lights);
+	memdelete_arr(sky_scene_state.last_frame_directional_lights);
+	material_storage->shader_free(sky_shader.default_shader);
+	material_storage->material_free(sky_shader.default_material);
+	material_storage->shader_free(sky_scene_state.fog_shader);
+	material_storage->material_free(sky_scene_state.fog_material);
 
 	if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.uniform_set)) {
 		RD::get_singleton()->free(sky_scene_state.uniform_set);
@@ -1072,6 +1086,7 @@ RendererSceneSkyRD::~RendererSceneSkyRD() {
 }
 
 void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	ERR_FAIL_COND(!p_env);
 
 	SkyMaterialData *material = nullptr;
@@ -1085,7 +1100,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
 		sky_material = sky_get_material(p_env->sky);
 
 		if (sky_material.is_valid()) {
-			material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+			material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 			if (!material || !material->shader_data->valid) {
 				material = nullptr;
 			}
@@ -1093,7 +1108,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
 
 		if (!material) {
 			sky_material = sky_shader.default_material;
-			material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+			material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 		}
 
 		ERR_FAIL_COND(!material);
@@ -1282,6 +1297,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
 }
 
 void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	ERR_FAIL_COND(!p_env);
 
 	Sky *sky = get_sky(p_env->sky);
@@ -1292,7 +1308,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
 	SkyMaterialData *material = nullptr;
 
 	if (sky_material.is_valid()) {
-		material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+		material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 		if (!material || !material->shader_data->valid) {
 			material = nullptr;
 		}
@@ -1300,7 +1316,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
 
 	if (!material) {
 		sky_material = sky_shader.default_material;
-		material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+		material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 	}
 
 	ERR_FAIL_COND(!material);
@@ -1450,6 +1466,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
 }
 
 void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	ERR_FAIL_COND(!p_env);
 
 	ERR_FAIL_COND(p_view_count == 0);
@@ -1467,7 +1484,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
 		sky_material = sky_get_material(p_env->sky);
 
 		if (sky_material.is_valid()) {
-			material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+			material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 			if (!material || !material->shader_data->valid) {
 				material = nullptr;
 			}
@@ -1475,13 +1492,13 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
 
 		if (!material) {
 			sky_material = sky_shader.default_material;
-			material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+			material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 		}
 	}
 
 	if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
 		sky_material = sky_scene_state.fog_material;
-		material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+		material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 	}
 
 	ERR_FAIL_COND(!material);
@@ -1556,6 +1573,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
 }
 
 void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	ERR_FAIL_COND(!p_env);
 
 	ERR_FAIL_COND(p_view_count == 0);
@@ -1570,7 +1588,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
 	sky_material = sky_get_material(p_env->sky);
 
 	if (sky_material.is_valid()) {
-		material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+		material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 		if (!material || !material->shader_data->valid) {
 			material = nullptr;
 		}
@@ -1578,7 +1596,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
 
 	if (!material) {
 		sky_material = sky_shader.default_material;
-		material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+		material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 	}
 
 	ERR_FAIL_COND(!material);
@@ -1640,6 +1658,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
 }
 
 void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
 	ERR_FAIL_COND(!p_env);
 
 	ERR_FAIL_COND(p_view_count == 0);
@@ -1657,7 +1676,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
 		sky_material = sky_get_material(p_env->sky);
 
 		if (sky_material.is_valid()) {
-			material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+			material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 			if (!material || !material->shader_data->valid) {
 				material = nullptr;
 			}
@@ -1665,13 +1684,13 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
 
 		if (!material) {
 			sky_material = sky_shader.default_material;
-			material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+			material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 		}
 	}
 
 	if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
 		sky_material = sky_scene_state.fog_material;
-		material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+		material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
 	}
 
 	ERR_FAIL_COND(!material);

+ 7 - 7
servers/rendering/renderer_rd/renderer_scene_sky_rd.h

@@ -105,7 +105,7 @@ private:
 		// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
 	};
 
-	struct SkyShaderData : public RendererStorageRD::ShaderData {
+	struct SkyShaderData : public RendererRD::ShaderData {
 		bool valid;
 		RID version;
 
@@ -129,7 +129,7 @@ private:
 		virtual void set_code(const String &p_Code);
 		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
 		virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
-		virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
 		virtual bool is_param_texture(const StringName &p_param) const;
 		virtual bool is_animated() const;
 		virtual bool casts_shadows() const;
@@ -227,7 +227,7 @@ public:
 		RID default_shader_rd;
 	} sky_shader;
 
-	struct SkyMaterialData : public RendererStorageRD::MaterialData {
+	struct SkyMaterialData : public RendererRD::MaterialData {
 		SkyShaderData *shader_data;
 		RID uniform_set;
 		bool uniform_set_updated;
@@ -281,11 +281,11 @@ public:
 	mutable RID_Owner<Sky, true> sky_owner;
 	int roughness_layers;
 
-	RendererStorageRD::ShaderData *_create_sky_shader_func();
-	static RendererStorageRD::ShaderData *_create_sky_shader_funcs();
+	RendererRD::ShaderData *_create_sky_shader_func();
+	static RendererRD::ShaderData *_create_sky_shader_funcs();
 
-	RendererStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
-	static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader);
+	RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
+	static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader);
 
 	RendererSceneSkyRD();
 	void init(RendererStorageRD *p_storage);

File diff suppressed because it is too large
+ 0 - 1619
servers/rendering/renderer_rd/renderer_storage_rd.cpp


+ 9 - 245
servers/rendering/renderer_rd/renderer_storage_rd.h

@@ -42,6 +42,8 @@
 #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/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
 #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
 #include "servers/rendering/renderer_scene_render.h"
 #include "servers/rendering/rendering_device.h"
@@ -127,61 +129,6 @@ public:
 		}
 	}
 
-	enum ShaderType {
-		SHADER_TYPE_2D,
-		SHADER_TYPE_3D,
-		SHADER_TYPE_PARTICLES,
-		SHADER_TYPE_SKY,
-		SHADER_TYPE_FOG,
-		SHADER_TYPE_MAX
-	};
-
-	struct ShaderData {
-		virtual void set_code(const String &p_Code) = 0;
-		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
-		virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
-
-		virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0;
-		virtual bool is_param_texture(const StringName &p_param) const = 0;
-		virtual bool is_animated() const = 0;
-		virtual bool casts_shadows() const = 0;
-		virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
-		virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
-
-		virtual ~ShaderData() {}
-	};
-
-	typedef ShaderData *(*ShaderDataRequestFunction)();
-
-	struct MaterialData {
-		void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
-		void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
-
-		virtual void set_render_priority(int p_priority) = 0;
-		virtual void set_next_pass(RID p_pass) = 0;
-		virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
-		virtual ~MaterialData();
-
-		//to be used internally by update_parameters, in the most common configuration of material parameters
-		bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
-		void free_parameters_uniform_set(RID p_uniform_set);
-
-	private:
-		friend class RendererStorageRD;
-		RID self;
-		List<RID>::Element *global_buffer_E = nullptr;
-		List<RID>::Element *global_texture_E = nullptr;
-		uint64_t global_textures_pass = 0;
-		Map<StringName, uint64_t> used_global_textures;
-
-		//internally by update_parameters_uniform_set
-		Vector<uint8_t> ubo_data;
-		RID uniform_buffer;
-		Vector<RID> texture_cache;
-	};
-	typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
-	static void _material_uniform_set_erased(void *p_material);
-
 	enum DefaultRDBuffer {
 		DEFAULT_RD_BUFFER_VERTEX,
 		DEFAULT_RD_BUFFER_NORMAL,
@@ -205,50 +152,6 @@ private:
 	RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
 	RID default_rd_storage_buffer;
 
-	/* SHADER */
-
-	struct Material;
-
-	struct Shader {
-		ShaderData *data;
-		String code;
-		ShaderType type;
-		Map<StringName, Map<int, RID>> default_texture_parameter;
-		Set<Material *> owners;
-	};
-
-	ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
-	mutable RID_Owner<Shader, true> shader_owner;
-
-	/* Material */
-
-	struct Material {
-		RID self;
-		MaterialData *data = nullptr;
-		Shader *shader = nullptr;
-		//shortcut to shader data and type
-		ShaderType shader_type = SHADER_TYPE_MAX;
-		uint32_t shader_id = 0;
-		bool uniform_dirty = false;
-		bool texture_dirty = false;
-		Map<StringName, Variant> params;
-		int32_t priority = 0;
-		RID next_pass;
-		SelfList<Material> update_element;
-
-		Dependency dependency;
-
-		Material() :
-				update_element(this) {}
-	};
-
-	MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
-	mutable RID_Owner<Material, true> material_owner;
-
-	SelfList<Material>::List material_update_list;
-	void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
-	void _update_queued_materials();
-
 	/* Mesh */
 
 	struct MeshInstance;
@@ -714,7 +617,7 @@ private:
 
 	Particles *particle_update_list = nullptr;
 
-	struct ParticlesShaderData : public ShaderData {
+	struct ParticlesShaderData : public RendererRD::ShaderData {
 		bool valid;
 		RID version;
 		bool uses_collision = false;
@@ -740,7 +643,7 @@ private:
 		virtual void set_code(const String &p_Code);
 		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
 		virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
-		virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
 		virtual bool is_param_texture(const StringName &p_param) const;
 		virtual bool is_animated() const;
 		virtual bool casts_shadows() const;
@@ -751,12 +654,12 @@ private:
 		virtual ~ParticlesShaderData();
 	};
 
-	ShaderData *_create_particles_shader_func();
-	static RendererStorageRD::ShaderData *_create_particles_shader_funcs() {
+	RendererRD::ShaderData *_create_particles_shader_func();
+	static RendererRD::ShaderData *_create_particles_shader_funcs() {
 		return base_singleton->_create_particles_shader_func();
 	}
 
-	struct ParticlesMaterialData : public MaterialData {
+	struct ParticlesMaterialData : public RendererRD::MaterialData {
 		ParticlesShaderData *shader_data = nullptr;
 		RID uniform_set;
 
@@ -766,8 +669,8 @@ private:
 		virtual ~ParticlesMaterialData();
 	};
 
-	MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
-	static RendererStorageRD::MaterialData *_create_particles_material_funcs(ShaderData *p_shader) {
+	RendererRD::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
+	static RendererRD::MaterialData *_create_particles_material_funcs(RendererRD::ShaderData *p_shader) {
 		return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
 	}
 
@@ -1054,72 +957,6 @@ private:
 		RID pipelines[SHADER_MAX];
 	} rt_sdf;
 
-	/* GLOBAL SHADER VARIABLES */
-
-	struct GlobalVariables {
-		enum {
-			BUFFER_DIRTY_REGION_SIZE = 1024
-		};
-		struct Variable {
-			Set<RID> texture_materials; // materials using this
-
-			RS::GlobalVariableType type;
-			Variant value;
-			Variant override;
-			int32_t buffer_index; //for vectors
-			int32_t buffer_elements; //for vectors
-		};
-
-		HashMap<StringName, Variable> variables;
-
-		struct Value {
-			float x;
-			float y;
-			float z;
-			float w;
-		};
-
-		struct ValueInt {
-			int32_t x;
-			int32_t y;
-			int32_t z;
-			int32_t w;
-		};
-
-		struct ValueUInt {
-			uint32_t x;
-			uint32_t y;
-			uint32_t z;
-			uint32_t w;
-		};
-
-		struct ValueUsage {
-			uint32_t elements = 0;
-		};
-
-		List<RID> materials_using_buffer;
-		List<RID> materials_using_texture;
-
-		RID buffer;
-		Value *buffer_values;
-		ValueUsage *buffer_usage;
-		bool *buffer_dirty_regions;
-		uint32_t buffer_dirty_region_count = 0;
-
-		uint32_t buffer_size;
-
-		bool must_update_texture_materials = false;
-		bool must_update_buffer_materials = false;
-
-		HashMap<RID, int32_t> instance_buffer_pos;
-
-	} global_variables;
-
-	int32_t _global_variable_allocate(uint32_t p_elements);
-	void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
-	void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
-
-	void _update_global_variables();
 	/* EFFECTS */
 
 	EffectsRD *effects = nullptr;
@@ -1138,58 +975,6 @@ public:
 
 	void sampler_rd_set_default(float p_mipmap_bias);
 
-	/* SHADER API */
-
-	RID shader_allocate();
-	void shader_initialize(RID p_shader);
-
-	void shader_set_code(RID p_shader, const String &p_code);
-	String shader_get_code(RID p_shader) const;
-	void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
-
-	void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index);
-	RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const;
-	Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
-	void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
-
-	virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const;
-
-	/* COMMON MATERIAL API */
-
-	RID material_allocate();
-	void material_initialize(RID p_material);
-
-	void material_set_shader(RID p_material, RID p_shader);
-
-	void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value);
-	Variant material_get_param(RID p_material, const StringName &p_param) const;
-
-	void material_set_next_pass(RID p_material, RID p_next_material);
-	void material_set_render_priority(RID p_material, int priority);
-
-	bool material_is_animated(RID p_material);
-	bool material_casts_shadows(RID p_material);
-
-	void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
-
-	void material_update_dependency(RID p_material, DependencyTracker *p_instance);
-
-	void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
-
-	_FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
-		Material *material = material_owner.get_or_null(p_material);
-		return material->shader_id;
-	}
-
-	_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
-		Material *material = material_owner.get_or_null(p_material);
-		if (!material || material->shader_type != p_shader_type) {
-			return nullptr;
-		} else {
-			return material->data;
-		}
-	}
-
 	/* MESH API */
 
 	RID mesh_allocate();
@@ -1972,27 +1757,6 @@ public:
 	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform);
 	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active);
 
-	/* GLOBAL VARIABLES API */
-
-	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value);
-	virtual void global_variable_remove(const StringName &p_name);
-	virtual Vector<StringName> global_variable_get_list() const;
-
-	virtual void global_variable_set(const StringName &p_name, const Variant &p_value);
-	virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value);
-	virtual Variant global_variable_get(const StringName &p_name) const;
-	virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const;
-	RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
-
-	virtual void global_variables_load_settings(bool p_load_textures = true);
-	virtual void global_variables_clear();
-
-	virtual int32_t global_variables_instance_allocate(RID p_instance);
-	virtual void global_variables_instance_free(RID p_instance);
-	virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value);
-
-	RID global_variables_get_storage_buffer() const;
-
 	/* RENDER TARGET API */
 
 	RID render_target_create();

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

@@ -0,0 +1,2392 @@
+/*************************************************************************/
+/*  material_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 "material_storage.h"
+#include "core/config/engine.h"
+#include "core/config/project_settings.h"
+#include "core/io/resource_loader.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+///////////////////////////////////////////////////////////////////////////
+// UBI helper functions
+
+_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
+	switch (type) {
+		case ShaderLanguage::TYPE_BOOL: {
+			uint32_t *gui = (uint32_t *)data;
+
+			if (p_array_size > 0) {
+				const PackedInt32Array &ba = value;
+				int s = ba.size();
+				const int *r = ba.ptr();
+
+				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+					if (i < s) {
+						gui[j] = (r[i] != 0) ? 1 : 0;
+					} else {
+						gui[j] = 0;
+					}
+					gui[j + 1] = 0; // ignored
+					gui[j + 2] = 0; // ignored
+					gui[j + 3] = 0; // ignored
+				}
+			} else {
+				bool v = value;
+				gui[0] = v ? 1 : 0;
+			}
+		} break;
+		case ShaderLanguage::TYPE_BVEC2: {
+			uint32_t *gui = (uint32_t *)data;
+
+			if (p_array_size > 0) {
+				const PackedInt32Array &ba = value;
+				int s = ba.size();
+				const int *r = ba.ptr();
+				int count = 2 * p_array_size;
+
+				for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+					if (i < s) {
+						gui[j] = r[i] ? 1 : 0;
+						gui[j + 1] = r[i + 1] ? 1 : 0;
+					} else {
+						gui[j] = 0;
+						gui[j + 1] = 0;
+					}
+					gui[j + 2] = 0; // ignored
+					gui[j + 3] = 0; // ignored
+				}
+			} else {
+				int v = value;
+				gui[0] = v & 1 ? 1 : 0;
+				gui[1] = v & 2 ? 1 : 0;
+			}
+		} break;
+		case ShaderLanguage::TYPE_BVEC3: {
+			uint32_t *gui = (uint32_t *)data;
+
+			if (p_array_size > 0) {
+				const PackedInt32Array &ba = value;
+				int s = ba.size();
+				const int *r = ba.ptr();
+				int count = 3 * p_array_size;
+
+				for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+					if (i < s) {
+						gui[j] = r[i] ? 1 : 0;
+						gui[j + 1] = r[i + 1] ? 1 : 0;
+						gui[j + 2] = r[i + 2] ? 1 : 0;
+					} else {
+						gui[j] = 0;
+						gui[j + 1] = 0;
+						gui[j + 2] = 0;
+					}
+					gui[j + 3] = 0; // ignored
+				}
+			} else {
+				int v = value;
+				gui[0] = (v & 1) ? 1 : 0;
+				gui[1] = (v & 2) ? 1 : 0;
+				gui[2] = (v & 4) ? 1 : 0;
+			}
+		} break;
+		case ShaderLanguage::TYPE_BVEC4: {
+			uint32_t *gui = (uint32_t *)data;
+
+			if (p_array_size > 0) {
+				const PackedInt32Array &ba = value;
+				int s = ba.size();
+				const int *r = ba.ptr();
+				int count = 4 * p_array_size;
+
+				for (int i = 0; i < count; i += 4) {
+					if (i < s) {
+						gui[i] = r[i] ? 1 : 0;
+						gui[i + 1] = r[i + 1] ? 1 : 0;
+						gui[i + 2] = r[i + 2] ? 1 : 0;
+						gui[i + 3] = r[i + 3] ? 1 : 0;
+					} else {
+						gui[i] = 0;
+						gui[i + 1] = 0;
+						gui[i + 2] = 0;
+						gui[i + 3] = 0;
+					}
+				}
+			} else {
+				int v = value;
+				gui[0] = (v & 1) ? 1 : 0;
+				gui[1] = (v & 2) ? 1 : 0;
+				gui[2] = (v & 4) ? 1 : 0;
+				gui[3] = (v & 8) ? 1 : 0;
+			}
+		} break;
+		case ShaderLanguage::TYPE_INT: {
+			int32_t *gui = (int32_t *)data;
+
+			if (p_array_size > 0) {
+				Vector<int> iv = value;
+				int s = iv.size();
+				const int *r = iv.ptr();
+
+				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+					if (i < s) {
+						gui[j] = r[i];
+					} else {
+						gui[j] = 0;
+					}
+					gui[j + 1] = 0; // ignored
+					gui[j + 2] = 0; // ignored
+					gui[j + 3] = 0; // ignored
+				}
+			} else {
+				int v = value;
+				gui[0] = v;
+			}
+		} break;
+		case ShaderLanguage::TYPE_IVEC2: {
+			Vector<int> iv = value;
+			int s = iv.size();
+			int32_t *gui = (int32_t *)data;
+
+			if (p_array_size <= 0) {
+				p_array_size = 1;
+			}
+			int count = 2 * p_array_size;
+
+			const int *r = iv.ptr();
+			for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+				if (i < s) {
+					gui[j] = r[i];
+					gui[j + 1] = r[i + 1];
+				} else {
+					gui[j] = 0;
+					gui[j + 1] = 0;
+				}
+				gui[j + 2] = 0; // ignored
+				gui[j + 3] = 0; // ignored
+			}
+		} break;
+		case ShaderLanguage::TYPE_IVEC3: {
+			Vector<int> iv = value;
+			int s = iv.size();
+			int32_t *gui = (int32_t *)data;
+
+			if (p_array_size <= 0) {
+				p_array_size = 1;
+			}
+			int count = 3 * p_array_size;
+
+			const int *r = iv.ptr();
+			for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+				if (i < s) {
+					gui[j] = r[i];
+					gui[j + 1] = r[i + 1];
+					gui[j + 2] = r[i + 2];
+				} else {
+					gui[j] = 0;
+					gui[j + 1] = 0;
+					gui[j + 2] = 0;
+				}
+				gui[j + 3] = 0; // ignored
+			}
+		} break;
+		case ShaderLanguage::TYPE_IVEC4: {
+			Vector<int> iv = value;
+			int s = iv.size();
+			int32_t *gui = (int32_t *)data;
+
+			if (p_array_size <= 0) {
+				p_array_size = 1;
+			}
+			int count = 4 * p_array_size;
+
+			const int *r = iv.ptr();
+			for (int i = 0; i < count; i += 4) {
+				if (i < s) {
+					gui[i] = r[i];
+					gui[i + 1] = r[i + 1];
+					gui[i + 2] = r[i + 2];
+					gui[i + 3] = r[i + 3];
+				} else {
+					gui[i] = 0;
+					gui[i + 1] = 0;
+					gui[i + 2] = 0;
+					gui[i + 3] = 0;
+				}
+			}
+		} break;
+		case ShaderLanguage::TYPE_UINT: {
+			uint32_t *gui = (uint32_t *)data;
+
+			if (p_array_size > 0) {
+				Vector<int> iv = value;
+				int s = iv.size();
+				const int *r = iv.ptr();
+
+				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+					if (i < s) {
+						gui[j] = r[i];
+					} else {
+						gui[j] = 0;
+					}
+					gui[j + 1] = 0; // ignored
+					gui[j + 2] = 0; // ignored
+					gui[j + 3] = 0; // ignored
+				}
+			} else {
+				int v = value;
+				gui[0] = v;
+			}
+		} break;
+		case ShaderLanguage::TYPE_UVEC2: {
+			Vector<int> iv = value;
+			int s = iv.size();
+			uint32_t *gui = (uint32_t *)data;
+
+			if (p_array_size <= 0) {
+				p_array_size = 1;
+			}
+			int count = 2 * p_array_size;
+
+			const int *r = iv.ptr();
+			for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+				if (i < s) {
+					gui[j] = r[i];
+					gui[j + 1] = r[i + 1];
+				} else {
+					gui[j] = 0;
+					gui[j + 1] = 0;
+				}
+				gui[j + 2] = 0; // ignored
+				gui[j + 3] = 0; // ignored
+			}
+		} break;
+		case ShaderLanguage::TYPE_UVEC3: {
+			Vector<int> iv = value;
+			int s = iv.size();
+			uint32_t *gui = (uint32_t *)data;
+
+			if (p_array_size <= 0) {
+				p_array_size = 1;
+			}
+			int count = 3 * p_array_size;
+
+			const int *r = iv.ptr();
+			for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+				if (i < s) {
+					gui[j] = r[i];
+					gui[j + 1] = r[i + 1];
+					gui[j + 2] = r[i + 2];
+				} else {
+					gui[j] = 0;
+					gui[j + 1] = 0;
+					gui[j + 2] = 0;
+				}
+				gui[j + 3] = 0; // ignored
+			}
+		} break;
+		case ShaderLanguage::TYPE_UVEC4: {
+			Vector<int> iv = value;
+			int s = iv.size();
+			uint32_t *gui = (uint32_t *)data;
+
+			if (p_array_size <= 0) {
+				p_array_size = 1;
+			}
+			int count = 4 * p_array_size;
+
+			const int *r = iv.ptr();
+			for (int i = 0; i < count; i++) {
+				if (i < s) {
+					gui[i] = r[i];
+					gui[i + 1] = r[i + 1];
+					gui[i + 2] = r[i + 2];
+					gui[i + 3] = r[i + 3];
+				} else {
+					gui[i] = 0;
+					gui[i + 1] = 0;
+					gui[i + 2] = 0;
+					gui[i + 3] = 0;
+				}
+			}
+		} break;
+		case ShaderLanguage::TYPE_FLOAT: {
+			float *gui = (float *)data;
+
+			if (p_array_size > 0) {
+				const PackedFloat32Array &a = value;
+				int s = a.size();
+
+				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+					if (i < s) {
+						gui[j] = a[i];
+					} else {
+						gui[j] = 0;
+					}
+					gui[j + 1] = 0; // ignored
+					gui[j + 2] = 0; // ignored
+					gui[j + 3] = 0; // ignored
+				}
+			} else {
+				float v = value;
+				gui[0] = v;
+			}
+		} break;
+		case ShaderLanguage::TYPE_VEC2: {
+			float *gui = (float *)data;
+
+			if (p_array_size > 0) {
+				const PackedVector2Array &a = value;
+				int s = a.size();
+
+				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+					if (i < s) {
+						gui[j] = a[i].x;
+						gui[j + 1] = a[i].y;
+					} else {
+						gui[j] = 0;
+						gui[j + 1] = 0;
+					}
+					gui[j + 2] = 0; // ignored
+					gui[j + 3] = 0; // ignored
+				}
+			} else {
+				Vector2 v = value;
+				gui[0] = v.x;
+				gui[1] = v.y;
+			}
+		} break;
+		case ShaderLanguage::TYPE_VEC3: {
+			float *gui = (float *)data;
+
+			if (p_array_size > 0) {
+				const PackedVector3Array &a = value;
+				int s = a.size();
+
+				for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+					if (i < s) {
+						gui[j] = a[i].x;
+						gui[j + 1] = a[i].y;
+						gui[j + 2] = a[i].z;
+					} else {
+						gui[j] = 0;
+						gui[j + 1] = 0;
+						gui[j + 2] = 0;
+					}
+					gui[j + 3] = 0; // ignored
+				}
+			} else {
+				Vector3 v = value;
+				gui[0] = v.x;
+				gui[1] = v.y;
+				gui[2] = v.z;
+			}
+		} break;
+		case ShaderLanguage::TYPE_VEC4: {
+			float *gui = (float *)data;
+
+			if (p_array_size > 0) {
+				if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
+					const PackedColorArray &a = value;
+					int s = a.size();
+
+					for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+						if (i < s) {
+							Color color = a[i];
+							if (p_linear_color) {
+								color = color.to_linear();
+							}
+							gui[j] = color.r;
+							gui[j + 1] = color.g;
+							gui[j + 2] = color.b;
+							gui[j + 3] = color.a;
+						} else {
+							gui[j] = 0;
+							gui[j + 1] = 0;
+							gui[j + 2] = 0;
+							gui[j + 3] = 0;
+						}
+					}
+				} else {
+					const PackedFloat32Array &a = value;
+					int s = a.size();
+					int count = 4 * p_array_size;
+
+					for (int i = 0; i < count; i += 4) {
+						if (i + 3 < s) {
+							gui[i] = a[i];
+							gui[i + 1] = a[i + 1];
+							gui[i + 2] = a[i + 2];
+							gui[i + 3] = a[i + 3];
+						} else {
+							gui[i] = 0;
+							gui[i + 1] = 0;
+							gui[i + 2] = 0;
+							gui[i + 3] = 0;
+						}
+					}
+				}
+			} else {
+				if (value.get_type() == Variant::COLOR) {
+					Color v = value;
+
+					if (p_linear_color) {
+						v = v.to_linear();
+					}
+
+					gui[0] = v.r;
+					gui[1] = v.g;
+					gui[2] = v.b;
+					gui[3] = v.a;
+				} else if (value.get_type() == Variant::RECT2) {
+					Rect2 v = value;
+
+					gui[0] = v.position.x;
+					gui[1] = v.position.y;
+					gui[2] = v.size.x;
+					gui[3] = v.size.y;
+				} else if (value.get_type() == Variant::QUATERNION) {
+					Quaternion v = value;
+
+					gui[0] = v.x;
+					gui[1] = v.y;
+					gui[2] = v.z;
+					gui[3] = v.w;
+				} else {
+					Plane v = value;
+
+					gui[0] = v.normal.x;
+					gui[1] = v.normal.y;
+					gui[2] = v.normal.z;
+					gui[3] = v.d;
+				}
+			}
+		} break;
+		case ShaderLanguage::TYPE_MAT2: {
+			float *gui = (float *)data;
+
+			if (p_array_size > 0) {
+				const PackedFloat32Array &a = value;
+				int s = a.size();
+
+				for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) {
+					if (i + 3 < s) {
+						gui[j] = a[i];
+						gui[j + 1] = a[i + 1];
+
+						gui[j + 4] = a[i + 2];
+						gui[j + 5] = a[i + 3];
+					} else {
+						gui[j] = 1;
+						gui[j + 1] = 0;
+
+						gui[j + 4] = 0;
+						gui[j + 5] = 1;
+					}
+					gui[j + 2] = 0; // ignored
+					gui[j + 3] = 0; // ignored
+					gui[j + 6] = 0; // ignored
+					gui[j + 7] = 0; // ignored
+				}
+			} else {
+				Transform2D v = value;
+
+				//in std140 members of mat2 are treated as vec4s
+				gui[0] = v.elements[0][0];
+				gui[1] = v.elements[0][1];
+				gui[2] = 0; // ignored
+				gui[3] = 0; // ignored
+
+				gui[4] = v.elements[1][0];
+				gui[5] = v.elements[1][1];
+				gui[6] = 0; // ignored
+				gui[7] = 0; // ignored
+			}
+		} break;
+		case ShaderLanguage::TYPE_MAT3: {
+			float *gui = (float *)data;
+
+			if (p_array_size > 0) {
+				const PackedFloat32Array &a = value;
+				int s = a.size();
+
+				for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
+					if (i + 8 < s) {
+						gui[j] = a[i];
+						gui[j + 1] = a[i + 1];
+						gui[j + 2] = a[i + 2];
+
+						gui[j + 4] = a[i + 3];
+						gui[j + 5] = a[i + 4];
+						gui[j + 6] = a[i + 5];
+
+						gui[j + 8] = a[i + 6];
+						gui[j + 9] = a[i + 7];
+						gui[j + 10] = a[i + 8];
+					} else {
+						gui[j] = 1;
+						gui[j + 1] = 0;
+						gui[j + 2] = 0;
+
+						gui[j + 4] = 0;
+						gui[j + 5] = 1;
+						gui[j + 6] = 0;
+
+						gui[j + 8] = 0;
+						gui[j + 9] = 0;
+						gui[j + 10] = 1;
+					}
+					gui[j + 3] = 0; // ignored
+					gui[j + 7] = 0; // ignored
+					gui[j + 11] = 0; // ignored
+				}
+			} else {
+				Basis v = value;
+				gui[0] = v.elements[0][0];
+				gui[1] = v.elements[1][0];
+				gui[2] = v.elements[2][0];
+				gui[3] = 0; // ignored
+
+				gui[4] = v.elements[0][1];
+				gui[5] = v.elements[1][1];
+				gui[6] = v.elements[2][1];
+				gui[7] = 0; // ignored
+
+				gui[8] = v.elements[0][2];
+				gui[9] = v.elements[1][2];
+				gui[10] = v.elements[2][2];
+				gui[11] = 0; // ignored
+			}
+		} break;
+		case ShaderLanguage::TYPE_MAT4: {
+			float *gui = (float *)data;
+
+			if (p_array_size > 0) {
+				const PackedFloat32Array &a = value;
+				int s = a.size();
+
+				for (int i = 0; i < p_array_size * 16; i += 16) {
+					if (i + 15 < s) {
+						gui[i] = a[i];
+						gui[i + 1] = a[i + 1];
+						gui[i + 2] = a[i + 2];
+						gui[i + 3] = a[i + 3];
+
+						gui[i + 4] = a[i + 4];
+						gui[i + 5] = a[i + 5];
+						gui[i + 6] = a[i + 6];
+						gui[i + 7] = a[i + 7];
+
+						gui[i + 8] = a[i + 8];
+						gui[i + 9] = a[i + 9];
+						gui[i + 10] = a[i + 10];
+						gui[i + 11] = a[i + 11];
+
+						gui[i + 12] = a[i + 12];
+						gui[i + 13] = a[i + 13];
+						gui[i + 14] = a[i + 14];
+						gui[i + 15] = a[i + 15];
+					} else {
+						gui[i] = 1;
+						gui[i + 1] = 0;
+						gui[i + 2] = 0;
+						gui[i + 3] = 0;
+
+						gui[i + 4] = 0;
+						gui[i + 5] = 1;
+						gui[i + 6] = 0;
+						gui[i + 7] = 0;
+
+						gui[i + 8] = 0;
+						gui[i + 9] = 0;
+						gui[i + 10] = 1;
+						gui[i + 11] = 0;
+
+						gui[i + 12] = 0;
+						gui[i + 13] = 0;
+						gui[i + 14] = 0;
+						gui[i + 15] = 1;
+					}
+				}
+			} else {
+				Transform3D v = value;
+				gui[0] = v.basis.elements[0][0];
+				gui[1] = v.basis.elements[1][0];
+				gui[2] = v.basis.elements[2][0];
+				gui[3] = 0;
+
+				gui[4] = v.basis.elements[0][1];
+				gui[5] = v.basis.elements[1][1];
+				gui[6] = v.basis.elements[2][1];
+				gui[7] = 0;
+
+				gui[8] = v.basis.elements[0][2];
+				gui[9] = v.basis.elements[1][2];
+				gui[10] = v.basis.elements[2][2];
+				gui[11] = 0;
+
+				gui[12] = v.origin.x;
+				gui[13] = v.origin.y;
+				gui[14] = v.origin.z;
+				gui[15] = 1;
+			}
+		} break;
+		default: {
+		}
+	}
+}
+
+_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
+	switch (type) {
+		case ShaderLanguage::TYPE_BOOL: {
+			uint32_t *gui = (uint32_t *)data;
+			*gui = value[0].boolean ? 1 : 0;
+		} break;
+		case ShaderLanguage::TYPE_BVEC2: {
+			uint32_t *gui = (uint32_t *)data;
+			gui[0] = value[0].boolean ? 1 : 0;
+			gui[1] = value[1].boolean ? 1 : 0;
+
+		} break;
+		case ShaderLanguage::TYPE_BVEC3: {
+			uint32_t *gui = (uint32_t *)data;
+			gui[0] = value[0].boolean ? 1 : 0;
+			gui[1] = value[1].boolean ? 1 : 0;
+			gui[2] = value[2].boolean ? 1 : 0;
+
+		} break;
+		case ShaderLanguage::TYPE_BVEC4: {
+			uint32_t *gui = (uint32_t *)data;
+			gui[0] = value[0].boolean ? 1 : 0;
+			gui[1] = value[1].boolean ? 1 : 0;
+			gui[2] = value[2].boolean ? 1 : 0;
+			gui[3] = value[3].boolean ? 1 : 0;
+
+		} break;
+		case ShaderLanguage::TYPE_INT: {
+			int32_t *gui = (int32_t *)data;
+			gui[0] = value[0].sint;
+
+		} break;
+		case ShaderLanguage::TYPE_IVEC2: {
+			int32_t *gui = (int32_t *)data;
+
+			for (int i = 0; i < 2; i++) {
+				gui[i] = value[i].sint;
+			}
+
+		} break;
+		case ShaderLanguage::TYPE_IVEC3: {
+			int32_t *gui = (int32_t *)data;
+
+			for (int i = 0; i < 3; i++) {
+				gui[i] = value[i].sint;
+			}
+
+		} break;
+		case ShaderLanguage::TYPE_IVEC4: {
+			int32_t *gui = (int32_t *)data;
+
+			for (int i = 0; i < 4; i++) {
+				gui[i] = value[i].sint;
+			}
+
+		} break;
+		case ShaderLanguage::TYPE_UINT: {
+			uint32_t *gui = (uint32_t *)data;
+			gui[0] = value[0].uint;
+
+		} break;
+		case ShaderLanguage::TYPE_UVEC2: {
+			int32_t *gui = (int32_t *)data;
+
+			for (int i = 0; i < 2; i++) {
+				gui[i] = value[i].uint;
+			}
+		} break;
+		case ShaderLanguage::TYPE_UVEC3: {
+			int32_t *gui = (int32_t *)data;
+
+			for (int i = 0; i < 3; i++) {
+				gui[i] = value[i].uint;
+			}
+
+		} break;
+		case ShaderLanguage::TYPE_UVEC4: {
+			int32_t *gui = (int32_t *)data;
+
+			for (int i = 0; i < 4; i++) {
+				gui[i] = value[i].uint;
+			}
+		} break;
+		case ShaderLanguage::TYPE_FLOAT: {
+			float *gui = (float *)data;
+			gui[0] = value[0].real;
+
+		} break;
+		case ShaderLanguage::TYPE_VEC2: {
+			float *gui = (float *)data;
+
+			for (int i = 0; i < 2; i++) {
+				gui[i] = value[i].real;
+			}
+
+		} break;
+		case ShaderLanguage::TYPE_VEC3: {
+			float *gui = (float *)data;
+
+			for (int i = 0; i < 3; i++) {
+				gui[i] = value[i].real;
+			}
+
+		} break;
+		case ShaderLanguage::TYPE_VEC4: {
+			float *gui = (float *)data;
+
+			for (int i = 0; i < 4; i++) {
+				gui[i] = value[i].real;
+			}
+		} break;
+		case ShaderLanguage::TYPE_MAT2: {
+			float *gui = (float *)data;
+
+			//in std140 members of mat2 are treated as vec4s
+			gui[0] = value[0].real;
+			gui[1] = value[1].real;
+			gui[2] = 0;
+			gui[3] = 0;
+			gui[4] = value[2].real;
+			gui[5] = value[3].real;
+			gui[6] = 0;
+			gui[7] = 0;
+		} break;
+		case ShaderLanguage::TYPE_MAT3: {
+			float *gui = (float *)data;
+
+			gui[0] = value[0].real;
+			gui[1] = value[1].real;
+			gui[2] = value[2].real;
+			gui[3] = 0;
+			gui[4] = value[3].real;
+			gui[5] = value[4].real;
+			gui[6] = value[5].real;
+			gui[7] = 0;
+			gui[8] = value[6].real;
+			gui[9] = value[7].real;
+			gui[10] = value[8].real;
+			gui[11] = 0;
+		} break;
+		case ShaderLanguage::TYPE_MAT4: {
+			float *gui = (float *)data;
+
+			for (int i = 0; i < 16; i++) {
+				gui[i] = value[i].real;
+			}
+		} break;
+		default: {
+		}
+	}
+}
+
+_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) {
+	if (p_array_size <= 0) {
+		p_array_size = 1;
+	}
+
+	switch (type) {
+		case ShaderLanguage::TYPE_BOOL:
+		case ShaderLanguage::TYPE_INT:
+		case ShaderLanguage::TYPE_UINT:
+		case ShaderLanguage::TYPE_FLOAT: {
+			memset(data, 0, 4 * p_array_size);
+		} break;
+		case ShaderLanguage::TYPE_BVEC2:
+		case ShaderLanguage::TYPE_IVEC2:
+		case ShaderLanguage::TYPE_UVEC2:
+		case ShaderLanguage::TYPE_VEC2: {
+			memset(data, 0, 8 * p_array_size);
+		} break;
+		case ShaderLanguage::TYPE_BVEC3:
+		case ShaderLanguage::TYPE_IVEC3:
+		case ShaderLanguage::TYPE_UVEC3:
+		case ShaderLanguage::TYPE_VEC3:
+		case ShaderLanguage::TYPE_BVEC4:
+		case ShaderLanguage::TYPE_IVEC4:
+		case ShaderLanguage::TYPE_UVEC4:
+		case ShaderLanguage::TYPE_VEC4: {
+			memset(data, 0, 16 * p_array_size);
+		} break;
+		case ShaderLanguage::TYPE_MAT2: {
+			memset(data, 0, 32 * p_array_size);
+		} break;
+		case ShaderLanguage::TYPE_MAT3: {
+			memset(data, 0, 48 * p_array_size);
+		} break;
+		case ShaderLanguage::TYPE_MAT4: {
+			memset(data, 0, 64 * p_array_size);
+		} break;
+
+		default: {
+		}
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////
+// MaterialData
+
+void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+	bool uses_global_buffer = false;
+
+	for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
+		if (E.value.order < 0) {
+			continue; // texture, does not go here
+		}
+
+		if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+			continue; //instance uniforms don't appear in the buffer
+		}
+
+		if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
+			//this is a global variable, get the index to it
+			GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key);
+			uint32_t index = 0;
+			if (gv) {
+				index = gv->buffer_index;
+			} else {
+				WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly.");
+			}
+
+			uint32_t offset = p_uniform_offsets[E.value.order];
+			uint32_t *intptr = (uint32_t *)&p_buffer[offset];
+			*intptr = index;
+			uses_global_buffer = true;
+			continue;
+		}
+
+		//regular uniform
+		uint32_t offset = p_uniform_offsets[E.value.order];
+#ifdef DEBUG_ENABLED
+		uint32_t size = 0U;
+		// The following code enforces a 16-byte alignment of uniform arrays.
+		if (E.value.array_size > 0) {
+			size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
+			int m = (16 * E.value.array_size);
+			if ((size % m) != 0U) {
+				size += m - (size % m);
+			}
+		} else {
+			size = ShaderLanguage::get_datatype_size(E.value.type);
+		}
+		ERR_CONTINUE(offset + size > p_buffer_size);
+#endif
+		uint8_t *data = &p_buffer[offset];
+		const Map<StringName, Variant>::Element *V = p_parameters.find(E.key);
+
+		if (V) {
+			//user provided
+			_fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
+
+		} else if (E.value.default_value.size()) {
+			//default value
+			_fill_std140_ubo_value(E.value.type, E.value.default_value, data);
+			//value=E.value.default_value;
+		} else {
+			//zero because it was not provided
+			if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+				//colors must be set as black, with alpha as 1.0
+				_fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
+			} else {
+				//else just zero it out
+				_fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
+			}
+		}
+	}
+
+	if (uses_global_buffer != (global_buffer_E != nullptr)) {
+		if (uses_global_buffer) {
+			global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self);
+		} else {
+			material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+			global_buffer_E = nullptr;
+		}
+	}
+}
+
+MaterialData::~MaterialData() {
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+	if (global_buffer_E) {
+		//unregister global buffers
+		material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+	}
+
+	if (global_texture_E) {
+		//unregister global textures
+
+		for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
+			GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+			if (v) {
+				v->texture_materials.erase(self);
+			}
+		}
+		//unregister material from those using global textures
+		material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+	}
+
+	if (uniform_buffer.is_valid()) {
+		RD::get_singleton()->free(uniform_buffer);
+	}
+}
+
+void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+	TextureStorage *texture_storage = TextureStorage::get_singleton();
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+#ifdef TOOLS_ENABLED
+	Texture *roughness_detect_texture = nullptr;
+	RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
+	Texture *normal_detect_texture = nullptr;
+#endif
+
+	bool uses_global_textures = false;
+	global_textures_pass++;
+
+	for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
+		const StringName &uniform_name = p_texture_uniforms[i].name;
+		int uniform_array_size = p_texture_uniforms[i].array_size;
+
+		Vector<RID> textures;
+
+		if (p_texture_uniforms[i].global) {
+			uses_global_textures = true;
+
+			GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name);
+			if (v) {
+				if (v->buffer_index >= 0) {
+					WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
+
+				} else {
+					Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name);
+					if (!E) {
+						E = used_global_textures.insert(uniform_name, global_textures_pass);
+						v->texture_materials.insert(self);
+					} else {
+						E->get() = global_textures_pass;
+					}
+
+					textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
+				}
+
+			} else {
+				WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
+			}
+		} else {
+			const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
+			if (V) {
+				if (V->get().is_array()) {
+					Array array = (Array)V->get();
+					if (uniform_array_size > 0) {
+						for (int j = 0; j < array.size(); j++) {
+							textures.push_back(array[j]);
+						}
+					} else {
+						if (array.size() > 0) {
+							textures.push_back(array[0]);
+						}
+					}
+				} else {
+					textures.push_back(V->get());
+				}
+			}
+
+			if (uniform_array_size > 0) {
+				if (textures.size() < uniform_array_size) {
+					const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+					for (int j = textures.size(); j < uniform_array_size; j++) {
+						if (W && W->get().has(j)) {
+							textures.push_back(W->get()[j]);
+						} else {
+							textures.push_back(RID());
+						}
+					}
+				}
+			} else if (textures.is_empty()) {
+				const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+				if (W && W->get().has(0)) {
+					textures.push_back(W->get()[0]);
+				}
+			}
+		}
+
+		RID rd_texture;
+
+		if (textures.is_empty()) {
+			//check default usage
+			switch (p_texture_uniforms[i].type) {
+				case ShaderLanguage::TYPE_ISAMPLER2D:
+				case ShaderLanguage::TYPE_USAMPLER2D:
+				case ShaderLanguage::TYPE_SAMPLER2D: {
+					switch (p_texture_uniforms[i].hint) {
+						case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+						case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+							rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+						} break;
+						case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
+							rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+						} break;
+						case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
+							rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+						} break;
+						case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
+							rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+						} break;
+						default: {
+							rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+						} break;
+					}
+				} break;
+
+				case ShaderLanguage::TYPE_SAMPLERCUBE: {
+					switch (p_texture_uniforms[i].hint) {
+						case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+						case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+							rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+						} break;
+						default: {
+							rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
+						} break;
+					}
+				} break;
+				case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
+					rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+				} break;
+
+				case ShaderLanguage::TYPE_ISAMPLER3D:
+				case ShaderLanguage::TYPE_USAMPLER3D:
+				case ShaderLanguage::TYPE_SAMPLER3D: {
+					rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+				} break;
+
+				case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+				case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+				case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
+					rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+				} break;
+
+				default: {
+				}
+			}
+#ifdef TOOLS_ENABLED
+			if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
+				roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
+			}
+#endif
+			if (uniform_array_size > 0) {
+				for (int j = 0; j < uniform_array_size; j++) {
+					p_textures[k++] = rd_texture;
+				}
+			} else {
+				p_textures[k++] = rd_texture;
+			}
+		} else {
+			bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO);
+
+			for (int j = 0; j < textures.size(); j++) {
+				Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]);
+
+				if (tex) {
+					rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
+#ifdef TOOLS_ENABLED
+					if (tex->detect_3d_callback && p_use_linear_color) {
+						tex->detect_3d_callback(tex->detect_3d_callback_ud);
+					}
+					if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
+						if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
+							normal_detect_texture = tex;
+						}
+						tex->detect_normal_callback(tex->detect_normal_callback_ud);
+					}
+					if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) {
+						//find the normal texture
+						roughness_detect_texture = tex;
+						roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
+					}
+#endif
+				}
+				if (rd_texture.is_null()) {
+					rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+				}
+#ifdef TOOLS_ENABLED
+				if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
+					roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
+				}
+#endif
+				p_textures[k++] = rd_texture;
+			}
+		}
+	}
+	{
+		//for textures no longer used, unregister them
+		List<Map<StringName, uint64_t>::Element *> to_delete;
+		for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
+			if (E->get() != global_textures_pass) {
+				to_delete.push_back(E);
+
+				GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key());
+				if (v) {
+					v->texture_materials.erase(self);
+				}
+			}
+		}
+
+		while (to_delete.front()) {
+			used_global_textures.erase(to_delete.front()->get());
+			to_delete.pop_front();
+		}
+		//handle registering/unregistering global textures
+		if (uses_global_textures != (global_texture_E != nullptr)) {
+			if (uses_global_textures) {
+				global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self);
+			} else {
+				material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+				global_texture_E = nullptr;
+			}
+		}
+	}
+}
+
+void MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
+	if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
+		RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
+		RD::get_singleton()->free(p_uniform_set);
+	}
+}
+
+bool MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+	if ((uint32_t)ubo_data.size() != p_ubo_size) {
+		p_uniform_dirty = true;
+		if (uniform_buffer.is_valid()) {
+			RD::get_singleton()->free(uniform_buffer);
+			uniform_buffer = RID();
+		}
+
+		ubo_data.resize(p_ubo_size);
+		if (ubo_data.size()) {
+			uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
+			memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
+		}
+
+		//clear previous uniform set
+		if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+			RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+			RD::get_singleton()->free(uniform_set);
+			uniform_set = RID();
+		}
+	}
+
+	//check whether buffer changed
+	if (p_uniform_dirty && ubo_data.size()) {
+		update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
+		RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
+	}
+
+	uint32_t tex_uniform_count = 0U;
+	for (int i = 0; i < p_texture_uniforms.size(); i++) {
+		tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1);
+	}
+
+	if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
+		texture_cache.resize(tex_uniform_count);
+		p_textures_dirty = true;
+
+		//clear previous uniform set
+		if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+			RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+			RD::get_singleton()->free(uniform_set);
+			uniform_set = RID();
+		}
+	}
+
+	if (p_textures_dirty && tex_uniform_count) {
+		update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
+	}
+
+	if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
+		// This material does not require an uniform set, so don't create it.
+		return false;
+	}
+
+	if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+		//no reason to update uniform set, only UBO (or nothing) was needed to update
+		return false;
+	}
+
+	Vector<RD::Uniform> uniforms;
+
+	{
+		if (p_ubo_size) {
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+			u.binding = 0;
+			u.append_id(uniform_buffer);
+			uniforms.push_back(u);
+		}
+
+		const RID *textures = texture_cache.ptrw();
+		for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
+			const int array_size = p_texture_uniforms[i].array_size;
+
+			RD::Uniform u;
+			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+			u.binding = 1 + k;
+			if (array_size > 0) {
+				for (int j = 0; j < array_size; j++) {
+					u.append_id(textures[k++]);
+				}
+			} else {
+				u.append_id(textures[k++]);
+			}
+			uniforms.push_back(u);
+		}
+	}
+
+	uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
+
+	RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, MaterialStorage::_material_uniform_set_erased, &self);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// MaterialStorage
+
+MaterialStorage *MaterialStorage::singleton = nullptr;
+
+MaterialStorage *MaterialStorage::get_singleton() {
+	return singleton;
+}
+
+MaterialStorage::MaterialStorage() {
+	singleton = this;
+
+	for (int i = 0; i < SHADER_TYPE_MAX; i++) {
+		shader_data_request_func[i] = nullptr;
+	}
+
+	static_assert(sizeof(GlobalVariables::Value) == 16);
+
+	global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+	global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
+	memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+	global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
+	global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+	memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+	global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+}
+
+MaterialStorage::~MaterialStorage() {
+	memdelete_arr(global_variables.buffer_values);
+	memdelete_arr(global_variables.buffer_usage);
+	memdelete_arr(global_variables.buffer_dirty_regions);
+	RD::get_singleton()->free(global_variables.buffer);
+
+	singleton = nullptr;
+}
+
+/* GLOBAL VARIABLE API */
+
+int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
+	int32_t idx = 0;
+	while (idx + p_elements <= global_variables.buffer_size) {
+		if (global_variables.buffer_usage[idx].elements == 0) {
+			bool valid = true;
+			for (uint32_t i = 1; i < p_elements; i++) {
+				if (global_variables.buffer_usage[idx + i].elements > 0) {
+					valid = false;
+					idx += i + global_variables.buffer_usage[idx + i].elements;
+					break;
+				}
+			}
+
+			if (!valid) {
+				continue; //if not valid, idx is in new position
+			}
+
+			return idx;
+		} else {
+			idx += global_variables.buffer_usage[idx].elements;
+		}
+	}
+
+	return -1;
+}
+
+void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
+	switch (p_type) {
+		case RS::GLOBAL_VAR_TYPE_BOOL: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			bool b = p_value;
+			bv.x = b ? 1.0 : 0.0;
+			bv.y = 0.0;
+			bv.z = 0.0;
+			bv.w = 0.0;
+
+		} break;
+		case RS::GLOBAL_VAR_TYPE_BVEC2: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			uint32_t bvec = p_value;
+			bv.x = (bvec & 1) ? 1.0 : 0.0;
+			bv.y = (bvec & 2) ? 1.0 : 0.0;
+			bv.z = 0.0;
+			bv.w = 0.0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_BVEC3: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			uint32_t bvec = p_value;
+			bv.x = (bvec & 1) ? 1.0 : 0.0;
+			bv.y = (bvec & 2) ? 1.0 : 0.0;
+			bv.z = (bvec & 4) ? 1.0 : 0.0;
+			bv.w = 0.0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_BVEC4: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			uint32_t bvec = p_value;
+			bv.x = (bvec & 1) ? 1.0 : 0.0;
+			bv.y = (bvec & 2) ? 1.0 : 0.0;
+			bv.z = (bvec & 4) ? 1.0 : 0.0;
+			bv.w = (bvec & 8) ? 1.0 : 0.0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_INT: {
+			GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+			int32_t v = p_value;
+			bv.x = v;
+			bv.y = 0;
+			bv.z = 0;
+			bv.w = 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_IVEC2: {
+			GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+			Vector2i v = p_value;
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = 0;
+			bv.w = 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_IVEC3: {
+			GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+			Vector3i v = p_value;
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = v.z;
+			bv.w = 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_IVEC4: {
+			GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+			Vector<int32_t> v = p_value;
+			bv.x = v.size() >= 1 ? v[0] : 0;
+			bv.y = v.size() >= 2 ? v[1] : 0;
+			bv.z = v.size() >= 3 ? v[2] : 0;
+			bv.w = v.size() >= 4 ? v[3] : 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_RECT2I: {
+			GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+			Rect2i v = p_value;
+			bv.x = v.position.x;
+			bv.y = v.position.y;
+			bv.z = v.size.x;
+			bv.w = v.size.y;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_UINT: {
+			GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+			uint32_t v = p_value;
+			bv.x = v;
+			bv.y = 0;
+			bv.z = 0;
+			bv.w = 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_UVEC2: {
+			GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+			Vector2i v = p_value;
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = 0;
+			bv.w = 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_UVEC3: {
+			GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+			Vector3i v = p_value;
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = v.z;
+			bv.w = 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_UVEC4: {
+			GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+			Vector<int32_t> v = p_value;
+			bv.x = v.size() >= 1 ? v[0] : 0;
+			bv.y = v.size() >= 2 ? v[1] : 0;
+			bv.z = v.size() >= 3 ? v[2] : 0;
+			bv.w = v.size() >= 4 ? v[3] : 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_FLOAT: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			float v = p_value;
+			bv.x = v;
+			bv.y = 0;
+			bv.z = 0;
+			bv.w = 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_VEC2: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			Vector2 v = p_value;
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = 0;
+			bv.w = 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_VEC3: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			Vector3 v = p_value;
+			bv.x = v.x;
+			bv.y = v.y;
+			bv.z = v.z;
+			bv.w = 0;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_VEC4: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			Plane v = p_value;
+			bv.x = v.normal.x;
+			bv.y = v.normal.y;
+			bv.z = v.normal.z;
+			bv.w = v.d;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_COLOR: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			Color v = p_value;
+			bv.x = v.r;
+			bv.y = v.g;
+			bv.z = v.b;
+			bv.w = v.a;
+
+			GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+			v = v.to_linear();
+			bv_linear.x = v.r;
+			bv_linear.y = v.g;
+			bv_linear.z = v.b;
+			bv_linear.w = v.a;
+
+		} break;
+		case RS::GLOBAL_VAR_TYPE_RECT2: {
+			GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+			Rect2 v = p_value;
+			bv.x = v.position.x;
+			bv.y = v.position.y;
+			bv.z = v.size.x;
+			bv.w = v.size.y;
+		} break;
+		case RS::GLOBAL_VAR_TYPE_MAT2: {
+			GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+			Vector<float> m2 = p_value;
+			if (m2.size() < 4) {
+				m2.resize(4);
+			}
+			bv[0].x = m2[0];
+			bv[0].y = m2[1];
+			bv[0].z = 0;
+			bv[0].w = 0;
+
+			bv[1].x = m2[2];
+			bv[1].y = m2[3];
+			bv[1].z = 0;
+			bv[1].w = 0;
+
+		} break;
+		case RS::GLOBAL_VAR_TYPE_MAT3: {
+			GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+			Basis v = p_value;
+			bv[0].x = v.elements[0][0];
+			bv[0].y = v.elements[1][0];
+			bv[0].z = v.elements[2][0];
+			bv[0].w = 0;
+
+			bv[1].x = v.elements[0][1];
+			bv[1].y = v.elements[1][1];
+			bv[1].z = v.elements[2][1];
+			bv[1].w = 0;
+
+			bv[2].x = v.elements[0][2];
+			bv[2].y = v.elements[1][2];
+			bv[2].z = v.elements[2][2];
+			bv[2].w = 0;
+
+		} break;
+		case RS::GLOBAL_VAR_TYPE_MAT4: {
+			GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+
+			Vector<float> m2 = p_value;
+			if (m2.size() < 16) {
+				m2.resize(16);
+			}
+
+			bv[0].x = m2[0];
+			bv[0].y = m2[1];
+			bv[0].z = m2[2];
+			bv[0].w = m2[3];
+
+			bv[1].x = m2[4];
+			bv[1].y = m2[5];
+			bv[1].z = m2[6];
+			bv[1].w = m2[7];
+
+			bv[2].x = m2[8];
+			bv[2].y = m2[9];
+			bv[2].z = m2[10];
+			bv[2].w = m2[11];
+
+			bv[3].x = m2[12];
+			bv[3].y = m2[13];
+			bv[3].z = m2[14];
+			bv[3].w = m2[15];
+
+		} break;
+		case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
+			GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+			Transform2D v = p_value;
+			bv[0].x = v.elements[0][0];
+			bv[0].y = v.elements[0][1];
+			bv[0].z = 0;
+			bv[0].w = 0;
+
+			bv[1].x = v.elements[1][0];
+			bv[1].y = v.elements[1][1];
+			bv[1].z = 0;
+			bv[1].w = 0;
+
+			bv[2].x = v.elements[2][0];
+			bv[2].y = v.elements[2][1];
+			bv[2].z = 1;
+			bv[2].w = 0;
+
+		} break;
+		case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
+			GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+			Transform3D v = p_value;
+			bv[0].x = v.basis.elements[0][0];
+			bv[0].y = v.basis.elements[1][0];
+			bv[0].z = v.basis.elements[2][0];
+			bv[0].w = 0;
+
+			bv[1].x = v.basis.elements[0][1];
+			bv[1].y = v.basis.elements[1][1];
+			bv[1].z = v.basis.elements[2][1];
+			bv[1].w = 0;
+
+			bv[2].x = v.basis.elements[0][2];
+			bv[2].y = v.basis.elements[1][2];
+			bv[2].z = v.basis.elements[2][2];
+			bv[2].w = 0;
+
+			bv[3].x = v.origin.x;
+			bv[3].y = v.origin.y;
+			bv[3].z = v.origin.z;
+			bv[3].w = 1;
+
+		} break;
+		default: {
+			ERR_FAIL();
+		}
+	}
+}
+
+void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
+	int32_t prev_chunk = -1;
+
+	for (int32_t i = 0; i < p_elements; i++) {
+		int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+		if (chunk != prev_chunk) {
+			if (!global_variables.buffer_dirty_regions[chunk]) {
+				global_variables.buffer_dirty_regions[chunk] = true;
+				global_variables.buffer_dirty_region_count++;
+			}
+		}
+
+		prev_chunk = chunk;
+	}
+}
+
+void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
+	ERR_FAIL_COND(global_variables.variables.has(p_name));
+	GlobalVariables::Variable gv;
+	gv.type = p_type;
+	gv.value = p_value;
+	gv.buffer_index = -1;
+
+	if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+		//is texture
+		global_variables.must_update_texture_materials = true; //normally there are none
+	} else {
+		gv.buffer_elements = 1;
+		if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
+			//color needs to elements to store srgb and linear
+			gv.buffer_elements = 2;
+		}
+		if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
+			//color needs to elements to store srgb and linear
+			gv.buffer_elements = 3;
+		}
+		if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
+			//color needs to elements to store srgb and linear
+			gv.buffer_elements = 4;
+		}
+
+		//is vector, allocate in buffer and update index
+		gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+		ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
+		global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+		_global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+		_global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+
+		global_variables.must_update_buffer_materials = true; //normally there are none
+	}
+
+	global_variables.variables[p_name] = gv;
+}
+
+void MaterialStorage::global_variable_remove(const StringName &p_name) {
+	if (!global_variables.variables.has(p_name)) {
+		return;
+	}
+	GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+	if (gv.buffer_index >= 0) {
+		global_variables.buffer_usage[gv.buffer_index].elements = 0;
+		global_variables.must_update_buffer_materials = true;
+	} else {
+		global_variables.must_update_texture_materials = true;
+	}
+
+	global_variables.variables.erase(p_name);
+}
+
+Vector<StringName> MaterialStorage::global_variable_get_list() const {
+	if (!Engine::get_singleton()->is_editor_hint()) {
+		ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
+	}
+
+	const StringName *K = nullptr;
+	Vector<StringName> names;
+	while ((K = global_variables.variables.next(K))) {
+		names.push_back(*K);
+	}
+	names.sort_custom<StringName::AlphCompare>();
+	return names;
+}
+
+void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
+	ERR_FAIL_COND(!global_variables.variables.has(p_name));
+	GlobalVariables::Variable &gv = global_variables.variables[p_name];
+	gv.value = p_value;
+	if (gv.override.get_type() == Variant::NIL) {
+		if (gv.buffer_index >= 0) {
+			//buffer
+			_global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+			_global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+		} else {
+			//texture
+			MaterialStorage *material_storage = MaterialStorage::get_singleton();
+			for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+				Material *material = material_storage->get_material(E->get());
+				ERR_CONTINUE(!material);
+				material_storage->_material_queue_update(material, false, true);
+			}
+		}
+	}
+}
+
+void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
+	if (!global_variables.variables.has(p_name)) {
+		return; //variable may not exist
+	}
+
+	ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
+
+	GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+	gv.override = p_value;
+
+	if (gv.buffer_index >= 0) {
+		//buffer
+		if (gv.override.get_type() == Variant::NIL) {
+			_global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+		} else {
+			_global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+		}
+
+		_global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+	} else {
+		//texture
+		MaterialStorage *material_storage = MaterialStorage::get_singleton();
+		for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+			Material *material = material_storage->get_material(E->get());
+			ERR_CONTINUE(!material);
+			material_storage->_material_queue_update(material, false, true);
+		}
+	}
+}
+
+Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+	if (!Engine::get_singleton()->is_editor_hint()) {
+		ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
+	}
+
+	if (!global_variables.variables.has(p_name)) {
+		return Variant();
+	}
+
+	return global_variables.variables[p_name].value;
+}
+
+RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const {
+	if (!global_variables.variables.has(p_name)) {
+		return RS::GLOBAL_VAR_TYPE_MAX;
+	}
+
+	return global_variables.variables[p_name].type;
+}
+
+RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+	if (!Engine::get_singleton()->is_editor_hint()) {
+		ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
+	}
+
+	return global_variable_get_type_internal(p_name);
+}
+
+void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+	List<PropertyInfo> settings;
+	ProjectSettings::get_singleton()->get_property_list(&settings);
+
+	for (const PropertyInfo &E : settings) {
+		if (E.name.begins_with("shader_globals/")) {
+			StringName name = E.name.get_slice("/", 1);
+			Dictionary d = ProjectSettings::get_singleton()->get(E.name);
+
+			ERR_CONTINUE(!d.has("type"));
+			ERR_CONTINUE(!d.has("value"));
+
+			String type = d["type"];
+
+			static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
+				"bool",
+				"bvec2",
+				"bvec3",
+				"bvec4",
+				"int",
+				"ivec2",
+				"ivec3",
+				"ivec4",
+				"rect2i",
+				"uint",
+				"uvec2",
+				"uvec3",
+				"uvec4",
+				"float",
+				"vec2",
+				"vec3",
+				"vec4",
+				"color",
+				"rect2",
+				"mat2",
+				"mat3",
+				"mat4",
+				"transform_2d",
+				"transform",
+				"sampler2D",
+				"sampler2DArray",
+				"sampler3D",
+				"samplerCube",
+			};
+
+			RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+
+			for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
+				if (global_var_type_names[i] == type) {
+					gvtype = RS::GlobalVariableType(i);
+					break;
+				}
+			}
+
+			ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
+
+			Variant value = d["value"];
+
+			if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+				//textire
+				if (!p_load_textures) {
+					value = RID();
+					continue;
+				}
+
+				String path = value;
+				RES resource = ResourceLoader::load(path);
+				ERR_CONTINUE(resource.is_null());
+				value = resource;
+			}
+
+			if (global_variables.variables.has(name)) {
+				//has it, update it
+				global_variable_set(name, value);
+			} else {
+				global_variable_add(name, gvtype, value);
+			}
+		}
+	}
+}
+
+void MaterialStorage::global_variables_clear() {
+	global_variables.variables.clear(); //not right but for now enough
+}
+
+RID MaterialStorage::global_variables_get_storage_buffer() const {
+	return global_variables.buffer;
+}
+
+int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
+	ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
+	int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+	global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
+	ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
+	global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+	return pos;
+}
+
+void MaterialStorage::global_variables_instance_free(RID p_instance) {
+	ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
+	int32_t pos = global_variables.instance_buffer_pos[p_instance];
+	if (pos >= 0) {
+		global_variables.buffer_usage[pos].elements = 0;
+	}
+	global_variables.instance_buffer_pos.erase(p_instance);
+}
+
+void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+	if (!global_variables.instance_buffer_pos.has(p_instance)) {
+		return; //just not allocated, ignore
+	}
+	int32_t pos = global_variables.instance_buffer_pos[p_instance];
+
+	if (pos < 0) {
+		return; //again, not allocated, ignore
+	}
+	ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+	ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+	ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
+		ShaderLanguage::TYPE_MAX, //nil
+		ShaderLanguage::TYPE_BOOL, //bool
+		ShaderLanguage::TYPE_INT, //int
+		ShaderLanguage::TYPE_FLOAT, //float
+		ShaderLanguage::TYPE_MAX, //string
+		ShaderLanguage::TYPE_VEC2, //vec2
+		ShaderLanguage::TYPE_IVEC2, //vec2i
+		ShaderLanguage::TYPE_VEC4, //rect2
+		ShaderLanguage::TYPE_IVEC4, //rect2i
+		ShaderLanguage::TYPE_VEC3, // vec3
+		ShaderLanguage::TYPE_IVEC3, //vec3i
+		ShaderLanguage::TYPE_MAX, //xform2d not supported here
+		ShaderLanguage::TYPE_VEC4, //plane
+		ShaderLanguage::TYPE_VEC4, //quat
+		ShaderLanguage::TYPE_MAX, //aabb not supported here
+		ShaderLanguage::TYPE_MAX, //basis not supported here
+		ShaderLanguage::TYPE_MAX, //xform not supported here
+		ShaderLanguage::TYPE_VEC4 //color
+	};
+
+	ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
+
+	ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+	pos += p_index;
+
+	_fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
+	_global_variable_mark_buffer_dirty(pos, 1);
+}
+
+void MaterialStorage::_update_global_variables() {
+	MaterialStorage *material_storage = MaterialStorage::get_singleton();
+	if (global_variables.buffer_dirty_region_count > 0) {
+		uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+		if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
+			// 25% of regions dirty, just update all buffer
+			RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
+			memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
+		} else {
+			uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+
+			for (uint32_t i = 0; i < total_regions; i++) {
+				if (global_variables.buffer_dirty_regions[i]) {
+					RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
+
+					global_variables.buffer_dirty_regions[i] = false;
+				}
+			}
+		}
+
+		global_variables.buffer_dirty_region_count = 0;
+	}
+
+	if (global_variables.must_update_buffer_materials) {
+		// only happens in the case of a buffer variable added or removed,
+		// so not often.
+		for (const RID &E : global_variables.materials_using_buffer) {
+			Material *material = material_storage->get_material(E);
+			ERR_CONTINUE(!material); //wtf
+
+			material_storage->_material_queue_update(material, true, false);
+		}
+
+		global_variables.must_update_buffer_materials = false;
+	}
+
+	if (global_variables.must_update_texture_materials) {
+		// only happens in the case of a buffer variable added or removed,
+		// so not often.
+		for (const RID &E : global_variables.materials_using_texture) {
+			Material *material = material_storage->get_material(E);
+			ERR_CONTINUE(!material); //wtf
+
+			material_storage->_material_queue_update(material, false, true);
+		}
+
+		global_variables.must_update_texture_materials = false;
+	}
+}
+
+/* SHADER API */
+
+RID MaterialStorage::shader_allocate() {
+	return shader_owner.allocate_rid();
+}
+
+void MaterialStorage::shader_initialize(RID p_rid) {
+	Shader shader;
+	shader.data = nullptr;
+	shader.type = SHADER_TYPE_MAX;
+
+	shader_owner.initialize_rid(p_rid, shader);
+}
+
+void MaterialStorage::shader_free(RID p_rid) {
+	Shader *shader = shader_owner.get_or_null(p_rid);
+	ERR_FAIL_COND(!shader);
+
+	//make material unreference this
+	while (shader->owners.size()) {
+		material_set_shader(shader->owners.front()->get()->self, RID());
+	}
+
+	//clear data if exists
+	if (shader->data) {
+		memdelete(shader->data);
+	}
+	shader_owner.free(p_rid);
+}
+
+void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND(!shader);
+
+	shader->code = p_code;
+	String mode_string = ShaderLanguage::get_shader_type(p_code);
+
+	ShaderType new_type;
+	if (mode_string == "canvas_item") {
+		new_type = SHADER_TYPE_2D;
+	} else if (mode_string == "particles") {
+		new_type = SHADER_TYPE_PARTICLES;
+	} else if (mode_string == "spatial") {
+		new_type = SHADER_TYPE_3D;
+	} else if (mode_string == "sky") {
+		new_type = SHADER_TYPE_SKY;
+	} else if (mode_string == "fog") {
+		new_type = SHADER_TYPE_FOG;
+	} else {
+		new_type = SHADER_TYPE_MAX;
+	}
+
+	if (new_type != shader->type) {
+		if (shader->data) {
+			memdelete(shader->data);
+			shader->data = nullptr;
+		}
+
+		for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+			Material *material = E->get();
+			material->shader_type = new_type;
+			if (material->data) {
+				memdelete(material->data);
+				material->data = nullptr;
+			}
+		}
+
+		shader->type = new_type;
+
+		if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) {
+			shader->data = shader_data_request_func[new_type]();
+		} else {
+			shader->type = SHADER_TYPE_MAX; //invalid
+		}
+
+		for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+			Material *material = E->get();
+			if (shader->data) {
+				material->data = material_get_data_request_function(new_type)(shader->data);
+				material->data->self = material->self;
+				material->data->set_next_pass(material->next_pass);
+				material->data->set_render_priority(material->priority);
+			}
+			material->shader_type = new_type;
+		}
+
+		if (shader->data) {
+			for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
+				for (const KeyValue<int, RID> &E2 : E.value) {
+					shader->data->set_default_texture_param(E.key, E2.value, E2.key);
+				}
+			}
+		}
+	}
+
+	if (shader->data) {
+		shader->data->set_code(p_code);
+	}
+
+	for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+		Material *material = E->get();
+		material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+		_material_queue_update(material, true, true);
+	}
+}
+
+String MaterialStorage::shader_get_code(RID p_shader) const {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND_V(!shader, String());
+	return shader->code;
+}
+
+void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND(!shader);
+	if (shader->data) {
+		return shader->data->get_param_list(p_param_list);
+	}
+}
+
+void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND(!shader);
+
+	if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) {
+		if (!shader->default_texture_parameter.has(p_name)) {
+			shader->default_texture_parameter[p_name] = Map<int, RID>();
+		}
+		shader->default_texture_parameter[p_name][p_index] = p_texture;
+	} else {
+		if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+			shader->default_texture_parameter[p_name].erase(p_index);
+
+			if (shader->default_texture_parameter[p_name].is_empty()) {
+				shader->default_texture_parameter.erase(p_name);
+			}
+		}
+	}
+	if (shader->data) {
+		shader->data->set_default_texture_param(p_name, p_texture, p_index);
+	}
+	for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+		Material *material = E->get();
+		_material_queue_update(material, false, true);
+	}
+}
+
+RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND_V(!shader, RID());
+	if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+		return shader->default_texture_parameter[p_name][p_index];
+	}
+
+	return RID();
+}
+
+Variant MaterialStorage::shader_get_param_default(RID p_shader, const StringName &p_param) const {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND_V(!shader, Variant());
+	if (shader->data) {
+		return shader->data->get_default_parameter(p_param);
+	}
+	return Variant();
+}
+
+void MaterialStorage::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) {
+	ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
+	shader_data_request_func[p_shader_type] = p_function;
+}
+
+RS::ShaderNativeSourceCode MaterialStorage::shader_get_native_source_code(RID p_shader) const {
+	Shader *shader = shader_owner.get_or_null(p_shader);
+	ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
+	if (shader->data) {
+		return shader->data->get_native_source_code();
+	}
+	return RS::ShaderNativeSourceCode();
+}
+
+/* MATERIAL API */
+
+void MaterialStorage::_material_uniform_set_erased(void *p_material) {
+	RID rid = *(RID *)p_material;
+	Material *material = MaterialStorage::get_singleton()->get_material(rid);
+	if (material) {
+		if (material->data) {
+			// Uniform set may be gone because a dependency was erased. This happens
+			// if a texture is deleted, so re-create it.
+			MaterialStorage::get_singleton()->_material_queue_update(material, false, true);
+		}
+		material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+	}
+}
+
+void MaterialStorage::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
+	material->uniform_dirty = material->uniform_dirty || p_uniform;
+	material->texture_dirty = material->texture_dirty || p_texture;
+
+	if (material->update_element.in_list()) {
+		return;
+	}
+
+	material_update_list.add(&material->update_element);
+}
+
+void MaterialStorage::_update_queued_materials() {
+	while (material_update_list.first()) {
+		Material *material = material_update_list.first()->self();
+		bool uniforms_changed = false;
+
+		if (material->data) {
+			uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
+		}
+		material->texture_dirty = false;
+		material->uniform_dirty = false;
+
+		material_update_list.remove(&material->update_element);
+
+		if (uniforms_changed) {
+			//some implementations such as 3D renderer cache the matreial uniform set, so update is required
+			material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+		}
+	}
+}
+
+RID MaterialStorage::material_allocate() {
+	return material_owner.allocate_rid();
+}
+
+void MaterialStorage::material_initialize(RID p_rid) {
+	material_owner.initialize_rid(p_rid);
+	Material *material = material_owner.get_or_null(p_rid);
+	material->self = p_rid;
+}
+
+void MaterialStorage::material_free(RID p_rid) {
+	Material *material = material_owner.get_or_null(p_rid);
+	ERR_FAIL_COND(!material);
+
+	material_set_shader(p_rid, RID()); //clean up shader
+	material->dependency.deleted_notify(p_rid);
+
+	material_owner.free(p_rid);
+}
+
+void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	if (material->data) {
+		memdelete(material->data);
+		material->data = nullptr;
+	}
+
+	if (material->shader) {
+		material->shader->owners.erase(material);
+		material->shader = nullptr;
+		material->shader_type = SHADER_TYPE_MAX;
+	}
+
+	if (p_shader.is_null()) {
+		material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+		material->shader_id = 0;
+		return;
+	}
+
+	Shader *shader = get_shader(p_shader);
+	ERR_FAIL_COND(!shader);
+	material->shader = shader;
+	material->shader_type = shader->type;
+	material->shader_id = p_shader.get_local_index();
+	shader->owners.insert(material);
+
+	if (shader->type == SHADER_TYPE_MAX) {
+		return;
+	}
+
+	ERR_FAIL_COND(shader->data == nullptr);
+
+	material->data = material_data_request_func[shader->type](shader->data);
+	material->data->self = p_material;
+	material->data->set_next_pass(material->next_pass);
+	material->data->set_render_priority(material->priority);
+	//updating happens later
+	material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+	_material_queue_update(material, true, true);
+}
+
+void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	if (p_value.get_type() == Variant::NIL) {
+		material->params.erase(p_param);
+	} else {
+		ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed
+		material->params[p_param] = p_value;
+	}
+
+	if (material->shader && material->shader->data) { //shader is valid
+		bool is_texture = material->shader->data->is_param_texture(p_param);
+		_material_queue_update(material, !is_texture, is_texture);
+	} else {
+		_material_queue_update(material, true, true);
+	}
+}
+
+Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, Variant());
+	if (material->params.has(p_param)) {
+		return material->params[p_param];
+	} else {
+		return Variant();
+	}
+}
+
+void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+
+	if (material->next_pass == p_next_material) {
+		return;
+	}
+
+	material->next_pass = p_next_material;
+	if (material->data) {
+		material->data->set_next_pass(p_next_material);
+	}
+
+	material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+}
+
+void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+	material->priority = priority;
+	if (material->data) {
+		material->data->set_render_priority(priority);
+	}
+}
+
+bool MaterialStorage::material_is_animated(RID p_material) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, false);
+	if (material->shader && material->shader->data) {
+		if (material->shader->data->is_animated()) {
+			return true;
+		} else if (material->next_pass.is_valid()) {
+			return material_is_animated(material->next_pass);
+		}
+	}
+	return false; //by default nothing is animated
+}
+
+bool MaterialStorage::material_casts_shadows(RID p_material) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND_V(!material, true);
+	if (material->shader && material->shader->data) {
+		if (material->shader->data->casts_shadows()) {
+			return true;
+		} else if (material->next_pass.is_valid()) {
+			return material_casts_shadows(material->next_pass);
+		}
+	}
+	return true; //by default everything casts shadows
+}
+
+void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+	if (material->shader && material->shader->data) {
+		material->shader->data->get_instance_param_list(r_parameters);
+
+		if (material->next_pass.is_valid()) {
+			material_get_instance_shader_parameters(material->next_pass, r_parameters);
+		}
+	}
+}
+
+void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+	Material *material = material_owner.get_or_null(p_material);
+	ERR_FAIL_COND(!material);
+	p_instance->update_dependency(&material->dependency);
+	if (material->next_pass.is_valid()) {
+		material_update_dependency(material->next_pass, p_instance);
+	}
+}
+
+void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) {
+	ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
+	material_data_request_func[p_shader_type] = p_function;
+}
+
+MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) {
+	ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr);
+	return material_data_request_func[p_shader_type];
+}

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

@@ -0,0 +1,315 @@
+/*************************************************************************/
+/*  material_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 MATERIAL_STORAGE_RD_H
+#define MATERIAL_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/shader_compiler.h"
+#include "servers/rendering/shader_language.h"
+#include "servers/rendering/storage/material_storage.h"
+
+namespace RendererRD {
+
+class MaterialStorage;
+
+/* SHADER Structs */
+
+enum ShaderType {
+	SHADER_TYPE_2D,
+	SHADER_TYPE_3D,
+	SHADER_TYPE_PARTICLES,
+	SHADER_TYPE_SKY,
+	SHADER_TYPE_FOG,
+	SHADER_TYPE_MAX
+};
+
+struct ShaderData {
+	virtual void set_code(const String &p_Code) = 0;
+	virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
+	virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
+
+	virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
+	virtual bool is_param_texture(const StringName &p_param) const = 0;
+	virtual bool is_animated() const = 0;
+	virtual bool casts_shadows() const = 0;
+	virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
+	virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
+
+	virtual ~ShaderData() {}
+};
+
+typedef ShaderData *(*ShaderDataRequestFunction)();
+
+struct Material;
+
+struct Shader {
+	ShaderData *data;
+	String code;
+	ShaderType type;
+	Map<StringName, Map<int, RID>> default_texture_parameter;
+	Set<Material *> owners;
+};
+
+/* Material structs */
+
+struct MaterialData {
+	void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
+	void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
+
+	virtual void set_render_priority(int p_priority) = 0;
+	virtual void set_next_pass(RID p_pass) = 0;
+	virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
+	virtual ~MaterialData();
+
+	//to be used internally by update_parameters, in the most common configuration of material parameters
+	bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+	void free_parameters_uniform_set(RID p_uniform_set);
+
+private:
+	friend class MaterialStorage;
+	RID self;
+	List<RID>::Element *global_buffer_E = nullptr;
+	List<RID>::Element *global_texture_E = nullptr;
+	uint64_t global_textures_pass = 0;
+	Map<StringName, uint64_t> used_global_textures;
+
+	//internally by update_parameters_uniform_set
+	Vector<uint8_t> ubo_data;
+	RID uniform_buffer;
+	Vector<RID> texture_cache;
+};
+
+typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
+
+struct Material {
+	RID self;
+	MaterialData *data = nullptr;
+	Shader *shader = nullptr;
+	//shortcut to shader data and type
+	ShaderType shader_type = SHADER_TYPE_MAX;
+	uint32_t shader_id = 0;
+	bool uniform_dirty = false;
+	bool texture_dirty = false;
+	Map<StringName, Variant> params;
+	int32_t priority = 0;
+	RID next_pass;
+	SelfList<Material> update_element;
+
+	RendererStorage::Dependency dependency;
+
+	Material() :
+			update_element(this) {}
+};
+
+/* Global variable structs */
+struct GlobalVariables {
+	enum {
+		BUFFER_DIRTY_REGION_SIZE = 1024
+	};
+	struct Variable {
+		Set<RID> texture_materials; // materials using this
+
+		RS::GlobalVariableType type;
+		Variant value;
+		Variant override;
+		int32_t buffer_index; //for vectors
+		int32_t buffer_elements; //for vectors
+	};
+
+	HashMap<StringName, Variable> variables;
+
+	struct Value {
+		float x;
+		float y;
+		float z;
+		float w;
+	};
+
+	struct ValueInt {
+		int32_t x;
+		int32_t y;
+		int32_t z;
+		int32_t w;
+	};
+
+	struct ValueUInt {
+		uint32_t x;
+		uint32_t y;
+		uint32_t z;
+		uint32_t w;
+	};
+
+	struct ValueUsage {
+		uint32_t elements = 0;
+	};
+
+	List<RID> materials_using_buffer;
+	List<RID> materials_using_texture;
+
+	RID buffer;
+	Value *buffer_values;
+	ValueUsage *buffer_usage;
+	bool *buffer_dirty_regions;
+	uint32_t buffer_dirty_region_count = 0;
+
+	uint32_t buffer_size;
+
+	bool must_update_texture_materials = false;
+	bool must_update_buffer_materials = false;
+
+	HashMap<RID, int32_t> instance_buffer_pos;
+};
+
+class MaterialStorage : public RendererMaterialStorage {
+private:
+	friend struct MaterialData;
+	static MaterialStorage *singleton;
+
+	/* GLOBAL VARIABLE API */
+
+	GlobalVariables global_variables;
+
+	int32_t _global_variable_allocate(uint32_t p_elements);
+	void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
+	void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+
+	/* SHADER API */
+
+	ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
+	mutable RID_Owner<Shader, true> shader_owner;
+
+	/* MATERIAL API */
+	MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
+	mutable RID_Owner<Material, true> material_owner;
+
+	SelfList<Material>::List material_update_list;
+
+	static void _material_uniform_set_erased(void *p_material);
+
+public:
+	static MaterialStorage *get_singleton();
+
+	MaterialStorage();
+	virtual ~MaterialStorage();
+
+	/* GLOBAL VARIABLE API */
+
+	void _update_global_variables();
+
+	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
+	virtual void global_variable_remove(const StringName &p_name) override;
+	virtual Vector<StringName> global_variable_get_list() const override;
+
+	virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
+	virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
+	virtual Variant global_variable_get(const StringName &p_name) const override;
+	virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
+	RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+
+	virtual void global_variables_load_settings(bool p_load_textures = true) override;
+	virtual void global_variables_clear() override;
+
+	virtual int32_t global_variables_instance_allocate(RID p_instance) override;
+	virtual void global_variables_instance_free(RID p_instance) override;
+	virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+
+	RID global_variables_get_storage_buffer() const;
+
+	/* SHADER API */
+
+	Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); };
+	bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
+
+	virtual RID shader_allocate() override;
+	virtual void shader_initialize(RID p_shader) override;
+	virtual void shader_free(RID p_rid) override;
+
+	virtual void shader_set_code(RID p_shader, const String &p_code) override;
+	virtual String shader_get_code(RID p_shader) const override;
+	virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
+
+	virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
+	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
+	virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const override;
+	void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
+
+	virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override;
+
+	/* MATERIAL API */
+
+	Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
+	bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
+
+	void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
+	void _update_queued_materials();
+
+	virtual RID material_allocate() override;
+	virtual void material_initialize(RID p_material) override;
+	virtual void material_free(RID p_rid) override;
+
+	virtual void material_set_shader(RID p_material, RID p_shader) override;
+
+	virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
+	virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;
+
+	virtual void material_set_next_pass(RID p_material, RID p_next_material) override;
+	virtual void material_set_render_priority(RID p_material, int priority) override;
+
+	virtual bool material_is_animated(RID p_material) override;
+	virtual bool material_casts_shadows(RID p_material) override;
+
+	virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
+
+	virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override;
+
+	void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
+	MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type);
+
+	_FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
+		Material *material = material_owner.get_or_null(p_material);
+		return material->shader_id;
+	}
+
+	_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
+		Material *material = material_owner.get_or_null(p_material);
+		if (!material || material->shader_type != p_shader_type) {
+			return nullptr;
+		} else {
+			return material->data;
+		}
+	}
+};
+
+} // namespace RendererRD
+
+#endif // !MATERIAL_STORAGE_RD_H

+ 1 - 1
servers/rendering/renderer_rd/storage_rd/texture_storage.cpp

@@ -949,7 +949,7 @@ void TextureStorage::texture_set_path(RID p_texture, const String &p_path) {
 }
 
 String TextureStorage::texture_get_path(RID p_texture) const {
-	RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+	Texture *tex = texture_owner.get_or_null(p_texture);
 	ERR_FAIL_COND_V(!tex, String());
 
 	return tex->path;

+ 24 - 24
servers/rendering/renderer_scene_cull.cpp

@@ -1438,7 +1438,7 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c
 		E->get().value = p_value;
 		if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) {
 			//update directly
-			RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value);
+			RSG::material_storage->global_variables_instance_update(p_instance, E->get().index, p_value);
 		}
 	}
 }
@@ -3627,9 +3627,9 @@ void RendererSceneCull::render_particle_colliders() {
 }
 
 void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
-	List<RendererStorage::InstanceShaderParam> plist;
-	RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
-	for (const RendererStorage::InstanceShaderParam &E : plist) {
+	List<RendererMaterialStorage::InstanceShaderParam> plist;
+	RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist);
+	for (const RendererMaterialStorage::InstanceShaderParam &E : plist) {
 		StringName name = E.info.name;
 		if (isparams.has(name)) {
 			if (isparams[name].info.type != E.info.type) {
@@ -3667,11 +3667,11 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 		}
 
 		if (p_instance->material_override.is_valid()) {
-			RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
+			RSG::material_storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
 		}
 
 		if (p_instance->material_overlay.is_valid()) {
-			RSG::storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker);
+			RSG::material_storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker);
 		}
 
 		if (p_instance->base_type == RS::INSTANCE_MESH) {
@@ -3688,7 +3688,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 
 			RID particle_material = RSG::storage->particles_get_process_material(p_instance->base);
 			if (particle_material.is_valid()) {
-				RSG::storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);
+				RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);
 			}
 		}
 
@@ -3704,10 +3704,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 			}
 
 			if (p_instance->material_override.is_valid()) {
-				if (!RSG::storage->material_casts_shadows(p_instance->material_override)) {
+				if (!RSG::material_storage->material_casts_shadows(p_instance->material_override)) {
 					can_cast_shadows = false;
 				}
-				is_animated = RSG::storage->material_is_animated(p_instance->material_override);
+				is_animated = RSG::material_storage->material_is_animated(p_instance->material_override);
 				_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override);
 			} else {
 				if (p_instance->base_type == RS::INSTANCE_MESH) {
@@ -3722,17 +3722,17 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 							if (!mat.is_valid()) {
 								cast_shadows = true;
 							} else {
-								if (RSG::storage->material_casts_shadows(mat)) {
+								if (RSG::material_storage->material_casts_shadows(mat)) {
 									cast_shadows = true;
 								}
 
-								if (RSG::storage->material_is_animated(mat)) {
+								if (RSG::material_storage->material_is_animated(mat)) {
 									is_animated = true;
 								}
 
 								_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
 
-								RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
+								RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
 							}
 						}
 
@@ -3754,16 +3754,16 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 								cast_shadows = true;
 
 							} else {
-								if (RSG::storage->material_casts_shadows(mat)) {
+								if (RSG::material_storage->material_casts_shadows(mat)) {
 									cast_shadows = true;
 								}
-								if (RSG::storage->material_is_animated(mat)) {
+								if (RSG::material_storage->material_is_animated(mat)) {
 									is_animated = true;
 								}
 
 								_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
 
-								RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
+								RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
 							}
 						}
 
@@ -3791,17 +3791,17 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 							if (!mat.is_valid()) {
 								cast_shadows = true;
 							} else {
-								if (RSG::storage->material_casts_shadows(mat)) {
+								if (RSG::material_storage->material_casts_shadows(mat)) {
 									cast_shadows = true;
 								}
 
-								if (RSG::storage->material_is_animated(mat)) {
+								if (RSG::material_storage->material_is_animated(mat)) {
 									is_animated = true;
 								}
 
 								_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
 
-								RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
+								RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
 							}
 						}
 					}
@@ -3813,8 +3813,8 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 			}
 
 			if (p_instance->material_overlay.is_valid()) {
-				can_cast_shadows = can_cast_shadows || RSG::storage->material_casts_shadows(p_instance->material_overlay);
-				is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay);
+				can_cast_shadows = can_cast_shadows || RSG::material_storage->material_casts_shadows(p_instance->material_overlay);
+				is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay);
 				_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay);
 			}
 
@@ -3834,16 +3834,16 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 			if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) {
 				p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
 				if (p_instance->instance_allocated_shader_parameters) {
-					p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
+					p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_variables_instance_allocate(p_instance->self);
 					scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset);
 
 					for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) {
 						if (E.value.value.get_type() != Variant::NIL) {
-							RSG::storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
+							RSG::material_storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
 						}
 					}
 				} else {
-					RSG::storage->global_variables_instance_free(p_instance->self);
+					RSG::material_storage->global_variables_instance_free(p_instance->self);
 					p_instance->instance_allocated_shader_parameters_offset = -1;
 					scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1);
 				}
@@ -3939,7 +3939,7 @@ bool RendererSceneCull::free(RID p_rid) {
 
 		if (instance->instance_allocated_shader_parameters) {
 			//free the used shader parameters
-			RSG::storage->global_variables_instance_free(instance->self);
+			RSG::material_storage->global_variables_instance_free(instance->self);
 		}
 		update_dirty_instances(); //in case something changed this
 

+ 0 - 60
servers/rendering/renderer_storage.h

@@ -65,7 +65,6 @@ public:
 		Map<DependencyTracker *, uint32_t> instances;
 	};
 
-public:
 	struct DependencyTracker {
 		void *userdata = nullptr;
 		typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *);
@@ -120,47 +119,6 @@ public:
 		Set<Dependency *> dependencies;
 	};
 
-	/* SHADER API */
-
-	virtual RID shader_allocate() = 0;
-	virtual void shader_initialize(RID p_rid) = 0;
-
-	virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
-	virtual String shader_get_code(RID p_shader) const = 0;
-	virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
-
-	virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
-	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0;
-	virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
-
-	virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
-
-	/* COMMON MATERIAL API */
-
-	virtual RID material_allocate() = 0;
-	virtual void material_initialize(RID p_rid) = 0;
-
-	virtual void material_set_render_priority(RID p_material, int priority) = 0;
-	virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0;
-
-	virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0;
-	virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0;
-
-	virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0;
-
-	virtual bool material_is_animated(RID p_material) = 0;
-	virtual bool material_casts_shadows(RID p_material) = 0;
-
-	struct InstanceShaderParam {
-		PropertyInfo info;
-		int index;
-		Variant default_value;
-	};
-
-	virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
-
-	virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0;
-
 	/* MESH API */
 
 	virtual RID mesh_allocate() = 0;
@@ -491,24 +449,6 @@ public:
 	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
 	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
 
-	/* GLOBAL VARIABLES */
-
-	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
-	virtual void global_variable_remove(const StringName &p_name) = 0;
-	virtual Vector<StringName> global_variable_get_list() const = 0;
-
-	virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
-	virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
-	virtual Variant global_variable_get(const StringName &p_name) const = 0;
-	virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
-
-	virtual void global_variables_load_settings(bool p_load_textures = true) = 0;
-	virtual void global_variables_clear() = 0;
-
-	virtual int32_t global_variables_instance_allocate(RID p_instance) = 0;
-	virtual void global_variables_instance_free(RID p_instance) = 0;
-	virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
-
 	/* RENDER TARGET */
 
 	enum RenderTargetFlags {

+ 1 - 0
servers/rendering/rendering_server_default.cpp

@@ -400,6 +400,7 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
 	RSG::rasterizer = RendererCompositor::create();
 	RSG::canvas_texture_storage = RSG::rasterizer->get_canvas_texture_storage();
 	RSG::decal_atlas_storage = RSG::rasterizer->get_decal_atlas_storage();
+	RSG::material_storage = RSG::rasterizer->get_material_storage();
 	RSG::texture_storage = RSG::rasterizer->get_texture_storage();
 	RSG::storage = RSG::rasterizer->get_storage();
 	RSG::canvas_render = RSG::rasterizer->get_canvas();

+ 13 - 7
servers/rendering/rendering_server_default.h

@@ -213,14 +213,13 @@ public:
 
 	FUNC2(texture_set_force_redraw_if_visible, RID, bool)
 
-//from now on, calls forwarded to this singleton
+	/* SHADER API */
+
 #undef ServerName
 #undef server_name
 
-#define ServerName RendererStorage
-#define server_name RSG::storage
-
-	/* SHADER API */
+#define ServerName RendererMaterialStorage
+#define server_name RSG::material_storage
 
 	FUNCRIDSPLIT(shader)
 
@@ -249,6 +248,13 @@ public:
 
 	/* MESH API */
 
+//from now on, calls forwarded to this singleton
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererStorage
+#define server_name RSG::storage
+
 	virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override {
 		RID mesh = RSG::storage->mesh_allocate();
 
@@ -870,8 +876,8 @@ public:
 #undef server_name
 #undef ServerName
 //from now on, calls forwarded to this singleton
-#define ServerName RendererStorage
-#define server_name RSG::storage
+#define ServerName RendererMaterialStorage
+#define server_name RSG::material_storage
 
 	FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
 	FUNC1(global_variable_remove, const StringName &)

+ 1 - 0
servers/rendering/rendering_server_globals.cpp

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

+ 2 - 0
servers/rendering/rendering_server_globals.h

@@ -36,6 +36,7 @@
 #include "servers/rendering/renderer_scene.h"
 #include "servers/rendering/storage/canvas_texture_storage.h"
 #include "servers/rendering/storage/decal_atlas_storage.h"
+#include "servers/rendering/storage/material_storage.h"
 #include "servers/rendering/storage/texture_storage.h"
 
 class RendererCanvasCull;
@@ -47,6 +48,7 @@ public:
 	static bool threaded;
 
 	static RendererCanvasTextureStorage *canvas_texture_storage;
+	static RendererMaterialStorage *material_storage;
 	static RendererTextureStorage *texture_storage;
 	static RendererDecalAtlasStorage *decal_atlas_storage;
 	static RendererStorage *storage;

+ 101 - 0
servers/rendering/storage/material_storage.h

@@ -0,0 +1,101 @@
+/*************************************************************************/
+/*  material_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 MATERIAL_STORAGE_H
+#define MATERIAL_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererMaterialStorage {
+public:
+	virtual ~RendererMaterialStorage(){};
+
+	/* GLOBAL VARIABLE API */
+	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
+	virtual void global_variable_remove(const StringName &p_name) = 0;
+	virtual Vector<StringName> global_variable_get_list() const = 0;
+
+	virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
+	virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
+	virtual Variant global_variable_get(const StringName &p_name) const = 0;
+	virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
+
+	virtual void global_variables_load_settings(bool p_load_textures = true) = 0;
+	virtual void global_variables_clear() = 0;
+
+	virtual int32_t global_variables_instance_allocate(RID p_instance) = 0;
+	virtual void global_variables_instance_free(RID p_instance) = 0;
+	virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
+
+	/* SHADER API */
+	virtual RID shader_allocate() = 0;
+	virtual void shader_initialize(RID p_rid) = 0;
+	virtual void shader_free(RID p_rid) = 0;
+
+	virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
+	virtual String shader_get_code(RID p_shader) const = 0;
+	virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
+
+	virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
+	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0;
+	virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
+
+	virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
+
+	/* MATERIAL API */
+
+	virtual RID material_allocate() = 0;
+	virtual void material_initialize(RID p_rid) = 0;
+	virtual void material_free(RID p_rid) = 0;
+
+	virtual void material_set_render_priority(RID p_material, int priority) = 0;
+	virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0;
+
+	virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0;
+	virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0;
+
+	virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0;
+
+	virtual bool material_is_animated(RID p_material) = 0;
+	virtual bool material_casts_shadows(RID p_material) = 0;
+
+	struct InstanceShaderParam {
+		PropertyInfo info;
+		int index;
+		Variant default_value;
+	};
+
+	virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
+
+	virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) = 0;
+};
+
+#endif // !MATERIAL_STORAGE_H

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