Blender V4.3
cycles/kernel/device/oneapi/image.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021-2022 Intel Corporation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
6
7/* For oneAPI implementation we do manual lookup and interpolation. */
8/* TODO: share implementation with ../cpu/image.h. */
9
10template<typename T> ccl_device_forceinline T tex_fetch(const TextureInfo &info, int index)
11{
12 return reinterpret_cast<ccl_global T *>(info.data)[index];
13}
14
16{
17 x %= width;
18 if (x < 0) {
19 x += width;
20 }
21 return x;
22}
23
25{
26 return clamp(x, 0, width - 1);
27}
28
30{
31 const int m = abs(x + (x < 0)) % (2 * width);
32 if (m >= width) {
33 return 2 * width - m - 1;
34 }
35 return m;
36}
37
38ccl_device_inline float4 svm_image_texture_read(const TextureInfo &info, int x, int y, int z)
39{
40 const int data_offset = x + info.width * y + info.width * info.height * z;
41 const int texture_type = info.data_type;
42
43 /* Float4 */
44 if (texture_type == IMAGE_DATA_TYPE_FLOAT4) {
45 return tex_fetch<float4>(info, data_offset);
46 }
47 /* Byte4 */
48 else if (texture_type == IMAGE_DATA_TYPE_BYTE4) {
49 uchar4 r = tex_fetch<uchar4>(info, data_offset);
50 float f = 1.0f / 255.0f;
51 return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
52 }
53 /* Ushort4 */
54 else if (texture_type == IMAGE_DATA_TYPE_USHORT4) {
55 ushort4 r = tex_fetch<ushort4>(info, data_offset);
56 float f = 1.0f / 65535.f;
57 return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
58 }
59 /* Float */
60 else if (texture_type == IMAGE_DATA_TYPE_FLOAT) {
61 float f = tex_fetch<float>(info, data_offset);
62 return make_float4(f, f, f, 1.0f);
63 }
64 /* UShort */
65 else if (texture_type == IMAGE_DATA_TYPE_USHORT) {
66 ushort r = tex_fetch<ushort>(info, data_offset);
67 float f = r * (1.0f / 65535.0f);
68 return make_float4(f, f, f, 1.0f);
69 }
70 else if (texture_type == IMAGE_DATA_TYPE_HALF) {
71 float f = tex_fetch<half>(info, data_offset);
72 return make_float4(f, f, f, 1.0f);
73 }
74 else if (texture_type == IMAGE_DATA_TYPE_HALF4) {
75 half4 r = tex_fetch<half4>(info, data_offset);
76 return make_float4(r.x, r.y, r.z, r.w);
77 }
78 /* Byte */
79 else {
80 uchar r = tex_fetch<uchar>(info, data_offset);
81 float f = r * (1.0f / 255.0f);
82 return make_float4(f, f, f, 1.0f);
83 }
84}
85
86ccl_device_inline float4 svm_image_texture_read_2d(int id, int x, int y)
87{
88 const TextureInfo &info = kernel_data_fetch(texture_info, id);
89
90 /* Wrap */
91 if (info.extension == EXTENSION_REPEAT) {
94 }
95 else if (info.extension == EXTENSION_EXTEND) {
98 }
99 else if (info.extension == EXTENSION_MIRROR) {
102 }
103 else {
104 if (x < 0 || x >= info.width || y < 0 || y >= info.height) {
105 return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
106 }
107 }
108
109 return svm_image_texture_read(info, x, y, 0);
110}
111
112ccl_device_inline float4 svm_image_texture_read_3d(int id, int x, int y, int z)
113{
114 const TextureInfo &info = kernel_data_fetch(texture_info, id);
115
116 /* Wrap */
117 if (info.extension == EXTENSION_REPEAT) {
121 }
122 else if (info.extension == EXTENSION_EXTEND) {
126 }
127 else if (info.extension == EXTENSION_MIRROR) {
131 }
132 else {
133 if (x < 0 || x >= info.width || y < 0 || y >= info.height || z < 0 || z >= info.depth) {
134 return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
135 }
136 }
137
138 return svm_image_texture_read(info, x, y, z);
139}
140
141static float svm_image_texture_frac(float x, int *ix)
142{
143 int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0);
144 *ix = i;
145 return x - (float)i;
146}
147
148#define SET_CUBIC_SPLINE_WEIGHTS(u, t) \
149 { \
150 u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \
151 u[1] = ((0.5f * t - 1.0f) * t) * t + (2.0f / 3.0f); \
152 u[2] = ((-0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f / 6.0f); \
153 u[3] = (1.0f / 6.0f) * t * t * t; \
154 } \
155 (void)0
156
157ccl_device float4 kernel_tex_image_interp(KernelGlobals, int id, float x, float y)
158{
159 const TextureInfo &info = kernel_data_fetch(texture_info, id);
160
162 /* Closest interpolation. */
163 int ix, iy;
164 svm_image_texture_frac(x * info.width, &ix);
165 svm_image_texture_frac(y * info.height, &iy);
166
167 return svm_image_texture_read_2d(id, ix, iy);
168 }
169 else if (info.interpolation == INTERPOLATION_LINEAR) {
170 /* Bilinear interpolation. */
171 int ix, iy;
172 float tx = svm_image_texture_frac(x * info.width - 0.5f, &ix);
173 float ty = svm_image_texture_frac(y * info.height - 0.5f, &iy);
174
175 float4 r;
176 r = (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_2d(id, ix, iy);
177 r += (1.0f - ty) * tx * svm_image_texture_read_2d(id, ix + 1, iy);
178 r += ty * (1.0f - tx) * svm_image_texture_read_2d(id, ix, iy + 1);
179 r += ty * tx * svm_image_texture_read_2d(id, ix + 1, iy + 1);
180 return r;
181 }
182 else {
183 /* Bicubic interpolation. */
184 int ix, iy;
185 float tx = svm_image_texture_frac(x * info.width - 0.5f, &ix);
186 float ty = svm_image_texture_frac(y * info.height - 0.5f, &iy);
187
188 float u[4], v[4];
191
192 float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
193
194 for (int y = 0; y < 4; y++) {
195 for (int x = 0; x < 4; x++) {
196 float weight = u[x] * v[y];
197 r += weight * svm_image_texture_read_2d(id, ix + x - 1, iy + y - 1);
198 }
199 }
200 return r;
201 }
202}
203
204#ifdef WITH_NANOVDB
205template<typename TexT, typename OutT> struct NanoVDBInterpolator {
206
207 static ccl_always_inline float read(float r)
208 {
209 return r;
210 }
211
212 static ccl_always_inline float4 read(const packed_float3 r)
213 {
214 return make_float4(r.x, r.y, r.z, 1.0f);
215 }
216
217 template<typename Acc>
218 static ccl_always_inline OutT interp_3d_closest(const Acc &acc, float x, float y, float z)
219 {
220 const nanovdb::Coord coord(int32_t(rintf(x)), int32_t(rintf(y)), int32_t(rintf(z)));
221 return read(acc.getValue(coord));
222 }
223
224 template<typename Acc>
225 static ccl_always_inline OutT interp_3d_linear(const Acc &acc, float x, float y, float z)
226 {
227 int ix, iy, iz;
228 const float tx = svm_image_texture_frac(x - 0.5f, &ix);
229 const float ty = svm_image_texture_frac(y - 0.5f, &iy);
230 const float tz = svm_image_texture_frac(z - 0.5f, &iz);
231
232 return mix(mix(mix(read(acc.getValue(nanovdb::Coord(ix, iy, iz))),
233 read(acc.getValue(nanovdb::Coord(ix, iy, iz + 1))),
234 tz),
235 mix(read(acc.getValue(nanovdb::Coord(ix, iy + 1, iz + 1))),
236 read(acc.getValue(nanovdb::Coord(ix, iy + 1, iz))),
237 1.0f - tz),
238 ty),
239 mix(mix(read(acc.getValue(nanovdb::Coord(ix + 1, iy + 1, iz))),
240 read(acc.getValue(nanovdb::Coord(ix + 1, iy + 1, iz + 1))),
241 tz),
242 mix(read(acc.getValue(nanovdb::Coord(ix + 1, iy, iz + 1))),
243 read(acc.getValue(nanovdb::Coord(ix + 1, iy, iz))),
244 1.0f - tz),
245 1.0f - ty),
246 tx);
247 }
248
249 /* Tricubic b-spline interpolation. */
250 template<typename Acc>
251 static ccl_always_inline OutT interp_3d_cubic(const Acc &acc, float x, float y, float z)
252 {
253 int ix, iy, iz;
254 int nix, niy, niz;
255 int pix, piy, piz;
256 int nnix, nniy, nniz;
257
258 /* A -0.5 offset is used to center the cubic samples around the sample point. */
259 const float tx = svm_image_texture_frac(x - 0.5f, &ix);
260 const float ty = svm_image_texture_frac(y - 0.5f, &iy);
261 const float tz = svm_image_texture_frac(z - 0.5f, &iz);
262
263 pix = ix - 1;
264 piy = iy - 1;
265 piz = iz - 1;
266 nix = ix + 1;
267 niy = iy + 1;
268 niz = iz + 1;
269 nnix = ix + 2;
270 nniy = iy + 2;
271 nniz = iz + 2;
272
273 const int xc[4] = {pix, ix, nix, nnix};
274 const int yc[4] = {piy, iy, niy, nniy};
275 const int zc[4] = {piz, iz, niz, nniz};
276 float u[4], v[4], w[4];
277
278 /* Some helper macros to keep code size reasonable.
279 * Lets the compiler inline all the matrix multiplications.
280 */
281# define DATA(x, y, z) (read(acc.getValue(nanovdb::Coord(xc[x], yc[y], zc[z]))))
282# define COL_TERM(col, row) \
283 (v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \
284 u[3] * DATA(3, col, row)))
285# define ROW_TERM(row) \
286 (w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row)))
287
291
292 /* Actual interpolation. */
293 return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
294
295# undef COL_TERM
296# undef ROW_TERM
297# undef DATA
298 }
299
300 static ccl_always_inline OutT
301 interp_3d(const TextureInfo &info, float x, float y, float z, int interp)
302 {
303 using namespace nanovdb;
304
305 NanoGrid<TexT> *const grid = (NanoGrid<TexT> *)info.data;
306
307 switch (interp) {
309 ReadAccessor<TexT> acc(grid->tree().root());
310 return interp_3d_closest(acc, x, y, z);
311 }
313 CachedReadAccessor<TexT> acc(grid->tree().root());
314 return interp_3d_linear(acc, x, y, z);
315 }
316 default: {
317 CachedReadAccessor<TexT> acc(grid->tree().root());
318 return interp_3d_cubic(acc, x, y, z);
319 }
320 }
321 }
322};
323#endif /* WITH_NANOVDB */
324
326{
327 const TextureInfo &info = kernel_data_fetch(texture_info, id);
328
329 if (info.use_transform_3d) {
330 Transform tfm = info.transform_3d;
331 P = transform_point(&tfm, P);
332 }
333
334 float x = P.x;
335 float y = P.y;
336 float z = P.z;
337
338 uint interpolation = (interp == INTERPOLATION_NONE) ? info.interpolation : interp;
339
340#ifdef WITH_NANOVDB
342 const float f = NanoVDBInterpolator<float, float>::interp_3d(info, x, y, z, interpolation);
343 return make_float4(f, f, f, 1.0f);
344 }
345 else if (info.data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
346 return NanoVDBInterpolator<packed_float3, float4>::interp_3d(info, x, y, z, interpolation);
347 }
348 else if (info.data_type == IMAGE_DATA_TYPE_NANOVDB_FPN) {
349 const float f = NanoVDBInterpolator<nanovdb::FpN, float>::interp_3d(
350 info, x, y, z, interpolation);
351 return make_float4(f, f, f, 1.0f);
352 }
353 else if (info.data_type == IMAGE_DATA_TYPE_NANOVDB_FP16) {
354 const float f = NanoVDBInterpolator<nanovdb::Fp16, float>::interp_3d(
355 info, x, y, z, interpolation);
356 return make_float4(f, f, f, 1.0f);
357 }
358#else
363 {
364 return make_float4(
366 }
367#endif
368 else {
369 x *= info.width;
370 y *= info.height;
371 z *= info.depth;
372 }
373
374 if (interpolation == INTERPOLATION_CLOSEST) {
375 /* Closest interpolation. */
376 int ix, iy, iz;
380
381 return svm_image_texture_read_3d(id, ix, iy, iz);
382 }
383 else if (interpolation == INTERPOLATION_LINEAR) {
384 /* Trilinear interpolation. */
385 int ix, iy, iz;
386 float tx = svm_image_texture_frac(x - 0.5f, &ix);
387 float ty = svm_image_texture_frac(y - 0.5f, &iy);
388 float tz = svm_image_texture_frac(z - 0.5f, &iz);
389
390 float4 r;
391 r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(id, ix, iy, iz);
392 r += (1.0f - tz) * (1.0f - ty) * tx * svm_image_texture_read_3d(id, ix + 1, iy, iz);
393 r += (1.0f - tz) * ty * (1.0f - tx) * svm_image_texture_read_3d(id, ix, iy + 1, iz);
394 r += (1.0f - tz) * ty * tx * svm_image_texture_read_3d(id, ix + 1, iy + 1, iz);
395
396 r += tz * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(id, ix, iy, iz + 1);
397 r += tz * (1.0f - ty) * tx * svm_image_texture_read_3d(id, ix + 1, iy, iz + 1);
398 r += tz * ty * (1.0f - tx) * svm_image_texture_read_3d(id, ix, iy + 1, iz + 1);
399 r += tz * ty * tx * svm_image_texture_read_3d(id, ix + 1, iy + 1, iz + 1);
400 return r;
401 }
402 else {
403 /* Tri-cubic interpolation. */
404 int ix, iy, iz;
405 float tx = svm_image_texture_frac(x - 0.5f, &ix);
406 float ty = svm_image_texture_frac(y - 0.5f, &iy);
407 float tz = svm_image_texture_frac(z - 0.5f, &iz);
408
409 float u[4], v[4], w[4];
413
414 float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
415
416 for (int z = 0; z < 4; z++) {
417 for (int y = 0; y < 4; y++) {
418 for (int x = 0; x < 4; x++) {
419 float weight = u[x] * v[y] * w[z];
420 r += weight * svm_image_texture_read_3d(id, ix + x - 1, iy + y - 1, iz + z - 1);
421 }
422 }
423 }
424 return r;
425 }
426}
427
428#undef SET_CUBIC_SPLINE_WEIGHTS
429
unsigned char uchar
unsigned short ushort
unsigned int uint
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
#define SET_CUBIC_SPLINE_WEIGHTS(u, t)
#define ROW_TERM(row)
CCL_NAMESPACE_BEGIN ccl_device_forceinline T tex_fetch(const TextureInfo &info, int index)
#define SET_CUBIC_SPLINE_WEIGHTS(u, t)
static float svm_image_texture_frac(float x, int *ix)
ccl_device_inline float4 svm_image_texture_read_2d(int id, int x, int y)
ccl_device_inline float4 svm_image_texture_read_3d(int id, int x, int y, int z)
ccl_device_inline int svm_image_texture_wrap_periodic(int x, int width)
ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals, int id, float3 P, int interp)
ccl_device_inline int svm_image_texture_wrap_clamp(int x, int width)
ccl_device float4 kernel_tex_image_interp(KernelGlobals, int id, float x, float y)
ccl_device_inline float4 svm_image_texture_read(const TextureInfo &info, int x, int y, int z)
ccl_device_inline int svm_image_texture_wrap_mirror(int x, int width)
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define ccl_device_forceinline
#define ccl_device
#define ccl_device_inline
#define ccl_global
#define CCL_NAMESPACE_END
ccl_device_forceinline float4 make_float4(const float x, const float y, const float z, const float w)
#define ccl_always_inline
draw_view in_light_buf[] float
#define mix(a, b, c)
Definition hash.h:36
ccl_device_inline float2 interp(const float2 a, const float2 b, float t)
VecBase< float, 4 > float4
signed int int32_t
Definition stdint.h:77
uint64_t data
uint use_transform_3d
uint interpolation
Transform transform_3d
Definition half.h:61
half x
Definition half.h:62
half w
Definition half.h:62
half z
Definition half.h:62
half y
Definition half.h:62
uchar z
uchar w
uchar x
uchar y
uint16_t w
uint16_t y
uint16_t z
uint16_t x
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
Definition transform.h:63
ccl_device_inline int abs(int x)
Definition util/math.h:120
ccl_device_inline int float_to_int(float f)
Definition util/math.h:424
ccl_device_inline int clamp(int a, int mn, int mx)
Definition util/math.h:379
@ IMAGE_DATA_TYPE_FLOAT
@ IMAGE_DATA_TYPE_NANOVDB_FP16
@ IMAGE_DATA_TYPE_FLOAT4
@ IMAGE_DATA_TYPE_USHORT4
@ IMAGE_DATA_TYPE_USHORT
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT3
@ IMAGE_DATA_TYPE_HALF
@ IMAGE_DATA_TYPE_BYTE4
@ IMAGE_DATA_TYPE_HALF4
@ IMAGE_DATA_TYPE_NANOVDB_FPN
#define TEX_IMAGE_MISSING_R
#define TEX_IMAGE_MISSING_B
@ INTERPOLATION_LINEAR
@ INTERPOLATION_NONE
@ INTERPOLATION_CLOSEST
@ EXTENSION_REPEAT
@ EXTENSION_EXTEND
@ EXTENSION_MIRROR
#define TEX_IMAGE_MISSING_A
#define TEX_IMAGE_MISSING_G