Переглянути джерело

Add a UniformSet cache

* Changed syntax usage for RD::Uniform to create faster with a single RID
* Converted render pass setup to use this in clustered renderer to test.

This is the first step into creating a proper uniform set cache system to simplify large parts of the codebase.
reduz 3 роки тому
батько
коміт
b0ca03b0a2
22 змінених файлів з 879 додано та 555 видалено
  1. 1 1
      core/templates/paged_allocator.h
  2. 64 65
      drivers/vulkan/rendering_device_vulkan.cpp
  3. 34 34
      modules/lightmapper_rd/lightmapper_rd.cpp
  4. 10 10
      servers/rendering/renderer_rd/cluster_builder_rd.cpp
  5. 46 46
      servers/rendering/renderer_rd/effects_rd.cpp
  6. 64 92
      servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
  7. 0 2
      servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
  8. 1 1
      servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
  9. 32 31
      servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
  10. 1 1
      servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
  11. 15 14
      servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
  12. 7 4
      servers/rendering/renderer_rd/renderer_compositor_rd.cpp
  13. 2 0
      servers/rendering/renderer_rd/renderer_compositor_rd.h
  14. 135 129
      servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
  15. 41 37
      servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
  16. 23 22
      servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
  17. 51 48
      servers/rendering/renderer_rd/renderer_storage_rd.cpp
  18. 4 4
      servers/rendering/renderer_rd/renderer_storage_rd.h
  19. 64 0
      servers/rendering/renderer_rd/uniform_set_cache_rd.cpp
  20. 221 0
      servers/rendering/renderer_rd/uniform_set_cache_rd.h
  21. 57 8
      servers/rendering/rendering_device.h
  22. 6 6
      servers/rendering/rendering_device_binds.h

+ 1 - 1
core/templates/paged_allocator.h

@@ -86,10 +86,10 @@ public:
 		}
 		p_mem->~T();
 		available_pool[allocs_available >> page_shift][allocs_available & page_mask] = p_mem;
+		allocs_available++;
 		if (thread_safe) {
 			spin_lock.unlock();
 		}
-		allocs_available++;
 	}
 
 	void reset(bool p_allow_unfreed = false) {

+ 64 - 65
drivers/vulkan/rendering_device_vulkan.cpp

@@ -5632,18 +5632,18 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 
 		switch (uniform.uniform_type) {
 			case UNIFORM_TYPE_SAMPLER: {
-				if (uniform.ids.size() != set_uniform.length) {
+				if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
 					if (set_uniform.length > 1) {
-						ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler elements, so it should be provided equal number of sampler IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler elements, so it should be provided equal number of sampler IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					} else {
-						ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") should provide one ID referencing a sampler (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") should provide one ID referencing a sampler (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					}
 				}
 
 				Vector<VkDescriptorImageInfo> image_info;
 
-				for (int j = 0; j < uniform.ids.size(); j++) {
-					VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j]);
+				for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+					VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j));
 					ERR_FAIL_COND_V_MSG(!sampler, RID(), "Sampler (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid sampler.");
 
 					VkDescriptorImageInfo img_info;
@@ -5655,31 +5655,31 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 				}
 
 				write.dstArrayElement = 0;
-				write.descriptorCount = uniform.ids.size();
+				write.descriptorCount = uniform.get_id_count();
 				write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
 				write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
 				write.pBufferInfo = nullptr;
 				write.pTexelBufferView = nullptr;
 
-				type_size = uniform.ids.size();
+				type_size = uniform.get_id_count();
 
 			} break;
 			case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: {
-				if (uniform.ids.size() != set_uniform.length * 2) {
+				if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) {
 					if (set_uniform.length > 1) {
-						ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler&texture elements, so it should provided twice the amount of IDs (sampler,texture pairs) to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler&texture elements, so it should provided twice the amount of IDs (sampler,texture pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					} else {
-						ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					}
 				}
 
 				Vector<VkDescriptorImageInfo> image_info;
 
-				for (int j = 0; j < uniform.ids.size(); j += 2) {
-					VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j + 0]);
+				for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) {
+					VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j + 0));
 					ERR_FAIL_COND_V_MSG(!sampler, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler.");
 
-					Texture *texture = texture_owner.get_or_null(uniform.ids[j + 1]);
+					Texture *texture = texture_owner.get_or_null(uniform.get_id(j + 1));
 					ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
 
 					ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(),
@@ -5692,7 +5692,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 					if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) {
 						UniformSet::AttachableTexture attachable_texture;
 						attachable_texture.bind = set_uniform.binding;
-						attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j + 1];
+						attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j + 1);
 						attachable_textures.push_back(attachable_texture);
 					}
 
@@ -5711,28 +5711,28 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 				}
 
 				write.dstArrayElement = 0;
-				write.descriptorCount = uniform.ids.size() / 2;
+				write.descriptorCount = uniform.get_id_count() / 2;
 				write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 				write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
 				write.pBufferInfo = nullptr;
 				write.pTexelBufferView = nullptr;
 
-				type_size = uniform.ids.size() / 2;
+				type_size = uniform.get_id_count() / 2;
 
 			} break;
 			case UNIFORM_TYPE_TEXTURE: {
-				if (uniform.ids.size() != set_uniform.length) {
+				if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
 					if (set_uniform.length > 1) {
-						ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					} else {
-						ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					}
 				}
 
 				Vector<VkDescriptorImageInfo> image_info;
 
-				for (int j = 0; j < uniform.ids.size(); j++) {
-					Texture *texture = texture_owner.get_or_null(uniform.ids[j]);
+				for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+					Texture *texture = texture_owner.get_or_null(uniform.get_id(j));
 					ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
 
 					ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(),
@@ -5745,7 +5745,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 					if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) {
 						UniformSet::AttachableTexture attachable_texture;
 						attachable_texture.bind = set_uniform.binding;
-						attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j];
+						attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j);
 						attachable_textures.push_back(attachable_texture);
 					}
 
@@ -5765,27 +5765,27 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 				}
 
 				write.dstArrayElement = 0;
-				write.descriptorCount = uniform.ids.size();
+				write.descriptorCount = uniform.get_id_count();
 				write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
 				write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
 				write.pBufferInfo = nullptr;
 				write.pTexelBufferView = nullptr;
 
-				type_size = uniform.ids.size();
+				type_size = uniform.get_id_count();
 			} break;
 			case UNIFORM_TYPE_IMAGE: {
-				if (uniform.ids.size() != set_uniform.length) {
+				if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
 					if (set_uniform.length > 1) {
-						ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					} else {
-						ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					}
 				}
 
 				Vector<VkDescriptorImageInfo> image_info;
 
-				for (int j = 0; j < uniform.ids.size(); j++) {
-					Texture *texture = texture_owner.get_or_null(uniform.ids[j]);
+				for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+					Texture *texture = texture_owner.get_or_null(uniform.get_id(j));
 
 					ERR_FAIL_COND_V_MSG(!texture, RID(),
 							"Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
@@ -5813,29 +5813,29 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 				}
 
 				write.dstArrayElement = 0;
-				write.descriptorCount = uniform.ids.size();
+				write.descriptorCount = uniform.get_id_count();
 				write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
 				write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
 				write.pBufferInfo = nullptr;
 				write.pTexelBufferView = nullptr;
 
-				type_size = uniform.ids.size();
+				type_size = uniform.get_id_count();
 
 			} break;
 			case UNIFORM_TYPE_TEXTURE_BUFFER: {
-				if (uniform.ids.size() != set_uniform.length) {
+				if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
 					if (set_uniform.length > 1) {
-						ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") texture buffer elements, so it should be provided equal number of texture buffer IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") texture buffer elements, so it should be provided equal number of texture buffer IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					} else {
-						ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture buffer (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					}
 				}
 
 				Vector<VkDescriptorBufferInfo> buffer_info;
 				Vector<VkBufferView> buffer_view;
 
-				for (int j = 0; j < uniform.ids.size(); j++) {
-					TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.ids[j]);
+				for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+					TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j));
 					ERR_FAIL_COND_V_MSG(!buffer, RID(), "Texture Buffer (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture buffer.");
 
 					buffer_info.push_back(buffer->buffer.buffer_info);
@@ -5843,21 +5843,21 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 				}
 
 				write.dstArrayElement = 0;
-				write.descriptorCount = uniform.ids.size();
+				write.descriptorCount = uniform.get_id_count();
 				write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
 				write.pImageInfo = nullptr;
 				write.pBufferInfo = buffer_infos.push_back(buffer_info)->get().ptr();
 				write.pTexelBufferView = buffer_views.push_back(buffer_view)->get().ptr();
 
-				type_size = uniform.ids.size();
+				type_size = uniform.get_id_count();
 
 			} break;
 			case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER: {
-				if (uniform.ids.size() != set_uniform.length * 2) {
+				if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) {
 					if (set_uniform.length > 1) {
-						ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler buffer elements, so it should provided twice the amount of IDs (sampler,buffer pairs) to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler buffer elements, so it should provided twice the amount of IDs (sampler,buffer pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					} else {
-						ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture buffer (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					}
 				}
 
@@ -5865,11 +5865,11 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 				Vector<VkDescriptorBufferInfo> buffer_info;
 				Vector<VkBufferView> buffer_view;
 
-				for (int j = 0; j < uniform.ids.size(); j += 2) {
-					VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j + 0]);
+				for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) {
+					VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j + 0));
 					ERR_FAIL_COND_V_MSG(!sampler, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler.");
 
-					TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.ids[j + 1]);
+					TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j + 1));
 
 					VkDescriptorImageInfo img_info;
 					img_info.sampler = *sampler;
@@ -5885,23 +5885,23 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 				}
 
 				write.dstArrayElement = 0;
-				write.descriptorCount = uniform.ids.size() / 2;
+				write.descriptorCount = uniform.get_id_count() / 2;
 				write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
 				write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
 				write.pBufferInfo = buffer_infos.push_back(buffer_info)->get().ptr();
 				write.pTexelBufferView = buffer_views.push_back(buffer_view)->get().ptr();
 
-				type_size = uniform.ids.size() / 2;
+				type_size = uniform.get_id_count() / 2;
 			} break;
 			case UNIFORM_TYPE_IMAGE_BUFFER: {
 				//todo
 
 			} break;
 			case UNIFORM_TYPE_UNIFORM_BUFFER: {
-				ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(),
-						"Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided).");
+				ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(),
+						"Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided).");
 
