Browse Source

Merge pull request #97554 from clayjohn/batching-uniform-sets

Combine texture and instance data into one uniform set in the 2D renderer
Rémi Verschelde 11 months ago
parent
commit
e7a9104f37

+ 71 - 93
servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

@@ -1974,6 +1974,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
 	default_canvas_texture = texture_storage->canvas_texture_allocate();
 	texture_storage->canvas_texture_initialize(default_canvas_texture);
 
+	RendererRD::TextureStorage::CanvasTextureInfo info = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_info(default_canvas_texture, default_filter, default_repeat, false, false);
+	default_texture_info.diffuse = info.diffuse;
+	default_texture_info.normal = info.normal;
+	default_texture_info.specular = info.specular;
+	default_texture_info.sampler = info.sampler;
+
 	state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
 
 	//create functions for shader and material
@@ -2219,7 +2225,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.default_transforms_uniform_set, TRANSFORMS_UNIFORM_SET);
 
 	Item *current_clip = nullptr;
-	state.current_tex_uniform_set = RID();
+	state.current_batch_uniform_set = RID();
 
 	for (uint32_t i = 0; i <= state.current_batch_index; i++) {
 		Batch *current_batch = &state.canvas_instance_batches[i];
@@ -2337,11 +2343,11 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 			instance_data->world[i] = world[i];
 		}
 
-		instance_data->flags = base_flags | r_current_batch->tex_flags; // Reset on each command for safety, keep canvas texture binding config.
+		instance_data->flags = base_flags | r_current_batch->tex_info.flags; // Reset on each command for safety, keep canvas texture binding config.
 
-		instance_data->color_texture_pixel_size[0] = r_current_batch->tex_texpixel_size.width;
-		instance_data->color_texture_pixel_size[1] = r_current_batch->tex_texpixel_size.height;
-		instance_data->specular_shininess = r_current_batch->tex_specular_shininess;
+		instance_data->color_texture_pixel_size[0] = r_current_batch->tex_info.texpixel_size.width;
+		instance_data->color_texture_pixel_size[1] = r_current_batch->tex_info.texpixel_size.height;
+		instance_data->specular_shininess = r_current_batch->tex_info.specular_shininess;
 
 		return instance_data;
 	};
@@ -2373,10 +2379,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 				bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF);
 				TextureState tex_state(rect->texture, texture_filter, texture_repeat, has_msdf, use_linear_colors);
 
-				if (tex_state != r_current_batch->tex_state) {
+				if (tex_state != r_current_batch->tex_info.state) {
 					r_current_batch = _new_batch(r_batch_broken);
-					r_current_batch->set_tex_state(tex_state);
-					_prepare_batch_texture(r_current_batch, rect->texture);
+					r_current_batch->tex_info.state = tex_state;
+					_prepare_batch_texture_info(r_current_batch, rect->texture);
 				}
 
 				Color modulated = rect->modulate * base_color;
@@ -2399,7 +2405,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 				Rect2 dst_rect;
 
 				if (rect->texture.is_valid()) {
-					src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * r_current_batch->tex_texpixel_size, rect->source.size * r_current_batch->tex_texpixel_size) : Rect2(0, 0, 1, 1);
+					src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * r_current_batch->tex_info.texpixel_size, rect->source.size * r_current_batch->tex_info.texpixel_size) : Rect2(0, 0, 1, 1);
 					dst_rect = Rect2(rect->rect.position, rect->rect.size);
 
 					if (dst_rect.size.width < 0) {
@@ -2484,10 +2490,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 				}
 
 				TextureState tex_state(np->texture, texture_filter, texture_repeat, false, use_linear_colors);
