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