ernie-renderer 0.2.0.dev16__tar.gz → 0.2.0.dev19__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.

Potentially problematic release.


This version of ernie-renderer might be problematic. Click here for more details.

Files changed (214) hide show
  1. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.github/workflows/ci.yml +1 -1
  2. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/CMakeLists.txt +5 -1
  3. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/CMakePresets.json +1 -0
  4. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/PKG-INFO +1 -1
  5. ernie_renderer-0.2.0.dev19/benchmarks/CMakeLists.txt +3 -0
  6. ernie_renderer-0.2.0.dev19/benchmarks/bench.h +52 -0
  7. ernie_renderer-0.2.0.dev19/benchmarks/main.cpp +22 -0
  8. ernie_renderer-0.2.0.dev19/benchmarks/scene_storage.cpp +118 -0
  9. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/ErnieTesting.cmake +1 -1
  10. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/CMakeLists.txt +0 -4
  11. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/cloud.cpp +1 -2
  12. ernie_renderer-0.2.0.dev19/ernie/scene/CMakeLists.txt +3 -0
  13. ernie_renderer-0.2.0.dev19/ernie/scene/path.cpp +193 -0
  14. ernie_renderer-0.2.0.dev19/ernie/scene/path.h +152 -0
  15. ernie_renderer-0.2.0.dev19/ernie/scene/storage.cpp +235 -0
  16. ernie_renderer-0.2.0.dev19/ernie/scene/storage.h +408 -0
  17. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/bytes.h +51 -1
  18. ernie_renderer-0.2.0.dev19/ernie/util/hash_index.h +103 -0
  19. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/random.h +18 -4
  20. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/text.h +15 -0
  21. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/CMakeLists.txt +6 -0
  22. ernie_renderer-0.2.0.dev19/tests/common.h +33 -0
  23. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/consumer/CMakeLists.txt +0 -4
  24. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/io/ies_test.cpp +6 -4
  25. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/io/image_test.cpp +4 -3
  26. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/io/nanovdb_test.cpp +10 -11
  27. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/io/raster_test.cpp +50 -55
  28. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/io/texture_test.cpp +10 -10
  29. ernie_renderer-0.2.0.dev19/tests/scene/path_test.cpp +93 -0
  30. ernie_renderer-0.2.0.dev19/tests/scene/storage_test.cpp +157 -0
  31. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/bytes_test.cpp +16 -0
  32. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/disk_cache_test.cpp +3 -2
  33. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/file_test.cpp +8 -13
  34. ernie_renderer-0.2.0.dev19/tests/util/hash_index_test.cpp +50 -0
  35. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/text_test.cpp +9 -0
  36. ernie_renderer-0.2.0.dev16/ernie/scene/CMakeLists.txt +0 -3
  37. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.clang-format +0 -0
  38. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.clang-tidy +0 -0
  39. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.dockerignore +0 -0
  40. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.gersemirc +0 -0
  41. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.gitattributes +0 -0
  42. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.github/scripts/coverage_badge.py +0 -0
  43. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.github/scripts/install-lavapipe-windows.sh +0 -0
  44. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.gitignore +0 -0
  45. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/.pre-commit-config.yaml +0 -0
  46. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/Dockerfile +0 -0
  47. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/LICENSE +0 -0
  48. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/README.md +0 -0
  49. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/ErnieConfig.cmake.in +0 -0
  50. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/ErnieFetch.cmake +0 -0
  51. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/ErnieInstall.cmake +0 -0
  52. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/ErniePackaging.cmake +0 -0
  53. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/ernie.pc.in +0 -0
  54. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/bc7enc.cmake +0 -0
  55. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/dlpack.cmake +0 -0
  56. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/glm.cmake +0 -0
  57. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/googletest.cmake +0 -0
  58. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/json.cmake +0 -0
  59. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/nanobind.cmake +0 -0
  60. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/openexr.cmake +0 -0
  61. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/stb.cmake +0 -0
  62. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/tracy.cmake +0 -0
  63. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/volk.cmake +0 -0
  64. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/cmake/third_party/vulkan_headers.cmake +0 -0
  65. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/docs/README.md +0 -0
  66. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/docs/index.md +0 -0
  67. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/docs/requirements.txt +0 -0
  68. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/app/CMakeLists.txt +0 -0
  69. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/app/main.cpp +0 -0
  70. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/device/CMakeLists.txt +0 -0
  71. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/device/vulkan_devices.cpp +0 -0
  72. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/device/vulkan_devices.h +0 -0
  73. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/graph/CMakeLists.txt +0 -0
  74. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/CMakeLists.txt +0 -0
  75. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/ies.cpp +0 -0
  76. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/ies.h +0 -0
  77. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/image.cpp +0 -0
  78. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/image.h +0 -0
  79. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/nanovdb.cpp +0 -0
  80. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/nanovdb.h +0 -0
  81. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/raster.cpp +0 -0
  82. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/raster.h +0 -0
  83. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/texture.cpp +0 -0
  84. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/io/texture.h +0 -0
  85. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/CMakeLists.txt +0 -0
  86. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/astronomy.cpp +0 -0
  87. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/astronomy.h +0 -0
  88. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/atmosphere.cpp +0 -0
  89. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/atmosphere.h +0 -0
  90. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/cloud.h +0 -0
  91. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/constants.h +0 -0
  92. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/reflectance_library.cpp +0 -0
  93. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/reflectance_library.h +0 -0
  94. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/reflectance_table.h +0 -0
  95. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/regolith.cpp +0 -0
  96. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/regolith.h +0 -0
  97. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/scattering.cpp +0 -0
  98. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/scattering.h +0 -0
  99. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/solar.cpp +0 -0
  100. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/solar.h +0 -0
  101. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/solar_table.h +0 -0
  102. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/spectrum.cpp +0 -0
  103. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/physics/spectrum.h +0 -0
  104. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/python/CMakeLists.txt +0 -0
  105. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/python/ernie/__init__.py +0 -0
  106. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/python/module.cpp +0 -0
  107. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/render/CMakeLists.txt +0 -0
  108. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/CMakeLists.txt +0 -0
  109. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/disk_cache.cpp +0 -0
  110. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/disk_cache.h +0 -0
  111. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/file.cpp +0 -0
  112. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/file.h +0 -0
  113. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/glm.h +0 -0
  114. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/linear_algebra.h +0 -0
  115. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/log.cpp +0 -0
  116. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/log.h +0 -0
  117. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/math.h +0 -0
  118. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/noise.cpp +0 -0
  119. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/noise.h +0 -0
  120. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/numbers.h +0 -0
  121. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/parallel.h +0 -0
  122. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/profiler.cpp +0 -0
  123. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/profiler.h +0 -0
  124. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/tensor.cpp +0 -0
  125. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/tensor.h +0 -0
  126. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/version.cpp +0 -0
  127. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/version.h +0 -0
  128. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/ernie/util/worker_pool.h +0 -0
  129. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/mkdocs.yml +0 -0
  130. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/pyproject.toml +0 -0
  131. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/consumer/main.cpp +0 -0
  132. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/device/vulkan_devices_test.cpp +0 -0
  133. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/exr/README.md +0 -0
  134. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/exr/make_exr.py +0 -0
  135. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/exr/rgb_float_zip.exr +0 -0
  136. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/exr/rgba_half_window.exr +0 -0
  137. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/exr/y_half_zips.exr +0 -0
  138. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/ies/README.md +0 -0
  139. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/ies/downlight_quadrant.ies +0 -0
  140. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/ies/floodlight_type_b.ies +0 -0
  141. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/ies/lamp.tilt +0 -0
  142. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/images/grey16.png +0 -0
  143. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/ktx2/README.md +0 -0
  144. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/ktx2/quadrants_etc1s.ktx2 +0 -0
  145. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/ktx2/quadrants_uastc_zstd.ktx2 +0 -0
  146. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/ktx2/tilted_normal_etc1s.ktx2 +0 -0
  147. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/ktx2/tilted_normal_uastc.ktx2 +0 -0
  148. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/tiff/README.md +0 -0
  149. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/tiff/float_deflate_predictor3.tif +0 -0
  150. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/tiff/float_raw.tif +0 -0
  151. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/tiff/int16_bigtiff_bigendian.tif +0 -0
  152. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/tiff/rgb_lzw_predictor2.tif +0 -0
  153. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/tiff/rgb_planar_lzw.tif +0 -0
  154. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/tiff/rgb_planar_raw.tif +0 -0
  155. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/tiff/rgb_tiled_deflate.tif +0 -0
  156. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/volumes/cube.nvdb +0 -0
  157. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/fixtures/volumes/make_nvdb.py +0 -0
  158. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/physics/astronomy_test.cpp +0 -0
  159. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/physics/atmosphere_test.cpp +0 -0
  160. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/physics/cloud_test.cpp +0 -0
  161. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/physics/reflectance_library_test.cpp +0 -0
  162. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/physics/regolith_test.cpp +0 -0
  163. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/physics/scattering_test.cpp +0 -0
  164. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/physics/solar_test.cpp +0 -0
  165. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/physics/spectrum_test.cpp +0 -0
  166. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/python/test_package.py +0 -0
  167. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/linear_algebra_test.cpp +0 -0
  168. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/log_test.cpp +0 -0
  169. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/math_test.cpp +0 -0
  170. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/noise_test.cpp +0 -0
  171. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/parallel_test.cpp +0 -0
  172. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/profiler_test.cpp +0 -0
  173. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/random_test.cpp +0 -0
  174. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/tensor_test.cpp +0 -0
  175. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/version_test.cpp +0 -0
  176. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/tests/util/worker_pool_test.cpp +0 -0
  177. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/CMakeLists.txt +0 -0
  178. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/LICENSE +0 -0
  179. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/LICENSES/Apache-2.0.txt +0 -0
  180. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/LICENSES/BSD-3-clause.txt +0 -0
  181. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/LICENSES/MIT.txt +0 -0
  182. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/NOTICE +0 -0
  183. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/README.md +0 -0
  184. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu.h +0 -0
  185. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_astc_cfgs.inl +0 -0
  186. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_astc_hdr_core.h +0 -0
  187. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_astc_helpers.h +0 -0
  188. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_containers.h +0 -0
  189. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_containers_impl.h +0 -0
  190. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_dds_transcoder.inl +0 -0
  191. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_etc1_mods.inl +0 -0
  192. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_file_headers.h +0 -0
  193. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_idct.h +0 -0
  194. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder.cpp +0 -0
  195. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder.h +0 -0
  196. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_internal.h +0 -0
  197. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_astc.inc +0 -0
  198. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_astc_0_255.inc +0 -0
  199. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_atc_55.inc +0 -0
  200. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_atc_56.inc +0 -0
  201. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_bc7_m5_alpha.inc +0 -0
  202. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_bc7_m5_color.inc +0 -0
  203. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_dxt1_5.inc +0 -0
  204. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_dxt1_6.inc +0 -0
  205. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_pvrtc2_45.inc +0 -0
  206. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_tables_pvrtc2_alpha_33.inc +0 -0
  207. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_transcoder_uastc.h +0 -0
  208. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_xbc7_decoder.h +0 -0
  209. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/transcoder/basisu_xbc7_decoder.inl +0 -0
  210. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/zstd/LICENSE +0 -0
  211. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/zstd/zstd.h +0 -0
  212. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/basisu/zstd/zstd_errors.h +0 -0
  213. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/nanovdb/LICENSE +0 -0
  214. {ernie_renderer-0.2.0.dev16 → ernie_renderer-0.2.0.dev19}/third_party/nanovdb/PNanoVDB.h +0 -0