-				if (tex_state != r_current_batch->tex_state) {
+				if (tex_state != r_current_batch->tex_info.state) {
 					r_current_batch = _new_batch(r_batch_broken);
-					r_current_batch->set_tex_state(tex_state);
-					_prepare_batch_texture(r_current_batch, np->texture);
+					r_current_batch->tex_info.state = tex_state;
+					_prepare_batch_texture_info(r_current_batch, np->texture);
 				}
 
 				InstanceData *instance_data = new_instance_data();
@@ -2499,7 +2505,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 					src_rect = Rect2(0, 0, 1, 1);
 				} else {
 					if (np->source != Rect2()) {
-						src_rect = Rect2(np->source.position.x * r_current_batch->tex_texpixel_size.width, np->source.position.y * r_current_batch->tex_texpixel_size.height, np->source.size.x * r_current_batch->tex_texpixel_size.width, np->source.size.y * r_current_batch->tex_texpixel_size.height);
+						src_rect = Rect2(np->source.position.x * r_current_batch->tex_info.texpixel_size.width, np->source.position.y * r_current_batch->tex_info.texpixel_size.height, np->source.size.x * r_current_batch->tex_info.texpixel_size.width, np->source.size.y * r_current_batch->tex_info.texpixel_size.height);
 						instance_data->color_texture_pixel_size[0] = 1.0 / np->source.size.width;
 						instance_data->color_texture_pixel_size[1] = 1.0 / np->source.size.height;
 					} else {
@@ -2553,10 +2559,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 				r_current_batch->command = c;
 
 				TextureState tex_state(polygon->texture, texture_filter, texture_repeat, false, use_linear_colors);
-				if (tex_state != r_current_batch->tex_state) {
+				if (tex_state != r_current_batch->tex_info.state) {
 					r_current_batch = _new_batch(r_batch_broken);
-					r_current_batch->set_tex_state(tex_state);
-					_prepare_batch_texture(r_current_batch, polygon->texture);
+					r_current_batch->tex_info.state = tex_state;
+					_prepare_batch_texture_info(r_current_batch, polygon->texture);
 				}
 
 				// pipeline variant
@@ -2596,10 +2602,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 					r_current_batch->pipeline_variant = variant[primitive->point_count - 1];
 
 					TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors);
-					if (tex_state != r_current_batch->tex_state) {
+					if (tex_state != r_current_batch->tex_info.state) {
 						r_current_batch = _new_batch(r_batch_broken);
-						r_current_batch->set_tex_state(tex_state);
-						_prepare_batch_texture(r_current_batch, primitive->texture);
+						r_current_batch->tex_info.state = tex_state;
+						_prepare_batch_texture_info(r_current_batch, primitive->texture);
 					}
 				}
 
@@ -2657,8 +2663,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 				if (c->type == Item::Command::TYPE_MESH) {
 					const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c);
 					TextureState tex_state(m->texture, texture_filter, texture_repeat, false, use_linear_colors);
-					r_current_batch->set_tex_state(tex_state);
-					_prepare_batch_texture(r_current_batch, m->texture);
+					r_current_batch->tex_info.state = tex_state;
+					_prepare_batch_texture_info(r_current_batch, m->texture);
 					instance_data = new_instance_data();
 
 					r_current_batch->mesh_instance_count = 1;
@@ -2680,8 +2686,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 					}
 
 					TextureState tex_state(mm->texture, texture_filter, texture_repeat, false, use_linear_colors);
-					r_current_batch->set_tex_state(tex_state);
-					_prepare_batch_texture(r_current_batch, mm->texture);
+					r_current_batch->tex_info.state = tex_state;
+					_prepare_batch_texture_info(r_current_batch, mm->texture);
 					instance_data = new_instance_data();
 
 					instance_data->flags |= 1; // multimesh, trails disabled
@@ -2698,8 +2704,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
 
 					const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
 					TextureState tex_state(pt->texture, texture_filter, texture_repeat, false, use_linear_colors);
-					r_current_batch->set_tex_state(tex_state);
-					_prepare_batch_texture(r_current_batch, pt->texture);
+					r_current_batch->tex_info.state = tex_state;
+					_prepare_batch_texture_info(r_current_batch, pt->texture);
 
 					instance_data = new_instance_data();
 
@@ -2795,7 +2801,20 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
 
 	ERR_FAIL_NULL(p_batch->command);
 
-	_bind_canvas_texture(p_draw_list, p_batch->tex_uniform_set);
+	{
+		RD::Uniform u_diffuse(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info.diffuse);
+		RD::Uniform u_normal(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info.normal);
+		RD::Uniform u_specular(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info.specular);
+		RD::Uniform u_sampler(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info.sampler);
+		RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
+
+		RID uniform_set = uniform_set_cache->get_cache(shader.default_version_rd_shader, BATCH_UNIFORM_SET, u_diffuse, u_normal, u_specular, u_sampler, u_instance_data);
+
+		if (state.current_batch_uniform_set != uniform_set) {
+			state.current_batch_uniform_set = uniform_set;
+			RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, BATCH_UNIFORM_SET);
+		}
+	}
 
 	switch (p_batch->command_type) {
 		case Item::Command::TYPE_RECT:
@@ -2810,13 +2829,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
 			PushConstant push_constant;
 			push_constant.base_instance_index = p_batch->start;
 			RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
-
-			RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
-			RD::get_singleton()->draw_list_bind_uniform_set(
-					p_draw_list,
-					uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data),
-					INSTANCE_DATA_UNIFORM_SET);
-
 			RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array);
 			RD::get_singleton()->draw_list_draw(p_draw_list, true, p_batch->instance_count);
 
