Cycles: Cleanup, split 2D interpolation function
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 7 Dec 2017 16:45:37 +0000 (17:45 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 8 Dec 2017 10:22:04 +0000 (11:22 +0100)
intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h

index 37ba0f692be78333c257884a62e202caa9371904..8e9bae1d7d814662a0ee027416d4294846e64846 100644 (file)
@@ -83,145 +83,160 @@ template<typename T> struct TextureInterpolator  {
                return x - (float)i;
        }
 
                return x - (float)i;
        }
 
-       static ccl_always_inline float4 interp(const TextureInfo& info, float x, float y)
+       /* ********  2D interpolation ******** */
+
+       static ccl_always_inline float4 interp_closest(const TextureInfo& info,
+                                                      float x, float y)
        {
        {
-               if(UNLIKELY(!info.data))
-                       return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+               const T *data = (const T*)info.data;
+               const int width = info.width;
+               const int height = info.height;
+               int ix, iy;
+               frac(x*(float)width, &ix);
+               frac(y*(float)height, &iy);
+               switch(info.extension) {
+                       case EXTENSION_REPEAT:
+                               ix = wrap_periodic(ix, width);
+                               iy = wrap_periodic(iy, height);
+                               break;
+                       case EXTENSION_CLIP:
+                               if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
+                                       return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+                               }
+                               ATTR_FALLTHROUGH;
+                       case EXTENSION_EXTEND:
+                               ix = wrap_clamp(ix, width);
+                               iy = wrap_clamp(iy, height);
+                               break;
+                       default:
+                               kernel_assert(0);
+                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+               }
+               return read(data[ix + iy*width]);
+       }
 
 
+       static ccl_always_inline float4 interp_linear(const TextureInfo& info,
+                                                     float x, float y)
+       {
                const T *data = (const T*)info.data;
                const T *data = (const T*)info.data;
-               int width = info.width;
-               int height = info.height;
+               const int width = info.width;
+               const int height = info.height;
                int ix, iy, nix, niy;
                int ix, iy, nix, niy;
-
-               if(info.interpolation == INTERPOLATION_CLOSEST) {
-                       frac(x*(float)width, &ix);
-                       frac(y*(float)height, &iy);
-                       switch(info.extension) {
-                               case EXTENSION_REPEAT:
-                                       ix = wrap_periodic(ix, width);
-                                       iy = wrap_periodic(iy, height);
-                                       break;
-                               case EXTENSION_CLIP:
-                                       if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
-                                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-                                       }
-                                       ATTR_FALLTHROUGH;
-                               case EXTENSION_EXTEND:
-                                       ix = wrap_clamp(ix, width);
-                                       iy = wrap_clamp(iy, height);
-                                       break;
-                               default:
-                                       kernel_assert(0);
+               const float tx = frac(x*(float)width - 0.5f, &ix);
+               const float ty = frac(y*(float)height - 0.5f, &iy);
+               switch(info.extension) {
+                       case EXTENSION_REPEAT:
+                               ix = wrap_periodic(ix, width);
+                               iy = wrap_periodic(iy, height);
+                               nix = wrap_periodic(ix+1, width);
+                               niy = wrap_periodic(iy+1, height);
+                               break;
+                       case EXTENSION_CLIP:
+                               if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
                                        return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
                                        return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-                       }
-                       return read(data[ix + iy*width]);
+                               }
+                               ATTR_FALLTHROUGH;
+                       case EXTENSION_EXTEND:
+                               nix = wrap_clamp(ix+1, width);
+                               niy = wrap_clamp(iy+1, height);
+                               ix = wrap_clamp(ix, width);
+                               iy = wrap_clamp(iy, height);
+                               break;
+                       default:
+                               kernel_assert(0);
+                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
                }
                }