@@ -96,7 +96,7 @@ jobs:
96
96
  - name: Build
97
97
  run: cmake --build --preset ci --parallel 4
98
98
  # The installed library used as end users use it: its headers compile alone and a program
99
- # links and runs against it (QA-072). Windows finds ernie.dll on the PATH.
99
+ # links and runs against it. Windows finds ernie.dll on the PATH.
100
100
  - name: Install and build a consumer
101
101
  shell: bash
102
102
  run: |
@@ -15,10 +15,11 @@ project(
15
15
  )
16
16
 
17
17
  # Pre-release suffix such as .dev12, written by CI.
18
- set(ERNIE_VERSION_SUFFIX ".dev16" CACHE STRING "Pre-release suffix of Ernie's version")
18
+ set(ERNIE_VERSION_SUFFIX ".dev19" CACHE STRING "Pre-release suffix of Ernie's version")
19
19
  set(ERNIE_VERSION "${PROJECT_VERSION}${ERNIE_VERSION_SUFFIX}")
20
20
 
21
21
  option(ERNIE_BUILD_TESTS "Build Ernie's tests" OFF)
22
+ option(ERNIE_BUILD_BENCHMARKS "Build Ernie's benchmarks" OFF)
22
23
  option(ERNIE_BUILD_PYTHON "Build Ernie's Python module" OFF)
