Blender  V3.3
kernel/bvh/volume.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
3  * and code copyright 2009-2012 Intel Corporation
4  *
5  * Modifications Copyright 2011-2022 Blender Foundation. */
6 
7 #if BVH_FEATURE(BVH_HAIR)
8 # define NODE_INTERSECT bvh_node_intersect
9 #else
10 # define NODE_INTERSECT bvh_aligned_node_intersect
11 #endif
12 
13 /* This is a template BVH traversal function for volumes, where
14  * various features can be enabled/disabled. This way we can compile optimized
15  * versions for each case without new features slowing things down.
16  *
17  * BVH_MOTION: motion blur rendering
18  */
19 
20 #ifndef __KERNEL_GPU__
22 #else
24 #endif
26  ccl_private const Ray *ray,
28  const uint visibility)
29 {
30  /* todo:
31  * - test if pushing distance on the stack helps (for non shadow rays)
32  * - separate version for shadow rays
33  * - likely and unlikely for if() statements
34  * - test restrict attribute for pointers
35  */
36 
37  /* traversal stack in CUDA thread-local memory */
40 
41  /* traversal variables in registers */
42  int stack_ptr = 0;
43  int node_addr = kernel_data.bvh.root;
44 
45  /* ray parameters in registers */
46  float3 P = ray->P;
47  float3 dir = bvh_clamp_direction(ray->D);
48  float3 idir = bvh_inverse_direction(dir);
49  const float tmin = ray->tmin;
50  int object = OBJECT_NONE;
51 
52  isect->t = ray->tmax;
53  isect->u = 0.0f;
54  isect->v = 0.0f;
55  isect->prim = PRIM_NONE;
56  isect->object = OBJECT_NONE;
57 
58  /* traversal loop */
59  do {
60  do {
61  /* traverse internal nodes */
62  while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
63  int node_addr_child1, traverse_mask;
64  float dist[2];
65  float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0);
66 
67  traverse_mask = NODE_INTERSECT(kg,
68  P,
70  dir,
71 #endif
72  idir,
73  tmin,
74  isect->t,
75  node_addr,
76  visibility,
77  dist);
78 
79  node_addr = __float_as_int(cnodes.z);
80  node_addr_child1 = __float_as_int(cnodes.w);
81 
82  if (traverse_mask == 3) {
83  /* Both children were intersected, push the farther one. */
84  bool is_closest_child1 = (dist[1] < dist[0]);
85  if (is_closest_child1) {
86  int tmp = node_addr;
87  node_addr = node_addr_child1;
88  node_addr_child1 = tmp;
89  }
90 
91  ++stack_ptr;
92  kernel_assert(stack_ptr < BVH_STACK_SIZE);
93  traversal_stack[stack_ptr] = node_addr_child1;
94  }
95  else {
96  /* One child was intersected. */
97  if (traverse_mask == 2) {
98  node_addr = node_addr_child1;
99  }
100  else if (traverse_mask == 0) {
101  /* Neither child was intersected. */
102  node_addr = traversal_stack[stack_ptr];
103  --stack_ptr;
104  }
105  }
106  }
107 
108  /* if node is leaf, fetch triangle list */
109  if (node_addr < 0) {
110  float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1));
111  int prim_addr = __float_as_int(leaf.x);
112 
113  if (prim_addr >= 0) {
114  const int prim_addr2 = __float_as_int(leaf.y);
115  const uint type = __float_as_int(leaf.w);
116 
117  /* pop */
118  node_addr = traversal_stack[stack_ptr];
119  --stack_ptr;
120 
121  /* primitive intersection */
122  switch (type & PRIMITIVE_ALL) {
123  case PRIMITIVE_TRIANGLE: {
124  /* intersect ray against primitive */
125  for (; prim_addr < prim_addr2; prim_addr++) {
126  kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type);
127  /* only primitives from volume object */
128  const int prim_object = (object == OBJECT_NONE) ?
129  kernel_data_fetch(prim_object, prim_addr) :
130  object;
131  const int prim = kernel_data_fetch(prim_index, prim_addr);
132  if (intersection_skip_self(ray->self, prim_object, prim)) {
133  continue;
134  }
135 
136  int object_flag = kernel_data_fetch(object_flag, prim_object);
137  if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
138  continue;
139  }
141  kg, isect, P, dir, tmin, isect->t, visibility, prim_object, prim, prim_addr);
142  }
143  break;
144  }
145 #if BVH_FEATURE(BVH_MOTION)
147  /* intersect ray against primitive */
148  for (; prim_addr < prim_addr2; prim_addr++) {
149  kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type);
150  /* only primitives from volume object */
151  const int prim_object = (object == OBJECT_NONE) ?
152  kernel_data_fetch(prim_object, prim_addr) :
153  object;
154  const int prim = kernel_data_fetch(prim_index, prim_addr);
155  if (intersection_skip_self(ray->self, prim_object, prim)) {
156  continue;
157  }
158  int object_flag = kernel_data_fetch(object_flag, prim_object);
159  if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
160  continue;
161  }
163  isect,
164  P,
165  dir,
166  tmin,
167  isect->t,
168  ray->time,
169  visibility,
170  prim_object,
171  prim,
172  prim_addr);
173  }
174  break;
175  }
176 #endif
177  default: {
178  break;
179  }
180  }
181  }
182  else {
183  /* instance push */
184  object = kernel_data_fetch(prim_object, -prim_addr - 1);
185  int object_flag = kernel_data_fetch(object_flag, object);
186  if (object_flag & SD_OBJECT_HAS_VOLUME) {
187 #if BVH_FEATURE(BVH_MOTION)
188  bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir);
189 #else
190  bvh_instance_push(kg, object, ray, &P, &dir, &idir);
191 #endif
192 
193  ++stack_ptr;
194  kernel_assert(stack_ptr < BVH_STACK_SIZE);
196 
197  node_addr = kernel_data_fetch(object_node, object);
198  }
199  else {
200  /* pop */
201  object = OBJECT_NONE;
202  node_addr = traversal_stack[stack_ptr];
203  --stack_ptr;
204  }
205  }
206  }
207  } while (node_addr != ENTRYPOINT_SENTINEL);
208 
209  if (stack_ptr >= 0) {
210  kernel_assert(object != OBJECT_NONE);
211 
212  /* instance pop */
213  bvh_instance_pop(ray, &P, &dir, &idir);
214 
215  object = OBJECT_NONE;
216  node_addr = traversal_stack[stack_ptr];
217  --stack_ptr;
218  }
219  } while (node_addr != ENTRYPOINT_SENTINEL);
220 
221  return (isect->prim != PRIM_NONE);
222 }
223 
225  ccl_private const Ray *ray,
226  ccl_private Intersection *isect,
227  const uint visibility)
228 {
229  return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, isect, visibility);
230 }
231 
232 #undef BVH_FUNCTION_NAME
233 #undef BVH_FUNCTION_FEATURES
234 #undef NODE_INTERSECT
unsigned int uint
Definition: BLI_sys_types.h:67
_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
float float4[4]
Definition: bvh/bvh.h:63
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
ccl_device_inline bool intersection_skip_self(ccl_private const RaySelfPrimitives &self, const int object, const int prim)
BLI_Stack * traversal_stack
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define BVH_STACK_SIZE
#define BVH_FEATURE(f)
#define ENTRYPOINT_SENTINEL
#define BVH_HAIR
#define BVH_FUNCTION_FULL_NAME(prefix)
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals kg, ccl_private const Ray *ray, ccl_private Intersection *isect, const uint visibility)
#define NODE_INTERSECT
ccl_device_inline void bvh_instance_push(KernelGlobals kg, int object, ccl_private const Ray *ray, ccl_private float3 *P, ccl_private float3 *dir, ccl_private float3 *idir)
ccl_device_inline float3 bvh_clamp_direction(float3 dir)
ccl_device_inline void bvh_instance_pop(ccl_private const Ray *ray, ccl_private float3 *P, ccl_private float3 *dir, ccl_private float3 *idir)
ccl_device_inline float3 bvh_inverse_direction(float3 dir)
@ PRIMITIVE_ALL
Definition: kernel/types.h:566
@ PRIMITIVE_MOTION_TRIANGLE
Definition: kernel/types.h:559
@ PRIMITIVE_TRIANGLE
Definition: kernel/types.h:551
#define PRIM_NONE
Definition: kernel/types.h:41
#define OBJECT_NONE
Definition: kernel/types.h:40
@ SD_OBJECT_HAS_VOLUME
Definition: kernel/types.h:812
static float P(float k)
Definition: math_interp.c:25
ccl_device_inline bool motion_triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, float3 P, float3 dir, float tmin, float tmax, float time, uint visibility, int object, int prim, int prim_addr)
CCL_NAMESPACE_BEGIN ccl_device_inline bool triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, float3 P, float3 dir, float tmin, float tmax, uint visibility, int object, int prim, int prim_addr)
ccl_device_inline int __float_as_int(float f)
Definition: util/math.h:243