Blender V4.3
local.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2010 NVIDIA Corporation
2 * SPDX-FileCopyrightText: 2009-2012 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Adapted from code by Intel & NVIDIA. */
7
8#if BVH_FEATURE(BVH_HAIR)
9# define NODE_INTERSECT bvh_node_intersect
10#else
11# define NODE_INTERSECT bvh_aligned_node_intersect
12#endif
13
14/* This is a template BVH traversal function for finding local intersections
15 * around the shading point, for subsurface scattering and bevel. We disable
16 * various features for performance, and for instanced objects avoid traversing
17 * other parts of the scene.
18 *
19 * BVH_MOTION: motion blur rendering
20 */
21
22#ifndef __KERNEL_GPU__
24#else
26#endif
27 bool
29 ccl_private const Ray *ray,
30 ccl_private LocalIntersection *local_isect,
31 int local_object,
32 ccl_private uint *lcg_state,
33 int max_hits)
34{
35 /* todo:
36 * - test if pushing distance on the stack helps (for non shadow rays)
37 * - separate version for shadow rays
38 * - likely and unlikely for if() statements
39 * - test restrict attribute for pointers
40 */
41
42 /* traversal stack in CUDA thread-local memory */
45
46 /* traversal variables in registers */
47 int stack_ptr = 0;
48 int node_addr = kernel_data_fetch(object_node, local_object);
49
50 /* ray parameters in registers */
51 float3 P = ray->P;
52 float3 dir = bvh_clamp_direction(ray->D);
53 float3 idir = bvh_inverse_direction(dir);
54 float tmin = ray->tmin;
55 int object = OBJECT_NONE;
56 float isect_t = ray->tmax;
57
58 if (local_isect != NULL) {
59 local_isect->num_hits = 0;
60 }
61 kernel_assert((local_isect == NULL) == (max_hits == 0));
62
63 const int object_flag = kernel_data_fetch(object_flag, local_object);
64 if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
65#if BVH_FEATURE(BVH_MOTION)
66 bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir);
67#else
68 bvh_instance_push(kg, local_object, ray, &P, &dir, &idir);
69#endif
70 object = local_object;
71 }
72
73 /* traversal loop */
74 do {
75 do {
76 /* traverse internal nodes */
77 while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
78 int node_addr_child1, traverse_mask;
79 float dist[2];
80 float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0);
81
82 traverse_mask = NODE_INTERSECT(kg,
83 P,
85 dir,
86#endif
87 idir,
88 tmin,
89 isect_t,
90 node_addr,
92 dist);
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 }
121 }
122
123 /* if node is leaf, fetch triangle list */
124 if (node_addr < 0) {
125 float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1));
126 int prim_addr = __float_as_int(leaf.x);
127
128 const int prim_addr2 = __float_as_int(leaf.y);
129 const uint type = __float_as_int(leaf.w);
130
131 /* pop */
132 node_addr = traversal_stack[stack_ptr];
133 --stack_ptr;
134
135 /* primitive intersection */
136 switch (type & PRIMITIVE_ALL) {
137 case PRIMITIVE_TRIANGLE: {
138 /* intersect ray against primitive */
139 for (; prim_addr < prim_addr2; prim_addr++) {
140 kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type);
141
142 /* Only intersect with matching object, for instanced objects we
143 * already know we are only intersecting the right object. */
144 if (object == OBJECT_NONE) {
145 if (kernel_data_fetch(prim_object, prim_addr) != local_object) {
146 continue;
147 }
148 }
149
150 /* Skip self intersection. */
151 const int prim = kernel_data_fetch(prim_index, prim_addr);
152 if (intersection_skip_self_local(ray->self, prim)) {
153 continue;
154 }
155
156 if (triangle_intersect_local(kg,
157 local_isect,
158 P,
159 dir,
160 local_object,
161 prim,
162 prim_addr,
163 tmin,
164 isect_t,
165 lcg_state,
166 max_hits))
167 {
168 return true;
169 }
170 }
171 break;
172 }
173#if BVH_FEATURE(BVH_MOTION)
175 /* intersect ray against primitive */
176 for (; prim_addr < prim_addr2; prim_addr++) {
177 kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type);
178
179 /* Only intersect with matching object, for instanced objects we
180 * already know we are only intersecting the right object. */
181 if (object == OBJECT_NONE) {
182 if (kernel_data_fetch(prim_object, prim_addr) != local_object) {
183 continue;
184 }
185 }
186
187 /* Skip self intersection. */
188 const int prim = kernel_data_fetch(prim_index, prim_addr);
189 if (intersection_skip_self_local(ray->self, prim)) {
190 continue;
191 }
192
193 if (motion_triangle_intersect_local(kg,
194 local_isect,
195 P,
196 dir,
197 ray->time,
198 local_object,
199 prim,
200 prim_addr,
201 tmin,
202 isect_t,
203 lcg_state,
204 max_hits))
205 {
206 return true;
207 }
208 }
209 break;
210 }
211#endif
212 default: {
213 break;
214 }
215 }
216 }
217 } while (node_addr != ENTRYPOINT_SENTINEL);
218 } while (node_addr != ENTRYPOINT_SENTINEL);
219
220 return false;
221}
222
224 ccl_private const Ray *ray,
225 ccl_private LocalIntersection *local_isect,
226 int local_object,
227 ccl_private uint *lcg_state,
228 int max_hits)
229{
230 return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, local_isect, local_object, lcg_state, max_hits);
231}
232
233#undef BVH_FUNCTION_NAME
234#undef BVH_FUNCTION_FEATURES
235#undef NODE_INTERSECT
unsigned int uint
Definition bvh/bvh.h:66
ccl_device_inline bool intersection_skip_self_local(ccl_ray_data const RaySelfPrimitives &self, const int prim)
BLI_Stack * traversal_stack
#define kernel_assert(cond)
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define NULL
#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 float3 bvh_inverse_direction(float3 dir)
@ PRIMITIVE_ALL
@ PRIMITIVE_MOTION_TRIANGLE
@ PRIMITIVE_TRIANGLE
@ PATH_RAY_ALL_VISIBILITY
#define OBJECT_NONE
@ SD_OBJECT_TRANSFORM_APPLIED
#define NODE_INTERSECT
Definition local.h:11