@@ -2839,13 +2851,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
 			PushConstant push_constant;
 			push_constant.base_instance_index = p_batch->start;
 			RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
-
-			RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
-			RD::get_singleton()->draw_list_bind_uniform_set(
-					p_draw_list,
-					uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data),
-					INSTANCE_DATA_UNIFORM_SET);
-
 			RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array);
 			if (pb->indices.is_valid()) {
 				RD::get_singleton()->draw_list_bind_index_array(p_draw_list, pb->indices);
@@ -2868,13 +2873,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
 			PushConstant push_constant;
 			push_constant.base_instance_index = p_batch->start;
 			RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
-
-			RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
-			RD::get_singleton()->draw_list_bind_uniform_set(
-					p_draw_list,
-					uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data),
-					INSTANCE_DATA_UNIFORM_SET);
-
 			RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]);
 			uint32_t instance_count = p_batch->instance_count;
 			RD::get_singleton()->draw_list_draw(p_draw_list, true, instance_count);
@@ -2934,12 +2932,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, PipelineV
 				break;
 			}
 
-			RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 0, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
-			RD::get_singleton()->draw_list_bind_uniform_set(
-					p_draw_list,
-					uniform_set_cache->get_cache(shader.default_version_rd_shader, INSTANCE_DATA_UNIFORM_SET, u_instance_data),
-					INSTANCE_DATA_UNIFORM_SET);
-
 			uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
 			static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
 
@@ -3046,60 +3038,46 @@ void RendererCanvasRenderRD::_allocate_instance_buffer() {
 	state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.push_back(buf);
 }
 
-void RendererCanvasRenderRD::_prepare_batch_texture(Batch *p_current_batch, RID p_texture) const {
+void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const {
 	if (p_texture.is_null()) {
 		p_texture = default_canvas_texture;
 	}
 
-	Color specular_shininess;
-	bool use_normal;
-	bool use_specular;
-	Size2i size;
-	bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set(
-			p_texture,
-			p_current_batch->tex_state.texture_filter(),
-			p_current_batch->tex_state.texture_repeat(),
-			shader.default_version_rd_shader,
-			CANVAS_TEXTURE_UNIFORM_SET,
-			p_current_batch->tex_state.linear_colors(),
-			p_current_batch->tex_uniform_set,
-			size,
-			specular_shininess,
-			use_normal,
-			use_specular,
-			p_current_batch->tex_state.texture_is_data());
+	RendererRD::TextureStorage::CanvasTextureInfo info =
+			RendererRD::TextureStorage::get_singleton()->canvas_texture_get_info(
+					p_texture,
+					p_current_batch->tex_info.state.texture_filter(),
+					p_current_batch->tex_info.state.texture_repeat(),
+					p_current_batch->tex_info.state.linear_colors(),
+					p_current_batch->tex_info.state.texture_is_data());
+
 	// something odd happened
-	if (!success) {
-		_prepare_batch_texture(p_current_batch, default_canvas_texture);
+	if (info.is_null()) {
+		_prepare_batch_texture_info(p_current_batch, default_canvas_texture);
 		return;
 	}
 
-	// cache values to be copied to instance data
-	if (specular_shininess.a < 0.999) {
-		p_current_batch->tex_flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED;
-	}
+	p_current_batch->tex_info.diffuse = info.diffuse;
+	p_current_batch->tex_info.normal = info.normal;
+	p_current_batch->tex_info.specular = info.specular;
+	p_current_batch->tex_info.sampler = info.sampler;
 
-	if (use_normal) {
-		p_current_batch->tex_flags |= FLAGS_DEFAULT_NORMAL_MAP_USED;
+	// cache values to be copied to instance data
+	if (info.specular_color.a < 0.999) {
+		p_current_batch->tex_info.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED;
 	}
 
-	uint8_t a = uint8_t(CLAMP(specular_shininess.a * 255.0, 0.0, 255.0));
-	uint8_t b = uint8_t(CLAMP(specular_shininess.b * 255.0, 0.0, 255.0));
-	uint8_t g = uint8_t(CLAMP(specular_shininess.g * 255.0, 0.0, 255.0));
-	uint8_t r = uint8_t(CLAMP(specular_shininess.r * 255.0, 0.0, 255.0));
-	p_current_batch->tex_specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r);
-
-	p_current_batch->tex_texpixel_size = Vector2(1.0 / float(size.width), 1.0 / float(size.height));
-}
-
-void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_uniform_set) {
-	if (state.current_tex_uniform_set == p_uniform_set) {
-		return;
+	if (info.use_normal) {
+		p_current_batch->tex_info.flags |= FLAGS_DEFAULT_NORMAL_MAP_USED;
 	}
 
-	state.current_tex_uniform_set = p_uniform_set;
+	uint8_t a = uint8_t(CLAMP(info.specular_color.a * 255.0, 0.0, 255.0));
+	uint8_t b = uint8_t(CLAMP(info.specular_color.b * 255.0, 0.0, 255.0));
+	uint8_t g = uint8_t(CLAMP(info.specular_color.g * 255.0, 0.0, 255.0));
+	uint8_t r = uint8_t(CLAMP(info.specular_color.r * 255.0, 0.0, 255.0));
+	p_current_batch->tex_info.specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r);
 
-	RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, p_uniform_set, CANVAS_TEXTURE_UNIFORM_SET);
+	p_current_batch->tex_info.texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height));
 }
 
 RendererCanvasRenderRD::~RendererCanvasRenderRD() {

+ 18 - 25
servers/rendering/renderer_rd/renderer_canvas_render_rd.h

@@ -45,8 +45,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 		BASE_UNIFORM_SET = 0,
 		MATERIAL_UNIFORM_SET = 1,
 		TRANSFORMS_UNIFORM_SET = 2,
-		CANVAS_TEXTURE_UNIFORM_SET = 3,
-		INSTANCE_DATA_UNIFORM_SET = 4,
+		BATCH_UNIFORM_SET = 3,
 	};
 
 	const int SAMPLERS_BINDING_FIRST_INDEX = 10;
