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.
This commit is contained in:
Tom Coxon 2021-09-06 13:32:59 +01:00 committed by Tom Coxon
parent f09ea4f0c8
commit 9e9bac1549
6 changed files with 9 additions and 3 deletions

View File

@ -176,7 +176,7 @@ void CanvasItemMaterial::flush_changes() {
void CanvasItemMaterial::_queue_shader_change() { void CanvasItemMaterial::_queue_shader_change() {
material_mutex.lock(); material_mutex.lock();
if (!element.in_list()) { if (is_initialized && !element.in_list()) {
dirty_materials->add(&element); dirty_materials->add(&element);
} }
@ -313,6 +313,7 @@ CanvasItemMaterial::CanvasItemMaterial() :
current_key.key = 0; current_key.key = 0;
current_key.invalid_key = 1; current_key.invalid_key = 1;
is_initialized = true;
_queue_shader_change(); _queue_shader_change();
} }

View File

@ -113,6 +113,7 @@ private:
_FORCE_INLINE_ void _queue_shader_change(); _FORCE_INLINE_ void _queue_shader_change();
_FORCE_INLINE_ bool _is_shader_dirty() const; _FORCE_INLINE_ bool _is_shader_dirty() const;
bool is_initialized = false;
BlendMode blend_mode; BlendMode blend_mode;
LightMode light_mode; LightMode light_mode;
bool particles_animation; bool particles_animation;

View File

@ -1073,7 +1073,7 @@ void SpatialMaterial::flush_changes() {
void SpatialMaterial::_queue_shader_change() { void SpatialMaterial::_queue_shader_change() {
material_mutex.lock(); material_mutex.lock();
if (!element.in_list()) { if (is_initialized && !element.in_list()) {
dirty_materials->add(&element); dirty_materials->add(&element);
} }
@ -2317,6 +2317,7 @@ SpatialMaterial::SpatialMaterial() :
current_key.key = 0; current_key.key = 0;
current_key.invalid_key = 1; current_key.invalid_key = 1;
is_initialized = true;
_queue_shader_change(); _queue_shader_change();
} }

View File

@ -366,6 +366,7 @@ private:
_FORCE_INLINE_ void _queue_shader_change(); _FORCE_INLINE_ void _queue_shader_change();
_FORCE_INLINE_ bool _is_shader_dirty() const; _FORCE_INLINE_ bool _is_shader_dirty() const;
bool is_initialized = false;
Color albedo; Color albedo;
float specular; float specular;
float metallic; float metallic;

View File

@ -690,7 +690,7 @@ void ParticlesMaterial::flush_changes() {
void ParticlesMaterial::_queue_shader_change() { void ParticlesMaterial::_queue_shader_change() {
material_mutex.lock(); material_mutex.lock();
if (!element.in_list()) { if (is_initialized && !element.in_list()) {
dirty_materials->add(&element); dirty_materials->add(&element);
} }
@ -1367,6 +1367,7 @@ ParticlesMaterial::ParticlesMaterial() :
current_key.key = 0; current_key.key = 0;
current_key.invalid_key = 1; current_key.invalid_key = 1;
is_initialized = true;
_queue_shader_change(); _queue_shader_change();
} }

View File

@ -203,6 +203,7 @@ private:
_FORCE_INLINE_ void _queue_shader_change(); _FORCE_INLINE_ void _queue_shader_change();
_FORCE_INLINE_ bool _is_shader_dirty() const; _FORCE_INLINE_ bool _is_shader_dirty() const;
bool is_initialized = false;
Vector3 direction; Vector3 direction;
float spread; float spread;
float flatness; float flatness;