Blender  V2.93
bvh_traversal.h
Go to the documentation of this file.
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 #if BVH_FEATURE(BVH_HAIR)
21 # define NODE_INTERSECT bvh_node_intersect
22 #else
23 # define NODE_INTERSECT bvh_aligned_node_intersect
24 #endif
25 
26 /* This is a template BVH traversal function, where various features can be
27  * enabled/disabled. This way we can compile optimized versions for each case
28  * without new features slowing things down.
29  *
30  * BVH_HAIR: hair curve rendering
31  * BVH_MOTION: motion blur rendering
32  */
33 
35  const Ray *ray,
36  Intersection *isect,
37  const uint visibility)
38 {
39  /* todo:
40  * - test if pushing distance on the stack helps (for non shadow rays)
41  * - separate version for shadow rays
42  * - likely and unlikely for if() statements
43  * - test restrict attribute for pointers
44  */
45 
46  /* traversal stack in CUDA thread-local memory */
49 
50  /* traversal variables in registers */
51  int stack_ptr = 0;
52  int node_addr = kernel_data.bvh.root;
53 
54  /* ray parameters in registers */
55  float3 P = ray->P;
56  float3 dir = bvh_clamp_direction(ray->D);
57  float3 idir = bvh_inverse_direction(dir);
58  int object = OBJECT_NONE;
59 
60 #if BVH_FEATURE(BVH_MOTION)
61  Transform ob_itfm;
62 #endif
63 
64  isect->t = ray->t;
65  isect->u = 0.0f;
66  isect->v = 0.0f;
67  isect->prim = PRIM_NONE;
68  isect->object = OBJECT_NONE;
69 
71 
72  /* traversal loop */
73  do {
74  do {
75  /* traverse internal nodes */
76  while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
77  int node_addr_child1, traverse_mask;
78  float dist[2];
79  float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
80 
81  {
82  traverse_mask = NODE_INTERSECT(kg,
83  P,
85  dir,
86 #endif
87  idir,
88  isect->t,
89  node_addr,
90  visibility,
91  dist);
92  }
93 
94  node_addr = __float_as_int(cnodes.z);
95  node_addr_child1 = __float_as_int(cnodes.w);
96 
97  if (traverse_mask == 3) {
98  /* Both children were intersected, push the farther one. */
99  bool is_closest_child1 = (dist[1] < dist[0]);
100  if (is_closest_child1) {
101  int tmp = node_addr;
102  node_addr = node_addr_child1;
103  node_addr_child1 = tmp;
104  }
105 
106  ++stack_ptr;
107  kernel_assert(stack_ptr < BVH_STACK_SIZE);
108  traversal_stack[stack_ptr] = node_addr_child1;
109  }
110  else {
111  /* One child was intersected. */
112  if (traverse_mask == 2) {
113  node_addr = node_addr_child1;
114  }
115  else if (traverse_mask == 0) {
116  /* Neither child was intersected. */
117  node_addr = traversal_stack[stack_ptr];
118  --stack_ptr;
119  }
120  }
122  }
123 
124  /* if node is leaf, fetch triangle list */
125  if (node_addr < 0) {
126  float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
127  int prim_addr = __float_as_int(leaf.x);
128 
129  if (prim_addr >= 0) {
130  const int prim_addr2 = __float_as_int(leaf.y);
131  const uint type = __float_as_int(leaf.w);
132 
133  /* pop */
134  node_addr = traversal_stack[stack_ptr];
135  --stack_ptr;
136 
137  /* primitive intersection */
138  switch (type & PRIMITIVE_ALL) {
139  case PRIMITIVE_TRIANGLE: {
140  for (; prim_addr < prim_addr2; prim_addr++) {
142  kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
143  if (triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr)) {
144  /* shadow ray early termination */
145  if (visibility & PATH_RAY_SHADOW_OPAQUE)
146  return true;
147  }
148  }
149  break;
150  }
151 #if BVH_FEATURE(BVH_MOTION)
153  for (; prim_addr < prim_addr2; prim_addr++) {
155  kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
157  kg, isect, P, dir, ray->time, visibility, object, prim_addr)) {
158  /* shadow ray early termination */
159  if (visibility & PATH_RAY_SHADOW_OPAQUE)
160  return true;
161  }
162  }
163  break;
164  }
165 #endif /* BVH_FEATURE(BVH_MOTION) */
166 #if BVH_FEATURE(BVH_HAIR)
171  for (; prim_addr < prim_addr2; prim_addr++) {
173  const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
174  kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
175  const bool hit = curve_intersect(
176  kg, isect, P, dir, visibility, object, prim_addr, ray->time, curve_type);
177  if (hit) {
178  /* shadow ray early termination */
179  if (visibility & PATH_RAY_SHADOW_OPAQUE)
180  return true;
181  }
182  }
183  break;
184  }
185 #endif /* BVH_FEATURE(BVH_HAIR) */
186  }
187  }
188  else {
189  /* instance push */
190  object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
191 
192 #if BVH_FEATURE(BVH_MOTION)
193  isect->t = bvh_instance_motion_push(
194  kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
195 #else
196  isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
197 #endif
198 
199  ++stack_ptr;
200  kernel_assert(stack_ptr < BVH_STACK_SIZE);
202 
203  node_addr = kernel_tex_fetch(__object_node, object);
204 
206  }
207  }
208  } while (node_addr != ENTRYPOINT_SENTINEL);
209 
210  if (stack_ptr >= 0) {
211  kernel_assert(object != OBJECT_NONE);
212 
213  /* instance pop */
214 #if BVH_FEATURE(BVH_MOTION)
215  isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
216 #else
217  isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
218 #endif
219 
220  object = OBJECT_NONE;
221  node_addr = traversal_stack[stack_ptr];
222  --stack_ptr;
223  }
224  } while (node_addr != ENTRYPOINT_SENTINEL);
225 
226  return (isect->prim != PRIM_NONE);
227 }
228 
230  const Ray *ray,
231  Intersection *isect,
232  const uint visibility)
233 {
234  return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, isect, visibility);
235 }
236 
237 #undef BVH_FUNCTION_NAME
238 #undef BVH_FUNCTION_FEATURES
239 #undef NODE_INTERSECT
unsigned int uint
Definition: BLI_sys_types.h:83
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
#define NODE_INTERSECT
Definition: bvh_traversal.h:23
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility)
#define BVH_STACK_SIZE
Definition: bvh_types.h:33
#define BVH_FEATURE(f)
Definition: bvh_types.h:43
#define BVH_DEBUG_INIT()
Definition: bvh_types.h:66
#define ENTRYPOINT_SENTINEL
Definition: bvh_types.h:30
#define BVH_DEBUG_NEXT_INTERSECTION()
Definition: bvh_types.h:68
#define BVH_DEBUG_NEXT_NODE()
Definition: bvh_types.h:67
#define BVH_HAIR
Definition: bvh_types.h:37
#define BVH_FUNCTION_FULL_NAME(prefix)
Definition: bvh_types.h:41
#define BVH_DEBUG_NEXT_INSTANCE()
Definition: bvh_types.h:69
Definition: bvh/bvh.h:80
BLI_Stack * traversal_stack
ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 dir, float time, uint visibility, int object, int prim_addr)
ccl_device_inline float3 bvh_clamp_direction(float3 dir)
Definition: geom_object.h:405
ccl_device_inline float3 bvh_inverse_direction(float3 dir)
Definition: geom_object.h:413
ccl_device_inline float bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float t)
Definition: geom_object.h:420
ccl_device_inline float bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float t)
Definition: geom_object.h:440
CCL_NAMESPACE_BEGIN ccl_device_inline bool triangle_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 dir, uint visibility, int object, int prim_addr)
#define kernel_data
#define kernel_assert(cond)
#define kernel_tex_fetch(tex, index)
#define ccl_device_inline
#define ccl_device_noinline
@ PRIMITIVE_MOTION_CURVE_RIBBON
Definition: kernel_types.h:691
@ PRIMITIVE_ALL
Definition: kernel_types.h:702
@ PRIMITIVE_MOTION_TRIANGLE
Definition: kernel_types.h:687
@ PRIMITIVE_CURVE_RIBBON
Definition: kernel_types.h:690
@ PRIMITIVE_MOTION_CURVE_THICK
Definition: kernel_types.h:689
@ PRIMITIVE_CURVE_THICK
Definition: kernel_types.h:688
@ PRIMITIVE_TRIANGLE
Definition: kernel_types.h:686
#define PRIM_NONE
Definition: kernel_types.h:60
@ PATH_RAY_SHADOW_OPAQUE
Definition: kernel_types.h:277
#define OBJECT_NONE
Definition: kernel_types.h:59
static float P(float k)
Definition: math_interp.c:41
ccl_device_inline int __float_as_int(float f)
Definition: util_math.h:202