@@ -423,24 +422,25 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 		}
 	};
 
+	struct TextureInfo {
+		TextureState state;
+		uint32_t specular_shininess = 0;
+		uint32_t flags = 0;
+		Vector2 texpixel_size;
+
+		RID diffuse;
+		RID normal;
+		RID specular;
+		RID sampler;
+	};
+
 	struct Batch {
 		// Position in the UBO measured in bytes
 		uint32_t start = 0;
 		uint32_t instance_count = 0;
 		uint32_t instance_buffer_index = 0;
 
-		TextureState tex_state;
-		RID tex_uniform_set;
-
-		// The following tex_ prefixed fields are used to cache the texture data for the current batch.
-		// These values are applied to new InstanceData for the batch
-
-		// The cached specular shininess derived from the current texture.
-		uint32_t tex_specular_shininess = 0;
-		// The cached texture flags, such as FLAGS_DEFAULT_SPECULAR_MAP_USED and FLAGS_DEFAULT_NORMAL_MAP_USED
-		uint32_t tex_flags = 0;
-		// The cached texture pixel size.
-		Vector2 tex_texpixel_size;
+		TextureInfo tex_info;
 
 		Color modulate = Color(1.0, 1.0, 1.0, 1.0);
 
@@ -462,14 +462,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 			uint32_t mesh_instance_count;
 		};
 		bool has_blend = false;
-
-		void set_tex_state(TextureState &p_tex_state) {
-			tex_state = p_tex_state;
-			tex_uniform_set = RID();
-			tex_texpixel_size = Size2();
-			tex_specular_shininess = 0;
-			tex_flags = 0;
-		}
 	};
 
 	struct DataBuffer {
@@ -509,7 +501,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 		uint32_t max_instances_per_buffer = 16384;
 		uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData);
 
-		RID current_tex_uniform_set;
+		RID current_batch_uniform_set;
 
 		LightUniform *light_uniforms = nullptr;
 
@@ -532,6 +524,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 
 	Item *items[MAX_RENDER_ITEMS];
 
+	TextureInfo default_texture_info;
+
 	bool using_directional_lights = false;
 	RID default_canvas_texture;
 
@@ -561,8 +555,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 	void _render_batch_items(RenderTarget p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr);
 	void _record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch);
 	void _render_batch(RD::DrawListID p_draw_list, PipelineVariants *p_pipeline_variants, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info = nullptr);
