rayd 0.2.0__tar.gz → 0.2.2__tar.gz

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.
Files changed (135) hide show
  1. {rayd-0.2.0 → rayd-0.2.2}/CMakeLists.txt +2 -0
  2. {rayd-0.2.0 → rayd-0.2.2}/PKG-INFO +1 -1
  3. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/scene/scene_edge.h +1 -0
  4. {rayd-0.2.0 → rayd-0.2.2}/pyproject.toml +1 -1
  5. {rayd-0.2.0 → rayd-0.2.2}/src/multipath/reflection_dedup.cu +41 -0
  6. {rayd-0.2.0 → rayd-0.2.2}/src/multipath/reflection_trace_host.cpp +6 -0
  7. rayd-0.2.2/src/native_launch_audit.cpp +170 -0
  8. rayd-0.2.2/src/native_launch_audit.h +90 -0
  9. {rayd-0.2.0 → rayd-0.2.2}/src/rayd.cpp +109 -0
  10. {rayd-0.2.0 → rayd-0.2.2}/src/scene/edge_bvh.cu +209 -60
  11. {rayd-0.2.0 → rayd-0.2.2}/src/scene/scene.cpp +5 -54
  12. {rayd-0.2.0 → rayd-0.2.2}/src/scene/scene_edge.cpp +9 -51
  13. {rayd-0.2.0 → rayd-0.2.2}/src/scene/scene_optix.cpp +11 -0
  14. rayd-0.2.2/tests/benchmark_edge_bvh_cutoff_compare.py +259 -0
  15. {rayd-0.2.0 → rayd-0.2.2}/tests/drjit/test_geometry.py +40 -0
  16. rayd-0.2.2/tests/profile_kernel_launches.py +303 -0
  17. {rayd-0.2.0 → rayd-0.2.2}/.github/constraints/drjit-build.txt +0 -0
  18. {rayd-0.2.0 → rayd-0.2.2}/.github/workflows/pypi.yml +0 -0
  19. {rayd-0.2.0 → rayd-0.2.2}/.gitignore +0 -0
  20. {rayd-0.2.0 → rayd-0.2.2}/LICENSE +0 -0
  21. {rayd-0.2.0 → rayd-0.2.2}/README.md +0 -0
  22. {rayd-0.2.0 → rayd-0.2.2}/cmake/embed_ptx.cmake +0 -0
  23. {rayd-0.2.0 → rayd-0.2.2}/docs/api_reference.md +0 -0
  24. {rayd-0.2.0 → rayd-0.2.2}/docs/build_optimization.md +0 -0
  25. {rayd-0.2.0 → rayd-0.2.2}/docs/edge_bvh_bottleneck_analysis.md +0 -0
  26. {rayd-0.2.0 → rayd-0.2.2}/docs/edge_bvh_lbvh_treelet_improvement_plan.md +0 -0
  27. {rayd-0.2.0 → rayd-0.2.2}/docs/edge_bvh_optimization_log.md +0 -0
  28. {rayd-0.2.0 → rayd-0.2.2}/docs/edge_bvh_stage3_preparation.md +0 -0
  29. {rayd-0.2.0 → rayd-0.2.2}/docs/multi_bounce_reflection_trace.md +0 -0
  30. {rayd-0.2.0 → rayd-0.2.2}/docs/performance_benchmark.json +0 -0
  31. {rayd-0.2.0 → rayd-0.2.2}/docs/performance_benchmark.png +0 -0
  32. {rayd-0.2.0 → rayd-0.2.2}/docs/reflection_trace_gpu_dedup.md +0 -0
  33. {rayd-0.2.0 → rayd-0.2.2}/docs/slang_interop.md +0 -0
  34. {rayd-0.2.0 → rayd-0.2.2}/examples/README.md +0 -0
  35. {rayd-0.2.0 → rayd-0.2.2}/examples/basics/camera_edge_sampling_gradient.py +0 -0
  36. {rayd-0.2.0 → rayd-0.2.2}/examples/basics/nearest_edge_query.py +0 -0
  37. {rayd-0.2.0 → rayd-0.2.2}/examples/basics/ray_mesh_intersection.py +0 -0
  38. {rayd-0.2.0 → rayd-0.2.2}/examples/renderer/README.md +0 -0
  39. {rayd-0.2.0 → rayd-0.2.2}/examples/renderer/cornell_box.png +0 -0
  40. {rayd-0.2.0 → rayd-0.2.2}/examples/renderer/cornell_box.py +0 -0
  41. {rayd-0.2.0 → rayd-0.2.2}/examples/renderer/rfdt.png +0 -0
  42. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/camera.h +0 -0
  43. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/constants.h +0 -0
  44. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/edge.h +0 -0
  45. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/fwd.h +0 -0
  46. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/intersection.h +0 -0
  47. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/mesh.h +0 -0
  48. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/optix.h +0 -0
  49. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/ray.h +0 -0
  50. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/rayd.h +0 -0
  51. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/reflection.h +0 -0
  52. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/scene/scene.h +0 -0
  53. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/scene/scene_optix.h +0 -0
  54. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/slang/interop.h +0 -0
  55. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/slang/interop_types.h +0 -0
  56. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/slang/rayd.slang +0 -0
  57. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/transform.h +0 -0
  58. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/types.h +0 -0
  59. {rayd-0.2.0 → rayd-0.2.2}/include/rayd/utils.h +0 -0
  60. {rayd-0.2.0 → rayd-0.2.2}/include/rayd_slang.slang +0 -0
  61. {rayd-0.2.0 → rayd-0.2.2}/rayd/__init__.py +0 -0
  62. {rayd-0.2.0 → rayd-0.2.2}/rayd/slang/__init__.py +0 -0
  63. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/__init__.py +0 -0
  64. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/_convert.py +0 -0
  65. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/_env.py +0 -0
  66. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/_interop_patch.py +0 -0
  67. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/_native.py +0 -0
  68. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/_state.py +0 -0
  69. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/_util.py +0 -0
  70. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/camera.py +0 -0
  71. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/mesh.py +0 -0
  72. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/scene.py +0 -0
  73. {rayd-0.2.0 → rayd-0.2.2}/rayd/torch/types.py +0 -0
  74. {rayd-0.2.0 → rayd-0.2.2}/src/camera.cpp +0 -0
  75. {rayd-0.2.0 → rayd-0.2.2}/src/mesh.cpp +0 -0
  76. {rayd-0.2.0 → rayd-0.2.2}/src/multipath/reflection_dedup.h +0 -0
  77. {rayd-0.2.0 → rayd-0.2.2}/src/multipath/reflection_trace.cu +0 -0
  78. {rayd-0.2.0 → rayd-0.2.2}/src/multipath/reflection_trace_host.h +0 -0
  79. {rayd-0.2.0 → rayd-0.2.2}/src/multipath/reflection_trace_params.h +0 -0
  80. {rayd-0.2.0 → rayd-0.2.2}/src/multipath/reflection_trace_ptx.h +0 -0
  81. {rayd-0.2.0 → rayd-0.2.2}/src/optix.cpp +0 -0
  82. {rayd-0.2.0 → rayd-0.2.2}/src/scene/edge_bvh.h +0 -0
  83. {rayd-0.2.0 → rayd-0.2.2}/src/scene/edge_bvh_config.h +0 -0
  84. {rayd-0.2.0 → rayd-0.2.2}/src/scene/experimental/edge_bvh_ploc.h +0 -0
  85. {rayd-0.2.0 → rayd-0.2.2}/src/scene/experimental/edge_bvh_ploc_build.inc +0 -0
  86. {rayd-0.2.0 → rayd-0.2.2}/src/scene/experimental/edge_bvh_ploc_kernels.inc +0 -0
  87. {rayd-0.2.0 → rayd-0.2.2}/src/scene/experimental/scene_edge_ploc.inc +0 -0
  88. {rayd-0.2.0 → rayd-0.2.2}/src/slang_interop.cpp +0 -0
  89. {rayd-0.2.0 → rayd-0.2.2}/tests/__init__.py +0 -0
  90. {rayd-0.2.0 → rayd-0.2.2}/tests/baseline_cases.py +0 -0
  91. {rayd-0.2.0 → rayd-0.2.2}/tests/baseline_utils.py +0 -0
  92. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/camera/perspective_fov.json +0 -0
  93. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/camera/perspective_intrinsic.json +0 -0
  94. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/camera/sample_primary_ray.json +0 -0
  95. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/camera/sample_to_world.json +0 -0
  96. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/camera/world_to_sample.json +0 -0
  97. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/edges/primary_edge_sampling.json +0 -0
  98. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/edges/secondary_edges.json +0 -0
  99. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/geometry/batched_hits.json +0 -0
  100. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/geometry/constant_hit.json +0 -0
  101. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/geometry/degenerate.json +0 -0
  102. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/geometry/miss.json +0 -0
  103. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/geometry/multi_mesh.json +0 -0
  104. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/geometry/uv.json +0 -0
  105. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/gradients/transform_gradients.json +0 -0
  106. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/gradients/vertex_gradients.json +0 -0
  107. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/manifest.json +0 -0
  108. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/stress/repeated_run_summary.json +0 -0
  109. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/transforms/composition_left_right.json +0 -0
  110. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/transforms/direction_transform_checks.json +0 -0
  111. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/transforms/matrix_entry_checks.json +0 -0
  112. {rayd-0.2.0 → rayd-0.2.2}/tests/baselines/drjit_v0_4_6/transforms/point_transform_checks.json +0 -0
  113. {rayd-0.2.0 → rayd-0.2.2}/tests/benchmark_edge_bvh_pressure.py +0 -0
  114. {rayd-0.2.0 → rayd-0.2.2}/tests/benchmark_edge_bvh_stages.py +0 -0
  115. {rayd-0.2.0 → rayd-0.2.2}/tests/benchmark_edge_queries.py +0 -0
  116. {rayd-0.2.0 → rayd-0.2.2}/tests/benchmark_support.py +0 -0
  117. {rayd-0.2.0 → rayd-0.2.2}/tests/drjit/__init__.py +0 -0
  118. {rayd-0.2.0 → rayd-0.2.2}/tests/drjit/test_baseline.py +0 -0
  119. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/__init__.py +0 -0
  120. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/cases/load_module_error.py +0 -0
  121. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/cases/slang_ad_autograd.py +0 -0
  122. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/cases/slang_ad_multi_param.py +0 -0
  123. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/cases/slang_ad_optimize.py +0 -0
  124. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/cases/slang_ad_struct_return.py +0 -0
  125. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/cases/slang_rayd_intersect.py +0 -0
  126. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/cases/slang_rayd_nearest_edge.py +0 -0
  127. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/shaders/rayd_query.slang +0 -0
  128. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/shaders/rayd_query_ad.slang +0 -0
  129. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/test_interop.slang +0 -0
  130. {rayd-0.2.0 → rayd-0.2.2}/tests/slang/test_slang.py +0 -0
  131. {rayd-0.2.0 → rayd-0.2.2}/tests/test_project_metadata.py +0 -0
  132. {rayd-0.2.0 → rayd-0.2.2}/tests/test_torch_interop_patch.py +0 -0
  133. {rayd-0.2.0 → rayd-0.2.2}/tests/torch/__init__.py +0 -0
  134. {rayd-0.2.0 → rayd-0.2.2}/tests/torch/test_edge_bvh_pressure.py +0 -0
  135. {rayd-0.2.0 → rayd-0.2.2}/tests/torch/test_geometry.py +0 -0
