mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-11 06:15:05 +00:00
gfx/shader/texture: Improve load/acquire behavior
Prevents massive stalls from happening unexpectedly due to repeatedly loading the same thing over and over.
This commit is contained in:
parent
7994d03166
commit
ba05258547
2 changed files with 75 additions and 49 deletions
|
@ -70,7 +70,10 @@ streamfx::gfx::shader::texture_field_type streamfx::gfx::shader::get_texture_fie
|
||||||
streamfx::gfx::shader::texture_parameter::texture_parameter(streamfx::gfx::shader::shader* parent,
|
streamfx::gfx::shader::texture_parameter::texture_parameter(streamfx::gfx::shader::shader* parent,
|
||||||
streamfx::obs::gs::effect_parameter param,
|
streamfx::obs::gs::effect_parameter param,
|
||||||
std::string prefix)
|
std::string prefix)
|
||||||
: parameter(parent, param, prefix)
|
: parameter(parent, param, prefix), _field_type(texture_field_type::Input), _keys(), _values(),
|
||||||
|
_type(texture_type::File), _active(false), _visible(false), _dirty(true),
|
||||||
|
_dirty_ts(std::chrono::high_resolution_clock::now()), _file_path(), _file_texture(), _source_name(), _source(),
|
||||||
|
_source_child(), _source_active(), _source_visible(), _source_rendertarget()
|
||||||
{
|
{
|
||||||
char string_buffer[256];
|
char string_buffer[256];
|
||||||
|
|
||||||
|
@ -138,6 +141,10 @@ streamfx::gfx::shader::texture_parameter::texture_parameter(streamfx::gfx::shade
|
||||||
_keys[1] = get_key();
|
_keys[1] = get_key();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (field_type() == texture_field_type::Input) {
|
||||||
|
// Special code for Input-only fields.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
streamfx::gfx::shader::texture_parameter::~texture_parameter() {}
|
streamfx::gfx::shader::texture_parameter::~texture_parameter() {}
|
||||||
|
@ -237,37 +244,60 @@ void streamfx::gfx::shader::texture_parameter::update(obs_data_t* settings)
|
||||||
if (is_automatic())
|
if (is_automatic())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
if (field_type() == texture_field_type::Input) {
|
||||||
if (field_type() == texture_field_type::Enum) {
|
_type = static_cast<texture_type>(obs_data_get_int(settings, _keys[0].c_str()));
|
||||||
std::filesystem::path file_path = obs_data_get_string(settings, get_key().data());
|
} else {
|
||||||
|
_type = texture_type::File;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_type == texture_type::File) {
|
||||||
|
auto file_path = std::filesystem::path(obs_data_get_string(settings, _keys[1].c_str()));
|
||||||
if (file_path.is_relative()) {
|
if (file_path.is_relative()) {
|
||||||
file_path = make_absolute_to(file_path, get_parent()->get_shader_file());
|
file_path = make_absolute_to(file_path, get_parent()->get_shader_file());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((file_path != _file_path) || !_file_texture) {
|
if (_file_path != file_path) {
|
||||||
auto file_texture = std::make_shared<streamfx::obs::gs::texture>(file_path.generic_u8string().c_str());
|
|
||||||
_file_texture = file_texture;
|
|
||||||
_file_path = file_path;
|
_file_path = file_path;
|
||||||
|
_dirty = true;
|
||||||
|
_dirty_ts = std::chrono::high_resolution_clock::now() - std::chrono::milliseconds(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (_type == texture_type::Source) {
|
||||||
auto type = static_cast<texture_type>(obs_data_get_int(settings, _keys[0].c_str()));
|
|
||||||
if (type == texture_type::File) {
|
|
||||||
std::filesystem::path file_path = obs_data_get_string(settings, _keys[1].c_str());
|
|
||||||
if (file_path.is_relative()) {
|
|
||||||
file_path = make_absolute_to(file_path, get_parent()->get_shader_file());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((file_path != _file_path) || !_file_texture) {
|
|
||||||
auto file_texture =
|
|
||||||
std::make_shared<streamfx::obs::gs::texture>(file_path.generic_u8string().c_str());
|
|
||||||
_file_texture = file_texture;
|
|
||||||
_file_path = file_path;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto source_name = obs_data_get_string(settings, _keys[2].c_str());
|
auto source_name = obs_data_get_string(settings, _keys[2].c_str());
|
||||||
|
|
||||||
|
if (_source_name != source_name) {
|
||||||
|
_source_name = source_name;
|
||||||
|
_dirty = true;
|
||||||
|
_dirty_ts = std::chrono::high_resolution_clock::now() - std::chrono::milliseconds(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::gfx::shader::texture_parameter::assign()
|
||||||
|
{
|
||||||
|
if (is_automatic())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the data has been marked dirty, and the future timestamp minus the now is smaller than 0ms.
|
||||||
|
if (_dirty && ((_dirty_ts - std::chrono::high_resolution_clock::now()) < std::chrono::milliseconds(0))) {
|
||||||
|
// Reload or Reacquire everything necessary.
|
||||||
|
try {
|
||||||
|
// Remove now unused references.
|
||||||
|
_source.reset();
|
||||||
|
_source_child.reset();
|
||||||
|
_source_active.reset();
|
||||||
|
_source_visible.reset();
|
||||||
|
_source_rendertarget.reset();
|
||||||
|
_file_texture.reset();
|
||||||
|
|
||||||
|
if (((field_type() == texture_field_type::Input) && (_type == texture_type::File))
|
||||||
|
|| (field_type() == texture_field_type::Enum)) {
|
||||||
|
if (!_file_path.empty()) {
|
||||||
|
_file_texture = std::make_shared<streamfx::obs::gs::texture>(
|
||||||
|
streamfx::util::platform::native_to_utf8(_file_path).generic_u8string().c_str());
|
||||||
|
}
|
||||||
|
} else if ((field_type() == texture_field_type::Input) && (_type == texture_type::Source)) {
|
||||||
// Try and grab the source itself.
|
// Try and grab the source itself.
|
||||||
auto source = std::shared_ptr<obs_source_t>(obs_get_source_by_name(source_name),
|
auto source = std::shared_ptr<obs_source_t>(obs_get_source_by_name(_source_name.c_str()),
|
||||||
[](obs_source_t* v) { obs_source_release(v); });
|
[](obs_source_t* v) { obs_source_release(v); });
|
||||||
if (!source) {
|
if (!source) {
|
||||||
throw std::runtime_error("Specified Source does not exist.");
|
throw std::runtime_error("Specified Source does not exist.");
|
||||||
|
@ -297,28 +327,13 @@ void streamfx::gfx::shader::texture_parameter::update(obs_data_t* settings)
|
||||||
_source = source;
|
_source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != _type) {
|
_dirty = false;
|
||||||
if (_type == texture_type::Source) {
|
} catch (const std::exception& ex) {
|
||||||
_source.reset();
|
_dirty_ts = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(5000);
|
||||||
_source_child.reset();
|
|
||||||
_source_active.reset();
|
|
||||||
_source_visible.reset();
|
|
||||||
_source_rendertarget.reset();
|
|
||||||
} else if (_type == texture_type::File) {
|
|
||||||
_file_texture.reset();
|
|
||||||
}
|
|
||||||
_type = type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// ToDo: Determine what to do with these.
|
_dirty_ts = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(5000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void streamfx::gfx::shader::texture_parameter::assign()
|
|
||||||
{
|
|
||||||
if (is_automatic())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If this is a source and active or visible, capture it.
|
// If this is a source and active or visible, capture it.
|
||||||
if ((_type == texture_type::Source) && (_active || _visible) && _source_rendertarget) {
|
if ((_type == texture_type::Source) && (_active || _visible) && _source_rendertarget) {
|
||||||
|
@ -354,12 +369,18 @@ void streamfx::gfx::shader::texture_parameter::assign()
|
||||||
auto tex = _source_rendertarget->get_texture();
|
auto tex = _source_rendertarget->get_texture();
|
||||||
if (tex) {
|
if (tex) {
|
||||||
get_parameter().set_texture(_source_rendertarget->get_texture(), false);
|
get_parameter().set_texture(_source_rendertarget->get_texture(), false);
|
||||||
|
} else {
|
||||||
|
get_parameter().set_texture(nullptr, false);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
get_parameter().set_texture(nullptr, false);
|
||||||
}
|
}
|
||||||
} else if (_type == texture_type::File) {
|
} else if (_type == texture_type::File) {
|
||||||
if (_file_texture) {
|
if (_file_texture) {
|
||||||
// Loaded files are always linear.
|
// Loaded files are always linear.
|
||||||
get_parameter().set_texture(_file_texture, false);
|
get_parameter().set_texture(_file_texture, false);
|
||||||
|
} else {
|
||||||
|
get_parameter().set_texture(nullptr, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <obs.h>
|
#include <obs.h>
|
||||||
|
#include <chrono>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "gfx-shader-param.hpp"
|
#include "gfx-shader-param.hpp"
|
||||||
#include "obs/gs/gs-rendertarget.hpp"
|
#include "obs/gs/gs-rendertarget.hpp"
|
||||||
|
@ -44,6 +45,10 @@ namespace streamfx::gfx {
|
||||||
bool _visible;
|
bool _visible;
|
||||||
std::filesystem::path _default;
|
std::filesystem::path _default;
|
||||||
|
|
||||||
|
// Data: Dirty state
|
||||||
|
bool _dirty;
|
||||||
|
std::chrono::high_resolution_clock::time_point _dirty_ts;
|
||||||
|
|
||||||
// Data: File
|
// Data: File
|
||||||
std::filesystem::path _file_path;
|
std::filesystem::path _file_path;
|
||||||
std::shared_ptr<streamfx::obs::gs::texture> _file_texture;
|
std::shared_ptr<streamfx::obs::gs::texture> _file_texture;
|
||||||
|
|
Loading…
Reference in a new issue