-				Buffer *buffer = uniform_buffer_owner.get_or_null(uniform.ids[0]);
+				Buffer *buffer = uniform_buffer_owner.get_or_null(uniform.get_id(0));
 				ERR_FAIL_COND_V_MSG(!buffer, RID(), "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
 
 				ERR_FAIL_COND_V_MSG(buffer->size != (uint32_t)set_uniform.length, RID(),
@@ -5916,15 +5916,15 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 
 			} break;
 			case UNIFORM_TYPE_STORAGE_BUFFER: {
-				ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(),
-						"Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided).");
+				ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(),
+						"Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided).");
 
 				Buffer *buffer = nullptr;
 
-				if (storage_buffer_owner.owns(uniform.ids[0])) {
-					buffer = storage_buffer_owner.get_or_null(uniform.ids[0]);
-				} else if (vertex_buffer_owner.owns(uniform.ids[0])) {
-					buffer = vertex_buffer_owner.get_or_null(uniform.ids[0]);
+				if (storage_buffer_owner.owns(uniform.get_id(0))) {
+					buffer = storage_buffer_owner.get_or_null(uniform.get_id(0));
+				} else if (vertex_buffer_owner.owns(uniform.get_id(0))) {
+					buffer = vertex_buffer_owner.get_or_null(uniform.get_id(0));
 
 					ERR_FAIL_COND_V_MSG(!(buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), RID(), "Vertex buffer supplied (binding: " + itos(uniform.binding) + ") was not created with storage flag.");
 				}
@@ -5944,18 +5944,18 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 			case UNIFORM_TYPE_INPUT_ATTACHMENT: {
 				ERR_FAIL_COND_V_MSG(shader->is_compute, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") supplied for compute shader (this is not allowed).");
 
-				if (uniform.ids.size() != set_uniform.length) {
+				if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
 					if (set_uniform.length > 1) {
-						ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					} else {
-						ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ").");
+						ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
 					}
 				}
 
 				Vector<VkDescriptorImageInfo> image_info;
 
-				for (int j = 0; j < uniform.ids.size(); j++) {
-					Texture *texture = texture_owner.get_or_null(uniform.ids[j]);
+				for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+					Texture *texture = texture_owner.get_or_null(uniform.get_id(j));
 
 					ERR_FAIL_COND_V_MSG(!texture, RID(),
 							"InputAttachment (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
@@ -5978,13 +5978,13 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 				}
 
 				write.dstArrayElement = 0;
-				write.descriptorCount = uniform.ids.size();
+				write.descriptorCount = uniform.get_id_count();
 				write.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
 				write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
 				write.pBufferInfo = nullptr;
 				write.pTexelBufferView = nullptr;
 
-				type_size = uniform.ids.size();
+				type_size = uniform.get_id_count();
 			} break;
 			default: {
 			}
@@ -6034,10 +6034,9 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 	_add_dependency(id, p_shader);
 	for (uint32_t i = 0; i < uniform_count; i++) {
 		const Uniform &uniform = uniforms[i];
-		int id_count = uniform.ids.size();
-		const RID *ids = uniform.ids.ptr();
+		int id_count = uniform.get_id_count();
 		for (int j = 0; j < id_count; j++) {
-			_add_dependency(id, ids[j]);
+			_add_dependency(id, uniform.get_id(j));
 		}
 	}
 

+ 34 - 34
modules/lightmapper_rd/lightmapper_rd.cpp

@@ -618,14 +618,14 @@ LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShade
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 0;
-			u.ids.push_back(dest_light_tex);
+			u.append_id(dest_light_tex);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 1;
-			u.ids.push_back(source_light_tex);
+			u.append_id(source_light_tex);
 			uniforms.push_back(u);
 		}
 	}
@@ -856,70 +856,70 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 1;
-			u.ids.push_back(vertex_buffer);
+			u.append_id(vertex_buffer);
 			base_uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 2;
-			u.ids.push_back(triangle_buffer);
+			u.append_id(triangle_buffer);
 			base_uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 3;
-			u.ids.push_back(triangle_cell_indices_buffer);
+			u.append_id(triangle_cell_indices_buffer);
 			base_uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 4;
-			u.ids.push_back(lights_buffer);
+			u.append_id(lights_buffer);
 			base_uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 5;
-			u.ids.push_back(seams_buffer);
+			u.append_id(seams_buffer);
 			base_uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 6;
-			u.ids.push_back(probe_positions_buffer);
+			u.append_id(probe_positions_buffer);
 			base_uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 7;
-			u.ids.push_back(grid_texture);
+			u.append_id(grid_texture);
 			base_uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 8;
-			u.ids.push_back(albedo_array_tex);
+			u.append_id(albedo_array_tex);
 			base_uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 9;
-			u.ids.push_back(emission_array_tex);
+			u.append_id(emission_array_tex);
 			base_uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 10;
-			u.ids.push_back(sampler);
+			u.append_id(sampler);
 			base_uniforms.push_back(u);
 		}
 	}
@@ -1057,14 +1057,14 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 0;
-				u.ids.push_back(position_tex);
+				u.append_id(position_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 1;
-				u.ids.push_back(unocclude_tex); //will be unused
+				u.append_id(unocclude_tex); //will be unused
 				uniforms.push_back(u);
 			}
 		}
@@ -1097,42 +1097,42 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 0;
-				u.ids.push_back(light_source_tex);
+				u.append_id(light_source_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 1;
-				u.ids.push_back(light_dest_tex); //will be unused
+				u.append_id(light_dest_tex); //will be unused
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 2;
-				u.ids.push_back(position_tex);
+				u.append_id(position_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 3;
-				u.ids.push_back(normal_tex);
+				u.append_id(normal_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 4;
-				u.ids.push_back(light_accum_tex);
+				u.append_id(light_accum_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 5;
-				u.ids.push_back(light_primary_dynamic_tex);
+				u.append_id(light_primary_dynamic_tex);
 				uniforms.push_back(u);
 			}
 		}
@@ -1176,57 +1176,57 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 0;
-				u.ids.push_back(light_dest_tex);
+				u.append_id(light_dest_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 1;
-				u.ids.push_back(light_source_tex);
+				u.append_id(light_source_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 2;
-				u.ids.push_back(position_tex);
+				u.append_id(position_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 3;
-				u.ids.push_back(normal_tex);
+				u.append_id(normal_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 4;
-				u.ids.push_back(light_accum_tex);
+				u.append_id(light_accum_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 5;
-				u.ids.push_back(unocclude_tex); //reuse unocclude tex
+				u.append_id(unocclude_tex); //reuse unocclude tex
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 6;
-				u.ids.push_back(light_environment_tex);
+				u.append_id(light_environment_tex);
 				uniforms.push_back(u);
 			}
 		}
 
 		RID secondary_uniform_set[2];
 		secondary_uniform_set[0] = rd->uniform_set_create(uniforms, compute_shader_secondary, 1);
-		uniforms.write[0].ids.write[0] = light_source_tex;
-		uniforms.write[1].ids.write[0] = light_dest_tex;
+		uniforms.write[0].set_id(0, light_source_tex);
+		uniforms.write[1].set_id(0, light_dest_tex);
 		secondary_uniform_set[1] = rd->uniform_set_create(uniforms, compute_shader_secondary, 1);
 
 		switch (p_quality) {
@@ -1332,28 +1332,28 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 0;
-				u.ids.push_back(light_probe_buffer);
+				u.append_id(light_probe_buffer);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 1;
-				u.ids.push_back(light_dest_tex);
+				u.append_id(light_dest_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 2;
-				u.ids.push_back(light_primary_dynamic_tex);
+				u.append_id(light_primary_dynamic_tex);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 3;
-				u.ids.push_back(light_environment_tex);
+				u.append_id(light_environment_tex);
 				uniforms.push_back(u);
 			}
 		}
@@ -1531,7 +1531,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 0;
-				u.ids.push_back(light_accum_tex2);
+				u.append_id(light_accum_tex2);
 				uniforms.push_back(u);
 			}
 		}

+ 10 - 10
servers/rendering/renderer_rd/cluster_builder_rd.cpp

@@ -287,21 +287,21 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.binding = 1;
-			u.ids.push_back(state_uniform);
+			u.append_id(state_uniform);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 2;
-			u.ids.push_back(element_buffer);
+			u.append_id(element_buffer);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 3;
-			u.ids.push_back(cluster_render_buffer);
+			u.append_id(cluster_render_buffer);
 			uniforms.push_back(u);
 		}
 
@@ -314,14 +314,14 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 1;
-			u.ids.push_back(cluster_render_buffer);
+			u.append_id(cluster_render_buffer);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 2;
-			u.ids.push_back(cluster_buffer);
+			u.append_id(cluster_buffer);
 			uniforms.push_back(u);
 		}
 
@@ -329,7 +329,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 3;
-			u.ids.push_back(element_buffer);
+			u.append_id(element_buffer);
 			uniforms.push_back(u);
 		}
 
@@ -342,14 +342,14 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 1;
-			u.ids.push_back(cluster_buffer);
+			u.append_id(cluster_buffer);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 2;
-			u.ids.push_back(p_color_buffer);
+			u.append_id(p_color_buffer);
 			uniforms.push_back(u);
 		}
 
@@ -357,14 +357,14 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 3;
-			u.ids.push_back(p_depth_buffer);
+			u.append_id(p_depth_buffer);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 4;
-			u.ids.push_back(p_depth_buffer_sampler);
+			u.append_id(p_depth_buffer_sampler);
 			uniforms.push_back(u);
 		}
 

+ 46 - 46
servers/rendering/renderer_rd/effects_rd.cpp

@@ -60,7 +60,7 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
 	RD::Uniform u;
 	u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 	u.binding = 0;
-	u.ids.push_back(p_image);
+	u.append_id(p_image);
 	uniforms.push_back(u);
 	//any thing with the same configuration (one texture in binding 0 for set 0), is good
 	RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 1);
@@ -82,7 +82,7 @@ RID EffectsRD::_get_uniform_set_for_input(RID p_texture) {
 	RD::Uniform u;
 	u.uniform_type = RD::UNIFORM_TYPE_INPUT_ATTACHMENT;
 	u.binding = 0;
-	u.ids.push_back(p_texture);
+	u.append_id(p_texture);
 	uniforms.push_back(u);
 	// This is specific to our subpass shader
 	RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, TONEMAP_MODE_SUBPASS), 0);
@@ -104,8 +104,8 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
 	RD::Uniform u;
 	u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 	u.binding = 0;
