From 6ecedd1e6ca7d8b10b13a3dab19074fd51b17bcf Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 29 Jul 2019 15:29:43 -0300 Subject: [PATCH] Add a system to properly update materials if the uniform set is gone (likely deleted texture) --- .../rasterizer_rd/rasterizer_canvas_rd.cpp | 27 ++++++++++++++----- .../rasterizer_rd/rasterizer_canvas_rd.h | 3 ++- .../visual/rasterizer_rd/rasterizer_rd.cpp | 3 +++ servers/visual/rasterizer_rd/rasterizer_rd.h | 4 +++ .../rasterizer_rd/rasterizer_storage_rd.cpp | 10 +++++++ .../rasterizer_rd/rasterizer_storage_rd.h | 1 + 6 files changed, 40 insertions(+), 8 deletions(-) diff --git a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp index 9dd8f7ce50..44a8af236e 100644 --- a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp +++ b/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; } diff --git a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h index edb8007f5c..e8da79755b 100644 --- a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h +++ b/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; diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_rd.cpp index 8a77d9a71e..682f87e519 100644 --- a/servers/visual/rasterizer_rd/rasterizer_rd.cpp +++ b/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); diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.h b/servers/visual/rasterizer_rd/rasterizer_rd.h index f5ee7ddc76..b9151260c9 100644 --- a/servers/visual/rasterizer_rd/rasterizer_rd.h +++ b/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; } diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp index fef3418d53..07cc6d6989 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp @@ -1631,6 +1631,16 @@ void RasterizerStorageRD::MaterialData::update_textures(const Mapshader_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) { diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h index c05d9a41f6..13d3dcaf43 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h +++ b/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);