Fix material_set_shader race condition.

This commit is contained in:
Skyth
2026-04-29 17:31:24 +03:00
parent 320e818469
commit f379b84004
2 changed files with 33 additions and 11 deletions
@@ -2162,6 +2162,7 @@ RID MaterialStorage::shader_allocate() {
void MaterialStorage::shader_initialize(RID p_rid, bool p_embedded) {
Shader shader;
shader.mutex = memnew(Mutex);
shader.data = nullptr;
shader.type = SHADER_TYPE_MAX;
shader.embedded = p_embedded;
@@ -2179,14 +2180,18 @@ void MaterialStorage::shader_free(RID p_rid) {
Shader *shader = shader_owner.get_or_null(p_rid);
ERR_FAIL_NULL(shader);
//make material unreference this
while (shader->owners.size()) {
material_set_shader((*shader->owners.begin())->self, RID());
}
{
MutexLock lock(*shader->mutex);
//clear data if exists
if (shader->data) {
memdelete(shader->data);
//make material unreference this
while (shader->owners.size()) {
material_set_shader((*shader->owners.begin())->self, RID());
}
//clear data if exists
if (shader->data) {
memdelete(shader->data);
}
}
if (shader->embedded) {
@@ -2195,6 +2200,8 @@ void MaterialStorage::shader_free(RID p_rid) {
embedded_set.erase(p_rid);
}
memdelete(shader->mutex);
shader_owner.free(p_rid);
}
@@ -2202,6 +2209,8 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_NULL(shader);
MutexLock lock(*shader->mutex);
shader->code = p_code;
String mode_string = ShaderLanguage::get_shader_type(p_code);
@@ -2322,9 +2331,14 @@ void MaterialStorage::shader_set_default_texture_parameter(RID p_shader, const S
if (shader->data) {
shader->data->set_default_texture_parameter(p_name, p_texture, p_index);
}
for (Material *E : shader->owners) {
Material *material = E;
_material_queue_update(material, false, true);
{
MutexLock lock(*shader->mutex);
for (Material *E : shader->owners) {
Material *material = E;
_material_queue_update(material, false, true);
}
}
}
@@ -2474,7 +2488,11 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
}
if (material->shader) {
material->shader->owners.erase(material);
{
MutexLock lock(*material->shader->mutex);
material->shader->owners.erase(material);
}
material->shader = nullptr;
material->shader_type = SHADER_TYPE_MAX;
}
@@ -2487,6 +2505,9 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
Shader *shader = get_shader(p_shader);
ERR_FAIL_NULL(shader);
MutexLock lock(*shader->mutex);
material->shader = shader;
material->shader_type = shader->type;
material->shader_id = p_shader.get_local_index();
@@ -265,6 +265,7 @@ private:
struct Material;
struct Shader {
Mutex *mutex = nullptr;
ShaderData *data = nullptr;
String code;
String path_hint;