-	u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
-	u.ids.push_back(p_texture);
+	u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+	u.append_id(p_texture);
 	uniforms.push_back(u);
 	// anything with the same configuration (one texture in binding 0 for set 0), is good
 	RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 0);
@@ -132,16 +132,16 @@ RID EffectsRD::_get_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 		u.binding = 0;
-		u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
-		u.ids.push_back(p_texture1);
+		u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+		u.append_id(p_texture1);
 		uniforms.push_back(u);
 	}
 	{
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 		u.binding = 1;
-		u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
-		u.ids.push_back(p_texture2);
+		u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+		u.append_id(p_texture2);
 		uniforms.push_back(u);
 	}
 	// anything with the same configuration (one texture in binding 0 for set 0), is good
@@ -164,8 +164,8 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m
 	RD::Uniform u;
 	u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 	u.binding = 0;
-	u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
-	u.ids.push_back(p_texture);
+	u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+	u.append_id(p_texture);
 	uniforms.push_back(u);
 	//any thing with the same configuration (one texture in binding 0 for set 0), is good
 	RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 0);
@@ -191,8 +191,8 @@ RID EffectsRD::_get_compute_uniform_set_from_texture_and_sampler(RID p_texture,
 	RD::Uniform u;
 	u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 	u.binding = 0;
-	u.ids.push_back(p_sampler);
-	u.ids.push_back(p_texture);
+	u.append_id(p_sampler);
+	u.append_id(p_texture);
 	uniforms.push_back(u);
 	//any thing with the same configuration (one texture in binding 0 for set 0), is good
 	RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0), 0);
@@ -219,16 +219,16 @@ RID EffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 		u.binding = 0;
-		u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
-		u.ids.push_back(p_texture1);
+		u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+		u.append_id(p_texture1);
 		uniforms.push_back(u);
 	}
 	{
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 		u.binding = 1;
-		u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
-		u.ids.push_back(p_texture2);
+		u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+		u.append_id(p_texture2);
 		uniforms.push_back(u);
 	}
 	//any thing with the same configuration (one texture in binding 0 for set 0), is good
@@ -256,14 +256,14 @@ RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_te
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.binding = 0;
-		u.ids.push_back(p_texture1);
+		u.append_id(p_texture1);
 		uniforms.push_back(u);
 	}
 	{
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.binding = 1;
-		u.ids.push_back(p_texture2);
+		u.append_id(p_texture2);
 		uniforms.push_back(u);
 	}
 	//any thing with the same configuration (one texture in binding 0 for set 0), is good
@@ -1389,28 +1389,28 @@ void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 0;
-			u.ids.push_back(p_depth_mipmaps[depth_index + 1]);
+			u.append_id(p_depth_mipmaps[depth_index + 1]);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 1;
-			u.ids.push_back(p_depth_mipmaps[depth_index + 2]);
+			u.append_id(p_depth_mipmaps[depth_index + 2]);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 2;
-			u.ids.push_back(p_depth_mipmaps[depth_index + 3]);
+			u.append_id(p_depth_mipmaps[depth_index + 3]);
 			uniforms.push_back(u);
 		}
 		if (use_full_mips) {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 3;
-			u.ids.push_back(p_depth_mipmaps[4]);
+			u.append_id(p_depth_mipmaps[4]);
 			uniforms.push_back(u);
 		}
 		ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
@@ -1537,22 +1537,22 @@ void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 				u.binding = 0;
-				u.ids.push_back(default_sampler);
-				u.ids.push_back(p_depth_mipmaps_texture);
+				u.append_id(default_sampler);
+				u.append_id(p_depth_mipmaps_texture);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 1;
-				u.ids.push_back(p_normal_buffer);
+				u.append_id(p_normal_buffer);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 				u.binding = 2;
-				u.ids.push_back(ss_effects.gather_constants_buffer);
+				u.append_id(ss_effects.gather_constants_buffer);
 				uniforms.push_back(u);
 			}
 			r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
@@ -1564,22 +1564,22 @@ void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 0;
-				u.ids.push_back(p_ao_pong);
+				u.append_id(p_ao_pong);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 				u.binding = 1;
-				u.ids.push_back(default_sampler);
-				u.ids.push_back(p_importance_map);
+				u.append_id(default_sampler);
+				u.append_id(p_importance_map);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 2;
-				u.ids.push_back(ssao.importance_map_load_counter);
+				u.append_id(ssao.importance_map_load_counter);
 				uniforms.push_back(u);
 			}
 			r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
@@ -1811,15 +1811,15 @@ void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 				u.binding = 0;
-				u.ids.push_back(default_mipmap_sampler);
-				u.ids.push_back(p_diffuse);
+				u.append_id(default_mipmap_sampler);
+				u.append_id(p_diffuse);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 				u.binding = 1;
-				u.ids.push_back(ssil.projection_uniform_buffer);
+				u.append_id(ssil.projection_uniform_buffer);
 				uniforms.push_back(u);
 			}
 			r_projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
@@ -1831,22 +1831,22 @@ void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 				u.binding = 0;
-				u.ids.push_back(default_sampler);
-				u.ids.push_back(p_depth_mipmaps_texture);
+				u.append_id(default_sampler);
+				u.append_id(p_depth_mipmaps_texture);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 1;
-				u.ids.push_back(p_normal_buffer);
+				u.append_id(p_normal_buffer);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 				u.binding = 2;
-				u.ids.push_back(ss_effects.gather_constants_buffer);
+				u.append_id(ss_effects.gather_constants_buffer);
 				uniforms.push_back(u);
 			}
 			r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
@@ -1858,22 +1858,22 @@ void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination,
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 0;
-				u.ids.push_back(p_ssil_pong);
+				u.append_id(p_ssil_pong);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 				u.binding = 1;
-				u.ids.push_back(default_sampler);
-				u.ids.push_back(p_importance_map);
+				u.append_id(default_sampler);
+				u.append_id(p_importance_map);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 2;
-				u.ids.push_back(ssil.importance_map_load_counter);
+				u.append_id(ssil.importance_map_load_counter);
 				uniforms.push_back(u);
 			}
 			r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
@@ -2131,7 +2131,7 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap,
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.binding = i;
-		u.ids.push_back(p_dest_cubemap[i]);
+		u.append_id(p_dest_cubemap[i]);
 		uniforms.push_back(u);
 	}
 	if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
@@ -2651,7 +2651,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
 					RD::Uniform u;
 					u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 					u.binding = 0;
-					u.ids.push_back(ssao.importance_map_load_counter);
+					u.append_id(ssao.importance_map_load_counter);
 					uniforms.push_back(u);
 				}
 				ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
@@ -2766,7 +2766,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 0;
-				u.ids.push_back(filter.coefficient_buffer);
+				u.append_id(filter.coefficient_buffer);
 				uniforms.push_back(u);
 			}
 			filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
@@ -2784,7 +2784,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 0;
-				u.ids.push_back(filter.coefficient_buffer);
+				u.append_id(filter.coefficient_buffer);
 				uniforms.push_back(u);
 			}
 			filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
@@ -2921,7 +2921,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 0;
-				u.ids.push_back(ssil.importance_map_load_counter);
+				u.append_id(ssil.importance_map_load_counter);
 				uniforms.push_back(u);
 			}
 			ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);

+ 64 - 92
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp

@@ -30,6 +30,7 @@
 
 #include "render_forward_clustered.h"
 #include "core/config/project_settings.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
 #include "servers/rendering/rendering_device.h"
 #include "servers/rendering/rendering_server_default.h"
 
@@ -824,7 +825,6 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
 	if (p_index >= (int)scene_state.uniform_buffers.size()) {
 		uint32_t from = scene_state.uniform_buffers.size();
 		scene_state.uniform_buffers.resize(p_index + 1);
-		render_pass_uniform_sets.resize(p_index + 1);
 		for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) {
 			scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
 		}
@@ -1991,11 +1991,9 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 		Vector<RD::Uniform> uniforms;
 
 		{
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.binding = 1;
-			u.ids.resize(12);
-			RID *ids_ptr = u.ids.ptrw();
+			Vector<RID> ids;
+			ids.resize(12);
+			RID *ids_ptr = ids.ptrw();
 			ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 			ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 			ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -2008,6 +2006,9 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 			ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 			ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+
 			uniforms.push_back(u);
 		}
 
@@ -2015,7 +2016,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 2;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.ids.push_back(scene_shader.shadow_sampler);
+			u.append_id(scene_shader.shadow_sampler);
 			uniforms.push_back(u);
 		}
 
@@ -2042,7 +2043,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 				} break;
 			}
 
-			u.ids.push_back(sampler);
+			u.append_id(sampler);
 			uniforms.push_back(u);
 		}
 
@@ -2069,7 +2070,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 				} break;
 			}
 
-			u.ids.push_back(sampler);
+			u.append_id(sampler);
 			uniforms.push_back(u);
 		}
 
@@ -2077,14 +2078,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 5;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(get_omni_light_buffer());
+			u.append_id(get_omni_light_buffer());
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 6;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(get_spot_light_buffer());
+			u.append_id(get_spot_light_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -2092,28 +2093,28 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 7;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(get_reflection_probe_buffer());
+			u.append_id(get_reflection_probe_buffer());
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 8;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-			u.ids.push_back(get_directional_light_buffer());
+			u.append_id(get_directional_light_buffer());
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 9;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(scene_state.lightmap_buffer);
+			u.append_id(scene_state.lightmap_buffer);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 10;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(scene_state.lightmap_capture_buffer);
+			u.append_id(scene_state.lightmap_capture_buffer);
 			uniforms.push_back(u);
 		}
 		{
@@ -2121,7 +2122,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			u.binding = 11;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID decal_atlas = storage->decal_atlas_get_texture();
-			u.ids.push_back(decal_atlas);
+			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
 		{
@@ -2129,14 +2130,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID decal_atlas = storage->decal_atlas_get_texture_srgb();
-			u.ids.push_back(decal_atlas);
+			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 13;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(get_decal_buffer());
+			u.append_id(get_decal_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -2144,7 +2145,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 14;
-			u.ids.push_back(storage->global_variables_get_storage_buffer());
+			u.append_id(storage->global_variables_get_storage_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -2152,7 +2153,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.binding = 15;
-			u.ids.push_back(sdfgi_get_ubo());
+			u.append_id(sdfgi_get_ubo());
 			uniforms.push_back(u);
 		}
 
@@ -2161,9 +2162,6 @@ 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) {
-	//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());
-
 	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);
@@ -2177,7 +2175,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		RD::Uniform u;
 		u.binding = 0;
 		u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-		u.ids.push_back(scene_state.uniform_buffers[p_index]);
+		u.append_id(scene_state.uniform_buffers[p_index]);
 		uniforms.push_back(u);
 	}
 	{
@@ -2188,7 +2186,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		if (instance_buffer == RID()) {
 			instance_buffer = scene_shader.default_vec4_xform_buffer; // any buffer will do since its not used
 		}
-		u.ids.push_back(instance_buffer);
+		u.append_id(instance_buffer);
 		uniforms.push_back(u);
 	}
 	{
@@ -2201,7 +2199,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		RD::Uniform u;
 		u.binding = 2;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		u.ids.push_back(radiance_texture);
+		u.append_id(radiance_texture);
 		uniforms.push_back(u);
 	}
 
@@ -2211,9 +2209,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		u.binding = 3;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		if (ref_texture.is_valid()) {
-			u.ids.push_back(ref_texture);
+			u.append_id(ref_texture);
 		} else {
-			u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
 		}
 		uniforms.push_back(u);
 	}