@@ -143,6 +143,8 @@ set(RAYD_CORE_SOURCE_FILES
143
143
  ${RAYD_SOURCE_DIR}/scene/scene.cpp
144
144
 
145
145
  ${RAYD_SOURCE_DIR}/optix.cpp
146
+ ${RAYD_SOURCE_DIR}/native_launch_audit.h
147
+ ${RAYD_SOURCE_DIR}/native_launch_audit.cpp
146
148
 
147
149
  ${RAYD_INCLUDE_DIR}/slang/interop.h
148
150
  ${RAYD_INCLUDE_DIR}/slang/interop_types.h
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rayd
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: RayD: minimalist differentiable ray tracing package wrapping Dr.Jit and OptiX.
5
5
  Author-Email: Xingyu Chen <xic063@ucsd.edu>
6
6
  License: BSD-3-Clause
@@ -64,6 +64,7 @@ public:
64
64
 
65
65
  private:
66
66
  void build_bvh(const SecondaryEdgeInfo &edge_info);
67
+ void set_all_active_state();
67
68
  void update_active_counts_from_mask(const MaskDetached &mask);
68
69
  IntDetached refit_leaf_nodes_from_primitive_indices(const SecondaryEdgeInfo &edge_info,
69
70
  const IntDetached &primitive_indices);
@@ -5,7 +5,7 @@ build-backend = "scikit_build_core.build"
5
5
 
6
6
  [project]
7
7
  name = "rayd"
8
- version = "0.2.0"
8
+ version = "0.2.2"
9
9
  description = "RayD: minimalist differentiable ray tracing package wrapping Dr.Jit and OptiX."
10
10
  readme = "README.md"
11
11
  authors = [{ name = "Xingyu Chen", email = "xic063@ucsd.edu" }]
@@ -8,6 +8,7 @@
8
8
  #include <string>
9
9
 
10
10
  #include <rayd/rayd.h>
11
+ #include "../native_launch_audit.h"
11
12
 
12
13
  namespace rayd {
13
14
 
@@ -366,17 +367,24 @@ int reflection_dedup_gpu(
366
367
  sizeof(int) * static_cast<size_t>(n_rays),
367
368
  stream),
368
369
  "reflection_dedup_gpu(): failed to clear discovery counts");
370
+ audit_cuda_memset_async();
369
371
  check_cuda_call(cudaMemsetAsync(out_representative_ray_index,
370
372
  0xFF,
371
373
  sizeof(int) * static_cast<size_t>(n_rays),
372
374
  stream),
373
375
  "reflection_dedup_gpu(): failed to clear representative indices");
376
+ audit_cuda_memset_async();
374
377
  check_cuda_call(cudaMemsetAsync(unique_count_device.get(),
375
378
  0,
376
379
  sizeof(int),
377
380
  stream),
378
381
  "reflection_dedup_gpu(): failed to clear unique counter");
382
+ audit_cuda_memset_async();
379
383
 
384
+ audit_cuda_kernel_launch("reflection_dedup_build_keys_kernel",
385
+ static_cast<uint32_t>(block_count), 1, 1,
386
+ block_size, 1, 1,
387
+ static_cast<uint64_t>(n_rays));
380
388
  reflection_dedup_build_keys_kernel<<<block_count, block_size, 0, stream>>>(
381
389
  n_rays,
382
390
  max_bounces,
@@ -392,6 +400,7 @@ int reflection_dedup_gpu(
392
400
  check_cuda_last_error("reflection_dedup_gpu(): failed to launch build-keys kernel");
393
401
 
394
402
  size_t sort_temp_size = 0;
403
+ audit_cub_sort();
395
404
  check_cuda_call(cub::DeviceRadixSort::SortPairs(nullptr,
396
405
  sort_temp_size,
397
406
  keys_in.get(),
@@ -404,6 +413,7 @@ int reflection_dedup_gpu(
404
413
  stream),
405
414
  "reflection_dedup_gpu(): failed to size first radix sort");
406
415
  CudaBuffer<char> sort_temp(std::max<size_t>(sort_temp_size, 1));
416
+ audit_cub_sort();
407
417
  check_cuda_call(cub::DeviceRadixSort::SortPairs(sort_temp.get(),
408
418
  sort_temp_size,
409
419
  keys_in.get(),
@@ -416,11 +426,16 @@ int reflection_dedup_gpu(
416
426
  stream),
417
427
  "reflection_dedup_gpu(): failed to run first radix sort");
418
428
 
429
+ audit_cuda_kernel_launch("reflection_dedup_mark_boundaries_kernel",
430
+ static_cast<uint32_t>(block_count), 1, 1,
431
+ block_size, 1, 1,
432
+ static_cast<uint64_t>(n_rays));
419
433
  reflection_dedup_mark_boundaries_kernel<<<block_count, block_size, 0, stream>>>(
420
434
  n_rays, keys_out.get(), boundary_flags.get());
421
435
  check_cuda_last_error("reflection_dedup_gpu(): failed to launch first boundary kernel");
422
436
 
423
437
  size_t scan_temp_size = 0;
438
+ audit_cub_scan();
424
439
  check_cuda_call(cub::DeviceScan::InclusiveSum(nullptr,
425
440
  scan_temp_size,
426
441
  boundary_flags.get(),
@@ -429,6 +444,7 @@ int reflection_dedup_gpu(
429
444
  stream),
430
445
  "reflection_dedup_gpu(): failed to size first scan");
431
446
  CudaBuffer<char> scan_temp(std::max<size_t>(scan_temp_size, 1));
447
+ audit_cub_scan();
432
448
  check_cuda_call(cub::DeviceScan::InclusiveSum(scan_temp.get(),
433
449
  scan_temp_size,
434
450
  boundary_flags.get(),
@@ -436,10 +452,18 @@ int reflection_dedup_gpu(
436
452
  n_rays,
437
453
  stream),
438
454
  "reflection_dedup_gpu(): failed to run first scan");
455
+ audit_cuda_kernel_launch("reflection_dedup_zero_base_ids_kernel",
456
+ static_cast<uint32_t>(block_count), 1, 1,
457
+ block_size, 1, 1,
458
+ static_cast<uint64_t>(n_rays));
439
459
  reflection_dedup_zero_base_ids_kernel<<<block_count, block_size, 0, stream>>>(
440
460
  n_rays, keys_out.get(), hash_group_ids.get());
441
461
  check_cuda_last_error("reflection_dedup_gpu(): failed to launch first id-fix kernel");
442
462
 
463
+ audit_cuda_kernel_launch("reflection_dedup_sub_cluster_kernel",
464
+ static_cast<uint32_t>(block_count), 1, 1,
465
+ block_size, 1, 1,
466
+ static_cast<uint64_t>(n_rays));
443
467
  reflection_dedup_sub_cluster_kernel<<<block_count, block_size, 0, stream>>>(
444
468
  n_rays,
445
469
  max_bounces,
@@ -456,6 +480,7 @@ int reflection_dedup_gpu(
456
480
  check_cuda_last_error("reflection_dedup_gpu(): failed to launch sub-cluster kernel");
457
481
 
458
482
  size_t cluster_sort_temp_size = 0;
483
+ audit_cub_sort();
459
484
  check_cuda_call(cub::DeviceRadixSort::SortPairs(nullptr,
460
485
  cluster_sort_temp_size,
461
486
  cluster_keys_in.get(),
@@ -468,6 +493,7 @@ int reflection_dedup_gpu(
468
493
  stream),
469
494
  "reflection_dedup_gpu(): failed to size second radix sort");
470
495
  CudaBuffer<char> cluster_sort_temp(std::max<size_t>(cluster_sort_temp_size, 1));
496
+ audit_cub_sort();
471
497
  check_cuda_call(cub::DeviceRadixSort::SortPairs(cluster_sort_temp.get(),
472
498
  cluster_sort_temp_size,
473
499
  cluster_keys_in.get(),
@@ -480,10 +506,15 @@ int reflection_dedup_gpu(
480
506
  stream),
481
507
  "reflection_dedup_gpu(): failed to run second radix sort");
482
508
 
509
+ audit_cuda_kernel_launch("reflection_dedup_mark_boundaries_kernel",
510
+ static_cast<uint32_t>(block_count), 1, 1,
511
+ block_size, 1, 1,
512
+ static_cast<uint64_t>(n_rays));
483
513
  reflection_dedup_mark_boundaries_kernel<<<block_count, block_size, 0, stream>>>(
484
514
  n_rays, cluster_keys_out.get(), boundary_flags.get());
485
515
  check_cuda_last_error("reflection_dedup_gpu(): failed to launch second boundary kernel");
486
516
 
517
+ audit_cub_scan();
487
518
  check_cuda_call(cub::DeviceScan::InclusiveSum(scan_temp.get(),
488
519
  scan_temp_size,
489
520
  boundary_flags.get(),
@@ -491,10 +522,18 @@ int reflection_dedup_gpu(
491
522
  n_rays,
492
523
  stream),
493
524
  "reflection_dedup_gpu(): failed to run second scan");
525
+ audit_cuda_kernel_launch("reflection_dedup_zero_base_ids_kernel",
526
+ static_cast<uint32_t>(block_count), 1, 1,
527
+ block_size, 1, 1,
528
+ static_cast<uint64_t>(n_rays));
494
529
  reflection_dedup_zero_base_ids_kernel<<<block_count, block_size, 0, stream>>>(
495
530
  n_rays, cluster_keys_out.get(), unique_path_ids.get());
496
531
  check_cuda_last_error("reflection_dedup_gpu(): failed to launch second id-fix kernel");
497
532
 
533
+ audit_cuda_kernel_launch("reflection_dedup_compact_kernel",
534
+ static_cast<uint32_t>(block_count), 1, 1,
535
+ block_size, 1, 1,
536
+ static_cast<uint64_t>(n_rays));
498
537
  reflection_dedup_compact_kernel<<<block_count, block_size, 0, stream>>>(
499
538
  n_rays,
500
539
  max_bounces,
@@ -537,12 +576,14 @@ int reflection_dedup_gpu(
537
576
  check_cuda_last_error("reflection_dedup_gpu(): failed to launch compact kernel");
538
577
 
539
578
  int unique_count = 0;
579
+ audit_cuda_memcpy_async();
540
580
  check_cuda_call(cudaMemcpyAsync(&unique_count,
541
581
  unique_count_device.get(),
542
582
  sizeof(int),
543
583
  cudaMemcpyDeviceToHost,
544
584
  stream),
545
585
  "reflection_dedup_gpu(): failed to copy unique count");
586
+ audit_cuda_stream_synchronize();
546
587
  check_cuda_call(cudaStreamSynchronize(stream),
547
588
  "reflection_dedup_gpu(): failed to finish dedup stream");
548
589
  return unique_count;
@@ -7,6 +7,7 @@
7
7
  #include <vector>
8
8
 
9
9
  #include "reflection_trace_ptx.h"
10
+ #include "../native_launch_audit.h"
10
11
 
11
12
  namespace rayd {
12
13
 
@@ -161,6 +162,7 @@ void ReflectionTracePipeline::build(OptixDeviceContext context,
161
162
  check_optix(optixSbtRecordPackHeader(pg_raygen_, &raygen_record),
162
163
  "optixSbtRecordPackHeader(raygen)");
163
164
  sbt_raygen_record_ = jit_malloc(AllocType::Device, sizeof(EmptySbtRecord));
165
+ audit_jit_memcpy();
164
166
  jit_memcpy(JitBackend::CUDA,
165
167
  sbt_raygen_record_,
166
168
  &raygen_record,
@@ -170,6 +172,7 @@ void ReflectionTracePipeline::build(OptixDeviceContext context,
170
172
  check_optix(optixSbtRecordPackHeader(pg_miss_, &miss_record),
171
173
  "optixSbtRecordPackHeader(miss)");
172
174
  sbt_miss_record_ = jit_malloc(AllocType::Device, sizeof(EmptySbtRecord));
175
+ audit_jit_memcpy();
173
176
  jit_memcpy(JitBackend::CUDA,
174
177
  sbt_miss_record_,
175
178
  &miss_record,
@@ -182,6 +185,7 @@ void ReflectionTracePipeline::build(OptixDeviceContext context,
182
185
  }
183
186
  sbt_hitgroup_records_ = jit_malloc(AllocType::Device,
184
187
  sizeof(EmptySbtRecord) * hitgroup_records.size());
188
+ audit_jit_memcpy();
185
189
  jit_memcpy(JitBackend::CUDA,
186
190
  sbt_hitgroup_records_,
187
191
  hitgroup_records.data(),
@@ -195,6 +199,7 @@ void ReflectionTracePipeline::build(OptixDeviceContext context,
195
199
  void ReflectionTracePipeline::launch(const ReflectionTraceParams &params) const {
196
200
  require(ready_, "ReflectionTracePipeline::launch(): pipeline is not ready.");
197
201
 
202
+ audit_jit_memcpy_async();
198
203
  jit_memcpy_async(JitBackend::CUDA,
199
204
  params_buffer_,
200
205
  &params,
@@ -209,6 +214,7 @@ void ReflectionTracePipeline::launch(const ReflectionTraceParams &params) const
209
214
  sbt.hitgroupRecordStrideInBytes = sizeof(EmptySbtRecord);
210
215
  sbt.hitgroupRecordCount = static_cast<unsigned int>(hitgroup_record_count_);
211
216
 
217
+ audit_optix_launch();
212
218
  check_optix(optixLaunch(pipeline_,
213
219
  jit_cuda_stream(),
214
220
  reinterpret_cast<CUdeviceptr>(params_buffer_),
@@ -0,0 +1,170 @@
1
+ #include "native_launch_audit.h"
2
+
3
+ #include <algorithm>
4
+ #include <mutex>
5
+
6
+ namespace rayd {
7
+
8
+ namespace {
9
+
10
+ std::mutex &audit_mutex() {
11
+ static std::mutex mutex;
12
+ return mutex;
13
+ }
14
+
15
+ NativeLaunchAuditSnapshot &audit_snapshot_storage() {
16
+ static NativeLaunchAuditSnapshot snapshot;
17
+ return snapshot;
18
+ }
19
+
20
+ thread_local NativeLaunchStage current_stage = NativeLaunchStage::Unknown;
21
+
22
+ NativeLaunchStageStats &stage_stats(NativeLaunchAuditSnapshot &snapshot,
23
+ NativeLaunchStage stage) {
24
+ switch (stage) {
25
+ case NativeLaunchStage::Build:
26
+ return snapshot.build;
27
+ case NativeLaunchStage::Sync:
28
+ return snapshot.sync;
29
+ case NativeLaunchStage::TraceReflections:
30
+ return snapshot.trace_reflections;
31
+ case NativeLaunchStage::Unknown:
32
+ default:
33
+ return snapshot.unknown;
34
+ }
35
+ }
36
+
37
+ void clear_stage_stats(NativeLaunchStageStats &stats) {
38
+ stats = NativeLaunchStageStats();
39
+ }
40
+
41
+ void update_kernel_stat(NativeLaunchStageStats &stats,
42
+ const char *label,
43
+ uint64_t threads,
44
+ uint64_t items) {
45
+ const std::string key = label != nullptr ? std::string(label) : std::string("unnamed");
46
+ auto it = std::find_if(stats.kernels.begin(),
47
+ stats.kernels.end(),
48
+ [&key](const NativeKernelLaunchStat &entry) {
49
+ return entry.label == key;
50
+ });
51
+ if (it == stats.kernels.end()) {
52
+ stats.kernels.push_back(NativeKernelLaunchStat { key, 1, threads, threads, items, items });
53
+ return;
54
+ }
55
+
56
+ it->launches += 1;
57
+ it->total_threads += threads;
58
+ it->max_threads = std::max(it->max_threads, threads);
59
+ it->total_items += items;
60
+ it->max_items = std::max(it->max_items, items);
61
+ }
62
+
63
+ template <typename Member>
64
+ void increment_counter(Member NativeLaunchStageStats::*member) {
65
+ std::lock_guard<std::mutex> guard(audit_mutex());
66
+ NativeLaunchStageStats &stats = stage_stats(audit_snapshot_storage(), current_stage);
67
+ stats.*member += 1;
68
+ }
69
+
70
+ } // namespace
71
+
72
+ ScopedNativeLaunchStage::ScopedNativeLaunchStage(NativeLaunchStage stage)
73
+ : previous_(current_stage) {
74
+ current_stage = stage;
75
+ }
76
+
77
+ ScopedNativeLaunchStage::~ScopedNativeLaunchStage() {
78
+ current_stage = previous_;
79
+ }
80
+
81
+ void native_launch_audit_clear() {
82
+ std::lock_guard<std::mutex> guard(audit_mutex());
83
+ NativeLaunchAuditSnapshot &snapshot = audit_snapshot_storage();
84
+ clear_stage_stats(snapshot.unknown);
85
+ clear_stage_stats(snapshot.build);
86
+ clear_stage_stats(snapshot.sync);
87
+ clear_stage_stats(snapshot.trace_reflections);
88
+ }
89
+
90
+ NativeLaunchAuditSnapshot native_launch_audit_snapshot() {
91
+ std::lock_guard<std::mutex> guard(audit_mutex());
92
+ return audit_snapshot_storage();
93
+ }
94
+
95
+ void audit_cuda_kernel_launch(const char *label,
96
+ uint32_t grid_x,
97
+ uint32_t grid_y,
98
+ uint32_t grid_z,
99
+ uint32_t block_x,
100
+ uint32_t block_y,
101
+ uint32_t block_z,
102
+ uint64_t items) {
103
+ const uint64_t threads =
104
+ static_cast<uint64_t>(grid_x) * static_cast<uint64_t>(grid_y) * static_cast<uint64_t>(grid_z) *
105
+ static_cast<uint64_t>(block_x) * static_cast<uint64_t>(block_y) * static_cast<uint64_t>(block_z);
106
+
107
+ std::lock_guard<std::mutex> guard(audit_mutex());
108
+ NativeLaunchStageStats &stats = stage_stats(audit_snapshot_storage(), current_stage);
109
+ stats.cuda_kernel_launches += 1;
110
+ stats.cuda_kernel_total_threads += threads;
111
+ update_kernel_stat(stats, label, threads, items);
112
+ }
113
+
114
+ void audit_cuda_memcpy() {
115
+ increment_counter(&NativeLaunchStageStats::cuda_memcpy);
116
+ }
117
+
118
+ void audit_cuda_memcpy_async() {
119
+ increment_counter(&NativeLaunchStageStats::cuda_memcpy_async);
120
+ }
121
+
122
+ void audit_cuda_memset_async() {
123
+ increment_counter(&NativeLaunchStageStats::cuda_memset_async);
124
+ }
125
+
126
+ void audit_cuda_stream_synchronize() {
127
+ increment_counter(&NativeLaunchStageStats::cuda_stream_synchronize);
128
+ }
129
+
130
+ void audit_cuda_event_record() {
131
+ increment_counter(&NativeLaunchStageStats::cuda_event_record);
132
+ }
133
+
134
+ void audit_cuda_stream_wait_event() {
135
+ increment_counter(&NativeLaunchStageStats::cuda_stream_wait_event);
136
+ }
137
+
138
+ void audit_cub_reduce() {
139
+ increment_counter(&NativeLaunchStageStats::cub_reduce);
140
+ }
141
+
142
+ void audit_cub_sort() {
143
+ increment_counter(&NativeLaunchStageStats::cub_sort);
144
+ }
145
+
146
+ void audit_cub_scan() {
147
+ increment_counter(&NativeLaunchStageStats::cub_scan);
148
+ }
149
+
150
+ void audit_jit_memcpy() {
151
+ increment_counter(&NativeLaunchStageStats::jit_memcpy);
152
+ }
153
+
154
+ void audit_jit_memcpy_async() {
155
+ increment_counter(&NativeLaunchStageStats::jit_memcpy_async);
156
+ }
157
+
158
+ void audit_optix_accel_build() {
159
+ increment_counter(&NativeLaunchStageStats::optix_accel_build);
160
+ }
161
+
162
+ void audit_optix_accel_compact() {
163
+ increment_counter(&NativeLaunchStageStats::optix_accel_compact);
164
+ }
165
+
166
+ void audit_optix_launch() {
167
+ increment_counter(&NativeLaunchStageStats::optix_launch);
168
+ }
169
+
170
+ } // namespace rayd
@@ -0,0 +1,90 @@
1
+ #pragma once
2
+
3
+ #include <cstdint>
4
+ #include <string>
5
+ #include <vector>
6
+
7
+ namespace rayd {
8
+
9
+ enum class NativeLaunchStage {
10
+ Unknown = 0,
11
+ Build,
12
+ Sync,
13
+ TraceReflections
14
+ };
15
+
16
+ struct NativeKernelLaunchStat {
17
+ std::string label;
18
+ uint64_t launches = 0;
19
+ uint64_t total_threads = 0;
20
+ uint64_t max_threads = 0;
21
+ uint64_t total_items = 0;
22
+ uint64_t max_items = 0;
23
+ };
24
+
25
+ struct NativeLaunchStageStats {
26
+ uint64_t cuda_kernel_launches = 0;
27
+ uint64_t cuda_kernel_total_threads = 0;
28
+ uint64_t cuda_memcpy = 0;
29
+ uint64_t cuda_memcpy_async = 0;
30
+ uint64_t cuda_memset_async = 0;
31
+ uint64_t cuda_stream_synchronize = 0;
32
+ uint64_t cuda_event_record = 0;
33
+ uint64_t cuda_stream_wait_event = 0;
34
+ uint64_t cub_reduce = 0;
35
+ uint64_t cub_sort = 0;
36
+ uint64_t cub_scan = 0;
37
+ uint64_t jit_memcpy = 0;
38
+ uint64_t jit_memcpy_async = 0;
39
+ uint64_t optix_accel_build = 0;
40
+ uint64_t optix_accel_compact = 0;
41
+ uint64_t optix_launch = 0;
42
+ std::vector<NativeKernelLaunchStat> kernels;
43
+ };
44
+
45
+ struct NativeLaunchAuditSnapshot {
46
+ NativeLaunchStageStats unknown;
47
+ NativeLaunchStageStats build;
48
+ NativeLaunchStageStats sync;
49
+ NativeLaunchStageStats trace_reflections;
50
+ };
51
+
52
+ class ScopedNativeLaunchStage {
53
+ public:
54
+ explicit ScopedNativeLaunchStage(NativeLaunchStage stage);
55
+ ~ScopedNativeLaunchStage();
56
+
57
+ ScopedNativeLaunchStage(const ScopedNativeLaunchStage &) = delete;
58
+ ScopedNativeLaunchStage &operator=(const ScopedNativeLaunchStage &) = delete;
59
+
60
+ private:
61
+ NativeLaunchStage previous_;
62
+ };
63
+
64
+ void native_launch_audit_clear();
65
+ NativeLaunchAuditSnapshot native_launch_audit_snapshot();
66
+
67
+ void audit_cuda_kernel_launch(const char *label,
68
+ uint32_t grid_x,
69
+ uint32_t grid_y,
70
+ uint32_t grid_z,
71
+ uint32_t block_x,
72
+ uint32_t block_y,
73
+ uint32_t block_z,
74
+ uint64_t items = 0);
75
+ void audit_cuda_memcpy();
76
+ void audit_cuda_memcpy_async();
77
+ void audit_cuda_memset_async();
78
+ void audit_cuda_stream_synchronize();
79
+ void audit_cuda_event_record();
80
+ void audit_cuda_stream_wait_event();
81
+ void audit_cub_reduce();
82
+ void audit_cub_sort();
83
+ void audit_cub_scan();
84
+ void audit_jit_memcpy();
85
+ void audit_jit_memcpy_async();
86
+ void audit_optix_accel_build();
87
+ void audit_optix_accel_compact();
88
+ void audit_optix_launch();
89
+
90
+ } // namespace rayd
@@ -15,6 +15,8 @@
15
15
  #include <rayd/camera.h>
16
16
  #include <rayd/scene/scene.h>
17
17
 
18
+ #include "native_launch_audit.h"
19
+
18
20
  namespace nb = nanobind;
19
21
  using namespace nb::literals;
20
22
  using namespace rayd;
@@ -139,6 +141,44 @@ struct type_caster<T, std::enable_if_t<drjit::is_array_v<T>, int>> {
139
141
  } // namespace nanobind::detail
140
142
 
141
143
  NB_MODULE(rayd, m) {
144
+ auto native_kernel_dict = [](const NativeKernelLaunchStat &entry) {
145
+ nb::dict result;
146
+ result["label"] = entry.label;
147
+ result["launches"] = entry.launches;
148
+ result["total_threads"] = entry.total_threads;
149
+ result["max_threads"] = entry.max_threads;
150
+ result["total_items"] = entry.total_items;
151
+ result["max_items"] = entry.max_items;
152
+ return result;
153
+ };
154
+
155
+ auto native_stage_dict = [&](const NativeLaunchStageStats &stats) {
156
+ nb::list kernels;
157
+ for (const NativeKernelLaunchStat &entry : stats.kernels) {
158
+ kernels.append(native_kernel_dict(entry));
159
+ }
160
+
161
+ nb::dict result;
162
+ result["cuda_kernel_launches"] = stats.cuda_kernel_launches;
163
+ result["cuda_kernel_total_threads"] = stats.cuda_kernel_total_threads;
164
+ result["cuda_memcpy"] = stats.cuda_memcpy;
165
+ result["cuda_memcpy_async"] = stats.cuda_memcpy_async;
166
+ result["cuda_memset_async"] = stats.cuda_memset_async;
167
+ result["cuda_stream_synchronize"] = stats.cuda_stream_synchronize;
168
+ result["cuda_event_record"] = stats.cuda_event_record;
169
+ result["cuda_stream_wait_event"] = stats.cuda_stream_wait_event;
170
+ result["cub_reduce"] = stats.cub_reduce;
171
+ result["cub_sort"] = stats.cub_sort;
172
+ result["cub_scan"] = stats.cub_scan;
173
+ result["jit_memcpy"] = stats.jit_memcpy;
174
+ result["jit_memcpy_async"] = stats.jit_memcpy_async;
175
+ result["optix_accel_build"] = stats.optix_accel_build;
176
+ result["optix_accel_compact"] = stats.optix_accel_compact;
177
+ result["optix_launch"] = stats.optix_launch;
178
+ result["kernels"] = kernels;
179
+ return result;
180
+ };
181
+
142
182
  auto bind_section = [](const char *name, auto &&fn) {
143
183
  try {
144
184
  fn();
@@ -164,6 +204,20 @@ NB_MODULE(rayd, m) {
164
204
  m.def("current_device",
165
205
  []() { return checked_cuda_device_count() > 0 ? jit_cuda_device() : 0; },
166
206
  "Return the current thread's active Dr.Jit CUDA device index.");
207
+ m.def("native_launch_audit_clear",
208
+ &native_launch_audit_clear,
209
+ "Clear grouped native launch audit counters.");
210
+ m.def("native_launch_audit",
211
+ [native_stage_dict]() {
212
+ const NativeLaunchAuditSnapshot snapshot = native_launch_audit_snapshot();
213
+ nb::dict result;
214
+ result["unknown"] = native_stage_dict(snapshot.unknown);
215
+ result["build"] = native_stage_dict(snapshot.build);
216
+ result["sync"] = native_stage_dict(snapshot.sync);
217
+ result["trace_reflections"] = native_stage_dict(snapshot.trace_reflections);
218
+ return result;
219
+ },
220
+ "Return grouped native launch audit counters.");
167
221
  m.def("set_device",
168
222
  &set_rayd_device,
169
223
  "device"_a,
@@ -448,6 +502,61 @@ NB_MODULE(rayd, m) {
448
502
  bind_section("mesh", [&]() {
449
503
  nb::class_<Mesh>(m, "Mesh")
450
504
  .def(nb::init<>())
505
+ .def("__init__",
506
+ [](Mesh *mesh,
507
+ nb::handle v_obj,
508
+ const Vector3iDetached &f,
509
+ nb::handle uv_obj,
510
+ const Vector3iDetached &f_uv,
511
+ bool verbose) {
512
+ const std::string v_module_name =
513
+ nb::cast<std::string>(v_obj.type().attr("__module__"));
514
+ const std::string v_type_name =
515
+ nb::cast<std::string>(v_obj.type().attr("__name__"));
516
+ const std::string uv_module_name =
517
+ nb::cast<std::string>(uv_obj.type().attr("__module__"));
518
+ const std::string uv_type_name =
519
+ nb::cast<std::string>(uv_obj.type().attr("__name__"));
520
+
521
+ const bool has_live_v =
522
+ v_module_name == "drjit.cuda.ad" && v_type_name == "Array3f";
523
+ const bool has_live_uv =
524
+ uv_module_name == "drjit.cuda.ad" && uv_type_name == "Array2f";
525
+ if (!has_live_v && !has_live_uv) {
526
+ throw nb::next_overload();
527
+ }
528
+
529
+ Vector3fDetached v_detached;
530
+ if (has_live_v) {
531
+ const Vector3f v_live = nb::cast<Vector3f>(v_obj);
532
+ v_detached = detach<false>(v_live);
533
+ } else if (!drjit_try_load<Vector3fDetached>(v_obj, v_detached, true)) {
534
+ throw nb::next_overload();
535
+ }
536
+
537
+ Vector2fDetached uv_detached;
538
+ if (has_live_uv) {
539
+ const Vector2f uv_live = nb::cast<Vector2f>(uv_obj);
540
+ uv_detached = detach<false>(uv_live);
541
+ } else if (!drjit_try_load<Vector2fDetached>(uv_obj, uv_detached, true)) {
542
+ throw nb::next_overload();
543
+ }
544
+
545
+ new (mesh) Mesh(v_detached, f, uv_detached, f_uv, verbose);
546
+ if (has_live_v) {
547
+ const Vector3f v_live = nb::cast<Vector3f>(v_obj);
548
+ mesh->set_vertex_positions(v_live);
549
+ }
550
+ if (has_live_uv) {
551
+ const Vector2f uv_live = nb::cast<Vector2f>(uv_obj);
552
+ mesh->set_vertex_uv(uv_live);
553
+ }
554
+ },
555
+ "v"_a,
556
+ "f"_a,
557
+ "uv"_a = Vector2fDetached(),
558
+ "f_uv"_a = Vector3iDetached(),
559
+ "verbose"_a = false)
451
560
  .def("__init__",
452
561
  [](Mesh *mesh,
453
562
  const Vector3fDetached &v,