ImBuf: optimize IMB_transform #115653

Merged
Aras Pranckevicius merged 15 commits from aras_p/blender:imb_transform_opt into main 2023-12-14 15:10:41 +01:00
3 changed files with 103 additions and 8 deletions
Showing only changes of commit 183f585f08 - Show all commits

View File

@ -524,6 +524,7 @@ if(WITH_GTESTS)
tests/BLI_math_bits_test.cc
tests/BLI_math_color_test.cc
tests/BLI_math_geom_test.cc
tests/BLI_math_interp_test.cc
tests/BLI_math_matrix_test.cc
tests/BLI_math_matrix_types_test.cc
tests/BLI_math_rotation_test.cc

View File

@ -15,10 +15,6 @@
#include "BLI_simd.h"
#include "BLI_strict_flags.h"
#if defined(_MSC_VER)
# include <intrin.h>
#endif
/**************************************************************************
* INTERPOLATIONS
*
@ -383,9 +379,9 @@ static __m128 rgba_uchar_to_simd(const uchar ptr[4])
static void simd_to_rgba_uchar(__m128 rgba, uchar dst[4])
{
/* Four RGBA integers in each lane of SSE. */
__m128i val = _mm_cvtps_epi32(rgba);
/* Pack to 16 bit values. */
__m128i rgba16 = _mm_packus_epi32(val, _mm_setzero_si128()); /* SSE 4.1 */
__m128i val = _mm_cvttps_epi32(rgba);
/* Pack to 16 bit signed values. */
__m128i rgba16 = _mm_packs_epi32(val, _mm_setzero_si128());
/* Pack to 8 bit values. */
__m128i rgba8 = _mm_packus_epi16(rgba16, _mm_setzero_si128());
/* Store the packed bits into destination. */
@ -470,7 +466,7 @@ void BLI_bilinear_interpolation_char(
__m128 rgba13 = _mm_add_ps(rgba1, rgba3);
__m128 rgba24 = _mm_add_ps(rgba2, rgba4);
__m128 rgba = _mm_add_ps(rgba13, rgba24);
rgba = _mm_round_ps(rgba, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); /* SSE 4.1 */
rgba = _mm_add_ps(rgba, _mm_set1_ps(0.5f));
simd_to_rgba_uchar(rgba, output);
#else
output[0] = (uchar)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f);

View File

@ -0,0 +1,98 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h"
#include "BLI_math_interp.h"
static constexpr int image_width = 3;
static constexpr int image_height = 3;
static constexpr unsigned char image_char[image_height][image_width][4] = {
{{255, 254, 217, 216}, {230, 230, 230, 230}, {240, 160, 90, 20}},
{{0, 1, 2, 3}, {62, 72, 82, 92}, {126, 127, 128, 129}},
{{1, 2, 3, 4}, {73, 108, 153, 251}, {128, 129, 130, 131}},
};
TEST(math_interp, BilinearCharExactSamples)
{
unsigned char res[4];
unsigned char exp1[4] = {73, 108, 153, 251};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 1.0f, 2.0f);
EXPECT_EQ_ARRAY(exp1, res, 4);
unsigned char exp2[4] = {240, 160, 90, 20};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 2.0f, 0.0f);
EXPECT_EQ_ARRAY(exp2, res, 4);
}
TEST(math_interp, BilinearCharHalfwayUSamples)
{
unsigned char res[4];
unsigned char exp1[4] = {31, 37, 42, 48};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 0.5f, 1.0f);
EXPECT_EQ_ARRAY(exp1, res, 4);
unsigned char exp2[4] = {243, 242, 224, 223};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 0.5f, 0.0f);
EXPECT_EQ_ARRAY(exp2, res, 4);
}
TEST(math_interp, BilinearCharHalfwayVSamples)
{
unsigned char res[4];
unsigned char exp1[4] = {1, 2, 3, 4};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 0.0f, 1.5f);
EXPECT_EQ_ARRAY(exp1, res, 4);
unsigned char exp2[4] = {127, 128, 129, 130};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 2.0f, 1.5f);
EXPECT_EQ_ARRAY(exp2, res, 4);
}
TEST(math_interp, BilinearCharSamples)
{
unsigned char res[4];
unsigned char exp1[4] = {136, 133, 132, 130};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 1.25f, 0.625f);
EXPECT_EQ_ARRAY(exp1, res, 4);
unsigned char exp2[4] = {219, 191, 167, 142};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 1.4f, 0.1f);
EXPECT_EQ_ARRAY(exp2, res, 4);
}
TEST(math_interp, BilinearCharPartiallyOutsideImage)
{
unsigned char res[4];
unsigned char exp1[4] = {1, 1, 2, 2};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, -0.5f, 2.0f);
EXPECT_EQ_ARRAY(exp1, res, 4);
unsigned char exp2[4] = {9, 11, 15, 22};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 1.25f, 2.9f);
EXPECT_EQ_ARRAY(exp2, res, 4);
unsigned char exp3[4] = {173, 115, 65, 14};
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 2.2f, -0.1f);
EXPECT_EQ_ARRAY(exp3, res, 4);
}
TEST(math_interp, BilinearCharFullyOutsideImage)
{
unsigned char res[4];
unsigned char exp[4] = {0, 0, 0, 0};
/* Out of range on U */
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, -1.5f, 0);
EXPECT_EQ_ARRAY(exp, res, 4);
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, -1.1f, 0);
EXPECT_EQ_ARRAY(exp, res, 4);
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 3, 0);
EXPECT_EQ_ARRAY(exp, res, 4);
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 5, 0);
EXPECT_EQ_ARRAY(exp, res, 4);
/* Out of range on V */
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 0, -3.2f);
EXPECT_EQ_ARRAY(exp, res, 4);
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 0, -1.5f);
EXPECT_EQ_ARRAY(exp, res, 4);
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 0, 3.1f);
EXPECT_EQ_ARRAY(exp, res, 4);
BLI_bilinear_interpolation_char(image_char[0][0], res, image_width, image_height, 0, 500.0f);
EXPECT_EQ_ARRAY(exp, res, 4);
}