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