-	void _prepare_batch_texture(Batch *p_current_batch, RID p_texture) const;
-	void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_uniform_set);
+	void _prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const;
 	[[nodiscard]] Batch *_new_batch(bool &r_batch_broken);
 	void _add_to_batch(uint32_t &r_index, bool &r_batch_broken, Batch *&r_current_batch);
 	void _allocate_instance_buffer();

+ 5 - 5
servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl

@@ -54,11 +54,6 @@ struct InstanceData {
 	uint lights[4];
 };
 
-layout(set = 4, binding = 0, std430) restrict readonly buffer DrawData {
-	InstanceData data[];
-}
-instances;
-
 layout(push_constant, std430) uniform Params {
 	uint base_instance_index; // base index to instance data
 	uint pad1;
@@ -163,3 +158,8 @@ layout(set = 3, binding = 0) uniform texture2D color_texture;
 layout(set = 3, binding = 1) uniform texture2D normal_texture;
 layout(set = 3, binding = 2) uniform texture2D specular_texture;
 layout(set = 3, binding = 3) uniform sampler texture_sampler;
+
+layout(set = 3, binding = 4, std430) restrict readonly buffer DrawData {
+	InstanceData data[];
+}
+instances;

+ 28 - 69
servers/rendering/renderer_rd/storage_rd/texture_storage.cpp

@@ -40,25 +40,12 @@ using namespace RendererRD;
 ///////////////////////////////////////////////////////////////////////////
 // TextureStorage::CanvasTexture
 
-void TextureStorage::CanvasTexture::clear_sets() {
-	if (cleared_cache) {
-		return;
-	}
-	for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
-		for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
-			for (int k = 0; k < 2; k++) {
-				if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j][k])) {
-					RD::get_singleton()->free(uniform_sets[i][j][k]);
-					uniform_sets[i][j][k] = RID();
-				}
-			}
-		}
-	}
-	cleared_cache = true;
+void TextureStorage::CanvasTexture::clear_cache() {
+	info_cache[0] = CanvasTextureCache();
+	info_cache[1] = CanvasTextureCache();
 }
 
 TextureStorage::CanvasTexture::~CanvasTexture() {
-	clear_sets();
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -612,8 +599,7 @@ void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::Canvas
 			ct->specular = p_texture;
 		} break;
 	}
-
-	ct->clear_sets();
+	ct->clear_cache();
 }
 
 void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
@@ -624,7 +610,6 @@ void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture,
 	ct->specular_color.g = p_specular_color.g;
 	ct->specular_color.b = p_specular_color.b;
 	ct->specular_color.a = p_shininess;
-	ct->clear_sets();
 }
 
 void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
@@ -632,7 +617,6 @@ void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS:
 	ERR_FAIL_NULL(ct);
 
 	ct->texture_filter = p_filter;
-	ct->clear_sets();
 }
 
 void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
@@ -640,17 +624,14 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS:
 	ERR_FAIL_NULL(ct);
 
 	ct->texture_repeat = p_repeat;
-	ct->clear_sets();
 }
 
-bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular, bool p_texture_is_data) {
+TextureStorage::CanvasTextureInfo TextureStorage::canvas_texture_get_info(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, bool p_use_srgb, bool p_texture_is_data) {
 	MaterialStorage *material_storage = MaterialStorage::get_singleton();
 
 	CanvasTexture *ct = nullptr;
 	Texture *t = get_texture(p_texture);
 
-	// TODO once we have our texture storage split off we'll look into moving this code into canvas_texture
-
 	if (t) {
 		//regular texture
 		if (!t->canvas_texture) {
@@ -667,93 +648,71 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
 	}
 
 	if (!ct) {
-		return false; //invalid texture RID
+		return CanvasTextureInfo(); //invalid texture RID
 	}
 
 	RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter;
-	ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false);
+	ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasTextureInfo());
 
 	RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
-	ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
+	ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, CanvasTextureInfo());
 
