warp-lang 1.0.2__py3-none-win_amd64.whl → 1.2.0__py3-none-win_amd64.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.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (356) hide show
  1. warp/__init__.py +108 -97
  2. warp/__init__.pyi +1 -1
  3. warp/bin/warp-clang.dll +0 -0
  4. warp/bin/warp.dll +0 -0
  5. warp/build.py +88 -113
  6. warp/build_dll.py +383 -375
  7. warp/builtins.py +3693 -3354
  8. warp/codegen.py +2925 -2792
  9. warp/config.py +40 -36
  10. warp/constants.py +49 -45
  11. warp/context.py +5409 -5102
  12. warp/dlpack.py +442 -442
  13. warp/examples/__init__.py +16 -16
  14. warp/examples/assets/bear.usd +0 -0
  15. warp/examples/assets/bunny.usd +0 -0
  16. warp/examples/assets/cartpole.urdf +110 -110
  17. warp/examples/assets/crazyflie.usd +0 -0
  18. warp/examples/assets/cube.usd +0 -0
  19. warp/examples/assets/nv_ant.xml +92 -92
  20. warp/examples/assets/nv_humanoid.xml +183 -183
  21. warp/examples/assets/quadruped.urdf +267 -267
  22. warp/examples/assets/rocks.nvdb +0 -0
  23. warp/examples/assets/rocks.usd +0 -0
  24. warp/examples/assets/sphere.usd +0 -0
  25. warp/examples/benchmarks/benchmark_api.py +381 -383
  26. warp/examples/benchmarks/benchmark_cloth.py +278 -277
  27. warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -88
  28. warp/examples/benchmarks/benchmark_cloth_jax.py +97 -100
  29. warp/examples/benchmarks/benchmark_cloth_numba.py +146 -142
  30. warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -77
  31. warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -86
  32. warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -112
  33. warp/examples/benchmarks/benchmark_cloth_warp.py +145 -146
  34. warp/examples/benchmarks/benchmark_launches.py +293 -295
  35. warp/examples/browse.py +29 -29
  36. warp/examples/core/example_dem.py +232 -219
  37. warp/examples/core/example_fluid.py +291 -267
  38. warp/examples/core/example_graph_capture.py +142 -126
  39. warp/examples/core/example_marching_cubes.py +186 -174
  40. warp/examples/core/example_mesh.py +172 -155
  41. warp/examples/core/example_mesh_intersect.py +203 -193
  42. warp/examples/core/example_nvdb.py +174 -170
  43. warp/examples/core/example_raycast.py +103 -90
  44. warp/examples/core/example_raymarch.py +197 -178
  45. warp/examples/core/example_render_opengl.py +183 -141
  46. warp/examples/core/example_sph.py +403 -387
  47. warp/examples/core/example_torch.py +219 -181
  48. warp/examples/core/example_wave.py +261 -248
  49. warp/examples/fem/bsr_utils.py +378 -380
  50. warp/examples/fem/example_apic_fluid.py +432 -389
  51. warp/examples/fem/example_burgers.py +262 -0
  52. warp/examples/fem/example_convection_diffusion.py +180 -168
  53. warp/examples/fem/example_convection_diffusion_dg.py +217 -209
  54. warp/examples/fem/example_deformed_geometry.py +175 -159
  55. warp/examples/fem/example_diffusion.py +199 -173
  56. warp/examples/fem/example_diffusion_3d.py +178 -152
  57. warp/examples/fem/example_diffusion_mgpu.py +219 -214
  58. warp/examples/fem/example_mixed_elasticity.py +242 -222
  59. warp/examples/fem/example_navier_stokes.py +257 -243
  60. warp/examples/fem/example_stokes.py +218 -192
  61. warp/examples/fem/example_stokes_transfer.py +263 -249
  62. warp/examples/fem/mesh_utils.py +133 -109
  63. warp/examples/fem/plot_utils.py +292 -287
  64. warp/examples/optim/example_bounce.py +258 -246
  65. warp/examples/optim/example_cloth_throw.py +220 -209
  66. warp/examples/optim/example_diffray.py +564 -536
  67. warp/examples/optim/example_drone.py +862 -835
  68. warp/examples/optim/example_inverse_kinematics.py +174 -168
  69. warp/examples/optim/example_inverse_kinematics_torch.py +183 -169
  70. warp/examples/optim/example_spring_cage.py +237 -231
  71. warp/examples/optim/example_trajectory.py +221 -199
  72. warp/examples/optim/example_walker.py +304 -293
  73. warp/examples/sim/example_cartpole.py +137 -129
  74. warp/examples/sim/example_cloth.py +194 -186
  75. warp/examples/sim/example_granular.py +122 -111
  76. warp/examples/sim/example_granular_collision_sdf.py +195 -186
  77. warp/examples/sim/example_jacobian_ik.py +234 -214
  78. warp/examples/sim/example_particle_chain.py +116 -105
  79. warp/examples/sim/example_quadruped.py +191 -180
  80. warp/examples/sim/example_rigid_chain.py +195 -187
  81. warp/examples/sim/example_rigid_contact.py +187 -177
  82. warp/examples/sim/example_rigid_force.py +125 -125
  83. warp/examples/sim/example_rigid_gyroscopic.py +107 -95
  84. warp/examples/sim/example_rigid_soft_contact.py +132 -122
  85. warp/examples/sim/example_soft_body.py +188 -177
  86. warp/fabric.py +337 -335
  87. warp/fem/__init__.py +61 -27
  88. warp/fem/cache.py +403 -388
  89. warp/fem/dirichlet.py +178 -179
  90. warp/fem/domain.py +262 -263
  91. warp/fem/field/__init__.py +100 -101
  92. warp/fem/field/field.py +148 -149
  93. warp/fem/field/nodal_field.py +298 -299
  94. warp/fem/field/restriction.py +22 -21
  95. warp/fem/field/test.py +180 -181
  96. warp/fem/field/trial.py +183 -183
  97. warp/fem/geometry/__init__.py +16 -19
  98. warp/fem/geometry/closest_point.py +69 -70
  99. warp/fem/geometry/deformed_geometry.py +270 -271
  100. warp/fem/geometry/element.py +748 -744
  101. warp/fem/geometry/geometry.py +184 -186
  102. warp/fem/geometry/grid_2d.py +380 -373
  103. warp/fem/geometry/grid_3d.py +437 -435
  104. warp/fem/geometry/hexmesh.py +953 -953
  105. warp/fem/geometry/nanogrid.py +455 -0
  106. warp/fem/geometry/partition.py +374 -376
  107. warp/fem/geometry/quadmesh_2d.py +532 -532
  108. warp/fem/geometry/tetmesh.py +840 -840
  109. warp/fem/geometry/trimesh_2d.py +577 -577
  110. warp/fem/integrate.py +1684 -1615
  111. warp/fem/operator.py +190 -191
  112. warp/fem/polynomial.py +214 -213
  113. warp/fem/quadrature/__init__.py +2 -2
  114. warp/fem/quadrature/pic_quadrature.py +243 -245
  115. warp/fem/quadrature/quadrature.py +295 -294
  116. warp/fem/space/__init__.py +179 -292
  117. warp/fem/space/basis_space.py +522 -489
  118. warp/fem/space/collocated_function_space.py +100 -105
  119. warp/fem/space/dof_mapper.py +236 -236
  120. warp/fem/space/function_space.py +148 -145
  121. warp/fem/space/grid_2d_function_space.py +148 -267
  122. warp/fem/space/grid_3d_function_space.py +167 -306
  123. warp/fem/space/hexmesh_function_space.py +253 -352
  124. warp/fem/space/nanogrid_function_space.py +202 -0
  125. warp/fem/space/partition.py +350 -350
  126. warp/fem/space/quadmesh_2d_function_space.py +261 -369
  127. warp/fem/space/restriction.py +161 -160
  128. warp/fem/space/shape/__init__.py +90 -15
  129. warp/fem/space/shape/cube_shape_function.py +728 -738
  130. warp/fem/space/shape/shape_function.py +102 -103
  131. warp/fem/space/shape/square_shape_function.py +611 -611
  132. warp/fem/space/shape/tet_shape_function.py +565 -567
  133. warp/fem/space/shape/triangle_shape_function.py +429 -429
  134. warp/fem/space/tetmesh_function_space.py +224 -292
  135. warp/fem/space/topology.py +297 -295
  136. warp/fem/space/trimesh_2d_function_space.py +153 -221
  137. warp/fem/types.py +77 -77
  138. warp/fem/utils.py +495 -495
  139. warp/jax.py +166 -141
  140. warp/jax_experimental.py +341 -339
  141. warp/native/array.h +1081 -1025
  142. warp/native/builtin.h +1603 -1560
  143. warp/native/bvh.cpp +402 -398
  144. warp/native/bvh.cu +533 -525
  145. warp/native/bvh.h +430 -429
  146. warp/native/clang/clang.cpp +496 -464
  147. warp/native/crt.cpp +42 -32
  148. warp/native/crt.h +352 -335
  149. warp/native/cuda_crt.h +1049 -1049
  150. warp/native/cuda_util.cpp +549 -540
  151. warp/native/cuda_util.h +288 -203
  152. warp/native/cutlass_gemm.cpp +34 -34
  153. warp/native/cutlass_gemm.cu +372 -372
  154. warp/native/error.cpp +66 -66
  155. warp/native/error.h +27 -27
  156. warp/native/exports.h +187 -0
  157. warp/native/fabric.h +228 -228
  158. warp/native/hashgrid.cpp +301 -278
  159. warp/native/hashgrid.cu +78 -77
  160. warp/native/hashgrid.h +227 -227
  161. warp/native/initializer_array.h +32 -32
  162. warp/native/intersect.h +1204 -1204
  163. warp/native/intersect_adj.h +365 -365
  164. warp/native/intersect_tri.h +322 -322
  165. warp/native/marching.cpp +2 -2
  166. warp/native/marching.cu +497 -497
  167. warp/native/marching.h +2 -2
  168. warp/native/mat.h +1545 -1498
  169. warp/native/matnn.h +333 -333
  170. warp/native/mesh.cpp +203 -203
  171. warp/native/mesh.cu +292 -293
  172. warp/native/mesh.h +1887 -1887
  173. warp/native/nanovdb/GridHandle.h +366 -0
  174. warp/native/nanovdb/HostBuffer.h +590 -0
  175. warp/native/nanovdb/NanoVDB.h +6624 -4782
  176. warp/native/nanovdb/PNanoVDB.h +3390 -2553
  177. warp/native/noise.h +850 -850
  178. warp/native/quat.h +1112 -1085
  179. warp/native/rand.h +303 -299
  180. warp/native/range.h +108 -108
  181. warp/native/reduce.cpp +156 -156
  182. warp/native/reduce.cu +348 -348
  183. warp/native/runlength_encode.cpp +61 -61
  184. warp/native/runlength_encode.cu +46 -46
  185. warp/native/scan.cpp +30 -30
  186. warp/native/scan.cu +36 -36
  187. warp/native/scan.h +7 -7
  188. warp/native/solid_angle.h +442 -442
  189. warp/native/sort.cpp +94 -94
  190. warp/native/sort.cu +97 -97
  191. warp/native/sort.h +14 -14
  192. warp/native/sparse.cpp +337 -337
  193. warp/native/sparse.cu +544 -544
  194. warp/native/spatial.h +630 -630
  195. warp/native/svd.h +562 -562
  196. warp/native/temp_buffer.h +30 -30
  197. warp/native/vec.h +1177 -1133
  198. warp/native/volume.cpp +529 -297
  199. warp/native/volume.cu +58 -32
  200. warp/native/volume.h +960 -538
  201. warp/native/volume_builder.cu +446 -425
  202. warp/native/volume_builder.h +34 -19
  203. warp/native/volume_impl.h +61 -0
  204. warp/native/warp.cpp +1057 -1052
  205. warp/native/warp.cu +2949 -2828
  206. warp/native/warp.h +321 -305
  207. warp/optim/__init__.py +9 -9
  208. warp/optim/adam.py +120 -120
  209. warp/optim/linear.py +1104 -939
  210. warp/optim/sgd.py +104 -92
  211. warp/render/__init__.py +10 -10
  212. warp/render/render_opengl.py +3356 -3204
  213. warp/render/render_usd.py +768 -749
  214. warp/render/utils.py +152 -150
  215. warp/sim/__init__.py +52 -59
  216. warp/sim/articulation.py +685 -685
  217. warp/sim/collide.py +1594 -1590
  218. warp/sim/import_mjcf.py +489 -481
  219. warp/sim/import_snu.py +220 -221
  220. warp/sim/import_urdf.py +536 -516
  221. warp/sim/import_usd.py +887 -881
  222. warp/sim/inertia.py +316 -317
  223. warp/sim/integrator.py +234 -233
  224. warp/sim/integrator_euler.py +1956 -1956
  225. warp/sim/integrator_featherstone.py +1917 -1991
  226. warp/sim/integrator_xpbd.py +3288 -3312
  227. warp/sim/model.py +4473 -4314
  228. warp/sim/particles.py +113 -112
  229. warp/sim/render.py +417 -403
  230. warp/sim/utils.py +413 -410
  231. warp/sparse.py +1289 -1227
  232. warp/stubs.py +2192 -2469
  233. warp/tape.py +1162 -225
  234. warp/tests/__init__.py +1 -1
  235. warp/tests/__main__.py +4 -4
  236. warp/tests/assets/test_index_grid.nvdb +0 -0
  237. warp/tests/assets/torus.usda +105 -105
  238. warp/tests/aux_test_class_kernel.py +26 -26
  239. warp/tests/aux_test_compile_consts_dummy.py +10 -10
  240. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -21
  241. warp/tests/aux_test_dependent.py +20 -22
  242. warp/tests/aux_test_grad_customs.py +21 -23
  243. warp/tests/aux_test_reference.py +9 -11
  244. warp/tests/aux_test_reference_reference.py +8 -10
  245. warp/tests/aux_test_square.py +15 -17
  246. warp/tests/aux_test_unresolved_func.py +14 -14
  247. warp/tests/aux_test_unresolved_symbol.py +14 -14
  248. warp/tests/disabled_kinematics.py +237 -239
  249. warp/tests/run_coverage_serial.py +31 -31
  250. warp/tests/test_adam.py +155 -157
  251. warp/tests/test_arithmetic.py +1088 -1124
  252. warp/tests/test_array.py +2415 -2326
  253. warp/tests/test_array_reduce.py +148 -150
  254. warp/tests/test_async.py +666 -656
  255. warp/tests/test_atomic.py +139 -141
  256. warp/tests/test_bool.py +212 -149
  257. warp/tests/test_builtins_resolution.py +1290 -1292
  258. warp/tests/test_bvh.py +162 -171
  259. warp/tests/test_closest_point_edge_edge.py +227 -228
  260. warp/tests/test_codegen.py +562 -553
  261. warp/tests/test_compile_consts.py +217 -101
  262. warp/tests/test_conditional.py +244 -246
  263. warp/tests/test_copy.py +230 -215
  264. warp/tests/test_ctypes.py +630 -632
  265. warp/tests/test_dense.py +65 -67
  266. warp/tests/test_devices.py +89 -98
  267. warp/tests/test_dlpack.py +528 -529
  268. warp/tests/test_examples.py +403 -378
  269. warp/tests/test_fabricarray.py +952 -955
  270. warp/tests/test_fast_math.py +60 -54
  271. warp/tests/test_fem.py +1298 -1278
  272. warp/tests/test_fp16.py +128 -130
  273. warp/tests/test_func.py +336 -337
  274. warp/tests/test_generics.py +596 -571
  275. warp/tests/test_grad.py +885 -640
  276. warp/tests/test_grad_customs.py +331 -336
  277. warp/tests/test_hash_grid.py +208 -164
  278. warp/tests/test_import.py +37 -39
  279. warp/tests/test_indexedarray.py +1132 -1134
  280. warp/tests/test_intersect.py +65 -67
  281. warp/tests/test_jax.py +305 -307
  282. warp/tests/test_large.py +169 -164
  283. warp/tests/test_launch.py +352 -354
  284. warp/tests/test_lerp.py +217 -261
  285. warp/tests/test_linear_solvers.py +189 -171
  286. warp/tests/test_lvalue.py +419 -493
  287. warp/tests/test_marching_cubes.py +63 -65
  288. warp/tests/test_mat.py +1799 -1827
  289. warp/tests/test_mat_lite.py +113 -115
  290. warp/tests/test_mat_scalar_ops.py +2905 -2889
  291. warp/tests/test_math.py +124 -193
  292. warp/tests/test_matmul.py +498 -499
  293. warp/tests/test_matmul_lite.py +408 -410
  294. warp/tests/test_mempool.py +186 -190
  295. warp/tests/test_mesh.py +281 -324
  296. warp/tests/test_mesh_query_aabb.py +226 -241
  297. warp/tests/test_mesh_query_point.py +690 -702
  298. warp/tests/test_mesh_query_ray.py +290 -303
  299. warp/tests/test_mlp.py +274 -276
  300. warp/tests/test_model.py +108 -110
  301. warp/tests/test_module_hashing.py +111 -0
  302. warp/tests/test_modules_lite.py +36 -39
  303. warp/tests/test_multigpu.py +161 -163
  304. warp/tests/test_noise.py +244 -248
  305. warp/tests/test_operators.py +248 -250
  306. warp/tests/test_options.py +121 -125
  307. warp/tests/test_peer.py +131 -137
  308. warp/tests/test_pinned.py +76 -78
  309. warp/tests/test_print.py +52 -54
  310. warp/tests/test_quat.py +2084 -2086
  311. warp/tests/test_rand.py +324 -288
  312. warp/tests/test_reload.py +207 -217
  313. warp/tests/test_rounding.py +177 -179
  314. warp/tests/test_runlength_encode.py +188 -190
  315. warp/tests/test_sim_grad.py +241 -0
  316. warp/tests/test_sim_kinematics.py +89 -97
  317. warp/tests/test_smoothstep.py +166 -168
  318. warp/tests/test_snippet.py +303 -266
  319. warp/tests/test_sparse.py +466 -460
  320. warp/tests/test_spatial.py +2146 -2148
  321. warp/tests/test_special_values.py +362 -0
  322. warp/tests/test_streams.py +484 -473
  323. warp/tests/test_struct.py +708 -675
  324. warp/tests/test_tape.py +171 -148
  325. warp/tests/test_torch.py +741 -743
  326. warp/tests/test_transient_module.py +85 -87
  327. warp/tests/test_types.py +554 -659
  328. warp/tests/test_utils.py +488 -499
  329. warp/tests/test_vec.py +1262 -1268
  330. warp/tests/test_vec_lite.py +71 -73
  331. warp/tests/test_vec_scalar_ops.py +2097 -2099
  332. warp/tests/test_verify_fp.py +92 -94
  333. warp/tests/test_volume.py +961 -736
  334. warp/tests/test_volume_write.py +338 -265
  335. warp/tests/unittest_serial.py +38 -37
  336. warp/tests/unittest_suites.py +367 -359
  337. warp/tests/unittest_utils.py +434 -578
  338. warp/tests/unused_test_misc.py +69 -71
  339. warp/tests/walkthrough_debug.py +85 -85
  340. warp/thirdparty/appdirs.py +598 -598
  341. warp/thirdparty/dlpack.py +143 -143
  342. warp/thirdparty/unittest_parallel.py +563 -561
  343. warp/torch.py +321 -295
  344. warp/types.py +4941 -4450
  345. warp/utils.py +1008 -821
  346. {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/LICENSE.md +126 -126
  347. {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/METADATA +365 -400
  348. warp_lang-1.2.0.dist-info/RECORD +359 -0
  349. warp/examples/assets/cube.usda +0 -42
  350. warp/examples/assets/sphere.usda +0 -56
  351. warp/examples/assets/torus.usda +0 -105
  352. warp/examples/fem/example_convection_diffusion_dg0.py +0 -194
  353. warp/native/nanovdb/PNanoVDBWrite.h +0 -295
  354. warp_lang-1.0.2.dist-info/RECORD +0 -352
  355. {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/WHEEL +0 -0
  356. {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,590 @@
1
+ // Copyright Contributors to the OpenVDB Project
2
+ // SPDX-License-Identifier: MPL-2.0
3
+
4
+ /*!
5
+ @file nanovdb/HostBuffer.h
6
+
7
+ @date April 20, 2021
8
+
9
+ @brief HostBuffer - a buffer that contains a shared or private bump
10
+ pool to either externally or internally managed host memory.
11
+
12
+ @details This HostBuffer can be used in multiple ways, most of which are
13
+ demonstrated in the examples below. Memory in the pool can
14
+ be managed or unmanged (e.g. internal or external) and can
15
+ be shared between multiple buffers or belong to a single buffer.
16
+
17
+ Example that uses HostBuffer::create inside io::readGrids to create a
18
+ full self-managed buffer, i.e. not shared and without padding, per grid in the file.
19
+ @code
20
+ auto handles = nanovdb::io::readGrids("file.nvdb");
21
+ @endcode
22
+
23
+ Example that uses HostBuffer::createFull. Assuming you have a raw pointer
24
+ to a NanoVDB grid of unknown type, this examples shows how to create its
25
+ GridHandle which can be used to enquire about the grid type and meta data.
26
+ @code
27
+ void *data;// pointer to a NanoVDB grid of unknown type
28
+ uint64_t size;// byte size of NanoVDB grid of unknown type
29
+ auto buffer = nanovdb::HostBuffer::createFull(size, data);
30
+ nanovdb::GridHandle<> gridHandle(std::move(buffer));
31
+ @endcode
32
+
33
+ Example that uses HostBuffer::createPool for internally managed host memory.
34
+ Suppose you want to read multiple grids in multiple files, but reuse the same
35
+ fixed sized memory buffer to both avoid memory fragmentation as well as
36
+ exceeding the fixed memory ceiling!
37
+ @code
38
+ auto pool = nanovdb::HostBuffer::createPool(1 << 30);// 1 GB memory pool
39
+ std::vector<std::string>> frames;// vector of grid names
40
+ for (int i=0; i<frames.size(); ++i) {
41
+ auto handles = nanovdb::io::readGrids(frames[i], 0, pool);// throws if grids in file exceed 1 GB
42
+ ...
43
+ pool.reset();// clears all handles and resets the memory pool for reuse
44
+ }
45
+ @endcode
46
+
47
+ Example that uses HostBuffer::createPool for externally managed host memory.
48
+ Note that in this example @c handles are allowed to outlive @c pool since
49
+ they internally store a shared pointer to the memory pool. However @c data
50
+ MUST outlive @c handles since the pool does not own its memory in this example.
51
+ @code
52
+ const size_t poolSize = 1 << 30;// 1 GB
53
+ void *data = std::malloc(size + NANOVDB_DATA_ALIGNMENT);// 1 GB pool with padding
54
+ void *buffer = nanovdb::alignPtr(data);// 32B aligned buffer
55
+ //void *buffer = std::aligned_alloc(NANOVDB_DATA_ALIGNMENT, poolSize);// in C++17
56
+ auto pool = nanovdb::HostBuffer::createPool(poolSize, buffer);
57
+ auto handles1 = nanovdb::io::readGrids("file1.nvdb", 0, pool);
58
+ auto handles2 = nanovdb::io::readGrids("file2.nvdb", 0, pool);
59
+ ....
60
+ std::free(data);
61
+ //std::free(buffer);
62
+ @endcode
63
+
64
+ Example that uses HostBuffer::createPool for externally managed host memory.
65
+ Note that in this example @c handles are allowed to outlive @c pool since
66
+ they internally store a shared pointer to the memory pool. However @c array
67
+ MUST outlive @c handles since the pool does not own its memory in this example.
68
+ @code
69
+ const size_t poolSize = 1 << 30;// 1 GB
70
+ std::unique_ptr<char[]> array(new char[size + NANOVDB_DATA_ALIGNMENT]);// scoped pool of 1 GB with padding
71
+ void *buffer = nanovdb::alignPtr(array.get());// 32B aligned buffer
72
+ auto pool = nanovdb::HostBuffer::createPool(poolSize, buffer);
73
+ auto handles = nanovdb::io::readGrids("file.nvdb", 0, pool);
74
+ @endcode
75
+ */
76
+
77
+ #ifndef NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED
78
+ #define NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED
79
+
80
+ #include <nanovdb/NanoVDB.h>// for NANOVDB_DATA_ALIGNMENT;
81
+ #include <stdint.h> // for types like int32_t etc
82
+ #include <cstdio> // for fprintf
83
+ #include <cstdlib> // for std::malloc/std::realloc/std::free
84
+ #include <memory>// for std::make_shared
85
+ #include <mutex>// for std::mutex
86
+ #include <unordered_set>// for std::unordered_set
87
+ #include <cassert>// for assert
88
+ #include <sstream>// for std::stringstream
89
+ #include <cstring>// for memcpy
90
+
91
+ #define checkPtr(ptr, msg) \
92
+ { \
93
+ ptrAssert((ptr), (msg), __FILE__, __LINE__); \
94
+ }
95
+
96
+ namespace nanovdb {
97
+
98
+ template<typename BufferT>
99
+ struct BufferTraits
100
+ {
101
+ static constexpr bool hasDeviceDual = false;
102
+ };
103
+
104
+ // ----------------------------> HostBuffer <--------------------------------------
105
+
106
+ /// @brief This is a buffer that contains a shared or private pool
107
+ /// to either externally or internally managed host memory.
108
+ ///
109
+ /// @note Terminology:
110
+ /// Pool: 0 = buffer.size() < buffer.poolSize()
111
+ /// Buffer: 0 < buffer.size() < buffer.poolSize()
112
+ /// Full: 0 < buffer.size() = buffer.poolSize()
113
+ /// Empty: 0 = buffer.size() = buffer.poolSize()
114
+ class HostBuffer
115
+ {
116
+ struct Pool;// forward declaration of private pool struct
117
+ std::shared_ptr<Pool> mPool;
118
+ uint64_t mSize; // total number of bytes for the NanoVDB grid.
119
+ void* mData; // raw buffer for the NanoVDB grid.
120
+
121
+ #if defined(DEBUG) || defined(_DEBUG)
122
+ static inline void ptrAssert(void* ptr, const char* msg, const char* file, int line, bool abort = true)
123
+ {
124
+ if (ptr == nullptr) {
125
+ fprintf(stderr, "NULL pointer error: %s %s %d\n", msg, file, line);
126
+ if (abort)
127
+ exit(1);
128
+ }
129
+ if (uint64_t(ptr) % NANOVDB_DATA_ALIGNMENT) {
130
+ fprintf(stderr, "Alignment pointer error: %s %s %d\n", msg, file, line);
131
+ if (abort)
132
+ exit(1);
133
+ }
134
+ }
135
+ #else
136
+ static inline void ptrAssert(void*, const char*, const char*, int, bool = true)
137
+ {
138
+ }
139
+ #endif
140
+
141
+ public:
142
+ /// @brief Return a full buffer or an empty buffer
143
+ HostBuffer(uint64_t bufferSize = 0);
144
+
145
+ /// @brief Move copy-constructor
146
+ HostBuffer(HostBuffer&& other);
147
+
148
+ /// @brief Custom descructor
149
+ ~HostBuffer() { this->clear(); }
150
+
151
+ /// @brief Move copy assignment operation
152
+ HostBuffer& operator=(HostBuffer&& other);
153
+
154
+ /// @brief Disallow copy-construction
155
+ HostBuffer(const HostBuffer&) = delete;
156
+
157
+ /// @brief Disallow copy assignment operation
158
+ HostBuffer& operator=(const HostBuffer&) = delete;
159
+
160
+ /// @brief Return a pool buffer which satisfies: buffer.size == 0,
161
+ /// buffer.poolSize() == poolSize, and buffer.data() == nullptr.
162
+ /// If data==nullptr, memory for the pool will be allocated.
163
+ ///
164
+ /// @throw If poolSize is zero.
165
+ static HostBuffer createPool(uint64_t poolSize, void *data = nullptr);
166
+
167
+ /// @brief Return a full buffer which satisfies: buffer.size == bufferSize,
168
+ /// buffer.poolSize() == bufferSize, and buffer.data() == data.
169
+ /// If data==nullptr, memory for the pool will be allocated.
170
+ ///
171
+ /// @throw If bufferSize is zero.
172
+ static HostBuffer createFull(uint64_t bufferSize, void *data = nullptr);
173
+
174
+ /// @brief Return a buffer with @c bufferSize bytes managed by
175
+ /// the specified memory @c pool. If none is provided, i.e.
176
+ /// @c pool == nullptr or @c pool->poolSize() == 0, one is
177
+ /// created with size @c bufferSize, i.e. a full buffer is returned.
178
+ ///
179
+ /// @throw If the specified @c pool has insufficient memory for
180
+ /// the requested buffer size.
181
+ static HostBuffer create(uint64_t bufferSize, const HostBuffer* pool = nullptr);
182
+
183
+ /// @brief Initialize as a full buffer with the specified size. If data is NULL
184
+ /// the memory is internally allocated.
185
+ void init(uint64_t bufferSize, void *data = nullptr);
186
+
187
+ //@{
188
+ /// @brief Retuns a pointer to the raw memory buffer managed by this allocator.
189
+ ///
190
+ /// @warning Note that the pointer can be NULL if the allocator was not initialized!
191
+ const void* data() const { return mData; }
192
+ void* data() { return mData; }
193
+ //@}
194
+
195
+ //@{
196
+ /// @brief Returns the size in bytes associated with this buffer.
197
+ uint64_t bufferSize() const { return mSize; }
198
+ uint64_t size() const { return this->bufferSize(); }
199
+ //@}
200
+
201
+ /// @brief Returns the size in bytes of the memory pool shared with this instance.
202
+ uint64_t poolSize() const;
203
+
204
+ /// @brief Return true if memory is managed (using std::malloc and std:free) by the
205
+ /// shared pool in this buffer. Else memory is assumed to be managed externally.
206
+ bool isManaged() const;
207
+
208
+ //@{
209
+ /// @brief Returns true if this buffer has no memory associated with it
210
+ bool isEmpty() const { return !mPool || mSize == 0 || mData == nullptr; }
211
+ bool empty() const { return this->isEmpty(); }
212
+ //@}
213
+
214
+ /// @brief Return true if this is a pool, i.e. an empty buffer with a nonempty
215
+ /// internal pool, i.e. this->size() == 0 and this->poolSize() != 0
216
+ bool isPool() const { return mSize == 0 && this->poolSize() > 0; }
217
+
218
+ /// @brief Return true if the pool exists, is nonempty but has no more available memory
219
+ bool isFull() const;
220
+
221
+ /// @brief Clear this buffer so it is empty.
222
+ void clear();
223
+
224
+ /// @brief Clears all existing buffers that are registered against the memory pool
225
+ /// and resets the pool so it can be reused to create new buffers.
226
+ ///
227
+ /// @throw If this instance is not empty or contains no pool.
228
+ ///
229
+ /// @warning This method is not thread-safe!
230
+ void reset();
231
+
232
+ /// @brief Total number of bytes from the pool currently in use by buffers
233
+ uint64_t poolUsage() const;
234
+
235
+ /// @brief resize the pool size. It will attempt to resize the existing
236
+ /// memory block, but if that fails a deep copy is performed.
237
+ /// If @c data is not NULL it will be used as new externally
238
+ /// managed memory for the pool. All registered buffers are
239
+ /// updated so GridHandle::grid might return a new address (if
240
+ /// deep copy was performed).
241
+ ///
242
+ /// @note This method can be use to resize the memory pool and even
243
+ /// change it from internally to externally managed memory or vice versa.
244
+ ///
245
+ /// @throw if @c poolSize is less than this->poolUsage() the used memory
246
+ /// or allocations fail.
247
+ void resizePool(uint64_t poolSize, void *data = nullptr);
248
+
249
+ }; // HostBuffer class
250
+
251
+ // --------------------------> Implementation of HostBuffer::Pool <------------------------------------
252
+
253
+ // This is private struct of HostBuffer so you can safely ignore the API
254
+ struct HostBuffer::Pool
255
+ {
256
+ using HashTableT = std::unordered_set<HostBuffer*>;
257
+ std::mutex mMutex; // mutex for updating mRegister and mFree
258
+ HashTableT mRegister;
259
+ void *mData, *mFree;
260
+ uint64_t mSize, mPadding;
261
+ bool mManaged;
262
+
263
+ /// @brief External memory ctor
264
+ Pool(uint64_t size = 0, void* data = nullptr)
265
+ : mData(data)
266
+ , mFree(mData)
267
+ , mSize(size)
268
+ , mPadding(0)
269
+ , mManaged(data == nullptr)
270
+ {
271
+ if (mManaged) {
272
+ mData = Pool::alloc(mSize);
273
+ if (mData == nullptr) throw std::runtime_error("Pool::Pool malloc failed");
274
+ }
275
+ mPadding = alignmentPadding(mData);
276
+ if (!mManaged && mPadding != 0) {
277
+ throw std::runtime_error("Pool::Pool: external memory buffer is not aligned to " +
278
+ std::to_string(NANOVDB_DATA_ALIGNMENT) +
279
+ " bytes.\nHint: use nanovdb::alignPtr or std::aligned_alloc (C++17 only)");
280
+ }
281
+ mFree = util::PtrAdd(mData, mPadding);
282
+ }
283
+
284
+ /// @brief Custom destructor
285
+ ~Pool()
286
+ {
287
+ assert(mRegister.empty());
288
+ if (mManaged) std::free(mData);
289
+ }
290
+
291
+ /// @brief Disallow copy-construction
292
+ Pool(const Pool&) = delete;
293
+
294
+ /// @brief Disallow move-construction
295
+ Pool(const Pool&&) = delete;
296
+
297
+ /// @brief Disallow copy assignment operation
298
+ Pool& operator=(const Pool&) = delete;
299
+
300
+ /// @brief Disallow move assignment operation
301
+ Pool& operator=(const Pool&&) = delete;
302
+
303
+ /// @brief Return the total number of bytes used from this Pool by buffers
304
+ uint64_t usage() const { return util::PtrDiff(mFree, mData) - mPadding; }
305
+
306
+ /// @brief Allocate a buffer of the specified size and add it to the register
307
+ void add(HostBuffer* buffer, uint64_t size)
308
+ {
309
+ void *alignedFree = util::PtrAdd(mFree, alignmentPadding(mFree));
310
+
311
+ if (util::PtrAdd(alignedFree, size) > util::PtrAdd(mData, mPadding + mSize)) {
312
+ std::stringstream ss;
313
+ ss << "HostBuffer::Pool: insufficient memory\n"
314
+ << "\tA buffer requested " << size << " bytes with " << NANOVDB_DATA_ALIGNMENT
315
+ << "-bytes alignment from a pool with "
316
+ << mSize << " bytes of which\n\t" << (util::PtrDiff(alignedFree, mData) - mPadding)
317
+ << " bytes are used by " << mRegister.size() << " other buffer(s). "
318
+ << "Pool is " << (mManaged ? "internally" : "externally") << " managed.\n";
319
+ //std::cerr << ss.str();
320
+ throw std::runtime_error(ss.str());
321
+ }
322
+ buffer->mSize = size;
323
+ const std::lock_guard<std::mutex> lock(mMutex);
324
+ mRegister.insert(buffer);
325
+ buffer->mData = alignedFree;
326
+ mFree = util::PtrAdd(alignedFree, size);
327
+ }
328
+
329
+ /// @brief Remove the specified buffer from the register
330
+ void remove(HostBuffer *buffer)
331
+ {
332
+ const std::lock_guard<std::mutex> lock(mMutex);
333
+ mRegister.erase(buffer);
334
+ }
335
+
336
+ /// @brief Replaces buffer1 with buffer2 in the register
337
+ void replace(HostBuffer *buffer1, HostBuffer *buffer2)
338
+ {
339
+ const std::lock_guard<std::mutex> lock(mMutex);
340
+ mRegister.erase( buffer1);
341
+ mRegister.insert(buffer2);
342
+ }
343
+
344
+ /// @brief Reset the register and all its buffers
345
+ void reset()
346
+ {
347
+ for (HostBuffer *buffer : mRegister) {
348
+ buffer->mPool.reset();
349
+ buffer->mSize = 0;
350
+ buffer->mData = nullptr;
351
+ }
352
+ mRegister.clear();
353
+ mFree = util::PtrAdd(mData, mPadding);
354
+ }
355
+
356
+ /// @brief Resize this Pool and update registered buffers as needed. If data is no NULL
357
+ /// it is used as externally managed memory.
358
+ void resize(uint64_t size, void *data = nullptr)
359
+ {
360
+ const uint64_t memUsage = this->usage();
361
+
362
+ const bool managed = (data == nullptr);
363
+
364
+ if (!managed && alignmentPadding(data) != 0) {
365
+ throw std::runtime_error("Pool::resize: external memory buffer is not aligned to " +
366
+ std::to_string(NANOVDB_DATA_ALIGNMENT) + " bytes");
367
+ }
368
+
369
+ if (memUsage > size) {
370
+ throw std::runtime_error("Pool::resize: insufficient memory");
371
+ }
372
+
373
+ uint64_t padding = 0;
374
+ if (mManaged && managed && size != mSize) { // managed -> managed
375
+ padding = mPadding;
376
+ data = Pool::realloc(mData, memUsage, size, padding); // performs both copy and free of mData
377
+ } else if (!mManaged && managed) { // un-managed -> managed
378
+ data = Pool::alloc(size);
379
+ padding = alignmentPadding(data);
380
+ }
381
+
382
+ if (data == nullptr) {
383
+ throw std::runtime_error("Pool::resize: allocation failed");
384
+ } else if (data != mData) {
385
+ void* paddedData = util::PtrAdd(data, padding);
386
+
387
+ if (!(mManaged && managed)) { // no need to copy if managed -> managed
388
+ memcpy(paddedData, util::PtrAdd(mData, mPadding), memUsage);
389
+ }
390
+
391
+ for (HostBuffer* buffer : mRegister) { // update registered buffers
392
+ //buffer->mData = paddedData + ptrdiff_t(buffer->mData - (mData + mPadding));
393
+ buffer->mData = util::PtrAdd(paddedData, util::PtrDiff(buffer->mData, util::PtrAdd(mData, mPadding)));
394
+ }
395
+ mFree = util::PtrAdd(paddedData, memUsage); // update the free pointer
396
+ if (mManaged && !managed) {// only free if managed -> un-managed
397
+ std::free(mData);
398
+ }
399
+
400
+ mData = data;
401
+ mPadding = padding;
402
+ }
403
+ mSize = size;
404
+ mManaged = managed;
405
+ }
406
+ /// @brief Return true is all the memory in this pool is in use.
407
+ bool isFull() const
408
+ {
409
+ assert(mFree <= util::PtrAdd(mData, mPadding + mSize));
410
+ return mSize > 0 ? mFree == util::PtrAdd(mData, mPadding + mSize) : false;
411
+ }
412
+
413
+ private:
414
+
415
+ static void* alloc(uint64_t size)
416
+ {
417
+ //#if (__cplusplus >= 201703L)
418
+ // return std::aligned_alloc(NANOVDB_DATA_ALIGNMENT, size);//C++17 or newer
419
+ //#else
420
+ // make sure we alloc enough space to align the result
421
+ return std::malloc(size + NANOVDB_DATA_ALIGNMENT);
422
+ //#endif
423
+ }
424
+
425
+ static void* realloc(void* const origData,
426
+ uint64_t origSize,
427
+ uint64_t desiredSize,
428
+ uint64_t& padding)
429
+ {
430
+ // make sure we alloc enough space to align the result
431
+ void* data = std::realloc(origData, desiredSize + NANOVDB_DATA_ALIGNMENT);
432
+
433
+ if (data != nullptr && data != origData) {
434
+ uint64_t newPadding = alignmentPadding(data);
435
+ // Number of padding bytes may have changed -- move data if that's the case
436
+ if (newPadding != padding) {
437
+ // Realloc should not happen when shrinking down buffer, but let's be safe
438
+ std::memmove(util::PtrAdd(data, newPadding),
439
+ util::PtrAdd(data, padding),
440
+ math::Min(origSize, desiredSize));
441
+ padding = newPadding;
442
+ }
443
+ }
444
+
445
+ return data;
446
+ }
447
+
448
+ };// struct HostBuffer::Pool
449
+
450
+ // --------------------------> Implementation of HostBuffer <------------------------------------
451
+
452
+ inline HostBuffer::HostBuffer(uint64_t size) : mPool(nullptr), mSize(size), mData(nullptr)
453
+ {
454
+ if (size>0) {
455
+ mPool = std::make_shared<Pool>(size);
456
+ mData = mPool->mFree;
457
+ mPool->mRegister.insert(this);
458
+ mPool->mFree = util::PtrAdd(mPool->mFree, size);
459
+ }
460
+ }
461
+
462
+ inline HostBuffer::HostBuffer(HostBuffer&& other) : mPool(other.mPool), mSize(other.mSize), mData(other.mData)
463
+ {
464
+ if (mPool && mSize != 0) {
465
+ mPool->replace(&other, this);
466
+ }
467
+ other.mPool.reset();
468
+ other.mSize = 0;
469
+ other.mData = nullptr;
470
+ }
471
+
472
+ inline void HostBuffer::init(uint64_t bufferSize, void *data)
473
+ {
474
+ if (bufferSize == 0) {
475
+ throw std::runtime_error("HostBuffer: invalid buffer size");
476
+ }
477
+ if (mPool) {
478
+ mPool.reset();
479
+ }
480
+ if (!mPool || mPool->mSize != bufferSize) {
481
+ mPool = std::make_shared<Pool>(bufferSize, data);
482
+ }
483
+ mPool->add(this, bufferSize);
484
+ }
485
+
486
+ inline HostBuffer& HostBuffer::operator=(HostBuffer&& other)
487
+ {
488
+ if (mPool) {
489
+ mPool->remove(this);
490
+ }
491
+ mPool = other.mPool;
492
+ mSize = other.mSize;
493
+ mData = other.mData;
494
+ if (mPool && mSize != 0) {
495
+ mPool->replace(&other, this);
496
+ }
497
+ other.mPool.reset();
498
+ other.mSize = 0;
499
+ other.mData = nullptr;
500
+ return *this;
501
+ }
502
+
503
+ inline uint64_t HostBuffer::poolSize() const
504
+ {
505
+ return mPool ? mPool->mSize : 0u;
506
+ }
507
+
508
+ inline uint64_t HostBuffer::poolUsage() const
509
+ {
510
+ return mPool ? mPool->usage(): 0u;
511
+ }
512
+
513
+ inline bool HostBuffer::isManaged() const
514
+ {
515
+ return mPool ? mPool->mManaged : false;
516
+ }
517
+
518
+ inline bool HostBuffer::isFull() const
519
+ {
520
+ return mPool ? mPool->isFull() : false;
521
+ }
522
+
523
+ inline HostBuffer HostBuffer::createPool(uint64_t poolSize, void *data)
524
+ {
525
+ if (poolSize == 0) {
526
+ throw std::runtime_error("HostBuffer: invalid pool size");
527
+ }
528
+ HostBuffer buffer;
529
+ buffer.mPool = std::make_shared<Pool>(poolSize, data);
530
+ // note the buffer is NOT registered by its pool since it is not using its memory
531
+ buffer.mSize = 0;
532
+ buffer.mData = nullptr;
533
+ return buffer;
534
+ }
535
+
536
+ inline HostBuffer HostBuffer::createFull(uint64_t bufferSize, void *data)
537
+ {
538
+ if (bufferSize == 0) {
539
+ throw std::runtime_error("HostBuffer: invalid buffer size");
540
+ }
541
+ HostBuffer buffer;
542
+ buffer.mPool = std::make_shared<Pool>(bufferSize, data);
543
+ buffer.mPool->add(&buffer, bufferSize);
544
+ return buffer;
545
+ }
546
+
547
+ inline HostBuffer HostBuffer::create(uint64_t bufferSize, const HostBuffer* pool)
548
+ {
549
+ HostBuffer buffer;
550
+ if (pool == nullptr || !pool->mPool) {
551
+ buffer.mPool = std::make_shared<Pool>(bufferSize);
552
+ } else {
553
+ buffer.mPool = pool->mPool;
554
+ }
555
+ buffer.mPool->add(&buffer, bufferSize);
556
+ return buffer;
557
+ }
558
+
559
+ inline void HostBuffer::clear()
560
+ {
561
+ if (mPool) {// remove self from the buffer register in the pool
562
+ mPool->remove(this);
563
+ }
564
+ mPool.reset();
565
+ mSize = 0;
566
+ mData = nullptr;
567
+ }
568
+
569
+ inline void HostBuffer::reset()
570
+ {
571
+ if (this->size()>0) {
572
+ throw std::runtime_error("HostBuffer: only empty buffers can call reset");
573
+ }
574
+ if (!mPool) {
575
+ throw std::runtime_error("HostBuffer: this buffer contains no pool to reset");
576
+ }
577
+ mPool->reset();
578
+ }
579
+
580
+ inline void HostBuffer::resizePool(uint64_t size, void *data)
581
+ {
582
+ if (!mPool) {
583
+ throw std::runtime_error("HostBuffer: this buffer contains no pool to resize");
584
+ }
585
+ mPool->resize(size, data);
586
+ }
587
+
588
+ } // namespace nanovdb
589
+
590
+ #endif // end of NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED