Blender  V3.3
local.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 #if BVH_FEATURE(BVH_HAIR)
6 # define NODE_INTERSECT bvh_node_intersect
7 #else
8 # define NODE_INTERSECT bvh_aligned_node_intersect
9 #endif
10 
11 /* This is a template BVH traversal function for finding local intersections
12  * around the shading point, for subsurface scattering and bevel. We disable
13  * various features for performance, and for instanced objects avoid traversing
14  * other parts of the scene.
15  *
16  * BVH_MOTION: motion blur rendering
17  */
18 
19 #ifndef __KERNEL_GPU__
21 #else
23 #endif
25  ccl_private const Ray *ray,
26  ccl_private LocalIntersection *local_isect,
27  int local_object,
28  ccl_private uint *lcg_state,
29  int max_hits)
30 {
31  /* todo:
32  * - test if pushing distance on the stack helps (for non shadow rays)
33  * - separate version for shadow rays
34  * - likely and unlikely for if() statements
35  * - test restrict attribute for pointers
36  */
37 
38  /* traversal stack in CUDA thread-local memory */
41 
42  /* traversal variables in registers */
43  int stack_ptr = 0;
44  int node_addr = kernel_data_fetch(object_node, local_object);
45 
46  /* ray parameters in registers */
47  float3 P = ray->P;
48  float3 dir = bvh_clamp_direction(ray->D);
49  float3 idir = bvh_inverse_direction(dir);
50  float tmin = ray->tmin;
51  int object = OBJECT_NONE;
52  float isect_t = ray->tmax;
53 
54  if (local_isect != NULL) {
55  local_isect->num_hits = 0;
56  }
57  kernel_assert((local_isect == NULL) == (max_hits == 0));
58 
59  const int object_flag = kernel_data_fetch(object_flag, local_object);
60  if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
61 #if BVH_FEATURE(BVH_MOTION)
62  bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir);
63 #else
64  bvh_instance_push(kg, local_object, ray, &P, &dir, &idir);
65 #endif
66  object = local_object;
67  }
68 
69  /* traversal loop */
70  do {
71  do {
72  /* traverse internal nodes */
73  while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
74  int node_addr_child1, traverse_mask;
75  float dist[2];
76  float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0);
77 
78  traverse_mask = NODE_INTERSECT(kg,
79  P,
81  dir,
82 #endif
83  idir,
84  tmin,
85  isect_t,
86  node_addr,
88  dist);
89 
90  node_addr = __float_as_int(cnodes.z);
91  node_addr_child1 = __float_as_int(cnodes.w);
92 
93  if (traverse_mask == 3) {
94  /* Both children were intersected, push the farther one. */
95  bool is_closest_child1 = (dist[1] < dist[0]);
96  if (is_closest_child1) {
97  int tmp = node_addr;
98  node_addr = node_addr_child1;
99  node_addr_child1 = tmp;
100  }
101 
102  ++stack_ptr;
103  kernel_assert(stack_ptr < BVH_STACK_SIZE);
104  traversal_stack[stack_ptr] = node_addr_child1;
105  }
106  else {
107  /* One child was intersected. */
108  if (traverse_mask == 2) {
109  node_addr = node_addr_child1;
110  }
111  else if (traverse_mask == 0) {
112  /* Neither child was intersected. */
113  node_addr = traversal_stack[stack_ptr];
114  --stack_ptr;
115  }
116  }
117  }
118 
119  /* if node is leaf, fetch triangle list */
120  if (node_addr < 0) {
121  float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1));
122  int prim_addr = __float_as_int(leaf.x);
123 
124  const int prim_addr2 = __float_as_int(leaf.y);
125  const uint type = __float_as_int(leaf.w);
126 
127  /* pop */
128  node_addr = traversal_stack[stack_ptr];
129  --stack_ptr;
130 
131  /* primitive intersection */
132  switch (type & PRIMITIVE_ALL) {
133  case PRIMITIVE_TRIANGLE: {
134  /* intersect ray against primitive */
135  for (; prim_addr < prim_addr2; prim_addr++) {
136  kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type);
137 
138  /* Only intersect with matching object, for instanced objects we
139  * already know we are only intersecting the right object. */
140  if (object == OBJECT_NONE) {
141  if (kernel_data_fetch(prim_object, prim_addr) != local_object) {
142  continue;
143  }
144  }
145 
146  /* Skip self intersection. */
147  const int prim = kernel_data_fetch(prim_index, prim_addr);
148  if (intersection_skip_self_local(ray->self, prim)) {
149  continue;
150  }
151 
152  if (triangle_intersect_local(kg,
153  local_isect,
154  P,
155  dir,
156  local_object,
157  prim,
158  prim_addr,
159  tmin,
160  isect_t,
161  lcg_state,
162  max_hits)) {
163  return true;
164  }
165  }
166  break;
167  }
168 #if BVH_FEATURE(BVH_MOTION)
170  /* intersect ray against primitive */
171  for (; prim_addr < prim_addr2; prim_addr++) {
172  kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type);
173 
174  /* Only intersect with matching object, for instanced objects we
175  * already know we are only intersecting the right object. */
176  if (object == OBJECT_NONE) {
177  if (kernel_data_fetch(prim_object, prim_addr) != local_object) {
178  continue;
179  }
180  }
181 
182  /* Skip self intersection. */
183  const int prim = kernel_data_fetch(prim_index, prim_addr);
184  if (intersection_skip_self_local(ray->self, prim)) {
185  continue;
186  }
187 
188  if (motion_triangle_intersect_local(kg,
189  local_isect,
190  P,
191  dir,
192  ray->time,
193  local_object,
194  prim,
195  prim_addr,
196  tmin,
197  isect_t,
198  lcg_state,
199  max_hits)) {
200  return true;
201  }
202  }
203  break;
204  }
205 #endif
206  default: {
207  break;
208  }
209  }
210  }
211  } while (node_addr != ENTRYPOINT_SENTINEL);
212  } while (node_addr != ENTRYPOINT_SENTINEL);
213 
214  return false;
215 }
216 
218  ccl_private const Ray *ray,
219  ccl_private LocalIntersection *local_isect,
220  int local_object,
221  ccl_private uint *lcg_state,
222  int max_hits)
223 {
224  return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, local_isect, local_object, lcg_state, max_hits);
225 }
226 
227 #undef BVH_FUNCTION_NAME
228 #undef BVH_FUNCTION_FEATURES
229 #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_local(ccl_private const RaySelfPrimitives &self, const int prim)
BLI_Stack * traversal_stack
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 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 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
@ PATH_RAY_ALL_VISIBILITY
Definition: kernel/types.h:217
#define OBJECT_NONE
Definition: kernel/types.h:40
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel/types.h:808
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals kg, ccl_private const Ray *ray, ccl_private LocalIntersection *local_isect, int local_object, ccl_private uint *lcg_state, int max_hits)
Definition: local.h:217
#define NODE_INTERSECT
Definition: local.h:8
static float P(float k)
Definition: math_interp.c:25
ccl_device_inline int __float_as_int(float f)
Definition: util/math.h:243