From 9ca190c96a242da66ec1844e1c92d2859901b2ae Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Fri, 3 Apr 2020 18:40:05 +0200 Subject: [PATCH] gfx-shader: Don't use modified_properties to reload shaders As OBS Studio locks some mutexes in a different order depending on what actions are being done, using modified_properties for GPU work causes things to freeze in place. Instead have users manually click the refresh button when they changed files in order to prevent this freeze from happening. Fixes: #118 --- data/locale/en-US.ini | 1 + source/gfx/shader/gfx-shader.cpp | 58 ++++++++++++++++++++++++++++---- source/gfx/shader/gfx-shader.hpp | 6 ++-- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index fe7eda4..4aba25a 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -63,6 +63,7 @@ MipGenerator.Intensity.Description="Intensity of the generator." # Shader Shader="Shader" +Shader.Refresh="Refresh Options and Parameters" Shader.Shader="Shader Options" Shader.Shader.File="File" Shader.Shader.Technique="Technique" diff --git a/source/gfx/shader/gfx-shader.cpp b/source/gfx/shader/gfx-shader.cpp index a8f6a39..4e0fd84 100644 --- a/source/gfx/shader/gfx-shader.cpp +++ b/source/gfx/shader/gfx-shader.cpp @@ -23,6 +23,7 @@ #include "plugin.hpp" #define ST "Shader" +#define ST_REFRESH ST ".Refresh" #define ST_SHADER ST ".Shader" #define ST_SHADER_FILE ST_SHADER ".File" #define ST_SHADER_TECHNIQUE ST_SHADER ".Technique" @@ -183,6 +184,15 @@ void gfx::shader::shader::properties(obs_properties_t* pr) { _have_current_params = false; + { + auto p = obs_properties_add_button2( + pr, ST_REFRESH, D_TRANSLATE(ST_REFRESH), + [](obs_properties_t* props, obs_property_t* prop, void* priv) { + return reinterpret_cast(priv)->on_refresh_properties(props, prop); + }, + this); + } + { auto grp = obs_properties_create(); obs_properties_add_group(pr, ST_SHADER, D_TRANSLATE(ST_SHADER), OBS_GROUP_NORMAL, grp); @@ -191,24 +201,25 @@ void gfx::shader::shader::properties(obs_properties_t* pr) auto p = obs_properties_add_path(grp, ST_SHADER_FILE, D_TRANSLATE(ST_SHADER_FILE), OBS_PATH_FILE, "*.*", nullptr); obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SHADER_FILE))); - obs_property_set_modified_callback2( + /*obs_property_set_modified_callback2( p, [](void* priv, obs_properties_t* props, obs_property_t* prop, obs_data_t* data) noexcept { - return reinterpret_cast(priv)->on_properties_modified(props, prop, data); + return reinterpret_cast(priv)->on_shader_or_technique_modified(props, prop, data); }, - this); + this);*/ } { auto p = obs_properties_add_list(grp, ST_SHADER_TECHNIQUE, D_TRANSLATE(ST_SHADER_TECHNIQUE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SHADER_TECHNIQUE))); - obs_property_set_modified_callback2( + /*obs_property_set_modified_callback2( p, [](void* priv, obs_properties_t* props, obs_property_t* prop, obs_data_t* data) noexcept { - return reinterpret_cast(priv)->on_properties_modified(props, prop, data); + return reinterpret_cast(priv)->on_shader_or_technique_modified(props, prop, data); }, - this); + this);*/ } + if (_mode != shader_mode::Transition) { auto grp2 = obs_properties_create(); obs_properties_add_group(grp, ST_SHADER_SIZE, D_TRANSLATE(ST_SHADER_SIZE), OBS_GROUP_NORMAL, grp2); @@ -229,9 +240,42 @@ void gfx::shader::shader::properties(obs_properties_t* pr) auto grp = obs_properties_create(); obs_properties_add_group(pr, ST_PARAMETERS, D_TRANSLATE(ST_PARAMETERS), OBS_GROUP_NORMAL, grp); } + + // Manually call the refresh. + on_refresh_properties(pr, nullptr); } -bool gfx::shader::shader::on_properties_modified(obs_properties_t* props, obs_property_t* prop, obs_data_t* data) +bool gfx::shader::shader::on_refresh_properties(obs_properties_t* props, obs_property_t* prop) +{ + if (_shader) { // Clear list of techniques and rebuild it. + obs_property_t* p_tech_list = obs_properties_get(props, ST_SHADER_TECHNIQUE); + obs_property_list_clear(p_tech_list); + for (size_t idx = 0; idx < _shader.count_techniques(); idx++) { + auto tech = _shader.get_technique(idx); + obs_property_list_add_string(p_tech_list, tech.name().c_str(), tech.name().c_str()); + } + } + { // Clear parameter options. + auto grp = obs_property_group_content(obs_properties_get(props, ST_PARAMETERS)); + for (auto p = obs_properties_first(grp); p != nullptr; p = obs_properties_first(grp)) { + obs::tools::obs_properties_remove_by_name(grp, obs_property_name(p)); + } + + // Rebuild new parameters. + obs_data_t* data = obs_source_get_settings(_self); + for (auto kv : _shader_params) { + kv.second->properties(grp, data); + kv.second->defaults(data); + kv.second->update(data); + } + obs_source_update(_self, data); + } + + return true; +} + +bool gfx::shader::shader::on_shader_or_technique_modified(obs_properties_t* props, obs_property_t* prop, + obs_data_t* data) { bool shader_dirty = false; bool param_dirty = false; diff --git a/source/gfx/shader/gfx-shader.hpp b/source/gfx/shader/gfx-shader.hpp index 078758a..0fdf98c 100644 --- a/source/gfx/shader/gfx-shader.hpp +++ b/source/gfx/shader/gfx-shader.hpp @@ -65,7 +65,7 @@ namespace gfx { // Cache float_t _time; float_t _time_loop; - int32_t _loops; + int32_t _loops; std::mt19937_64 _random; bool _have_current_params; @@ -84,7 +84,9 @@ namespace gfx { void properties(obs_properties_t* props); - bool on_properties_modified(obs_properties_t* props, obs_property_t* prop, obs_data_t* data); + bool on_refresh_properties(obs_properties_t* props, obs_property_t* prop); + + bool on_shader_or_technique_modified(obs_properties_t* props, obs_property_t* prop, obs_data_t* data); bool update_shader(obs_data_t* data, bool& shader_dirty, bool& param_dirty);