diff options
Diffstat (limited to 'source/blender/compositor/realtime_compositor/intern/result.cc')
-rw-r--r-- | source/blender/compositor/realtime_compositor/intern/result.cc | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/source/blender/compositor/realtime_compositor/intern/result.cc b/source/blender/compositor/realtime_compositor/intern/result.cc new file mode 100644 index 00000000000..8059367d211 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/intern/result.cc @@ -0,0 +1,257 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_float3x3.hh" +#include "BLI_math_vec_types.hh" + +#include "GPU_shader.h" +#include "GPU_state.h" +#include "GPU_texture.h" + +#include "COM_domain.hh" +#include "COM_result.hh" +#include "COM_texture_pool.hh" + +namespace blender::realtime_compositor { + +Result::Result(ResultType type, TexturePool &texture_pool) + : type_(type), texture_pool_(&texture_pool) +{ +} + +void Result::allocate_texture(Domain domain) +{ + is_single_value_ = false; + switch (type_) { + case ResultType::Float: + texture_ = texture_pool_->acquire_float(domain.size); + break; + case ResultType::Vector: + texture_ = texture_pool_->acquire_vector(domain.size); + break; + case ResultType::Color: + texture_ = texture_pool_->acquire_color(domain.size); + break; + } + domain_ = domain; +} + +void Result::allocate_single_value() +{ + is_single_value_ = true; + /* Single values are stored in 1x1 textures as well as the single value members. */ + const int2 texture_size{1, 1}; + switch (type_) { + case ResultType::Float: + texture_ = texture_pool_->acquire_float(texture_size); + break; + case ResultType::Vector: + texture_ = texture_pool_->acquire_vector(texture_size); + break; + case ResultType::Color: + texture_ = texture_pool_->acquire_color(texture_size); + break; + } + domain_ = Domain::identity(); +} + +void Result::allocate_invalid() +{ + allocate_single_value(); + switch (type_) { + case ResultType::Float: + set_float_value(0.0f); + break; + case ResultType::Vector: + set_vector_value(float3(0.0f)); + break; + case ResultType::Color: + set_color_value(float4(0.0f)); + break; + } +} + +void Result::bind_as_texture(GPUShader *shader, const char *texture_name) const +{ + /* Make sure any prior writes to the texture are reflected before reading from it. */ + GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH); + + const int texture_image_unit = GPU_shader_get_texture_binding(shader, texture_name); + GPU_texture_bind(texture_, texture_image_unit); +} + +void Result::bind_as_image(GPUShader *shader, const char *image_name) const +{ + const int image_unit = GPU_shader_get_texture_binding(shader, image_name); + GPU_texture_image_bind(texture_, image_unit); +} + +void Result::unbind_as_texture() const +{ + GPU_texture_unbind(texture_); +} + +void Result::unbind_as_image() const +{ + GPU_texture_image_unbind(texture_); +} + +void Result::pass_through(Result &target) +{ + /* Increment the reference count of the master by the original reference count of the target. */ + increment_reference_count(target.reference_count()); + + /* Make the target an exact copy of this result, but keep the initial reference count, as this is + * a property of the original result and is needed for correctly resetting the result before the + * next evaluation. */ + const int initial_reference_count = target.initial_reference_count_; + target = *this; + target.initial_reference_count_ = initial_reference_count; + + target.master_ = this; +} + +void Result::transform(const float3x3 &transformation) +{ + domain_.transform(transformation); +} + +RealizationOptions &Result::get_realization_options() +{ + return domain_.realization_options; +} + +float Result::get_float_value() const +{ + return float_value_; +} + +float3 Result::get_vector_value() const +{ + return vector_value_; +} + +float4 Result::get_color_value() const +{ + return color_value_; +} + +float Result::get_float_value_default(float default_value) const +{ + if (is_single_value()) { + return get_float_value(); + } + return default_value; +} + +float3 Result::get_vector_value_default(const float3 &default_value) const +{ + if (is_single_value()) { + return get_vector_value(); + } + return default_value; +} + +float4 Result::get_color_value_default(const float4 &default_value) const +{ + if (is_single_value()) { + return get_color_value(); + } + return default_value; +} + +void Result::set_float_value(float value) +{ + float_value_ = value; + GPU_texture_update(texture_, GPU_DATA_FLOAT, &float_value_); +} + +void Result::set_vector_value(const float3 &value) +{ + vector_value_ = value; + GPU_texture_update(texture_, GPU_DATA_FLOAT, vector_value_); +} + +void Result::set_color_value(const float4 &value) +{ + color_value_ = value; + GPU_texture_update(texture_, GPU_DATA_FLOAT, color_value_); +} + +void Result::set_initial_reference_count(int count) +{ + initial_reference_count_ = count; +} + +void Result::reset() +{ + master_ = nullptr; + reference_count_ = initial_reference_count_; +} + +void Result::increment_reference_count(int count) +{ + /* If there is a master result, increment its reference count instead. */ + if (master_) { + master_->increment_reference_count(count); + return; + } + + reference_count_ += count; +} + +void Result::release() +{ + /* If there is a master result, release it instead. */ + if (master_) { + master_->release(); + return; + } + + /* Decrement the reference count, and if it reaches zero, release the texture back into the + * texture pool. */ + reference_count_--; + if (reference_count_ == 0) { + texture_pool_->release(texture_); + } +} + +bool Result::should_compute() +{ + return initial_reference_count_ != 0; +} + +ResultType Result::type() const +{ + return type_; +} + +bool Result::is_texture() const +{ + return !is_single_value_; +} + +bool Result::is_single_value() const +{ + return is_single_value_; +} + +GPUTexture *Result::texture() const +{ + return texture_; +} + +int Result::reference_count() const +{ + /* If there is a master result, return its reference count instead. */ + if (master_) { + return master_->reference_count(); + } + return reference_count_; +} + +const Domain &Result::domain() const +{ + return domain_; +} + +} // namespace blender::realtime_compositor |