[Bf-blender-cvs] [e9c8ae767a2] master: Performance: Split ImBuf sampling.

Jeroen Bakker noreply at git.blender.org
Fri Jun 11 11:38:26 CEST 2021


Commit: e9c8ae767a2b82f15838d79d910cc828a00f84c7
Author: Jeroen Bakker
Date:   Fri Jun 11 10:53:52 2021 +0200
Branches: master
https://developer.blender.org/rBe9c8ae767a2b82f15838d79d910cc828a00f84c7

Performance: Split ImBuf sampling.

When sampling ImBuf can be a char or a float buffer. Current sampling
functions added overhead by checking which kind of buffer was passed
every pixel that was sampled. When performing image processing this
check can be removed outside the inner loop adding 5% of performance
increase in the `IMB_transform` operator.

===================================================================

M	source/blender/imbuf/intern/imageprocess.c

===================================================================

diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index c88a9b81ff2..4320f30884b 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -127,6 +127,22 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, in
 /** \name Bi-Linear Interpolation
  * \{ */
 
+BLI_INLINE void bilinear_interpolation_color_fl(
+    struct ImBuf *in, unsigned char UNUSED(outI[4]), float outF[4], float u, float v)
+{
+  BLI_assert(outF);
+  BLI_assert(in->rect_float);
+  BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v);
+}
+
+BLI_INLINE void bilinear_interpolation_color_char(
+    struct ImBuf *in, unsigned char outI[4], float UNUSED(outF[4]), float u, float v)
+{
+  BLI_assert(outI);
+  BLI_assert(in->rect);
+  BLI_bilinear_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v);
+}
+
 void bilinear_interpolation_color(
     struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v)
 {
@@ -238,60 +254,58 @@ void bilinear_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, i
 /** \name Nearest Interpolation
  * \{ */
 
-/* function assumes out to be zero'ed, only does RGBA */
-void nearest_interpolation_color(
-    struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v)
+/* functions assumes out to be zero'ed, only does RGBA */
+BLI_INLINE void nearest_interpolation_color_char(
+    struct ImBuf *in, unsigned char outI[4], float UNUSED(outF[4]), float u, float v)
 {
-  const float *dataF;
-  unsigned char *dataI;
-  int y1, x1;
-
+  BLI_assert(outI);
+  BLI_assert(in->rect);
   /* ImBuf in must have a valid rect or rect_float, assume this is already checked */
+  int x1 = (int)(u);
+  int y1 = (int)(v);
 
-  x1 = (int)(u);
-  y1 = (int)(v);
+  /* sample area entirely outside image? */
+  if (x1 < 0 || x1 >= in->x || y1 < 0 || y1 >= in->y) {
+    outI[0] = outI[1] = outI[2] = outI[3] = 0;
+    return;
+  }
+
+  const size_t offset = (in->x * y1 + x1) * 4;
+  const unsigned char *dataI = (unsigned char *)in->rect + offset;
+  outI[0] = dataI[0];
+  outI[1] = dataI[1];
+  outI[2] = dataI[2];
+  outI[3] = dataI[3];
+}
+
+BLI_INLINE void nearest_interpolation_color_fl(
+    struct ImBuf *in, unsigned char UNUSED(outI[4]), float outF[4], float u, float v)
+{
+  BLI_assert(outF);
+  BLI_assert(in->rect_float);
+  /* ImBuf in must have a valid rect or rect_float, assume this is already checked */
+  int x1 = (int)(u);
+  int y1 = (int)(v);
 
   /* sample area entirely outside image? */
-  if (x1 < 0 || x1 > in->x - 1 || y1 < 0 || y1 > in->y - 1) {
-    if (outI) {
-      outI[0] = outI[1] = outI[2] = outI[3] = 0;
-    }
-    if (outF) {
-      outF[0] = outF[1] = outF[2] = outF[3] = 0.0f;
-    }
+  if (x1 < 0 || x1 >= in->x || y1 < 0 || y1 >= in->y) {
+    zero_v4(outF);
     return;
   }
 
-  /* sample including outside of edges of image */
-  if (x1 < 0 || y1 < 0) {
-    if (outI) {
-      outI[0] = 0;
-      outI[1] = 0;
-      outI[2] = 0;
-      outI[3] = 0;
-    }
-    if (outF) {
-      outF[0] = 0.0f;
-      outF[1] = 0.0f;
-      outF[2] = 0.0f;
-      outF[3] = 0.0f;
-    }
+  const size_t offset = (in->x * y1 + x1) * 4;
+  const float *dataF = in->rect_float + offset;
+  copy_v4_v4(outF, dataF);
+}
+
+void nearest_interpolation_color(
+    struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v)
+{
+  if (outF) {
+    nearest_interpolation_color_fl(in, outI, outF, u, v);
   }
   else {
-    dataI = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x1;
-    if (outI) {
-      outI[0] = dataI[0];
-      outI[1] = dataI[1];
-      outI[2] = dataI[2];
-      outI[3] = dataI[3];
-    }
-    dataF = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x1;
-    if (outF) {
-      outF[0] = dataF[0];
-      outF[1] = dataF[1];
-      outF[2] = dataF[2];
-      outF[3] = dataF[3];
-    }
+    nearest_interpolation_color_char(in, outI, outF, u, v);
   }
 }
 
@@ -436,7 +450,14 @@ static void imb_transform_nearest_scanlines(void *custom_data,
                                             int num_scanlines)
 {
   const TransformUserData *user_data = custom_data;
-  imb_transform_scanlines(user_data, start_scanline, num_scanlines, nearest_interpolation_color);
+  InterpolationColorFunction interpolation = NULL;
+  if (user_data->dst->rect_float) {
+    interpolation = nearest_interpolation_color_fl;
+  }
+  else {
+    interpolation = nearest_interpolation_color_char;
+  }
+  imb_transform_scanlines(user_data, start_scanline, num_scanlines, interpolation);
 }
 
 static void imb_transform_bilinear_scanlines(void *custom_data,
@@ -444,7 +465,14 @@ static void imb_transform_bilinear_scanlines(void *custom_data,
                                              int num_scanlines)
 {
   const TransformUserData *user_data = custom_data;
-  imb_transform_scanlines(user_data, start_scanline, num_scanlines, bilinear_interpolation_color);
+  InterpolationColorFunction interpolation = NULL;
+  if (user_data->dst->rect_float) {
+    interpolation = bilinear_interpolation_color_fl;
+  }
+  else if (user_data->dst->rect) {
+    interpolation = bilinear_interpolation_color_char;
+  }
+  imb_transform_scanlines(user_data, start_scanline, num_scanlines, interpolation);
 }
 
 static ScanlineThreadFunc imb_transform_scanline_func(const eIMBInterpolationFilterMode filter)



More information about the Bf-blender-cvs mailing list