-               else if(info.interpolation == INTERPOLATION_LINEAR) {
-                       float tx = frac(x*(float)width - 0.5f, &ix);
-                       float ty = frac(y*(float)height - 0.5f, &iy);
-
-                       switch(info.extension) {
-                               case EXTENSION_REPEAT:
-                                       ix = wrap_periodic(ix, width);
-                                       iy = wrap_periodic(iy, height);
-
-                                       nix = wrap_periodic(ix+1, width);
-                                       niy = wrap_periodic(iy+1, height);
-                                       break;
-                               case EXTENSION_CLIP:
-                                       if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
-                                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-                                       }
-                                       ATTR_FALLTHROUGH;
-                               case EXTENSION_EXTEND:
-                                       nix = wrap_clamp(ix+1, width);
-                                       niy = wrap_clamp(iy+1, height);
-
-                                       ix = wrap_clamp(ix, width);
-                                       iy = wrap_clamp(iy, height);
-                                       break;
-                               default:
-                                       kernel_assert(0);
-                                       return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-                       }
-
-                       float4 r = (1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width]);
-                       r += (1.0f - ty)*tx*read(data[nix + iy*width]);
-                       r += ty*(1.0f - tx)*read(data[ix + niy*width]);
-                       r += ty*tx*read(data[nix + niy*width]);
+               float4 r = (1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width]);
+               r += (1.0f - ty)*tx*read(data[nix + iy*width]);
+               r += ty*(1.0f - tx)*read(data[ix + niy*width]);
+               r += ty*tx*read(data[nix + niy*width]);
+               return r;
+       }
 
 
-                       return r;
-               }
-               else {
-                       /* Bicubic b-spline interpolation. */
-                       float tx = frac(x*(float)width - 0.5f, &ix);
-                       float ty = frac(y*(float)height - 0.5f, &iy);
-                       int pix, piy, nnix, nniy;
-                       switch(info.extension) {
-                               case EXTENSION_REPEAT:
-                                       ix = wrap_periodic(ix, width);
-                                       iy = wrap_periodic(iy, height);
-
-                                       pix = wrap_periodic(ix-1, width);
-                                       piy = wrap_periodic(iy-1, height);
-
-                                       nix = wrap_periodic(ix+1, width);
-                                       niy = wrap_periodic(iy+1, height);
-
-                                       nnix = wrap_periodic(ix+2, width);
-                                       nniy = wrap_periodic(iy+2, height);
-                                       break;
-                               case EXTENSION_CLIP:
-                                       if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
-                                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-                                       }
-                                       ATTR_FALLTHROUGH;
-                               case EXTENSION_EXTEND:
-                                       pix = wrap_clamp(ix-1, width);
-                                       piy = wrap_clamp(iy-1, height);
-
-                                       nix = wrap_clamp(ix+1, width);
-                                       niy = wrap_clamp(iy+1, height);
-
-                                       nnix = wrap_clamp(ix+2, width);
-                                       nniy = wrap_clamp(iy+2, height);
-
-                                       ix = wrap_clamp(ix, width);
-                                       iy = wrap_clamp(iy, height);
-                                       break;
-                               default:
-                                       kernel_assert(0);
+       static ccl_always_inline float4 interp_cubic(const TextureInfo& info,
+                                                    float x, float y)
+       {
+               const T *data = (const T*)info.data;
+               const int width = info.width;
+               const int height = info.height;
+               int ix, iy, nix, niy;
+               const float tx = frac(x*(float)width - 0.5f, &ix);
+               const float ty = frac(y*(float)height - 0.5f, &iy);
+               int pix, piy, nnix, nniy;
+               switch(info.extension) {
+                       case EXTENSION_REPEAT:
+                               ix = wrap_periodic(ix, width);
+                               iy = wrap_periodic(iy, height);
+                               pix = wrap_periodic(ix-1, width);
+                               piy = wrap_periodic(iy-1, height);
+                               nix = wrap_periodic(ix+1, width);
+                               niy = wrap_periodic(iy+1, height);
+                               nnix = wrap_periodic(ix+2, width);
+                               nniy = wrap_periodic(iy+2, height);
+                               break;
+                       case EXTENSION_CLIP:
+                               if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
                                        return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
                                        return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-                       }
-
-                       const int xc[4] = {pix, ix, nix, nnix};
-                       const int yc[4] = {width * piy,
-                                          width * iy,
-                                          width * niy,
-                                          width * nniy};
-                       float u[4], v[4];
-                       /* Some helper macro to keep code reasonable size,
-                        * let compiler to inline all the matrix multiplications.
-                        */
+                               }
+                               ATTR_FALLTHROUGH;
+                       case EXTENSION_EXTEND:
+                               pix = wrap_clamp(ix-1, width);
+                               piy = wrap_clamp(iy-1, height);
+                               nix = wrap_clamp(ix+1, width);
+                               niy = wrap_clamp(iy+1, height);
+                               nnix = wrap_clamp(ix+2, width);
+                               nniy = wrap_clamp(iy+2, height);
+                               ix = wrap_clamp(ix, width);
+                               iy = wrap_clamp(iy, height);
+                               break;
+                       default:
+                               kernel_assert(0);
+                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+               }
+               const int xc[4] = {pix, ix, nix, nnix};
+               const int yc[4] = {width * piy,
+                                  width * iy,
+                                  width * niy,
+                                  width * nniy};
+               float u[4], v[4];
+               /* Some helper macro to keep code reasonable size,
+                * let compiler to inline all the matrix multiplications.
+                */
 #define DATA(x, y) (read(data[xc[x] + yc[y]]))
 #define TERM(col) \
 #define DATA(x, y) (read(data[xc[x] + yc[y]]))
 #define TERM(col) \
