Cysles: Avoid having ShaderData on the stack
[blender.git] / intern / cycles / kernel / geom / geom_bvh.h
1 /*
2  * Adapted from code Copyright 2009-2010 NVIDIA Corporation
3  * Modifications Copyright 2011, Blender Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /* BVH
19  *
20  * Bounding volume hierarchy for ray tracing. We compile different variations
21  * of the same BVH traversal function for faster rendering when some types of
22  * primitives are not needed, using #includes to work around the lack of
23  * C++ templates in OpenCL.
24  *
25  * Originally based on "Understanding the Efficiency of Ray Traversal on GPUs",
26  * the code has been extended and modified to support more primitives and work
27  * with CPU/CUDA/OpenCL. */
28
29 CCL_NAMESPACE_BEGIN
30
31 /* Don't inline intersect functions on GPU, this is faster */
32 #ifdef __KERNEL_GPU__
33 #define ccl_device_intersect ccl_device_noinline
34 #else
35 #define ccl_device_intersect ccl_device_inline
36 #endif
37
38 /* BVH intersection function variations */
39
40 #define BVH_INSTANCING                  1
41 #define BVH_MOTION                              2
42 #define BVH_HAIR                                4
43 #define BVH_HAIR_MINIMUM_WIDTH  8
44
45 #define BVH_NAME_JOIN(x,y) x ## _ ## y
46 #define BVH_NAME_EVAL(x,y) BVH_NAME_JOIN(x,y)
47 #define BVH_FUNCTION_FULL_NAME(prefix) BVH_NAME_EVAL(prefix, BVH_FUNCTION_NAME)
48
49 #define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
50
51 /* Common QBVH functions. */
52 #ifdef __QBVH__
53 #include "geom_qbvh.h"
54 #endif
55
56 /* Regular BVH traversal */
57
58 #define BVH_FUNCTION_NAME bvh_intersect
59 #define BVH_FUNCTION_FEATURES 0
60 #include "geom_bvh_traversal.h"
61
62 #if defined(__INSTANCING__)
63 #define BVH_FUNCTION_NAME bvh_intersect_instancing
64 #define BVH_FUNCTION_FEATURES BVH_INSTANCING
65 #include "geom_bvh_traversal.h"
66 #endif
67
68 #if defined(__HAIR__)
69 #define BVH_FUNCTION_NAME bvh_intersect_hair
70 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
71 #include "geom_bvh_traversal.h"
72 #endif
73
74 #if defined(__OBJECT_MOTION__)
75 #define BVH_FUNCTION_NAME bvh_intersect_motion
76 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
77 #include "geom_bvh_traversal.h"
78 #endif
79
80 #if defined(__HAIR__) && defined(__OBJECT_MOTION__)
81 #define BVH_FUNCTION_NAME bvh_intersect_hair_motion
82 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION
83 #include "geom_bvh_traversal.h"
84 #endif
85
86 /* Subsurface scattering BVH traversal */
87
88 #if defined(__SUBSURFACE__)
89 #define BVH_FUNCTION_NAME bvh_intersect_subsurface
90 #define BVH_FUNCTION_FEATURES 0
91 #include "geom_bvh_subsurface.h"
92 #endif
93
94 #if defined(__SUBSURFACE__) && defined(__INSTANCING__)
95 #define BVH_FUNCTION_NAME bvh_intersect_subsurface_instancing
96 #define BVH_FUNCTION_FEATURES BVH_INSTANCING
97 #include "geom_bvh_subsurface.h"
98 #endif
99
100 #if defined(__SUBSURFACE__) && defined(__HAIR__)
101 #define BVH_FUNCTION_NAME bvh_intersect_subsurface_hair
102 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
103 #include "geom_bvh_subsurface.h"
104 #endif
105
106 #if defined(__SUBSURFACE__) && defined(__OBJECT_MOTION__)
107 #define BVH_FUNCTION_NAME bvh_intersect_subsurface_motion
108 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
109 #include "geom_bvh_subsurface.h"
110 #endif
111
112 #if defined(__SUBSURFACE__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
113 #define BVH_FUNCTION_NAME bvh_intersect_subsurface_hair_motion
114 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION
115 #include "geom_bvh_subsurface.h"
116 #endif
117
118 /* Volume BVH traversal */
119
120 #if defined(__VOLUME__)
121 #define BVH_FUNCTION_NAME bvh_intersect_volume
122 #define BVH_FUNCTION_FEATURES 0
123 #include "geom_bvh_volume.h"
124 #endif
125
126 #if defined(__VOLUME__) && defined(__INSTANCING__)
127 #define BVH_FUNCTION_NAME bvh_intersect_volume_instancing
128 #define BVH_FUNCTION_FEATURES BVH_INSTANCING
129 #include "geom_bvh_volume.h"
130 #endif
131
132 #if defined(__VOLUME__) && defined(__HAIR__)
133 #define BVH_FUNCTION_NAME bvh_intersect_volume_hair
134 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
135 #include "geom_bvh_volume.h"
136 #endif
137
138 #if defined(__VOLUME__) && defined(__OBJECT_MOTION__)
139 #define BVH_FUNCTION_NAME bvh_intersect_volume_motion
140 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
141 #include "geom_bvh_volume.h"
142 #endif
143
144 #if defined(__VOLUME__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
145 #define BVH_FUNCTION_NAME bvh_intersect_volume_hair_motion
146 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION
147 #include "geom_bvh_volume.h"
148 #endif
149
150 /* Record all intersections - Shadow BVH traversal */
151
152 #if defined(__SHADOW_RECORD_ALL__)
153 #define BVH_FUNCTION_NAME bvh_intersect_shadow_all
154 #define BVH_FUNCTION_FEATURES 0
155 #include "geom_bvh_shadow.h"
156 #endif
157
158 #if defined(__SHADOW_RECORD_ALL__) && defined(__INSTANCING__)
159 #define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing
160 #define BVH_FUNCTION_FEATURES BVH_INSTANCING
161 #include "geom_bvh_shadow.h"
162 #endif
163
164 #if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__)
165 #define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
166 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
167 #include "geom_bvh_shadow.h"
168 #endif
169
170 #if defined(__SHADOW_RECORD_ALL__) && defined(__OBJECT_MOTION__)
171 #define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
172 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
173 #include "geom_bvh_shadow.h"
174 #endif
175
176 #if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
177 #define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion
178 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION
179 #include "geom_bvh_shadow.h"
180 #endif
181
182 /* Record all intersections - Volume BVH traversal  */
183
184 #if defined(__VOLUME_RECORD_ALL__)
185 #define BVH_FUNCTION_NAME bvh_intersect_volume_all
186 #define BVH_FUNCTION_FEATURES 0
187 #include "geom_bvh_volume_all.h"
188 #endif
189
190 #if defined(__VOLUME_RECORD_ALL__) && defined(__INSTANCING__)
191 #define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing
192 #define BVH_FUNCTION_FEATURES BVH_INSTANCING
193 #include "geom_bvh_volume_all.h"
194 #endif
195
196 #if defined(__VOLUME_RECORD_ALL__) && defined(__HAIR__)
197 #define BVH_FUNCTION_NAME bvh_intersect_volume_all_hair
198 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
199 #include "geom_bvh_volume_all.h"
200 #endif
201
202 #if defined(__VOLUME_RECORD_ALL__) && defined(__OBJECT_MOTION__)
203 #define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
204 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
205 #include "geom_bvh_volume_all.h"
206 #endif
207
208 #if defined(__VOLUME_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
209 #define BVH_FUNCTION_NAME bvh_intersect_volume_all_hair_motion
210 #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION
211 #include "geom_bvh_volume_all.h"
212 #endif
213
214 #undef BVH_FEATURE
215 #undef BVH_NAME_JOIN
216 #undef BVH_NAME_EVAL
217 #undef BVH_FUNCTION_FULL_NAME
218
219 ccl_device_intersect bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect,
220                                          uint *lcg_state, float difl, float extmax)
221 {
222 #ifdef __OBJECT_MOTION__
223         if(kernel_data.bvh.have_motion) {
224 #ifdef __HAIR__
225                 if(kernel_data.bvh.have_curves)
226                         return bvh_intersect_hair_motion(kg, ray, isect, visibility, lcg_state, difl, extmax);
227 #endif /* __HAIR__ */
228
229                 return bvh_intersect_motion(kg, ray, isect, visibility);
230         }
231 #endif /* __OBJECT_MOTION__ */
232
233 #ifdef __HAIR__ 
234         if(kernel_data.bvh.have_curves)
235                 return bvh_intersect_hair(kg, ray, isect, visibility, lcg_state, difl, extmax);
236 #endif /* __HAIR__ */
237
238 #ifdef __KERNEL_CPU__
239
240 #ifdef __INSTANCING__
241         if(kernel_data.bvh.have_instancing)
242                 return bvh_intersect_instancing(kg, ray, isect, visibility);
243 #endif /* __INSTANCING__ */
244
245         return bvh_intersect(kg, ray, isect, visibility);
246 #else /* __KERNEL_CPU__ */
247
248 #ifdef __INSTANCING__
249         return bvh_intersect_instancing(kg, ray, isect, visibility);
250 #else
251         return bvh_intersect(kg, ray, isect, visibility);
252 #endif /* __INSTANCING__ */
253
254 #endif /* __KERNEL_CPU__ */
255 }
256
257 #ifdef __SUBSURFACE__
258 ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
259                                                      const Ray *ray,
260                                                      SubsurfaceIntersection *ss_isect,
261                                                      int subsurface_object,
262                                                      uint *lcg_state,
263                                                      int max_hits)
264 {
265 #ifdef __OBJECT_MOTION__
266         if(kernel_data.bvh.have_motion) {
267 #ifdef __HAIR__
268                 if(kernel_data.bvh.have_curves) {
269                         return bvh_intersect_subsurface_hair_motion(kg,
270                                                                     ray,
271                                                                     ss_isect,
272                                                                     subsurface_object,
273                                                                     lcg_state,
274                                                                     max_hits);
275                 }
276 #endif /* __HAIR__ */
277
278                 return bvh_intersect_subsurface_motion(kg,
279                                                        ray,
280                                                        ss_isect,
281                                                        subsurface_object,
282                                                        lcg_state,
283                                                        max_hits);
284         }
285 #endif /* __OBJECT_MOTION__ */
286
287 #ifdef __HAIR__
288         if(kernel_data.bvh.have_curves) {
289                 return bvh_intersect_subsurface_hair(kg,
290                                                      ray,
291                                                      ss_isect,
292                                                      subsurface_object,
293                                                      lcg_state,
294                                                      max_hits);
295         }
296 #endif /* __HAIR__ */
297
298 #ifdef __KERNEL_CPU__
299
300 #ifdef __INSTANCING__
301         if(kernel_data.bvh.have_instancing) {
302                 return bvh_intersect_subsurface_instancing(kg,
303                                                            ray,
304                                                            ss_isect,
305                                                            subsurface_object,
306                                                            lcg_state,
307                                                            max_hits);
308         }
309 #endif /* __INSTANCING__ */
310
311         return bvh_intersect_subsurface(kg,
312                                         ray,
313                                         ss_isect,
314                                         subsurface_object,
315                                         lcg_state,
316                                         max_hits);
317 #else /* __KERNEL_CPU__ */
318
319 #ifdef __INSTANCING__
320         return bvh_intersect_subsurface_instancing(kg,
321                                                    ray,
322                                                    ss_isect,
323                                                    subsurface_object,
324                                                    lcg_state,
325                                                    max_hits);
326 #else
327         return bvh_intersect_subsurface(kg,
328                                         ray,
329                                         ss_isect,
330                                         subsurface_object,
331                                         lcg_state,
332                                         max_hits);
333 #endif /* __INSTANCING__ */
334
335 #endif /* __KERNEL_CPU__ */
336 }
337 #endif
338
339 #ifdef __SHADOW_RECORD_ALL__
340 ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits)
341 {
342 #ifdef __OBJECT_MOTION__
343         if(kernel_data.bvh.have_motion) {
344 #ifdef __HAIR__
345                 if(kernel_data.bvh.have_curves)
346                         return bvh_intersect_shadow_all_hair_motion(kg, ray, isect, max_hits, num_hits);
347 #endif /* __HAIR__ */
348
349                 return bvh_intersect_shadow_all_motion(kg, ray, isect, max_hits, num_hits);
350         }
351 #endif /* __OBJECT_MOTION__ */
352
353 #ifdef __HAIR__ 
354         if(kernel_data.bvh.have_curves)
355                 return bvh_intersect_shadow_all_hair(kg, ray, isect, max_hits, num_hits);
356 #endif /* __HAIR__ */
357
358 #ifdef __INSTANCING__
359         if(kernel_data.bvh.have_instancing)
360                 return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits);
361 #endif /* __INSTANCING__ */
362
363         return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits);
364 }
365 #endif
366
367 #ifdef __VOLUME__
368 ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg,
369                             const Ray *ray,
370                             Intersection *isect)
371 {
372 #ifdef __OBJECT_MOTION__
373         if(kernel_data.bvh.have_motion) {
374 #ifdef __HAIR__
375                 if(kernel_data.bvh.have_curves)
376                         return bvh_intersect_volume_hair_motion(kg, ray, isect);
377 #endif /* __HAIR__ */
378
379                 return bvh_intersect_volume_motion(kg, ray, isect);
380         }
381 #endif /* __OBJECT_MOTION__ */
382
383 #ifdef __HAIR__
384         if(kernel_data.bvh.have_curves)
385                 return bvh_intersect_volume_hair(kg, ray, isect);
386 #endif /* __HAIR__ */
387
388 #ifdef __KERNEL_CPU__
389
390 #ifdef __INSTANCING__
391         if(kernel_data.bvh.have_instancing)
392                 return bvh_intersect_volume_instancing(kg, ray, isect);
393 #endif /* __INSTANCING__ */
394
395         return bvh_intersect_volume(kg, ray, isect);
396 #else /* __KERNEL_CPU__ */
397
398 #ifdef __INSTANCING__
399         return bvh_intersect_volume_instancing(kg, ray, isect);
400 #else
401         return bvh_intersect_volume(kg, ray, isect);
402 #endif /* __INSTANCING__ */
403
404 #endif /* __KERNEL_CPU__ */
405 }
406 #endif
407
408 #ifdef __VOLUME_RECORD_ALL__
409 ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg,
410                                                      const Ray *ray,
411                                                      Intersection *isect,
412                                                      const uint max_hits)
413 {
414 #ifdef __OBJECT_MOTION__
415         if(kernel_data.bvh.have_motion) {
416 #ifdef __HAIR__
417                 if(kernel_data.bvh.have_curves)
418                         return bvh_intersect_volume_all_hair_motion(kg, ray, isect, max_hits);
419 #endif /* __HAIR__ */
420
421                 return bvh_intersect_volume_all_motion(kg, ray, isect, max_hits);
422         }
423 #endif /* __OBJECT_MOTION__ */
424
425 #ifdef __HAIR__
426         if(kernel_data.bvh.have_curves)
427                 return bvh_intersect_volume_all_hair(kg, ray, isect, max_hits);
428 #endif /* __HAIR__ */
429
430 #ifdef __INSTANCING__
431         if(kernel_data.bvh.have_instancing)
432                 return bvh_intersect_volume_all_instancing(kg, ray, isect, max_hits);
433 #endif /* __INSTANCING__ */
434
435         return bvh_intersect_volume_all(kg, ray, isect, max_hits);
436 }
437 #endif
438
439
440 /* Ray offset to avoid self intersection.
441  *
442  * This function should be used to compute a modified ray start position for
443  * rays leaving from a surface. */
444
445 ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
446 {
447 #ifdef __INTERSECTION_REFINE__
448         const float epsilon_f = 1e-5f;
449         /* ideally this should match epsilon_f, but instancing and motion blur
450          * precision makes it problematic */
451         const float epsilon_test = 1.0f;
452         const int epsilon_i = 32;
453
454         float3 res;
455
456         /* x component */
457         if(fabsf(P.x) < epsilon_test) {
458                 res.x = P.x + Ng.x*epsilon_f;
459         }
460         else {
461                 uint ix = __float_as_uint(P.x);
462                 ix += ((ix ^ __float_as_uint(Ng.x)) >> 31)? -epsilon_i: epsilon_i;
463                 res.x = __uint_as_float(ix);
464         }
465
466         /* y component */
467         if(fabsf(P.y) < epsilon_test) {
468                 res.y = P.y + Ng.y*epsilon_f;
469         }
470         else {
471                 uint iy = __float_as_uint(P.y);
472                 iy += ((iy ^ __float_as_uint(Ng.y)) >> 31)? -epsilon_i: epsilon_i;
473                 res.y = __uint_as_float(iy);
474         }
475
476         /* z component */
477         if(fabsf(P.z) < epsilon_test) {
478                 res.z = P.z + Ng.z*epsilon_f;
479         }
480         else {
481                 uint iz = __float_as_uint(P.z);
482                 iz += ((iz ^ __float_as_uint(Ng.z)) >> 31)? -epsilon_i: epsilon_i;
483                 res.z = __uint_as_float(iz);
484         }
485
486         return res;
487 #else
488         const float epsilon_f = 1e-4f;
489         return P + epsilon_f*Ng;
490 #endif
491 }
492
493 #if defined(__SHADOW_RECORD_ALL__) || defined (__VOLUME_RECORD_ALL__)
494 /* ToDo: Move to another file? */
495 ccl_device int intersections_compare(const void *a, const void *b)
496 {
497         const Intersection *isect_a = (const Intersection*)a;
498         const Intersection *isect_b = (const Intersection*)b;
499
500         if(isect_a->t < isect_b->t)
501                 return -1;
502         else if(isect_a->t > isect_b->t)
503                 return 1;
504         else
505                 return 0;
506 }
507 #endif
508
509 CCL_NAMESPACE_END
510