Cycles: Make all #include statements relative to cycles source directory
[blender.git] / intern / cycles / util / util_half.h
1 /*
2  * Copyright 2011-2013 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 #ifndef __UTIL_HALF_H__
18 #define __UTIL_HALF_H__
19
20 #include "util/util_types.h"
21 #include "util/util_math.h"
22
23 #ifdef __KERNEL_SSE2__
24 #include "util/util_simd.h"
25 #endif
26
27 CCL_NAMESPACE_BEGIN
28
29 /* Half Floats */
30
31 #ifdef __KERNEL_OPENCL__
32
33 #define float4_store_half(h, f, scale) vstore_half4(f * (scale), 0, h);
34
35 #else
36
37 /* CUDA has its own half data type, no need to define then */
38 #ifndef __KERNEL_CUDA__
39 typedef unsigned short half;
40 #endif
41
42 struct half4 { half x, y, z, w; };
43
44 #ifdef __KERNEL_CUDA__
45
46 ccl_device_inline void float4_store_half(half *h, float4 f, float scale)
47 {
48         h[0] = __float2half(f.x * scale);
49         h[1] = __float2half(f.y * scale);
50         h[2] = __float2half(f.z * scale);
51         h[3] = __float2half(f.w * scale);
52 }
53
54 #else
55
56 ccl_device_inline void float4_store_half(half *h, float4 f, float scale)
57 {
58 #ifndef __KERNEL_SSE2__
59         for(int i = 0; i < 4; i++) {
60                 /* optimized float to half for pixels:
61                  * assumes no negative, no nan, no inf, and sets denormal to 0 */
62                 union { uint i; float f; } in;
63                 float fscale = f[i] * scale;
64                 in.f = (fscale > 0.0f)? ((fscale < 65504.0f)? fscale: 65504.0f): 0.0f;
65                 int x = in.i;
66
67                 int absolute = x & 0x7FFFFFFF;
68                 int Z = absolute + 0xC8000000;
69                 int result = (absolute < 0x38800000)? 0: Z;
70                 int rshift = (result >> 13);
71
72                 h[i] = (rshift & 0x7FFF);
73         }
74 #else
75         /* same as above with SSE */
76         ssef fscale = load4f(f) * scale;
77         ssef x = min(max(fscale, 0.0f), 65504.0f);
78
79 #ifdef __KERNEL_AVX2__
80         ssei rpack = _mm_cvtps_ph(x, 0);
81 #else
82         ssei absolute = cast(x) & 0x7FFFFFFF;
83         ssei Z = absolute + 0xC8000000;
84         ssei result = andnot(absolute < 0x38800000, Z);
85         ssei rshift = (result >> 13) & 0x7FFF;
86         ssei rpack = _mm_packs_epi32(rshift, rshift);
87 #endif
88
89         _mm_storel_pi((__m64*)h, _mm_castsi128_ps(rpack));
90 #endif
91 }
92
93 ccl_device_inline float half_to_float(half h)
94 {
95         float f;
96
97         *((int*) &f) = ((h & 0x8000) << 16) | (((h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13);
98
99         return f;
100 }
101
102 ccl_device_inline float4 half4_to_float4(half4 h)
103 {
104         float4 f;
105
106         f.x = half_to_float(h.x);
107         f.y = half_to_float(h.y);
108         f.z = half_to_float(h.z);
109         f.w = half_to_float(h.w);
110
111         return f;
112 }
113
114 ccl_device_inline half float_to_half(float f)
115 {
116         const uint u = __float_as_uint(f);
117         /* Sign bit, shifted to it's position. */
118         uint sign_bit = u & 0x80000000;
119         sign_bit >>= 16;
120         /* Exponent. */
121         uint exponent_bits = u & 0x7f800000;
122         /* Non-sign bits. */
123         uint value_bits = u & 0x7fffffff;
124         value_bits >>= 13;  /* Align mantissa on MSB. */
125         value_bits -= 0x1c000;  /* Adjust bias. */
126         /* Flush-to-zero. */
127         value_bits = (exponent_bits < 0x38800000) ? 0 : value_bits;
128         /* Clamp-to-max. */
129         value_bits = (exponent_bits > 0x47000000) ? 0x7bff : value_bits;
130         /* Denormals-as-zero. */
131         value_bits = (exponent_bits == 0 ? 0 : value_bits);
132         /* Re-insert sign bit and return. */
133         return (value_bits | sign_bit);
134 }
135
136 #endif
137
138 #endif
139
140 CCL_NAMESPACE_END
141
142 #endif /* __UTIL_HALF_H__ */
143