Fix material_set_shader race condition.
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user