Browse Source

Add a system to properly update materials if the uniform set is gone (likely deleted texture)

Juan Linietsky 6 years ago
parent
commit
6ecedd1e6c

+ 20 - 7
servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp

@@ -1,6 +1,7 @@
 #include "rasterizer_canvas_rd.h"
 #include "core/math/math_funcs.h"
 #include "core/project_settings.h"
+#include "rasterizer_rd.h"
 
 void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
 
@@ -1500,14 +1501,25 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
 
 		if (ci->material.is_valid()) {
 			MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
-			if (md && md->shader_data->valid && md->shader_data->uses_screen_texture) {
-				if (!material_screen_texture_found) {
-					backbuffer_copy = true;
-					back_buffer_rect = Rect2();
+			if (md && md->shader_data->valid) {
+
+				if (md->shader_data->uses_screen_texture) {
+					if (!material_screen_texture_found) {
+						backbuffer_copy = true;
+						back_buffer_rect = Rect2();
+					}
+					if (screen_uniform_set.is_null()) {
+						RID backbuffer_shader = shader.canvas_shader.version_get_shader(md->shader_data->version, 0); //any version is fine
+						screen_uniform_set = storage->render_target_get_back_buffer_uniform_set(p_to_render_target, backbuffer_shader);
+					}
 				}
-				if (screen_uniform_set.is_null()) {
-					RID backbuffer_shader = shader.canvas_shader.version_get_shader(md->shader_data->version, 0); //any version is fine
-					screen_uniform_set = storage->render_target_get_back_buffer_uniform_set(p_to_render_target, backbuffer_shader);
+
+				if (md->last_frame != RasterizerRD::get_frame_number()) {
+					md->last_frame = RasterizerRD::get_frame_number();
+					if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) {
+						//textures may have been removed, hence invalidating this uniform set.
+						storage->material_force_update_textures(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
+					}
 				}
 			}
 		}
@@ -2149,6 +2161,7 @@ RasterizerCanvasRD::MaterialData::~MaterialData() {
 RasterizerStorageRD::MaterialData *RasterizerCanvasRD::_create_material_func(ShaderData *p_shader) {
 	MaterialData *material_data = memnew(MaterialData);
 	material_data->shader_data = p_shader;
+	material_data->last_frame = false;
 	//update will happen later anyway so do nothing.
 	return material_data;
 }

+ 2 - 1
servers/visual/rasterizer_rd/rasterizer_canvas_rd.h

@@ -4,10 +4,10 @@
 #include "servers/visual/rasterizer.h"
 #include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
 #include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
-#include "servers/visual/rendering_device.h"
 #include "servers/visual/rasterizer_rd/shader_compiler_rd.h"
 #include "servers/visual/rasterizer_rd/shaders/canvas.glsl.gen.h"
 #include "servers/visual/rasterizer_rd/shaders/canvas_occlusion.glsl.gen.h"
+#include "servers/visual/rendering_device.h"
 
 class RasterizerCanvasRD : public RasterizerCanvas {
 
@@ -167,6 +167,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
 	}
 
 	struct MaterialData : public RasterizerStorageRD::MaterialData {
+		uint64_t last_frame;
 		ShaderData *shader_data;
 		RID uniform_buffer;
 		RID uniform_set;

+ 3 - 0
servers/visual/rasterizer_rd/rasterizer_rd.cpp

@@ -46,6 +46,7 @@ void RasterizerRD::blit_render_targets_to_screen(int p_screen, const BlitToScree
 }
 
 void RasterizerRD::begin_frame(double frame_step) {
+	frame++;
 	time += frame_step;
 	canvas->set_time(time);
 }
@@ -121,6 +122,7 @@ void RasterizerRD::initialize() {
 }
 
 ThreadWorkPool RasterizerRD::thread_work_pool;
+uint32_t RasterizerRD::frame = 1;
 
 void RasterizerRD::finalize() {
 
@@ -139,6 +141,7 @@ void RasterizerRD::finalize() {
 RasterizerRD::RasterizerRD() {
 	thread_work_pool.init();
 	time = 0;
+
 	storage = memnew(RasterizerStorageRD);
 	canvas = memnew(RasterizerCanvasRD(storage));
 	scene = memnew(RasterizerSceneForwardRD);

+ 4 - 0
servers/visual/rasterizer_rd/rasterizer_rd.h

@@ -24,6 +24,8 @@ protected:
 
 	double time;
 
+	static uint32_t frame;
+
 public:
 	RasterizerStorage *get_storage() { return storage; }
 	RasterizerCanvas *get_canvas() { return canvas; }
@@ -39,6 +41,8 @@ public:
 	void end_frame(bool p_swap_buffers);
 	void finalize();
 
+	static _ALWAYS_INLINE_ uint64_t get_frame_number() { return frame; }
+
 	static Error is_viable() {
 		return OK;
 	}

+ 10 - 0
servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp

@@ -1631,6 +1631,16 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va
 	}
 }
 
+void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) {
+	Material *material = material_owner.getornull(p_material);
+	if (material->shader_type != p_shader_type) {
+		return;
+	}
+	if (material->data) {
+		material->data->update_parameters(material->params, false, true);
+	}
+}
+
 void RasterizerStorageRD::_update_queued_materials() {
 	Material *material = material_update_list;
 	while (material) {

+ 1 - 0
servers/visual/rasterizer_rd/rasterizer_storage_rd.h

@@ -329,6 +329,7 @@ public:
 	bool material_casts_shadows(RID p_material);
 
 	void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance);
+	void material_force_update_textures(RID p_material, ShaderType p_shader_type);
 
 	void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);