-                       (v[col] * (u[0] * DATA(0, col) + \
-                                  u[1] * DATA(1, col) + \
-                                  u[2] * DATA(2, col) + \
-                                  u[3] * DATA(3, col)))
-
-                       SET_CUBIC_SPLINE_WEIGHTS(u, tx);
-                       SET_CUBIC_SPLINE_WEIGHTS(v, ty);
+               (v[col] * (u[0] * DATA(0, col) + \
+                          u[1] * DATA(1, col) + \
+                          u[2] * DATA(2, col) + \
+                          u[3] * DATA(3, col)))
 
 
-                       /* Actual interpolation. */
-                       return TERM(0) + TERM(1) + TERM(2) + TERM(3);
+               SET_CUBIC_SPLINE_WEIGHTS(u, tx);
+               SET_CUBIC_SPLINE_WEIGHTS(v, ty);
 
 
+               /* Actual interpolation. */
+               return TERM(0) + TERM(1) + TERM(2) + TERM(3);
 #undef TERM
 #undef DATA
 #undef TERM
 #undef DATA
+       }
+
+       static ccl_always_inline float4 interp(const TextureInfo& info, float x, float y)
+       {
+               if(UNLIKELY(!info.data)) {
+                       return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+               }
+               switch(info.interpolation) {
+                       case INTERPOLATION_CLOSEST:
+                               return interp_closest(info, x, y);
+                       case INTERPOLATION_LINEAR:
+                               return interp_linear(info, x, y);
+                       default:
+                               return interp_cubic(info, x, y);
                }
        }
 
                }
        }
 
-       static ccl_always_inline float4 interp_3d_closest(const TextureInfo& info, float x, float y, float z)
+       /* ********  3D interpolation ******** */
+
+       static ccl_always_inline float4 interp_3d_closest(const TextureInfo& info,
+                                                         float x, float y, float z)
        {
                int width = info.width;
                int height = info.height;
        {
                int width = info.width;
                int height = info.height;
@@ -259,7 +274,8 @@ template<typename T> struct TextureInterpolator  {
                return read(data[ix + iy*width + iz*width*height]);
        }
 
                return read(data[ix + iy*width + iz*width*height]);
        }
 
-       static ccl_always_inline float4 interp_3d_linear(const TextureInfo& info, float x, float y, float z)
+       static ccl_always_inline float4 interp_3d_linear(const TextureInfo& info,
+                                                        float x, float y, float z)
        {
                int width = info.width;
                int height = info.height;
        {
                int width = info.width;
                int height = info.height;