Blender V4.3
kernel/bvh/bvh.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#include "kernel/bvh/types.h"
8#include "kernel/bvh/util.h"
9
11
12/* Device specific acceleration structures for ray tracing. */
13
14#if defined(__EMBREE__)
16# define __BVH2__
17#elif defined(__METALRT__)
19#elif defined(__KERNEL_OPTIX__)
21#elif defined(__HIPRT__)
23#else
24# define __BVH2__
25#endif
26
27#if defined(__KERNEL_ONEAPI__) && defined(WITH_EMBREE_GPU)
28/* bool is apparently not tested for specialization constants:
29 * https://github.com/intel/llvm/blob/39d1c65272a786b2b13a6f094facfddf9408406d/sycl/test/basic_tests/SYCL-2020-spec-constants.cpp#L25-L27
30 * Instead of adding one more bool specialization constant, we reuse existing embree_features one
31 * and use RTC_FEATURE_FLAG_NONE as value to test for avoiding to call Embree on GPU.
32 */
33/* We set it to RTC_FEATURE_FLAG_NONE by default so AoT binaries contain MNE and ray-trace kernels
34 * pre-compiled without Embree.
35 * Changing this default value would require updating the logic in oneapi_load_kernels(). */
36static constexpr sycl::specialization_id<RTCFeatureFlags> oneapi_embree_features{
37 RTC_FEATURE_FLAG_NONE};
38# define IF_USING_EMBREE \
39 if (kernel_handler.get_specialization_constant<oneapi_embree_features>() != \
40 RTC_FEATURE_FLAG_NONE)
41# define IF_NOT_USING_EMBREE \
42 if (kernel_handler.get_specialization_constant<oneapi_embree_features>() == \
43 RTC_FEATURE_FLAG_NONE)
44#else
45# define IF_USING_EMBREE
46# define IF_NOT_USING_EMBREE
47#endif
48
50
51#ifdef __BVH2__
52
53/* BVH2
54 *
55 * Bounding volume hierarchy for ray tracing, when no native acceleration
56 * structure is available for the device.
57 *
58 * We compile different variations of the same BVH traversal function for
59 * faster rendering when some types of primitives are not needed, using #includes
60 * to work around the lack of C++ templates in OpenCL.
61 *
62 * Originally based on "Understanding the Efficiency of Ray Traversal on GPUs",
63 * the code has been extended and modified to support more primitives and work
64 * with CPU and various GPU kernel languages. */
65
66# include "kernel/bvh/nodes.h"
67
68/* Regular BVH traversal */
69
70# define BVH_FUNCTION_NAME bvh_intersect
71# define BVH_FUNCTION_FEATURES BVH_POINTCLOUD
72# include "kernel/bvh/traversal.h"
73
74# if defined(__HAIR__)
75# define BVH_FUNCTION_NAME bvh_intersect_hair
76# define BVH_FUNCTION_FEATURES BVH_HAIR | BVH_POINTCLOUD
77# include "kernel/bvh/traversal.h"
78# endif
79
80# if defined(__OBJECT_MOTION__)
81# define BVH_FUNCTION_NAME bvh_intersect_motion
82# define BVH_FUNCTION_FEATURES BVH_MOTION | BVH_POINTCLOUD
83# include "kernel/bvh/traversal.h"
84# endif
85
86# if defined(__HAIR__) && defined(__OBJECT_MOTION__)
87# define BVH_FUNCTION_NAME bvh_intersect_hair_motion
88# define BVH_FUNCTION_FEATURES BVH_HAIR | BVH_MOTION | BVH_POINTCLOUD
89# include "kernel/bvh/traversal.h"
90# endif
91
93 ccl_private const Ray *ray,
94 const uint visibility,
96{
97 if (!intersection_ray_valid(ray)) {
98 return false;
99 }
100
101# ifdef __EMBREE__
103 {
104 if (kernel_data.device_bvh) {
105 return kernel_embree_intersect(kg, ray, visibility, isect);
106 }
107 }
108# endif
109
111 {
112# ifdef __OBJECT_MOTION__
113 if (kernel_data.bvh.have_motion) {
114# ifdef __HAIR__
115 if (kernel_data.bvh.have_curves) {
116 return bvh_intersect_hair_motion(kg, ray, isect, visibility);
117 }
118# endif /* __HAIR__ */
119
120 return bvh_intersect_motion(kg, ray, isect, visibility);
121 }
122# endif /* __OBJECT_MOTION__ */
123
124# ifdef __HAIR__
125 if (kernel_data.bvh.have_curves) {
126 return bvh_intersect_hair(kg, ray, isect, visibility);
127 }
128# endif /* __HAIR__ */
129
130 return bvh_intersect(kg, ray, isect, visibility);
131 }
132
133 kernel_assert(false);
134 return false;
135}
136
138 ccl_private const Ray *ray,
139 const uint visibility)
140{
141 Intersection isect;
142 return scene_intersect(kg, ray, visibility, &isect);
143}
144
145/* Single object BVH traversal, for SSS/AO/bevel. */
146
147# ifdef __BVH_LOCAL__
148
149# define BVH_FUNCTION_NAME bvh_intersect_local
150# define BVH_FUNCTION_FEATURES BVH_HAIR
151# include "kernel/bvh/local.h"
152
153# if defined(__OBJECT_MOTION__)
154# define BVH_FUNCTION_NAME bvh_intersect_local_motion
155# define BVH_FUNCTION_FEATURES BVH_MOTION | BVH_HAIR
156# include "kernel/bvh/local.h"
157# endif
158
159template<bool single_hit = false>
160ccl_device_intersect bool scene_intersect_local(KernelGlobals kg,
161 ccl_private const Ray *ray,
162 ccl_private LocalIntersection *local_isect,
163 int local_object,
164 ccl_private uint *lcg_state,
165 int max_hits)
166{
167 if (!intersection_ray_valid(ray)) {
168 if (local_isect) {
169 local_isect->num_hits = 0;
170 }
171 return false;
172 }
173
174# ifdef __EMBREE__
176 {
177 if (kernel_data.device_bvh) {
178 return kernel_embree_intersect_local(
179 kg, ray, local_isect, local_object, lcg_state, max_hits);
180 }
181 }
182# endif
183
185 {
186# ifdef __OBJECT_MOTION__
187 if (kernel_data.bvh.have_motion) {
188 return bvh_intersect_local_motion(kg, ray, local_isect, local_object, lcg_state, max_hits);
189 }
190# endif /* __OBJECT_MOTION__ */
191 return bvh_intersect_local(kg, ray, local_isect, local_object, lcg_state, max_hits);
192 }
193
194 kernel_assert(false);
195 return false;
196}
197# endif
198
199/* Transparent shadow BVH traversal, recording multiple intersections. */
200
201# ifdef __SHADOW_RECORD_ALL__
202
203# define BVH_FUNCTION_NAME bvh_intersect_shadow_all
204# define BVH_FUNCTION_FEATURES BVH_POINTCLOUD
205# include "kernel/bvh/shadow_all.h"
206
207# if defined(__HAIR__)
208# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
209# define BVH_FUNCTION_FEATURES BVH_HAIR | BVH_POINTCLOUD
210# include "kernel/bvh/shadow_all.h"
211# endif
212
213# if defined(__OBJECT_MOTION__)
214# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
215# define BVH_FUNCTION_FEATURES BVH_MOTION | BVH_POINTCLOUD
216# include "kernel/bvh/shadow_all.h"
217# endif
218
219# if defined(__HAIR__) && defined(__OBJECT_MOTION__)
220# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion
221# define BVH_FUNCTION_FEATURES BVH_HAIR | BVH_MOTION | BVH_POINTCLOUD
222# include "kernel/bvh/shadow_all.h"
223# endif
224
225ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals kg,
227 ccl_private const Ray *ray,
228 uint visibility,
229 uint max_hits,
230 ccl_private uint *num_recorded_hits,
231 ccl_private float *throughput)
232{
233 if (!intersection_ray_valid(ray)) {
234 *num_recorded_hits = 0;
235 *throughput = 1.0f;
236 return false;
237 }
238
239# ifdef __EMBREE__
241 {
242 if (kernel_data.device_bvh) {
243 return kernel_embree_intersect_shadow_all(
244 kg, state, ray, visibility, max_hits, num_recorded_hits, throughput);
245 }
246 }
247# endif
248
250 {
251# ifdef __OBJECT_MOTION__
252 if (kernel_data.bvh.have_motion) {
253# ifdef __HAIR__
254 if (kernel_data.bvh.have_curves) {
255 return bvh_intersect_shadow_all_hair_motion(
256 kg, ray, state, visibility, max_hits, num_recorded_hits, throughput);
257 }
258# endif /* __HAIR__ */
259
260 return bvh_intersect_shadow_all_motion(
261 kg, ray, state, visibility, max_hits, num_recorded_hits, throughput);
262 }
263# endif /* __OBJECT_MOTION__ */
264
265# ifdef __HAIR__
266 if (kernel_data.bvh.have_curves) {
267 return bvh_intersect_shadow_all_hair(
268 kg, ray, state, visibility, max_hits, num_recorded_hits, throughput);
269 }
270# endif /* __HAIR__ */
271
272 return bvh_intersect_shadow_all(
273 kg, ray, state, visibility, max_hits, num_recorded_hits, throughput);
274 }
275
276 kernel_assert(false);
277 return false;
278}
279# endif /* __SHADOW_RECORD_ALL__ */
280
281/* Volume BVH traversal, for initializing or updating the volume stack. */
282
283# if defined(__VOLUME__) && !defined(__VOLUME_RECORD_ALL__)
284
285# define BVH_FUNCTION_NAME bvh_intersect_volume
286# define BVH_FUNCTION_FEATURES BVH_HAIR
287# include "kernel/bvh/volume.h"
288
289# if defined(__OBJECT_MOTION__)
290# define BVH_FUNCTION_NAME bvh_intersect_volume_motion
291# define BVH_FUNCTION_FEATURES BVH_MOTION | BVH_HAIR
292# include "kernel/bvh/volume.h"
293# endif
294
295ccl_device_intersect bool scene_intersect_volume(KernelGlobals kg,
296 ccl_private const Ray *ray,
298 const uint visibility)
299{
300 if (!intersection_ray_valid(ray)) {
301 return false;
302 }
303
304# ifdef __EMBREE__
306 {
307 if (kernel_data.device_bvh) {
308 return kernel_embree_intersect_volume(kg, ray, isect, visibility);
309 }
310 }
311# endif
312
314 {
315# ifdef __OBJECT_MOTION__
316 if (kernel_data.bvh.have_motion) {
317 return bvh_intersect_volume_motion(kg, ray, isect, visibility);
318 }
319# endif /* __OBJECT_MOTION__ */
320
321 return bvh_intersect_volume(kg, ray, isect, visibility);
322 }
323
324 kernel_assert(false);
325 return false;
326}
327# endif /* defined(__VOLUME__) && !defined(__VOLUME_RECORD_ALL__) */
328
329/* Volume BVH traversal, for initializing or updating the volume stack.
330 * Variation that records multiple intersections at once. */
331
332# if defined(__VOLUME__) && defined(__VOLUME_RECORD_ALL__)
333
334# define BVH_FUNCTION_NAME bvh_intersect_volume_all
335# define BVH_FUNCTION_FEATURES BVH_HAIR
336# include "kernel/bvh/volume_all.h"
337
338# if defined(__OBJECT_MOTION__)
339# define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
340# define BVH_FUNCTION_FEATURES BVH_MOTION | BVH_HAIR
341# include "kernel/bvh/volume_all.h"
342# endif
343
344ccl_device_intersect uint scene_intersect_volume(KernelGlobals kg,
345 ccl_private const Ray *ray,
347 const uint max_hits,
348 const uint visibility)
349{
350 if (!intersection_ray_valid(ray)) {
351 return false;
352 }
353
354# ifdef __EMBREE__
356 {
357 if (kernel_data.device_bvh) {
358 return kernel_embree_intersect_volume(kg, ray, isect, max_hits, visibility);
359 }
360 }
361# endif
362
364 {
365# ifdef __OBJECT_MOTION__
366 if (kernel_data.bvh.have_motion) {
367 return bvh_intersect_volume_all_motion(kg, ray, isect, max_hits, visibility);
368 }
369# endif /* __OBJECT_MOTION__ */
370
371 return bvh_intersect_volume_all(kg, ray, isect, max_hits, visibility);
372 }
373
374 kernel_assert(false);
375 return false;
376}
377
378# endif /* defined(__VOLUME__) && defined(__VOLUME_RECORD_ALL__) */
379
380# undef BVH_FEATURE
381# undef BVH_NAME_JOIN
382# undef BVH_NAME_EVAL
383# undef BVH_FUNCTION_FULL_NAME
384
385#endif /* __BVH2__ */
386
unsigned int uint
CCL_NAMESPACE_BEGIN ccl_device_inline bool intersection_ray_valid(ccl_private const Ray *ray)
#define kernel_assert(cond)
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define ccl_private
#define CCL_NAMESPACE_END
#define IF_NOT_USING_EMBREE
ccl_device_intersect bool scene_intersect(KernelGlobals kg, ccl_private const Ray *ray, const uint visibility, ccl_private Intersection *isect)
ccl_device_intersect bool scene_intersect_shadow(KernelGlobals kg, ccl_private const Ray *ray, const uint visibility)
#define IF_USING_EMBREE
#define ccl_device_intersect
ccl_device_intersect bool kernel_embree_intersect(KernelGlobals kg, ccl_private const Ray *ray, const uint visibility, ccl_private Intersection *isect)
static ulong state[N]
IntegratorShadowStateCPU *ccl_restrict IntegratorShadowState
Definition state.h:230