Cycles: Cleanup, use explicit comparison with NULL
[blender.git] / intern / cycles / kernel / bvh / bvh_local.h
1 /*
2  * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
3  * and code copyright 2009-2012 Intel Corporation
4  *
5  * Modifications Copyright 2011-2013, Blender Foundation.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #ifdef __QBVH__
21 #  include "kernel/bvh/qbvh_local.h"
22 #  ifdef __KERNEL_AVX2__
23 #    include "kernel/bvh/obvh_local.h"
24 #  endif
25 #endif
26
27 #if BVH_FEATURE(BVH_HAIR)
28 #  define NODE_INTERSECT bvh_node_intersect
29 #else
30 #  define NODE_INTERSECT bvh_aligned_node_intersect
31 #endif
32
33 /* This is a template BVH traversal function for finding local intersections
34  * around the shading point, for subsurface scattering and bevel. We disable
35  * various features for performance, and for instanced objects avoid traversing
36  * other parts of the scene.
37  *
38  * BVH_MOTION: motion blur rendering
39  *
40  */
41
42 #ifndef __KERNEL_GPU__
43 ccl_device
44 #else
45 ccl_device_inline
46 #endif
47 bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
48                                  const Ray *ray,
49                                  LocalIntersection *local_isect,
50                                  int local_object,
51                                  uint *lcg_state,
52                                  int max_hits)
53 {
54         /* todo:
55          * - test if pushing distance on the stack helps (for non shadow rays)
56          * - separate version for shadow rays
57          * - likely and unlikely for if() statements
58          * - test restrict attribute for pointers
59          */
60
61         /* traversal stack in CUDA thread-local memory */
62         int traversal_stack[BVH_STACK_SIZE];
63         traversal_stack[0] = ENTRYPOINT_SENTINEL;
64
65         /* traversal variables in registers */
66         int stack_ptr = 0;
67         int node_addr = kernel_tex_fetch(__object_node, local_object);
68
69         /* ray parameters in registers */
70         float3 P = ray->P;
71         float3 dir = bvh_clamp_direction(ray->D);
72         float3 idir = bvh_inverse_direction(dir);
73         int object = OBJECT_NONE;
74         float isect_t = ray->t;
75
76         if(local_isect != NULL) {
77                 local_isect->num_hits = 0;
78         }
79         kernel_assert((local_isect == NULL) == (max_hits == 0));
80
81         const int object_flag = kernel_tex_fetch(__object_flag, local_object);
82         if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
83 #if BVH_FEATURE(BVH_MOTION)
84                 Transform ob_itfm;
85                 isect_t = bvh_instance_motion_push(kg,
86                                                    local_object,
87                                                    ray,
88                                                    &P,
89                                                    &dir,
90                                                    &idir,
91                                                    isect_t,
92                                                    &ob_itfm);
93 #else
94                 isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
95 #endif
96                 object = local_object;
97         }
98
99 #if defined(__KERNEL_SSE2__)
100         const shuffle_swap_t shuf_identity = shuffle_swap_identity();
101         const shuffle_swap_t shuf_swap = shuffle_swap_swap();
102
103         const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
104         ssef Psplat[3], idirsplat[3];
105 #  if BVH_FEATURE(BVH_HAIR)
106         ssef tnear(0.0f), tfar(isect_t);
107 #  endif
108         shuffle_swap_t shufflexyz[3];
109
110         Psplat[0] = ssef(P.x);
111         Psplat[1] = ssef(P.y);
112         Psplat[2] = ssef(P.z);
113
114         ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t);
115
116         gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
117 #endif
118
119         /* traversal loop */
120         do {
121                 do {
122                         /* traverse internal nodes */
123                         while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
124                                 int node_addr_child1, traverse_mask;
125                                 float dist[2];
126                                 float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
127
128 #if !defined(__KERNEL_SSE2__)
129                                 traverse_mask = NODE_INTERSECT(kg,
130                                                                P,
131 #  if BVH_FEATURE(BVH_HAIR)
132                                                                dir,
133 #  endif
134                                                                idir,
135                                                                isect_t,
136                                                                node_addr,
137                                                                PATH_RAY_ALL_VISIBILITY,
138                                                                dist);
139 #else // __KERNEL_SSE2__
140                                 traverse_mask = NODE_INTERSECT(kg,
141                                                                P,
142                                                                dir,
143 #  if BVH_FEATURE(BVH_HAIR)
144                                                                tnear,
145                                                                tfar,
146 #  endif
147                                                                tsplat,
148                                                                Psplat,
149                                                                idirsplat,
150                                                                shufflexyz,
151                                                                node_addr,
152                                                                PATH_RAY_ALL_VISIBILITY,
153                                                                dist);
154 #endif // __KERNEL_SSE2__
155
156                                 node_addr = __float_as_int(cnodes.z);
157                                 node_addr_child1 = __float_as_int(cnodes.w);
158
159                                 if(traverse_mask == 3) {
160                                         /* Both children were intersected, push the farther one. */
161                                         bool is_closest_child1 = (dist[1] < dist[0]);
162                                         if(is_closest_child1) {
163                                                 int tmp = node_addr;
164                                                 node_addr = node_addr_child1;
165                                                 node_addr_child1 = tmp;
166                                         }
167
168                                         ++stack_ptr;
169                                         kernel_assert(stack_ptr < BVH_STACK_SIZE);
170                                         traversal_stack[stack_ptr] = node_addr_child1;
171                                 }
172                                 else {
173                                         /* One child was intersected. */
174                                         if(traverse_mask == 2) {
175                                                 node_addr = node_addr_child1;
176                                         }
177                                         else if(traverse_mask == 0) {
178                                                 /* Neither child was intersected. */
179                                                 node_addr = traversal_stack[stack_ptr];
180                                                 --stack_ptr;
181                                         }
182                                 }
183                         }
184
185                         /* if node is leaf, fetch triangle list */
186                         if(node_addr < 0) {
187                                 float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
188                                 int prim_addr = __float_as_int(leaf.x);
189
190                                 const int prim_addr2 = __float_as_int(leaf.y);
191                                 const uint type = __float_as_int(leaf.w);
192
193                                 /* pop */
194                                 node_addr = traversal_stack[stack_ptr];
195                                 --stack_ptr;
196
197                                 /* primitive intersection */
198                                 switch(type & PRIMITIVE_ALL) {
199                                         case PRIMITIVE_TRIANGLE: {
200                                                 /* intersect ray against primitive */
201                                                 for(; prim_addr < prim_addr2; prim_addr++) {
202                                                         kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
203                                                         if(triangle_intersect_local(kg,
204                                                                                     local_isect,
205                                                                                     P,
206                                                                                     dir,
207                                                                                     object,
208                                                                                     local_object,
209                                                                                     prim_addr,
210                                                                                     isect_t,
211                                                                                     lcg_state,
212                                                                                     max_hits)) {
213                                                                 return true;
214                                                         }
215                                                 }
216                                                 break;
217                                         }
218 #if BVH_FEATURE(BVH_MOTION)
219                                         case PRIMITIVE_MOTION_TRIANGLE: {
220                                                 /* intersect ray against primitive */
221                                                 for(; prim_addr < prim_addr2; prim_addr++) {
222                                                         kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
223                                                         if(motion_triangle_intersect_local(kg,
224                                                                                            local_isect,
225                                                                                            P,
226                                                                                            dir,
227                                                                                            ray->time,
228                                                                                            object,
229                                                                                            local_object,
230                                                                                            prim_addr,
231                                                                                            isect_t,
232                                                                                            lcg_state,
233                                                                                            max_hits)) {
234                                                                 return true;
235                                                         }
236                                                 }
237                                                 break;
238                                         }
239 #endif
240                                         default: {
241                                                 break;
242                                         }
243                                 }
244                         }
245                 } while(node_addr != ENTRYPOINT_SENTINEL);
246         } while(node_addr != ENTRYPOINT_SENTINEL);
247
248         return false;
249 }
250
251 ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
252                                          const Ray *ray,
253                                          LocalIntersection *local_isect,
254                                          int local_object,
255                                          uint *lcg_state,
256                                          int max_hits)
257 {
258         switch(kernel_data.bvh.bvh_layout) {
259 #ifdef __KERNEL_AVX2__
260                 case BVH_LAYOUT_BVH8:
261                         return BVH_FUNCTION_FULL_NAME(OBVH)(kg,
262                                                             ray,
263                                                             local_isect,
264                                                             local_object,
265                                                             lcg_state,
266                                                             max_hits);
267 #endif
268 #ifdef __QBVH__
269                 case BVH_LAYOUT_BVH4:
270                         return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
271                                                             ray,
272                                                             local_isect,
273                                                             local_object,
274                                                             lcg_state,
275                                                             max_hits);
276 #endif
277                 case BVH_LAYOUT_BVH2:
278                         return BVH_FUNCTION_FULL_NAME(BVH)(kg,
279                                                            ray,
280                                                            local_isect,
281                                                            local_object,
282                                                            lcg_state,
283                                                            max_hits);
284         }
285         kernel_assert(!"Should not happen");
286         return false;
287 }
288
289 #undef BVH_FUNCTION_NAME
290 #undef BVH_FUNCTION_FEATURES
291 #undef NODE_INTERSECT