ClangFormat: apply to source, most of intern
[blender.git] / intern / cycles / kernel / kernels / cuda / kernel_cuda_image.h
1 /*
2  * Copyright 2017 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* w0, w1, w2, and w3 are the four cubic B-spline basis functions. */
18 ccl_device float cubic_w0(float a)
19 {
20   return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f);
21 }
22
23 ccl_device float cubic_w1(float a)
24 {
25   return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f);
26 }
27
28 ccl_device float cubic_w2(float a)
29 {
30   return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f);
31 }
32
33 ccl_device float cubic_w3(float a)
34 {
35   return (1.0f / 6.0f) * (a * a * a);
36 }
37
38 /* g0 and g1 are the two amplitude functions. */
39 ccl_device float cubic_g0(float a)
40 {
41   return cubic_w0(a) + cubic_w1(a);
42 }
43
44 ccl_device float cubic_g1(float a)
45 {
46   return cubic_w2(a) + cubic_w3(a);
47 }
48
49 /* h0 and h1 are the two offset functions */
50 ccl_device float cubic_h0(float a)
51 {
52   /* Note +0.5 offset to compensate for CUDA linear filtering convention. */
53   return -1.0f + cubic_w1(a) / (cubic_w0(a) + cubic_w1(a)) + 0.5f;
54 }
55
56 ccl_device float cubic_h1(float a)
57 {
58   return 1.0f + cubic_w3(a) / (cubic_w2(a) + cubic_w3(a)) + 0.5f;
59 }
60
61 /* Fast bicubic texture lookup using 4 bilinear lookups, adapted from CUDA samples. */
62 template<typename T>
63 ccl_device T
64 kernel_tex_image_interp_bicubic(const TextureInfo &info, CUtexObject tex, float x, float y)
65 {
66   x = (x * info.width) - 0.5f;
67   y = (y * info.height) - 0.5f;
68
69   float px = floor(x);
70   float py = floor(y);
71   float fx = x - px;
72   float fy = y - py;
73
74   float g0x = cubic_g0(fx);
75   float g1x = cubic_g1(fx);
76   float x0 = (px + cubic_h0(fx)) / info.width;
77   float x1 = (px + cubic_h1(fx)) / info.width;
78   float y0 = (py + cubic_h0(fy)) / info.height;
79   float y1 = (py + cubic_h1(fy)) / info.height;
80
81   return cubic_g0(fy) * (g0x * tex2D<T>(tex, x0, y0) + g1x * tex2D<T>(tex, x1, y0)) +
82          cubic_g1(fy) * (g0x * tex2D<T>(tex, x0, y1) + g1x * tex2D<T>(tex, x1, y1));
83 }
84
85 /* Fast tricubic texture lookup using 8 trilinear lookups. */
86 template<typename T>
87 ccl_device T kernel_tex_image_interp_bicubic_3d(
88     const TextureInfo &info, CUtexObject tex, float x, float y, float z)
89 {
90   x = (x * info.width) - 0.5f;
91   y = (y * info.height) - 0.5f;
92   z = (z * info.depth) - 0.5f;
93
94   float px = floor(x);
95   float py = floor(y);
96   float pz = floor(z);
97   float fx = x - px;
98   float fy = y - py;
99   float fz = z - pz;
100
101   float g0x = cubic_g0(fx);
102   float g1x = cubic_g1(fx);
103   float g0y = cubic_g0(fy);
104   float g1y = cubic_g1(fy);
105   float g0z = cubic_g0(fz);
106   float g1z = cubic_g1(fz);
107
108   float x0 = (px + cubic_h0(fx)) / info.width;
109   float x1 = (px + cubic_h1(fx)) / info.width;
110   float y0 = (py + cubic_h0(fy)) / info.height;
111   float y1 = (py + cubic_h1(fy)) / info.height;
112   float z0 = (pz + cubic_h0(fz)) / info.depth;
113   float z1 = (pz + cubic_h1(fz)) / info.depth;
114
115   return g0z * (g0y * (g0x * tex3D<T>(tex, x0, y0, z0) + g1x * tex3D<T>(tex, x1, y0, z0)) +
116                 g1y * (g0x * tex3D<T>(tex, x0, y1, z0) + g1x * tex3D<T>(tex, x1, y1, z0))) +
117          g1z * (g0y * (g0x * tex3D<T>(tex, x0, y0, z1) + g1x * tex3D<T>(tex, x1, y0, z1)) +
118                 g1y * (g0x * tex3D<T>(tex, x0, y1, z1) + g1x * tex3D<T>(tex, x1, y1, z1)));
119 }
120
121 ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y)
122 {
123   const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
124   CUtexObject tex = (CUtexObject)info.data;
125
126   /* float4, byte4, ushort4 and half4 */
127   const int texture_type = kernel_tex_type(id);
128   if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
129       texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
130     if (info.interpolation == INTERPOLATION_CUBIC) {
131       return kernel_tex_image_interp_bicubic<float4>(info, tex, x, y);
132     }
133     else {
134       return tex2D<float4>(tex, x, y);
135     }
136   }
137   /* float, byte and half */
138   else {
139     float f;
140
141     if (info.interpolation == INTERPOLATION_CUBIC) {
142       f = kernel_tex_image_interp_bicubic<float>(info, tex, x, y);
143     }
144     else {
145       f = tex2D<float>(tex, x, y);
146     }
147
148     return make_float4(f, f, f, 1.0f);
149   }
150 }
151
152 ccl_device float4 kernel_tex_image_interp_3d(
153     KernelGlobals *kg, int id, float x, float y, float z, InterpolationType interp)
154 {
155   const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
156   CUtexObject tex = (CUtexObject)info.data;
157   uint interpolation = (interp == INTERPOLATION_NONE) ? info.interpolation : interp;
158
159   const int texture_type = kernel_tex_type(id);
160   if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
161       texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
162     if (interpolation == INTERPOLATION_CUBIC) {
163       return kernel_tex_image_interp_bicubic_3d<float4>(info, tex, x, y, z);
164     }
165     else {
166       return tex3D<float4>(tex, x, y, z);
167     }
168   }
169   else {
170     float f;
171
172     if (interpolation == INTERPOLATION_CUBIC) {
173       f = kernel_tex_image_interp_bicubic_3d<float>(info, tex, x, y, z);
174     }
175     else {
176       f = tex3D<float>(tex, x, y, z);
177     }
178
179     return make_float4(f, f, f, 1.0f);
180   }
181 }