@@ -2229,7 +2227,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		if (!texture.is_valid()) {
 			texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
 		}
-		u.ids.push_back(texture);
+		u.append_id(texture);
 		uniforms.push_back(u);
 	}
 	{
@@ -2237,9 +2235,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		u.binding = 5;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
-			u.ids.push_back(directional_shadow_get_texture());
+			u.append_id(directional_shadow_get_texture());
 		} else {
-			u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
 		}
 		uniforms.push_back(u);
 	}
@@ -2247,16 +2245,16 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		RD::Uniform u;
 		u.binding = 6;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		u.ids.resize(scene_state.max_lightmaps);
+
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
 		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
 			if (p_render_data && i < p_render_data->lightmaps->size()) {
 				RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
 				RID texture = storage->lightmap_get_texture(base);
 				RID rd_texture = storage->texture_get_rd_texture(texture);
-				u.ids.write[i] = rd_texture;
+				u.append_id(rd_texture);
 			} else {
-				u.ids.write[i] = default_tex;
+				u.append_id(default_tex);
 			}
 		}
 
@@ -2266,7 +2264,6 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		RD::Uniform u;
 		u.binding = 7;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
 			if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) {
@@ -2274,9 +2271,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 				if (!tex.is_valid()) {
 					tex = default_tex;
 				}
-				u.ids.write[i] = tex;
+				u.append_id(tex);
 			} else {
-				u.ids.write[i] = default_tex;
+				u.append_id(default_tex);
 			}
 		}
 
@@ -2288,7 +2285,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		u.binding = 8;
 		u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 		RID cb = (p_render_data && p_render_data->cluster_buffer.is_valid()) ? p_render_data->cluster_buffer : scene_shader.default_vec4_xform_buffer;
-		u.ids.push_back(cb);
+		u.append_id(cb);
 		uniforms.push_back(u);
 	}
 
@@ -2298,7 +2295,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
 		RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
-		u.ids.push_back(texture);
+		u.append_id(texture);
 		uniforms.push_back(u);
 	}
 	{
@@ -2307,7 +2304,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
 		RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
-		u.ids.push_back(texture);
+		u.append_id(texture);
 		uniforms.push_back(u);
 	}
 
@@ -2317,7 +2314,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.binding = 11;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL);
-			u.ids.push_back(texture);
+			u.append_id(texture);
 			uniforms.push_back(u);
 		}
 
@@ -2327,7 +2324,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID();
 			RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
-			u.ids.push_back(texture);
+			u.append_id(texture);
 			uniforms.push_back(u);
 		}
 
@@ -2337,7 +2334,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID();
 			RID texture = ambient_buffer.is_valid() ? ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
-			u.ids.push_back(texture);
+			u.append_id(texture);
 			uniforms.push_back(u);
 		}
 
@@ -2347,7 +2344,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID();
 			RID texture = reflection_buffer.is_valid() ? reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
-			u.ids.push_back(texture);
+			u.append_id(texture);
 			uniforms.push_back(u);
 		}
 		{
@@ -2360,7 +2357,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			} else {
 				t = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
 			}
-			u.ids.push_back(t);
+			u.append_id(t);
 			uniforms.push_back(u);
 		}
 		{
@@ -2368,9 +2365,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.binding = 16;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
-				u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers));
+				u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers));
 			} else {
-				u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+				u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE));
 			}
 			uniforms.push_back(u);
 		}
@@ -2378,7 +2375,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			RD::Uniform u;
 			u.binding = 17;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-			u.ids.push_back(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer());
+			u.append_id(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer());
 			uniforms.push_back(u);
 		}
 		{
@@ -2394,7 +2391,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			} else {
 				vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 			}
-			u.ids.push_back(vfog);
+			u.append_id(vfog);
 			uniforms.push_back(u);
 		}
 		{
@@ -2403,42 +2400,29 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID();
 			RID texture = ssil.is_valid() ? ssil : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
-			u.ids.push_back(texture);
+			u.append_id(texture);
 			uniforms.push_back(u);
 		}
 	}
 
-	if (p_index >= (int)render_pass_uniform_sets.size()) {
-		render_pass_uniform_sets.resize(p_index + 1);
-	}
-
-	if (render_pass_uniform_sets[p_index].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_sets[p_index])) {
-		RD::get_singleton()->free(render_pass_uniform_sets[p_index]);
-	}
-
-	render_pass_uniform_sets[p_index] = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET);
-	return render_pass_uniform_sets[p_index];
+	return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET, uniforms);
 }
 
 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) {
-	if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) {
-		RD::get_singleton()->free(sdfgi_pass_uniform_set);
-	}
-
 	Vector<RD::Uniform> uniforms;
 
 	{
 		RD::Uniform u;
 		u.binding = 0;
 		u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-		u.ids.push_back(scene_state.uniform_buffers[0]);
+		u.append_id(scene_state.uniform_buffers[0]);
 		uniforms.push_back(u);
 	}
 	{
 		RD::Uniform u;
 		u.binding = 1;
 		u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-		u.ids.push_back(scene_state.instance_buffer[RENDER_LIST_SECONDARY]);
+		u.append_id(scene_state.instance_buffer[RENDER_LIST_SECONDARY]);
 		uniforms.push_back(u);
 	}
 	{
@@ -2447,7 +2431,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		RD::Uniform u;
 		u.binding = 2;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		u.ids.push_back(radiance_texture);
+		u.append_id(radiance_texture);
 		uniforms.push_back(u);
 	}
 
@@ -2457,7 +2441,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		RD::Uniform u;
 		u.binding = 3;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		u.ids.push_back(ref_texture);
+		u.append_id(ref_texture);
 		uniforms.push_back(u);
 	}
 
@@ -2467,7 +2451,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		u.binding = 4;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
-		u.ids.push_back(texture);
+		u.append_id(texture);
 		uniforms.push_back(u);
 	}
 
@@ -2477,7 +2461,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		u.binding = 5;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
-		u.ids.push_back(texture);
+		u.append_id(texture);
 		uniforms.push_back(u);
 	}
 
@@ -2486,10 +2470,10 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		RD::Uniform u;
 		u.binding = 6;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		u.ids.resize(scene_state.max_lightmaps);
+
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
 		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
-			u.ids.write[i] = default_tex;
+			u.append_id(default_tex);
 		}
 
 		uniforms.push_back(u);
@@ -2500,10 +2484,10 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		RD::Uniform u;
 		u.binding = 7;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
+
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
-			u.ids.write[i] = default_tex;
+			u.append_id(default_tex);
 		}
 
 		uniforms.push_back(u);
@@ -2514,7 +2498,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		u.binding = 8;
 		u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 		RID cb = scene_shader.default_vec4_xform_buffer;
-		u.ids.push_back(cb);
+		u.append_id(cb);
 		uniforms.push_back(u);
 	}
 
@@ -2524,33 +2508,32 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.binding = 9;
-		u.ids.push_back(p_albedo_texture);
+		u.append_id(p_albedo_texture);
 		uniforms.push_back(u);
 	}
 	{
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.binding = 10;
-		u.ids.push_back(p_emission_texture);
+		u.append_id(p_emission_texture);
 		uniforms.push_back(u);
 	}
 	{
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.binding = 11;
-		u.ids.push_back(p_emission_aniso_texture);
+		u.append_id(p_emission_aniso_texture);
 		uniforms.push_back(u);
 	}
 	{
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.binding = 12;
-		u.ids.push_back(p_geom_facing_texture);
+		u.append_id(p_geom_facing_texture);
 		uniforms.push_back(u);
 	}
 
-	sdfgi_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET);
-	return sdfgi_pass_uniform_set;
+	return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET, uniforms);
 }
 
 RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) {
@@ -3218,17 +3201,6 @@ RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
 RenderForwardClustered::~RenderForwardClustered() {
 	directional_shadow_atlas_set_size(0);
 
-	//clear base uniform set if still valid
-	for (uint32_t i = 0; i < render_pass_uniform_sets.size(); i++) {
-		if (render_pass_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_sets[i])) {
-			RD::get_singleton()->free(render_pass_uniform_sets[i]);
-		}
-	}
-
-	if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) {
-		RD::get_singleton()->free(sdfgi_pass_uniform_set);
-	}
-
 	{
 		for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) {
 			RD::get_singleton()->free(scene_state.uniform_buffers[i]);

+ 0 - 2
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h

@@ -121,8 +121,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
 	void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb);
 
 	RID render_base_uniform_set;
-	LocalVector<RID> render_pass_uniform_sets;
-	RID sdfgi_pass_uniform_set;
 
 	uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
 

+ 1 - 1
servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp

@@ -751,7 +751,7 @@ void fragment() {
 		Vector<RD::Uniform> uniforms;
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-		u.ids.push_back(default_vec4_xform_buffer);
+		u.append_id(default_vec4_xform_buffer);
 		u.binding = 0;
 		uniforms.push_back(u);
 

+ 32 - 31
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

@@ -306,7 +306,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		RD::Uniform u;
 		u.binding = 0;
 		u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-		u.ids.push_back(scene_state.uniform_buffers[p_index]);
+		u.append_id(scene_state.uniform_buffers[p_index]);
 		uniforms.push_back(u);
 	}
 
@@ -320,7 +320,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		RD::Uniform u;
 		u.binding = 2;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		u.ids.push_back(radiance_texture);
+		u.append_id(radiance_texture);
 		uniforms.push_back(u);
 	}
 
