Blender V4.5
device/hiprt/common.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#ifdef __HIPRT__
6
7struct RayPayload {
9 RaySelfPrimitives self;
10 uint visibility;
11 int prim_type;
12 float ray_time;
13};
14
15/* Some ray types might use the same intersection function for regular and shadow intersections,
16 * but have different filter functions for them. To make this code simpler subclass from
17 * RayPayload.
18 *
19 * NOTE: This assumes that reinterpret_cast from void pointer to RayPayload works correctly. */
20struct ShadowPayload : RayPayload {
21 int in_state;
22 uint max_hits;
23 uint num_hits;
24 uint *r_num_recorded_hits;
25 float *r_throughput;
26};
27
28struct LocalPayload {
30 RaySelfPrimitives self;
31 float ray_time;
32 int local_object;
33 uint max_hits;
34 uint *lcg_state;
35 LocalIntersection *local_isect;
36};
37
38# define SET_HIPRT_RAY(RAY_RT, RAY) \
39 RAY_RT.direction = RAY->D; \
40 RAY_RT.origin = RAY->P; \
41 RAY_RT.maxT = RAY->tmax; \
42 RAY_RT.minT = RAY->tmin;
43
44# define GET_TRAVERSAL_STACK() \
45 Stack stack(kg->global_stack_buffer, kg->shared_stack); \
46 Instance_Stack instance_stack;
47
48# define GET_TRAVERSAL_ANY_HIT(FUNCTION_TABLE, RAY_TYPE, RAY_TIME) \
49 hiprtSceneTraversalAnyHitCustomStack<Stack, Instance_Stack> traversal( \
50 (hiprtScene)kernel_data.device_bvh, \
51 ray_hip, \
52 stack, \
53 instance_stack, \
54 visibility, \
55 hiprtTraversalHintDefault, \
56 &payload, \
57 kernel_params.FUNCTION_TABLE, \
58 RAY_TYPE, \
59 RAY_TIME);
60
61# define GET_TRAVERSAL_CLOSEST_HIT(FUNCTION_TABLE, RAY_TYPE, RAY_TIME) \
62 hiprtSceneTraversalClosestCustomStack<Stack, Instance_Stack> traversal( \
63 (hiprtScene)kernel_data.device_bvh, \
64 ray_hip, \
65 stack, \
66 instance_stack, \
67 visibility, \
68 hiprtTraversalHintDefault, \
69 &payload, \
70 kernel_params.FUNCTION_TABLE, \
71 RAY_TYPE, \
72 RAY_TIME);
73
74ccl_device_inline void set_intersect_point(KernelGlobals kg,
75 const hiprtHit &hit,
77{
78 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
79 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
80
81 isect->type = kernel_data_fetch(objects, object_id).primitive_type;
82
83 isect->t = hit.t;
84 isect->prim = hit.primID + prim_offset;
85 isect->object = object_id;
86 isect->u = hit.uv.x;
87 isect->v = hit.uv.y;
88}
89
90/* --------------------------------------------------------------------
91 * Custom intersection functions.
92 */
93
94ccl_device_inline bool curve_custom_intersect(const hiprtRay &ray,
95 RayPayload *payload,
96 hiprtHit &hit)
97
98{
99 /* Could also cast shadow payload to get the elements needed to do the intersection no need to
100 * write a separate function for shadow intersection. */
101
102 KernelGlobals kg = payload->kg;
103
104 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
105
106 /* `data_offset.x`: where the data (prim id, type )for the geometry of the current object begins
107 * the prim_id that is in hiprtHit hit is local to the particular geometry so we add the above
108 * `ofstream` to map prim id in hiprtHit to the one compatible to what next stage expects
109 * `data_offset.y`: the offset that has to be added to a local primitive to get the global
110 * `primitive id = kernel_data_fetch(object_prim_offset, object_id);` */
111 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
112
113 const int prim_offset = data_offset.y;
114
115 const int2 prim_info = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x);
116 const int curve_index = prim_info.x;
117 const int key_value = prim_info.y;
118
119# ifdef __SHADOW_LINKING__
120 if (intersection_skip_shadow_link(kg, payload->self, object_id)) {
121 return false; /* Ignore hit - continue traversal. */
122 }
123# endif
124
125 if (intersection_skip_self_shadow(payload->self, object_id, curve_index + prim_offset)) {
126 return false;
127 }
128
129 const float ray_time = payload->ray_time;
130
131 if ((key_value & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) {
132 const int time_offset = kernel_data_fetch(prim_time_offset, object_id);
133 const float2 prims_time = kernel_data_fetch(prims_time, hit.primID + time_offset);
134 if (ray_time < prims_time.x || ray_time > prims_time.y) {
135 return false;
136 }
137 }
138
139 Intersection isect;
140 const bool b_hit = curve_intersect(kg,
141 &isect,
142 ray.origin,
143 ray.direction,
144 ray.minT,
145 ray.maxT,
146 object_id,
147 curve_index + prim_offset,
148 ray_time,
149 key_value);
150 if (b_hit) {
151 hit.uv.x = isect.u;
152 hit.uv.y = isect.v;
153 hit.t = isect.t;
154 hit.primID = isect.prim;
155 payload->prim_type = isect.type; /* packed_curve_type */
156 }
157
158 return b_hit;
159}
160
161ccl_device_inline bool motion_triangle_custom_intersect(const hiprtRay &ray,
162 RayPayload *payload,
163 hiprtHit &hit)
164{
165 KernelGlobals kg = payload->kg;
166 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
167 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
168 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
169
170 const int prim_id_local = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x).x;
171 const int prim_id_global = prim_id_local + prim_offset;
172
173 if (intersection_skip_self_shadow(payload->self, object_id, prim_id_global)) {
174 return false;
175 }
176
177 Intersection isect;
178 const bool b_hit = motion_triangle_intersect(kg,
179 &isect,
180 ray.origin,
181 ray.direction,
182 ray.minT,
183 ray.maxT,
184 payload->ray_time,
185 payload->visibility,
186 object_id,
187 prim_id_global,
188 hit.instanceID);
189
190 if (b_hit) {
191 hit.uv.x = isect.u;
192 hit.uv.y = isect.v;
193 hit.t = isect.t;
194 hit.primID = isect.prim;
195 payload->prim_type = isect.type;
196 }
197
198 return b_hit;
199}
200
201ccl_device_inline bool motion_triangle_custom_local_intersect(const hiprtRay &ray,
202 LocalPayload *payload,
203 hiprtHit &hit)
204{
205# ifdef __OBJECT_MOTION__
206 KernelGlobals kg = payload->kg;
207
208 const int object_id = payload->local_object;
209 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
210 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
211
212 const int prim_id_local = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x).x;
213 const int prim_id_global = prim_id_local + prim_offset;
214
215 if (intersection_skip_self_local(payload->self, prim_id_global)) {
216 return false;
217 }
218
219 return motion_triangle_intersect_local(kg,
220 payload->local_isect,
221 ray.origin,
222 ray.direction,
223 payload->ray_time,
224 object_id,
225 prim_id_global,
226 prim_id_local,
227 ray.minT,
228 ray.maxT,
229 payload->lcg_state,
230 payload->max_hits);
231
232# else
233 return false;
234# endif
235}
236
237ccl_device_inline bool motion_triangle_custom_volume_intersect(const hiprtRay &ray,
238 RayPayload *payload,
239 hiprtHit &hit)
240{
241# ifdef __OBJECT_MOTION__
242 KernelGlobals kg = payload->kg;
243
244 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
245 const int object_flag = kernel_data_fetch(object_flag, object_id);
246
247 if (!(object_flag & SD_OBJECT_HAS_VOLUME)) {
248 return false;
249 }
250
251 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
252 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
253
254 const int prim_id_local = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x).x;
255 const int prim_id_global = prim_id_local + prim_offset;
256
257 if (intersection_skip_self_shadow(payload->self, object_id, prim_id_global)) {
258 return false;
259 }
260
261 Intersection isect;
262 const bool b_hit = motion_triangle_intersect(kg,
263 &isect,
264 ray.origin,
265 ray.direction,
266 ray.minT,
267 ray.maxT,
268 payload->ray_time,
269 payload->visibility,
270 object_id,
271 prim_id_global,
272 prim_id_local);
273
274 if (b_hit) {
275 hit.uv.x = isect.u;
276 hit.uv.y = isect.v;
277 hit.t = isect.t;
278 hit.primID = isect.prim;
279 payload->prim_type = isect.type;
280 }
281
282 return b_hit;
283# else
284 return false;
285# endif
286}
287
288ccl_device_inline bool point_custom_intersect(const hiprtRay &ray,
289 RayPayload *payload,
290 hiprtHit &hit)
291{
292# if defined(__POINTCLOUD__)
293 KernelGlobals kg = payload->kg;
294
295 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
296 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
297 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
298
299 const int2 prim_info = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x);
300 const int prim_id_local = prim_info.x;
301 const int prim_id_global = prim_id_local + prim_offset;
302
303 const int primitive_type = prim_info.y;
304
305# ifdef __SHADOW_LINKING__
306 if (intersection_skip_shadow_link(kg, payload->self, object_id)) {
307 return false; /* Ignore hit - continue traversal */
308 }
309# endif
310
311 if (intersection_skip_self_shadow(payload->self, object_id, prim_id_global)) {
312 return false;
313 }
314
315 const float ray_time = payload->ray_time;
316
317 if ((primitive_type & PRIMITIVE_MOTION_POINT) && kernel_data.bvh.use_bvh_steps) {
318 const int time_offset = kernel_data_fetch(prim_time_offset, object_id);
319 const float2 prims_time = kernel_data_fetch(prims_time, hit.primID + time_offset);
320 if (ray_time < prims_time.x || ray_time > prims_time.y) {
321 return false;
322 }
323 }
324
325 Intersection isect;
326 const bool b_hit = point_intersect(kg,
327 &isect,
328 ray.origin,
329 ray.direction,
330 ray.minT,
331 ray.maxT,
332 object_id,
333 prim_id_global,
334 ray_time,
335 primitive_type);
336
337 if (b_hit) {
338 hit.uv.x = isect.u;
339 hit.uv.y = isect.v;
340 hit.t = isect.t;
341 hit.primID = isect.prim;
342 payload->prim_type = isect.type;
343 }
344
345 return b_hit;
346# else
347 return false;
348# endif
349}
350
351/* --------------------------------------------------------------------
352 * Intersection filters.
353 */
354
355ccl_device_inline bool closest_intersection_filter(const hiprtRay &ray,
356 RayPayload *payload,
357 const hiprtHit &hit)
358{
359 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
360 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
361 const int prim = hit.primID + prim_offset;
362
363# ifdef __SHADOW_LINKING__
364 if (intersection_skip_shadow_link(payload->kg, payload->self, object_id)) {
365 return true; /* Ignore hit - continue traversal. */
366 }
367# endif
368
369 if (intersection_skip_self_shadow(payload->self, object_id, prim)) {
370 return true; /* Ignore hit - continue traversal. */
371 }
372
373 return false;
374}
375
376ccl_device_inline bool shadow_intersection_filter(const hiprtRay &ray,
377 ShadowPayload *payload,
378 const hiprtHit &hit)
379
380{
381 KernelGlobals kg = payload->kg;
382
383 const uint num_hits = payload->num_hits;
384 const uint max_hits = payload->max_hits;
385 const int state = payload->in_state;
386 const RaySelfPrimitives &self = payload->self;
387
388 const int object = kernel_data_fetch(user_instance_id, hit.instanceID);
389 const int prim_offset = kernel_data_fetch(object_prim_offset, object);
390 const int prim = hit.primID + prim_offset;
391
392 const float ray_tmax = hit.t;
393
394# ifdef __SHADOW_LINKING__
395 if (intersection_skip_shadow_link(kg, self, object)) {
396 return true; /* Ignore hit - continue traversal */
397 }
398# endif
399
400# ifdef __VISIBILITY_FLAG__
401 if ((kernel_data_fetch(objects, object).visibility & payload->visibility) == 0) {
402 return true; /* No hit - continue traversal. */
403 }
404# endif
405
406 if (intersection_skip_self_shadow(self, object, prim)) {
407 return true; /* No hit -continue traversal. */
408 }
409
410 if (intersection_skip_shadow_already_recoded(kg, state, object, prim, num_hits)) {
411 return true;
412 }
413
414 const float u = hit.uv.x;
415 const float v = hit.uv.y;
416 const int primitive_type = kernel_data_fetch(objects, object).primitive_type;
417
418# ifndef __TRANSPARENT_SHADOWS__
419 return false;
420# else
421 if (num_hits >= max_hits ||
422 !(intersection_get_shader_flags(kg, prim, primitive_type) & SD_HAS_TRANSPARENT_SHADOW))
423 {
424 return false;
425 }
426
427 uint record_index = *payload->r_num_recorded_hits;
428
429 payload->num_hits = num_hits + 1;
430 *(payload->r_num_recorded_hits) += 1;
431
432 const uint max_record_hits = min(max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
433 if (record_index >= max_record_hits) {
434 float max_recorded_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
435 uint max_recorded_hit = 0;
436
437 for (int i = 1; i < max_record_hits; i++) {
438 const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
439 if (isect_t > max_recorded_t) {
440 max_recorded_t = isect_t;
441 max_recorded_hit = i;
442 }
443 }
444
445 if (ray_tmax >= max_recorded_t) {
446 return true;
447 }
448
449 record_index = max_recorded_hit;
450 }
451
452 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, u) = u;
453 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, v) = v;
454 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, t) = ray_tmax;
455 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, prim) = prim;
456 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, object) = object;
457 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, type) = primitive_type;
458
459 return true;
460# endif /* __TRANSPARENT_SHADOWS__ */
461}
462
463ccl_device_inline bool shadow_intersection_filter_curves(const hiprtRay &ray,
464 ShadowPayload *payload,
465 const hiprtHit &hit)
466
467{
468 KernelGlobals kg = payload->kg;
469
470 const uint num_hits = payload->num_hits;
471 const uint num_recorded_hits = *(payload->r_num_recorded_hits);
472 const uint max_hits = payload->max_hits;
473 const RaySelfPrimitives &self = payload->self;
474
475 const int object = kernel_data_fetch(user_instance_id, hit.instanceID);
476 const int prim = hit.primID;
477
478 const float ray_tmax = hit.t;
479
480# ifdef __SHADOW_LINKING__
481 /* It doesn't seem like this is necessary. */
482 if (intersection_skip_shadow_link(kg, self, object)) {
483 return true; /* Ignore hit - continue traversal. */
484 }
485# endif
486
487# ifdef __VISIBILITY_FLAG__
488 if ((kernel_data_fetch(objects, object).visibility & payload->visibility) == 0) {
489 return true; /* No hit - continue traversal. */
490 }
491# endif
492
493 if (intersection_skip_self_shadow(self, object, prim)) {
494 return true; /* No hit -continue traversal. */
495 }
496
497 if (intersection_skip_shadow_already_recoded(kg, payload->in_state, object, prim, num_hits)) {
498 return true;
499 }
500
501 const float u = hit.uv.x;
502 const float v = hit.uv.y;
503
504 if (u == 0.0f || u == 1.0f) {
505 return true; /* Continue traversal. */
506 }
507
508 const int primitive_type = payload->prim_type;
509
510# ifndef __TRANSPARENT_SHADOWS__
511 return false;
512# else
513 if (num_hits >= max_hits ||
514 !(intersection_get_shader_flags(kg, prim, primitive_type) & SD_HAS_TRANSPARENT_SHADOW))
515 {
516 return false;
517 }
518
519 float throughput = *payload->r_throughput;
520 throughput *= intersection_curve_shadow_transparency(kg, object, prim, primitive_type, u);
521 *payload->r_throughput = throughput;
522 payload->num_hits += 1;
523
524 if (throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
525 return false;
526 }
527
528 return true;
529# endif /* __TRANSPARENT_SHADOWS__ */
530}
531
532ccl_device_inline bool local_intersection_filter(const hiprtRay &ray,
533 LocalPayload *payload,
534 const hiprtHit &hit)
535{
536# ifdef __BVH_LOCAL__
537 KernelGlobals kg = payload->kg;
538
539 const int object_id = payload->local_object;
540 const uint max_hits = payload->max_hits;
541
542 /* Triangle primitive uses hardware intersection, other primitives do custom intersection
543 * which does reservoir sampling for intersections. For the custom primitives only check
544 * whether we can stop traversal early on. The rest of the checks here only do for the
545 * regular triangles. */
546 const int primitive_type = kernel_data_fetch(objects, object_id).primitive_type;
547 if (primitive_type != PRIMITIVE_TRIANGLE) {
548 if (max_hits == 0) {
549 return false;
550 }
551 return true;
552 }
553
554 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
555 const int prim = hit.primID + prim_offset;
556# ifndef __RAY_OFFSET__
557 if (intersection_skip_self_local(payload->self, prim)) {
558 return true; /* Continue search. */
559 }
560# endif
561
562 if (max_hits == 0) {
563 return false; /* Stop search. */
564 }
565
566 const int hit_index = local_intersect_get_record_index(
567 payload->local_isect, hit.t, payload->lcg_state, max_hits);
568 if (hit_index == -1) {
569 return true; /* Continue search. */
570 }
571
572 Intersection *isect = &payload->local_isect->hits[hit_index];
573 isect->t = hit.t;
574 isect->u = hit.uv.x;
575 isect->v = hit.uv.y;
576 isect->prim = prim;
577 isect->object = object_id;
578 isect->type = primitive_type;
579
580 payload->local_isect->Ng[hit_index] = hit.normal;
581
582 return true;
583# else
584 return false;
585# endif
586}
587
588ccl_device_inline bool volume_intersection_filter(const hiprtRay &ray,
589 RayPayload *payload,
590 const hiprtHit &hit)
591{
592 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
593 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
594 const int prim = hit.primID + prim_offset;
595 const int object_flag = kernel_data_fetch(object_flag, object_id);
596
597 if (intersection_skip_self(payload->self, object_id, prim)) {
598 return true;
599 }
600 if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
601 return true;
602 }
603 return false;
604}
605
606HIPRT_DEVICE bool intersectFunc(const uint geom_type,
607 const uint ray_type,
608 const hiprtFuncTableHeader &tableHeader,
609 const hiprtRay &ray,
610 void *payload,
611 hiprtHit &hit)
612{
613 const uint index = tableHeader.numGeomTypes * ray_type + geom_type;
614 switch (index) {
617 return curve_custom_intersect(ray, (RayPayload *)payload, hit);
620 return motion_triangle_custom_intersect(ray, (RayPayload *)payload, hit);
622 return motion_triangle_custom_local_intersect(ray, (LocalPayload *)payload, hit);
624 return motion_triangle_custom_volume_intersect(ray, (RayPayload *)payload, hit);
627 return point_custom_intersect(ray, (RayPayload *)payload, hit);
628 default:
629 break;
630 }
631 return false;
632}
633
634HIPRT_DEVICE bool filterFunc(const uint geom_type,
635 const uint ray_type,
636 const hiprtFuncTableHeader &tableHeader,
637 const hiprtRay &ray,
638 void *payload,
639 const hiprtHit &hit)
640{
641 const uint index = tableHeader.numGeomTypes * ray_type + geom_type;
642 switch (index) {
644 return closest_intersection_filter(ray, (RayPayload *)payload, hit);
646 return shadow_intersection_filter_curves(ray, (ShadowPayload *)payload, hit);
650 return shadow_intersection_filter(ray, (ShadowPayload *)payload, hit);
653 return local_intersection_filter(ray, (LocalPayload *)payload, hit);
656 return volume_intersection_filter(ray, (RayPayload *)payload, hit);
657 default:
658 break;
659 }
660 return false;
661}
662
663#endif
unsigned int uint
ATTR_WARN_UNUSED_RESULT const BMVert * v
PyObject * self
ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals kg, const int prim, const int type)
ccl_device_inline bool intersection_skip_shadow_link(KernelGlobals kg, const ccl_ray_data RaySelfPrimitives &self, const int isect_object)
ccl_device_inline bool intersection_skip_self_shadow(const ccl_ray_data RaySelfPrimitives &self, const int object, const int prim)
ccl_device_inline bool intersection_skip_self(const ccl_ray_data RaySelfPrimitives &self, const int object, const int prim)
#define CURVE_SHADOW_TRANSPARENCY_CUTOFF
ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg, const int object, const int prim, const int type, const float u)
ccl_device_forceinline bool intersection_skip_shadow_already_recoded(KernelGlobals kg, IntegratorShadowState state, const int object, const int prim, const int num_hits)
ccl_device_inline bool intersection_skip_self_local(const ccl_ray_data RaySelfPrimitives &self, const int prim)
#define kernel_data
#define kernel_data_fetch(name, index)
#define INTEGRATOR_SHADOW_ISECT_SIZE
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
@ Motion_Triangle_Filter_Volume
@ Motion_Triangle_Filter_Local
@ Triangle_Filter_Closest
@ Curve_Filter_Shadow
@ Motion_Triangle_Filter_Shadow
@ Point_Filter_Shadow
@ Triangle_Filter_Local
@ Triangle_Filter_Volume
@ Triangle_Filter_Shadow
@ Motion_Triangle_Intersect_Shadow
@ Curve_Intersect_Function
@ Motion_Triangle_Intersect_Function
@ Point_Intersect_Shadow
@ Curve_Intersect_Shadow
@ Point_Intersect_Function
@ Motion_Triangle_Intersect_Volume
@ Motion_Triangle_Intersect_Local
@ SD_HAS_TRANSPARENT_SHADOW
@ PRIMITIVE_MOTION
@ PRIMITIVE_TRIANGLE
@ PRIMITIVE_MOTION_POINT
@ SD_OBJECT_HAS_VOLUME
static ulong state[N]
ccl_device_inline bool motion_triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, const float3 P, const float3 dir, const float tmin, const float tmax, const float time, const uint visibility, const int object, const int prim, const int prim_addr)
#define min(a, b)
Definition sort.cc:36
#define INTEGRATOR_STATE_ARRAY_WRITE(state, nested_struct, array_index, member)
Definition state.h:240
#define INTEGRATOR_STATE_ARRAY(state, nested_struct, array_index, member)
Definition state.h:238
float y
int x
Definition types_int2.h:13
int y
Definition types_int2.h:13
i
Definition text_draw.cc:230