From a2f3decb8852d079d575dc017a79c7f5fbc0a5d5 Mon Sep 17 00:00:00 2001 From: Tom Coxon Date: Mon, 6 Sep 2021 13:32:59 +0100 Subject: [PATCH] Prevent shaders from generating code before the constructor finishes. Fixes #43733: "creating SpatialMaterial in a separate thread creates invalid shaders (temporarily)." The bug occurred because various setters called in materials' constructors add materials to queues that are processed on the main thread. This means that when the materials are created in another thread, they can be processed on the main thread before the constructor has finished. The fix adds a flag to affected materials that prevents them from being added to the queue until their constructors have finished initialising all the members. (cherry picked from commit 9e9bac1549cb293850feac145622267153f9c7aa) --- scene/2d/canvas_item.cpp | 3 ++- scene/2d/canvas_item.h | 1 + scene/resources/material.cpp | 3 ++- scene/resources/material.h | 1 + scene/resources/particles_material.cpp | 3 ++- scene/resources/particles_material.h | 1 + 6 files changed, 9 insertions(+), 3 deletions(-) diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 6d8b1508f26..ab5e3580cb5 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -162,7 +162,7 @@ void CanvasItemMaterial::_queue_shader_change() { material_mutex.lock(); - if (!element.in_list()) { + if (is_initialized && !element.in_list()) { dirty_materials->add(&element); } @@ -313,6 +313,7 @@ CanvasItemMaterial::CanvasItemMaterial() : current_key.key = 0; current_key.invalid_key = 1; + is_initialized = true; _queue_shader_change(); } diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 6ecd0b31a12..28fa1b4564f 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -116,6 +116,7 @@ private: _FORCE_INLINE_ void _queue_shader_change(); _FORCE_INLINE_ bool _is_shader_dirty() const; + bool is_initialized = false; BlendMode blend_mode; LightMode light_mode; bool particles_animation; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 079c3bc32db..3f7362b012d 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -1071,7 +1071,7 @@ void SpatialMaterial::_queue_shader_change() { material_mutex.lock(); - if (!element.in_list()) { + if (is_initialized && !element.in_list()) { dirty_materials->add(&element); } @@ -2409,6 +2409,7 @@ SpatialMaterial::SpatialMaterial() : current_key.key = 0; current_key.invalid_key = 1; + is_initialized = true; _queue_shader_change(); } diff --git a/scene/resources/material.h b/scene/resources/material.h index cba64cc24f8..5644590629d 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -371,6 +371,7 @@ private: _FORCE_INLINE_ void _queue_shader_change(); _FORCE_INLINE_ bool _is_shader_dirty() const; + bool is_initialized = false; Color albedo; float specular; float metallic; diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 18260d6c39d..1ff8975e062 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -621,7 +621,7 @@ void ParticlesMaterial::_queue_shader_change() { material_mutex.lock(); - if (!element.in_list()) { + if (is_initialized && !element.in_list()) { dirty_materials->add(&element); } @@ -1282,6 +1282,7 @@ ParticlesMaterial::ParticlesMaterial() : current_key.key = 0; current_key.invalid_key = 1; + is_initialized = true; _queue_shader_change(); } diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index 8ea6db9f093..afc30903904 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -198,6 +198,7 @@ private: _FORCE_INLINE_ void _queue_shader_change(); _FORCE_INLINE_ bool _is_shader_dirty() const; + bool is_initialized = false; Vector3 direction; float spread; float flatness;