/* 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(float4(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_; } float4 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; } float4 Result::get_vector_value_default(const float4 &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 float4 &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