This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/blenkernel/intern/attribute_math.cc
Iliay Katueshenock 55a332da64 Attribute Math: Improve performance of mixer in some cases
The `DefaultMixer` for mixing generic data types has some issues:
1. The full buffer is always zeroed, even if only some is used.
2. Finalizing also works on all values, even if only some are used.
3. "mixing" doesn't allow setting the first value, requiring that
everything is cleared beforehand.

This commit adds the following functionality:
1. Constructor with the specified `IndexMask` for preliminary zeroing.
2. `set` method to overwrite the value.
3. `finalize` with the specified mask to process a subset of values.

This is useful in situations where you want to use the
DefaultMixer without having to overwrite all the values many times.

A performance improvement was observed for NURBS curve evaluation and
attribute interpolation from the point to curve domain of about 15% and
35% respectively (100,000 curves).

Differential Revision: https://developer.blender.org/D15434
2022-08-03 10:18:02 -05:00

136 lines
4.4 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_attribute_math.hh"
namespace blender::attribute_math {
ColorGeometry4fMixer::ColorGeometry4fMixer(MutableSpan<ColorGeometry4f> buffer,
ColorGeometry4f default_color)
: ColorGeometry4fMixer(buffer, buffer.index_range(), default_color)
{
}
ColorGeometry4fMixer::ColorGeometry4fMixer(MutableSpan<ColorGeometry4f> buffer,
const IndexMask mask,
const ColorGeometry4f default_color)
: buffer_(buffer), default_color_(default_color), total_weights_(buffer.size(), 0.0f)
{
const ColorGeometry4f zero{0.0f, 0.0f, 0.0f, 0.0f};
mask.foreach_index([&](const int64_t i) { buffer_[i] = zero; });
}
void ColorGeometry4fMixer::set(const int64_t index,
const ColorGeometry4f &color,
const float weight)
{
BLI_assert(weight >= 0.0f);
buffer_[index].r = color.r * weight;
buffer_[index].g = color.g * weight;
buffer_[index].b = color.b * weight;
buffer_[index].a = color.a * weight;
total_weights_[index] = weight;
}
void ColorGeometry4fMixer::mix_in(const int64_t index,
const ColorGeometry4f &color,
const float weight)
{
BLI_assert(weight >= 0.0f);
ColorGeometry4f &output_color = buffer_[index];
output_color.r += color.r * weight;
output_color.g += color.g * weight;
output_color.b += color.b * weight;
output_color.a += color.a * weight;
total_weights_[index] += weight;
}
void ColorGeometry4fMixer::finalize()
{
this->finalize(buffer_.index_range());
}
void ColorGeometry4fMixer::finalize(const IndexMask mask)
{
mask.foreach_index([&](const int64_t i) {
const float weight = total_weights_[i];
ColorGeometry4f &output_color = buffer_[i];
if (weight > 0.0f) {
const float weight_inv = 1.0f / weight;
output_color.r *= weight_inv;
output_color.g *= weight_inv;
output_color.b *= weight_inv;
output_color.a *= weight_inv;
}
else {
output_color = default_color_;
}
});
}
ColorGeometry4bMixer::ColorGeometry4bMixer(MutableSpan<ColorGeometry4b> buffer,
const ColorGeometry4b default_color)
: ColorGeometry4bMixer(buffer, buffer.index_range(), default_color)
{
}
ColorGeometry4bMixer::ColorGeometry4bMixer(MutableSpan<ColorGeometry4b> buffer,
const IndexMask mask,
const ColorGeometry4b default_color)
: buffer_(buffer),
default_color_(default_color),
total_weights_(buffer.size(), 0.0f),
accumulation_buffer_(buffer.size(), float4(0, 0, 0, 0))
{
const ColorGeometry4b zero{0, 0, 0, 0};
mask.foreach_index([&](const int64_t i) { buffer_[i] = zero; });
}
void ColorGeometry4bMixer::ColorGeometry4bMixer::set(int64_t index,
const ColorGeometry4b &color,
const float weight)
{
BLI_assert(weight >= 0.0f);
accumulation_buffer_[index][0] = color.r * weight;
accumulation_buffer_[index][1] = color.g * weight;
accumulation_buffer_[index][2] = color.b * weight;
accumulation_buffer_[index][3] = color.a * weight;
total_weights_[index] = weight;
}
void ColorGeometry4bMixer::mix_in(int64_t index, const ColorGeometry4b &color, float weight)
{
BLI_assert(weight >= 0.0f);
float4 &accum_value = accumulation_buffer_[index];
accum_value[0] += color.r * weight;
accum_value[1] += color.g * weight;
accum_value[2] += color.b * weight;
accum_value[3] += color.a * weight;
total_weights_[index] += weight;
}
void ColorGeometry4bMixer::finalize()
{
this->finalize(buffer_.index_range());
}
void ColorGeometry4bMixer::finalize(const IndexMask mask)
{
mask.foreach_index([&](const int64_t i) {
const float weight = total_weights_[i];
const float4 &accum_value = accumulation_buffer_[i];
ColorGeometry4b &output_color = buffer_[i];
if (weight > 0.0f) {
const float weight_inv = 1.0f / weight;
output_color.r = accum_value[0] * weight_inv;
output_color.g = accum_value[1] * weight_inv;
output_color.b = accum_value[2] * weight_inv;
output_color.a = accum_value[3] * weight_inv;
}
else {
output_color = default_color_;
}
});
}
} // namespace blender::attribute_math