@@ -330,9 +330,9 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		u.binding = 3;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		if (ref_texture.is_valid()) {
-			u.ids.push_back(ref_texture);
+			u.append_id(ref_texture);
 		} else {
-			u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
 		}
 		uniforms.push_back(u);
 	}
@@ -348,7 +348,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		if (!texture.is_valid()) {
 			texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
 		}
-		u.ids.push_back(texture);
+		u.append_id(texture);
 		uniforms.push_back(u);
 	}
 	{
@@ -356,9 +356,9 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		u.binding = 5;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
-			u.ids.push_back(directional_shadow_get_texture());
+			u.append_id(directional_shadow_get_texture());
 		} else {
-			u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
 		}
 		uniforms.push_back(u);
 	}
@@ -368,16 +368,16 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		RD::Uniform u;
 		u.binding = 6;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-		u.ids.resize(scene_state.max_lightmaps);
+
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
 		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
 			if (p_render_data && i < p_render_data->lightmaps->size()) {
 				RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
 				RID texture = storage->lightmap_get_texture(base);
 				RID rd_texture = storage->texture_get_rd_texture(texture);
-				u.ids.write[i] = rd_texture;
+				u.append_id(rd_texture);
 			} else {
-				u.ids.write[i] = default_tex;
+				u.append_id(default_tex);
 			}
 		}
 
@@ -411,7 +411,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		u.binding = 8;
 		u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 		RID cb = p_cluster_buffer.is_valid() ? p_cluster_buffer : default_vec4_xform_buffer;
-		u.ids.push_back(cb);
+		u.append_id(cb);
 		uniforms.push_back(u);
 	}
 	*/
@@ -422,7 +422,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
 		RID texture = (dbt.is_valid()) ? dbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
-		u.ids.push_back(texture);
+		u.append_id(texture);
 		uniforms.push_back(u);
 	}
 	{
@@ -431,7 +431,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
 		RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
-		u.ids.push_back(texture);
+		u.append_id(texture);
 		uniforms.push_back(u);
 	}
 
@@ -1145,11 +1145,9 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 		Vector<RD::Uniform> uniforms;
 
 		{
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.binding = 1;
-			u.ids.resize(12);
-			RID *ids_ptr = u.ids.ptrw();
+			Vector<RID> ids;
+			ids.resize(12);
+			RID *ids_ptr = ids.ptrw();
 			ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 			ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 			ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -1162,6 +1160,9 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 			ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 			ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+
 			uniforms.push_back(u);
 		}
 
@@ -1169,7 +1170,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 2;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.ids.push_back(scene_shader.shadow_sampler);
+			u.append_id(scene_shader.shadow_sampler);
 			uniforms.push_back(u);
 		}
 
@@ -1196,7 +1197,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 				} break;
 			}
 
-			u.ids.push_back(sampler);
+			u.append_id(sampler);
 			uniforms.push_back(u);
 		}
 
@@ -1223,7 +1224,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 				} break;
 			}
 
-			u.ids.push_back(sampler);
+			u.append_id(sampler);
 			uniforms.push_back(u);
 		}
 
@@ -1231,14 +1232,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 5;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(get_omni_light_buffer());
+			u.append_id(get_omni_light_buffer());
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 6;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(get_spot_light_buffer());
+			u.append_id(get_spot_light_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -1246,28 +1247,28 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.binding = 7;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(get_reflection_probe_buffer());
+			u.append_id(get_reflection_probe_buffer());
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 8;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-			u.ids.push_back(get_directional_light_buffer());
+			u.append_id(get_directional_light_buffer());
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 9;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(scene_state.lightmap_buffer);
+			u.append_id(scene_state.lightmap_buffer);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 10;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(scene_state.lightmap_capture_buffer);
+			u.append_id(scene_state.lightmap_capture_buffer);
 			uniforms.push_back(u);
 		}
 		{
@@ -1275,7 +1276,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			u.binding = 11;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID decal_atlas = storage->decal_atlas_get_texture();
-			u.ids.push_back(decal_atlas);
+			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
 		{
@@ -1283,14 +1284,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID decal_atlas = storage->decal_atlas_get_texture_srgb();
-			u.ids.push_back(decal_atlas);
+			u.append_id(decal_atlas);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.binding = 13;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(get_decal_buffer());
+			u.append_id(get_decal_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -1298,7 +1299,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 14;
-			u.ids.push_back(storage->global_variables_get_storage_buffer());
+			u.append_id(storage->global_variables_get_storage_buffer());
 			uniforms.push_back(u);
 		}
 

+ 1 - 1
servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp

@@ -734,7 +734,7 @@ void fragment() {
 		Vector<RD::Uniform> uniforms;
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-		u.ids.push_back(default_vec4_xform_buffer);
+		u.append_id(default_vec4_xform_buffer);
 		u.binding = 0;
 		uniforms.push_back(u);
 

+ 15 - 14
servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

@@ -931,7 +931,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 		u.binding = 1;
-		u.ids.push_back(state.canvas_state_buffer);
+		u.append_id(state.canvas_state_buffer);
 		uniforms.push_back(u);
 	}
 
@@ -939,7 +939,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 		u.binding = 2;
-		u.ids.push_back(state.lights_uniform_buffer);
+		u.append_id(state.lights_uniform_buffer);
 		uniforms.push_back(u);
 	}
 
@@ -947,7 +947,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.binding = 3;
-		u.ids.push_back(storage->decal_atlas_get_texture());
+		u.append_id(storage->decal_atlas_get_texture());
 		uniforms.push_back(u);
 	}
 
@@ -955,7 +955,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.binding = 4;
-		u.ids.push_back(state.shadow_texture);
+		u.append_id(state.shadow_texture);
 		uniforms.push_back(u);
 	}
 
@@ -963,7 +963,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 		u.binding = 5;
-		u.ids.push_back(state.shadow_sampler);
+		u.append_id(state.shadow_sampler);
 		uniforms.push_back(u);
 	}
 
@@ -980,7 +980,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 				screen = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
 			}
 		}
-		u.ids.push_back(screen);
+		u.append_id(screen);
 		uniforms.push_back(u);
 	}
 
@@ -989,17 +989,15 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.binding = 7;
 		RID sdf = storage->render_target_get_sdf_texture(p_to_render_target);
-		u.ids.push_back(sdf);
+		u.append_id(sdf);
 		uniforms.push_back(u);
 	}
 
 	{
 		//needs samplers for the material (uses custom textures) create them
-		RD::Uniform u;
-		u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-		u.binding = 8;
-		u.ids.resize(12);
-		RID *ids_ptr = u.ids.ptrw();
+		Vector<RID> ids;
+		ids.resize(12);
+		RID *ids_ptr = ids.ptrw();
 		ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 		ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 		ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -1012,6 +1010,9 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
 		ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 		ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 		ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+		RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 8, ids);
+
 		uniforms.push_back(u);
 	}
 
@@ -1019,7 +1020,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.ids.push_back(storage->global_variables_get_storage_buffer());
+		u.append_id(storage->global_variables_get_storage_buffer());
 		uniforms.push_back(u);
 	}
 
@@ -2567,7 +2568,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 0;
-			u.ids.push_back(storage->get_default_rd_storage_buffer());
+			u.append_id(storage->get_default_rd_storage_buffer());
 			uniforms.push_back(u);
 		}
 

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

@@ -56,8 +56,8 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 			u.binding = 0;
-			u.ids.push_back(blit.sampler);
-			u.ids.push_back(rd_texture);
+			u.append_id(blit.sampler);
+			u.append_id(rd_texture);
 			uniforms.push_back(u);
 			RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0);
 
@@ -175,8 +175,8 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 		u.binding = 0;
-		u.ids.push_back(blit.sampler);
-		u.ids.push_back(rd_texture);
+		u.append_id(blit.sampler);
+		u.append_id(rd_texture);
 		uniforms.push_back(u);
 		uset = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0);
 	}
@@ -241,6 +241,8 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
 RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
 
 RendererCompositorRD::RendererCompositorRD() {
+	uniform_set_cache = memnew(UniformSetCacheRD);
+
 	{
 		String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path();
 		if (shader_cache_dir.is_empty()) {
@@ -301,5 +303,6 @@ RendererCompositorRD::RendererCompositorRD() {
 }
 
 RendererCompositorRD::~RendererCompositorRD() {
+	memdelete(uniform_set_cache);
 	ShaderRD::set_shader_cache_dir(String());
 }

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

@@ -39,9 +39,11 @@
 #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h"
 #include "servers/rendering/renderer_rd/renderer_storage_rd.h"
 #include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
 
 class RendererCompositorRD : public RendererCompositor {
 protected:
+	UniformSetCacheRD *uniform_set_cache;
 	RendererCanvasRenderRD *canvas;
 	RendererStorageRD *storage;
 	RendererSceneRenderRD *scene;

Різницю між файлами не показано, бо вона завелика
+ 135 - 129
servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp


+ 41 - 37
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -4181,7 +4181,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.binding = 0;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			u.ids.push_back(rb->volumetric_fog->fog_map);
+			u.append_id(rb->volumetric_fog->fog_map);
 			uniforms.push_back(u);
 		}
 
@@ -4246,7 +4246,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 				u.binding = 1;
-				u.ids.push_back(rb->volumetric_fog->emissive_map);
+				u.append_id(rb->volumetric_fog->emissive_map);
 				uniforms.push_back(u);
 			}
 
@@ -4254,7 +4254,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 				u.binding = 2;
-				u.ids.push_back(volumetric_fog.volume_ubo);
+				u.append_id(volumetric_fog.volume_ubo);
 				uniforms.push_back(u);
 			}
 
@@ -4266,7 +4266,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 				u.binding = 3;
-				u.ids.push_back(rb->volumetric_fog->density_map);
+				u.append_id(rb->volumetric_fog->density_map);
 				uniforms.push_back(u);
 			}
 
@@ -4278,7 +4278,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 				u.binding = 4;
-				u.ids.push_back(rb->volumetric_fog->light_map);
+				u.append_id(rb->volumetric_fog->light_map);
 				uniforms.push_back(u);
 			}
 
@@ -4399,9 +4399,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			u.binding = 1;
 			ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
 			if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) {
-				u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
+				u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
 			} else {
-				u.ids.push_back(shadow_atlas->depth);
+				u.append_id(shadow_atlas->depth);
 			}
 
 			uniforms.push_back(u);