23
24
  option(ERNIE_BUILD_APP "Build the ernie program" ON)
24
25
  option(ERNIE_WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF)
@@ -110,6 +111,9 @@ if(ERNIE_BUILD_TESTS)
110
111
  enable_testing()
111
112
  add_subdirectory(tests)
112
113
  endif()
114
+ if(ERNIE_BUILD_BENCHMARKS)
115
+ add_subdirectory(benchmarks)
116
+ endif()
113
117
 
114
118
  if(PROJECT_IS_TOP_LEVEL AND NOT SKBUILD)
115
119
  include(cmake/ErniePackaging.cmake)
@@ -15,6 +15,7 @@
15
15
  "cacheVariables": {
16
16
  "CMAKE_BUILD_TYPE": "RelWithDebInfo",
17
17
  "ERNIE_BUILD_TESTS": "ON",
18
+ "ERNIE_BUILD_BENCHMARKS": "ON",
18
19
  "ERNIE_BUILD_PYTHON": "ON",
19
20
  "ERNIE_BUILD_APP": "ON"
20
21
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ernie-renderer
3
- Version: 0.2.0.dev16
3
+ Version: 0.2.0.dev19
4
4
  Summary: Efficient Renderer for Natural and Interplanetary Environments: a physically based, spectral Vulkan ray tracer
5
5
  Author: Alex Maietta
6
6
  License-Expression: BSD-3-Clause
@@ -0,0 +1,3 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ add_executable(ernie_benchmarks main.cpp scene_storage.cpp)
3
+ target_link_libraries(ernie_benchmarks PRIVATE ernie_static ernie_build_options)
@@ -0,0 +1,52 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file bench.h
3
+ /// @brief Registering and timing benchmarks, which report against a target and never fail on time.
4
+ #pragma once
5
+
6
+ #include <algorithm>
7
+ #include <chrono>
8
+ #include <functional>
9
+ #include <string>
10
+ #include <vector>
11
+
12
+ namespace ernie::bench {
13
+
14
+ /// What a benchmark measured: its fastest run and the time it aims for, in milliseconds.
15
+ struct Timing {
16
+ double ms = 0.0;
17
+ double targetMs = 0.0;
18
+ };
19
+
20
+ struct Benchmark {
21
+ std::string name;
22
+ std::function<Timing()> run;
23
+ };
24
+
25
+ /// @return Every benchmark registered at static initialization.
26
+ inline std::vector<Benchmark>& Registry() {
27
+ static std::vector<Benchmark> benchmarks;
28
+ return benchmarks;
29
+ }
30
+
31
+ /// Registers a benchmark from a namespace-scope `const bool`.
32
+ inline bool Register(std::string name, std::function<Timing()> run) {
33
+ Registry().push_back({std::move(name), std::move(run)});
34
+ return true;
35
+ }
36
+
37
+ /// @brief Times `step` `runs` times, after `setup` before each, to see past a noisy machine.
38
+ /// @return The fastest run, in milliseconds.
39
+ template <typename Setup, typename Step>
40
+ double Fastest(const Setup& setup, const Step& step, int runs = 5) {
41
+ double best = 1e30;
42
+ for (int run = 0; run < runs; ++run) {
43
+ setup();
44
+ const auto start = std::chrono::steady_clock::now();
45
+ step();
46
+ const auto elapsed = std::chrono::steady_clock::now() - start;
47
+ best = std::min(best, std::chrono::duration<double, std::milli>(elapsed).count());
48
+ }
49
+ return best;
50
+ }
51
+
52
+ } // namespace ernie::bench
@@ -0,0 +1,22 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file main.cpp
3
+ /// @brief Runs the registered benchmarks whose names contain the first argument, and prints each
4
+ /// fastest time beside its target.
5
+ #include "benchmarks/bench.h"
6
+
7
+ #include <cstdio>
8
+ #include <string_view>
9
+
10
+ int main(int argc, char** argv) {
11
+ const std::string_view filter = argc > 1 ? argv[1] : "";
12
+ std::printf("%-48s %12s %12s\n", "benchmark", "ms", "target ms");
13
+ for (const ernie::bench::Benchmark& benchmark : ernie::bench::Registry()) {
14
+ if (benchmark.name.find(filter) == std::string::npos) {
15
+ continue;
16
+ }
17
+ const ernie::bench::Timing timing = benchmark.run();
18
+ std::printf("%-48s %12.3f %12.3f%s\n", benchmark.name.c_str(), timing.ms, timing.targetMs,
19
+ timing.ms > timing.targetMs ? " over" : "");
20
+ }
21
+ return 0;
22
+ }
@@ -0,0 +1,118 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file scene_storage.cpp
3
+ /// @brief The prim store at 100,000 prims: create, first sync, one edit, edit all, add and remove.
4
+ #include "benchmarks/bench.h"
5
+ #include "ernie/scene/storage.h"
6
+
7
+ #include <memory>
8
+ #include <string>
9
+ #include <vector>
10
+
11
+ namespace ernie::bench {
12
+ namespace {
13
+
14
+ constexpr std::uint32_t kPrims = 100'000;
15
+
16
+ /// 100,000 instanced robots, one per environment, with transforms.
17
+ struct Robots {
18
+ std::unique_ptr<PrimStore> store;
19
+ AttributeId transform = 0;
20
+ BucketId bucket = 0;
21
+ std::vector<PrimId> prims;
22
+
23
+ void Reset() {
24
+ store = std::make_unique<PrimStore>();
25
+ transform = store->Tokens().Intern("xformOp:transform");
26
+ bucket = store->AddBucket(
27
+ {store->Tokens().Intern("Xform"), {}},
28
+ std::vector<ColumnLayout>{ColumnLayout::Of<glm::dmat4>(transform, glm::dmat4(1.0))});
29
+ prims.clear();
30
+ }
31
+
32
+ void Create() {
33
+ PathTable& paths = store->Paths();
34
+ const PathId world = paths.Child(kRootPath, "World");
35
+ const Token robot = store->Tokens().Intern("robot");
36
+ std::vector<PathId> robots(kPrims);
37
+ paths.Reserve(2 * kPrims);
38
+ for (std::uint32_t i = 0; i < kPrims; ++i) {
39
+ robots[i] = paths.Child(paths.Child(world, "env_" + std::to_string(i)), robot);
40
+ }
41
+ prims = store->DefineMany(robots, bucket);
42
+ const std::span<glm::dmat4> transforms = store->Write<glm::dmat4>(bucket, transform);
43
+ for (std::uint32_t i = 0; i < kPrims; ++i) {
44
+ transforms[i] = glm::dmat4(1.0);
45
+ transforms[i][3] = glm::dvec4(i, 0.0, 0.0, 1.0);
46
+ }
47
+ }
48
+
49
+ void Fresh() {
50
+ Reset();
51
+ Create();
52
+ }
53
+ };
54
+
55
+ const bool kCreate = Register("scene.storage.create_100k", [] {
56
+ Robots robots;
57
+ return Timing{Fastest([&] { robots.Reset(); }, [&] { robots.Create(); }), 50.0};
58
+ });
59
+
60
+ const bool kFirstSync = Register("scene.storage.first_sync_100k", [] {
61
+ Robots robots;
62
+ return Timing{Fastest([&] { robots.Fresh(); }, [&] { robots.store->ChangesSince(0); }), 50.0};
63
+ });
64
+
65
+ const bool kOneEdit = Register("scene.storage.one_edit_of_100k", [] {
66
+ Robots robots;
67
+ robots.Fresh();
68
+ std::uint64_t cursor = 0;
69
+ const double ms =
70
+ Fastest([&] { cursor = robots.store->Version(); },
71
+ [&] {
72
+ robots.store->Set(robots.prims[54'321], robots.transform, glm::dmat4(2.0));
73
+ robots.store->ChangesSince(cursor);
74
+ });
75
+ return Timing{ms, 1.0};
76
+ });
77
+
78
+ const bool kEditAll = Register("scene.storage.edit_all_100k", [] {
79
+ Robots robots;
80
+ robots.Fresh();
81
+ std::uint64_t cursor = 0;
82
+ const double ms = Fastest([&] { cursor = robots.store->Version(); },
83
+ [&] {
84
+ for (glm::dmat4& transform : robots.store->Write<glm::dmat4>(
85
+ robots.bucket, robots.transform)) {
86
+ transform[3].y += 1.0;
87
+ }
88
+ robots.store->ChangesSince(cursor);
89
+ });
90
+ return Timing{ms, 10.0};
91
+ });
92
+
93
+ const bool kAddRemove = Register("scene.storage.add_remove_1000_of_100k", [] {
94
+ Robots robots;
95
+ std::uint64_t cursor = 0;
96
+ const double ms = Fastest(
97
+ [&] {
98
+ robots.Fresh();
99
+ cursor = robots.store->Version();
100
+ },
101
+ [&] {
102
+ for (std::uint32_t i = 0; i < 1000; ++i) {
103
+ robots.store->Remove(robots.prims[i * 97]);
104
+ }
105
+ PathTable& paths = robots.store->Paths();
106
+ const PathId spawned = paths.Child(kRootPath, "Spawned");
107
+ std::vector<PathId> added(1000);
108
+ for (std::uint32_t i = 0; i < 1000; ++i) {
109
+ added[i] = paths.Child(spawned, "p" + std::to_string(i));
110
+ }
111
+ robots.store->DefineMany(added, robots.bucket);
112
+ robots.store->ChangesSince(cursor);
113
+ });
114
+ return Timing{ms, 5.0};
115
+ });
116
+
117
+ } // namespace
118
+ } // namespace ernie::bench
@@ -4,7 +4,7 @@ include_guard(GLOBAL)
4
4
  include("${CMAKE_CURRENT_LIST_DIR}/third_party/googletest.cmake")
5
5
  include(GoogleTest)
6
6
 
7
- # Hard timeouts per label; the time budgets tests aim for are far smaller.
7
+ # Hard timeouts per label, to catch hangs; timings are tracked by benchmarks/.
8
8
  set(ERNIE_TEST_TIMEOUT_unit 10)
9
9
  set(ERNIE_TEST_TIMEOUT_gpu 60)
10
10
  set(ERNIE_TEST_TIMEOUT_accuracy 120)
@@ -54,12 +54,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
54
54
  target_link_options(ernie PRIVATE "LINKER:--exclude-libs,ALL")
55
55
  endif()
56
56
 
57
- # The same objects as one static library, for in-tree programs and tests, which may also reach
58
- # internal APIs, and for the Python module, which carries everything itself.
59
57
  add_library(ernie_static STATIC)
60
58
  target_link_libraries(ernie_static PUBLIC ${ernie_layers})
61
- # Its objects export the API (ERNIE_API), so on Windows every program linking it would also write
62
- # an import library; the ernie program's would collide with libernie's own ernie.lib and ernie.exp.
63
59
  target_link_options(ernie_static INTERFACE "$<$<CXX_COMPILER_ID:MSVC>:/NOIMPLIB;/NOEXP>")
64
60
 
65
61
  if(ERNIE_BUILD_APP)
@@ -491,8 +491,7 @@ CloudTransportTable SimulateCloudTransport(const DropletPhaseTable& phase,
491
491
  ParallelFor(shape.lightCosines * shape.thicknesses, [&](std::size_t job) {
492
492
  const std::size_t light = job % shape.lightCosines;
493
493
  const std::size_t thickness = shape.thicknesses - 1 - job / shape.lightCosines;
494
- const std::uint64_t seed =
495
- options.seed * 0x100000001b3ull + static_cast<std::uint64_t>(job) * 0x9e3779b9ull;
494
+ const std::uint64_t seed = HashCombine(options.seed, job);
496
495
  const SlabTallies tallies =
497
496
  SimulateSlab(shape, sampler, light, thickness, options.photons, seed);
498
497
  StoreSlab(tallies, light, thickness, options.photons, table);
@@ -0,0 +1,3 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+ add_library(ernie_scene OBJECT path.cpp storage.cpp)
3
+ target_link_libraries(ernie_scene PUBLIC ernie_physics ernie_io PRIVATE ernie_build_options)
@@ -0,0 +1,193 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file path.cpp
3
+ /// @brief Path parsing, token interning and the path table.
4
+ #include "ernie/scene/path.h"
5
+
6
+ #include "ernie/util/random.h"
7
+ #include "ernie/util/text.h"
8
+
9
+ #include <algorithm>
10
+ #include <stdexcept>
11
+
12
+ namespace ernie {
13
+
14
+ namespace {
15
+
16
+ /// Calls `visit(name)` for each name of an absolute path's text; "/a/" ends in an empty name.
17
+ template <typename Visit> void ForEachName(std::string_view text, const Visit& visit) {
18
+ if (text.size() <= 1) {
19
+ return;
20
+ }
21
+ for (std::size_t start = 1; start <= text.size();) {
22
+ const std::size_t end = std::min(text.find('/', start), text.size());
23
+ visit(text.substr(start, end - start));
24
+ start = end + 1;
25
+ }
26
+ }
27
+
28
+ } // namespace
29
+
30
+ bool Path::IsValidName(std::string_view name) {
31
+ return IsIdentifier(name);
32
+ }
33
+
34
+ Path::Path(std::string_view text) {
35
+ if (text.empty() || text.front() != '/') {
36
+ throw std::invalid_argument("Prim path '" + std::string(text) + "' is not absolute");
37
+ }
38
+ ForEachName(text, [&](std::string_view name) {
39
+ if (!IsValidName(name)) {
40
+ throw std::invalid_argument("Prim path '" + std::string(text) +
41
+ "' has an invalid name");
42
+ }
43
+ });
44
+ text_ = text;
45
+ }
46
+
47
+ Path Path::Root() {
48
+ return Path("/");
49
+ }
50
+
51
+ std::string_view Path::Name() const {
52
+ if (text_.size() <= 1) {
53
+ return {};
54
+ }
55
+ return std::string_view(text_).substr(text_.rfind('/') + 1);
56
+ }
57
+
58
+ Path Path::Parent() const {
59
+ if (text_.size() <= 1) {
60
+ return {};
61
+ }
62
+ const std::size_t slash = text_.rfind('/');
63
+ return slash == 0 ? Root() : Path(std::string_view(text_).substr(0, slash));
64
+ }
65
+
66
+ Path Path::Child(std::string_view name) const {
67
+ if (IsEmpty() || !IsValidName(name)) {
68
+ throw std::invalid_argument("Cannot append '" + std::string(name) + "' to '" + text_ + "'");
69
+ }
70
+ Path child;
71
+ child.text_ = IsRoot() ? "/" + std::string(name) : text_ + "/" + std::string(name);
72
+ return child;
73
+ }
74
+
75
+ bool Path::HasPrefix(const Path& ancestor) const {
76
+ if (ancestor.IsEmpty() || IsEmpty()) {
77
+ return false;
78
+ }
79
+ if (ancestor.IsRoot()) {
80
+ return true;
81
+ }
82
+ return text_.starts_with(ancestor.text_) &&
83
+ (text_.size() == ancestor.text_.size() || text_[ancestor.text_.size()] == '/');
84
+ }
85
+
86
+ TokenTable::TokenTable() {
87
+ Intern("");
88
+ }
89
+
90
+ Token TokenTable::Intern(std::string_view text) {
91
+ const auto next = static_cast<Token>(texts_.size());
92
+ const Token token = index_.Insert(std::hash<std::string_view>()(text), next,
93
+ [&](Token other) { return texts_[other] == text; });
94
+ if (token == next) {
95
+ texts_.emplace_back(text);
96
+ }
97
+ return token;
98
+ }
99
+
100
+ std::optional<Token> TokenTable::Find(std::string_view text) const {
101
+ return index_.Find(std::hash<std::string_view>()(text),
102
+ [&](Token other) { return texts_[other] == text; });
103
+ }
104
+
105
+ PathTable::PathTable() : nodes_(1) {}
106
+
107
+ std::uint64_t PathTable::Hash(PathId parent, Token name) {
108
+ return Mix64(std::uint64_t{parent} << 32 | name);
109
+ }
110
+
111
+ void PathTable::Reserve(std::size_t count) {
112
+ nodes_.reserve(nodes_.size() + count);
113
+ children_.Reserve(children_.Size() + count);
114
+ names_.Reserve(count);
115
+ }
116
+
117
+ PathId PathTable::Child(PathId parent, Token name) {
118
+ const auto next = static_cast<PathId>(nodes_.size());
119
+ const PathId id = children_.Insert(Hash(parent, name), next, [&](PathId other) {
120
+ return nodes_[other].parent == parent && nodes_[other].name == name;
121
+ });
122
+ if (id != next) {
123
+ return id;
124
+ }
125
+ nodes_.push_back({parent, name});
126
+ Node& above = nodes_[parent];
127
+ if (above.firstChild == kNoPath) {
128
+ above.firstChild = id;
129
+ } else {
130
+ nodes_[above.lastChild].nextSibling = id;
131
+ }
132
+ above.lastChild = id;
133
+ return id;
134
+ }
135
+
136
+ PathId PathTable::Intern(const Path& path) {
137
+ if (path.IsEmpty()) {
138
+ throw std::invalid_argument("An empty path names no prim");
139
+ }
140
+ PathId id = kRootPath;
141
+ ForEachName(path.String(), [&](std::string_view name) { id = Child(id, name); });
142
+ return id;
143
+ }
144
+
145
+ std::optional<PathId> PathTable::Find(const Path& path) const {
146
+ if (path.IsEmpty()) {
147
+ return std::nullopt;
148
+ }
149
+ PathId id = kRootPath;
150
+ bool found = true;
151
+ ForEachName(path.String(), [&](std::string_view name) {
152
+ const std::optional<Token> token = found ? names_.Find(name) : std::nullopt;
153
+ const std::optional<PathId> child =
154
+ token ? children_.Find(Hash(id, *token),
155
+ [&](PathId other) {
156
+ return nodes_[other].parent == id &&
157
+ nodes_[other].name == *token;
158
+ })
159
+ : std::nullopt;
160
+ found = child.has_value();
161
+ if (found) {
162
+ id = *child;
163
+ }
164
+ });
165
+ return found ? std::optional(id) : std::nullopt;
166
+ }
167
+
168
+ Path PathTable::ToPath(PathId id) const {
169
+ if (id == kRootPath) {
170
+ return Path::Root();
171
+ }
172
+ std::vector<std::string_view> names;
173
+ for (; id != kRootPath; id = nodes_[id].parent) {
174
+ names.push_back(names_.Text(nodes_[id].name));
175
+ }
176
+ std::string text;
177
+ for (auto name = names.rbegin(); name != names.rend(); ++name) {
178
+ text += '/';
179
+ text += *name;
180
+ }
181
+ return Path(text);
182
+ }
183
+
184
+ bool PathTable::HasPrefix(PathId id, PathId ancestor) const {
185
+ for (; id != kNoPath; id = nodes_[id].parent) {
186
+ if (id == ancestor) {
187
+ return true;
188
+ }
189
+ }
190
+ return false;
191
+ }
192
+
193
+ } // namespace ernie
@@ -0,0 +1,152 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file path.h
3
+ /// @brief Prim paths, interned names, and the scene's table of paths as (parent, name) nodes.
4
+ #pragma once
5
+
6
+ #include "ernie/util/hash_index.h"
7
+
8
+ #include <compare>
9
+ #include <cstdint>
10
+ #include <deque>
11
+ #include <functional>
12
+ #include <limits>
13
+ #include <optional>
14
+ #include <string>
15
+ #include <string_view>
16
+ #include <vector>
17
+
18
+ namespace ernie {
19
+
20
+ /// @brief An absolute prim path such as `/World/Rover/Wheel_FL`, as text.
21
+ class Path {
22
+ public:
23
+ Path() = default;
24
+ /// @param text An absolute path of valid names.
25
+ /// @throws std::invalid_argument If it is not.
26
+ Path(std::string_view text);
27
+ Path(const char* text) : Path(std::string_view(text)) {}
28
+ Path(const std::string& text) : Path(std::string_view(text)) {}
29
+
30
+ static Path Root();
31
+ /// @return Whether `name` is a valid prim name: a letter or underscore, then letters, digits
32
+ /// and underscores.
33
+ static bool IsValidName(std::string_view name);
34
+
35
+ const std::string& String() const {
36
+ return text_;
37
+ }
38
+ bool IsEmpty() const {
39
+ return text_.empty();
40
+ }
41
+ bool IsRoot() const {
42
+ return text_ == "/";
43
+ }
44
+ /// @return The last name; empty for the root and the empty path.
45
+ std::string_view Name() const;
46
+ /// @return The parent; empty for the root and the empty path.
47
+ Path Parent() const;
48
+ /// @throws std::invalid_argument If this path is empty or `name` is invalid.
49
+ Path Child(std::string_view name) const;
50
+ /// @return Whether this path is `ancestor` or lies below it.
51
+ bool HasPrefix(const Path& ancestor) const;
52
+
53
+ auto operator<=>(const Path&) const = default;
54
+
55
+ private:
56
+ std::string text_;
57
+ };
58
+
59
+ /// An interned name; 0 is no name.
60
+ using Token = std::uint32_t;
61
+
62
+ /// @brief Interned strings: each distinct name is stored once and compared as a number.
63
+ class TokenTable {
64
+ public:
65
+ TokenTable();
66
+ /// @return The name's token, adding it if new.
67
+ Token Intern(std::string_view text);
68
+ /// @return The name's token, if interned.
69
+ std::optional<Token> Find(std::string_view text) const;
70
+ std::string_view Text(Token token) const {
71
+ return texts_[token];
72
+ }
73
+ void Reserve(std::size_t count) {
74
+ index_.Reserve(count);
75
+ }
76
+
77
+ private:
78
+ std::deque<std::string> texts_;
79
+ HashIndex index_;
80
+ };
81
+
82
+ /// An interned path, a node of a `PathTable`; 0 is the root.
83
+ using PathId = std::uint32_t;
84
+ inline constexpr PathId kRootPath = 0;
85
+ inline constexpr PathId kNoPath = std::numeric_limits<PathId>::max();
86
+
87
+ /// @brief Every path the scene has named, as (parent, name) nodes with their children in order.
88
+ /// Paths are never removed, so ids stay valid; prims come and go on them.
89
+ class PathTable {
90
+ public:
91
+ PathTable();
92
+
93
+ /// @return The path's id, adding it and its ancestors if new.
94
+ PathId Intern(const Path& path);
95
+ /// @return The child's id, adding it if new.
96
+ PathId Child(PathId parent, Token name);
97
+ PathId Child(PathId parent, std::string_view name) {
98
+ return Child(parent, names_.Intern(name));
99
+ }
100
+ /// @return The path's id, if interned.
101
+ std::optional<PathId> Find(const Path& path) const;
102
+
103
+ Path ToPath(PathId id) const;
104
+ PathId Parent(PathId id) const {
105
+ return nodes_[id].parent;
106
+ }
107
+ Token Name(PathId id) const {
108
+ return nodes_[id].name;
109
+ }
110
+ PathId FirstChild(PathId id) const {
111
+ return nodes_[id].firstChild;
112
+ }
113
+ PathId NextSibling(PathId id) const {
114
+ return nodes_[id].nextSibling;
115
+ }
116
+ /// @return Whether `id` is `ancestor` or lies below it.
117
+ bool HasPrefix(PathId id, PathId ancestor) const;
118
+
119
+ std::size_t Size() const {
120
+ return nodes_.size();
121
+ }
122
+ /// Makes room for `count` more paths and as many new names.
123
+ void Reserve(std::size_t count);
124
+ TokenTable& Names() {
125
+ return names_;
126
+ }
127
+ const TokenTable& Names() const {
128
+ return names_;
129
+ }
130
+
131
+ private:
132
+ struct Node {
133
+ PathId parent = kNoPath;
134
+ Token name = 0;
135
+ PathId firstChild = kNoPath;
136
+ PathId lastChild = kNoPath;
137
+ PathId nextSibling = kNoPath;
138
+ };
139
+ static std::uint64_t Hash(PathId parent, Token name);
140
+
141
+ TokenTable names_;
142
+ std::vector<Node> nodes_;
143
+ HashIndex children_;
144
+ };
145
+
146
+ } // namespace ernie
147
+
148
+ template <> struct std::hash<ernie::Path> {
149
+ std::size_t operator()(const ernie::Path& path) const noexcept {
150
+ return std::hash<std::string>()(path.String());
151
+ }
152
+ };