Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
| Show All 22 Lines | |||||
| #endif | #endif | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| /* Make template functions private so symbols don't conflict between kernels with different | /* Make template functions private so symbols don't conflict between kernels with different | ||||
| * instruction sets. */ | * instruction sets. */ | ||||
| namespace { | namespace { | ||||
| template<typename T> struct TextureInterpolator { | |||||
| #define SET_CUBIC_SPLINE_WEIGHTS(u, t) \ | #define SET_CUBIC_SPLINE_WEIGHTS(u, t) \ | ||||
| { \ | { \ | ||||
| u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \ | u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \ | ||||
| u[1] = ((0.5f * t - 1.0f) * t) * t + (2.0f / 3.0f); \ | u[1] = ((0.5f * t - 1.0f) * t) * t + (2.0f / 3.0f); \ | ||||
| u[2] = ((-0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f / 6.0f); \ | u[2] = ((-0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f / 6.0f); \ | ||||
| u[3] = (1.0f / 6.0f) * t * t * t; \ | u[3] = (1.0f / 6.0f) * t * t * t; \ | ||||
| } \ | } \ | ||||
| (void)0 | (void)0 | ||||
| ccl_always_inline float frac(float x, int *ix) | |||||
| { | |||||
| int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0); | |||||
| *ix = i; | |||||
| return x - (float)i; | |||||
| } | |||||
| template<typename T> struct TextureInterpolator { | |||||
| static ccl_always_inline float4 read(float4 r) | static ccl_always_inline float4 read(float4 r) | ||||
| { | { | ||||
| return r; | return r; | ||||
| } | } | ||||
| static ccl_always_inline float4 read(uchar4 r) | static ccl_always_inline float4 read(uchar4 r) | ||||
| { | { | ||||
| float f = 1.0f / 255.0f; | float f = 1.0f / 255.0f; | ||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | static ccl_always_inline int wrap_periodic(int x, int width) | ||||
| return x; | return x; | ||||
| } | } | ||||
| static ccl_always_inline int wrap_clamp(int x, int width) | static ccl_always_inline int wrap_clamp(int x, int width) | ||||
| { | { | ||||
| return clamp(x, 0, width - 1); | return clamp(x, 0, width - 1); | ||||
| } | } | ||||
| static ccl_always_inline float frac(float x, int *ix) | |||||
| { | |||||
| int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0); | |||||
| *ix = i; | |||||
| return x - (float)i; | |||||
| } | |||||
| /* ******** 2D interpolation ******** */ | /* ******** 2D interpolation ******** */ | ||||
| static ccl_always_inline float4 interp_closest(const TextureInfo &info, float x, float y) | static ccl_always_inline float4 interp_closest(const TextureInfo &info, float x, float y) | ||||
| { | { | ||||
| const T *data = (const T *)info.data; | const T *data = (const T *)info.data; | ||||
| const int width = info.width; | const int width = info.width; | ||||
| const int height = info.height; | const int height = info.height; | ||||
| int ix, iy; | int ix, iy; | ||||
| ▲ Show 20 Lines • Show All 241 Lines • ▼ Show 20 Lines | #undef DATA | ||||
| * enabled. | * enabled. | ||||
| */ | */ | ||||
| #if defined(__GNUC__) || defined(__clang__) | #if defined(__GNUC__) || defined(__clang__) | ||||
| static ccl_always_inline | static ccl_always_inline | ||||
| #else | #else | ||||
| static ccl_never_inline | static ccl_never_inline | ||||
| #endif | #endif | ||||
| float4 | float4 | ||||
| interp_3d_tricubic(const TextureInfo &info, float x, float y, float z) | interp_3d_cubic(const TextureInfo &info, float x, float y, float z) | ||||
| { | { | ||||
| int width = info.width; | int width = info.width; | ||||
| int height = info.height; | int height = info.height; | ||||
| int depth = info.depth; | int depth = info.depth; | ||||
| int ix, iy, iz; | int ix, iy, iz; | ||||
| int nix, niy, niz; | int nix, niy, niz; | ||||
| /* Tricubic b-spline interpolation. */ | /* Tricubic b-spline interpolation. */ | ||||
| const float tx = frac(x * (float)width - 0.5f, &ix); | const float tx = frac(x * (float)width - 0.5f, &ix); | ||||
| ▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | if (UNLIKELY(!info.data)) | ||||
| return make_float4(0.0f, 0.0f, 0.0f, 0.0f); | return make_float4(0.0f, 0.0f, 0.0f, 0.0f); | ||||
| switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) { | switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) { | ||||
| case INTERPOLATION_CLOSEST: | case INTERPOLATION_CLOSEST: | ||||
| return interp_3d_closest(info, x, y, z); | return interp_3d_closest(info, x, y, z); | ||||
| case INTERPOLATION_LINEAR: | case INTERPOLATION_LINEAR: | ||||
| return interp_3d_linear(info, x, y, z); | return interp_3d_linear(info, x, y, z); | ||||
| default: | default: | ||||
| return interp_3d_tricubic(info, x, y, z); | return interp_3d_cubic(info, x, y, z); | ||||
| } | } | ||||
| } | } | ||||
| #undef SET_CUBIC_SPLINE_WEIGHTS | |||||
| }; | }; | ||||
| #ifdef WITH_NANOVDB | #ifdef WITH_NANOVDB | ||||
| template<typename T> struct NanoVDBInterpolator { | template<typename T> struct NanoVDBInterpolator { | ||||
| typedef nanovdb::ReadAccessor<nanovdb::NanoRoot<T>> ReadAccessorT; | |||||
| static ccl_always_inline float4 read(float r) | static ccl_always_inline float4 read(float r) | ||||
| { | { | ||||
| return make_float4(r, r, r, 1.0f); | return make_float4(r, r, r, 1.0f); | ||||
| } | } | ||||
| static ccl_always_inline float4 read(nanovdb::Vec3f r) | static ccl_always_inline float4 read(nanovdb::Vec3f r) | ||||
| { | { | ||||
| return make_float4(r[0], r[1], r[2], 1.0f); | return make_float4(r[0], r[1], r[2], 1.0f); | ||||
| } | } | ||||
| static ccl_always_inline float4 interp_3d_closest(ReadAccessorT acc, float x, float y, float z) | |||||
| { | |||||
| const nanovdb::Vec3f xyz(x, y, z); | |||||
| return read(nanovdb::NearestNeighborSampler<ReadAccessorT, false>(acc)(xyz)); | |||||
| } | |||||
| static ccl_always_inline float4 interp_3d_linear(ReadAccessorT acc, float x, float y, float z) | |||||
| { | |||||
| const nanovdb::Vec3f xyz(x - 0.5f, y - 0.5f, z - 0.5f); | |||||
| return read(nanovdb::TrilinearSampler<ReadAccessorT, false>(acc)(xyz)); | |||||
| } | |||||
| # if defined(__GNUC__) || defined(__clang__) | |||||
| static ccl_always_inline | |||||
| # else | |||||
| static ccl_never_inline | |||||
| # endif | |||||
| float4 | |||||
| interp_3d_cubic(ReadAccessorT acc, float x, float y, float z) | |||||
| { | |||||
| int ix, iy, iz; | |||||
| int nix, niy, niz; | |||||
| int pix, piy, piz; | |||||
| int nnix, nniy, nniz; | |||||
| /* Tricubic b-spline interpolation. */ | |||||
| const float tx = frac(x - 0.5f, &ix); | |||||
| const float ty = frac(y - 0.5f, &iy); | |||||
| const float tz = frac(z - 0.5f, &iz); | |||||
| pix = ix - 1; | |||||
| piy = iy - 1; | |||||
| piz = iz - 1; | |||||
| nix = ix + 1; | |||||
| niy = iy + 1; | |||||
| niz = iz + 1; | |||||
| nnix = ix + 2; | |||||
| nniy = iy + 2; | |||||
| nniz = iz + 2; | |||||
| const int xc[4] = {pix, ix, nix, nnix}; | |||||
| const int yc[4] = {piy, iy, niy, nniy}; | |||||
| const int zc[4] = {piz, iz, niz, nniz}; | |||||
| float u[4], v[4], w[4]; | |||||
| /* Some helper macro to keep code reasonable size, | |||||
| * let compiler to inline all the matrix multiplications. | |||||
| */ | |||||
| # define DATA(x, y, z) (read(acc.getValue(nanovdb::Coord(xc[x], yc[y], zc[z])))) | |||||
| # define COL_TERM(col, row) \ | |||||
| (v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \ | |||||
| u[3] * DATA(3, col, row))) | |||||
| # define ROW_TERM(row) \ | |||||
| (w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row))) | |||||
| SET_CUBIC_SPLINE_WEIGHTS(u, tx); | |||||
| SET_CUBIC_SPLINE_WEIGHTS(v, ty); | |||||
| SET_CUBIC_SPLINE_WEIGHTS(w, tz); | |||||
| /* Actual interpolation. */ | |||||
| return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3); | |||||
| # undef COL_TERM | |||||
| # undef ROW_TERM | |||||
| # undef DATA | |||||
| } | |||||
| static ccl_always_inline float4 | static ccl_always_inline float4 | ||||
| interp_3d(const TextureInfo &info, float x, float y, float z, InterpolationType interp) | interp_3d(const TextureInfo &info, float x, float y, float z, InterpolationType interp) | ||||
| { | { | ||||
| const nanovdb::Vec3f xyz(x, y, z); | using namespace nanovdb; | ||||
| nanovdb::NanoGrid<T> *const grid = (nanovdb::NanoGrid<T> *)info.data; | |||||
| const nanovdb::NanoRoot<T> &root = grid->tree().root(); | NanoGrid<T> *const grid = (NanoGrid<T> *)info.data; | ||||
| const NanoRoot<T> &root = grid->tree().root(); | |||||
| typedef nanovdb::ReadAccessor<nanovdb::NanoRoot<T>> ReadAccessorT; | |||||
| switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) { | switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) { | ||||
| case INTERPOLATION_CLOSEST: | case INTERPOLATION_CLOSEST: | ||||
| return read(nanovdb::SampleFromVoxels<ReadAccessorT, 0, false>(root)(xyz)); | return interp_3d_closest(root, x, y, z); | ||||
| case INTERPOLATION_LINEAR: | case INTERPOLATION_LINEAR: | ||||
| return read(nanovdb::SampleFromVoxels<ReadAccessorT, 1, false>(root)(xyz)); | return interp_3d_linear(root, x, y, z); | ||||
| default: | default: | ||||
| return read(nanovdb::SampleFromVoxels<ReadAccessorT, 3, false>(root)(xyz)); | return interp_3d_cubic(root, x, y, z); | ||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| #endif | #endif | ||||
| #undef SET_CUBIC_SPLINE_WEIGHTS | |||||
| ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y) | ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y) | ||||
| { | { | ||||
| const TextureInfo &info = kernel_tex_fetch(__texture_info, id); | const TextureInfo &info = kernel_tex_fetch(__texture_info, id); | ||||
| switch (info.data_type) { | switch (info.data_type) { | ||||
| case IMAGE_DATA_TYPE_HALF: | case IMAGE_DATA_TYPE_HALF: | ||||
| return TextureInterpolator<half>::interp(info, x, y); | return TextureInterpolator<half>::interp(info, x, y); | ||||
| case IMAGE_DATA_TYPE_BYTE: | case IMAGE_DATA_TYPE_BYTE: | ||||
| ▲ Show 20 Lines • Show All 66 Lines • Show Last 20 Lines | |||||