ClangFormat: apply to source, most of intern
[blender.git] / intern / cycles / kernel / kernels / opencl / kernel_opencl_image.h
1 /*
2  * Copyright 2016 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 /* For OpenCL we do manual lookup and interpolation. */
18
19 ccl_device_inline ccl_global TextureInfo *kernel_tex_info(KernelGlobals *kg, uint id)
20 {
21   const uint tex_offset = id
22 #define KERNEL_TEX(type, name) +1
23 #include "kernel/kernel_textures.h"
24       ;
25
26   return &((ccl_global TextureInfo *)kg->buffers[0])[tex_offset];
27 }
28
29 #define tex_fetch(type, info, index) \
30   ((ccl_global type *)(kg->buffers[info->cl_buffer] + info->data))[(index)]
31
32 ccl_device_inline int svm_image_texture_wrap_periodic(int x, int width)
33 {
34   x %= width;
35   if (x < 0)
36     x += width;
37   return x;
38 }
39
40 ccl_device_inline int svm_image_texture_wrap_clamp(int x, int width)
41 {
42   return clamp(x, 0, width - 1);
43 }
44
45 ccl_device_inline float4 svm_image_texture_read(KernelGlobals *kg,
46                                                 const ccl_global TextureInfo *info,
47                                                 int id,
48                                                 int offset)
49 {
50   const int texture_type = kernel_tex_type(id);
51
52   /* Float4 */
53   if (texture_type == IMAGE_DATA_TYPE_FLOAT4) {
54     return tex_fetch(float4, info, offset);
55   }
56   /* Byte4 */
57   else if (texture_type == IMAGE_DATA_TYPE_BYTE4) {
58     uchar4 r = tex_fetch(uchar4, info, offset);
59     float f = 1.0f / 255.0f;
60     return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
61   }
62   /* Ushort4 */
63   else if (texture_type == IMAGE_DATA_TYPE_USHORT4) {
64     ushort4 r = tex_fetch(ushort4, info, offset);
65     float f = 1.0f / 65535.f;
66     return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
67   }
68   /* Float */
69   else if (texture_type == IMAGE_DATA_TYPE_FLOAT) {
70     float f = tex_fetch(float, info, offset);
71     return make_float4(f, f, f, 1.0f);
72   }
73   /* UShort */
74   else if (texture_type == IMAGE_DATA_TYPE_USHORT) {
75     ushort r = tex_fetch(ushort, info, offset);
76     float f = r * (1.0f / 65535.0f);
77     return make_float4(f, f, f, 1.0f);
78   }
79   /* Byte */
80 #ifdef cl_khr_fp16
81   /* half and half4 are optional in OpenCL */
82   else if (texture_type == IMAGE_DATA_TYPE_HALF) {
83     float f = tex_fetch(half, info, offset);
84     return make_float4(f, f, f, 1.0f);
85   }
86   else if (texture_type == IMAGE_DATA_TYPE_HALF4) {
87     half4 r = tex_fetch(half4, info, offset);
88     return make_float4(r.x, r.y, r.z, r.w);
89   }
90 #endif
91   else {
92     uchar r = tex_fetch(uchar, info, offset);
93     float f = r * (1.0f / 255.0f);
94     return make_float4(f, f, f, 1.0f);
95   }
96 }
97
98 ccl_device_inline float4 svm_image_texture_read_2d(KernelGlobals *kg, int id, int x, int y)
99 {
100   const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
101
102   /* Wrap */
103   if (info->extension == EXTENSION_REPEAT) {
104     x = svm_image_texture_wrap_periodic(x, info->width);
105     y = svm_image_texture_wrap_periodic(y, info->height);
106   }
107   else {
108     x = svm_image_texture_wrap_clamp(x, info->width);
109     y = svm_image_texture_wrap_clamp(y, info->height);
110   }
111
112   int offset = x + info->width * y;
113   return svm_image_texture_read(kg, info, id, offset);
114 }
115
116 ccl_device_inline float4 svm_image_texture_read_3d(KernelGlobals *kg, int id, int x, int y, int z)
117 {
118   const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
119
120   /* Wrap */
121   if (info->extension == EXTENSION_REPEAT) {
122     x = svm_image_texture_wrap_periodic(x, info->width);
123     y = svm_image_texture_wrap_periodic(y, info->height);
124     z = svm_image_texture_wrap_periodic(z, info->depth);
125   }
126   else {
127     x = svm_image_texture_wrap_clamp(x, info->width);
128     y = svm_image_texture_wrap_clamp(y, info->height);
129     z = svm_image_texture_wrap_clamp(z, info->depth);
130   }
131
132   int offset = x + info->width * y + info->width * info->height * z;
133   return svm_image_texture_read(kg, info, id, offset);
134 }
135
136 ccl_device_inline float svm_image_texture_frac(float x, int *ix)
137 {
138   int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0);
139   *ix = i;
140   return x - (float)i;
141 }
142
143 #define SET_CUBIC_SPLINE_WEIGHTS(u, t) \
144   { \
145     u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \
146     u[1] = ((0.5f * t - 1.0f) * t) * t + (2.0f / 3.0f); \
147     u[2] = ((-0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f / 6.0f); \
148     u[3] = (1.0f / 6.0f) * t * t * t; \
149   } \
150   (void)0
151
152 ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y)
153 {
154   const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
155
156   if (info->extension == EXTENSION_CLIP) {
157     if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
158       return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
159     }
160   }
161
162   if (info->interpolation == INTERPOLATION_CLOSEST) {
163     /* Closest interpolation. */
164     int ix, iy;
165     svm_image_texture_frac(x * info->width, &ix);
166     svm_image_texture_frac(y * info->height, &iy);
167
168     return svm_image_texture_read_2d(kg, id, ix, iy);
169   }
170   else if (info->interpolation == INTERPOLATION_LINEAR) {
171     /* Bilinear interpolation. */
172     int ix, iy;
173     float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
174     float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
175
176     float4 r;
177     r = (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_2d(kg, id, ix, iy);
178     r += (1.0f - ty) * tx * svm_image_texture_read_2d(kg, id, ix + 1, iy);
179     r += ty * (1.0f - tx) * svm_image_texture_read_2d(kg, id, ix, iy + 1);
180     r += ty * tx * svm_image_texture_read_2d(kg, id, ix + 1, iy + 1);
181     return r;
182   }
183   else {
184     /* Bicubic interpolation. */
185     int ix, iy;
186     float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
187     float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
188
189     float u[4], v[4];
190     SET_CUBIC_SPLINE_WEIGHTS(u, tx);
191     SET_CUBIC_SPLINE_WEIGHTS(v, ty);
192
193     float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
194
195     for (int y = 0; y < 4; y++) {
196       for (int x = 0; x < 4; x++) {
197         float weight = u[x] * v[y];
198         r += weight * svm_image_texture_read_2d(kg, id, ix + x - 1, iy + y - 1);
199       }
200     }
201     return r;
202   }
203 }
204
205 ccl_device float4
206 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x, float y, float z, int interp)
207 {
208   const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
209
210   if (info->extension == EXTENSION_CLIP) {
211     if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
212       return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
213     }
214   }
215
216   uint interpolation = (interp == INTERPOLATION_NONE) ? info->interpolation : interp;
217
218   if (interpolation == INTERPOLATION_CLOSEST) {
219     /* Closest interpolation. */
220     int ix, iy, iz;
221     svm_image_texture_frac(x * info->width, &ix);
222     svm_image_texture_frac(y * info->height, &iy);
223     svm_image_texture_frac(z * info->depth, &iz);
224
225     return svm_image_texture_read_3d(kg, id, ix, iy, iz);
226   }
227   else if (interpolation == INTERPOLATION_LINEAR) {
228     /* Bilinear interpolation. */
229     int ix, iy, iz;
230     float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
231     float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
232     float tz = svm_image_texture_frac(z * info->depth - 0.5f, &iz);
233
234     float4 r;
235     r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy, iz);
236     r += (1.0f - tz) * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy, iz);
237     r += (1.0f - tz) * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy + 1, iz);
238     r += (1.0f - tz) * ty * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy + 1, iz);
239
240     r += tz * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy, iz + 1);
241     r += tz * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy, iz + 1);
242     r += tz * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy + 1, iz + 1);
243     r += tz * ty * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy + 1, iz + 1);
244     return r;
245   }
246   else {
247     /* Bicubic interpolation. */
248     int ix, iy, iz;
249     float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
250     float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
251     float tz = svm_image_texture_frac(z * info->depth - 0.5f, &iz);
252
253     float u[4], v[4], w[4];
254     SET_CUBIC_SPLINE_WEIGHTS(u, tx);
255     SET_CUBIC_SPLINE_WEIGHTS(v, ty);
256     SET_CUBIC_SPLINE_WEIGHTS(w, tz);
257
258     float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
259
260     for (int z = 0; z < 4; z++) {
261       for (int y = 0; y < 4; y++) {
262         for (int x = 0; x < 4; x++) {
263           float weight = u[x] * v[y] * w[z];
264           r += weight * svm_image_texture_read_3d(kg, id, ix + x - 1, iy + y - 1, iz + z - 1);
265         }
266       }
267     }
268     return r;
269   }
270 }
271
272 #undef SET_CUBIC_SPLINE_WEIGHTS