From 34a19f07a44ea6cf5a092825e29b1246cede7069 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 26 Nov 2024 13:32:40 -0300 Subject: [PATCH] Restore dirty list for BaseMaterial3D but don't use it on resource loader. --- scene/register_scene_types.cpp | 1 + scene/resources/material.cpp | 88 ++++++++++++++++++++-------------- scene/resources/material.h | 8 +++- 3 files changed, 59 insertions(+), 38 deletions(-) diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index ff739bbead2..bac541350cc 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -890,6 +890,7 @@ void register_scene_types() { GDREGISTER_CLASS(ProceduralSkyMaterial); GDREGISTER_CLASS(PanoramaSkyMaterial); GDREGISTER_CLASS(PhysicalSkyMaterial); + SceneTree::add_idle_callback(BaseMaterial3D::flush_changes); BaseMaterial3D::init_shaders(); GDREGISTER_CLASS(MeshLibrary); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index ecc1982aa5e..109449d4325 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -99,9 +99,13 @@ void Material::_mark_initialized(const Callable &p_add_to_dirty_list, const Call if (ResourceLoader::is_within_load()) { DEV_ASSERT(init_state != INIT_STATE_READY); if (init_state == INIT_STATE_UNINITIALIZED) { // Prevent queueing twice. - init_state = INIT_STATE_INITIALIZING; - callable_mp(this, &Material::_mark_ready).call_deferred(); - p_update_shader.call_deferred(); + if (p_update_shader.is_valid()) { + init_state = INIT_STATE_INITIALIZING; + callable_mp(this, &Material::_mark_ready).call_deferred(); + p_update_shader.call_deferred(); + } else { + init_state = INIT_STATE_READY; + } } } else { // Straightforward conditions. @@ -578,6 +582,8 @@ ShaderMaterial::~ShaderMaterial() { HashMap BaseMaterial3D::shader_map; Mutex BaseMaterial3D::shader_map_mutex; BaseMaterial3D::ShaderNames *BaseMaterial3D::shader_names = nullptr; +Mutex BaseMaterial3D::material_mutex; +SelfList::List BaseMaterial3D::dirty_materials; void BaseMaterial3D::init_shaders() { shader_names = memnew(ShaderNames); @@ -666,21 +672,13 @@ HashMap> BaseMaterial3D::materials_for_2d; void BaseMaterial3D::finish_shaders() { materials_for_2d.clear(); + dirty_materials.clear(); + memdelete(shader_names); shader_names = nullptr; } -void BaseMaterial3D::_mark_dirty() { - dirty = true; -} - void BaseMaterial3D::_update_shader() { - if (!dirty) { - return; - } - - dirty = false; - MaterialKey mk = _compute_key(); if (mk == current_key) { return; //no update required in the end @@ -1962,6 +1960,23 @@ void BaseMaterial3D::_check_material_rid() { } } +void BaseMaterial3D::flush_changes() { + MutexLock lock(material_mutex); + + while (dirty_materials.first()) { + dirty_materials.first()->self()->_update_shader(); + dirty_materials.first()->remove_from_list(); + } +} + +void BaseMaterial3D::_queue_shader_change() { + MutexLock lock(material_mutex); + + if (_is_initialized() && !element.in_list()) { + dirty_materials.add(&element); + } +} + void BaseMaterial3D::_material_set_param(const StringName &p_name, const Variant &p_value) { if (_get_material().is_valid()) { RS::get_singleton()->material_set_param(_get_material(), p_name, p_value); @@ -2171,7 +2186,7 @@ void BaseMaterial3D::set_detail_uv(DetailUV p_detail_uv) { } detail_uv = p_detail_uv; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::DetailUV BaseMaterial3D::get_detail_uv() const { @@ -2184,7 +2199,7 @@ void BaseMaterial3D::set_blend_mode(BlendMode p_mode) { } blend_mode = p_mode; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::BlendMode BaseMaterial3D::get_blend_mode() const { @@ -2193,7 +2208,7 @@ BaseMaterial3D::BlendMode BaseMaterial3D::get_blend_mode() const { void BaseMaterial3D::set_detail_blend_mode(BlendMode p_mode) { detail_blend_mode = p_mode; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::BlendMode BaseMaterial3D::get_detail_blend_mode() const { @@ -2206,7 +2221,7 @@ void BaseMaterial3D::set_transparency(Transparency p_transparency) { } transparency = p_transparency; - _mark_dirty(); + _queue_shader_change(); notify_property_list_changed(); } @@ -2220,7 +2235,7 @@ void BaseMaterial3D::set_alpha_antialiasing(AlphaAntiAliasing p_alpha_aa) { } alpha_antialiasing_mode = p_alpha_aa; - _mark_dirty(); + _queue_shader_change(); notify_property_list_changed(); } @@ -2234,7 +2249,7 @@ void BaseMaterial3D::set_shading_mode(ShadingMode p_shading_mode) { } shading_mode = p_shading_mode; - _mark_dirty(); + _queue_shader_change(); notify_property_list_changed(); } @@ -2248,7 +2263,7 @@ void BaseMaterial3D::set_depth_draw_mode(DepthDrawMode p_mode) { } depth_draw_mode = p_mode; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::DepthDrawMode BaseMaterial3D::get_depth_draw_mode() const { @@ -2261,7 +2276,7 @@ void BaseMaterial3D::set_cull_mode(CullMode p_mode) { } cull_mode = p_mode; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::CullMode BaseMaterial3D::get_cull_mode() const { @@ -2274,7 +2289,7 @@ void BaseMaterial3D::set_diffuse_mode(DiffuseMode p_mode) { } diffuse_mode = p_mode; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::DiffuseMode BaseMaterial3D::get_diffuse_mode() const { @@ -2287,7 +2302,7 @@ void BaseMaterial3D::set_specular_mode(SpecularMode p_mode) { } specular_mode = p_mode; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::SpecularMode BaseMaterial3D::get_specular_mode() const { @@ -2317,7 +2332,7 @@ void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) { update_configuration_warning(); } - _mark_dirty(); + _queue_shader_change(); } bool BaseMaterial3D::get_flag(Flags p_flag) const { @@ -2333,7 +2348,7 @@ void BaseMaterial3D::set_feature(Feature p_feature, bool p_enabled) { features[p_feature] = p_enabled; notify_property_list_changed(); - _mark_dirty(); + _queue_shader_change(); } bool BaseMaterial3D::get_feature(Feature p_feature) const { @@ -2353,7 +2368,7 @@ void BaseMaterial3D::set_texture(TextureParam p_param, const Ref &p_t } notify_property_list_changed(); - _mark_dirty(); + _queue_shader_change(); } Ref BaseMaterial3D::get_texture(TextureParam p_param) const { @@ -2373,7 +2388,7 @@ Ref BaseMaterial3D::get_texture_by_name(const StringName &p_name) con void BaseMaterial3D::set_texture_filter(TextureFilter p_filter) { texture_filter = p_filter; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::TextureFilter BaseMaterial3D::get_texture_filter() const { @@ -2610,7 +2625,7 @@ float BaseMaterial3D::get_uv2_triplanar_blend_sharpness() const { void BaseMaterial3D::set_billboard_mode(BillboardMode p_mode) { billboard_mode = p_mode; - _mark_dirty(); + _queue_shader_change(); notify_property_list_changed(); } @@ -2647,7 +2662,7 @@ bool BaseMaterial3D::get_particles_anim_loop() const { void BaseMaterial3D::set_heightmap_deep_parallax(bool p_enable) { deep_parallax = p_enable; - _mark_dirty(); + _queue_shader_change(); notify_property_list_changed(); } @@ -2693,7 +2708,7 @@ bool BaseMaterial3D::get_heightmap_deep_parallax_flip_binormal() const { void BaseMaterial3D::set_grow_enabled(bool p_enable) { grow_enabled = p_enable; - _mark_dirty(); + _queue_shader_change(); notify_property_list_changed(); } @@ -2762,7 +2777,7 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_metallic_texture_channel() co void BaseMaterial3D::set_roughness_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); roughness_texture_channel = p_channel; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::TextureChannel BaseMaterial3D::get_roughness_texture_channel() const { @@ -2844,7 +2859,7 @@ void BaseMaterial3D::set_on_top_of_alpha() { void BaseMaterial3D::set_proximity_fade_enabled(bool p_enable) { proximity_fade_enabled = p_enable; - _mark_dirty(); + _queue_shader_change(); notify_property_list_changed(); } @@ -2881,7 +2896,7 @@ float BaseMaterial3D::get_msdf_outline_size() const { void BaseMaterial3D::set_distance_fade(DistanceFadeMode p_mode) { distance_fade = p_mode; - _mark_dirty(); + _queue_shader_change(); notify_property_list_changed(); } @@ -2912,7 +2927,7 @@ void BaseMaterial3D::set_emission_operator(EmissionOperator p_op) { return; } emission_op = p_op; - _mark_dirty(); + _queue_shader_change(); } BaseMaterial3D::EmissionOperator BaseMaterial3D::get_emission_operator() const { @@ -3443,7 +3458,8 @@ void BaseMaterial3D::_bind_methods() { BIND_ENUM_CONSTANT(DISTANCE_FADE_OBJECT_DITHER); } -BaseMaterial3D::BaseMaterial3D(bool p_orm) { +BaseMaterial3D::BaseMaterial3D(bool p_orm) : + element(this) { orm = p_orm; // Initialize to the same values as the shader set_albedo(Color(1.0, 1.0, 1.0, 1.0)); @@ -3510,7 +3526,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) { current_key.invalid_key = 1; - _mark_dirty(); + _mark_initialized(callable_mp(this, &BaseMaterial3D::_queue_shader_change), Callable()); } BaseMaterial3D::~BaseMaterial3D() { diff --git a/scene/resources/material.h b/scene/resources/material.h index edd82b779e1..36d325bd33f 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -467,15 +467,18 @@ private: StringName albedo_texture_size; }; + static Mutex material_mutex; + static SelfList::List dirty_materials; static ShaderNames *shader_names; - void _mark_dirty(); + SelfList element; + void _update_shader(); + _FORCE_INLINE_ void _queue_shader_change(); void _check_material_rid(); void _material_set_param(const StringName &p_name, const Variant &p_value); bool orm; - bool dirty = true; RID shader_rid; HashMap pending_params; @@ -780,6 +783,7 @@ public: static void init_shaders(); static void finish_shaders(); + static void flush_changes(); static Ref get_material_for_2d(bool p_shaded, Transparency p_transparency, bool p_double_sided, bool p_billboard = false, bool p_billboard_y = false, bool p_msdf = false, bool p_no_depth = false, bool p_fixed_size = false, TextureFilter p_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, AlphaAntiAliasing p_alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF, RID *r_shader_rid = nullptr);