-	RID uniform_set = ct->uniform_sets[filter][repeat][int(p_use_srgb)];
-	if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
-		//create and update
-		Vector<RD::Uniform> uniforms;
+	CanvasTextureCache &ctc = ct->info_cache[int(p_use_srgb)];
+	if (!RD::get_singleton()->texture_is_valid(ctc.diffuse) ||
+			!RD::get_singleton()->texture_is_valid(ctc.normal) ||
+			!RD::get_singleton()->texture_is_valid(ctc.specular)) {
 		{ //diffuse
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			u.binding = 0;
-
 			t = get_texture(ct->diffuse);
 			if (!t) {
-				u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+				ctc.diffuse = texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
 				ct->size_cache = Size2i(1, 1);
 			} else {
-				u.append_id(t->rd_texture_srgb.is_valid() && p_use_srgb && !p_texture_is_data ? t->rd_texture_srgb : t->rd_texture);
+				ctc.diffuse = t->rd_texture_srgb.is_valid() && p_use_srgb && !p_texture_is_data ? t->rd_texture_srgb : t->rd_texture;
 				ct->size_cache = Size2i(t->width_2d, t->height_2d);
 				if (t->render_target) {
 					t->render_target->was_used = true;
 				}
 			}
-			uniforms.push_back(u);
 		}
 		{ //normal
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			u.binding = 1;
-
 			t = get_texture(ct->normal_map);
 			if (!t) {
-				u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
+				ctc.normal = texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
 				ct->use_normal_cache = false;
 			} else {
-				u.append_id(t->rd_texture);
+				ctc.normal = t->rd_texture;
 				ct->use_normal_cache = true;
 				if (t->render_target) {
 					t->render_target->was_used = true;
 				}
 			}
-			uniforms.push_back(u);
 		}
 		{ //specular
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			u.binding = 2;
-
 			t = get_texture(ct->specular);
 			if (!t) {
-				u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+				ctc.specular = texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
 				ct->use_specular_cache = false;
 			} else {
-				u.append_id(t->rd_texture);
+				ctc.specular = t->rd_texture;
 				ct->use_specular_cache = true;
 				if (t->render_target) {
 					t->render_target->was_used = true;
 				}
 			}
-			uniforms.push_back(u);
 		}
-		{ //sampler
-			RD::Uniform u;
-			u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
-			u.binding = 3;
-			u.append_id(material_storage->sampler_rd_get_default(filter, repeat));
-			uniforms.push_back(u);
-		}
-
-		uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
-		ct->uniform_sets[filter][repeat][int(p_use_srgb)] = uniform_set;
-		ct->cleared_cache = false;
 	}
 
-	r_uniform_set = uniform_set;
-	r_size = ct->size_cache;
-	r_specular_shininess = ct->specular_color;
-	r_use_normal = ct->use_normal_cache;
-	r_use_specular = ct->use_specular_cache;
+	CanvasTextureInfo res;
+	res.diffuse = ctc.diffuse;
+	res.normal = ctc.normal;
+	res.specular = ctc.specular;
+	res.sampler = material_storage->sampler_rd_get_default(filter, repeat);
+	res.size = ct->size_cache;
+	res.specular_color = ct->specular_color;
+	res.use_normal = ct->use_normal_cache;
+	res.use_specular = ct->use_specular_cache;
 
-	return true;
+	return res;
 }
 
 /* Texture API */

+ 24 - 3
servers/rendering/renderer_rd/storage_rd/texture_storage.h

@@ -76,6 +76,21 @@ public:
 		TYPE_3D
 	};
 
+	struct CanvasTextureInfo {
+		RID diffuse;
+		RID normal;
+		RID specular;
+		RID sampler;
+		Size2i size;
+		Color specular_color;
+
+		bool use_normal = false;
+		bool use_specular = false;
+
+		_FORCE_INLINE_ bool is_valid() const { return diffuse.is_valid(); }
+		_FORCE_INLINE_ bool is_null() const { return diffuse.is_null(); }
+	};
+
 private:
 	friend class LightStorage;
 	friend class MaterialStorage;
@@ -86,6 +101,12 @@ private:
 
 	/* Canvas Texture API */
 
+	struct CanvasTextureCache {
+		RID diffuse = RID();
+		RID normal = RID();
+		RID specular = RID();
+	};
+
 	class CanvasTexture {
 	public:
 		RID diffuse;
@@ -96,14 +117,14 @@ private:
 
 		RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
 		RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
-		RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX][2];
+		CanvasTextureCache info_cache[2];
 
 		Size2i size_cache = Size2i(1, 1);
 		bool use_normal_cache = false;
 		bool use_specular_cache = false;
 		bool cleared_cache = true;
 
-		void clear_sets();
+		void clear_cache();
 		~CanvasTexture();
 	};
 
@@ -477,7 +498,7 @@ public:
 	virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
 	virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
 
-	bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular, bool p_texture_is_data);
+	CanvasTextureInfo canvas_texture_get_info(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, bool p_use_srgb, bool p_texture_is_data);
 
 	/* Texture API */