@@ -4413,9 +4413,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 2;
 			if (directional_shadow.depth.is_valid()) {
-				u.ids.push_back(directional_shadow.depth);
+				u.append_id(directional_shadow.depth);
 			} else {
-				u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
+				u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
 			}
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
@@ -4425,7 +4425,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 3;
-			u.ids.push_back(get_omni_light_buffer());
+			u.append_id(get_omni_light_buffer());
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4433,7 +4433,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 4;
-			u.ids.push_back(get_spot_light_buffer());
+			u.append_id(get_spot_light_buffer());
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4442,7 +4442,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.binding = 5;
-			u.ids.push_back(get_directional_light_buffer());
+			u.append_id(get_directional_light_buffer());
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4451,7 +4451,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 6;
-			u.ids.push_back(rb->cluster_builder->get_cluster_buffer());
+			u.append_id(rb->cluster_builder->get_cluster_buffer());
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4460,7 +4460,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 7;
-			u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4469,7 +4469,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 8;
-			u.ids.push_back(rb->volumetric_fog->light_density_map);
+			u.append_id(rb->volumetric_fog->light_density_map);
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4478,7 +4478,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 9;
-			u.ids.push_back(rb->volumetric_fog->fog_map);
+			u.append_id(rb->volumetric_fog->fog_map);
 			uniforms.push_back(u);
 		}
 
@@ -4486,7 +4486,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 9;
-			u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
+			u.append_id(rb->volumetric_fog->prev_light_density_map);
 			copy_uniforms.push_back(u);
 		}
 
@@ -4494,7 +4494,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 10;
-			u.ids.push_back(shadow_sampler);
+			u.append_id(shadow_sampler);
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4503,7 +4503,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.binding = 11;
-			u.ids.push_back(render_buffers_get_voxel_gi_buffer(p_render_buffers));
+			u.append_id(render_buffers_get_voxel_gi_buffer(p_render_buffers));
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4513,7 +4513,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 12;
 			for (int i = 0; i < RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES; i++) {
-				u.ids.push_back(rb->gi.voxel_gi_textures[i]);
+				u.append_id(rb->gi.voxel_gi_textures[i]);
 			}
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
@@ -4522,7 +4522,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 13;
-			u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+			u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4530,7 +4530,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.binding = 14;
-			u.ids.push_back(volumetric_fog.params_ubo);
+			u.append_id(volumetric_fog.params_ubo);
 			uniforms.push_back(u);
 			copy_uniforms.push_back(u);
 		}
@@ -4538,7 +4538,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 15;
-			u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
+			u.append_id(rb->volumetric_fog->prev_light_density_map);
 			uniforms.push_back(u);
 		}
 		{
@@ -4549,7 +4549,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 			u.binding = 16;
-			u.ids.push_back(rb->volumetric_fog->density_map);
+			u.append_id(rb->volumetric_fog->density_map);
 			uniforms.push_back(u);
 		}
 		{
@@ -4560,7 +4560,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 			u.binding = 17;
-			u.ids.push_back(rb->volumetric_fog->light_map);
+			u.append_id(rb->volumetric_fog->light_map);
 			uniforms.push_back(u);
 		}
 
@@ -4572,7 +4572,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 #endif
 			u.binding = 18;
-			u.ids.push_back(rb->volumetric_fog->emissive_map);
+			u.append_id(rb->volumetric_fog->emissive_map);
 			uniforms.push_back(u);
 		}
 
@@ -4582,7 +4582,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 			u.binding = 19;
 			RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
 			RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID();
-			u.ids.push_back(sky_texture.is_valid() ? sky_texture : radiance_texture);
+			u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture);
 			uniforms.push_back(u);
 		}
 
@@ -4590,7 +4590,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 
 		rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
 
-		SWAP(uniforms.write[7].ids.write[0], uniforms.write[8].ids.write[0]);
+		RID aux7 = uniforms.write[7].get_id(0);
+		RID aux8 = uniforms.write[8].get_id(0);
+
+		uniforms.write[7].set_id(0, aux8);
+		uniforms.write[8].set_id(0, aux7);
 
 		rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, 0), 0);
 	}
@@ -4605,7 +4609,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 				u.binding = 0;
-				u.ids.push_back(gi.sdfgi_ubo);
+				u.append_id(gi.sdfgi_ubo);
 				uniforms.push_back(u);
 			}
 
@@ -4613,7 +4617,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 1;
-				u.ids.push_back(rb->sdfgi->ambient_texture);
+				u.append_id(rb->sdfgi->ambient_texture);
 				uniforms.push_back(u);
 			}
 
@@ -4621,7 +4625,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 2;
-				u.ids.push_back(rb->sdfgi->occlusion_texture);
+				u.append_id(rb->sdfgi->occlusion_texture);
 				uniforms.push_back(u);
 			}
 
@@ -5754,11 +5758,9 @@ void fog() {
 			Vector<RD::Uniform> uniforms;
 
 			{
-				RD::Uniform u;
-				u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-				u.binding = 1;
-				u.ids.resize(12);
-				RID *ids_ptr = u.ids.ptrw();
+				Vector<RID> ids;
+				ids.resize(12);
+				RID *ids_ptr = ids.ptrw();
 				ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 				ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -5771,6 +5773,8 @@ void fog() {
 				ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 				ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 				ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+				RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
 				uniforms.push_back(u);
 			}
 
@@ -5778,7 +5782,7 @@ void fog() {
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 2;
-				u.ids.push_back(storage->global_variables_get_storage_buffer());
+				u.append_id(storage->global_variables_get_storage_buffer());
 				uniforms.push_back(u);
 			}
 

+ 23 - 22
servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp

@@ -630,9 +630,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.binding = 0;
 		if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) {
-			u.ids.push_back(radiance);
+			u.append_id(radiance);
 		} else {
-			u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+			u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
 		}
 		uniforms.push_back(u);
 	}
@@ -642,15 +642,15 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
 		u.binding = 1; // half res
 		if (half_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) {
 			if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
-				u.ids.push_back(reflection.layers[0].views[1]);
+				u.append_id(reflection.layers[0].views[1]);
 			} else {
-				u.ids.push_back(half_res_pass);
+				u.append_id(half_res_pass);
 			}
 		} else {
 			if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
-				u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+				u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
 			} else {
-				u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+				u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
 			}
 		}
 		uniforms.push_back(u);
@@ -661,15 +661,15 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
 		u.binding = 2; // quarter res
 		if (quarter_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) {
 			if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
-				u.ids.push_back(reflection.layers[0].views[2]);
+				u.append_id(reflection.layers[0].views[2]);
 			} else {
-				u.ids.push_back(quarter_res_pass);
+				u.append_id(quarter_res_pass);
 			}
 		} else {
 			if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
-				u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+				u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
 			} else {
-				u.ids.push_back(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+				u.append_id(p_storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
 			}
 		}
 		uniforms.push_back(u);
@@ -918,11 +918,9 @@ void sky() {
 		Vector<RD::Uniform> uniforms;
 
 		{
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.binding = 0;
-			u.ids.resize(12);
-			RID *ids_ptr = u.ids.ptrw();
+			Vector<RID> ids;
+			ids.resize(12);
+			RID *ids_ptr = ids.ptrw();
 			ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 			ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 			ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -935,6 +933,9 @@ void sky() {
 			ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 			ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 			ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 0, ids);
+
 			uniforms.push_back(u);
 		}
 
@@ -942,7 +943,7 @@ void sky() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 1;
-			u.ids.push_back(storage->global_variables_get_storage_buffer());
+			u.append_id(storage->global_variables_get_storage_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -950,7 +951,7 @@ void sky() {
 			RD::Uniform u;
 			u.binding = 2;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-			u.ids.push_back(sky_scene_state.uniform_buffer);
+			u.append_id(sky_scene_state.uniform_buffer);
 			uniforms.push_back(u);
 		}
 
@@ -958,7 +959,7 @@ void sky() {
 			RD::Uniform u;
 			u.binding = 3;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-			u.ids.push_back(sky_scene_state.directional_light_buffer);
+			u.append_id(sky_scene_state.directional_light_buffer);
 			uniforms.push_back(u);
 		}
 
@@ -972,7 +973,7 @@ void sky() {
 			u.binding = 0;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
-			u.ids.push_back(vfog);
+			u.append_id(vfog);
 			uniforms.push_back(u);
 		}
 
@@ -1005,21 +1006,21 @@ void sky() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 0;
-			u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 1;
-			u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.binding = 2;
-			u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+			u.append_id(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
 			uniforms.push_back(u);
 		}
 

+ 51 - 48
servers/rendering/renderer_rd/renderer_storage_rd.cpp

@@ -1320,10 +1320,10 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
 
 			t = texture_owner.get_or_null(ct->diffuse);
 			if (!t) {
-				u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+				u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
 				ct->size_cache = Size2i(1, 1);
 			} else {
-				u.ids.push_back(t->rd_texture);
+				u.append_id(t->rd_texture);
 				ct->size_cache = Size2i(t->width_2d, t->height_2d);
 			}
 			uniforms.push_back(u);
@@ -1335,10 +1335,10 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
 
 			t = texture_owner.get_or_null(ct->normal_map);
 			if (!t) {
-				u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
+				u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
 				ct->use_normal_cache = false;
 			} else {
-				u.ids.push_back(t->rd_texture);
+				u.append_id(t->rd_texture);
 				ct->use_normal_cache = true;
 			}
 			uniforms.push_back(u);
@@ -1350,10 +1350,10 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
 
 			t = texture_owner.get_or_null(ct->specular);
 			if (!t) {
-				u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+				u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
 				ct->use_specular_cache = false;
 			} else {
-				u.ids.push_back(t->rd_texture);
+				u.append_id(t->rd_texture);
 				ct->use_specular_cache = true;
 			}
 			uniforms.push_back(u);
@@ -1362,7 +1362,7 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
 			u.binding = 3;
-			u.ids.push_back(sampler_rd_get_default(filter, repeat));
+			u.append_id(sampler_rd_get_default(filter, repeat));
 			uniforms.push_back(u);
 		}
 
@@ -2933,7 +2933,7 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.binding = 0;
-			u.ids.push_back(uniform_buffer);
+			u.append_id(uniform_buffer);
 			uniforms.push_back(u);
 		}
 
@@ -2946,10 +2946,10 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
 			u.binding = 1 + k;
 			if (array_size > 0) {
 				for (int j = 0; j < array_size; j++) {
-					u.ids.push_back(textures[k++]);
+					u.append_id(textures[k++]);
 				}
 			} else {
-				u.ids.push_back(textures[k++]);
+				u.append_id(textures[k++]);
 			}
 			uniforms.push_back(u);
 		}
