diff --git a/source/nvidia/vfx/nvidia-vfx-superresolution.cpp b/source/nvidia/vfx/nvidia-vfx-superresolution.cpp index ccfcfaa5..50b7586a 100644 --- a/source/nvidia/vfx/nvidia-vfx-superresolution.cpp +++ b/source/nvidia/vfx/nvidia-vfx-superresolution.cpp @@ -21,6 +21,7 @@ #include "nvidia-vfx-superresolution.hpp" #include #include +#include #include "obs/gs/gs-helper.hpp" #include "util/util-logging.hpp" #include "util/utility.hpp" @@ -39,6 +40,37 @@ #define D_LOG_DEBUG(...) P_LOG_DEBUG(ST_PREFIX __VA_ARGS__) #endif +static std::vector supported_scale_factors{4. / 3., 1.5, 2., 3., 4.}; + +static float find_closest_scale_factor(float factor) +{ + std::pair minimal = {0.f, std::numeric_limits::max()}; + for (float delta : supported_scale_factors) { + float value = abs(delta - factor); + if (minimal.second > value) { + minimal.first = delta; + minimal.second = value; + } + } + + return minimal.first; +} + +static size_t find_closest_scale_factor_index(float factor) +{ + std::pair minimal = {0.f, std::numeric_limits::max()}; + for (size_t idx = 0; idx < supported_scale_factors.size(); idx++) { + float delta = supported_scale_factors[idx]; + float value = abs(delta - factor); + if (minimal.second > value) { + minimal.first = idx; + minimal.second = value; + } + } + + return minimal.first; +} + streamfx::nvidia::vfx::superresolution::~superresolution() { auto gctx = ::streamfx::obs::gs::context(); @@ -138,23 +170,14 @@ void streamfx::nvidia::vfx::superresolution::set_scale(float scale) scale = std::clamp(scale, 1., 4.); // Match to nearest scale. - std::pair minimal = {0.f, std::numeric_limits::max()}; - std::vector deltas{ - 1.f + (1.f / 3.f), 1.5f, 2.0f, 3.0f, 4.0f, - }; - for (float delta : deltas) { - float value = abs(delta - scale); - if (minimal.second > value) { - minimal.first = delta; - minimal.second = value; - } - } + double factor = find_closest_scale_factor(scale); // If anything was changed, flag the effect as dirty. - if (!::streamfx::util::math::is_close(_scale, minimal.first, 0.01f)) + if (!::streamfx::util::math::is_close(_scale, factor, 0.01f)) _dirty = true; - _scale = minimal.first; + // Save new scale factor. + _scale = factor; } float streamfx::nvidia::vfx::superresolution::scale() @@ -182,6 +205,10 @@ void streamfx::nvidia::vfx::superresolution::size(std::pair max_height = 1080; } + // Restore Input Size + input_size.first = size.first; + input_size.second = size.second; + // Calculate Input Size if (input_size.first > input_size.second) { // Dominant Width @@ -198,8 +225,20 @@ void streamfx::nvidia::vfx::superresolution::size(std::pair } // Calculate Output Size. - output_size.first = static_cast(input_size.first * _scale); - output_size.second = static_cast(input_size.second * _scale); + output_size.first = static_cast(std::lround(input_size.first * _scale)); + output_size.second = static_cast(std::lround(input_size.second * _scale)); + + // Verify that this is a valid scale factor. + float width_mul = (static_cast(output_size.first) / static_cast(input_size.first)); + float height_mul = (static_cast(output_size.second) / static_cast(input_size.second)); + if (!::streamfx::util::math::is_close(width_mul, _scale, 0.00001) + || !::streamfx::util::math::is_close(height_mul, _scale, 0.00001)) { + size_t scale_idx = find_closest_scale_factor_index(_scale); + if (scale_idx < supported_scale_factors.size()) { + _scale = supported_scale_factors[scale_idx + 1]; + this->size(size, input_size, output_size); + } + } } std::shared_ptr<::streamfx::obs::gs::texture>