raystrack 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1285 @@
1
+ from __future__ import annotations
2
+
3
+ import math
4
+
5
+ import numba as nb
6
+ import numpy as np
7
+ from numba import cuda
8
+
9
+ INF = 1.0e20
10
+ STACK_SIZE = 64
11
+ MAX_SHARED_SURF = 1024
12
+ TREGENZA_BINS = 145
13
+
14
+
15
+ @cuda.jit(device=True, inline=True)
16
+ def _aabb_tmin_dev(o0, o1, o2, inv0, inv1, inv2, bmin0, bmin1, bmin2, bmax0, bmax1, bmax2):
17
+ tmin = (bmin0 - o0) * inv0
18
+ tmax = (bmax0 - o0) * inv0
19
+ if tmin > tmax:
20
+ tmp = tmin
21
+ tmin = tmax
22
+ tmax = tmp
23
+
24
+ tymin = (bmin1 - o1) * inv1
25
+ tymax = (bmax1 - o1) * inv1
26
+ if tymin > tymax:
27
+ tmp = tymin
28
+ tymin = tymax
29
+ tymax = tmp
30
+ if (tmin > tymax) or (tymin > tmax):
31
+ return INF
32
+ if tymin > tmin:
33
+ tmin = tymin
34
+ if tymax < tmax:
35
+ tmax = tymax
36
+
37
+ tzmin = (bmin2 - o2) * inv2
38
+ tzmax = (bmax2 - o2) * inv2
39
+ if tzmin > tzmax:
40
+ tmp = tzmin
41
+ tzmin = tzmax
42
+ tzmax = tmp
43
+ if (tmin > tzmax) or (tzmin > tmax):
44
+ return INF
45
+ if tzmin > tmin:
46
+ tmin = tzmin
47
+ if tzmax < tmax:
48
+ tmax = tzmax
49
+ if tmax < 0.0:
50
+ return INF
51
+ return tmin if tmin > 0.0 else 0.0
52
+
53
+
54
+ @cuda.jit(device=True, inline=True)
55
+ def _skip_surface(surface_id, surf_active, emit_sid, min_sid):
56
+ if surf_active[surface_id] == 0:
57
+ return True
58
+ if surface_id < min_sid:
59
+ return True
60
+ return surface_id == emit_sid
61
+
62
+
63
+ @cuda.jit(device=True, inline=True)
64
+ def _binary_search_cdf(cdf, x):
65
+ lo = 0
66
+ hi = cdf.shape[0] - 1
67
+ while lo <= hi:
68
+ mid = (lo + hi) // 2
69
+ v = cdf[mid]
70
+ if v < x:
71
+ lo = mid + 1
72
+ else:
73
+ hi = mid - 1
74
+ if lo < 0:
75
+ return 0
76
+ if lo >= cdf.shape[0]:
77
+ return cdf.shape[0] - 1
78
+ return lo
79
+
80
+
81
+ @cuda.jit
82
+ def kernel_trace_firsthit(orig, dirs, v0, e1, e2, norm, sid, surf_active, emit_sid, min_sid, hit_sid, hit_front):
83
+ k = cuda.grid(1)
84
+ if k >= orig.shape[0]:
85
+ return
86
+
87
+ o0 = orig[k, 0]
88
+ o1 = orig[k, 1]
89
+ o2 = orig[k, 2]
90
+ d0 = dirs[k, 0]
91
+ d1 = dirs[k, 1]
92
+ d2 = dirs[k, 2]
93
+
94
+ best = INF
95
+ hit = -1
96
+ front = 0
97
+
98
+ for i in range(v0.shape[0]):
99
+ surf = sid[i]
100
+ if _skip_surface(surf, surf_active, emit_sid, min_sid):
101
+ continue
102
+
103
+ px = d1 * e2[i, 2] - d2 * e2[i, 1]
104
+ py = d2 * e2[i, 0] - d0 * e2[i, 2]
105
+ pz = d0 * e2[i, 1] - d1 * e2[i, 0]
106
+ det = e1[i, 0] * px + e1[i, 1] * py + e1[i, 2] * pz
107
+ if abs(det) < 1e-7:
108
+ continue
109
+
110
+ inv_det = 1.0 / det
111
+ tx = o0 - v0[i, 0]
112
+ ty = o1 - v0[i, 1]
113
+ tz = o2 - v0[i, 2]
114
+ u = (tx * px + ty * py + tz * pz) * inv_det
115
+ if u < 0.0 or u > 1.0:
116
+ continue
117
+
118
+ qx = ty * e1[i, 2] - tz * e1[i, 1]
119
+ qy = tz * e1[i, 0] - tx * e1[i, 2]
120
+ qz = tx * e1[i, 1] - ty * e1[i, 0]
121
+ v = (d0 * qx + d1 * qy + d2 * qz) * inv_det
122
+ if v < 0.0 or u + v > 1.0:
123
+ continue
124
+
125
+ tparam = (e2[i, 0] * qx + e2[i, 1] * qy + e2[i, 2] * qz) * inv_det
126
+ if 1e-6 < tparam < best:
127
+ best = tparam
128
+ hit = surf
129
+ front = 1 if -(d0 * norm[i, 0] + d1 * norm[i, 1] + d2 * norm[i, 2]) > 0.0 else 0
130
+
131
+ hit_sid[k] = hit
132
+ hit_front[k] = front if hit >= 0 else 0
133
+
134
+
135
+ @cuda.jit
136
+ def kernel_trace_bvh_firsthit(
137
+ orig,
138
+ dirs,
139
+ v0,
140
+ e1,
141
+ e2,
142
+ norm,
143
+ sid,
144
+ surf_active,
145
+ bb_min,
146
+ bb_max,
147
+ left,
148
+ right,
149
+ start,
150
+ cnt,
151
+ emit_sid,
152
+ min_sid,
153
+ hit_sid,
154
+ hit_front,
155
+ ):
156
+ k = cuda.grid(1)
157
+ if k >= orig.shape[0]:
158
+ return
159
+
160
+ o0 = orig[k, 0]
161
+ o1 = orig[k, 1]
162
+ o2 = orig[k, 2]
163
+ d0 = dirs[k, 0]
164
+ d1 = dirs[k, 1]
165
+ d2 = dirs[k, 2]
166
+
167
+ inv0 = 1.0 / d0 if abs(d0) > 1e-9 else 1e10
168
+ inv1 = 1.0 / d1 if abs(d1) > 1e-9 else 1e10
169
+ inv2 = 1.0 / d2 if abs(d2) > 1e-9 else 1e10
170
+
171
+ root_t = _aabb_tmin_dev(
172
+ o0,
173
+ o1,
174
+ o2,
175
+ inv0,
176
+ inv1,
177
+ inv2,
178
+ bb_min[0, 0],
179
+ bb_min[0, 1],
180
+ bb_min[0, 2],
181
+ bb_max[0, 0],
182
+ bb_max[0, 1],
183
+ bb_max[0, 2],
184
+ )
185
+ if root_t >= INF:
186
+ hit_sid[k] = -1
187
+ hit_front[k] = 0
188
+ return
189
+
190
+ stack = cuda.local.array(STACK_SIZE, nb.int32)
191
+ tstack = cuda.local.array(STACK_SIZE, nb.float32)
192
+ sp = 0
193
+ stack[sp] = 0
194
+ tstack[sp] = root_t
195
+ sp += 1
196
+
197
+ best = INF
198
+ hit = -1
199
+ front = 0
200
+
201
+ while sp > 0:
202
+ sp -= 1
203
+ node = stack[sp]
204
+ node_t = tstack[sp]
205
+ if node_t >= best:
206
+ continue
207
+
208
+ if cnt[node] > 0:
209
+ for t in range(cnt[node]):
210
+ tri = start[node] + t
211
+ surf = sid[tri]
212
+ if _skip_surface(surf, surf_active, emit_sid, min_sid):
213
+ continue
214
+
215
+ px = d1 * e2[tri, 2] - d2 * e2[tri, 1]
216
+ py = d2 * e2[tri, 0] - d0 * e2[tri, 2]
217
+ pz = d0 * e2[tri, 1] - d1 * e2[tri, 0]
218
+ det = e1[tri, 0] * px + e1[tri, 1] * py + e1[tri, 2] * pz
219
+ if abs(det) < 1e-7:
220
+ continue
221
+
222
+ inv_det = 1.0 / det
223
+ tx = o0 - v0[tri, 0]
224
+ ty = o1 - v0[tri, 1]
225
+ tz = o2 - v0[tri, 2]
226
+ u = (tx * px + ty * py + tz * pz) * inv_det
227
+ if u < 0.0 or u > 1.0:
228
+ continue
229
+
230
+ qx = ty * e1[tri, 2] - tz * e1[tri, 1]
231
+ qy = tz * e1[tri, 0] - tx * e1[tri, 2]
232
+ qz = tx * e1[tri, 1] - ty * e1[tri, 0]
233
+ v = (d0 * qx + d1 * qy + d2 * qz) * inv_det
234
+ if v < 0.0 or u + v > 1.0:
235
+ continue
236
+
237
+ tparam = (e2[tri, 0] * qx + e2[tri, 1] * qy + e2[tri, 2] * qz) * inv_det
238
+ if 1e-6 < tparam < best:
239
+ best = tparam
240
+ hit = surf
241
+ front = 1 if -(d0 * norm[tri, 0] + d1 * norm[tri, 1] + d2 * norm[tri, 2]) > 0.0 else 0
242
+ else:
243
+ ln = left[node]
244
+ rn = right[node]
245
+ tl = _aabb_tmin_dev(
246
+ o0,
247
+ o1,
248
+ o2,
249
+ inv0,
250
+ inv1,
251
+ inv2,
252
+ bb_min[ln, 0],
253
+ bb_min[ln, 1],
254
+ bb_min[ln, 2],
255
+ bb_max[ln, 0],
256
+ bb_max[ln, 1],
257
+ bb_max[ln, 2],
258
+ )
259
+ tr = _aabb_tmin_dev(
260
+ o0,
261
+ o1,
262
+ o2,
263
+ inv0,
264
+ inv1,
265
+ inv2,
266
+ bb_min[rn, 0],
267
+ bb_min[rn, 1],
268
+ bb_min[rn, 2],
269
+ bb_max[rn, 0],
270
+ bb_max[rn, 1],
271
+ bb_max[rn, 2],
272
+ )
273
+
274
+ if tl < tr:
275
+ if tr < best and sp < STACK_SIZE:
276
+ stack[sp] = rn
277
+ tstack[sp] = tr
278
+ sp += 1
279
+ if tl < best and sp < STACK_SIZE:
280
+ stack[sp] = ln
281
+ tstack[sp] = tl
282
+ sp += 1
283
+ else:
284
+ if tl < best and sp < STACK_SIZE:
285
+ stack[sp] = ln
286
+ tstack[sp] = tl
287
+ sp += 1
288
+ if tr < best and sp < STACK_SIZE:
289
+ stack[sp] = rn
290
+ tstack[sp] = tr
291
+ sp += 1
292
+
293
+ hit_sid[k] = hit
294
+ hit_front[k] = front if hit >= 0 else 0
295
+
296
+
297
+ @cuda.jit
298
+ def kernel_trace_combined(orig, dirs, v0, e1, e2, norm, sid, surf_active, emit_sid, matrix_min_sid, hit_sid, hit_front, any_hitmask):
299
+ k = cuda.grid(1)
300
+ if k >= orig.shape[0]:
301
+ return
302
+
303
+ o0 = orig[k, 0]
304
+ o1 = orig[k, 1]
305
+ o2 = orig[k, 2]
306
+ d0 = dirs[k, 0]
307
+ d1 = dirs[k, 1]
308
+ d2 = dirs[k, 2]
309
+
310
+ best_matrix = INF
311
+ hit = -1
312
+ front = 0
313
+ any_hit = 0
314
+
315
+ for i in range(v0.shape[0]):
316
+ surf = sid[i]
317
+ if surf == emit_sid or surf_active[surf] == 0:
318
+ continue
319
+
320
+ px = d1 * e2[i, 2] - d2 * e2[i, 1]
321
+ py = d2 * e2[i, 0] - d0 * e2[i, 2]
322
+ pz = d0 * e2[i, 1] - d1 * e2[i, 0]
323
+ det = e1[i, 0] * px + e1[i, 1] * py + e1[i, 2] * pz
324
+ if abs(det) < 1e-7:
325
+ continue
326
+
327
+ inv_det = 1.0 / det
328
+ tx = o0 - v0[i, 0]
329
+ ty = o1 - v0[i, 1]
330
+ tz = o2 - v0[i, 2]
331
+ u = (tx * px + ty * py + tz * pz) * inv_det
332
+ if u < 0.0 or u > 1.0:
333
+ continue
334
+
335
+ qx = ty * e1[i, 2] - tz * e1[i, 1]
336
+ qy = tz * e1[i, 0] - tx * e1[i, 2]
337
+ qz = tx * e1[i, 1] - ty * e1[i, 0]
338
+ v = (d0 * qx + d1 * qy + d2 * qz) * inv_det
339
+ if v < 0.0 or u + v > 1.0:
340
+ continue
341
+
342
+ tparam = (e2[i, 0] * qx + e2[i, 1] * qy + e2[i, 2] * qz) * inv_det
343
+ if tparam <= 1e-6:
344
+ continue
345
+
346
+ any_hit = 1
347
+ if surf < matrix_min_sid:
348
+ continue
349
+ if tparam < best_matrix:
350
+ best_matrix = tparam
351
+ hit = surf
352
+ front = 1 if -(d0 * norm[i, 0] + d1 * norm[i, 1] + d2 * norm[i, 2]) > 0.0 else 0
353
+
354
+ hit_sid[k] = hit
355
+ hit_front[k] = front if hit >= 0 else 0
356
+ any_hitmask[k] = any_hit
357
+
358
+
359
+ @cuda.jit
360
+ def kernel_trace_bvh_combined(
361
+ orig,
362
+ dirs,
363
+ v0,
364
+ e1,
365
+ e2,
366
+ norm,
367
+ sid,
368
+ surf_active,
369
+ bb_min,
370
+ bb_max,
371
+ left,
372
+ right,
373
+ start,
374
+ cnt,
375
+ emit_sid,
376
+ matrix_min_sid,
377
+ hit_sid,
378
+ hit_front,
379
+ any_hitmask,
380
+ ):
381
+ k = cuda.grid(1)
382
+ if k >= orig.shape[0]:
383
+ return
384
+
385
+ o0 = orig[k, 0]
386
+ o1 = orig[k, 1]
387
+ o2 = orig[k, 2]
388
+ d0 = dirs[k, 0]
389
+ d1 = dirs[k, 1]
390
+ d2 = dirs[k, 2]
391
+
392
+ inv0 = 1.0 / d0 if abs(d0) > 1e-9 else 1e10
393
+ inv1 = 1.0 / d1 if abs(d1) > 1e-9 else 1e10
394
+ inv2 = 1.0 / d2 if abs(d2) > 1e-9 else 1e10
395
+
396
+ root_t = _aabb_tmin_dev(
397
+ o0,
398
+ o1,
399
+ o2,
400
+ inv0,
401
+ inv1,
402
+ inv2,
403
+ bb_min[0, 0],
404
+ bb_min[0, 1],
405
+ bb_min[0, 2],
406
+ bb_max[0, 0],
407
+ bb_max[0, 1],
408
+ bb_max[0, 2],
409
+ )
410
+ if root_t >= INF:
411
+ hit_sid[k] = -1
412
+ hit_front[k] = 0
413
+ any_hitmask[k] = 0
414
+ return
415
+
416
+ stack = cuda.local.array(STACK_SIZE, nb.int32)
417
+ tstack = cuda.local.array(STACK_SIZE, nb.float32)
418
+ sp = 0
419
+ stack[sp] = 0
420
+ tstack[sp] = root_t
421
+ sp += 1
422
+
423
+ best_matrix = INF
424
+ hit = -1
425
+ front = 0
426
+ any_hit = 0
427
+
428
+ while sp > 0:
429
+ sp -= 1
430
+ node = stack[sp]
431
+ node_t = tstack[sp]
432
+ if node_t >= best_matrix:
433
+ continue
434
+
435
+ if cnt[node] > 0:
436
+ for t in range(cnt[node]):
437
+ tri = start[node] + t
438
+ surf = sid[tri]
439
+ if surf == emit_sid or surf_active[surf] == 0:
440
+ continue
441
+
442
+ px = d1 * e2[tri, 2] - d2 * e2[tri, 1]
443
+ py = d2 * e2[tri, 0] - d0 * e2[tri, 2]
444
+ pz = d0 * e2[tri, 1] - d1 * e2[tri, 0]
445
+ det = e1[tri, 0] * px + e1[tri, 1] * py + e1[tri, 2] * pz
446
+ if abs(det) < 1e-7:
447
+ continue
448
+
449
+ inv_det = 1.0 / det
450
+ tx = o0 - v0[tri, 0]
451
+ ty = o1 - v0[tri, 1]
452
+ tz = o2 - v0[tri, 2]
453
+ u = (tx * px + ty * py + tz * pz) * inv_det
454
+ if u < 0.0 or u > 1.0:
455
+ continue
456
+
457
+ qx = ty * e1[tri, 2] - tz * e1[tri, 1]
458
+ qy = tz * e1[tri, 0] - tx * e1[tri, 2]
459
+ qz = tx * e1[tri, 1] - ty * e1[tri, 0]
460
+ v = (d0 * qx + d1 * qy + d2 * qz) * inv_det
461
+ if v < 0.0 or u + v > 1.0:
462
+ continue
463
+
464
+ tparam = (e2[tri, 0] * qx + e2[tri, 1] * qy + e2[tri, 2] * qz) * inv_det
465
+ if tparam <= 1e-6:
466
+ continue
467
+
468
+ any_hit = 1
469
+ if surf < matrix_min_sid:
470
+ continue
471
+ if tparam < best_matrix:
472
+ best_matrix = tparam
473
+ hit = surf
474
+ front = 1 if -(d0 * norm[tri, 0] + d1 * norm[tri, 1] + d2 * norm[tri, 2]) > 0.0 else 0
475
+ else:
476
+ ln = left[node]
477
+ rn = right[node]
478
+ tl = _aabb_tmin_dev(
479
+ o0,
480
+ o1,
481
+ o2,
482
+ inv0,
483
+ inv1,
484
+ inv2,
485
+ bb_min[ln, 0],
486
+ bb_min[ln, 1],
487
+ bb_min[ln, 2],
488
+ bb_max[ln, 0],
489
+ bb_max[ln, 1],
490
+ bb_max[ln, 2],
491
+ )
492
+ tr = _aabb_tmin_dev(
493
+ o0,
494
+ o1,
495
+ o2,
496
+ inv0,
497
+ inv1,
498
+ inv2,
499
+ bb_min[rn, 0],
500
+ bb_min[rn, 1],
501
+ bb_min[rn, 2],
502
+ bb_max[rn, 0],
503
+ bb_max[rn, 1],
504
+ bb_max[rn, 2],
505
+ )
506
+
507
+ if tl < tr:
508
+ if tr < best_matrix and sp < STACK_SIZE:
509
+ stack[sp] = rn
510
+ tstack[sp] = tr
511
+ sp += 1
512
+ if tl < best_matrix and sp < STACK_SIZE:
513
+ stack[sp] = ln
514
+ tstack[sp] = tl
515
+ sp += 1
516
+ else:
517
+ if tl < best_matrix and sp < STACK_SIZE:
518
+ stack[sp] = ln
519
+ tstack[sp] = tl
520
+ sp += 1
521
+ if tr < best_matrix and sp < STACK_SIZE:
522
+ stack[sp] = rn
523
+ tstack[sp] = tr
524
+ sp += 1
525
+
526
+ hit_sid[k] = hit
527
+ hit_front[k] = front if hit >= 0 else 0
528
+ any_hitmask[k] = any_hit
529
+
530
+
531
+ @cuda.jit
532
+ def kernel_reduce_hits(hit_sid, hit_front, hits_f, hits_b, n_surf):
533
+ tid = cuda.threadIdx.x
534
+ block_size = cuda.blockDim.x
535
+ idx = cuda.grid(1)
536
+ stride = cuda.gridsize(1)
537
+
538
+ if n_surf <= MAX_SHARED_SURF:
539
+ shared_f = cuda.shared.array(MAX_SHARED_SURF, nb.int32)
540
+ shared_b = cuda.shared.array(MAX_SHARED_SURF, nb.int32)
541
+
542
+ i = tid
543
+ while i < n_surf:
544
+ shared_f[i] = 0
545
+ shared_b[i] = 0
546
+ i += block_size
547
+ cuda.syncthreads()
548
+
549
+ i = idx
550
+ while i < hit_sid.shape[0]:
551
+ hit = hit_sid[i]
552
+ if 0 <= hit < n_surf:
553
+ if hit_front[i] != 0:
554
+ cuda.atomic.add(shared_f, hit, 1)
555
+ else:
556
+ cuda.atomic.add(shared_b, hit, 1)
557
+ i += stride
558
+ cuda.syncthreads()
559
+
560
+ i = tid
561
+ while i < n_surf:
562
+ val_f = shared_f[i]
563
+ val_b = shared_b[i]
564
+ if val_f != 0:
565
+ cuda.atomic.add(hits_f, i, val_f)
566
+ if val_b != 0:
567
+ cuda.atomic.add(hits_b, i, val_b)
568
+ i += block_size
569
+ else:
570
+ i = idx
571
+ while i < hit_sid.shape[0]:
572
+ hit = hit_sid[i]
573
+ if 0 <= hit < n_surf:
574
+ if hit_front[i] != 0:
575
+ cuda.atomic.add(hits_f, hit, 1)
576
+ else:
577
+ cuda.atomic.add(hits_b, hit, 1)
578
+ i += stride
579
+
580
+
581
+ @cuda.jit
582
+ def kernel_accumulate_hits(hits_f_iter, hits_b_iter, hits_f_total, hits_b_total):
583
+ i = cuda.grid(1)
584
+ if i >= hits_f_iter.shape[0]:
585
+ return
586
+ hits_f_total[i] += hits_f_iter[i]
587
+ hits_b_total[i] += hits_b_iter[i]
588
+
589
+
590
+ @cuda.jit
591
+ def kernel_accumulate_hits_stats(
592
+ hits_f_iter,
593
+ hits_b_iter,
594
+ hits_f_total,
595
+ hits_b_total,
596
+ sum_f,
597
+ sumsq_f,
598
+ sum_b,
599
+ sumsq_b,
600
+ inv_rays,
601
+ ):
602
+ i = cuda.grid(1)
603
+ if i >= hits_f_iter.shape[0]:
604
+ return
605
+
606
+ hf = hits_f_iter[i]
607
+ hb = hits_b_iter[i]
608
+ xf = float(hf) * inv_rays
609
+ xb = float(hb) * inv_rays
610
+
611
+ hits_f_total[i] += hf
612
+ hits_b_total[i] += hb
613
+ sum_f[i] += xf
614
+ sumsq_f[i] += xf * xf
615
+ sum_b[i] += xb
616
+ sumsq_b[i] += xb * xb
617
+
618
+
619
+ @cuda.jit
620
+ def kernel_zero_i64(a):
621
+ i = cuda.grid(1)
622
+ if i < a.size:
623
+ a[i] = 0
624
+
625
+
626
+ @cuda.jit
627
+ def kernel_zero_i32(a):
628
+ i = cuda.grid(1)
629
+ if i < a.size:
630
+ a[i] = 0
631
+
632
+
633
+ @cuda.jit
634
+ def kernel_build_rays(
635
+ u_grid,
636
+ v_grid,
637
+ halton_tri,
638
+ halton_u,
639
+ halton_v,
640
+ halton_r1,
641
+ halton_r2,
642
+ cdf,
643
+ tri_a,
644
+ tri_e1,
645
+ tri_e2,
646
+ tri_u,
647
+ tri_v,
648
+ tri_n,
649
+ tri_origin_eps,
650
+ rays_per_cell,
651
+ orig,
652
+ dire,
653
+ cp_grid,
654
+ cp_dims,
655
+ ):
656
+ k = cuda.grid(1)
657
+ n_rays = orig.shape[0]
658
+ if k >= n_rays:
659
+ return
660
+
661
+ cell = k // rays_per_cell
662
+ ug = (u_grid[cell] + cp_grid[0]) % 1.0
663
+ vg = (v_grid[cell] + cp_grid[1]) % 1.0
664
+
665
+ q_tri = (halton_tri[k] + cp_dims[0]) % 1.0
666
+ tri = _binary_search_cdf(cdf, q_tri)
667
+
668
+ ur = (halton_u[k] + cp_dims[1] + ug) % 1.0
669
+ vr = (halton_v[k] + cp_dims[2] + vg) % 1.0
670
+
671
+ s = math.sqrt(ur)
672
+ mix_b = s * vr
673
+ mix_c = s * (1.0 - vr)
674
+
675
+ ax = tri_a[tri, 0]
676
+ ay = tri_a[tri, 1]
677
+ az = tri_a[tri, 2]
678
+
679
+ px = ax + mix_b * tri_e1[tri, 0] + mix_c * tri_e2[tri, 0]
680
+ py = ay + mix_b * tri_e1[tri, 1] + mix_c * tri_e2[tri, 1]
681
+ pz = az + mix_b * tri_e1[tri, 2] + mix_c * tri_e2[tri, 2]
682
+
683
+ r1 = (halton_r1[k] + cp_dims[3]) % 1.0
684
+ r2 = (halton_r2[k] + cp_dims[4]) % 1.0
685
+ sin_t = math.sqrt(1.0 - r1)
686
+ phi = 6.283185307179586 * r2
687
+ x = sin_t * math.cos(phi)
688
+ y = sin_t * math.sin(phi)
689
+ z = math.sqrt(r1)
690
+
691
+ dx = x * tri_u[tri, 0] + y * tri_v[tri, 0] + z * tri_n[tri, 0]
692
+ dy = x * tri_u[tri, 1] + y * tri_v[tri, 1] + z * tri_n[tri, 1]
693
+ dz = x * tri_u[tri, 2] + y * tri_v[tri, 2] + z * tri_n[tri, 2]
694
+ eps = tri_origin_eps[tri]
695
+
696
+ orig[k, 0] = px + eps * tri_n[tri, 0]
697
+ orig[k, 1] = py + eps * tri_n[tri, 1]
698
+ orig[k, 2] = pz + eps * tri_n[tri, 2]
699
+ dire[k, 0] = dx
700
+ dire[k, 1] = dy
701
+ dire[k, 2] = dz
702
+
703
+
704
+ @cuda.jit(device=True, inline=True)
705
+ def _tregenza_patch_id(dx, dy, dz):
706
+ if dz <= 0.0:
707
+ return -1
708
+
709
+ ring_hi_sin = (
710
+ 0.20791169081775934,
711
+ 0.40673664307580015,
712
+ 0.5877852522924731,
713
+ 0.7431448254773942,
714
+ 0.8660254037844386,
715
+ 0.9510565162951535,
716
+ 0.9945218953682733,
717
+ 1.0,
718
+ )
719
+ ring_n = (30, 30, 24, 24, 18, 12, 6, 1)
720
+ ring_start = (0, 30, 60, 84, 108, 126, 138, 144)
721
+
722
+ ridx = 7
723
+ for j in range(8):
724
+ if dz < ring_hi_sin[j] or j == 7:
725
+ ridx = j
726
+ break
727
+
728
+ n_az = ring_n[ridx]
729
+ base = ring_start[ridx]
730
+ if n_az == 1:
731
+ return base
732
+
733
+ az = math.atan2(dy, dx) * 57.29577951308232
734
+ if az < 0.0:
735
+ az += 360.0
736
+ width = 360.0 / n_az
737
+ off = (180.0 / n_az) if (ridx & 1) == 1 else 0.0
738
+ t = az - off
739
+ if t < 0.0:
740
+ t += 360.0
741
+ elif t >= 360.0:
742
+ t -= 360.0
743
+ aidx = int(t // width)
744
+ if aidx >= n_az:
745
+ aidx = n_az - 1
746
+ return base + aidx
747
+
748
+
749
+ @cuda.jit
750
+ def kernel_bin_tregenza(dirs, any_hitmask, counts):
751
+ shared_counts = cuda.shared.array(TREGENZA_BINS, nb.int32)
752
+ tid = cuda.threadIdx.x
753
+ block_size = cuda.blockDim.x
754
+ idx = cuda.grid(1)
755
+ stride = cuda.gridsize(1)
756
+
757
+ i = tid
758
+ while i < TREGENZA_BINS:
759
+ shared_counts[i] = 0
760
+ i += block_size
761
+ cuda.syncthreads()
762
+
763
+ i = idx
764
+ while i < dirs.shape[0]:
765
+ if any_hitmask[i] == 0:
766
+ pid = _tregenza_patch_id(dirs[i, 0], dirs[i, 1], dirs[i, 2])
767
+ if pid >= 0:
768
+ cuda.atomic.add(shared_counts, pid, 1)
769
+ i += stride
770
+ cuda.syncthreads()
771
+
772
+ i = tid
773
+ while i < TREGENZA_BINS:
774
+ val = shared_counts[i]
775
+ if val != 0:
776
+ cuda.atomic.add(counts, i, val)
777
+ i += block_size
778
+
779
+
780
+ @cuda.jit
781
+ def kernel_count_upward_misses(dirs, any_hitmask, count):
782
+ shared_total = cuda.shared.array(1, nb.int32)
783
+ tid = cuda.threadIdx.x
784
+ idx = cuda.grid(1)
785
+ stride = cuda.gridsize(1)
786
+
787
+ if tid == 0:
788
+ shared_total[0] = 0
789
+ cuda.syncthreads()
790
+
791
+ i = idx
792
+ while i < dirs.shape[0]:
793
+ if any_hitmask[i] == 0 and dirs[i, 2] > 0.0:
794
+ cuda.atomic.add(shared_total, 0, 1)
795
+ i += stride
796
+ cuda.syncthreads()
797
+
798
+ if tid == 0 and shared_total[0] != 0:
799
+ cuda.atomic.add(count, 0, shared_total[0])
800
+
801
+
802
+ @cuda.jit
803
+ def kernel_trace_tregenza(orig, dirs, v0, e1, e2, sid, surf_active, emit_sid, min_sid, counts):
804
+ shared_counts = cuda.shared.array(TREGENZA_BINS, nb.int32)
805
+ tid = cuda.threadIdx.x
806
+ block_size = cuda.blockDim.x
807
+ idx = cuda.grid(1)
808
+ stride = cuda.gridsize(1)
809
+
810
+ i = tid
811
+ while i < TREGENZA_BINS:
812
+ shared_counts[i] = 0
813
+ i += block_size
814
+ cuda.syncthreads()
815
+
816
+ i = idx
817
+ while i < orig.shape[0]:
818
+ o0 = orig[i, 0]
819
+ o1 = orig[i, 1]
820
+ o2 = orig[i, 2]
821
+ d0 = dirs[i, 0]
822
+ d1 = dirs[i, 1]
823
+ d2 = dirs[i, 2]
824
+
825
+ hit_any = 0
826
+ for tri in range(v0.shape[0]):
827
+ surf = sid[tri]
828
+ if _skip_surface(surf, surf_active, emit_sid, min_sid):
829
+ continue
830
+
831
+ px = d1 * e2[tri, 2] - d2 * e2[tri, 1]
832
+ py = d2 * e2[tri, 0] - d0 * e2[tri, 2]
833
+ pz = d0 * e2[tri, 1] - d1 * e2[tri, 0]
834
+ det = e1[tri, 0] * px + e1[tri, 1] * py + e1[tri, 2] * pz
835
+ if abs(det) < 1e-7:
836
+ continue
837
+
838
+ inv_det = 1.0 / det
839
+ tx = o0 - v0[tri, 0]
840
+ ty = o1 - v0[tri, 1]
841
+ tz = o2 - v0[tri, 2]
842
+ u = (tx * px + ty * py + tz * pz) * inv_det
843
+ if u < 0.0 or u > 1.0:
844
+ continue
845
+
846
+ qx = ty * e1[tri, 2] - tz * e1[tri, 1]
847
+ qy = tz * e1[tri, 0] - tx * e1[tri, 2]
848
+ qz = tx * e1[tri, 1] - ty * e1[tri, 0]
849
+ v = (d0 * qx + d1 * qy + d2 * qz) * inv_det
850
+ if v < 0.0 or u + v > 1.0:
851
+ continue
852
+
853
+ tparam = (e2[tri, 0] * qx + e2[tri, 1] * qy + e2[tri, 2] * qz) * inv_det
854
+ if tparam > 1e-6:
855
+ hit_any = 1
856
+ break
857
+
858
+ if hit_any == 0:
859
+ pid = _tregenza_patch_id(d0, d1, d2)
860
+ if pid >= 0:
861
+ cuda.atomic.add(shared_counts, pid, 1)
862
+ i += stride
863
+ cuda.syncthreads()
864
+
865
+ i = tid
866
+ while i < TREGENZA_BINS:
867
+ val = shared_counts[i]
868
+ if val != 0:
869
+ cuda.atomic.add(counts, i, val)
870
+ i += block_size
871
+
872
+
873
+ @cuda.jit
874
+ def kernel_trace_count_upward(orig, dirs, v0, e1, e2, sid, surf_active, emit_sid, min_sid, count):
875
+ shared_total = cuda.shared.array(1, nb.int32)
876
+ tid = cuda.threadIdx.x
877
+ idx = cuda.grid(1)
878
+ stride = cuda.gridsize(1)
879
+
880
+ if tid == 0:
881
+ shared_total[0] = 0
882
+ cuda.syncthreads()
883
+
884
+ i = idx
885
+ while i < orig.shape[0]:
886
+ o0 = orig[i, 0]
887
+ o1 = orig[i, 1]
888
+ o2 = orig[i, 2]
889
+ d0 = dirs[i, 0]
890
+ d1 = dirs[i, 1]
891
+ d2 = dirs[i, 2]
892
+
893
+ hit_any = 0
894
+ for tri in range(v0.shape[0]):
895
+ surf = sid[tri]
896
+ if _skip_surface(surf, surf_active, emit_sid, min_sid):
897
+ continue
898
+
899
+ px = d1 * e2[tri, 2] - d2 * e2[tri, 1]
900
+ py = d2 * e2[tri, 0] - d0 * e2[tri, 2]
901
+ pz = d0 * e2[tri, 1] - d1 * e2[tri, 0]
902
+ det = e1[tri, 0] * px + e1[tri, 1] * py + e1[tri, 2] * pz
903
+ if abs(det) < 1e-7:
904
+ continue
905
+
906
+ inv_det = 1.0 / det
907
+ tx = o0 - v0[tri, 0]
908
+ ty = o1 - v0[tri, 1]
909
+ tz = o2 - v0[tri, 2]
910
+ u = (tx * px + ty * py + tz * pz) * inv_det
911
+ if u < 0.0 or u > 1.0:
912
+ continue
913
+
914
+ qx = ty * e1[tri, 2] - tz * e1[tri, 1]
915
+ qy = tz * e1[tri, 0] - tx * e1[tri, 2]
916
+ qz = tx * e1[tri, 1] - ty * e1[tri, 0]
917
+ v = (d0 * qx + d1 * qy + d2 * qz) * inv_det
918
+ if v < 0.0 or u + v > 1.0:
919
+ continue
920
+
921
+ tparam = (e2[tri, 0] * qx + e2[tri, 1] * qy + e2[tri, 2] * qz) * inv_det
922
+ if tparam > 1e-6:
923
+ hit_any = 1
924
+ break
925
+
926
+ if hit_any == 0 and d2 > 0.0:
927
+ cuda.atomic.add(shared_total, 0, 1)
928
+ i += stride
929
+ cuda.syncthreads()
930
+
931
+ if tid == 0 and shared_total[0] != 0:
932
+ cuda.atomic.add(count, 0, shared_total[0])
933
+
934
+
935
+ @cuda.jit
936
+ def kernel_trace_bvh_tregenza(
937
+ orig,
938
+ dirs,
939
+ v0,
940
+ e1,
941
+ e2,
942
+ sid,
943
+ surf_active,
944
+ bb_min,
945
+ bb_max,
946
+ left,
947
+ right,
948
+ start,
949
+ cnt,
950
+ emit_sid,
951
+ min_sid,
952
+ counts,
953
+ ):
954
+ shared_counts = cuda.shared.array(TREGENZA_BINS, nb.int32)
955
+ tid = cuda.threadIdx.x
956
+ block_size = cuda.blockDim.x
957
+ idx = cuda.grid(1)
958
+ stride = cuda.gridsize(1)
959
+
960
+ i = tid
961
+ while i < TREGENZA_BINS:
962
+ shared_counts[i] = 0
963
+ i += block_size
964
+ cuda.syncthreads()
965
+
966
+ i = idx
967
+ while i < orig.shape[0]:
968
+ o0 = orig[i, 0]
969
+ o1 = orig[i, 1]
970
+ o2 = orig[i, 2]
971
+ d0 = dirs[i, 0]
972
+ d1 = dirs[i, 1]
973
+ d2 = dirs[i, 2]
974
+
975
+ inv0 = 1.0 / d0 if abs(d0) > 1e-9 else 1e10
976
+ inv1 = 1.0 / d1 if abs(d1) > 1e-9 else 1e10
977
+ inv2 = 1.0 / d2 if abs(d2) > 1e-9 else 1e10
978
+
979
+ root_t = _aabb_tmin_dev(
980
+ o0,
981
+ o1,
982
+ o2,
983
+ inv0,
984
+ inv1,
985
+ inv2,
986
+ bb_min[0, 0],
987
+ bb_min[0, 1],
988
+ bb_min[0, 2],
989
+ bb_max[0, 0],
990
+ bb_max[0, 1],
991
+ bb_max[0, 2],
992
+ )
993
+
994
+ hit_any = 0
995
+ if root_t < INF:
996
+ stack = cuda.local.array(STACK_SIZE, nb.int32)
997
+ tstack = cuda.local.array(STACK_SIZE, nb.float32)
998
+ sp = 0
999
+ stack[sp] = 0
1000
+ tstack[sp] = root_t
1001
+ sp += 1
1002
+
1003
+ while sp > 0 and hit_any == 0:
1004
+ sp -= 1
1005
+ node = stack[sp]
1006
+
1007
+ if cnt[node] > 0:
1008
+ for t in range(cnt[node]):
1009
+ tri = start[node] + t
1010
+ surf = sid[tri]
1011
+ if _skip_surface(surf, surf_active, emit_sid, min_sid):
1012
+ continue
1013
+
1014
+ px = d1 * e2[tri, 2] - d2 * e2[tri, 1]
1015
+ py = d2 * e2[tri, 0] - d0 * e2[tri, 2]
1016
+ pz = d0 * e2[tri, 1] - d1 * e2[tri, 0]
1017
+ det = e1[tri, 0] * px + e1[tri, 1] * py + e1[tri, 2] * pz
1018
+ if abs(det) < 1e-7:
1019
+ continue
1020
+
1021
+ inv_det = 1.0 / det
1022
+ tx = o0 - v0[tri, 0]
1023
+ ty = o1 - v0[tri, 1]
1024
+ tz = o2 - v0[tri, 2]
1025
+ u = (tx * px + ty * py + tz * pz) * inv_det
1026
+ if u < 0.0 or u > 1.0:
1027
+ continue
1028
+
1029
+ qx = ty * e1[tri, 2] - tz * e1[tri, 1]
1030
+ qy = tz * e1[tri, 0] - tx * e1[tri, 2]
1031
+ qz = tx * e1[tri, 1] - ty * e1[tri, 0]
1032
+ v = (d0 * qx + d1 * qy + d2 * qz) * inv_det
1033
+ if v < 0.0 or u + v > 1.0:
1034
+ continue
1035
+
1036
+ tparam = (e2[tri, 0] * qx + e2[tri, 1] * qy + e2[tri, 2] * qz) * inv_det
1037
+ if tparam > 1e-6:
1038
+ hit_any = 1
1039
+ break
1040
+ else:
1041
+ ln = left[node]
1042
+ rn = right[node]
1043
+ tl = _aabb_tmin_dev(
1044
+ o0,
1045
+ o1,
1046
+ o2,
1047
+ inv0,
1048
+ inv1,
1049
+ inv2,
1050
+ bb_min[ln, 0],
1051
+ bb_min[ln, 1],
1052
+ bb_min[ln, 2],
1053
+ bb_max[ln, 0],
1054
+ bb_max[ln, 1],
1055
+ bb_max[ln, 2],
1056
+ )
1057
+ tr = _aabb_tmin_dev(
1058
+ o0,
1059
+ o1,
1060
+ o2,
1061
+ inv0,
1062
+ inv1,
1063
+ inv2,
1064
+ bb_min[rn, 0],
1065
+ bb_min[rn, 1],
1066
+ bb_min[rn, 2],
1067
+ bb_max[rn, 0],
1068
+ bb_max[rn, 1],
1069
+ bb_max[rn, 2],
1070
+ )
1071
+
1072
+ if tl < tr:
1073
+ if tr < INF and sp < STACK_SIZE:
1074
+ stack[sp] = rn
1075
+ tstack[sp] = tr
1076
+ sp += 1
1077
+ if tl < INF and sp < STACK_SIZE:
1078
+ stack[sp] = ln
1079
+ tstack[sp] = tl
1080
+ sp += 1
1081
+ else:
1082
+ if tl < INF and sp < STACK_SIZE:
1083
+ stack[sp] = ln
1084
+ tstack[sp] = tl
1085
+ sp += 1
1086
+ if tr < INF and sp < STACK_SIZE:
1087
+ stack[sp] = rn
1088
+ tstack[sp] = tr
1089
+ sp += 1
1090
+
1091
+ if hit_any == 0:
1092
+ pid = _tregenza_patch_id(d0, d1, d2)
1093
+ if pid >= 0:
1094
+ cuda.atomic.add(shared_counts, pid, 1)
1095
+ i += stride
1096
+ cuda.syncthreads()
1097
+
1098
+ i = tid
1099
+ while i < TREGENZA_BINS:
1100
+ val = shared_counts[i]
1101
+ if val != 0:
1102
+ cuda.atomic.add(counts, i, val)
1103
+ i += block_size
1104
+
1105
+
1106
+ @cuda.jit
1107
+ def kernel_trace_bvh_count_upward(
1108
+ orig,
1109
+ dirs,
1110
+ v0,
1111
+ e1,
1112
+ e2,
1113
+ sid,
1114
+ surf_active,
1115
+ bb_min,
1116
+ bb_max,
1117
+ left,
1118
+ right,
1119
+ start,
1120
+ cnt,
1121
+ emit_sid,
1122
+ min_sid,
1123
+ count,
1124
+ ):
1125
+ shared_total = cuda.shared.array(1, nb.int32)
1126
+ tid = cuda.threadIdx.x
1127
+ idx = cuda.grid(1)
1128
+ stride = cuda.gridsize(1)
1129
+
1130
+ if tid == 0:
1131
+ shared_total[0] = 0
1132
+ cuda.syncthreads()
1133
+
1134
+ i = idx
1135
+ while i < orig.shape[0]:
1136
+ o0 = orig[i, 0]
1137
+ o1 = orig[i, 1]
1138
+ o2 = orig[i, 2]
1139
+ d0 = dirs[i, 0]
1140
+ d1 = dirs[i, 1]
1141
+ d2 = dirs[i, 2]
1142
+
1143
+ inv0 = 1.0 / d0 if abs(d0) > 1e-9 else 1e10
1144
+ inv1 = 1.0 / d1 if abs(d1) > 1e-9 else 1e10
1145
+ inv2 = 1.0 / d2 if abs(d2) > 1e-9 else 1e10
1146
+
1147
+ root_t = _aabb_tmin_dev(
1148
+ o0,
1149
+ o1,
1150
+ o2,
1151
+ inv0,
1152
+ inv1,
1153
+ inv2,
1154
+ bb_min[0, 0],
1155
+ bb_min[0, 1],
1156
+ bb_min[0, 2],
1157
+ bb_max[0, 0],
1158
+ bb_max[0, 1],
1159
+ bb_max[0, 2],
1160
+ )
1161
+
1162
+ hit_any = 0
1163
+ if root_t < INF:
1164
+ stack = cuda.local.array(STACK_SIZE, nb.int32)
1165
+ tstack = cuda.local.array(STACK_SIZE, nb.float32)
1166
+ sp = 0
1167
+ stack[sp] = 0
1168
+ tstack[sp] = root_t
1169
+ sp += 1
1170
+
1171
+ while sp > 0 and hit_any == 0:
1172
+ sp -= 1
1173
+ node = stack[sp]
1174
+
1175
+ if cnt[node] > 0:
1176
+ for t in range(cnt[node]):
1177
+ tri = start[node] + t
1178
+ surf = sid[tri]
1179
+ if _skip_surface(surf, surf_active, emit_sid, min_sid):
1180
+ continue
1181
+
1182
+ px = d1 * e2[tri, 2] - d2 * e2[tri, 1]
1183
+ py = d2 * e2[tri, 0] - d0 * e2[tri, 2]
1184
+ pz = d0 * e2[tri, 1] - d1 * e2[tri, 0]
1185
+ det = e1[tri, 0] * px + e1[tri, 1] * py + e1[tri, 2] * pz
1186
+ if abs(det) < 1e-7:
1187
+ continue
1188
+
1189
+ inv_det = 1.0 / det
1190
+ tx = o0 - v0[tri, 0]
1191
+ ty = o1 - v0[tri, 1]
1192
+ tz = o2 - v0[tri, 2]
1193
+ u = (tx * px + ty * py + tz * pz) * inv_det
1194
+ if u < 0.0 or u > 1.0:
1195
+ continue
1196
+
1197
+ qx = ty * e1[tri, 2] - tz * e1[tri, 1]
1198
+ qy = tz * e1[tri, 0] - tx * e1[tri, 2]
1199
+ qz = tx * e1[tri, 1] - ty * e1[tri, 0]
1200
+ v = (d0 * qx + d1 * qy + d2 * qz) * inv_det
1201
+ if v < 0.0 or u + v > 1.0:
1202
+ continue
1203
+
1204
+ tparam = (e2[tri, 0] * qx + e2[tri, 1] * qy + e2[tri, 2] * qz) * inv_det
1205
+ if tparam > 1e-6:
1206
+ hit_any = 1
1207
+ break
1208
+ else:
1209
+ ln = left[node]
1210
+ rn = right[node]
1211
+ tl = _aabb_tmin_dev(
1212
+ o0,
1213
+ o1,
1214
+ o2,
1215
+ inv0,
1216
+ inv1,
1217
+ inv2,
1218
+ bb_min[ln, 0],
1219
+ bb_min[ln, 1],
1220
+ bb_min[ln, 2],
1221
+ bb_max[ln, 0],
1222
+ bb_max[ln, 1],
1223
+ bb_max[ln, 2],
1224
+ )
1225
+ tr = _aabb_tmin_dev(
1226
+ o0,
1227
+ o1,
1228
+ o2,
1229
+ inv0,
1230
+ inv1,
1231
+ inv2,
1232
+ bb_min[rn, 0],
1233
+ bb_min[rn, 1],
1234
+ bb_min[rn, 2],
1235
+ bb_max[rn, 0],
1236
+ bb_max[rn, 1],
1237
+ bb_max[rn, 2],
1238
+ )
1239
+
1240
+ if tl < tr:
1241
+ if tr < INF and sp < STACK_SIZE:
1242
+ stack[sp] = rn
1243
+ tstack[sp] = tr
1244
+ sp += 1
1245
+ if tl < INF and sp < STACK_SIZE:
1246
+ stack[sp] = ln
1247
+ tstack[sp] = tl
1248
+ sp += 1
1249
+ else:
1250
+ if tl < INF and sp < STACK_SIZE:
1251
+ stack[sp] = ln
1252
+ tstack[sp] = tl
1253
+ sp += 1
1254
+ if tr < INF and sp < STACK_SIZE:
1255
+ stack[sp] = rn
1256
+ tstack[sp] = tr
1257
+ sp += 1
1258
+
1259
+ if hit_any == 0 and d2 > 0.0:
1260
+ cuda.atomic.add(shared_total, 0, 1)
1261
+ i += stride
1262
+ cuda.syncthreads()
1263
+
1264
+ if tid == 0 and shared_total[0] != 0:
1265
+ cuda.atomic.add(count, 0, shared_total[0])
1266
+
1267
+
1268
+ __all__ = [
1269
+ "kernel_trace_firsthit",
1270
+ "kernel_trace_bvh_firsthit",
1271
+ "kernel_trace_combined",
1272
+ "kernel_trace_bvh_combined",
1273
+ "kernel_reduce_hits",
1274
+ "kernel_accumulate_hits",
1275
+ "kernel_accumulate_hits_stats",
1276
+ "kernel_zero_i64",
1277
+ "kernel_zero_i32",
1278
+ "kernel_build_rays",
1279
+ "kernel_bin_tregenza",
1280
+ "kernel_count_upward_misses",
1281
+ "kernel_trace_tregenza",
1282
+ "kernel_trace_bvh_tregenza",
1283
+ "kernel_trace_count_upward",
1284
+ "kernel_trace_bvh_count_upward",
1285
+ ]