@@ -3155,7 +3155,7 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
 			RD::Uniform u;
 			u.binding = 0;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(s->vertex_buffer);
+			u.append_id(s->vertex_buffer);
 			uniforms.push_back(u);
 		}
 		{
@@ -3163,9 +3163,9 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
 			u.binding = 1;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			if (s->skin_buffer.is_valid()) {
-				u.ids.push_back(s->skin_buffer);
+				u.append_id(s->skin_buffer);
 			} else {
-				u.ids.push_back(default_rd_storage_buffer);
+				u.append_id(default_rd_storage_buffer);
 			}
 			uniforms.push_back(u);
 		}
@@ -3174,9 +3174,9 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
 			u.binding = 2;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			if (s->blend_shape_buffer.is_valid()) {
-				u.ids.push_back(s->blend_shape_buffer);
+				u.append_id(s->blend_shape_buffer);
 			} else {
-				u.ids.push_back(default_rd_storage_buffer);
+				u.append_id(default_rd_storage_buffer);
 			}
 			uniforms.push_back(u);
 		}
@@ -3618,7 +3618,7 @@ void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh,
 			RD::Uniform u;
 			u.binding = 1;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.ids.push_back(s.vertex_buffer);
+			u.append_id(s.vertex_buffer);
 			uniforms.push_back(u);
 		}
 		{
@@ -3626,9 +3626,9 @@ void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh,
 			u.binding = 2;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			if (mi->blend_weights_buffer.is_valid()) {
-				u.ids.push_back(mi->blend_weights_buffer);
+				u.append_id(mi->blend_weights_buffer);
 			} else {
-				u.ids.push_back(default_rd_storage_buffer);
+				u.append_id(default_rd_storage_buffer);
 			}
 			uniforms.push_back(u);
 		}
@@ -4953,14 +4953,14 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 0;
-			u.ids.push_back(p_particles->frame_params_buffer);
+			u.append_id(p_particles->frame_params_buffer);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 1;
-			u.ids.push_back(p_particles->particle_buffer);
+			u.append_id(p_particles->particle_buffer);
 			uniforms.push_back(u);
 		}
 
@@ -4969,9 +4969,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 2;
 			if (p_particles->emission_storage_buffer.is_valid()) {
-				u.ids.push_back(p_particles->emission_storage_buffer);
+				u.append_id(p_particles->emission_storage_buffer);
 			} else {
-				u.ids.push_back(default_rd_storage_buffer);
+				u.append_id(default_rd_storage_buffer);
 			}
 			uniforms.push_back(u);
 		}
@@ -4984,9 +4984,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
 				if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer
 					_particles_allocate_emission_buffer(sub_emitter);
 				}
-				u.ids.push_back(sub_emitter->emission_storage_buffer);
+				u.append_id(sub_emitter->emission_storage_buffer);
 			} else {
-				u.ids.push_back(default_rd_storage_buffer);
+				u.append_id(default_rd_storage_buffer);
 			}
 			uniforms.push_back(u);
 		}
@@ -5257,7 +5257,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
 					if (rd_tex == RID()) {
 						rd_tex = default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE];
 					}
-					u.ids.push_back(rd_tex);
+					u.append_id(rd_tex);
 				}
 				uniforms.push_back(u);
 			}
@@ -5266,9 +5266,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
 				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 				u.binding = 1;
 				if (collision_heightmap_texture.is_valid()) {
-					u.ids.push_back(collision_heightmap_texture);
+					u.append_id(collision_heightmap_texture);
 				} else {
-					u.ids.push_back(default_rd_textures[DEFAULT_RD_TEXTURE_BLACK]);
+					u.append_id(default_rd_textures[DEFAULT_RD_TEXTURE_BLACK]);
 				}
 				uniforms.push_back(u);
 			}
@@ -5402,7 +5402,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 0;
-				u.ids.push_back(particles->particles_sort_buffer);
+				u.append_id(particles->particles_sort_buffer);
 				uniforms.push_back(u);
 			}
 
@@ -5522,14 +5522,14 @@ void RendererStorageRD::_particles_update_buffers(Particles *particles) {
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 1;
-				u.ids.push_back(particles->particle_buffer);
+				u.append_id(particles->particle_buffer);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 2;
-				u.ids.push_back(particles->particle_instance_buffer);
+				u.append_id(particles->particle_instance_buffer);
 				uniforms.push_back(u);
 			}
 
@@ -5627,9 +5627,9 @@ void RendererStorageRD::update_particles() {
 					u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 					u.binding = 0;
 					if (particles->trail_bind_pose_buffer.is_valid()) {
-						u.ids.push_back(particles->trail_bind_pose_buffer);
+						u.append_id(particles->trail_bind_pose_buffer);
 					} else {
-						u.ids.push_back(default_rd_storage_buffer);
+						u.append_id(default_rd_storage_buffer);
 					}
 					uniforms.push_back(u);
 				}
@@ -6315,7 +6315,7 @@ void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool
 				RD::Uniform u;
 				u.binding = 0;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-				u.ids.push_back(skeleton->buffer);
+				u.append_id(skeleton->buffer);
 				uniforms.push_back(u);
 			}
 			skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
@@ -7146,21 +7146,21 @@ void RendererStorageRD::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 1;
-				u.ids.push_back(voxel_gi->octree_buffer);
+				u.append_id(voxel_gi->octree_buffer);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 2;
-				u.ids.push_back(voxel_gi->data_buffer);
+				u.append_id(voxel_gi->data_buffer);
 				uniforms.push_back(u);
 			}
 			{
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 				u.binding = 3;
-				u.ids.push_back(shared_tex);
+				u.append_id(shared_tex);
 				uniforms.push_back(u);
 			}
 
@@ -8008,33 +8008,36 @@ void RendererStorageRD::_render_target_allocate_sdf(RenderTarget *rt) {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 1;
-			u.ids.push_back(rt->sdf_buffer_write);
+			u.append_id(rt->sdf_buffer_write);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 2;
-			u.ids.push_back(rt->sdf_buffer_read);
+			u.append_id(rt->sdf_buffer_read);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 3;
-			u.ids.push_back(rt->sdf_buffer_process[0]);
+			u.append_id(rt->sdf_buffer_process[0]);
 			uniforms.push_back(u);
 		}
 		{
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 			u.binding = 4;
-			u.ids.push_back(rt->sdf_buffer_process[1]);
+			u.append_id(rt->sdf_buffer_process[1]);
 			uniforms.push_back(u);
 		}
 
 		rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
-		SWAP(uniforms.write[2].ids.write[0], uniforms.write[3].ids.write[0]);
+		RID aux2 = uniforms.write[2].get_id(0);
+		RID aux3 = uniforms.write[3].get_id(0);
+		uniforms.write[2].set_id(0, aux3);
+		uniforms.write[3].set_id(0, aux2);
 		rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
 	}
 }
@@ -10074,11 +10077,9 @@ void process() {
 		Vector<RD::Uniform> uniforms;
 
 		{
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.binding = 1;
-			u.ids.resize(12);
-			RID *ids_ptr = u.ids.ptrw();
+			Vector<RID> ids;
+			ids.resize(12);
+			RID *ids_ptr = ids.ptrw();
 			ids_ptr[0] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 			ids_ptr[1] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
 			ids_ptr[2] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -10091,6 +10092,8 @@ void process() {
 			ids_ptr[9] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 			ids_ptr[10] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
 			ids_ptr[11] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+			RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
 			uniforms.push_back(u);
 		}
 
@@ -10098,7 +10101,7 @@ void process() {
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 2;
-			u.ids.push_back(global_variables_get_storage_buffer());
+			u.append_id(global_variables_get_storage_buffer());
 			uniforms.push_back(u);
 		}
 
@@ -10167,7 +10170,7 @@ void process() {
 				RD::Uniform u;
 				u.binding = 0;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-				u.ids.push_back(default_rd_storage_buffer);
+				u.append_id(default_rd_storage_buffer);
 				uniforms.push_back(u);
 			}
 			skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);

+ 4 - 4
servers/rendering/renderer_rd/renderer_storage_rd.h

@@ -1765,7 +1765,7 @@ public:
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 0;
-			u.ids.push_back(multimesh->buffer);
+			u.append_id(multimesh->buffer);
 			uniforms.push_back(u);
 			multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
 		}
@@ -1780,7 +1780,7 @@ public:
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 0;
-			u.ids.push_back(multimesh->buffer);
+			u.append_id(multimesh->buffer);
 			uniforms.push_back(u);
 			multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
 		}
@@ -1818,7 +1818,7 @@ public:
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.binding = 0;
-			u.ids.push_back(skeleton->buffer);
+			u.append_id(skeleton->buffer);
 			uniforms.push_back(u);
 			skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
 		}
@@ -2276,7 +2276,7 @@ public:
 				RD::Uniform u;
 				u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 				u.binding = 0;
-				u.ids.push_back(particles->particle_instance_buffer);
+				u.append_id(particles->particle_instance_buffer);
 				uniforms.push_back(u);
 			}
 

+ 64 - 0
servers/rendering/renderer_rd/uniform_set_cache_rd.cpp

