gfx-shader: Add support for validating file differences

Removes the stutter when re-opening the properties dialog which was caused by recompiling the same exact shader every time this happened. Also paves the way for simple file watching.
This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2019-12-21 18:23:26 +01:00
parent 2faa68f9be
commit 9ef60cc2f9
2 changed files with 64 additions and 17 deletions

View file

@ -31,21 +31,40 @@
#define ST_PARAMETERS ST ".Parameters"
gfx::shader::shader::shader(obs_source_t* self, shader_mode mode)
: _self(self), _mode(mode), _shader(), _shader_file(), _time()
: _self(self), _mode(mode), _base_width(1), _base_height(1), _input_a(), _input_b(),
_shader(), _shader_file(), _shader_tech("Draw"), _shader_file_mt(), _shader_file_sz(), _shader_file_tick(0),
_shader_params_invalid(true),
_width_type(size_type::Percent), _width_value(1.0), _height_type(size_type::Percent), _height_value(1.0),
_time(0), _random()
{
_random.seed(static_cast<unsigned long long>(time(NULL)));
}
gfx::shader::shader::~shader() {}
void gfx::shader::shader::load_shader(std::filesystem::path file)
bool gfx::shader::shader::load_shader(std::filesystem::path file)
{
_shader = gs::effect(file);
_shader_file = file;
if (!is_shader_different(file))
return false;
_shader = gs::effect(file);
_shader_file = file;
_shader_file_mt = std::filesystem::last_write_time(file);
_shader_file_sz = std::filesystem::file_size(file);
_shader_file_tick = 0;
_shader_params_invalid = true;
return true;
}
void gfx::shader::shader::load_shader_params()
{
if (!_shader_params_invalid)
return;
_shader_params.clear();
if (!_shader)
@ -82,6 +101,8 @@ void gfx::shader::shader::load_shader_params()
}
}
}
_shader_params_invalid = false;
}
void gfx::shader::shader::properties(obs_properties_t* pr)
@ -134,6 +155,25 @@ void gfx::shader::shader::properties(obs_properties_t* pr)
}
}
bool gfx::shader::shader::is_shader_different(std::filesystem::path file)
{
// Check if the file name differs.
if (file != _shader_file)
return true;
// Is the file write time different?
if (std::filesystem::last_write_time(_shader_file) != _shader_file_mt) {
return true;
}
// Is the file size different?
if (std::filesystem::file_size(_shader_file) != _shader_file_sz) {
return true;
}
return false;
}
bool gfx::shader::shader::on_shader_changed(obs_properties_t* props, obs_property_t* prop, obs_data_t* data)
{
// Load changed shader.
@ -206,7 +246,8 @@ void gfx::shader::shader::update_shader(obs_data_t* data)
std::string file = file_c ? file_c : "";
if (file != "") {
try {
load_shader(file);
if (!load_shader(file))
return;
} catch (const std::exception& ex) {
P_LOG_ERROR("Failed to load shader: %s.", ex.what());
_shader.reset();
@ -222,9 +263,12 @@ void gfx::shader::shader::update_shader(obs_data_t* data)
void gfx::shader::shader::update_technique(obs_data_t* data)
{
{
const char* shader_tech_c = obs_data_get_string(data, ST_SHADER_TECHNIQUE);
_shader_tech = shader_tech_c ? shader_tech_c : "";
const char* shader_tech_c = obs_data_get_string(data, ST_SHADER_TECHNIQUE);
std::string shader_tech = shader_tech_c ? shader_tech_c : "";
if ((_shader_params_invalid) || (_shader_tech != shader_tech)) {
_shader_tech = shader_tech;
_shader_params_invalid = true;
load_shader_params();
}
}

View file

@ -61,11 +61,13 @@ namespace gfx {
std::shared_ptr<gs::texture> _input_b;
// Shader
gs::effect _shader;
std::filesystem::path _shader_file;
std::string _shader_tech;
// Shader Params
gs::effect _shader;
std::filesystem::path _shader_file;
std::string _shader_tech;
std::filesystem::file_time_type _shader_file_mt;
uintmax_t _shader_file_sz;
float_t _shader_file_tick;
bool _shader_params_invalid;
std::map<std::string, std::shared_ptr<parameter>> _shader_params;
// Options
@ -75,20 +77,21 @@ namespace gfx {
double_t _height_value;
// Cache
float_t _time;
std::mt19937_64 _random;
std::list<std::string> _string_cache;
float_t _time;
std::mt19937_64 _random;
public:
shader(obs_source_t* self, shader_mode mode);
~shader();
void load_shader(std::filesystem::path file);
bool load_shader(std::filesystem::path file);
void load_shader_params();
void properties(obs_properties_t* props);
bool is_shader_different(std::filesystem::path file);
bool on_shader_changed(obs_properties_t* props, obs_property_t* prop, obs_data_t* data);
bool on_technique_changed(obs_properties_t* props, obs_property_t* prop, obs_data_t* data);