@@ -0,0 +1,64 @@
+/*************************************************************************/
+/*  uniform_set_cache_rd.cpp                                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "uniform_set_cache_rd.h"
+
+UniformSetCacheRD *UniformSetCacheRD::singleton = nullptr;
+
+void UniformSetCacheRD::_invalidate(Cache *p_cache) {
+	if (p_cache->prev) {
+		p_cache->prev->next = p_cache->next;
+	} else {
+		// At begining of table
+		uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE;
+		hash_table[table_idx] = p_cache->next;
+	}
+
+	if (p_cache->next) {
+		p_cache->next->prev = p_cache->prev;
+	}
+
+	cache_allocator.free(p_cache);
+	cache_instances_used--;
+}
+void UniformSetCacheRD::_uniform_set_invalidation_callback(void *p_userdata) {
+	singleton->_invalidate(reinterpret_cast<Cache *>(p_userdata));
+}
+
+UniformSetCacheRD::UniformSetCacheRD() {
+	ERR_FAIL_COND(singleton != nullptr);
+	singleton = this;
+}
+
+UniformSetCacheRD::~UniformSetCacheRD() {
+	if (cache_instances_used > 0) {
+		ERR_PRINT("At exit: " + itos(cache_instances_used) + " uniform set cache instance(s) still in use.");
+	}
+}

+ 221 - 0
servers/rendering/renderer_rd/uniform_set_cache_rd.h

@@ -0,0 +1,221 @@
+/*************************************************************************/
+/*  uniform_set_cache_rd.h                                               */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef UNIFORM_SET_CACHE_H
+#define UNIFORM_SET_CACHE_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/paged_allocator.h"
+#include "servers/rendering/rendering_device.h"
+
+class UniformSetCacheRD : public Object {
+	GDCLASS(UniformSetCacheRD, Object)
+
+	struct Cache {
+		Cache *prev = nullptr;
+		Cache *next = nullptr;
+		uint32_t hash = 0;
+		RID shader;
+		uint32_t set = 0;
+		RID cache;
+		LocalVector<RD::Uniform> uniforms;
+	};
+
+	PagedAllocator<Cache> cache_allocator;
+
+	enum {
+		HASH_TABLE_SIZE = 16381 // Prime
+	};
+
+	Cache *hash_table[HASH_TABLE_SIZE] = {};
+
+	static _FORCE_INLINE_ uint32_t _hash_uniform(const RD::Uniform &u, uint32_t h) {
+		h = hash_djb2_one_32(u.uniform_type, h);
+		h = hash_djb2_one_32(u.binding, h);
+		uint32_t rsize = u.get_id_count();
+		for (uint32_t j = 0; j < rsize; j++) {
+			h = hash_djb2_one_64(u.get_id(j).get_id(), h);
+		}
+		return h;
+	}
+
+	static _FORCE_INLINE_ bool _compare_uniform(const RD::Uniform &a, const RD::Uniform &b) {
+		if (a.binding != b.binding) {
+			return false;
+		}
+		if (a.uniform_type != b.uniform_type) {
+			return false;
+		}
+		uint32_t rsize = a.get_id_count();
+		if (rsize != b.get_id_count()) {
+			return false;
+		}
+		for (uint32_t j = 0; j < rsize; j++) {
+			if (a.get_id(j) != b.get_id(j)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	_FORCE_INLINE_ uint32_t _hash_args(uint32_t h, const RD::Uniform &arg) {
+		return _hash_uniform(arg, h);
+	}
+
+	template <typename... Args>
+	uint32_t _hash_args(uint32_t h, const RD::Uniform &arg, Args... args) {
+		h = _hash_uniform(arg, h);
+		return _hash_args(h, args...);
+	}
+
+	_FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RD::Uniform> &uniforms, const RD::Uniform &arg) {
+		return _compare_uniform(uniforms[idx], arg);
+	}
+
+	template <typename... Args>
+	_FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RD::Uniform> &uniforms, const RD::Uniform &arg, Args... args) {
+		if (!_compare_uniform(uniforms[idx], arg)) {
+			return false;
+		}
+		return _compare_args(idx + 1, uniforms, args...);
+	}
+
+	_FORCE_INLINE_ void _create_args(Vector<RD::Uniform> &uniforms, const RD::Uniform &arg) {
+		uniforms.push_back(arg);
+	}
+
+	template <typename... Args>
+	_FORCE_INLINE_ void _create_args(Vector<RD::Uniform> &uniforms, const RD::Uniform &arg, Args... args) {
+		uniforms.push_back(arg);
+		_create_args(uniforms, args...);
+	}
+
+	static UniformSetCacheRD *singleton;
+
+	uint32_t cache_instances_used = 0;
+
+	void _invalidate(Cache *p_cache);
+	static void _uniform_set_invalidation_callback(void *p_userdata);
+
+	RID _allocate_from_uniforms(RID p_shader, uint32_t p_set, uint32_t p_hash, uint32_t p_table_idx, const Vector<RD::Uniform> &p_uniforms) {
+		RID rid = RD::get_singleton()->uniform_set_create(p_uniforms, p_shader, p_set);
+		ERR_FAIL_COND_V(rid.is_null(), rid);
+
+		Cache *c = cache_allocator.alloc();
+		c->hash = p_hash;
+		c->set = p_set;
+		c->shader = p_shader;
+		c->cache = rid;
+		c->uniforms.resize(p_uniforms.size());
+		for (uint32_t i = 0; i < c->uniforms.size(); i++) {
+			c->uniforms[i] = p_uniforms[i];
+		}
+		c->prev = nullptr;
+		c->next = hash_table[p_table_idx];
+		if (hash_table[p_table_idx]) {
+			hash_table[p_table_idx]->prev = c;
+		}
+		hash_table[p_table_idx] = c;
+
+		RD::get_singleton()->uniform_set_set_invalidation_callback(rid, _uniform_set_invalidation_callback, c);
+
+		cache_instances_used++;
+
+		return rid;
+	}
+
+public:
+	template <typename... Args>
+	RID get_cache(RID p_shader, uint32_t p_set, Args... args) {
+		uint32_t h = hash_djb2_one_64(p_shader.get_id());
+		h = hash_djb2_one_32(p_set, h);
+		h = _hash_args(h, args...);
+
+		uint32_t table_idx = h % HASH_TABLE_SIZE;
+		{
+			const Cache *c = hash_table[table_idx];
+
+			while (c) {
+				if (c->hash == h && c->set == p_set && c->shader == p_shader && _compare_args(0, c->uniforms, args...)) {
+					return c->cache;
+				}
+				c = c->next;
+			}
+		}
+
+		// Not in cache, create:
+
+		Vector<RD::Uniform> uniforms;
+		_create_args(uniforms, args...);
+
+		return _allocate_from_uniforms(p_shader, p_set, h, table_idx, uniforms);
+	}
+
+	template <typename... Args>
+	RID get_cache_vec(RID p_shader, uint32_t p_set, const Vector<RD::Uniform> &p_uniforms) {
+		uint32_t h = hash_djb2_one_64(p_shader.get_id());
+		h = hash_djb2_one_32(p_set, h);
+		for (int i = 0; i < p_uniforms.size(); i++) {
+			h = _hash_uniform(p_uniforms[i], h);
+		}
+
+		uint32_t table_idx = h % HASH_TABLE_SIZE;
+		{
+			const Cache *c = hash_table[table_idx];
+
+			while (c) {
+				if (c->hash == h && c->set == p_set && c->shader == p_shader) {
+					bool all_ok = true;
+					for (int i = 0; i < p_uniforms.size(); i++) {
+						if (!_compare_uniform(p_uniforms[i], c->uniforms[i])) {
+							all_ok = false;
+							break;
+						}
+					}
+
+					if (all_ok) {
+						return c->cache;
+					}
+				}
+				c = c->next;
+			}
+		}
+
+		// Not in cache, create:
+		return _allocate_from_uniforms(p_shader, p_set, h, table_idx, p_uniforms);
+	}
+
+	static UniformSetCacheRD *get_singleton() { return singleton; }
+
+	UniformSetCacheRD();
+	~UniformSetCacheRD();
+};
+
+#endif // UNIFORMSETCACHE_H

+ 57 - 8
servers/rendering/rendering_device.h

@@ -726,16 +726,65 @@ public:
 
 	struct Uniform {
 		UniformType uniform_type;
-		int binding; //binding index as specified in shader
+		int binding; // Binding index as specified in shader.
 
-		//for single items, provide one ID, for
-		//multiple items (declared as arrays in shader),
-		//provide more
-		//for sampler with texture, supply two IDs for each.
-		//accepted IDs are: Sampler, Texture, Uniform Buffer and Texture Buffer
-		Vector<RID> ids;
+	private:
+		// In most cases only one ID is provided per binding, so avoid allocating memory unnecesarily for performance.
+		RID id; // If only one is provided, this is used.
+		Vector<RID> ids; // If multiple ones are provided, this is used instead.
 
-		Uniform() {
+	public:
+		_FORCE_INLINE_ uint32_t get_id_count() const {
+			return (id.is_valid() ? 1 : ids.size());
+		}
+
+		_FORCE_INLINE_ RID get_id(uint32_t p_idx) const {
+			if (id.is_valid()) {
+				ERR_FAIL_COND_V(p_idx != 0, RID());
+				return id;
+			} else {
+				return ids[p_idx];
+			}
+		}
+		_FORCE_INLINE_ void set_id(uint32_t p_idx, RID p_id) {
+			if (id.is_valid()) {
+				ERR_FAIL_COND(p_idx != 0);
+				id = p_id;
+			} else {
+				ids.write[p_idx] = p_id;
+			}
+		}
+
+		_FORCE_INLINE_ void append_id(RID p_id) {
+			if (ids.is_empty()) {
+				if (id == RID()) {
+					id = p_id;
+				} else {
+					ids.push_back(id);
+					ids.push_back(p_id);
+					id = RID();
+				}
+			} else {
+				ids.push_back(p_id);
+			}
+		}
+
+		_FORCE_INLINE_ void clear_ids() {
+			id = RID();
+			ids.clear();
+		}
+
+		_FORCE_INLINE_ Uniform(UniformType p_type, int p_binding, RID p_id) {
+			uniform_type = p_type;
+			binding = p_binding;
+			id = p_id;
+		}
+		_FORCE_INLINE_ Uniform(UniformType p_type, int p_binding, const Vector<RID> &p_ids) {
+			uniform_type = p_type;
+			binding = p_binding;
+			ids = p_ids;
+		}
+		_FORCE_INLINE_ Uniform() {
 			uniform_type = UNIFORM_TYPE_IMAGE;
 			binding = 0;
 		}

+ 6 - 6
servers/rendering/rendering_device_binds.h

@@ -441,23 +441,23 @@ public:
 	RD_SETGET(RD::UniformType, uniform_type)
 	RD_SETGET(int32_t, binding)
 
-	void add_id(const RID &p_id) { base.ids.push_back(p_id); }
-	void clear_ids() { base.ids.clear(); }
+	void add_id(const RID &p_id) { base.append_id(p_id); }
+	void clear_ids() { base.clear_ids(); }
 	Array get_ids() const {
 		Array ids;
-		for (int i = 0; i < base.ids.size(); i++) {
-			ids.push_back(base.ids[i]);
+		for (uint32_t i = 0; i < base.get_id_count(); i++) {
+			ids.push_back(base.get_id(i));
 		}
 		return ids;
 	}
 
 protected:
 	void _set_ids(const Array &p_ids) {
-		base.ids.clear();
+		base.clear_ids();
 		for (int i = 0; i < p_ids.size(); i++) {
 			RID id = p_ids[i];
 			ERR_FAIL_COND(id.is_null());
-			base.ids.push_back(id);
+			base.append_id(id);
 		}
 	}
 	static void _bind_methods() {

Деякі файли не було показано, через те що забагато файлів було змінено