Compare commits
400
Commits
v8.2
...
feature/docs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7ec6329dc | ||
|
|
a28c227175 | ||
|
|
30e59dc432 | ||
|
|
3fff04fa64 | ||
|
|
a75b75617b | ||
|
|
9abae44383 | ||
|
|
7fffe564ef | ||
|
|
375c683456 | ||
|
|
960336887b | ||
|
|
519f0a7611 | ||
|
|
9bf2128fbf | ||
|
|
c0d83f5c05 | ||
|
|
712e52b73c | ||
|
|
9bebd58275 | ||
|
|
2d271ea533 | ||
|
|
2ea65109da | ||
|
|
dcb01a3980 | ||
|
|
dd2601c418 | ||
|
|
e6aedc8d4a | ||
|
|
b4d8722397 | ||
|
|
effbb49b17 | ||
|
|
88b0fa9219 | ||
|
|
35e1f42de1 | ||
|
|
f896bd6044 | ||
|
|
f29cd321bb | ||
|
|
338b6a94d0 | ||
|
|
0590d451a0 | ||
|
|
d1658b35c1 | ||
|
|
96f70bcca7 | ||
|
|
e5a740ae4b | ||
|
|
eca97bf881 | ||
|
|
516ec15407 | ||
|
|
21358f6bac | ||
|
|
9af9fe39ec | ||
|
|
d3ec8b4ef6 | ||
|
|
7a1c1764be | ||
|
|
066b246497 | ||
|
|
95ec31f958 | ||
|
|
beb3a5676a | ||
|
|
fe9a4f40cf | ||
|
|
60345f608b | ||
|
|
d8c87998b3 | ||
|
|
4af542d726 | ||
|
|
3a01af9300 | ||
|
|
c79a9748aa | ||
|
|
0407c65348 | ||
|
|
7175c6cd83 | ||
|
|
57cb9d668c | ||
|
|
48dcb9e819 | ||
|
|
618866ba10 | ||
|
|
5528666aec | ||
|
|
ec3e9076f3 | ||
|
|
30ec1ab10c | ||
|
|
059dca5cdd | ||
|
|
5a63a337e3 | ||
|
|
65d835b0ff | ||
|
|
cfca72f703 | ||
|
|
d0730e9d13 | ||
|
|
8a022b424b | ||
|
|
3739f79373 | ||
|
|
d7103cd3d8 | ||
|
|
189174c42a | ||
|
|
6a73481166 | ||
|
|
c4e3a24e2b | ||
|
|
75a4a87161 | ||
|
|
934a8ac27b | ||
|
|
4b3f1b8630 | ||
|
|
8512ed8883 | ||
|
|
4a2d6c8fa6 | ||
|
|
2292e87eb4 | ||
|
|
ce3da91b29 | ||
|
|
a4f650c447 | ||
|
|
fcc6b81423 | ||
|
|
56065ce8ff | ||
|
|
972d6599f2 | ||
|
|
b8be4faea4 | ||
|
|
980975a5b4 | ||
|
|
4e6899a3ec | ||
|
|
76454f1f20 | ||
|
|
c6b35215a4 | ||
|
|
4ff1d35c82 | ||
|
|
91118edcb1 | ||
|
|
6a93c99170 | ||
|
|
12220abb0c | ||
|
|
8b727c6ed5 | ||
|
|
69e70400b9 | ||
|
|
d13ae10f26 | ||
|
|
fff0c58a16 | ||
|
|
2d66be6188 | ||
|
|
a85b9b6b42 | ||
|
|
9537376d04 | ||
|
|
e27d0de155 | ||
|
|
8e51ce59e7 | ||
|
|
d4e59bcf33 | ||
|
|
2048b23535 | ||
|
|
e5af19e0e2 | ||
|
|
895efbfe0d | ||
|
|
7cc06f7170 | ||
|
|
0ae676abaa | ||
|
|
76afe6fb68 | ||
|
|
2d5c1a8bbe | ||
|
|
ad209a385f | ||
|
|
ce59ea6140 | ||
|
|
9cbcc9cb81 | ||
|
|
7e0fca6a5a | ||
|
|
db7f9101cc | ||
|
|
635756aba3 | ||
|
|
7052cdef48 | ||
|
|
67ffad6178 | ||
|
|
4888f00ff5 | ||
|
|
a4d6003df7 | ||
|
|
9271af7a08 | ||
|
|
02bd916a71 | ||
|
|
f019614876 | ||
|
|
09a411ff49 | ||
|
|
b8e985fe0f | ||
|
|
859c977309 | ||
|
|
94003c0b0e | ||
|
|
377780640e | ||
|
|
e64d292b3a | ||
|
|
8f6a9f48fa | ||
|
|
3cd5a766a5 | ||
|
|
7946c6dfd4 | ||
|
|
afcb340208 | ||
|
|
4d442df9b7 | ||
|
|
e225d5572c | ||
|
|
a9b4834eab | ||
|
|
8ff498b146 | ||
|
|
d910665b7e | ||
|
|
69153a31a5 | ||
|
|
bb657ef2f3 | ||
|
|
9687f82596 | ||
|
|
60d0f4d508 | ||
|
|
e22ee5fed9 | ||
|
|
b2ace91c03 | ||
|
|
d5a01c1e60 | ||
|
|
fb28c2227f | ||
|
|
f58d73e9ae | ||
|
|
2ff33ad9ee | ||
|
|
fa85b6cca7 | ||
|
|
5ee7c94e7f | ||
|
|
6b950cbe7b | ||
|
|
d33bda9bd1 | ||
|
|
d0c7321810 | ||
|
|
bd2389c4d4 | ||
|
|
312a478f2f | ||
|
|
a9eb193a06 | ||
|
|
f5df6052e5 | ||
|
|
8005f083f4 | ||
|
|
b9bc98606b | ||
|
|
86cbe16b5f | ||
|
|
873cdf6e9e | ||
|
|
1a08025ba8 | ||
|
|
0d5ac2f455 | ||
|
|
8bf573d1db | ||
|
|
7a0cf6ea0e | ||
|
|
ff1387bcbe | ||
|
|
b612ecda84 | ||
|
|
5d1cd6581a | ||
|
|
dce77a06d0 | ||
|
|
78d7a719fc | ||
|
|
520b9ed309 | ||
|
|
87cbc75eaa | ||
|
|
f970885766 | ||
|
|
68f32e1690 | ||
|
|
61a22e6399 | ||
|
|
4f666c3352 | ||
|
|
1ebf245a18 | ||
|
|
1ae4d940ea | ||
|
|
6966d7453d | ||
|
|
13b3e2ecdf | ||
|
|
5eefa363e7 | ||
|
|
d0b0556a6c | ||
|
|
6614e86095 | ||
|
|
9bb8b662a5 | ||
|
|
2cf576153f | ||
|
|
a3738368a2 | ||
|
|
738472de21 | ||
|
|
6849ddf786 | ||
|
|
baab47d670 | ||
|
|
dc06acfe09 | ||
|
|
3b15296a7c | ||
|
|
93aeac726e | ||
|
|
ee93e7f45b | ||
|
|
6f57f73c4e | ||
|
|
788e8757d8 | ||
|
|
9eae15c073 | ||
|
|
95b51bcff8 | ||
|
|
a71f65ca26 | ||
|
|
27bb6a76bc | ||
|
|
c5cd82c5ae | ||
|
|
54931251fb | ||
|
|
d7b23724b1 | ||
|
|
44d64179da | ||
|
|
3f85157279 | ||
|
|
40951fb8f3 | ||
|
|
c7e714420e | ||
|
|
4d3699cd93 | ||
|
|
2257c4a871 | ||
|
|
f5de408b4a | ||
|
|
f1233e09c2 | ||
|
|
9ab719f9ba | ||
|
|
7bb9dd8bd0 | ||
|
|
7a351c833c | ||
|
|
0b103c7932 | ||
|
|
c81aa6e3de | ||
|
|
2e48460193 | ||
|
|
6513580519 | ||
|
|
7dc9d0b509 | ||
|
|
77616b6844 | ||
|
|
4caad60fb0 | ||
|
|
97df82a1cc | ||
|
|
9565573e32 | ||
|
|
b58e5767a9 | ||
|
|
e82b156948 | ||
|
|
6791aedc37 | ||
|
|
184e9edb4c | ||
|
|
c269e1e62f | ||
|
|
3ccd810799 | ||
|
|
01cc769c31 | ||
|
|
43852835b9 | ||
|
|
414bed84c2 | ||
|
|
086aa1a723 | ||
|
|
9cd0e6bd8f | ||
|
|
24fc26e926 | ||
|
|
ac44ac26b0 | ||
|
|
3c5f69efea | ||
|
|
9b17a3cd75 | ||
|
|
0ed0f19ea4 | ||
|
|
4243bf5ccb | ||
|
|
e012cd48fd | ||
|
|
dfb4ed3f69 | ||
|
|
d2e58c4e00 | ||
|
|
f875f25e93 | ||
|
|
961b41ed99 | ||
|
|
96e5f6f172 | ||
|
|
355598dd30 | ||
|
|
c9ad78e0ef | ||
|
|
0fa79437f1 | ||
|
|
431dc10b49 | ||
|
|
94456ff5d5 | ||
|
|
381c8b4286 | ||
|
|
e82998d788 | ||
|
|
f642758144 | ||
|
|
b733122c78 | ||
|
|
4a81678276 | ||
|
|
7ab301c876 | ||
|
|
ec9ba3712e | ||
|
|
71e6205301 | ||
|
|
c50b0337c9 | ||
|
|
a89ea6d9c5 | ||
|
|
edf82f31ae | ||
|
|
a47b9c36b6 | ||
|
|
1716a69218 | ||
|
|
d10cce6a54 | ||
|
|
d2cc79772b | ||
|
|
4148292111 | ||
|
|
7be5c5f806 | ||
|
|
d9ad136a3f | ||
|
|
89771d5516 | ||
|
|
82fea032c9 | ||
|
|
0e8d2ca7ae | ||
|
|
e918c24938 | ||
|
|
88f37efaca | ||
|
|
e4b7880749 | ||
|
|
aea1a973af | ||
|
|
a4def54057 | ||
|
|
b9b699666b | ||
|
|
6a8530e277 | ||
|
|
103dedf7ca | ||
|
|
024af54484 | ||
|
|
fe42b9df78 | ||
|
|
d2cad6a59e | ||
|
|
71175f3f45 | ||
|
|
5be286d609 | ||
|
|
01b0557370 | ||
|
|
16497e2b99 | ||
|
|
413654cb5d | ||
|
|
67c393ab56 | ||
|
|
35bff52507 | ||
|
|
de4f1b51e0 | ||
|
|
f9a0a52cfb | ||
|
|
2df9db6021 | ||
|
|
6571ca00e8 | ||
|
|
413e738eb5 | ||
|
|
2d7aefa2eb | ||
|
|
f1b08001c9 | ||
|
|
5d6c306b7f | ||
|
|
11fb0a3a53 | ||
|
|
8408cb701a | ||
|
|
8cbd1002c0 | ||
|
|
61482ea129 | ||
|
|
5a72304f90 | ||
|
|
8a5f85cb56 | ||
|
|
52048612df | ||
|
|
54dc561d35 | ||
|
|
dbbff4a42d | ||
|
|
ebd71bef19 | ||
|
|
213f6b68fd | ||
|
|
6cfa1157db | ||
|
|
7fc1ac796c | ||
|
|
160fd92893 | ||
|
|
1501a6fc3d | ||
|
|
6b89ad915f | ||
|
|
d9ed0db2f3 | ||
|
|
9816253c27 | ||
|
|
6f5de6ffef | ||
|
|
c5edf69041 | ||
|
|
089a3ba351 | ||
|
|
fc6cc1b340 | ||
|
|
cd5e31d42f | ||
|
|
6979173be8 | ||
|
|
8d6283e6b5 | ||
|
|
f8ede9b459 | ||
|
|
dc9e31722b | ||
|
|
b46898ed1d | ||
|
|
8f32c626d6 | ||
|
|
fb95b36634 | ||
|
|
a708428e1a | ||
|
|
7d740e4894 | ||
|
|
2dac7b62de | ||
|
|
d94c17d3eb | ||
|
|
551c60fdd9 | ||
|
|
80c14c5fcf | ||
|
|
5f93d04abc | ||
|
|
bc68d45cfc | ||
|
|
be37ad36e9 | ||
|
|
b208c1aaa0 | ||
|
|
7fb95cbd58 | ||
|
|
91915f84a6 | ||
|
|
e41eed9110 | ||
|
|
80431d4a42 | ||
|
|
360e52f429 | ||
|
|
6df4fb2f79 | ||
|
|
9032113ace | ||
|
|
4a9031418e | ||
|
|
1b44ac71e8 | ||
|
|
d804e32eb6 | ||
|
|
f6b2ee1d27 | ||
|
|
3f01e47e06 | ||
|
|
bb65901510 | ||
|
|
4a645fb35c | ||
|
|
6628553f40 | ||
|
|
e33b3aad0c | ||
|
|
f4573f3031 | ||
|
|
86eaa67b1b | ||
|
|
829d517a2f | ||
|
|
9568d860db | ||
|
|
d261f9cd05 | ||
|
|
3e11bca775 | ||
|
|
a9c925bb20 | ||
|
|
9b8ab1ed3b | ||
|
|
3ab9d8049a | ||
|
|
197f42ec44 | ||
|
|
58e09b4ddd | ||
|
|
329dbcf6b5 | ||
|
|
ddcce5a9c2 | ||
|
|
98cd38921f | ||
|
|
f1f4f475fa | ||
|
|
b4c6ac8712 | ||
|
|
beb8c2c173 | ||
|
|
0b7464087c | ||
|
|
067975c455 | ||
|
|
44a81554f1 | ||
|
|
ac97c17ed8 | ||
|
|
44a4dea1d8 | ||
|
|
43473e7ed0 | ||
|
|
48959eb672 | ||
|
|
48694cd9ef | ||
|
|
605e5e4a9d | ||
|
|
61dc4de0c6 | ||
|
|
5aea27a578 | ||
|
|
2880f3d3c7 | ||
|
|
e3191e7ff1 | ||
|
|
35394a3744 | ||
|
|
f5f0b5b3de | ||
|
|
e4fb245cf0 | ||
|
|
4c597b4de9 | ||
|
|
51f2cc03dc | ||
|
|
fb7a45b9f7 | ||
|
|
e7c6ad9bc8 | ||
|
|
ac3b2d030d | ||
|
|
fe1781b46a | ||
|
|
08fb13b6e9 | ||
|
|
3edc233091 | ||
|
|
2054ad567f | ||
|
|
179c78bfee | ||
|
|
2fa84284f9 | ||
|
|
11fe784eeb | ||
|
|
ff3a765946 | ||
|
|
d19a1dd473 | ||
|
|
87609f8eef | ||
|
|
663e16493a | ||
|
|
7f5633c044 | ||
|
|
2ba0ca4b4e | ||
|
|
773bd7aa3a | ||
|
|
038156c9fb | ||
|
|
35e7fc1926 | ||
|
|
8928a39fe0 | ||
|
|
eeddd9b0b3 |
@@ -1,206 +0,0 @@
|
||||
|
||||
name: AX
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'feature/**'
|
||||
- 'pr/**'
|
||||
paths-ignore:
|
||||
- 'CHANGES'
|
||||
- 'doc/**'
|
||||
- 'openvdb_maya/**'
|
||||
- 'openvdb_houdini/**'
|
||||
- 'pendingchanges/**'
|
||||
- '**.md'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- 'CHANGES'
|
||||
- 'doc/**'
|
||||
- 'openvdb_maya/**'
|
||||
- 'openvdb_houdini/**'
|
||||
- 'pendingchanges/**'
|
||||
- '**.md'
|
||||
schedule:
|
||||
# run this workflow every midnight Tuesday
|
||||
- cron: '0 0 * * 2'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
type:
|
||||
description: 'The type of CI to run (all, mac, linux, grammar)'
|
||||
required: true
|
||||
default: 'all'
|
||||
|
||||
jobs:
|
||||
linux-ax-vfx:
|
||||
# VFX platform builds for OpenVDB AX
|
||||
if: |
|
||||
github.event_name != 'workflow_dispatch' ||
|
||||
github.event.inputs.type == 'all' ||
|
||||
github.event.inputs.type == 'linux'
|
||||
runs-on: ubuntu-latest
|
||||
name: >
|
||||
linux-ax-vfx:${{ matrix.image }}-
|
||||
cxx:${{ matrix.compiler }}-
|
||||
${{ matrix.build }}
|
||||
container:
|
||||
image: aswf/ci-openvdb:${{ matrix.image }}
|
||||
env:
|
||||
CXX: ${{ matrix.compiler }}
|
||||
strategy:
|
||||
matrix:
|
||||
image: ['2019-clang8', '2020-clang7', '2021-clang10']
|
||||
compiler: ['clang++']
|
||||
build: ['Release']
|
||||
j: [2]
|
||||
# Extra builds
|
||||
include:
|
||||
- image: '2020-clang7'
|
||||
compiler: 'clang++'
|
||||
build: 'Debug'
|
||||
j: 2
|
||||
- image: '2020-clang7'
|
||||
compiler: 'g++'
|
||||
build: 'Release'
|
||||
# disable parallel builds when using GCC due to memory limits
|
||||
j: 1
|
||||
- image: '2019-clang8'
|
||||
compiler: 'g++'
|
||||
build: 'Release'
|
||||
# disable parallel builds when using GCC due to memory limits
|
||||
j: 1
|
||||
- image: '2021-clang10'
|
||||
compiler: 'g++'
|
||||
build: 'Release'
|
||||
# disable parallel builds when using GCC due to memory limits
|
||||
j: 1
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: build
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
-j ${{ matrix.j }}
|
||||
--build-type=${{ matrix.build }}
|
||||
--components="core,axcore,axbin,axtest"
|
||||
--cargs="-DOPENVDB_CXX_STRICT=ON"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
- name: test_doxygen_examples
|
||||
run: ./ci/extract_test_examples.sh
|
||||
|
||||
linux-ax-standalone-vfx:
|
||||
# VFX platform builds for OpenVDB AX against an existing VDB installation
|
||||
if: |
|
||||
github.event_name != 'workflow_dispatch' ||
|
||||
github.event.inputs.type == 'all' ||
|
||||
github.event.inputs.type == 'linux'
|
||||
runs-on: ubuntu-latest
|
||||
name: >
|
||||
linux-ax-standalone-vfx:${{ matrix.image }}-
|
||||
cxx:${{ matrix.compiler }}-
|
||||
llvm:${{ matrix.llvm }}-
|
||||
${{ matrix.build }}
|
||||
container:
|
||||
image: aswf/ci-openvdb:${{ matrix.image }}
|
||||
env:
|
||||
CXX: ${{ matrix.compiler }}
|
||||
strategy:
|
||||
matrix:
|
||||
image: ['2019-clang6', '2019-clang7', '2019-clang8', '2019-clang9', '2020-clang7', '2021-clang10']
|
||||
compiler: ['clang++']
|
||||
build: ['Release']
|
||||
j: [2]
|
||||
# Extra builds
|
||||
include:
|
||||
- image: '2020-clang7'
|
||||
compiler: 'g++'
|
||||
build: 'Release'
|
||||
# disable parallel builds when using GCC due to memory limits
|
||||
j: 1
|
||||
- image: '2020-clang7'
|
||||
compiler: 'clang++'
|
||||
build: 'Debug'
|
||||
j: 2
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: vdb
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
-j ${{ matrix.j }}
|
||||
--build-type=${{ matrix.build }}
|
||||
--components="core"
|
||||
--cargs="-DOPENVDB_CXX_STRICT=ON"
|
||||
- name: clean
|
||||
run: rm -rf build
|
||||
- name: build
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
-j ${{ matrix.j }}
|
||||
--build-type=${{ matrix.build }}
|
||||
--components="axcore,axbin,axtest"
|
||||
--cargs="-DOPENVDB_CXX_STRICT=ON"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
- name: test_doxygen_examples
|
||||
run: ./ci/extract_test_examples.sh
|
||||
|
||||
macos-core:
|
||||
if: |
|
||||
github.event_name != 'workflow_dispatch' ||
|
||||
github.event.inputs.type == 'all' ||
|
||||
github.event.inputs.type == 'mac'
|
||||
runs-on: macos-10.15
|
||||
name: macos-cxx:${{ matrix.compiler }}-llvm:${{ matrix.llvm }}-${{ matrix.build }}
|
||||
env:
|
||||
CXX: ${{ matrix.compiler }}
|
||||
strategy:
|
||||
matrix:
|
||||
compiler: ['clang++']
|
||||
build: ['Release']
|
||||
llvm: ['7','8','9','11','12'] #@note llvm10 never got its own brew formula...
|
||||
# Extra builds
|
||||
include:
|
||||
- compiler: 'g++'
|
||||
build: 'Release'
|
||||
llvm: '8'
|
||||
- compiler: 'clang++'
|
||||
build: 'Debug'
|
||||
llvm: '8'
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install_deps
|
||||
run: ./ci/install_macos_ax.sh ${{ matrix.llvm }}
|
||||
- name: build
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--build-type=${{ matrix.build }}
|
||||
--components="core,axcore,axbin,axtest"
|
||||
--cargs="-DLLVM_DIR=/usr/local/opt/llvm@${{ matrix.llvm }}/lib/cmake/llvm"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
- name: test_doxygen_examples
|
||||
run: ./ci/extract_test_examples.sh
|
||||
|
||||
gen-grammar:
|
||||
if: |
|
||||
github.event_name == 'workflow_dispatch' &&
|
||||
github.event.inputs.type == 'grammar'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: aswf/ci-openvdb:2021-clang10
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: build
|
||||
run: ./ci/build.sh -v --components=axgr --target=openvdb_ax_grammar --cargs=\"-DOPENVDB_AX_GRAMMAR_NO_LINES=ON\"
|
||||
- name: upload grammar
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ax_grammar
|
||||
path: ./build/openvdb_ax/openvdb_ax/openvdb_ax/grammar
|
||||
retention-days: 5
|
||||
@@ -1,276 +0,0 @@
|
||||
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'feature/**'
|
||||
- 'pr/**'
|
||||
paths-ignore:
|
||||
- 'CHANGES'
|
||||
- 'doc/**'
|
||||
- 'openvdb_maya/**'
|
||||
- 'openvdb_houdini/**'
|
||||
- 'openvdb_ax/**'
|
||||
- 'pendingchanges/**'
|
||||
- '**.md'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- 'CHANGES'
|
||||
- 'doc/**'
|
||||
- 'openvdb_maya/**'
|
||||
- 'openvdb_houdini/**'
|
||||
- 'openvdb_ax/**'
|
||||
- 'pendingchanges/**'
|
||||
- '**.md'
|
||||
schedule:
|
||||
# run this workflow every day at 7am UTC
|
||||
- cron: '0 7 * * *'
|
||||
# run this workflow every Monday 00:00 UTC
|
||||
# warning: This pattern is checked in various places below
|
||||
- cron: '0 0 * * 1'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
type:
|
||||
description: 'The type of CI to run (all, linux, win, mac)'
|
||||
required: true
|
||||
default: 'all'
|
||||
|
||||
jobs:
|
||||
linux-vfx:
|
||||
# VFX platform jobs. These are run on the appropriate CentOS images from
|
||||
# the provided ASWF docker containers
|
||||
if: |
|
||||
github.event_name != 'workflow_dispatch' ||
|
||||
github.event.inputs.type == 'all' ||
|
||||
github.event.inputs.type == 'linux'
|
||||
runs-on: ubuntu-latest
|
||||
name: >
|
||||
linux-vfx:${{ matrix.config.image }}-
|
||||
abi:${{ matrix.config.abi }}-
|
||||
cxx:${{ matrix.config.cxx }}-
|
||||
type:${{ matrix.config.build }}
|
||||
container:
|
||||
image: aswf/ci-openvdb:${{ matrix.config.image }}
|
||||
env:
|
||||
CXX: ${{ matrix.config.cxx }}
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- { cxx: clang++, image: '2019', abi: '6', build: 'Release' }
|
||||
- { cxx: clang++, image: '2020', abi: '7', build: 'Release' }
|
||||
- { cxx: clang++, image: '2021', abi: '8', build: 'Release' }
|
||||
- { cxx: clang++, image: '2021', abi: '9', build: 'Release' }
|
||||
- { cxx: clang++, image: '2021', abi: '8', build: 'Debug' }
|
||||
- { cxx: clang++, image: '2022-clang11', abi: '9', build: 'Release' }
|
||||
- { cxx: g++, image: '2020', abi: '7', build: 'Release' }
|
||||
- { cxx: g++, image: '2021', abi: '8', build: 'Release' }
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install_gtest
|
||||
run: ./ci/install_gtest.sh 1.8.0
|
||||
- name: build
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--build-type=${{ matrix.config.build }}
|
||||
--components=\"core,python,bin,test\"
|
||||
--cargs=\"-DOPENVDB_CXX_STRICT=ON -DOPENVDB_ABI_VERSION_NUMBER=${{ matrix.config.abi }}\"
|
||||
- name: test
|
||||
# Always run tests on weekly builds but skip Debug on commits as they take a while.
|
||||
# https://github.community/t/distinct-job-for-each-schedule/17811/2
|
||||
if: contains(github.event.schedule, '0 0 * * 1') || matrix.config.build == 'Release'
|
||||
run: |
|
||||
cd build && ctest -V
|
||||
cd - && ./ci/test_install.sh
|
||||
|
||||
windows:
|
||||
# Windows CI. Tests static and dynamic builds with MT and MD respectively.
|
||||
if: |
|
||||
github.event_name != 'workflow_dispatch' ||
|
||||
github.event.inputs.type == 'all' ||
|
||||
github.event.inputs.type == 'win'
|
||||
runs-on: windows-2019
|
||||
name: windows-vc:${{ matrix.config.vc }}-type:${{ matrix.config.build }}
|
||||
env:
|
||||
VCPKG_DEFAULT_TRIPLET: ${{ matrix.config.vc }}
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
# static build of blosc from vcpkg does not build internal sources.
|
||||
# USE_STATIC_DEPENDENCIES is required for IlmBase/OpenEXR defines and
|
||||
# Boost as both shared and static libs are installed.
|
||||
- { vc: 'x64-windows-static', build: 'Release', cmake: '-A x64 -G \"Visual Studio 16 2019\" -DOPENVDB_CORE_SHARED=OFF -DUSE_STATIC_DEPENDENCIES=ON -DBLOSC_USE_EXTERNAL_SOURCES=ON' }
|
||||
- { vc: 'x64-windows-static', build: 'Debug', cmake: '-A x64 -G \"Visual Studio 16 2019\" -DOPENVDB_CORE_SHARED=OFF -DUSE_STATIC_DEPENDENCIES=ON -DBLOSC_USE_EXTERNAL_SOURCES=ON' }
|
||||
- { vc: 'x64-windows', build: 'Release', cmake: '-A x64 -G \"Visual Studio 16 2019\" -DOPENVDB_CORE_STATIC=OFF' }
|
||||
- { vc: 'x64-windows', build: 'Debug', cmake: '-A x64 -G \"Visual Studio 16 2019\" -DOPENVDB_CORE_STATIC=OFF' }
|
||||
#- { vc: 'x64-windows', build: 'Release', cmake: '-G \"MinGW Makefiles\" -DOPENVDB_CORE_STATIC=OFF' }
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: path
|
||||
run: |
|
||||
# note: system path must be modified in a previous step to it's use
|
||||
echo "$Env:VCPKG_INSTALLATION_ROOT\installed\${{ matrix.config.vc }}\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
echo "${{github.workspace}}\build\openvdb\openvdb\${{ matrix.config.build }}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
- name: install
|
||||
shell: bash
|
||||
run: ./ci/install_windows.sh
|
||||
- name: build
|
||||
shell: bash
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--config=${{ matrix.config.build }}
|
||||
--components=\"core,bin,test\"
|
||||
--cargs=\'${{ matrix.config.cmake }} -DVCPKG_TARGET_TRIPLET=${VCPKG_DEFAULT_TRIPLET} -DCMAKE_TOOLCHAIN_FILE=\"${VCPKG_INSTALLATION_ROOT}\\scripts\\buildsystems\\vcpkg.cmake\"\'
|
||||
- name: test
|
||||
shell: bash
|
||||
# Always run tests on weekly builds but skip Debug on commits as they take a while.
|
||||
# https://github.community/t/distinct-job-for-each-schedule/17811/2
|
||||
if: contains(github.event.schedule, '0 0 * * 1') || matrix.config.build == 'Release'
|
||||
run: cd build && ctest -V
|
||||
|
||||
linux-extra:
|
||||
# Extra configuration tests, all run on the ASWF docker images. These run weekly
|
||||
# rather than on PR/merge
|
||||
if: |
|
||||
contains(github.event.schedule, '0 0 * * 1') ||
|
||||
(github.event_name == 'workflow_dispatch' &&
|
||||
(github.event.inputs.type == 'all' ||
|
||||
github.event.inputs.type == 'linux'))
|
||||
runs-on: ubuntu-latest
|
||||
name: linux-extra:${{ matrix.config.name }}
|
||||
container:
|
||||
image: aswf/ci-openvdb:2021
|
||||
env:
|
||||
CXX: clang++
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- { name: 'abi8lite', cmake: '-DUSE_BLOSC=OFF -DUSE_ZLIB=OFF' }
|
||||
- { name: 'abi8half', cmake: '-DUSE_BLOSC=OFF -DUSE_IMATH_HALF=ON' }
|
||||
- { name: 'abi8sse', cmake: '-DOPENVDB_SIMD=SSE42' }
|
||||
- { name: 'abi8avx', cmake: '-DOPENVDB_SIMD=AVX' }
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install_gtest
|
||||
run: ./ci/install_gtest.sh 1.10.0
|
||||
- name: build
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--build-type=Release
|
||||
--components=\"core,python,bin,test\"
|
||||
--cargs=\"-DOPENVDB_CXX_STRICT=ON -DOPENVDB_ABI_VERSION_NUMBER=8 ${{ matrix.config.cmake }}\"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
|
||||
testabi8gcc10:
|
||||
if: |
|
||||
github.event_name != 'workflow_dispatch' ||
|
||||
github.event.inputs.type == 'all' ||
|
||||
github.event.inputs.type == 'linux'
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
CXX: g++-10
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install_boost
|
||||
run: sudo apt-get -q install -y libboost-dev libboost-system-dev libboost-iostreams-dev
|
||||
- name: install_tbb
|
||||
run: sudo apt-get -q install -y libtbb-dev
|
||||
- name: install_gtest
|
||||
run: sudo apt-get -q install -y libgtest-dev
|
||||
- name: build
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--build-type=Release
|
||||
--components=\"core,test\"
|
||||
--cargs=\"-DUSE_BLOSC=OFF -DUSE_ZLIB=OFF -DOPENVDB_ABI_VERSION_NUMBER=8 -DCMAKE_INSTALL_PREFIX=`pwd`\"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
|
||||
testabi8clang10:
|
||||
if: |
|
||||
github.event_name != 'workflow_dispatch' ||
|
||||
github.event.inputs.type == 'all' ||
|
||||
github.event.inputs.type == 'linux'
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
CXX: clang++-10
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install_boost
|
||||
run: sudo apt-get -q install -y libboost-dev libboost-system-dev libboost-iostreams-dev
|
||||
- name: install_tbb
|
||||
run: sudo apt-get -q install -y libtbb-dev
|
||||
- name: install_gtest
|
||||
run: sudo apt-get -q install -y libgtest-dev
|
||||
- name: build
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--build-type=Release
|
||||
--components=\"core,test\"
|
||||
--cargs=\"-DUSE_BLOSC=OFF -DUSE_ZLIB=OFF -DOPENVDB_ABI_VERSION_NUMBER=8 -DCMAKE_INSTALL_PREFIX=`pwd`\"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
|
||||
testmacos1015:
|
||||
if: |
|
||||
github.event_name != 'workflow_dispatch' ||
|
||||
github.event.inputs.type == 'all' ||
|
||||
github.event.inputs.type == 'mac'
|
||||
runs-on: macos-10.15
|
||||
env:
|
||||
CXX: clang++
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install
|
||||
shell: bash
|
||||
# brew boost-python3 installs a "Keg-only" version of python which is
|
||||
# not installed to PATH. We must manually provide the location of the
|
||||
# required python installation to CMake through a hint variable which
|
||||
# is exported in install_macos.sh
|
||||
run: ./ci/install_macos.sh
|
||||
- name: install
|
||||
shell: bash
|
||||
run: ./ci/install_blosc.sh 1.5.0
|
||||
- name: build
|
||||
shell: bash
|
||||
# Also need to disable compiler warnings for ABI 6 and above due to
|
||||
# the version of clang installed
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--build-type=Release
|
||||
--components=\"core,python,bin,test\"
|
||||
--cargs=\"-DOPENVDB_CXX_STRICT=OFF -DOPENVDB_ABI_VERSION_NUMBER=8 -DOPENVDB_SIMD=SSE42\"
|
||||
- name: test
|
||||
shell: bash
|
||||
run: cd build && ctest -V
|
||||
|
||||
# Test EXR 3 and TBB 2021 on MacOS
|
||||
testmacos1015_latest:
|
||||
runs-on: macos-10.15
|
||||
env:
|
||||
CXX: clang++
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install
|
||||
shell: bash
|
||||
run: |
|
||||
brew update
|
||||
brew install bash gnu-getopt cmake imath openexr boost tbb glfw googletest
|
||||
echo "/usr/local/opt/gnu-getopt/bin" >> $GITHUB_PATH
|
||||
- name: build
|
||||
shell: bash
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--build-type=Release
|
||||
--components=\"core,bin,test\"
|
||||
--cargs=\"-DOPENVDB_CXX_STRICT=OFF -DUSE_BLOSC=OFF -DUSE_ZLIB=OFF\"
|
||||
- name: test
|
||||
shell: bash
|
||||
run: cd build && ctest -V
|
||||
@@ -42,22 +42,44 @@ jobs:
|
||||
run: pip install epydoc
|
||||
- name: install_latex
|
||||
run: yum -y install texlive-latex-bin texlive-dvips texlive-collection-fontsrecommended texlive-collection-latexrecommended
|
||||
- name: install_cmake
|
||||
run: ./ci/install_cmake.sh 3.15.0
|
||||
- name: build
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--build-type=Release
|
||||
--components="core,python,doc"
|
||||
--cargs=\"-DUSE_BLOSC=OFF -DOPENVDB_CORE_STATIC=OFF -DOPENVDB_PYTHON_WRAP_ALL_GRID_TYPES=ON -DDISABLE_DEPENDENCY_VERSION_CHECKS=ON\"
|
||||
--cargs=\"
|
||||
-DUSE_BLOSC=OFF
|
||||
-DOPENVDB_CORE_STATIC=OFF
|
||||
-DOPENVDB_PYTHON_WRAP_ALL_GRID_TYPES=ON
|
||||
-DUSE_EXPLICIT_INSTANTIATION=OFF
|
||||
-DDISABLE_DEPENDENCY_VERSION_CHECKS=ON
|
||||
\"
|
||||
- name: epydoc
|
||||
run: |
|
||||
epydoc --html -o /usr/local/share/doc/OpenVDB/html/python pyopenvdb
|
||||
- name: pre_deploy
|
||||
# Overwrite global SSH configuration
|
||||
run: >
|
||||
echo "Host *
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile=/dev/null
|
||||
" > /etc/ssh/ssh_config
|
||||
- name: deploy
|
||||
# only deploy documentation to gh-pages on a manual workflow dispatch
|
||||
# only deploy documentation on a manual workflow dispatch
|
||||
if: |
|
||||
github.repository_owner == 'AcademySoftwareFoundation' &&
|
||||
github.event_name == 'workflow_dispatch' &&
|
||||
github.event.inputs.deploy == 'true'
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
|
||||
publish_dir: /usr/local/share/doc/OpenVDB/html
|
||||
destination_dir: documentation/doxygen
|
||||
external_repository: AcademySoftwareFoundation/openvdb-website
|
||||
publish_branch: doxygen
|
||||
full_commit_message: "Automatic doxygen documentation update
|
||||
- Deployed from: AcademySoftwareFoundation/openvdb ${{ github.sha }}
|
||||
|
||||
Signed-off-by: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>"
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
|
||||
name: Houdini
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'feature/**'
|
||||
- 'pr/**'
|
||||
paths-ignore:
|
||||
- 'CHANGES'
|
||||
- 'doc/**'
|
||||
- 'openvdb_maya/**'
|
||||
- 'pendingchanges/**'
|
||||
- '**.md'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- 'CHANGES'
|
||||
- 'doc/**'
|
||||
- 'openvdb_maya/**'
|
||||
- 'pendingchanges/**'
|
||||
- '**.md'
|
||||
schedule:
|
||||
# run this workflow every day at 7am UTC
|
||||
- cron: '0 7 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
checksecret:
|
||||
# Check that valid github secrets have been set. This isn't needed to retrieve
|
||||
# the cache, but ensures that the job doens't start with an empty cache
|
||||
name: Verify Houdini Secrets
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
HOUDINI_SECRETS: ${{ steps.check.outputs.HOUDINI_SECRETS }}
|
||||
steps:
|
||||
- id: check
|
||||
env:
|
||||
HOUDINI_CLIENT_ID: ${{ secrets.HOUDINI_CLIENT_ID }}
|
||||
HOUDINI_SECRET_KEY: ${{ secrets.HOUDINI_SECRET_KEY }}
|
||||
run: echo "::set-output name=HOUDINI_SECRETS::${{ env.HOUDINI_CLIENT_ID != '' && env.HOUDINI_SECRET_KEY != '' }}"
|
||||
- name: Skip Next Jobs
|
||||
if: steps.check.outputs.HOUDINI_SECRETS != 'true'
|
||||
run: echo "HOUDINI_CLIENT_ID and HOUDINI_SECRET_KEY GitHub Action Secrets needs to be set to install Houdini builds"
|
||||
|
||||
linux-vfx-houdini:
|
||||
needs: [checksecret]
|
||||
if: >
|
||||
${{ needs.checksecret.outputs.HOUDINI_SECRETS == 'true' ||
|
||||
github.repository_owner == 'AcademySoftwareFoundation' }}
|
||||
runs-on: ubuntu-latest
|
||||
name: hou:${{ matrix.config.hou }}-vfx:${{ matrix.config.image }}-cxx:${{ matrix.config.cxx }}
|
||||
container:
|
||||
image: aswf/ci-base:${{ matrix.config.image }}
|
||||
env:
|
||||
CXX: ${{ matrix.config.cxx }}
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
# build against VFX Ref 2018 even though it's unsupported, just to make sure that we test Boost 1.61
|
||||
- { cxx: clang++, image: '2018', hou: '18_0', j: '2', build: 'Release', components: 'core,hou,bin,python,test,axcore,axbin,axtest', disable_checks: 'ON' }
|
||||
- { cxx: clang++, image: '2019', hou: '18_0', j: '2', build: 'Release', components: 'core,hou,bin,python,test,axcore,axbin,axtest', disable_checks: 'OFF' }
|
||||
- { cxx: clang++, image: '2020', hou: '18_5', j: '2', build: 'Release', components: 'core,hou,bin,python,test,axcore,axbin,axtest', disable_checks: 'OFF' }
|
||||
- { cxx: clang++, image: '2020', hou: '18_5', j: '2', build: 'Debug', components: 'core,hou', disable_checks: 'OFF' }
|
||||
- { cxx: g++, image: '2020', hou: '18_5', j: '1', build: 'Release', components: 'core,hou', disable_checks: 'OFF' }
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: fetch_houdini
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hou
|
||||
key: vdb-v3-houdini${{ matrix.config.hou }}-${{ hashFiles('hou/hou.tar.gz') }}
|
||||
restore-keys: vdb-v3-houdini${{ matrix.config.hou }}-
|
||||
- name: validate_houdini
|
||||
run: test -f "hou/hou.tar.gz"
|
||||
# Make sure the cache is copied, not moved, as the cache action always posts the cache.
|
||||
# Also make sure that the unpacked install is NOT in the root of the OpenVDB checkout
|
||||
# otherwise CMake's install RPATHs wil not work correctly.
|
||||
- name: install_houdini
|
||||
run: |
|
||||
mkdir $HOME/houdini_install
|
||||
cp hou/hou.tar.gz $HOME/houdini_install/hou.tar.gz
|
||||
cd $HOME/houdini_install && tar -xzf hou.tar.gz && cd -
|
||||
- name: install_cmake
|
||||
run: ./ci/install_cmake.sh 3.12.0
|
||||
- name: install_gtest
|
||||
run: ./ci/install_gtest.sh 1.10.0
|
||||
- name: build
|
||||
shell: bash
|
||||
run: >
|
||||
cd $HOME/houdini_install/hou && source houdini_setup_bash && cd - &&
|
||||
./ci/build.sh -v
|
||||
-j ${{ matrix.config.j }}
|
||||
--build-type=${{ matrix.config.build }}
|
||||
--components="${{ matrix.config.components }}"
|
||||
--cargs=\"-DDISABLE_CMAKE_SEARCH_PATHS=ON -DOPENVDB_BUILD_HOUDINI_ABITESTS=ON -DOPENVDB_HOUDINI_INSTALL_PREFIX=/tmp -DDISABLE_DEPENDENCY_VERSION_CHECKS=${{ matrix.config.disable_checks }}\"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
# Final check to make sure the cache still exists
|
||||
- name: validate_houdini
|
||||
run: test -f "hou/hou.tar.gz"
|
||||
@@ -1,108 +0,0 @@
|
||||
|
||||
name: Houdini Cache
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# run this workflow every sunday at noon UTC
|
||||
- cron: '0 12 * * 0'
|
||||
workflow_dispatch:
|
||||
|
||||
# download the latest production version of Houdini, strip out headers,
|
||||
# libraries and binaries required for building OpenVDB and if the build
|
||||
# succeeds, put it into the GitHub Actions cache
|
||||
|
||||
jobs:
|
||||
checksecret:
|
||||
# Check that valid github secrets have been set for the ability to
|
||||
# download Houdini and cache it. The secrets are used in download_houdini.py
|
||||
name: Verify Houdini Secrets
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
HOUDINI_SECRETS: ${{ steps.check.outputs.HOUDINI_SECRETS }}
|
||||
steps:
|
||||
- id: check
|
||||
env:
|
||||
HOUDINI_CLIENT_ID: ${{ secrets.HOUDINI_CLIENT_ID }}
|
||||
HOUDINI_SECRET_KEY: ${{ secrets.HOUDINI_SECRET_KEY }}
|
||||
run: echo "::set-output name=HOUDINI_SECRETS::${{ env.HOUDINI_CLIENT_ID != '' && env.HOUDINI_SECRET_KEY != '' }}"
|
||||
- name: Skip Next Jobs
|
||||
if: steps.check.outputs.HOUDINI_SECRETS != 'true'
|
||||
run: echo "HOUDINI_CLIENT_ID and HOUDINI_SECRET_KEY GitHub Action Secrets needs to be set to install Houdini builds"
|
||||
|
||||
linux_houdini18_5:
|
||||
needs: [checksecret]
|
||||
if: >
|
||||
${{ needs.checksecret.outputs.HOUDINI_SECRETS == 'true' ||
|
||||
github.repository_owner == 'AcademySoftwareFoundation' }}
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CXX: clang++
|
||||
HOUDINI_CLIENT_ID: ${{ secrets.HOUDINI_CLIENT_ID }}
|
||||
HOUDINI_SECRET_KEY: ${{ secrets.HOUDINI_SECRET_KEY }}
|
||||
container:
|
||||
image: aswf/ci-base:2020
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: download_houdini
|
||||
run: ./ci/download_houdini.sh 18.5 ON
|
||||
- name: install_houdini
|
||||
run: |
|
||||
mkdir $HOME/houdini_install
|
||||
cp hou/hou.tar.gz $HOME/houdini_install/hou.tar.gz
|
||||
cd $HOME/houdini_install && tar -xzf hou.tar.gz && cd -
|
||||
- name: install_gtest
|
||||
run: ./ci/install_gtest.sh 1.10.0
|
||||
- name: build
|
||||
shell: bash
|
||||
run: >
|
||||
cd $HOME/houdini_install/hou && source houdini_setup_bash && cd - &&
|
||||
./ci/build.sh -v
|
||||
--build-type=Release
|
||||
--components="core,hou,bin,python,test,axcore,axbin,axtest"
|
||||
--cargs=\"-DDISABLE_CMAKE_SEARCH_PATHS=ON -DOPENVDB_BUILD_HOUDINI_ABITESTS=ON -DOPENVDB_HOUDINI_INSTALL_PREFIX=/tmp\"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
- name: write_houdini_cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hou
|
||||
key: vdb-v3-houdini18_5-${{ hashFiles('hou/hou.tar.gz') }}
|
||||
|
||||
linux_houdini18_0:
|
||||
needs: [checksecret]
|
||||
if: >
|
||||
${{ needs.checksecret.outputs.HOUDINI_SECRETS == 'true' ||
|
||||
github.repository_owner == 'AcademySoftwareFoundation' }}
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CXX: clang++
|
||||
HOUDINI_CLIENT_ID: ${{ secrets.HOUDINI_CLIENT_ID }}
|
||||
HOUDINI_SECRET_KEY: ${{ secrets.HOUDINI_SECRET_KEY }}
|
||||
container:
|
||||
image: aswf/ci-base:2019
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: download_houdini
|
||||
run: ./ci/download_houdini.sh 18.0 ON
|
||||
- name: install_houdini
|
||||
run: |
|
||||
mkdir $HOME/houdini_install
|
||||
cp hou/hou.tar.gz $HOME/houdini_install/hou.tar.gz
|
||||
cd $HOME/houdini_install && tar -xzf hou.tar.gz && cd -
|
||||
- name: install_gtest
|
||||
run: ./ci/install_gtest.sh 1.10.0
|
||||
- name: build
|
||||
shell: bash
|
||||
run: >
|
||||
cd $HOME/houdini_install/hou && source houdini_setup_bash && cd - &&
|
||||
./ci/build.sh -v
|
||||
--build-type=Release
|
||||
--components="core,hou,bin,python,test,axcore,axbin,axtest"
|
||||
--cargs=\"-DDISABLE_CMAKE_SEARCH_PATHS=ON -DOPENVDB_BUILD_HOUDINI_ABITESTS=ON -DOPENVDB_HOUDINI_INSTALL_PREFIX=/tmp\"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
- name: write_houdini_cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hou
|
||||
key: vdb-v3-houdini18_0-${{ hashFiles('hou/hou.tar.gz') }}
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
# This workflow is for running various sanitizers on OpenVDB. We currently
|
||||
# only use clang over gcc (for no particular reason). Note that some of the
|
||||
# errors produces by these sanitizers may be fairly obscure as the
|
||||
# llvm-symbolizer is not installed on the openvdb image. The address
|
||||
# sanitizer should never fail.
|
||||
|
||||
name: Sanitizers
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# run this workflow every Monday 00:00 UTC
|
||||
- cron: '0 0 * * 1'
|
||||
|
||||
jobs:
|
||||
linux-vfx:
|
||||
runs-on: ubuntu-latest
|
||||
name: linux-clang-sanitizer:${{ matrix.config.build }}
|
||||
container:
|
||||
image: aswf/ci-openvdb:2021
|
||||
env:
|
||||
CXX: clang++
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- { build: 'asan', cmake: '-DUSE_BLOSC=OFF' } # We never called blosc_destroy(), so disable blosc to silence these errors
|
||||
- { build: 'ubsan', cmake: '' } # Currently doesn't error, just reports all issues
|
||||
#- { build: 'lsan', cmake: '' } # asan encompasses and includes lsan
|
||||
#- { build: 'tsan', cmake: '' } # requires full stack rebuild for valid results (including libc++)
|
||||
#- { build: 'msan', cmake: '' } # requires full stack rebuild for valid results (including libc++)
|
||||
#- { build: 'coverage', cmake: '' } # todo
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install_gtest
|
||||
run: ./ci/install_gtest.sh 1.8.0
|
||||
- name: build
|
||||
run: >
|
||||
./ci/build.sh -v
|
||||
--build-type=${{ matrix.config.build }}
|
||||
--components="core,axcore,test,axtest"
|
||||
--cargs=\"-DOPENVDB_CXX_STRICT=ON -DOPENVDB_CORE_STATIC=OFF -DOPENVDB_AX_STATIC=OFF ${{ matrix.config.cmake }}\"
|
||||
- name: test
|
||||
run: cd build && ctest -V
|
||||
@@ -1,33 +0,0 @@
|
||||
|
||||
name: Whitespace
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'tsc/meetings/**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'tsc/meetings/**'
|
||||
|
||||
jobs:
|
||||
# Search the git repository for any trailing spaces excluding meeting notes
|
||||
trailingspaces:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: test
|
||||
run: |
|
||||
set +e
|
||||
git grep -n -I -E '^.+[ ]+$' -- ':!tsc/meetings/*'
|
||||
test $? -eq 1
|
||||
|
||||
# Search for any tabs excluding meeting notes, image files and a few others
|
||||
spacesnottabs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: test
|
||||
run: |
|
||||
set +e
|
||||
git grep -n " " -- ':!*/whitespace.yml' ':!tsc/meetings/*' ':!*.svg' ':!*.cmd' ':!*.png'
|
||||
test $? -eq 1
|
||||
@@ -1,20 +1,58 @@
|
||||
OpenVDB Version History
|
||||
=======================
|
||||
|
||||
Version 9.0.0 - In development
|
||||
Version 9.0.1 - In development
|
||||
|
||||
ABI changes:
|
||||
- Added transient data to the RootNode, InternalNode and LeafNode.
|
||||
|
||||
|
||||
Version 8.2.0 - In development
|
||||
Bug Fixes:
|
||||
- Minor fix to move assignment operator in nanovdb/util/HostBuffer.h.
|
||||
This could potentially be a problem on Windows debug builds (unconfirmed).
|
||||
- Minor fix to range in openvdb/tools/LevelSetSphere.h. This could result
|
||||
in data races for multi-threaded execution (unconfirmed) [Reported by Tommy Hinks]
|
||||
- Fixed a bug with Tree::combineExtended which wouldn't propagate the resulting active state when a destination tile overlapped a source child node. [Reported by @frapit]
|
||||
- Fix unit tests failures with Blosc versions >= 1.19.0.
|
||||
|
||||
New features:
|
||||
- Added support for AMD's HIP API in NanoVDB [Contributed by Blender Foundation]
|
||||
- Added bindings mechanism to AX to allow differing data and AX attribute names (@) in Point and Volume executables.
|
||||
- Added support for OpenVDB AX on Windows.
|
||||
|
||||
Improvements:
|
||||
- Added a --thread [n] argument to the vdb_ax binary.
|
||||
- Added a --copy-file-metadata option to vdb_ax. This behaviour is now off by default.
|
||||
- Added support for multiple input files with the vdb_ax binary using -i. Positional arguments as input files are deprecated.
|
||||
- Added tools::minMax() which supports multithreaded evaluation of active minimum and maximum values. Grid::evalMinMax() has been deprecated. [Contributed by Greg Hurst]
|
||||
|
||||
Build:
|
||||
- Regenerated AX grammar with Flex 2.6.4 and Bison 3.8.2.
|
||||
- Improved locating NumPy in CMake when multiple python versions are installed.
|
||||
- Fixed an issue which could report Python as missing when using CMake 3.18 and later on some systems. [Reported by Sam James]
|
||||
|
||||
Houdini:
|
||||
- Added Attribute Bindings to AX SOP to allow differently named AX attributes (@) and target point attributes/volumes.
|
||||
- Fix race condition in OpenVDB Merge SOP that could cause crashes
|
||||
or merged VDBs to not be deleted.
|
||||
|
||||
|
||||
Version 9.0.0 - October 29, 2021
|
||||
|
||||
This version introduces ABI changes relative to older major releases,
|
||||
so to preserve ABI compatibility it might be necessary to define the
|
||||
macro OPENVDB_ABI_VERSION_NUMBER=N, where, for example, N is 7 for
|
||||
Houdini 18.5 and 8 for Houdini 19.0.
|
||||
|
||||
Official release of NanoVDB, which for the first time offers GPU support
|
||||
for static sparse volumes in OpenVDB.
|
||||
|
||||
New features:
|
||||
- Faster build times from support for explicit template instantiation,
|
||||
which is enabled by default for most of the tools.
|
||||
- Added support for OpenEXR 3 and TBB 2021.
|
||||
- Added transient data to the RootNode, InternalNode, and LeafNode.
|
||||
|
||||
Improvements:
|
||||
- Added tools::countActiveLeafVoxels(), tools::countInactiveVoxels(),
|
||||
tools::countInactiveLeafVoxels() and tools::activeTiles() to perform
|
||||
multi-threaded counting. The Tree methods now use these implementations.
|
||||
|
||||
Improvements:
|
||||
- Moved from the deprecated TBB task scheduler to TBB arenas. Various
|
||||
methods now respect the TBB arena state they were invoked from.
|
||||
- Introduced a new thread/Threading.h header to consolidate calls to
|
||||
@@ -25,12 +63,106 @@ Version 8.2.0 - In development
|
||||
hue, saturation and value inputs to RGB values and vice-versa.
|
||||
- PointDataGrid conversion can now be performed using 32-bit float arrays.
|
||||
- Improved support for size_t grid types on systems where size_t is a
|
||||
unique type
|
||||
unique type.
|
||||
[Contributed by Brecht Van Lommel]
|
||||
- Add support for dilation in one direction and extending a field in one
|
||||
direction in fast sweeping algorithms.
|
||||
- Added PNG support to vdb_render which can be enabled with during CMake
|
||||
with -DUSE_PNG=ON.
|
||||
- Explicit template instantiation has been enabled by default for most of
|
||||
the tools. This pre-compiles template instantiations into the core library
|
||||
to reduce the time spent compiling code in downstream libraries or
|
||||
applications.
|
||||
- Added a python binding for OpenVDB AX which allows you to invoke accelerated
|
||||
AX code from the python module.
|
||||
|
||||
Bug Fixes:
|
||||
- Fixed a bug where ax::run() would crash if it could not parse a single
|
||||
statement.
|
||||
|
||||
ABI changes:
|
||||
- Added transient data to the RootNode, InternalNode, and LeafNode.
|
||||
|
||||
API changes:
|
||||
- DynamicNodeManager can now set one grain size for threading across leaf nodes
|
||||
and another for threading across non-leaf nodes.
|
||||
- StringGrid and StringTrees are deprecated.
|
||||
- The NullInterrupter is now a virtual base class to help reduce
|
||||
compile-time instantiation cost.
|
||||
|
||||
Houdini:
|
||||
- Fix crash in VDB Combine in Copy B mode if the second input has
|
||||
more VDBs than the first.
|
||||
- VDB Vector Merge SOP is now VDB Vector From Scalar SOP to distinguish
|
||||
it from the VDB Merge SOP. It keeps the same internal name so this
|
||||
is merely a label change.
|
||||
- Add option to pass in OPENVDB_DSO_NAMES to CMake to configure which
|
||||
Houdini DSOs are compiled.
|
||||
- VDB Activate SOP now has an option for the expansion pattern to use
|
||||
for dilation.
|
||||
- The label for Voxels to Expand is now Expand Voxels to match Houdini.
|
||||
- Fix bug to allow VDB LOD SOPs to be chained together.
|
||||
- SOP Extrapolate supports dilation in one direction and extending a field
|
||||
in one (domain) direction.
|
||||
- The default OpenVDB ABI is now 8 for Houdini versions > 18.5.
|
||||
- VDB Visualize Tree SOP is now multi-threaded and provides slicing and
|
||||
color remapping.
|
||||
- A new HoudiniInterrupter has been added that derives from the
|
||||
NullInterrupter and the Interrupter is now deprecated. All the SOPs have
|
||||
been updated to use the new HoudiniInterrupter.
|
||||
- Add a sanitizer in SOP OpenVDB Extrapolate when expanding a narrow-band
|
||||
level-set with a dilation value of 0, which will result in no operation.
|
||||
|
||||
Build:
|
||||
- Added support for TBB 2021.
|
||||
- Enabled the OPENVDB_FUTURE_DEPRECATION variable by default to warn on
|
||||
upcoming deprecations.
|
||||
- Introduced a OPENVDB_DOXYGEN_INTERNAL CMake variable which is ON by
|
||||
default and removes the majority of internal namespaces from the
|
||||
generated doxygen.
|
||||
- Improved the doxygen deprecation listings, folder layouts and fixes
|
||||
issues when using later versions of doxygen.
|
||||
- Build fixes for MinGW on Windows.
|
||||
[Contributed by Brecht Sanders]
|
||||
- Added support for OpenEXR 3.
|
||||
[Contributed by Cary Phillips]
|
||||
- Added an OPENVDB_NAMESPACE_SUFFIX CMake string option which provides
|
||||
the ability to customise the VDB namespace.
|
||||
- The Python Module now appends the base directory defined by
|
||||
Python_SITELIB to the default install path (typically dist-packages
|
||||
or site-packages).
|
||||
[Contributed by Ignacio Vizzo]
|
||||
- As of this release, VFX Reference Platform 2019 is no longer supported.
|
||||
CMake now issues deprecation warnings for 2020 VFX Reference Platform
|
||||
version dependencies.
|
||||
- Build fixes for OpenVDB AX with C++17 and greater.
|
||||
- Bumped the new blosc version future minimum to 1.17.0.
|
||||
- OpenEXR is now optional for vdb_render. It can be enabled with
|
||||
-DUSE_EXR=ON.
|
||||
|
||||
|
||||
Version 8.2.0 - November 24, 2021
|
||||
|
||||
Improvements:
|
||||
- Added tools::countActiveLeafVoxels(), tools::countInactiveVoxels(),
|
||||
tools::countInactiveLeafVoxels() and tools::activeTiles() to perform
|
||||
multi-threaded counting. The Tree methods now use these implementations.
|
||||
- Moved from the deprecated TBB task scheduler to TBB arenas. Various
|
||||
methods now respect the TBB arena state they were invoked from.
|
||||
- Introduced a new thread/Threading.h header to consolidate calls to
|
||||
third-party threading methods.
|
||||
- Minor performance improvements to dilation calls in fast sweeping
|
||||
algorithms.
|
||||
- Added hsvtogrb() and rgbtohsv() AX helper functions for converting
|
||||
hue, saturation and value inputs to RGB values and vice-versa.
|
||||
- PointDataGrid conversion can now be performed using 32-bit float arrays.
|
||||
- Improved support for size_t grid types on systems where size_t is a
|
||||
unique type.
|
||||
[Contributed by Brecht Van Lommel]
|
||||
- Minor performance improvements to dilation calls in fast sweeping
|
||||
algorithms
|
||||
algorithms.
|
||||
- Add support for dilation in one direction and extending a field in one
|
||||
direction
|
||||
direction in fast sweeping algorithms.
|
||||
|
||||
API changes:
|
||||
- DynamicNodeManager can now set one grain size for threading across leaf nodes
|
||||
@@ -49,10 +181,12 @@ Version 8.2.0 - In development
|
||||
- The label for Voxels to Expand is now Expand Voxels to match Houdini.
|
||||
- Fix bug to allow VDB LOD SOPs to be chained together.
|
||||
- SOP Extrapolate supports dilation in one direction and extending a field
|
||||
in one (domain) direction
|
||||
in one (domain) direction.
|
||||
- The default OpenVDB ABI is now 8 for Houdini versions > 18.5.
|
||||
- VDB Visualize Tree SOP is now multi-threaded and provides slicing and
|
||||
color remapping.
|
||||
- Add a sanitizer in SOP OpenVDB Extrapolate when expanding a narrow-band
|
||||
level-set with a dilation value of 0, which will result in no operation.
|
||||
|
||||
Build:
|
||||
- Added support for TBB 2021.
|
||||
@@ -63,15 +197,15 @@ Version 8.2.0 - In development
|
||||
generated doxygen.
|
||||
- Improved the doxygen deprecation listings, folder layouts and fixes
|
||||
issues when using later versions of doxygen.
|
||||
- Build fixes for MinGW on Windows
|
||||
- Build fixes for MinGW on Windows.
|
||||
[Contributed by Brecht Sanders]
|
||||
- Added support for OpenEXR 3
|
||||
- Added support for OpenEXR 3.
|
||||
[Contributed by Cary Phillips]
|
||||
- Added an OPENVDB_NAMESPACE_SUFFIX CMake string option which provides
|
||||
the ability to customise the VDB namespace.
|
||||
- The Python Module now appends the base directory defined by
|
||||
Python_SITELIB to the default install path (typically dist-packages
|
||||
or site-packages)
|
||||
or site-packages).
|
||||
[Contributed by Ignacio Vizzo]
|
||||
|
||||
|
||||
|
||||
+124
-349
@@ -42,7 +42,7 @@
|
||||
|
||||
# note: cmake_minimum_required must be called before project commands to
|
||||
# ensure policy scope is set up correctly
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
# CMP0091 allows for MSVC ABI targetting via CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
# from CMake 3.15 and above. Must come before project().
|
||||
@@ -52,9 +52,9 @@ endif()
|
||||
|
||||
###### Version
|
||||
|
||||
set(OpenVDB_MAJOR_VERSION 8)
|
||||
set(OpenVDB_MINOR_VERSION 2)
|
||||
set(OpenVDB_PATCH_VERSION 0)
|
||||
set(OpenVDB_MAJOR_VERSION 9)
|
||||
set(OpenVDB_MINOR_VERSION 0)
|
||||
set(OpenVDB_PATCH_VERSION 1)
|
||||
set(OpenVDB_VERSION "${OpenVDB_MAJOR_VERSION}.${OpenVDB_MINOR_VERSION}.${OpenVDB_PATCH_VERSION}")
|
||||
|
||||
project(OpenVDB LANGUAGES CXX VERSION ${OpenVDB_VERSION})
|
||||
@@ -73,16 +73,19 @@ option(OPENVDB_BUILD_DOCS "Build the OpenVDB documentation" OFF)
|
||||
option(OPENVDB_BUILD_HOUDINI_PLUGIN "Build the Houdini plugin" OFF)
|
||||
option(OPENVDB_BUILD_HOUDINI_ABITESTS "Build the Houdini ABI tests" OFF)
|
||||
|
||||
option(OPENVDB_BUILD_AX "Build the OpenVDB AX library" OFF)
|
||||
option(OPENVDB_BUILD_AX_BINARIES "Build the OpenVDB AX command line binary" OFF)
|
||||
option(OPENVDB_BUILD_AX "Build the OpenVDB AX library. Turns ON if USE_AX is ON." ${USE_AX})
|
||||
option(OPENVDB_BUILD_AX_UNITTESTS "Build the OpenVDB AX unit tests" OFF)
|
||||
|
||||
option(OPENVDB_BUILD_NANOVDB "Build the NanoVDB library. Turns ON if USE_NANOVDB is ON." ${USE_NANOVDB})
|
||||
|
||||
option(OPENVDB_BUILD_MAYA_PLUGIN "Build the Maya plugin" OFF)
|
||||
option(OPENVDB_ENABLE_RPATH "Build with RPATH information" ON)
|
||||
option(OPENVDB_CXX_STRICT "Enable or disable pre-defined compiler warnings" OFF)
|
||||
|
||||
cmake_dependent_option(OPENVDB_INSTALL_CMAKE_MODULES
|
||||
"Install the provided OpenVDB CMake modules when building the core library"
|
||||
ON "OPENVDB_BUILD_CORE" OFF)
|
||||
|
||||
option(USE_HOUDINI [=[
|
||||
Build the library against a Houdini installation. Turns on automatically if OPENVDB_BUILD_HOUDINI_PLUGIN is enabled.
|
||||
When enabled, you do not need to provide dependency locations for TBB, Blosc, IlmBase and OpenEXR. Boost must be
|
||||
@@ -90,6 +93,8 @@ provided. IlmBase/OpenEXR can optionally be provided if Houdini Version >= 17.5.
|
||||
option(USE_MAYA [=[
|
||||
Build the library against a Maya installation. Turns on automatically if OPENVDB_BUILD_MAYA_PLUGIN is enabled.
|
||||
When enabled, you do not need to provide dependency locations for TBB. All other dependencies must be provided.]=] OFF)
|
||||
option(USE_TBB [=[
|
||||
Use TBB in building the NanoVDB library.]=] ON)
|
||||
option(USE_BLOSC [=[
|
||||
Use blosc while building openvdb components. If OPENVDB_BUILD_CORE is OFF, CMake attempts to query the located
|
||||
openvdb build configuration to decide on blosc support. You may set this to on to force blosc to be used if you
|
||||
@@ -101,11 +106,18 @@ option(USE_LOG4CPLUS [=[
|
||||
Use log4cplus while building openvdb components. If OPENVDB_BUILD_CORE is OFF, CMake attempts to query the
|
||||
located openvdb build configuration to decide on log4cplus support. You may set this to on to force log4cplus
|
||||
to be used if you know it to be required.]=] OFF)
|
||||
option(USE_EXR [=[
|
||||
Use OpenEXR while building openvdb components. If enabled, this also switches USE_IMATH_HALF to ON unless
|
||||
it too was provided and set to OFF.]=] OFF)
|
||||
option(USE_IMATH_HALF [=[
|
||||
Use the definiton of half floating point types from the Imath library. If OFF, the embedded definition provided
|
||||
by OpenVDB is used. If OPENVDB_BUILD_CORE is OFF, CMake attempts to query the located openvdb build configuration
|
||||
to select the correct half support. You may set this to on to force Imath half to be used if you know it to be
|
||||
required.]=] OFF)
|
||||
required.]=] ${USE_EXR})
|
||||
option(USE_PNG "Use PNG while building openvdb components." OFF)
|
||||
option(USE_AX "Use OpenVDB AX while building openvdb components." ${OPENVDB_BUILD_AX})
|
||||
option(USE_NANOVDB "Use NanoVDB while building openvdb components." ${OPENVDB_BUILD_NANOVDB})
|
||||
|
||||
cmake_dependent_option(OPENVDB_DISABLE_BOOST_IMPLICIT_LINKING
|
||||
"Disable the implicit linking of Boost libraries on Windows" ON "WIN32" OFF)
|
||||
option(USE_CCACHE "Build using Ccache if found on the path" ON)
|
||||
@@ -113,7 +125,7 @@ option(USE_STATIC_DEPENDENCIES [=[
|
||||
Only search for and use static libraries. If OFF the shared versions of requried libraries are prioritised, falling
|
||||
back to static libraries. Forcing individual static dependencies can be enabled by setting XXX_USE_STATIC_LIBS
|
||||
to ON, where XXX is the package name. On Windows this behaviour is less strict, with any located libraries assumed
|
||||
to be static. ]=] OFF)
|
||||
to be static. This has no effect for any packages found with Xxx_DIR (i.e. CMake CONFIG mode).]=] OFF)
|
||||
option(DISABLE_DEPENDENCY_VERSION_CHECKS [=[
|
||||
Disable minimum version checks for OpenVDB dependencies. It is strongly recommended that this remains disabled.
|
||||
Consider updating your dependencies where possible if encountering minimum requirement CMake errors.]=] OFF)
|
||||
@@ -122,12 +134,17 @@ Disable CMakes default system search paths when locating dependencies. When enab
|
||||
its default system search routine if it cannot find a dependency with the provided settings. When disabled, only
|
||||
paths provided through the Xxx_ROOT, supported XXX_INCLUDEDIR/XXX_LIBRARYDIR variables or the SYSTEM_LIBRARY_PATHS
|
||||
list will be searched.]=] OFF)
|
||||
option(OPENVDB_USE_DEPRECATED_ABI_6 "Bypass minimum ABI requirement checks" OFF)
|
||||
option(OPENVDB_USE_FUTURE_ABI_9 "Bypass future ABI check" OFF)
|
||||
option(OPENVDB_USE_DEPRECATED_ABI_7 "Bypass minimum ABI requirement checks" OFF)
|
||||
option(OPENVDB_USE_DEPRECATED_ABI_8 "Bypass minimum ABI requirement checks" OFF)
|
||||
option(OPENVDB_USE_FUTURE_ABI_10 "Bypass future ABI check" OFF)
|
||||
option(OPENVDB_FUTURE_DEPRECATION "Generate messages for upcoming deprecation" ON)
|
||||
option(OPENVDB_ENABLE_UNINSTALL "Adds a CMake uninstall target." ON)
|
||||
option(USE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." OFF)
|
||||
option(USE_PKGCONFIG "Use pkg-config to search for dependent libraries." ON)
|
||||
cmake_dependent_option(USE_PKGCONFIG "Use pkg-config to search for dependent libraries." ON "NOT WIN32" OFF)
|
||||
|
||||
option(USE_EXPLICIT_INSTANTIATION "Use explicit instantiation for all supported classes and methods against a
|
||||
pre-defined list of OpenVDB trees. This makes the core library larger and slower to compile, but speeds up
|
||||
the compilation of all dependent code by bypassing the expensive template instantation." ON)
|
||||
|
||||
set(SYSTEM_LIBRARY_PATHS "" CACHE STRING [=[
|
||||
A global list of library paths to additionally use into when searching for dependencies.]=])
|
||||
@@ -136,7 +153,6 @@ The number of threads to use when invoking MSVC builds with cmake --build. CMake
|
||||
cmake --parallel and CMAKE_BUILD_PARALLEL_LEVEL only change the number of PROJECTS that are built in parallel,
|
||||
NOT the number of TU's ]=])
|
||||
|
||||
|
||||
set(_CONCURRENT_MALLOC_OPTIONS None Auto Jemalloc Tbbmalloc)
|
||||
if(NOT CONCURRENT_MALLOC)
|
||||
set(CONCURRENT_MALLOC Auto CACHE STRING
|
||||
@@ -170,14 +186,49 @@ if(USE_BLOSC AND NOT USE_ZLIB)
|
||||
message(WARNING "ZLib can only be disabled if Blosc is also disabled. Enabling ZLib.")
|
||||
endif()
|
||||
|
||||
# Top-level location for all openvdb headers
|
||||
set(OPENVDB_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/openvdb")
|
||||
if(USE_NANOVDB)
|
||||
if(OPENVDB_BUILD_CORE AND NOT OPENVDB_BUILD_NANOVDB)
|
||||
message(FATAL_ERROR "Invalid CMake build configuration:
|
||||
OPENVDB_BUILD_CORE: [ON]
|
||||
OPENVDB_BUILD_NANOVDB: [OFF]
|
||||
USE_NANOVDB: [ON]
|
||||
If you are rebuilding the core library and using sub components, building
|
||||
these sub components must also be enabled (i.e. -DOPENVDB_BUILD_NANOVDB=ON).")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_AX)
|
||||
if(OPENVDB_BUILD_CORE AND NOT OPENVDB_BUILD_AX)
|
||||
message(FATAL_ERROR "Invalid CMake build configuration:
|
||||
OPENVDB_BUILD_CORE: [ON]
|
||||
OPENVDB_BUILD_AX: [OFF]
|
||||
USE_AX: [ON]
|
||||
If you are rebuilding the core library and using sub components, building
|
||||
these sub components must also be enabled (i.e. -DOPENVDB_BUILD_AX=ON).")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(OPENVDB_BUILD_HOUDINI_PLUGIN OR OPENVDB_BUILD_HOUDINI_ABITESTS)
|
||||
set(USE_HOUDINI ON)
|
||||
endif()
|
||||
|
||||
if(OPENVDB_BUILD_MAYA_PLUGIN)
|
||||
set(USE_MAYA ON)
|
||||
endif()
|
||||
|
||||
if(USE_MAYA AND USE_HOUDINI)
|
||||
# @todo technically this is possible so long as library versions match
|
||||
# exactly but it's difficult to validate and dangerous
|
||||
message(FATAL_ERROR "Cannot build both Houdini and Maya plugins against "
|
||||
"the same core dependencies. Plugins must be compiled separately to "
|
||||
"ensure the required DCC dependencies are met.")
|
||||
endif()
|
||||
|
||||
###### Deprecated options
|
||||
|
||||
if(USE_EXR)
|
||||
message(FATAL_ERROR "The USE_EXR option has been removed. Use USE_IMATH_HALF to use the Half "
|
||||
"implementation from IMath, or leave OFF to use the new embedded version of half floating point types.")
|
||||
if(OPENVDB_CODE_COVERAGE)
|
||||
message(FATAL_ERROR "The OPENVDB_CODE_COVERAGE option has been removed. Choose instead the unique"
|
||||
"build type -DCMAKE_BUILD_TYPE=coverage")
|
||||
endif()
|
||||
if(OPENVDB_BUILD_HOUDINI_SOPS)
|
||||
message(FATAL_ERROR "The OPENVDB_BUILD_HOUDINI_SOPS option has been removed. Use OPENVDB_BUILD_HOUDINI_PLUGIN.")
|
||||
@@ -189,154 +240,33 @@ endif()
|
||||
# Various root level CMake options which are marked as advanced
|
||||
|
||||
mark_as_advanced(
|
||||
CONCURRENT_MALLOC
|
||||
DISABLE_CMAKE_SEARCH_PATHS
|
||||
DISABLE_DEPENDENCY_VERSION_CHECKS
|
||||
OPENVDB_BUILD_HOUDINI_ABITESTS
|
||||
OPENVDB_CXX_STRICT
|
||||
OPENVDB_ENABLE_RPATH
|
||||
USE_HOUDINI
|
||||
USE_MAYA
|
||||
USE_LOG4CPLUS
|
||||
USE_IMATH_HALF
|
||||
USE_CCACHE
|
||||
OPENVDB_BUILD_HOUDINI_ABITESTS
|
||||
DISABLE_DEPENDENCY_VERSION_CHECKS
|
||||
DISABLE_CMAKE_SEARCH_PATHS
|
||||
OPENVDB_USE_DEPRECATED_ABI_6
|
||||
OPENVDB_USE_FUTURE_ABI_9
|
||||
OPENVDB_FUTURE_DEPRECATION
|
||||
CONCURRENT_MALLOC
|
||||
USE_COLORED_OUTPUT
|
||||
SYSTEM_LIBRARY_PATHS
|
||||
OPENVDB_SIMD
|
||||
OPENVDB_USE_DEPRECATED_ABI_7
|
||||
OPENVDB_USE_DEPRECATED_ABI_8
|
||||
OPENVDB_USE_FUTURE_ABI_10
|
||||
SYSTEM_LIBRARY_PATHS
|
||||
USE_CCACHE
|
||||
USE_COLORED_OUTPUT
|
||||
USE_HOUDINI
|
||||
USE_IMATH_HALF
|
||||
USE_LOG4CPLUS
|
||||
USE_MAYA
|
||||
)
|
||||
|
||||
# Configure minimum version requirements - some are treated specially and fall
|
||||
# outside of the DISABLE_DEPENDENCY_VERSION_CHECKS catch
|
||||
|
||||
set(MINIMUM_CXX_STANDARD 14)
|
||||
|
||||
# @note Blosc version is currently treated as exception which must be adhered
|
||||
# to. The minimum version must be at least 1.5.0. Previous versions are incompatible.
|
||||
# Later versions (including 1.5.4), can be buggy on certain platforms.
|
||||
set(MINIMUM_BLOSC_VERSION 1.5.0)
|
||||
# @note ABI always enforced so the correct deprecation messages are available.
|
||||
# OPENVDB_USE_DEPRECATED_ABI_<VERSION> should be used to circumvent this
|
||||
set(MINIMUM_OPENVDB_ABI_VERSION 6)
|
||||
set(FUTURE_MINIMUM_OPENVDB_ABI_VERSION 7)
|
||||
set(FUTURE_OPENVDB_ABI_VERSION 9)
|
||||
|
||||
if(NOT DISABLE_DEPENDENCY_VERSION_CHECKS)
|
||||
# @note Currently tracking CY2019 of the VFX platform where available
|
||||
set(MINIMUM_GCC_VERSION 6.3.1)
|
||||
set(MINIMUM_CLANG_VERSION 3.8)
|
||||
set(MINIMUM_ICC_VERSION 17)
|
||||
set(MINIMUM_MSVC_VERSION 19.10)
|
||||
|
||||
set(MINIMUM_BOOST_VERSION 1.61) # @warning should be 1.66, but H18 ships with 1.61
|
||||
set(MINIMUM_ILMBASE_VERSION 2.2) # @warning should be 2.3, but H18 ships with 2.2
|
||||
set(MINIMUM_OPENEXR_VERSION 2.2) # @warning should be 2.3, but H18 ships with 2.2
|
||||
set(MINIMUM_ZLIB_VERSION 1.2.7)
|
||||
set(MINIMUM_TBB_VERSION 2018.0)
|
||||
set(MINIMUM_LLVM_VERSION 6.0.0)
|
||||
|
||||
set(MINIMUM_PYTHON_VERSION 2.7)
|
||||
set(MINIMUM_NUMPY_VERSION 1.14.0)
|
||||
|
||||
set(MINIMUM_GOOGLETEST_VERSION 1.8)
|
||||
set(MINIMUM_GLFW_VERSION 3.1)
|
||||
set(MINIMUM_LOG4CPLUS_VERSION 1.1.2)
|
||||
set(MINIMUM_HOUDINI_VERSION 18.0)
|
||||
|
||||
# These always promote warnings rather than errors
|
||||
set(MINIMUM_MAYA_VERSION 2017)
|
||||
set(MINIMUM_DOXYGEN_VERSION 1.8.8)
|
||||
endif()
|
||||
|
||||
# VFX 20 deprecations to transition to MINIMUM_* variables in OpenVDB 9.0.0
|
||||
|
||||
# Note: CMake 3.15 chosen as possible next version due to Windows support
|
||||
# with CMAKE_MSVC_RUNTIME_LIBRARY, numpy modules with CMake 3.14 and simplified
|
||||
# python linkage on macOS (Python::Module target in 3.15)
|
||||
set(FUTURE_MINIMUM_CMAKE_VERSION 3.15)
|
||||
|
||||
# No compiler upgrades planned
|
||||
#set(FUTURE_MINIMUM_GCC_VERSION 6.3.1)
|
||||
#set(FUTURE_MINIMUM_ICC_VERSION 17)
|
||||
#set(FUTURE_MINIMUM_MSVC_VERSION 19.10)
|
||||
|
||||
set(FUTURE_MINIMUM_ILMBASE_VERSION 2.4)
|
||||
set(FUTURE_MINIMUM_OPENEXR_VERSION 2.4)
|
||||
set(FUTURE_MINIMUM_BOOST_VERSION 1.70)
|
||||
set(FUTURE_MINIMUM_TBB_VERSION 2019.0)
|
||||
set(FUTURE_MINIMUM_PYTHON_VERSION 3.7)
|
||||
set(FUTURE_MINIMUM_NUMPY_VERSION 1.17.0)
|
||||
set(FUTURE_MINIMUM_HOUDINI_VERSION 18.5)
|
||||
set(FUTURE_MINIMUM_LLVM_VERSION 8.0.0)
|
||||
|
||||
#########################################################################
|
||||
|
||||
# General CMake and CXX settings
|
||||
# Configure MINIMUM and FUTURE_MINIMUM version variables
|
||||
|
||||
if(FUTURE_MINIMUM_CMAKE_VERSION)
|
||||
if(${CMAKE_VERSION} VERSION_LESS ${FUTURE_MINIMUM_CMAKE_VERSION})
|
||||
message(DEPRECATION "Support for CMake versions < ${FUTURE_MINIMUM_CMAKE_VERSION} "
|
||||
"is deprecated and will be removed.")
|
||||
endif()
|
||||
endif()
|
||||
include(cmake/config/OpenVDBVersions.cmake)
|
||||
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD ${MINIMUM_CXX_STANDARD} CACHE STRING
|
||||
"The C++ standard whose features are requested to build OpenVDB components." FORCE)
|
||||
elseif(CMAKE_CXX_STANDARD LESS ${MINIMUM_CXX_STANDARD})
|
||||
message(FATAL_ERROR "Provided C++ Standard is less than the supported minimum."
|
||||
"Required is at least \"${MINIMUM_CXX_STANDARD}\" (found ${CMAKE_CXX_STANDARD})")
|
||||
endif()
|
||||
|
||||
# Configure MS Runtime
|
||||
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY AND CMAKE_VERSION VERSION_LESS 3.15)
|
||||
# CMAKE_MSVC_RUNTIME_LIBRARY selects the MSVC runtime library for use by compilers
|
||||
# targeting the MSVC ABI. Options are: MultiThreaded MultiThreadedDLL MultiThreadedDebug
|
||||
# MultiThreadedDebugDLL. If empty, CMake defaults to MultiThreaded$<$<CONFIG:Debug>:Debug>DLL
|
||||
message(FATAL_ERROR "CMAKE_MSVC_RUNTIME_LIBRARY support is only available from CMake 3.15")
|
||||
endif()
|
||||
if(WIN32 AND CMAKE_MSVC_RUNTIME_LIBRARY)
|
||||
message(STATUS "CMAKE_MSVC_RUNTIME_LIBRARY set to target ${CMAKE_MSVC_RUNTIME_LIBRARY}")
|
||||
|
||||
# Configure Boost library varient on Windows
|
||||
if(NOT Boost_USE_STATIC_RUNTIME)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL MultiThreaded OR
|
||||
CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL MultiThreadedDebug)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT Boost_USE_DEBUG_RUNTIME)
|
||||
set(Boost_USE_DEBUG_RUNTIME OFF)
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL MultiThreadedDebugDLL OR
|
||||
CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL MultiThreadedDebug)
|
||||
set(Boost_USE_DEBUG_RUNTIME ON)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
|
||||
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
|
||||
|
||||
if(OPENVDB_ENABLE_RPATH)
|
||||
# Configure rpath for installation base on the following:
|
||||
# https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling
|
||||
set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
# @todo make relocatable?
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
|
||||
# For CMake's find Threads module which brings in pthread - This flag
|
||||
# forces the compiler -pthread flag vs -lpthread
|
||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
#########################################################################
|
||||
|
||||
enable_testing()
|
||||
|
||||
@@ -344,13 +274,6 @@ enable_testing()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
|
||||
# Add backports to support older versions of CMake
|
||||
# FindNumPy.cmake is needed if CMake < 3.14
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.14)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/backports")
|
||||
endif()
|
||||
|
||||
# Add cmake modules to installation command
|
||||
# @todo fix our glew cmake module
|
||||
|
||||
@@ -371,26 +294,6 @@ if(OPENVDB_INSTALL_CMAKE_MODULES)
|
||||
install(FILES ${OPENVDB_CMAKE_MODULES} DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/OpenVDB)
|
||||
endif()
|
||||
|
||||
# Configure DCC installation if necessary
|
||||
|
||||
if(OPENVDB_BUILD_HOUDINI_PLUGIN OR
|
||||
OPENVDB_BUILD_HOUDINI_ABITESTS)
|
||||
set(USE_HOUDINI ON)
|
||||
endif()
|
||||
|
||||
if(OPENVDB_BUILD_MAYA_PLUGIN)
|
||||
set(USE_MAYA ON)
|
||||
endif()
|
||||
|
||||
if(USE_MAYA AND USE_HOUDINI)
|
||||
# @todo technically this is possible so long as library versions match
|
||||
# exactly but it's difficult to validate and dangerous
|
||||
message(FATAL_ERROR "Cannot build both Houdini and Maya plugins against "
|
||||
"the same core dependencies. Plugins must be compiled separately to "
|
||||
"ensure the required DCC dependencies are met."
|
||||
)
|
||||
endif()
|
||||
|
||||
# Configure component dependencies by loading the Houdini/Maya setup
|
||||
# scripts. These also find the Houdini/Maya installations
|
||||
|
||||
@@ -406,15 +309,6 @@ if(OPENVDB_BUILD_DOCS)
|
||||
add_subdirectory(doc)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(OPENVDB_BUILD_AX OR
|
||||
OPENVDB_BUILD_AX_GRAMMAR OR
|
||||
OPENVDB_BUILD_AX_BINARIES OR
|
||||
OPENVDB_BUILD_AX_UNITTESTS)
|
||||
message(FATAL_ERROR "Currently no support for building OpenVDB AX or the OpenVDB AX grammar on Windows.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT OPENVDB_BUILD_AX AND OPENVDB_BUILD_AX_GRAMMAR)
|
||||
# only re-generate the AX grammar
|
||||
set(OPENVDB_AX_SHARED OFF CACHE BOOL "" FORCE)
|
||||
@@ -428,13 +322,13 @@ if(NOT (
|
||||
OPENVDB_BUILD_CORE OR
|
||||
OPENVDB_BUILD_BINARIES OR
|
||||
OPENVDB_BUILD_AX OR
|
||||
OPENVDB_BUILD_AX_BINARIES OR
|
||||
OPENVDB_BUILD_AX_UNITTESTS OR
|
||||
OPENVDB_BUILD_PYTHON_MODULE OR
|
||||
OPENVDB_BUILD_UNITTESTS OR
|
||||
OPENVDB_BUILD_HOUDINI_PLUGIN OR
|
||||
OPENVDB_BUILD_HOUDINI_ABITESTS OR
|
||||
OPENVDB_BUILD_MAYA_PLUGIN)
|
||||
OPENVDB_BUILD_MAYA_PLUGIN OR
|
||||
OPENVDB_BUILD_NANOVDB)
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
@@ -452,153 +346,13 @@ if(USE_CCACHE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Build type configuration
|
||||
|
||||
if(OPENVDB_CODE_COVERAGE)
|
||||
message(DEPRECATION "The OPENVDB_CODE_COVERAGE option is deprecated. Choose instead the unique"
|
||||
"build type -DCMAKE_BUILD_TYPE=coverage")
|
||||
set(CMAKE_BUILD_TYPE coverage)
|
||||
endif()
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
include(cmake/config/OpenVDBBuildTypes.cmake)
|
||||
|
||||
if(CMAKE_BUILD_TYPE EQUAL coverage)
|
||||
# use .gcno extension instead of .cc.gcno
|
||||
# @note This is an undocumented internal cmake var and does not work
|
||||
# with multi config generators
|
||||
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)
|
||||
endif()
|
||||
|
||||
# CMAKE_BUILD_TYPE is ignored for multi config generators i.e. MSVS
|
||||
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(NOT _isMultiConfig)
|
||||
message(STATUS "CMake Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
endif()
|
||||
|
||||
#########################################################################
|
||||
|
||||
# Compiler configuration. Add definitions for a number of compiler warnings
|
||||
# for sub projects and verify version requirements
|
||||
# @todo add definitions for Intel.
|
||||
# Configure general CMake and CXX settings
|
||||
|
||||
set(HAS_AVAILABLE_WARNINGS FALSE)
|
||||
include(cmake/config/OpenVDBCXX.cmake)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_CLANG_VERSION)
|
||||
message(FATAL_ERROR "Insufficient clang++ version. Minimum required is "
|
||||
"\"${MINIMUM_CLANG_VERSION}\". Found version \"${CMAKE_CXX_COMPILER_VERSION}\""
|
||||
)
|
||||
endif()
|
||||
if(OPENVDB_CXX_STRICT)
|
||||
message(STATUS "Configuring Clang CXX warnings")
|
||||
set(HAS_AVAILABLE_WARNINGS TRUE)
|
||||
add_compile_options(
|
||||
-Werror
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wconversion
|
||||
-Wno-sign-conversion
|
||||
)
|
||||
endif()
|
||||
if(USE_COLORED_OUTPUT)
|
||||
message(STATUS "Enabling colored compiler output")
|
||||
add_compile_options(-fcolor-diagnostics)
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_GCC_VERSION)
|
||||
message(FATAL_ERROR "Insufficient g++ version. Minimum required is "
|
||||
"\"${MINIMUM_GCC_VERSION}\". Found version \"${CMAKE_CXX_COMPILER_VERSION}\""
|
||||
)
|
||||
endif()
|
||||
if(OPENVDB_FUTURE_DEPRECATION AND FUTURE_MINIMUM_GCC_VERSION)
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS FUTURE_MINIMUM_GCC_VERSION)
|
||||
message(DEPRECATION "Support for GCC versions < ${FUTURE_MINIMUM_GCC_VERSION} "
|
||||
"is deprecated and will be removed.")
|
||||
endif()
|
||||
endif()
|
||||
if(OPENVDB_CXX_STRICT)
|
||||
message(STATUS "Configuring GCC CXX warnings")
|
||||
set(HAS_AVAILABLE_WARNINGS TRUE)
|
||||
add_compile_options(
|
||||
-Werror
|
||||
-Wall
|
||||
-Wextra
|
||||
-pedantic
|
||||
-Wcast-align
|
||||
-Wcast-qual
|
||||
-Wconversion
|
||||
-Wdisabled-optimization
|
||||
-Woverloaded-virtual
|
||||
)
|
||||
endif()
|
||||
if(USE_COLORED_OUTPUT)
|
||||
message(STATUS "Enabling colored compiler output")
|
||||
add_compile_options(-fdiagnostics-color=always)
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_ICC_VERSION)
|
||||
message(FATAL_ERROR "Insufficient ICC version. Minimum required is "
|
||||
"\"${MINIMUM_ICC_VERSION}\". Found version \"${CMAKE_CXX_COMPILER_VERSION}\""
|
||||
)
|
||||
endif()
|
||||
if(OPENVDB_FUTURE_DEPRECATION AND FUTURE_MINIMUM_ICC_VERSION)
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS FUTURE_MINIMUM_ICC_VERSION)
|
||||
message(DEPRECATION "Support for ICC versions < ${FUTURE_MINIMUM_ICC_VERSION} "
|
||||
"is deprecated and will be removed.")
|
||||
endif()
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_MSVC_VERSION)
|
||||
message(FATAL_ERROR "Insufficient MSVC version. Minimum required is "
|
||||
"\"${MINIMUM_MSVC_VERSION}\". Found version \"${CMAKE_CXX_COMPILER_VERSION}\""
|
||||
)
|
||||
endif()
|
||||
if(OPENVDB_FUTURE_DEPRECATION AND FUTURE_MINIMUM_MSVC_VERSION)
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS FUTURE_MINIMUM_MSVC_VERSION)
|
||||
message(DEPRECATION "Support for MSVC versions < ${FUTURE_MINIMUM_MSVC_VERSION} "
|
||||
"is deprecated and will be removed.")
|
||||
endif()
|
||||
endif()
|
||||
# Increase the number of sections that an object file can contain
|
||||
add_compile_options(/bigobj)
|
||||
# Excludes APIs such as Cryptography, DDE, RPC, Shell, and Windows Sockets
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
# Disable non-secure CRT library function warnings
|
||||
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/
|
||||
# compiler-warning-level-3-c4996?view=vs-2019#unsafe-crt-library-functions
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
# Disable POSIX function name warnings
|
||||
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/
|
||||
# compiler-warning-level-3-c4996?view=vs-2019#posix-function-names
|
||||
add_definitions(-D_CRT_NONSTDC_NO_WARNINGS)
|
||||
if(NOT OPENVDB_CXX_STRICT)
|
||||
message(STATUS "Suppressing some noisy MSVC CXX warnings, "
|
||||
"set OPENVDB_CXX_STRICT=ON to re-enable them.")
|
||||
# Conversion from int64_t to long
|
||||
add_compile_options(/wd4244)
|
||||
# It's not possible to use STL types in DLL interfaces in a portable and
|
||||
# reliable way so disable this warning
|
||||
add_compile_options(/wd4251)
|
||||
# Conversion from size_t to uLong
|
||||
add_compile_options(/wd4267)
|
||||
# Non dll-interface class used as base for dll-interface class
|
||||
add_compile_options(/wd4275)
|
||||
# Truncation from 'int' to 'bool'
|
||||
add_compile_options(/wd4305)
|
||||
endif()
|
||||
# If a user has explicitly requested a parallel build, configure this during CMake
|
||||
if(MSVC_MP_THREAD_COUNT AND MSVC_MP_THREAD_COUNT GREATER 1)
|
||||
add_compile_options(/MP${MSVC_MP_THREAD_COUNT})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(OPENVDB_CXX_STRICT AND NOT HAS_AVAILABLE_WARNINGS)
|
||||
message(WARNING "No available CXX warnings for compiler ${CMAKE_CXX_COMPILER_ID}")
|
||||
endif()
|
||||
unset(HAS_AVAILABLE_WARNINGS)
|
||||
#########################################################################
|
||||
|
||||
# Configure malloc library. Use Jemalloc for Linux and non-Maya, otherwise Tbbmalloc.
|
||||
# * On Mac OSX, linking against Jemalloc < 4.3.0 seg-faults with this error:
|
||||
@@ -627,12 +381,13 @@ endif()
|
||||
# Configure SIMD. AVX implies SSE 4.2.
|
||||
|
||||
if(OPENVDB_SIMD STREQUAL "AVX")
|
||||
add_compile_options(-mavx -msse4.2)
|
||||
add_definitions(-DOPENVDB_USE_AVX)
|
||||
add_definitions(-DOPENVDB_USE_SSE42)
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-mavx>")
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-msse4.2>")
|
||||
add_compile_definitions("$<$<COMPILE_LANGUAGE:CXX>:OPENVDB_USE_AVX>")
|
||||
add_compile_definitions("$<$<COMPILE_LANGUAGE:CXX>:OPENVDB_USE_SSE42>")
|
||||
elseif(OPENVDB_SIMD STREQUAL "SSE42")
|
||||
add_compile_options(-msse4.2)
|
||||
add_definitions(-DOPENVDB_USE_SSE42)
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-msse4.2>")
|
||||
add_compile_definitions("$<$<COMPILE_LANGUAGE:CXX>:OPENVDB_USE_SSE42>")
|
||||
endif()
|
||||
|
||||
#########################################################################
|
||||
@@ -654,7 +409,19 @@ endif()
|
||||
|
||||
# Configure OpenVDB Library and ABI versions
|
||||
|
||||
if(NOT OPENVDB_BUILD_CORE)
|
||||
set(NEEDS_OPENVDB OFF)
|
||||
|
||||
if(OPENVDB_BUILD_AX OR
|
||||
OPENVDB_BUILD_BINARIES OR
|
||||
OPENVDB_BUILD_UNITTESTS OR
|
||||
OPENVDB_BUILD_HOUDINI_PLUGIN OR
|
||||
OPENVDB_BUILD_MAYA_PLUGIN OR
|
||||
OPENVDB_BUILD_PYTHON_MODULE OR
|
||||
OPENVDB_BUILD_HOUDINI_ABITESTS)
|
||||
set(NEEDS_OPENVDB ON)
|
||||
endif()
|
||||
|
||||
if(NOT OPENVDB_BUILD_CORE AND NEEDS_OPENVDB)
|
||||
# Find VDB installation and determine lib/abi versions. This resets the
|
||||
# version and ABI numbers
|
||||
find_package(OpenVDB REQUIRED)
|
||||
@@ -674,11 +441,19 @@ message(STATUS "Configuring for OpenVDB Version ${OpenVDB_VERSION}")
|
||||
# Locate openvdb_ax if necessary
|
||||
|
||||
if(NOT OPENVDB_BUILD_AX AND
|
||||
(OPENVDB_BUILD_AX_BINARIES OR
|
||||
OPENVDB_BUILD_AX_UNITTESTS))
|
||||
(OPENVDB_BUILD_AX_UNITTESTS OR
|
||||
USE_AX))
|
||||
find_package(OpenVDB REQUIRED COMPONENTS openvdb_ax)
|
||||
endif()
|
||||
|
||||
# Locate nanovdb if necessary
|
||||
|
||||
if(NOT OPENVDB_BUILD_NANOVDB AND
|
||||
USE_NANOVDB)
|
||||
find_package(OpenVDB REQUIRED COMPONENTS nanovdb)
|
||||
endif()
|
||||
|
||||
|
||||
# Validate the OpenVDB ABI Version. If OpenVDB_ABI is not set, we're either building
|
||||
# the core library OR the ABI hasn't been deduced from a VDB installation. Use the
|
||||
# value from OPENVDB_ABI_VERSION_NUMBER, falling back to the lib major version number
|
||||
@@ -752,10 +527,6 @@ if(OPENVDB_BUILD_AX)
|
||||
add_subdirectory(openvdb_ax/openvdb_ax)
|
||||
endif()
|
||||
|
||||
if(OPENVDB_BUILD_AX_BINARIES)
|
||||
add_subdirectory(openvdb_ax/openvdb_ax/cmd)
|
||||
endif()
|
||||
|
||||
if(OPENVDB_BUILD_AX_UNITTESTS)
|
||||
add_subdirectory(openvdb_ax/openvdb_ax/test)
|
||||
endif()
|
||||
@@ -765,7 +536,7 @@ if(OPENVDB_BUILD_PYTHON_MODULE)
|
||||
endif()
|
||||
|
||||
if(OPENVDB_BUILD_BINARIES)
|
||||
add_subdirectory(openvdb/openvdb/cmd)
|
||||
add_subdirectory(openvdb_cmd)
|
||||
endif()
|
||||
|
||||
if(OPENVDB_BUILD_UNITTESTS)
|
||||
@@ -784,6 +555,10 @@ if(OPENVDB_BUILD_MAYA_PLUGIN)
|
||||
add_subdirectory(openvdb_maya/openvdb_maya)
|
||||
endif()
|
||||
|
||||
if(OPENVDB_BUILD_NANOVDB)
|
||||
add_subdirectory(nanovdb/nanovdb)
|
||||
endif()
|
||||
|
||||
##########################################################################
|
||||
|
||||
if(OPENVDB_ENABLE_UNINSTALL)
|
||||
|
||||
+26
-23
@@ -5,36 +5,39 @@
|
||||
# https://git-scm.com/docs/gitignore#_pattern_format
|
||||
|
||||
# Admin/General
|
||||
/.github/ @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
/ci/ @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
/cmake/ @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
/doc/ @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
/pendingchanges/ @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
/tsc/ @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
CODEOWNERS @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
LICENSE @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
CHANGES @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
*.md @kmuseth @apradhana @jmlait @idclip @danrbailey
|
||||
/.github/ @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
/ci/ @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
/cmake/ @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
/doc/ @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
/pendingchanges/ @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
/tsc/ @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
CODEOWNERS @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
LICENSE @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
CHANGES @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
*.md @kmuseth @apradhana @jmlait @idclip @danrbailey @richhones
|
||||
|
||||
# Core OpenVDB Library
|
||||
/openvdb/ @kmuseth
|
||||
/openvdb/openvdb/points/ @danrbailey @idclip
|
||||
/openvdb/ @kmuseth
|
||||
/openvdb/openvdb/points/ @danrbailey @idclip
|
||||
|
||||
# OpenVDB AX
|
||||
/openvdb_ax/ @idclip
|
||||
/openvdb_ax/ @idclip @richhones
|
||||
|
||||
# NanoVDB
|
||||
/nanovdb/ @kmuseth
|
||||
|
||||
# OpenVDB Houdini - Default
|
||||
/openvdb_houdini/ @kmuseth
|
||||
/openvdb_houdini/ @kmuseth
|
||||
|
||||
# OpenVDB Houdini - VDB Primitive and SideFX Utils
|
||||
/openvdb_houdini/openvdb_houdini/GEO_PrimVDB.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/GU_PrimVDB.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/GEO_VDBTranslator.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/GT_GEOPrimCollectVDB.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/SOP_VDBVerbUtils.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/UT_VDBUtils.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/GEO_PrimVDB.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/GU_PrimVDB.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/GEO_VDBTranslator.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/GT_GEOPrimCollectVDB.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/SOP_VDBVerbUtils.* @jmlait
|
||||
/openvdb_houdini/openvdb_houdini/UT_VDBUtils.* @jmlait
|
||||
|
||||
# OpenVDB Houdini - VDB Points
|
||||
/openvdb_houdini/openvdb_houdini/PointUtils.* @danrbailey @idclip
|
||||
/openvdb_houdini/openvdb_houdini/*_OpenVDB_Points_* @danrbailey @idclip
|
||||
/openvdb_houdini/openvdb_houdini/GR_PrimVDBPoints.* @danrbailey @idclip
|
||||
/openvdb_houdini/openvdb_houdini/PointUtils.* @danrbailey @idclip
|
||||
/openvdb_houdini/openvdb_houdini/*_OpenVDB_Points_* @danrbailey @idclip
|
||||
/openvdb_houdini/openvdb_houdini/GR_PrimVDBPoints.* @danrbailey @idclip
|
||||
|
||||
@@ -97,6 +97,7 @@ All meetings of the TSC are open to participation by any member of the OpenVDB c
|
||||
* Jeff Lait, SideFX
|
||||
* Nick Avramoussis, WETA
|
||||
* Dan Bailey, ILM
|
||||
* Richard Jones, DNEG
|
||||
|
||||
# Release Process
|
||||
|
||||
|
||||
+7
-6
@@ -6,10 +6,11 @@
|
||||
The current OpenVDB maintainers are:
|
||||
|
||||
|
||||
| Name | Email |
|
||||
| -------------- | -----------------
|
||||
| Jeff Lait | jlait@sidefx.com
|
||||
| Dan Bailey | danbailey@ilm.com
|
||||
| Name | Email |
|
||||
| ---------------- | -----------------
|
||||
| Jeff Lait | jlait@sidefx.com
|
||||
| Dan Bailey | danbailey@ilm.com
|
||||
| Nick Avramoussis | navramoussis@wetafx.co.nz
|
||||
| Ken Museth | ken.museth@gmail.com
|
||||
| Andre Pradhana | andre.pradhana@dreamworks.com
|
||||
| Ken Museth | ken.museth@gmail.com
|
||||
| Andre Pradhana | andre.pradhana@dreamworks.com
|
||||
| Richard Jones | rhj@dneg.com
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||

|
||||
|
||||
[](LICENSE.md)
|
||||
[](LICENSE)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/2774)
|
||||
[](https://slack.aswf.io/)
|
||||
|
||||
| Build | Status |
|
||||
| --------------- | ------ |
|
||||
| OpenVDB | [](https://github.com/AcademySoftwareFoundation/openvdb/actions?query=workflow%3ABuild) |
|
||||
| OpenVDB AX | [](https://github.com/AcademySoftwareFoundation/openvdb/actions?query=workflow%3Aax) |
|
||||
|
||||
| OpenVDB | AX | Nano | Houdini |
|
||||
| :----: | :----: | :----: | :----: |
|
||||
| [](https://github.com/AcademySoftwareFoundation/openvdb/actions/workflows/build.yml) | [](https://github.com/AcademySoftwareFoundation/openvdb/actions/workflows/ax.yml) | [](https://github.com/AcademySoftwareFoundation/openvdb/actions/workflows/nanovdb.yml) | [](https://github.com/AcademySoftwareFoundation/openvdb/actions/workflows/houdini.yml) |
|
||||
|
||||
[Website](https://www.openvdb.org) |
|
||||
[Discussion Forum](https://www.openvdb.org/forum) |
|
||||
[Discussion Forum](https://github.com/AcademySoftwareFoundation/openvdb/discussions) |
|
||||
[Documentation](https://academysoftwarefoundation.github.io/openvdb)
|
||||
|
||||
OpenVDB is an open source C++ library comprising a novel hierarchical data structure and a large suite of tools for the efficient storage and manipulation of sparse volumetric data discretized on three-dimensional grids. It was developed by DreamWorks Animation for use in volumetric applications typically encountered in feature film production.
|
||||
@@ -32,64 +33,41 @@ OpenVDB welcomes contributions to the OpenVDB project. Please refer to the [cont
|
||||
|
||||
### Developer Quick Start
|
||||
|
||||
The following provides basic installation examples for the core OpenVDB library. Other components, such as the python module, OpenVDB AX and various executables, may require additional dependencies. See the [build documentation](https://academysoftwarefoundation.github.io/openvdb/build.html) for help with installations.
|
||||
The following provides basic installation examples for the core OpenVDB library. Other components, such as the python module, OpenVDB AX, NanoVDB and various executables, may require additional dependencies. See the [build documentation](https://academysoftwarefoundation.github.io/openvdb/build.html) for help with installations.
|
||||
|
||||
#### Linux
|
||||
##### Installing Dependencies (Boost, TBB, Blosc)
|
||||
|
||||
```
|
||||
```bash
|
||||
apt-get install -y libboost-iostreams-dev
|
||||
apt-get install -y libboost-system-dev
|
||||
apt-get install -y libtbb-dev
|
||||
```
|
||||
```
|
||||
git clone git@github.com:Blosc/c-blosc.git
|
||||
cd c-blosc
|
||||
git checkout tags/v1.5.0 -b v1.5.0
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j4
|
||||
make install
|
||||
cd ../..
|
||||
apt-get install -y libblosc-dev
|
||||
```
|
||||
|
||||
##### Building OpenVDB
|
||||
```
|
||||
```bash
|
||||
git clone git@github.com:AcademySoftwareFoundation/openvdb.git
|
||||
cd openvdb
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j4
|
||||
make install
|
||||
make -j4 && make install
|
||||
```
|
||||
#### macOS
|
||||
##### Installing Dependencies (Boost, TBB, Blosc)
|
||||
```
|
||||
```bash
|
||||
brew install boost
|
||||
brew install tbb
|
||||
```
|
||||
```
|
||||
git clone git@github.com:Blosc/c-blosc.git
|
||||
cd c-blosc
|
||||
git checkout tags/v1.5.0 -b v1.5.0
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j4
|
||||
make install
|
||||
cd ../..
|
||||
brew install c-blosc
|
||||
```
|
||||
##### Building OpenVDB
|
||||
```
|
||||
```bash
|
||||
git clone git@github.com:AcademySoftwareFoundation/openvdb.git
|
||||
cd openvdb
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j4
|
||||
make install
|
||||
make -j4 && make install
|
||||
```
|
||||
#### Windows
|
||||
##### Installing Dependencies (Boost, TBB, Blosc)
|
||||
@@ -100,19 +78,18 @@ It is recommended to set the `VCPKG_DEFAULT_TRIPLET` environment variable to
|
||||
[Git](https://git-scm.com/downloads), [vcpkg](https://github.com/microsoft/vcpkg)
|
||||
and [CMake](https://cmake.org/download/) to be installed.
|
||||
|
||||
```
|
||||
```bash
|
||||
vcpkg install zlib:x64-windows
|
||||
vcpkg install blosc:x64-windows
|
||||
vcpkg install tbb:x64-windows
|
||||
vcpkg install boost-iostreams:x64-windows
|
||||
vcpkg install boost-system:x64-windows
|
||||
vcpkg install boost-any:x64-windows
|
||||
vcpkg install boost-algorithm:x64-windows
|
||||
vcpkg install boost-uuid:x64-windows
|
||||
vcpkg install boost-interprocess:x64-windows
|
||||
```
|
||||
##### Building OpenVDB
|
||||
```
|
||||
```bash
|
||||
git clone git@github.com:AcademySoftwareFoundation/openvdb.git
|
||||
cd openvdb
|
||||
mkdir build
|
||||
@@ -120,3 +97,43 @@ cd build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=<PATH_TO_VCPKG>\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows -A x64 ..
|
||||
cmake --build . --parallel 4 --config Release --target install
|
||||
```
|
||||
|
||||
#### Building OpenVDB AX
|
||||
|
||||
OpenVDB AX depends on the core OpenVDB library. See the [build documentation](https://academysoftwarefoundation.github.io/openvdb/build.html) for all available AX component options:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:AcademySoftwareFoundation/openvdb.git
|
||||
cd openvdb
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DOPENVDB_BUILD_AX=ON ..
|
||||
make -j4 && make install
|
||||
```
|
||||
|
||||
#### Building NanoVDB
|
||||
|
||||
NanoVDB can be built with and without OpenVDB support. To see full build instructions
|
||||
see the [NanoVDB build documentation](https://academysoftwarefoundation.github.io/openvdb/NanoVDB_HowToBuild.html)
|
||||
|
||||
#### Building Without OpenVDB Support
|
||||
|
||||
```bash
|
||||
git clone git@github.com:AcademySoftwareFoundation/openvdb.git
|
||||
cd openvdb/nanovdb/nanovdb # Build from the subdirectory
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j4 && make install
|
||||
```
|
||||
|
||||
#### Building With OpenVDB Support
|
||||
|
||||
```bash
|
||||
git clone git@github.com:AcademySoftwareFoundation/openvdb.git
|
||||
cd openvdb
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DOPENVDB_BUILD_NANOVDB=ON ..
|
||||
make -j4 && make install
|
||||
```
|
||||
|
||||
+19
-16
@@ -17,6 +17,7 @@ OPTS_ARGS+=("v") ## See --verbose
|
||||
OPTL_ARGS+=("components:") ## Specify cmake component(s) to enable
|
||||
OPTL_ARGS+=("config:") ## Specify cmake configuration during the build step
|
||||
OPTL_ARGS+=("target:") ## Specify target(s) to build
|
||||
OPTL_ARGS+=("build-dir:") ## Build directory
|
||||
OPTL_ARGS+=("cargs:") ## args to pass directly to cmake generation step
|
||||
OPTL_ARGS+=("build-type:") ## Release, Debug, etc.
|
||||
OPTL_ARGS+=("verbose") ## Verbose build output
|
||||
@@ -25,6 +26,7 @@ OPTL_ARGS+=("verbose") ## Verbose build output
|
||||
declare -A PARMS
|
||||
PARMS[--components]=core,bin
|
||||
PARMS[--target]=install
|
||||
PARMS[--build-dir]=build
|
||||
# github actions runners have 2 threads
|
||||
# https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
|
||||
PARMS[-j]=2
|
||||
@@ -35,13 +37,22 @@ COMPONENTS['core']='OPENVDB_BUILD_CORE'
|
||||
COMPONENTS['python']='OPENVDB_BUILD_PYTHON_MODULE'
|
||||
COMPONENTS['test']='OPENVDB_BUILD_UNITTESTS'
|
||||
COMPONENTS['bin']='OPENVDB_BUILD_BINARIES'
|
||||
COMPONENTS['view']='OPENVDB_BUILD_VDB_VIEW'
|
||||
COMPONENTS['render']='OPENVDB_BUILD_VDB_RENDER'
|
||||
COMPONENTS['hou']='OPENVDB_BUILD_HOUDINI_PLUGIN'
|
||||
COMPONENTS['doc']='OPENVDB_BUILD_DOCS'
|
||||
|
||||
COMPONENTS['axcore']='OPENVDB_BUILD_AX'
|
||||
COMPONENTS['axgr']='OPENVDB_BUILD_AX_GRAMMAR'
|
||||
COMPONENTS['axbin']='OPENVDB_BUILD_AX_BINARIES'
|
||||
COMPONENTS['axtest']='OPENVDB_BUILD_AX_UNITTESTS'
|
||||
|
||||
COMPONENTS['nano']='OPENVDB_BUILD_NANOVDB'
|
||||
COMPONENTS['nanotest']='NANOVDB_BUILD_UNITTESTS'
|
||||
COMPONENTS['nanoexam']='NANOVDB_BUILD_EXAMPLES'
|
||||
COMPONENTS['nanobench']='NANOVDB_BUILD_BENCHMARK'
|
||||
COMPONENTS['nanotool']='NANOVDB_BUILD_TOOLS'
|
||||
|
||||
################################################
|
||||
|
||||
HAS_PARM() {
|
||||
@@ -87,6 +98,8 @@ if HAS_PARM --cargs; then
|
||||
if [ -z $CMAKE_EXTRA ]; then CMAKE_EXTRA=${PARMS[--cargs]}
|
||||
else CMAKE_EXTRA+=" "${PARMS[--cargs]}; fi
|
||||
fi
|
||||
BUILD_DIR=${PARMS[--build-dir]}
|
||||
|
||||
# handle whitespace
|
||||
eval "CMAKE_EXTRA=($CMAKE_EXTRA)"
|
||||
|
||||
@@ -131,15 +144,7 @@ echo "Build using ${CMAKE_BUILD_PARALLEL_LEVEL} threads"
|
||||
# However it does not seem to for our project.
|
||||
# https://gitlab.kitware.com/cmake/cmake/-/issues/20564
|
||||
|
||||
CMAKE_BUILD_CMD="cmake --build . --parallel ${PARMS[-j]} --target $TARGET"
|
||||
|
||||
if HAS_PARM -v || HAS_PARM --verbose; then
|
||||
# cmake 3.14 and later required for --verbose
|
||||
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
|
||||
if [ $(version $CMAKE_VERSION) -gt $(version '3.14.0') ]; then
|
||||
CMAKE_BUILD_CMD+=" --verbose"
|
||||
fi
|
||||
fi
|
||||
CMAKE_BUILD_CMD="cmake --build . --parallel ${PARMS[-j]} --target $TARGET --verbose"
|
||||
|
||||
if HAS_PARM --config; then
|
||||
CMAKE_BUILD_CMD+=" --config ${PARMS[--config]}"
|
||||
@@ -147,21 +152,19 @@ fi
|
||||
|
||||
################################################
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
mkdir -p ${BUILD_DIR}
|
||||
cd ${BUILD_DIR}
|
||||
|
||||
# Report the cmake commands
|
||||
set -x
|
||||
|
||||
# Note:
|
||||
# - all sub binary options are always on and can be toggles with: OPENVDB_BUILD_BINARIES=ON/OFF
|
||||
# - print and lod binary options are always on and can be toggles with: OPENVDB_BUILD_BINARIES=ON/OFF
|
||||
cmake \
|
||||
-DOPENVDB_USE_DEPRECATED_ABI_6=ON \
|
||||
-DOPENVDB_USE_FUTURE_ABI_9=ON \
|
||||
-DOPENVDB_USE_DEPRECATED_ABI_7=ON \
|
||||
-DOPENVDB_USE_DEPRECATED_ABI_8=ON \
|
||||
-DOPENVDB_BUILD_VDB_PRINT=ON \
|
||||
-DOPENVDB_BUILD_VDB_LOD=ON \
|
||||
-DOPENVDB_BUILD_VDB_RENDER=ON \
|
||||
-DOPENVDB_BUILD_VDB_VIEW=ON \
|
||||
-DMSVC_MP_THREAD_COUNT=${PARMS[-j]} \
|
||||
"${CMAKE_EXTRA[@]}" \
|
||||
..
|
||||
|
||||
Executable
+106
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
import zipfile
|
||||
import argparse
|
||||
|
||||
try:
|
||||
from urllib.request import urlretrieve
|
||||
except ImportError:
|
||||
from urllib import urlretrieve
|
||||
|
||||
parser = argparse.ArgumentParser(description='VDB files to download')
|
||||
parser.add_argument('--files', '-f', type=str, nargs='+',
|
||||
help='files to download i.e. bunny.vdb fire.vdb')
|
||||
args = parser.parse_args()
|
||||
|
||||
vdbs = [
|
||||
'armadillo.vdb',
|
||||
'boat_points.vdb',
|
||||
'buddha.vdb',
|
||||
'bunny.vdb',
|
||||
'bunny_cloud.vdb',
|
||||
'bunny_points.vdb',
|
||||
'crawler.vdb',
|
||||
'cube.vdb',
|
||||
'dragon.vdb',
|
||||
'emu.vdb',
|
||||
'explosion.vdb',
|
||||
'fire.vdb',
|
||||
'icosahedron.vdb',
|
||||
'iss.vdb',
|
||||
'smoke1.vdb',
|
||||
'smoke2.vdb',
|
||||
'space.vdb',
|
||||
'sphere.vdb',
|
||||
'sphere_points.vdb',
|
||||
'torus.vdb',
|
||||
'torus_knot.vdb',
|
||||
'utahteapot.vdb',
|
||||
'venusstatue.vdb',
|
||||
'waterfall_points.vdb'
|
||||
]
|
||||
|
||||
if args.files:
|
||||
vdbs = list(set(vdbs) & set(args.files))
|
||||
if not vdbs:
|
||||
raise RuntimeError('No valid VDBs specified for download')
|
||||
|
||||
# forma urls in the form:
|
||||
# 'https://artifacts.aswf.io/io/aswf/openvdb/models/buddha.vdb/1.0.0/buddha.vdb-1.0.0.zip'
|
||||
|
||||
vdb_urls = []
|
||||
for vdb in vdbs:
|
||||
url = 'https://artifacts.aswf.io/io/aswf/openvdb/models/' + \
|
||||
vdb +'/1.0.0/' + vdb + '-1.0.0.zip'
|
||||
vdb_urls.append(url)
|
||||
|
||||
|
||||
def download(link, filelocation):
|
||||
urlretrieve(link, filelocation)
|
||||
|
||||
# Init downloads
|
||||
|
||||
downloads = dict()
|
||||
|
||||
for url in vdb_urls:
|
||||
zip_filename = os.path.basename(url)
|
||||
print('Initiating download "' + url + '"')
|
||||
download_thread = threading.Thread(target=download, args=(url,zip_filename))
|
||||
download_thread.start()
|
||||
downloads[zip_filename] = download_thread
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
# Process files
|
||||
|
||||
while downloads:
|
||||
zip_file = None
|
||||
while not zip_file:
|
||||
time.sleep(1)
|
||||
for file, thread in downloads.items():
|
||||
if not thread.is_alive():
|
||||
thread.join()
|
||||
zip_file = file
|
||||
break
|
||||
# Remove the entry
|
||||
del downloads[zip_file]
|
||||
|
||||
try:
|
||||
# Extract the downloaded zip
|
||||
print('Extracting "' + zip_file + '"...')
|
||||
sys.stdout.flush()
|
||||
with zipfile.ZipFile(zip_file, 'r') as zip_ref:
|
||||
zip_ref.extractall()
|
||||
|
||||
print('Cleaning up "' + zip_file + '"...')
|
||||
sys.stdout.flush()
|
||||
if os.path.isfile(zip_file): os.remove(zip_file)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
pass
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
set -e
|
||||
|
||||
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/../"
|
||||
VDB_AX=$ROOT/build/openvdb_ax/openvdb_ax/cmd/vdb_ax
|
||||
VDB_AX=$ROOT/build/openvdb_cmd/vdb_ax/vdb_ax
|
||||
|
||||
DOCS=()
|
||||
DOCS+=($ROOT/doc/ax/ax.txt)
|
||||
|
||||
+19
-1
@@ -3,6 +3,11 @@
|
||||
set -ex
|
||||
|
||||
BLOSC_VERSION="$1"
|
||||
INSTALL_ROOT="$2"
|
||||
CMAKE_EXTRA=()
|
||||
if [ ! -z "${INSTALL_ROOT}" ]; then
|
||||
CMAKE_EXTRA+=("-DCMAKE_INSTALL_PREFIX=${INSTALL_ROOT}")
|
||||
fi
|
||||
|
||||
git clone https://github.com/Blosc/c-blosc.git
|
||||
cd c-blosc
|
||||
@@ -13,6 +18,19 @@ fi
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../.
|
||||
|
||||
# On MacOS there's a bug between blosc 1.14-1.20 where unistd isn't included
|
||||
# in zlib-1.2.8/gzlib.c. Provide -DPREFER_EXTERNAL_ZLIB to use the installed
|
||||
# version of zlib.
|
||||
# https://github.com/Blosc/python-blosc/issues/229
|
||||
cmake \
|
||||
-DPREFER_EXTERNAL_ZLIB=ON \
|
||||
-DBUILD_STATIC=OFF \
|
||||
-DBUILD_TESTS=OFF \
|
||||
-DBUILD_FUZZERS=OFF \
|
||||
-DBUILD_BENCHMARKS=OFF \
|
||||
"${CMAKE_EXTRA[@]}" \
|
||||
..
|
||||
|
||||
make -j4
|
||||
make install
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ex
|
||||
|
||||
LLVM_CRT="$1"
|
||||
|
||||
git clone -b llvmorg-12.0.0 --depth 1 https://github.com/llvm/llvm-project.git llvm
|
||||
cd llvm
|
||||
|
||||
mkdir .build
|
||||
cd .build
|
||||
|
||||
# @note currently only test static builds with MT
|
||||
cmake -S ../llvm -A x64 -G "Visual Studio 16 2019" -Thost=x64 \
|
||||
-DCMAKE_INSTALL_PREFIX="${HOME}/llvm_install" \
|
||||
-DLLVM_TARGETS_TO_BUILD="host" \
|
||||
-DLLVM_BUILD_TOOLS=OFF \
|
||||
-DLLVM_INCLUDE_BENCHMARKS=OFF \
|
||||
-DLLVM_INCLUDE_EXAMPLES=OFF \
|
||||
-DLLVM_INCLUDE_TESTS=OFF \
|
||||
-DLLVM_INCLUDE_TOOLS=OFF \
|
||||
-DLLVM_USE_CRT_RELEASE=${LLVM_CRT} \
|
||||
..
|
||||
|
||||
cmake --build . --config Release --target install
|
||||
|
||||
cd ..
|
||||
|
||||
du -h .build -d0
|
||||
du -h ${HOME}/llvm_install -d0
|
||||
|
||||
rm -rf .build
|
||||
@@ -3,5 +3,5 @@
|
||||
set -ex
|
||||
|
||||
vcpkg update
|
||||
vcpkg install zlib openexr tbb gtest blosc glfw3 glew \
|
||||
boost-iostreams boost-system boost-any boost-uuid boost-interprocess boost-algorithm
|
||||
vcpkg install zlib libpng openexr tbb gtest blosc glfw3 glew \
|
||||
boost-iostreams boost-any boost-uuid boost-interprocess boost-algorithm
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
# Download and install CUDA on windows. Based off the scripts by:
|
||||
# https://github.com/ptheywood/cuda-cmake-github-actions
|
||||
|
||||
## -------------------
|
||||
## Constants
|
||||
## -------------------
|
||||
|
||||
# Dictionary of known cuda versions and thier download URLS, which do not follow a consistent pattern :(
|
||||
$CUDA_KNOWN_URLS = @{
|
||||
"8.0.44" = "http://developer.nvidia.com/compute/cuda/8.0/Prod/network_installers/cuda_8.0.44_win10_network-exe";
|
||||
"8.0.61" = "http://developer.nvidia.com/compute/cuda/8.0/Prod2/network_installers/cuda_8.0.61_win10_network-exe";
|
||||
"9.0.176" = "http://developer.nvidia.com/compute/cuda/9.0/Prod/network_installers/cuda_9.0.176_win10_network-exe";
|
||||
"9.1.85" = "http://developer.nvidia.com/compute/cuda/9.1/Prod/network_installers/cuda_9.1.85_win10_network";
|
||||
"9.2.148" = "http://developer.nvidia.com/compute/cuda/9.2/Prod2/network_installers2/cuda_9.2.148_win10_network";
|
||||
"10.0.130" = "http://developer.nvidia.com/compute/cuda/10.0/Prod/network_installers/cuda_10.0.130_win10_network";
|
||||
"10.1.105" = "http://developer.nvidia.com/compute/cuda/10.1/Prod/network_installers/cuda_10.1.105_win10_network.exe";
|
||||
"10.1.168" = "http://developer.nvidia.com/compute/cuda/10.1/Prod/network_installers/cuda_10.1.168_win10_network.exe";
|
||||
"10.1.243" = "http://developer.download.nvidia.com/compute/cuda/10.1/Prod/network_installers/cuda_10.1.243_win10_network.exe";
|
||||
"10.2.89" = "http://developer.download.nvidia.com/compute/cuda/10.2/Prod/network_installers/cuda_10.2.89_win10_network.exe";
|
||||
"11.0.1" = "http://developer.download.nvidia.com/compute/cuda/11.0.1/network_installers/cuda_11.0.1_win10_network.exe";
|
||||
"11.0.2" = "http://developer.download.nvidia.com/compute/cuda/11.0.2/network_installers/cuda_11.0.2_win10_network.exe";
|
||||
"11.0.3" = "http://developer.download.nvidia.com/compute/cuda/11.0.3/network_installers/cuda_11.0.3_win10_network.exe";
|
||||
"11.1.0" = "https://developer.download.nvidia.com/compute/cuda/11.1.0/network_installers/cuda_11.1.0_win10_network.exe";
|
||||
"11.1.1" = "https://developer.download.nvidia.com/compute/cuda/11.1.1/network_installers/cuda_11.1.1_win10_network.exe";
|
||||
"11.2.0" = "https://developer.download.nvidia.com/compute/cuda/11.2.0/network_installers/cuda_11.2.0_win10_network.exe";
|
||||
"11.2.1" = "https://developer.download.nvidia.com/compute/cuda/11.2.1/network_installers/cuda_11.2.1_win10_network.exe";
|
||||
"11.2.2" = "https://developer.download.nvidia.com/compute/cuda/11.2.2/network_installers/cuda_11.2.2_win10_network.exe";
|
||||
"11.3.0" = "https://developer.download.nvidia.com/compute/cuda/11.3.0/network_installers/cuda_11.3.0_win10_network.exe"
|
||||
}
|
||||
|
||||
# @todo - change this to be based on _MSC_VER intead, or invert it to be CUDA keyed instead?
|
||||
$VISUAL_STUDIO_MIN_CUDA = @{
|
||||
"2019" = "10.1";
|
||||
"2017" = "10.0"; # Depends on which version of 2017! 9.0 to 10.0 depending on version
|
||||
"2015" = "8.0"; # might support older, unsure.
|
||||
}
|
||||
|
||||
# cuda_runtime.h is in nvcc <= 10.2, but cudart >= 11.0
|
||||
# @todo - make this easier to vary per CUDA version.
|
||||
$CUDA_PACKAGES_IN = @(
|
||||
"nvcc";
|
||||
"visual_studio_integration";
|
||||
"curand_dev";
|
||||
"nvrtc_dev";
|
||||
"cudart";
|
||||
)
|
||||
|
||||
|
||||
## -------------------
|
||||
## Select CUDA version
|
||||
## -------------------
|
||||
|
||||
# Get the cuda version from the environment as env:cuda.
|
||||
$CUDA_VERSION_FULL = $env:cuda
|
||||
# Make sure CUDA_VERSION_FULL is set and valid, otherwise error.
|
||||
|
||||
# Validate CUDA version, extracting components via regex
|
||||
$cuda_ver_matched = $CUDA_VERSION_FULL -match "^(?<major>[1-9][0-9]*)\.(?<minor>[0-9]+)\.(?<patch>[0-9]+)$"
|
||||
if(-not $cuda_ver_matched){
|
||||
Write-Output "Invalid CUDA version specified, <major>.<minor>.<patch> required. '$CUDA_VERSION_FULL'."
|
||||
exit 1
|
||||
}
|
||||
$CUDA_MAJOR=$Matches.major
|
||||
$CUDA_MINOR=$Matches.minor
|
||||
$CUDA_PATCH=$Matches.patch
|
||||
|
||||
## ---------------------------
|
||||
## Visual studio support check
|
||||
## ---------------------------
|
||||
# Exit if visual studio is too new for the cuda version.
|
||||
$VISUAL_STUDIO = $env:visual_studio.trim()
|
||||
if ($VISUAL_STUDIO.length -ge 4) {
|
||||
$VISUAL_STUDIO_YEAR = $VISUAL_STUDIO.Substring($VISUAL_STUDIO.Length-4)
|
||||
if ($VISUAL_STUDIO_YEAR.length -eq 4 -and $VISUAL_STUDIO_MIN_CUDA.containsKey($VISUAL_STUDIO_YEAR)){
|
||||
$MINIMUM_CUDA_VERSION = $VISUAL_STUDIO_MIN_CUDA[$VISUAL_STUDIO_YEAR]
|
||||
if ([version]$CUDA_VERSION_FULL -lt [version]$MINIMUM_CUDA_VERSION) {
|
||||
Write-Output "Error: Visual Studio $($VISUAL_STUDIO_YEAR) requires CUDA >= $($MINIMUM_CUDA_VERSION)"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Output "Warning: Unknown Visual Studio Version. CUDA version may be insufficient."
|
||||
}
|
||||
|
||||
## ------------------------------------------------
|
||||
## Select CUDA packages to install from environment
|
||||
## ------------------------------------------------
|
||||
|
||||
$CUDA_PACKAGES = ""
|
||||
|
||||
# for CUDA >= 11 cudart is a required package.
|
||||
# if([version]$CUDA_VERSION_FULL -ge [version]"11.0") {
|
||||
# if(-not $CUDA_PACKAGES_IN -contains "cudart") {
|
||||
# $CUDA_PACKAGES_IN += 'cudart'
|
||||
# }
|
||||
# }
|
||||
|
||||
Foreach ($package in $CUDA_PACKAGES_IN) {
|
||||
# Make sure the correct package name is used for nvcc.
|
||||
if($package -eq "nvcc" -and [version]$CUDA_VERSION_FULL -lt [version]"9.1"){
|
||||
$package="compiler"
|
||||
} elseif($package -eq "compiler" -and [version]$CUDA_VERSION_FULL -ge [version]"9.1") {
|
||||
$package="nvcc"
|
||||
}
|
||||
$CUDA_PACKAGES += " $($package)_$($CUDA_MAJOR).$($CUDA_MINOR)"
|
||||
|
||||
}
|
||||
echo "$($CUDA_PACKAGES)"
|
||||
## -----------------
|
||||
## Prepare download
|
||||
## -----------------
|
||||
|
||||
# Select the download link if known, otherwise have a guess.
|
||||
$CUDA_REPO_PKG_REMOTE=""
|
||||
if($CUDA_KNOWN_URLS.containsKey($CUDA_VERSION_FULL)){
|
||||
$CUDA_REPO_PKG_REMOTE=$CUDA_KNOWN_URLS[$CUDA_VERSION_FULL]
|
||||
} else{
|
||||
# Guess what the url is given the most recent pattern (at the time of writing, 10.1)
|
||||
Write-Output "note: URL for CUDA ${$CUDA_VERSION_FULL} not known, estimating."
|
||||
$CUDA_REPO_PKG_REMOTE="http://developer.download.nvidia.com/compute/cuda/$($CUDA_MAJOR).$($CUDA_MINOR)/Prod/network_installers/cuda_$($CUDA_VERSION_FULL)_win10_network.exe"
|
||||
}
|
||||
$CUDA_REPO_PKG_LOCAL="cuda_$($CUDA_VERSION_FULL)_win10_network.exe"
|
||||
|
||||
|
||||
## ------------
|
||||
## Install CUDA
|
||||
## ------------
|
||||
|
||||
# Get CUDA network installer
|
||||
Write-Output "Downloading CUDA Network Installer for $($CUDA_VERSION_FULL) from: $($CUDA_REPO_PKG_REMOTE)"
|
||||
Invoke-WebRequest $CUDA_REPO_PKG_REMOTE -OutFile $CUDA_REPO_PKG_LOCAL | Out-Null
|
||||
if(Test-Path -Path $CUDA_REPO_PKG_LOCAL){
|
||||
Write-Output "Downloading Complete"
|
||||
} else {
|
||||
Write-Output "Error: Failed to download $($CUDA_REPO_PKG_LOCAL) from $($CUDA_REPO_PKG_REMOTE)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Invoke silent install of CUDA (via network installer)
|
||||
Write-Output "Installing CUDA $($CUDA_VERSION_FULL). Subpackages $($CUDA_PACKAGES)"
|
||||
Start-Process -Wait -FilePath .\"$($CUDA_REPO_PKG_LOCAL)" -ArgumentList "-s $($CUDA_PACKAGES)"
|
||||
|
||||
# Check the return status of the CUDA installer.
|
||||
if (!$?) {
|
||||
Write-Output "Error: CUDA installer reported error. $($LASTEXITCODE)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Store the CUDA_PATH in the environment for the current session, to be forwarded in the action.
|
||||
$CUDA_PATH = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$($CUDA_MAJOR).$($CUDA_MINOR)"
|
||||
$CUDA_PATH_VX_Y = "CUDA_PATH_V$($CUDA_MAJOR)_$($CUDA_MINOR)"
|
||||
# Set environmental variables in this session
|
||||
$env:CUDA_PATH = "$($CUDA_PATH)"
|
||||
$env:CUDA_PATH_VX_Y = "$($CUDA_PATH_VX_Y)"
|
||||
Write-Output "CUDA_PATH $($CUDA_PATH)"
|
||||
Write-Output "CUDA_PATH_VX_Y $($CUDA_PATH_VX_Y)"
|
||||
|
||||
# PATH needs updating elsewhere, anything in here won't persist.
|
||||
# Append $CUDA_PATH/bin to path.
|
||||
# Set CUDA_PATH as an environmental variable
|
||||
|
||||
|
||||
# If executing on github actions, emit the appropriate echo statements to update environment variables
|
||||
if (Test-Path "env:GITHUB_ACTIONS") {
|
||||
# Set paths for subsequent steps, using $env:CUDA_PATH
|
||||
echo "Adding CUDA to CUDA_PATH, CUDA_PATH_X_Y and PATH"
|
||||
echo "CUDA_PATH=$env:CUDA_PATH" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
echo "$env:CUDA_PATH_VX_Y=$env:CUDA_PATH" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
echo "$env:CUDA_PATH/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
}
|
||||
+2
-2
@@ -8,10 +8,10 @@ set -e
|
||||
# the expected VDB installation
|
||||
|
||||
cmakelists="
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(TestInstall LANGUAGES CXX)
|
||||
find_package(OpenVDB REQUIRED COMPONENTS openvdb)
|
||||
add_executable(test_vdb_print \"../openvdb/openvdb/cmd/openvdb_print.cc\")
|
||||
add_executable(test_vdb_print \"../openvdb_cmd/vdb_print/main.cc\")
|
||||
target_link_libraries(test_vdb_print OpenVDB::openvdb)
|
||||
"
|
||||
mkdir tmp
|
||||
|
||||
+4
-14
@@ -88,7 +88,7 @@ may be provided to tell this module where to look.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
mark_as_advanced(
|
||||
@@ -192,7 +192,7 @@ list(APPEND _BLOSC_LIBRARYDIR_SEARCH_DIRS
|
||||
|
||||
set(_BLOSC_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
if(BLOSC_USE_STATIC_LIBS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
|
||||
endif()
|
||||
@@ -377,18 +377,8 @@ if(NOT TARGET Blosc::blosc)
|
||||
INTERFACE_LINK_DIRECTORIES
|
||||
"\$<\$<CONFIG:Release>:${Blosc_RELEASE_LIBRARY_DIRS}>;\$<\$<CONFIG:Debug>:${Blosc_DEBUG_LIBRARY_DIRS}>")
|
||||
target_link_libraries(Blosc::blosc INTERFACE
|
||||
$<$<CONFIG:Release>:lz4;snappy;zlib>
|
||||
$<$<CONFIG:Debug>:lz4d;snappyd;zlibd>)
|
||||
|
||||
if(BLOSC_USE_STATIC_LIBS)
|
||||
target_link_libraries(Blosc::blosc INTERFACE
|
||||
$<$<CONFIG:Release>:zstd_static>
|
||||
$<$<CONFIG:Debug>:zstd_staticd>)
|
||||
else()
|
||||
target_link_libraries(Blosc::blosc INTERFACE
|
||||
$<$<CONFIG:Release>:zstd>
|
||||
$<$<CONFIG:Debug>:zstdd>)
|
||||
endif()
|
||||
$<$<CONFIG:Release>:lz4;snappy;zlib;zstd>
|
||||
$<$<CONFIG:Debug>:lz4d;snappyd;zlibd;zstd>)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
+133
-38
@@ -34,6 +34,17 @@ This will define the following variables:
|
||||
The version of the CppUnit library which was found.
|
||||
``CppUnit_INCLUDE_DIRS``
|
||||
Include directories needed to use CppUnit.
|
||||
``CppUnit_RELEASE_LIBRARIES``
|
||||
Libraries needed to link to the release version of CppUnit.
|
||||
``CppUnit_RELEASE_LIBRARY_DIRS``
|
||||
CppUnit release library directories.
|
||||
``CppUnit_DEBUG_LIBRARIES``
|
||||
Libraries needed to link to the debug version of CppUnit.
|
||||
``CppUnit_DEBUG_LIBRARY_DIRS``
|
||||
CppUnit debug library directories.
|
||||
|
||||
Deprecated - use [RELEASE|DEBUG] variants:
|
||||
|
||||
``CppUnit_LIBRARIES``
|
||||
Libraries needed to link to CppUnit.
|
||||
``CppUnit_LIBRARY_DIRS``
|
||||
@@ -61,6 +72,8 @@ may be provided to tell this module where to look.
|
||||
Preferred include directory e.g. <prefix>/include
|
||||
``CPPUNIT_LIBRARYDIR``
|
||||
Preferred library directory e.g. <prefix>/lib
|
||||
``CPPUNIT_DEBUG_SUFFIX``
|
||||
Suffix of the debug version of CppUnit libs. Defaults to "_d".
|
||||
``SYSTEM_LIBRARY_PATHS``
|
||||
Global list of library paths intended to be searched by and find_xxx call
|
||||
``CPPUNIT_USE_STATIC_LIBS``
|
||||
@@ -70,7 +83,7 @@ may be provided to tell this module where to look.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
@@ -140,6 +153,10 @@ endif()
|
||||
# Search for CppUnit lib DIR
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
if(NOT DEFINED CPPUNIT_DEBUG_SUFFIX)
|
||||
set(CPPUNIT_DEBUG_SUFFIX "d")
|
||||
endif()
|
||||
|
||||
set(_CPPUNIT_LIBRARYDIR_SEARCH_DIRS "")
|
||||
list(APPEND _CPPUNIT_LIBRARYDIR_SEARCH_DIRS
|
||||
${CPPUNIT_LIBRARYDIR}
|
||||
@@ -152,7 +169,7 @@ list(APPEND _CPPUNIT_LIBRARYDIR_SEARCH_DIRS
|
||||
|
||||
set(_CPPUNIT_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
if(CPPUNIT_USE_STATIC_LIBS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
|
||||
else()
|
||||
@@ -164,19 +181,68 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Build suffix directories
|
||||
list(APPEND CPPUNIT_BUILD_TYPES RELEASE DEBUG)
|
||||
|
||||
find_library(CppUnit_LIBRARY cppunit
|
||||
${_FIND_CPPUNIT_ADDITIONAL_OPTIONS}
|
||||
PATHS ${_CPPUNIT_LIBRARYDIR_SEARCH_DIRS}
|
||||
PATH_SUFFIXES ${CMAKE_INSTALL_LIBDIR} lib64 lib
|
||||
)
|
||||
foreach(BUILD_TYPE ${CPPUNIT_BUILD_TYPES})
|
||||
set(_CPPUNIT_LIB_NAME cppunit)
|
||||
if(BUILD_TYPE STREQUAL DEBUG)
|
||||
set(_CPPUNIT_LIB_NAME "${_CPPUNIT_LIB_NAME}${CPPUNIT_DEBUG_SUFFIX}")
|
||||
endif()
|
||||
|
||||
# Find the lib
|
||||
find_library(CppUnit_LIBRARY_${BUILD_TYPE} ${_CPPUNIT_LIB_NAME}
|
||||
${_FIND_CPPUNIT_ADDITIONAL_OPTIONS}
|
||||
PATHS ${_CPPUNIT_LIBRARYDIR_SEARCH_DIRS}
|
||||
PATH_SUFFIXES ${CMAKE_INSTALL_LIBDIR} lib64 lib
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Reset library suffix
|
||||
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_CPPUNIT_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
unset(_CPPUNIT_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||
|
||||
if(CppUnit_LIBRARY_DEBUG AND CppUnit_LIBRARY_RELEASE)
|
||||
# if the generator is multi-config or if CMAKE_BUILD_TYPE is set for
|
||||
# single-config generators, set optimized and debug libraries
|
||||
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(_isMultiConfig OR CMAKE_BUILD_TYPE)
|
||||
set(CppUnit_LIBRARY optimized ${CppUnit_LIBRARY_RELEASE} debug ${CppUnit_LIBRARY_DEBUG})
|
||||
else()
|
||||
# For single-config generators where CMAKE_BUILD_TYPE has no value,
|
||||
# just use the release libraries
|
||||
set(CppUnit_LIBRARY ${CppUnit_LIBRARY_RELEASE})
|
||||
endif()
|
||||
# FIXME: This probably should be set for both cases
|
||||
set(CppUnit_LIBRARIES optimized ${CppUnit_LIBRARY_RELEASE} debug ${CppUnit_LIBRARY_DEBUG})
|
||||
endif()
|
||||
|
||||
# if only the release version was found, set the debug variable also to the release version
|
||||
if(CppUnit_LIBRARY_RELEASE AND NOT CppUnit_LIBRARY_DEBUG)
|
||||
set(CppUnit_LIBRARY_DEBUG ${CppUnit_LIBRARY_RELEASE})
|
||||
set(CppUnit_LIBRARY ${CppUnit_LIBRARY_RELEASE})
|
||||
set(CppUnit_LIBRARIES ${CppUnit_LIBRARY_RELEASE})
|
||||
endif()
|
||||
|
||||
# if only the debug version was found, set the release variable also to the debug version
|
||||
if(CppUnit_LIBRARY_DEBUG AND NOT CppUnit_LIBRARY_RELEASE)
|
||||
set(CppUnit_LIBRARY_RELEASE ${CppUnit_LIBRARY_DEBUG})
|
||||
set(CppUnit_LIBRARY ${CppUnit_LIBRARY_DEBUG})
|
||||
set(CppUnit_LIBRARIES ${CppUnit_LIBRARY_DEBUG})
|
||||
endif()
|
||||
|
||||
# If the debug & release library ends up being the same, omit the keywords
|
||||
if("${CppUnit_LIBRARY_RELEASE}" STREQUAL "${CppUnit_LIBRARY_DEBUG}")
|
||||
set(CppUnit_LIBRARY ${CppUnit_LIBRARY_RELEASE} )
|
||||
set(CppUnit_LIBRARIES ${CppUnit_LIBRARY_RELEASE} )
|
||||
endif()
|
||||
|
||||
if(CppUnit_LIBRARY)
|
||||
set(CppUnit_FOUND TRUE)
|
||||
else()
|
||||
set(CppUnit_FOUND FALSE)
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# Cache and set CppUnit_FOUND
|
||||
# ------------------------------------------------------------------------
|
||||
@@ -190,36 +256,65 @@ find_package_handle_standard_args(CppUnit
|
||||
VERSION_VAR CppUnit_VERSION
|
||||
)
|
||||
|
||||
if(CppUnit_FOUND)
|
||||
# Configure lib type. If XXX_USE_STATIC_LIBS, we always assume a static
|
||||
# lib is in use. If win32, we can't mark the import .libs as shared, so
|
||||
# these are always marked as UNKNOWN. Otherwise, infer from extension.
|
||||
set(CPPUNIT_LIB_TYPE UNKNOWN)
|
||||
if(CPPUNIT_USE_STATIC_LIBS)
|
||||
if(NOT CppUnit_FOUND)
|
||||
if(CppUnit_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Unable to find CppUnit")
|
||||
endif()
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Partition release/debug lib vars
|
||||
|
||||
set(CppUnit_RELEASE_LIBRARIES ${CppUnit_LIBRARY_RELEASE})
|
||||
get_filename_component(CppUnit_RELEASE_LIBRARY_DIRS ${CppUnit_RELEASE_LIBRARIES} DIRECTORY)
|
||||
set(CppUnit_DEBUG_LIBRARIES ${CppUnit_LIBRARY_DEBUG})
|
||||
get_filename_component(CppUnit_DEBUG_LIBRARY_DIRS ${CppUnit_DEBUG_LIBRARIES} DIRECTORY)
|
||||
set(CppUnit_LIBRARIES ${CppUnit_RELEASE_LIBRARIES})
|
||||
set(CppUnit_LIBRARY_DIRS ${CppUnit_RELEASE_LIBRARY_DIRS})
|
||||
set(CppUnit_INCLUDE_DIRS ${CppUnit_INCLUDE_DIR})
|
||||
|
||||
# Configure lib type. If XXX_USE_STATIC_LIBS, we always assume a static
|
||||
# lib is in use. If win32, we can't mark the import .libs as shared, so
|
||||
# these are always marked as UNKNOWN. Otherwise, infer from extension.
|
||||
set(CPPUNIT_LIB_TYPE UNKNOWN)
|
||||
if(CPPUNIT_USE_STATIC_LIBS)
|
||||
set(CPPUNIT_LIB_TYPE STATIC)
|
||||
elseif(UNIX)
|
||||
get_filename_component(_CPPUNIT_EXT ${CppUnit_LIBRARY_RELEASE} EXT)
|
||||
if(_CPPUNIT_EXT STREQUAL ".a")
|
||||
set(CPPUNIT_LIB_TYPE STATIC)
|
||||
elseif(UNIX)
|
||||
get_filename_component(_CPPUNIT_EXT ${CppUnit_LIBRARY} EXT)
|
||||
if(_CPPUNIT_EXT STREQUAL ".a")
|
||||
set(CPPUNIT_LIB_TYPE STATIC)
|
||||
elseif(_CPPUNIT_EXT STREQUAL ".so" OR
|
||||
_CPPUNIT_EXT STREQUAL ".dylib")
|
||||
set(CPPUNIT_LIB_TYPE SHARED)
|
||||
endif()
|
||||
elseif(_CPPUNIT_EXT STREQUAL ".so" OR
|
||||
_CPPUNIT_EXT STREQUAL ".dylib")
|
||||
set(CPPUNIT_LIB_TYPE SHARED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT TARGET CppUnit::cppunit)
|
||||
add_library(CppUnit::cppunit ${CPPUNIT_LIB_TYPE} IMPORTED)
|
||||
set_target_properties(CppUnit::cppunit PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS "${PC_CppUnit_CFLAGS_OTHER}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CppUnit_INCLUDE_DIRS}")
|
||||
|
||||
# Standard location
|
||||
set_target_properties(CppUnit::cppunit PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
|
||||
IMPORTED_LOCATION "${CppUnit_LIBRARY}")
|
||||
|
||||
# Release location
|
||||
if(EXISTS "${CppUnit_LIBRARY_RELEASE}")
|
||||
set_property(TARGET CppUnit::cppunit APPEND PROPERTY
|
||||
IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_target_properties(CppUnit::cppunit PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
|
||||
IMPORTED_LOCATION_RELEASE "${CppUnit_LIBRARY_RELEASE}")
|
||||
endif()
|
||||
|
||||
# Debug location
|
||||
if(EXISTS "${CppUnit_LIBRARY_DEBUG}")
|
||||
set_property(TARGET CppUnit::cppunit APPEND PROPERTY
|
||||
IMPORTED_CONFIGURATIONS DEBUG)
|
||||
set_target_properties(CppUnit::cppunit PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX"
|
||||
IMPORTED_LOCATION_DEBUG "${CppUnit_LIBRARY_DEBUG}")
|
||||
endif()
|
||||
|
||||
set(CppUnit_LIBRARIES ${CppUnit_LIBRARY})
|
||||
set(CppUnit_INCLUDE_DIRS ${CppUnit_INCLUDE_DIR})
|
||||
|
||||
get_filename_component(CppUnit_LIBRARY_DIRS ${CppUnit_LIBRARY} DIRECTORY)
|
||||
|
||||
if(NOT TARGET CppUnit::cppunit)
|
||||
add_library(CppUnit::cppunit ${CPPUNIT_LIB_TYPE} IMPORTED)
|
||||
set_target_properties(CppUnit::cppunit PROPERTIES
|
||||
IMPORTED_LOCATION "${CppUnit_LIBRARIES}"
|
||||
INTERFACE_COMPILE_OPTIONS "${PC_CppUnit_CFLAGS_OTHER}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CppUnit_INCLUDE_DIRS}"
|
||||
)
|
||||
endif()
|
||||
elseif(CppUnit_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Unable to find CppUnit")
|
||||
endif()
|
||||
|
||||
@@ -97,7 +97,7 @@ may be provided to tell this module where to look.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ may be provided to tell this module where to look.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ list(APPEND _JEMALLOC_LIBRARYDIR_SEARCH_DIRS
|
||||
|
||||
set(_JEMALLOC_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
if(JEMALLOC_USE_STATIC_LIBS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
|
||||
else()
|
||||
|
||||
@@ -87,7 +87,7 @@ may be provided to tell this module where to look.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ list(APPEND _LOG4CPLUS_LIBRARYDIR_SEARCH_DIRS
|
||||
|
||||
set(_LOG4CPLUS_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
if(LOG4CPLUS_USE_STATIC_LIBS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
|
||||
endif()
|
||||
|
||||
@@ -93,7 +93,7 @@ may be provided to tell this module where to look.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
|
||||
+53
-15
@@ -18,6 +18,7 @@ Use this module by invoking find_package with the form::
|
||||
# "pyopenvdb" for the python plugin
|
||||
# "openvdb_ax" for the OpenVDB AX extension
|
||||
# "openvdb_houdini" for the houdini plugin
|
||||
# "nanovdb" for the nanovdb extension
|
||||
)
|
||||
|
||||
IMPORTED Targets
|
||||
@@ -33,6 +34,8 @@ IMPORTED Targets
|
||||
The openvdb houdini library target.
|
||||
``OpenVDB::openvdb_ax``
|
||||
The openvdb_ax library target.
|
||||
``OpenVDB::nanovdb``
|
||||
The nanovdb library target.
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
@@ -104,7 +107,7 @@ may be provided to tell this module where to look.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
@@ -127,6 +130,7 @@ set(_OPENVDB_COMPONENT_LIST
|
||||
pyopenvdb
|
||||
openvdb_ax
|
||||
openvdb_houdini
|
||||
nanovdb
|
||||
)
|
||||
|
||||
if(OpenVDB_FIND_COMPONENTS)
|
||||
@@ -272,6 +276,16 @@ foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS})
|
||||
${CMAKE_INSTALL_INCLUDEDIR}
|
||||
include
|
||||
)
|
||||
elseif(${COMPONENT} STREQUAL "nanovdb")
|
||||
# Look for NanoVDB.h
|
||||
find_path(OpenVDB_${COMPONENT}_INCLUDE_DIR NanoVDB.h
|
||||
${_FIND_OPENVDB_ADDITIONAL_OPTIONS}
|
||||
PATHS ${_VDB_COMPONENT_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
${CMAKE_INSTALL_INCLUDEDIR}/nanovdb
|
||||
${CMAKE_INSTALL_INCLUDEDIR}
|
||||
include
|
||||
)
|
||||
endif()
|
||||
unset(_VDB_COMPONENT_SEARCH_DIRS)
|
||||
endforeach()
|
||||
@@ -343,7 +357,7 @@ list(REMOVE_DUPLICATES OPENVDB_PYTHON_PATH_SUFFIXES)
|
||||
list(REMOVE_DUPLICATES OPENVDB_LIB_PATH_SUFFIXES)
|
||||
|
||||
# Static library setup
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
if(OPENVDB_USE_STATIC_LIBS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
|
||||
endif()
|
||||
@@ -356,6 +370,7 @@ endif()
|
||||
set(OpenVDB_LIB_COMPONENTS "")
|
||||
|
||||
foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS})
|
||||
message("COMPONENT = " ${COMPONENT})
|
||||
set(LIB_NAME ${COMPONENT})
|
||||
|
||||
# Add in extra component paths
|
||||
@@ -386,10 +401,19 @@ foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS})
|
||||
endif()
|
||||
|
||||
list(APPEND OpenVDB_LIB_COMPONENTS ${OpenVDB_${COMPONENT}_LIBRARY})
|
||||
if(OpenVDB_${COMPONENT}_LIBRARY)
|
||||
set(OpenVDB_${COMPONENT}_FOUND TRUE)
|
||||
if(${COMPONENT} STREQUAL "nanovdb")
|
||||
# nanovdb is headers-only, no lib component
|
||||
if(OpenVDB_${COMPONENT}_INCLUDE_DIR)
|
||||
set(OpenVDB_${COMPONENT}_FOUND TRUE)
|
||||
else()
|
||||
set(OpenVDB_${COMPONENT}_FOUND FALSE)
|
||||
endif()
|
||||
else()
|
||||
set(OpenVDB_${COMPONENT}_FOUND FALSE)
|
||||
if(OpenVDB_${COMPONENT}_LIBRARY)
|
||||
set(OpenVDB_${COMPONENT}_FOUND TRUE)
|
||||
else()
|
||||
set(OpenVDB_${COMPONENT}_FOUND FALSE)
|
||||
endif()
|
||||
endif()
|
||||
unset(_VDB_COMPONENT_SEARCH_DIRS)
|
||||
endforeach()
|
||||
@@ -405,7 +429,6 @@ unset(_OPENVDB_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||
# ------------------------------------------------------------------------
|
||||
# Cache and set OPENVDB_FOUND
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(OpenVDB
|
||||
FOUND_VAR OpenVDB_FOUND
|
||||
@@ -438,7 +461,7 @@ if(NOT _OPENVDB_HAS_NEW_VERSION_HEADER)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT OpenVDB_FIND_QUIET)
|
||||
if(NOT OpenVDB_FIND_QUIETLY)
|
||||
if(NOT OpenVDB_ABI)
|
||||
message(WARNING "Unable to determine OpenVDB ABI version from OpenVDB "
|
||||
"installation. The library major version \"${OpenVDB_MAJOR_VERSION}\" "
|
||||
@@ -473,13 +496,13 @@ if(NOT OPENVDB_USE_STATIC_LIBS AND NOT Boost_USE_STATIC_LIBS)
|
||||
set(Boost_USE_STATIC_LIBS OFF)
|
||||
endif()
|
||||
|
||||
find_package(Boost REQUIRED COMPONENTS iostreams system)
|
||||
find_package(Boost REQUIRED COMPONENTS iostreams)
|
||||
|
||||
# Add deps for pyopenvdb
|
||||
# @todo track for numpy
|
||||
|
||||
if(pyopenvdb IN_LIST OpenVDB_FIND_COMPONENTS)
|
||||
find_package(PythonLibs REQUIRED)
|
||||
find_package(Python REQUIRED)
|
||||
|
||||
# Boost python handling - try and find both python and pythonXx (version suffixed).
|
||||
# Prioritize the version suffixed library, failing if neither exist.
|
||||
@@ -547,6 +570,10 @@ if(WIN32)
|
||||
list(APPEND OpenVDB_DEFINITIONS NOMINMAX)
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
list(APPEND OpenVDB_DEFINITIONS _USE_MATH_DEFINES)
|
||||
endif()
|
||||
|
||||
if(OpenVDB_ABI)
|
||||
# Newer version of OpenVDB defines this in version.h, but it is are also
|
||||
# provided here to maintain backwards compatibility with header include
|
||||
@@ -632,8 +659,8 @@ if(OpenVDB_USES_IMATH_HALF)
|
||||
if(WIN32)
|
||||
# @note OPENVDB_OPENEXR_STATICLIB is old functionality and should be removed
|
||||
if(OPENEXR_USE_STATIC_LIBS OR
|
||||
(${ILMBASE_LIB_TYPE} STREQUAL STATIC_LIBRARY) OR
|
||||
(${IMATH_LIB_TYPE} STREQUAL STATIC_LIBRARY))
|
||||
("${ILMBASE_LIB_TYPE}" STREQUAL "STATIC_LIBRARY") OR
|
||||
("${IMATH_LIB_TYPE}" STREQUAL "STATIC_LIBRARY"))
|
||||
list(APPEND OpenVDB_DEFINITIONS OPENVDB_OPENEXR_STATICLIB)
|
||||
endif()
|
||||
endif()
|
||||
@@ -648,10 +675,7 @@ endif()
|
||||
# namespaced headers are correctly prioritized. Otherwise other include paths
|
||||
# from shared installs (including houdini) may pull in the wrong headers
|
||||
|
||||
set(_OPENVDB_VISIBLE_DEPENDENCIES
|
||||
Boost::iostreams
|
||||
Boost::system
|
||||
)
|
||||
set(_OPENVDB_VISIBLE_DEPENDENCIES Boost::iostreams)
|
||||
|
||||
if(OpenVDB_USES_IMATH_HALF)
|
||||
list(APPEND _OPENVDB_VISIBLE_DEPENDENCIES $<TARGET_NAME_IF_EXISTS:IlmBase::Half> $<TARGET_NAME_IF_EXISTS:Imath::Imath>)
|
||||
@@ -797,5 +821,19 @@ if(OpenVDB_openvdb_ax_LIBRARY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# OpenVDB::nanovdb
|
||||
|
||||
if(OpenVDB_nanovdb_LIBRARY)
|
||||
if(NOT TARGET OpenVDB::nanovdb)
|
||||
add_library(OpenVDB::nanovdb INTERFACE IMPORTED)
|
||||
set_target_properties(OpenVDB::nanovdb PROPERTIES
|
||||
IMPORTED_LOCATION "${OpenVDB_nanovdb_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenVDB_nanovdb_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "OpenVDB::openvdb;"
|
||||
INTERFACE_COMPILE_FEATURES cxx_std_14
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
unset(_OPENVDB_VISIBLE_DEPENDENCIES)
|
||||
unset(_OPENVDB_HIDDEN_DEPENDENCIES)
|
||||
|
||||
+4
-3
@@ -93,7 +93,7 @@ may be provided to tell this module where to look.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ if(NOT DEFINED TBB_DEBUG_SUFFIX)
|
||||
endif()
|
||||
set(_TBB_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
if(TBB_USE_STATIC_LIBS)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
|
||||
endif()
|
||||
@@ -412,7 +412,8 @@ foreach(COMPONENT ${TBB_FIND_COMPONENTS})
|
||||
set_target_properties(TBB::${COMPONENT} PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS "${PC_Tbb_CFLAGS_OTHER}"
|
||||
INTERFACE_COMPILE_DEFINITIONS "${Tbb_${COMPONENT}_DEFINITIONS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Tbb_INCLUDE_DIR}")
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Tbb_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_DIRECTORIES "${Tbb_LIBRARY_DIRS}")
|
||||
|
||||
# Standard location
|
||||
set_target_properties(TBB::${COMPONENT} PROPERTIES
|
||||
|
||||
@@ -47,7 +47,7 @@ The following variables may be provided to tell this module where to look.
|
||||
# Find the glfw3 installation and use glfw's CMake to initialize
|
||||
# the glfw lib
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
set(_FIND_GLFW3_ADDITIONAL_OPTIONS "")
|
||||
if(DISABLE_CMAKE_SEARCH_PATHS)
|
||||
|
||||
@@ -75,8 +75,10 @@ may be provided to tell this module where to look.
|
||||
# Find the Houdini installation and use Houdini's CMake to initialize
|
||||
# the Houdini lib
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
# Include utility functions for version information
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/OpenVDBUtils.cmake)
|
||||
|
||||
set(_FIND_HOUDINI_ADDITIONAL_OPTIONS "")
|
||||
if(DISABLE_CMAKE_SEARCH_PATHS)
|
||||
@@ -331,14 +333,22 @@ endif()
|
||||
# Explicitly configure the OpenVDB ABI version depending on the Houdini
|
||||
# version.
|
||||
|
||||
if(Houdini_VERSION_MAJOR_MINOR VERSION_EQUAL 18.0)
|
||||
set(OPENVDB_HOUDINI_ABI 6)
|
||||
elseif(Houdini_VERSION_MAJOR_MINOR VERSION_EQUAL 18.5)
|
||||
if(Houdini_VERSION_MAJOR_MINOR VERSION_EQUAL 18.5)
|
||||
set(OPENVDB_HOUDINI_ABI 7)
|
||||
else()
|
||||
message(WARNING "Unknown version of Houdini, assuming OpenVDB ABI=8, "
|
||||
"but if this not correct, the CMake flag -DOPENVDB_HOUDINI_ABI=<N> can override this value.")
|
||||
set(OPENVDB_HOUDINI_ABI 8)
|
||||
find_file(_houdini_openvdb_version_file "openvdb/version.h"
|
||||
PATHS ${HOUDINI_INCLUDE_DIR}
|
||||
NO_DEFAULT_PATH)
|
||||
if(_houdini_openvdb_version_file)
|
||||
OPENVDB_VERSION_FROM_HEADER("${_houdini_openvdb_version_file}"
|
||||
ABI OPENVDB_HOUDINI_ABI)
|
||||
endif()
|
||||
unset(_houdini_openvdb_version_file)
|
||||
if(NOT OPENVDB_HOUDINI_ABI)
|
||||
message(WARNING "Unknown version of Houdini, assuming OpenVDB ABI=${OpenVDB_MAJOR_VERSION}, "
|
||||
"but if this not correct, the CMake flag -DOPENVDB_HOUDINI_ABI=<N> can override this value.")
|
||||
set(OPENVDB_HOUDINI_ABI ${OpenVDB_MAJOR_VERSION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
@@ -51,7 +51,7 @@ variables may be provided to tell this module where to look.
|
||||
# Find the Maya installation and use Maya's CMake to initialize
|
||||
# the Maya lib
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
|
||||
set(_FIND_MAYA_ADDITIONAL_OPTIONS "")
|
||||
|
||||
@@ -57,7 +57,7 @@ The following functions are provided:
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
|
||||
function(OPENVDB_GET_VERSION_DEFINE HEADER KEY VALUE)
|
||||
|
||||
@@ -16,7 +16,7 @@ existing from a previous run of cmake.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt")
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
# Copyright Contributors to the OpenVDB Project
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
#[=======================================================================[.rst:
|
||||
|
||||
FindNumPy
|
||||
-----------
|
||||
|
||||
Find NumPy include dirs and libraries.
|
||||
|
||||
Note that this is limited functionality which has been modified and
|
||||
back-ported from Kitware's CMake (3.14) python support module which
|
||||
finds NumPy exclusively by calling methods through a python interpreter.
|
||||
It's expected that python has already been found through CMake.
|
||||
|
||||
Use this module by invoking find_package with the form::
|
||||
|
||||
find_package(NumPy
|
||||
[version] [EXACT] # Minimum or EXACT version
|
||||
[REQUIRED] # Fail with error if NumPy is not found
|
||||
)
|
||||
|
||||
IMPORTED Targets
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``Python::NumPy``
|
||||
The NumPy library target.
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This will define the following variables:
|
||||
|
||||
``Python_NumPy_FOUND``
|
||||
True if the system has the NumPy library.
|
||||
``Python_NumPy_VERSION``
|
||||
The version of the NumPy library which was found.
|
||||
``Python_NumPy_INCLUDE_DIRS``
|
||||
Include directories needed to use NumPy.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
set(_PYTHON_PREFIX Python)
|
||||
|
||||
if(NOT ${_PYTHON_PREFIX}_EXECUTABLE)
|
||||
message(FATAL_ERROR "Unable to locate NumPy without first locating Python "
|
||||
"using find_package(). Alternatively, ensure that the variable "
|
||||
"${_PYTHON_PREFIX}_EXECUTABLE is set to your python executable.")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
|
||||
"from __future__ import print_function\ntry: import numpy; print(numpy.get_include())\nexcept:pass\n"
|
||||
RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
|
||||
OUTPUT_VARIABLE _${_PYTHON_PREFIX}_NumPy_PATH
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if (NOT _${_PYTHON_PREFIX}_RESULT)
|
||||
find_path(${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR
|
||||
NAMES "numpy/arrayobject.h" "numpy/numpyconfig.h"
|
||||
HINTS "${_${_PYTHON_PREFIX}_NumPy_PATH}"
|
||||
NO_DEFAULT_PATH)
|
||||
endif()
|
||||
if(${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR)
|
||||
set(${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
|
||||
set(${_PYTHON_PREFIX}_NumPy_FOUND TRUE)
|
||||
endif()
|
||||
if(${_PYTHON_PREFIX}_NumPy_FOUND)
|
||||
execute_process(
|
||||
COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
|
||||
"from __future__ import print_function\ntry: import numpy; print(numpy.__version__)\nexcept:pass\n"
|
||||
RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
|
||||
OUTPUT_VARIABLE _${_PYTHON_PREFIX}_NumPy_VERSION)
|
||||
if (NOT _${_PYTHON_PREFIX}_RESULT)
|
||||
set(${_PYTHON_PREFIX}_NumPy_VERSION "${_${_PYTHON_PREFIX}_NumPy_VERSION}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Note no found var here - ${_PYTHON_PREFIX}_NumPy_FOUND is used to match
|
||||
# later CMake functionality
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(NumPy
|
||||
REQUIRED_VARS
|
||||
${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR
|
||||
VERSION_VAR ${_PYTHON_PREFIX}_NumPy_VERSION
|
||||
)
|
||||
|
||||
if (${_PYTHON_PREFIX}_NumPy_FOUND AND NOT TARGET ${_PYTHON_PREFIX}::NumPy)
|
||||
add_library(${_PYTHON_PREFIX}::NumPy INTERFACE IMPORTED)
|
||||
set_property(TARGET ${_PYTHON_PREFIX}::NumPy
|
||||
PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
|
||||
endif()
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
# Build Types
|
||||
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}
|
||||
CACHE STRING [=[Choose the type of build. CMake natively supports the following options: None Debug Release
|
||||
RelWithDebInfo MinSizeRel. OpenVDB additionally supports the following sanitizers and tools:
|
||||
coverage tsan asan lsan msan ubsan]=]
|
||||
FORCE)
|
||||
|
||||
# Note that the thread, address and memory sanitizers are incompatible with each other
|
||||
set(EXTRA_BUILD_TYPES coverage tsan asan lsan msan ubsan)
|
||||
|
||||
# Set all build flags to empty (unless they have been provided)
|
||||
|
||||
# DebugNoInfo - An internal build type only used by the OpenVDB CI. no optimizations, no symbols, asserts enabled
|
||||
set(CMAKE_CXX_FLAGS_DebugNoInfo "" CACHE STRING "Flags used by the C++ compiler during DebugNoInfo builds.")
|
||||
|
||||
# Requires add_link_options from 3.13
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.13)
|
||||
if(${CMAKE_BUILD_TYPE} IN_LIST EXTRA_BUILD_TYPES)
|
||||
message(FATAL_ERROR "Build type ${CMAKE_BUILD_TYPE} requires CMake version 3.13 or higher.")
|
||||
endif()
|
||||
return()
|
||||
endif()
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
foreach(TYPE ${EXTRA_BUILD_TYPES})
|
||||
set(CMAKE_CXX_FLAGS_${U_TYPE} "" CACHE STRING "Flags used by the C++ compiler during ${TYPE} builds.")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_${U_TYPE} "" CACHE STRING "Flags used by the linker during ${TYPE} builds.")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_${U_TYPE} "" CACHE STRING "Flags used by the linker during ${TYPE} builds.")
|
||||
endforeach()
|
||||
|
||||
# Init generator options - we use generator expressions to allow builds with both
|
||||
# clang and GCC. Sanitizers are currently only configured for clang and GCC.
|
||||
# @todo from CMake 3.15, switch to comma list of CXX_COMPILER_ID.
|
||||
|
||||
# Coverage
|
||||
add_compile_options("$<$<CONFIG:COVERAGE>:--coverage>")
|
||||
add_link_options("$<$<CONFIG:COVERAGE>:--coverage>")
|
||||
|
||||
# ThreadSanitizer
|
||||
add_compile_options("$<$<AND:$<CONFIG:TSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=thread>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:TSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-g;-O1>")
|
||||
add_link_options("$<$<AND:$<CONFIG:TSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=thread>")
|
||||
|
||||
# AddressSanitize
|
||||
add_compile_options("$<$<AND:$<CONFIG:ASAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=address>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:ASAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fno-omit-frame-pointer;-g;-O1>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:ASAN>,$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize-address-use-after-scope;-fno-optimize-sibling-calls>")
|
||||
# -fsanitize-address-use-after-scope added in GCC 7
|
||||
add_compile_options("$<$<AND:$<CONFIG:ASAN>,$<CXX_COMPILER_ID:GNU>,$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,7.0.0>>:-fsanitize-address-use-after-scope>")
|
||||
add_link_options("$<$<AND:$<CONFIG:ASAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=address>")
|
||||
|
||||
# LeakSanitizer
|
||||
add_compile_options("$<$<AND:$<CONFIG:LSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=leak>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:LSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fno-omit-frame-pointer;-g;-O1>")
|
||||
add_link_options("$<$<AND:$<CONFIG:LSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=leak>")
|
||||
|
||||
# MemorySanitizer
|
||||
add_compile_options("$<$<AND:$<CONFIG:MSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=memory>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:MSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fno-omit-frame-pointer;-g;-O2>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:MSAN>,$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:--fno-optimize-sibling-calls;-fsanitize-memory-track-origins=2>")
|
||||
add_link_options("$<$<AND:$<CONFIG:MSAN>,$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=memory>")
|
||||
|
||||
# UndefinedBehaviour
|
||||
add_compile_options("$<$<AND:$<CONFIG:UBSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=undefined>")
|
||||
add_link_options("$<$<AND:$<CONFIG:UBSAN>,$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>>:-fsanitize=undefined>")
|
||||
@@ -0,0 +1,266 @@
|
||||
# Copyright Contributors to the OpenVDB Project
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
#[=======================================================================[
|
||||
|
||||
CXX and CMAKE_CXX options and definitions for OpenVDB build types
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
###############################################################################
|
||||
|
||||
# General CMake and CXX settings
|
||||
|
||||
if(FUTURE_MINIMUM_CMAKE_VERSION)
|
||||
if(${CMAKE_VERSION} VERSION_LESS ${FUTURE_MINIMUM_CMAKE_VERSION})
|
||||
message(DEPRECATION "Support for CMake versions < ${FUTURE_MINIMUM_CMAKE_VERSION} "
|
||||
"is deprecated and will be removed.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD ${MINIMUM_CXX_STANDARD} CACHE STRING
|
||||
"The C++ standard whose features are requested to build OpenVDB components." FORCE)
|
||||
elseif(CMAKE_CXX_STANDARD LESS ${MINIMUM_CXX_STANDARD})
|
||||
message(FATAL_ERROR "Provided C++ Standard is less than the supported minimum."
|
||||
"Required is at least \"${MINIMUM_CXX_STANDARD}\" (found ${CMAKE_CXX_STANDARD})")
|
||||
endif()
|
||||
if(OPENVDB_FUTURE_DEPRECATION AND FUTURE_MINIMUM_CXX_STANDARD)
|
||||
if(CMAKE_CXX_STANDARD LESS ${FUTURE_MINIMUM_CXX_STANDARD})
|
||||
message(DEPRECATION "C++ < 17 is deprecated and will be removed.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Configure MS Runtime
|
||||
|
||||
if(WIN32 AND CMAKE_MSVC_RUNTIME_LIBRARY)
|
||||
message(STATUS "CMAKE_MSVC_RUNTIME_LIBRARY set to target ${CMAKE_MSVC_RUNTIME_LIBRARY}")
|
||||
|
||||
# Configure Boost library varient on Windows
|
||||
if(NOT Boost_USE_STATIC_RUNTIME)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL MultiThreaded OR
|
||||
CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL MultiThreadedDebug)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT Boost_USE_DEBUG_RUNTIME)
|
||||
set(Boost_USE_DEBUG_RUNTIME OFF)
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL MultiThreadedDebugDLL OR
|
||||
CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL MultiThreadedDebug)
|
||||
set(Boost_USE_DEBUG_RUNTIME ON)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
|
||||
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
|
||||
|
||||
if(OPENVDB_ENABLE_RPATH)
|
||||
# Configure rpath for installation base on the following:
|
||||
# https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling
|
||||
set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
# @todo make relocatable?
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
|
||||
# For CMake's find Threads module which brings in pthread - This flag
|
||||
# forces the compiler -pthread flag vs -lpthread
|
||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
|
||||
###############################################################################
|
||||
|
||||
# Compiler version checks
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_CLANG_VERSION)
|
||||
message(FATAL_ERROR "Insufficient clang++ version. Minimum required is "
|
||||
"\"${MINIMUM_CLANG_VERSION}\". Found version \"${CMAKE_CXX_COMPILER_VERSION}\""
|
||||
)
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_GCC_VERSION)
|
||||
message(FATAL_ERROR "Insufficient g++ version. Minimum required is "
|
||||
"\"${MINIMUM_GCC_VERSION}\". Found version \"${CMAKE_CXX_COMPILER_VERSION}\""
|
||||
)
|
||||
endif()
|
||||
if(OPENVDB_FUTURE_DEPRECATION AND FUTURE_MINIMUM_GCC_VERSION)
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS FUTURE_MINIMUM_GCC_VERSION)
|
||||
message(DEPRECATION "Support for GCC versions < ${FUTURE_MINIMUM_GCC_VERSION} "
|
||||
"is deprecated and will be removed.")
|
||||
endif()
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_ICC_VERSION)
|
||||
message(FATAL_ERROR "Insufficient ICC version. Minimum required is "
|
||||
"\"${MINIMUM_ICC_VERSION}\". Found version \"${CMAKE_CXX_COMPILER_VERSION}\""
|
||||
)
|
||||
endif()
|
||||
if(OPENVDB_FUTURE_DEPRECATION AND FUTURE_MINIMUM_ICC_VERSION)
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS FUTURE_MINIMUM_ICC_VERSION)
|
||||
message(DEPRECATION "Support for ICC versions < ${FUTURE_MINIMUM_ICC_VERSION} "
|
||||
"is deprecated and will be removed.")
|
||||
endif()
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_MSVC_VERSION)
|
||||
message(FATAL_ERROR "Insufficient MSVC version. Minimum required is "
|
||||
"\"${MINIMUM_MSVC_VERSION}\". Found version \"${CMAKE_CXX_COMPILER_VERSION}\""
|
||||
)
|
||||
endif()
|
||||
if(OPENVDB_FUTURE_DEPRECATION AND FUTURE_MINIMUM_MSVC_VERSION)
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS FUTURE_MINIMUM_MSVC_VERSION)
|
||||
message(DEPRECATION "Support for MSVC versions < ${FUTURE_MINIMUM_MSVC_VERSION} "
|
||||
"is deprecated and will be removed.")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Unsupported CXX compiler ${CMAKE_CXX_COMPILER_ID}")
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
|
||||
# Increase the number of sections that an object file can contain
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/bigobj>")
|
||||
# Excludes APIs such as Cryptography, DDE, RPC, Shell, and Windows Sockets
|
||||
add_compile_definitions("$<$<CXX_COMPILER_ID:MSVC>:WIN32_LEAN_AND_MEAN>")
|
||||
# Disable non-secure CRT library function warnings
|
||||
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/
|
||||
# compiler-warning-level-3-c4996?view=vs-2019#unsafe-crt-library-functions
|
||||
add_compile_definitions("$<$<CXX_COMPILER_ID:MSVC>:_CRT_SECURE_NO_WARNINGS>")
|
||||
# Disable POSIX function name warnings
|
||||
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/
|
||||
# compiler-warning-level-3-c4996?view=vs-2019#posix-function-names
|
||||
add_compile_definitions("$<$<CXX_COMPILER_ID:MSVC>:_CRT_NONSTDC_NO_WARNINGS>")
|
||||
# If a user has explicitly requested a parallel build, configure this during CMake
|
||||
if(MSVC_MP_THREAD_COUNT AND MSVC_MP_THREAD_COUNT GREATER 1)
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/MP${MSVC_MP_THREAD_COUNT}>")
|
||||
endif()
|
||||
|
||||
if(OPENVDB_CXX_STRICT)
|
||||
message(STATUS "Configuring CXX warnings")
|
||||
# Clang/AppleClang
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>:-Werror>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>:-Wall>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>:-Wextra>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>:-Wconversion>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>:-Wno-sign-conversion>")
|
||||
# GNU
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Werror>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wall>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wextra>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-pedantic>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wcast-align>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wcast-qual>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wconversion>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wdisabled-optimization>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Woverloaded-virtual>")
|
||||
else()
|
||||
# NO OPENVDB_CXX_STRICT, suppress some warnings
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
message(STATUS "Suppressing some noisy MSVC CXX warnings, "
|
||||
"set OPENVDB_CXX_STRICT=ON to re-enable them.")
|
||||
endif()
|
||||
# Conversion from int64_t to long
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/wd4244>")
|
||||
# It's not possible to use STL types in DLL interfaces in a portable and
|
||||
# reliable way so disable this warning
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/wd4251>")
|
||||
# Conversion from size_t to uLong
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/wd4267>")
|
||||
# Non dll-interface class used as base for dll-interface class
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/wd4275>")
|
||||
# Truncation from 'int' to 'bool'
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/wd4305>")
|
||||
endif()
|
||||
|
||||
if(USE_COLORED_OUTPUT)
|
||||
message(STATUS "Enabling colored compiler output")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>:-fcolor-diagnostics>")
|
||||
add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-fdiagnostics-color=always>")
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
|
||||
# Build Types
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}
|
||||
CACHE STRING [=[Choose the type of build. CMake natively supports the following options: None Debug Release
|
||||
RelWithDebInfo MinSizeRel. OpenVDB additionally supports the following sanitizers and tools:
|
||||
coverage tsan asan lsan msan ubsan]=]
|
||||
FORCE)
|
||||
|
||||
if(CMAKE_BUILD_TYPE EQUAL coverage)
|
||||
# use .gcno extension instead of .cc.gcno
|
||||
# @note This is an undocumented internal cmake var and does not work
|
||||
# with multi config generators
|
||||
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)
|
||||
endif()
|
||||
|
||||
# Note that the thread, address and memory sanitizers are incompatible with each other
|
||||
set(EXTRA_BUILD_TYPES coverage tsan asan lsan msan ubsan)
|
||||
|
||||
# Set all build flags to empty (unless they have been provided)
|
||||
|
||||
# DebugNoInfo - An internal build type only used by the OpenVDB CI. no optimizations, no symbols, asserts enabled
|
||||
set(CMAKE_CXX_FLAGS_DebugNoInfo "" CACHE STRING "Flags used by the C++ compiler during DebugNoInfo builds.")
|
||||
|
||||
foreach(TYPE ${EXTRA_BUILD_TYPES})
|
||||
set(CMAKE_CXX_FLAGS_${U_TYPE} "" CACHE STRING "Flags used by the C++ compiler during ${TYPE} builds.")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_${U_TYPE} "" CACHE STRING "Flags used by the linker during ${TYPE} builds.")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_${U_TYPE} "" CACHE STRING "Flags used by the linker during ${TYPE} builds.")
|
||||
endforeach()
|
||||
|
||||
# Init generator options - we use generator expressions to allow builds with both
|
||||
# clang and GCC. Sanitizers are currently only configured for clang and GCC.
|
||||
|
||||
# Coverage
|
||||
add_compile_options("$<$<AND:$<CONFIG:COVERAGE>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:--coverage>")
|
||||
add_link_options("$<$<AND:$<CONFIG:COVERAGE>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:--coverage>")
|
||||
|
||||
# ThreadSanitizer
|
||||
add_compile_options("$<$<AND:$<CONFIG:TSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fsanitize=thread>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:TSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-g;-O1>")
|
||||
add_link_options("$<$<AND:$<CONFIG:TSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fsanitize=thread>")
|
||||
|
||||
# AddressSanitize
|
||||
add_compile_options("$<$<AND:$<CONFIG:ASAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fsanitize=address>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:ASAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fno-omit-frame-pointer;-g;-O1>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:ASAN>,$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>>:-fsanitize-address-use-after-scope;-fno-optimize-sibling-calls>")
|
||||
# -fsanitize-address-use-after-scope added in GCC 7
|
||||
add_compile_options("$<$<AND:$<CONFIG:ASAN>,$<COMPILE_LANG_AND_ID:CXX,GNU>,$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,7.0.0>>:-fsanitize-address-use-after-scope>")
|
||||
add_link_options("$<$<AND:$<CONFIG:ASAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fsanitize=address>")
|
||||
|
||||
# LeakSanitizer
|
||||
add_compile_options("$<$<AND:$<CONFIG:LSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fsanitize=leak>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:LSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fno-omit-frame-pointer;-g;-O1>")
|
||||
add_link_options("$<$<AND:$<CONFIG:LSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fsanitize=leak>")
|
||||
|
||||
# MemorySanitizer
|
||||
add_compile_options("$<$<AND:$<CONFIG:MSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fsanitize=memory>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:MSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fno-omit-frame-pointer;-g;-O2>")
|
||||
add_compile_options("$<$<AND:$<CONFIG:MSAN>,$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>>:--fno-optimize-sibling-calls;-fsanitize-memory-track-origins=2>")
|
||||
add_link_options("$<$<AND:$<CONFIG:MSAN>,$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>>:-fsanitize=memory>")
|
||||
|
||||
# UndefinedBehaviour
|
||||
add_compile_options("$<$<AND:$<CONFIG:UBSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fsanitize=undefined>")
|
||||
add_link_options("$<$<AND:$<CONFIG:UBSAN>,$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>>:-fsanitize=undefined>")
|
||||
|
||||
# CMAKE_BUILD_TYPE is ignored for multi config generators i.e. MSVS
|
||||
|
||||
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(NOT _isMultiConfig)
|
||||
message(STATUS "CMake Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# Copyright Contributors to the OpenVDB Project
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
#[=======================================================================[
|
||||
|
||||
Current and future version requirements for all OpenVDB dependencies,
|
||||
including compilers, language features and OpenVDB's ABI.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
###############################################################################
|
||||
|
||||
# Configure minimum version requirements - some are treated specially and fall
|
||||
# outside of the DISABLE_DEPENDENCY_VERSION_CHECKS catch
|
||||
set(MINIMUM_CXX_STANDARD 14)
|
||||
|
||||
# @note ABI always enforced so the correct deprecation messages are available.
|
||||
# OPENVDB_USE_DEPRECATED_ABI_<VERSION> should be used to circumvent this
|
||||
set(MINIMUM_OPENVDB_ABI_VERSION 7)
|
||||
set(FUTURE_MINIMUM_OPENVDB_ABI_VERSION 9)
|
||||
set(FUTURE_OPENVDB_ABI_VERSION 10)
|
||||
|
||||
if(NOT DISABLE_DEPENDENCY_VERSION_CHECKS)
|
||||
# @note Currently tracking CY2020 of the VFX platform where available
|
||||
set(MINIMUM_GCC_VERSION 6.3.1)
|
||||
set(MINIMUM_CLANG_VERSION 3.8)
|
||||
set(MINIMUM_ICC_VERSION 17)
|
||||
set(MINIMUM_MSVC_VERSION 19.10)
|
||||
|
||||
set(MINIMUM_BOOST_VERSION 1.70)
|
||||
set(MINIMUM_ILMBASE_VERSION 2.4)
|
||||
set(MINIMUM_OPENEXR_VERSION 2.4)
|
||||
set(MINIMUM_ZLIB_VERSION 1.2.7)
|
||||
set(MINIMUM_TBB_VERSION 2019.0)
|
||||
set(MINIMUM_LLVM_VERSION 7.0.0)
|
||||
set(MINIMUM_BLOSC_VERSION 1.5.0)
|
||||
|
||||
set(MINIMUM_PYTHON_VERSION 2.7) # @warning should be 3.7.x, but H18.5+ can still be used with 2.7.x
|
||||
set(MINIMUM_NUMPY_VERSION 1.17.0)
|
||||
|
||||
set(MINIMUM_GOOGLETEST_VERSION 1.10)
|
||||
set(MINIMUM_GLFW_VERSION 3.1)
|
||||
set(MINIMUM_LOG4CPLUS_VERSION 1.1.2)
|
||||
set(MINIMUM_HOUDINI_VERSION 18.5)
|
||||
|
||||
# These always promote warnings rather than errors
|
||||
set(MINIMUM_MAYA_VERSION 2017)
|
||||
set(MINIMUM_DOXYGEN_VERSION 1.8.8)
|
||||
endif()
|
||||
|
||||
# VFX 21 deprecations to transition to MINIMUM_* variables in OpenVDB 10.0.0
|
||||
|
||||
set(FUTURE_MINIMUM_GCC_VERSION 9.3.1)
|
||||
set(FUTURE_MINIMUM_ICC_VERSION 19)
|
||||
# set(FUTURE_MINIMUM_MSVC_VERSION 19.10)
|
||||
|
||||
set(FUTURE_MINIMUM_CXX_STANDARD 17)
|
||||
set(FUTURE_MINIMUM_CMAKE_VERSION 3.18)
|
||||
#set(FUTURE_MINIMUM_ILMBASE_VERSION 2.4) # Minimum is already 2.4
|
||||
#set(FUTURE_MINIMUM_OPENEXR_VERSION 2.4) # Minimum is already 2.4
|
||||
set(FUTURE_MINIMUM_BOOST_VERSION 1.73)
|
||||
set(FUTURE_MINIMUM_BLOSC_VERSION 1.17.0)
|
||||
set(FUTURE_MINIMUM_TBB_VERSION 2020.2)
|
||||
set(FUTURE_MINIMUM_PYTHON_VERSION 3.7)
|
||||
set(FUTURE_MINIMUM_NUMPY_VERSION 1.19.0)
|
||||
set(FUTURE_MINIMUM_HOUDINI_VERSION 19.0)
|
||||
set(FUTURE_MINIMUM_LLVM_VERSION 10.0.0)
|
||||
@@ -0,0 +1,30 @@
|
||||
#################################################################################
|
||||
## This file is loaded by the Undefined Behaviour Sanitizer build for the unit ##
|
||||
## tests. It can be used to ignore various errors reported by the sanitizer. ##
|
||||
## This is especially useful with upstream issues (e.g. boost/tbb). For help ##
|
||||
## defining suppression rules, see: ##
|
||||
## https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html ##
|
||||
## The build is configured with CMAKE_BUILD_TYPE=ubsan. ##
|
||||
#################################################################################
|
||||
|
||||
##### Upstream #####
|
||||
|
||||
# Lots of warnings from TBB, ignore them
|
||||
alignment:tbb/concurrent_hash_map.h
|
||||
vptr:tbb/parallel_reduce.h
|
||||
vptr:tbb/task.h
|
||||
|
||||
##### OpenVDB #####
|
||||
|
||||
# The sOn/sOff static bool data held on the LeaffBuff<bool> objects can be
|
||||
# initialised to arbitrary true/false values. See the note in LeafBuffer.h
|
||||
enum:openvdb/tools/Activate.h
|
||||
# Some 2s complement tests, ignore the negative shifts
|
||||
# @todo Should address these
|
||||
shift-base:TestMultiResGrid.cc
|
||||
shift-base:openvdb/math/Coord.h
|
||||
|
||||
##### OpenVDB AX #####
|
||||
|
||||
# Ignore overflows reported from old OpenSimplexNoise
|
||||
signed-integer-overflow:openvdb_ax/math/OpenSimplexNoise.cc
|
||||
+41
-1
@@ -7,7 +7,7 @@
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(OpenVDBDocs LANGUAGES NONE)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
@@ -21,6 +21,7 @@ include(GNUInstallDirs)
|
||||
# all documentation is included.
|
||||
option(OPENVDB_DOXYGEN_AX "Build AX documentation" ON)
|
||||
option(OPENVDB_DOXYGEN_HOUDINI "Build Houdini documentation" ON)
|
||||
option(OPENVDB_DOXYGEN_NANOVDB "Build NanoVDB documentation" ON)
|
||||
option(OPENVDB_DOXYGEN_INTERNAL [=[
|
||||
Enable documentation of methods and classes which have been explicitly marked as internal
|
||||
]=] OFF)
|
||||
@@ -84,11 +85,13 @@ set(DOXYGEN_FULL_PATH_NAMES YES)
|
||||
set(DOXYGEN_STRIP_FROM_PATH
|
||||
"${CMAKE_SOURCE_DIR}/openvdb"
|
||||
"${CMAKE_SOURCE_DIR}/openvdb_ax"
|
||||
"${CMAKE_SOURCE_DIR}/nanovdb"
|
||||
"${CMAKE_SOURCE_DIR}/openvdb_houdini"
|
||||
"${CMAKE_SOURCE_DIR}")
|
||||
set(DOXYGEN_STRIP_FROM_INC_PATH
|
||||
"${CMAKE_SOURCE_DIR}/openvdb"
|
||||
"${CMAKE_SOURCE_DIR}/openvdb_ax"
|
||||
"${CMAKE_SOURCE_DIR}/nanovdb"
|
||||
"${CMAKE_SOURCE_DIR}/openvdb_houdini")
|
||||
|
||||
# Shows which source files generated the respected doxygen docs
|
||||
@@ -221,6 +224,43 @@ if(OPENVDB_DOXYGEN_AX)
|
||||
openvdb_ax/openvdb_ax/test)
|
||||
endif()
|
||||
|
||||
if(OPENVDB_DOXYGEN_NANOVDB)
|
||||
list(APPEND DOXYGEN_ENABLED_SECTIONS "NANOVDB")
|
||||
|
||||
list(APPEND DOXY_FILES
|
||||
doc/nanovdb/doc.md
|
||||
doc/nanovdb/FAQ.md
|
||||
doc/nanovdb/SourceTree.md
|
||||
doc/nanovdb/HowToBuild.md
|
||||
doc/nanovdb/HelloWorld.md
|
||||
nanovdb/nanovdb
|
||||
nanovdb/nanovdb/util
|
||||
nanovdb/nanovdb/cmd/convert
|
||||
nanovdb/nanovdb/cmd/print
|
||||
nanovdb/nanovdb/cmd/validate
|
||||
nanovdb/nanovdb/examples/benchmark
|
||||
nanovdb/nanovdb/examples/ex_bump_pool_buffer
|
||||
nanovdb/nanovdb/examples/ex_collide_level_set
|
||||
nanovdb/nanovdb/examples/ex_make_custom_nanovdb
|
||||
nanovdb/nanovdb/examples/ex_make_funny_nanovdb
|
||||
nanovdb/nanovdb/examples/ex_make_nanovdb_sphere
|
||||
nanovdb/nanovdb/examples/ex_make_typed_grids
|
||||
nanovdb/nanovdb/examples/ex_map_pool_buffer
|
||||
nanovdb/nanovdb/examples/ex_modify_nanovdb_thrust
|
||||
nanovdb/nanovdb/examples/ex_openvdb_to_nanovdb
|
||||
nanovdb/nanovdb/examples/ex_openvdb_to_nanovdb_accessor
|
||||
nanovdb/nanovdb/examples/ex_openvdb_to_nanovdb_cuda
|
||||
nanovdb/nanovdb/examples/ex_raytrace_fog_volume
|
||||
nanovdb/nanovdb/examples/ex_raytrace_level_set
|
||||
nanovdb/nanovdb/examples/ex_read_nanovdb_sphere
|
||||
nanovdb/nanovdb/examples/ex_read_nanovdb_sphere_accessor
|
||||
nanovdb/nanovdb/examples/ex_read_nanovdb_sphere_accessor_cuda
|
||||
nanovdb/nanovdb/examples/ex_util
|
||||
nanovdb/nanovdb/examples/ex_vox_to_nanovdb
|
||||
nanovdb/nanovdb/examples/ex_write_nanovdb_grids
|
||||
nanovdb/nanovdb/unittest)
|
||||
endif()
|
||||
|
||||
set(DOXYGEN_VERBATIM_VARS DOXYGEN_ALIASES DOXYGEN_PREDEFINED)
|
||||
|
||||
# Always add to build target (can't use USE_STAMP_FILE as we include
|
||||
|
||||
+13
-5
@@ -84,12 +84,12 @@ given FindModule e.g. `FindBlosc.cmake`:
|
||||
path on first runs of CMake (i.e. these variables are not
|
||||
[cached](https://cmake.org/cmake/help/latest/command/set.html#set-cache-entry)).
|
||||
They are listed in priority order. Note that the prefix is always capitalized.
|
||||
- @b XXX_INCLUDEDIR / @b XXX_LIBRARYDIR - Preferred include and library
|
||||
directories
|
||||
- @b Xxx_ROOT - Preferred installation prefix. The given dependency is
|
||||
expected to follow a folder structure `Xxx_ROOT/include` and `Xxx_ROOT/lib`
|
||||
exist. Note that unlike the above, this is the case matching name of the
|
||||
find package .i.e. Blosc_ROOT, IlmBase_ROOT, TBB_ROOT etc.
|
||||
- @b XXX_INCLUDEDIR / @b XXX_LIBRARYDIR - Preferred include and library
|
||||
directories
|
||||
- @b SYSTEM_LIBRARY_PATHS - A list of paths appended to all include and lib
|
||||
searches.
|
||||
- @b XXX_USE_STATIC_LIBS - Only search for static libraries for the given
|
||||
@@ -154,6 +154,9 @@ for this:
|
||||
that were created using blosc compression. This includes OpenVDB files from
|
||||
Houdini.
|
||||
|
||||
See the note in the [known issues list](@ref depKnownIssues) regarding supported
|
||||
versions of blosc.
|
||||
|
||||
@subsection buildZLibSupport ZLIB Support
|
||||
|
||||
ZLIB is an optional dependency of all OpenVDB components. The documented build
|
||||
@@ -188,6 +191,10 @@ OpenVDB AX Library | The OpenVDB AX library
|
||||
OpenVDB AX Binary | Command line binary for running OpenVDB AX code | OPENVDB_BUILD_AX_BINARIES | OFF |
|
||||
OpenVDB AX Grammar | Allows for re-generation of AX grammar, typically not required | OPENVDB_BUILD_AX_GRAMMAR | OFF |
|
||||
OpenVDB AX Unit Tests | OpenVDB AX's Unit Test suite | OPENVDB_BUILD_AX_UNITTESTS | OFF |
|
||||
NanoVDB | NanoVDB headers | OPENVDB_BUILD_NANOVDB | OFF |
|
||||
NanoVDB Tools | NanoVDB command line tools | NANOVDB_BUILD_TOOLS | OFF |
|
||||
NanoVDB Examples | NanoVDB example binaries and benchmarks | NANOVDB_BUILD_EXAMPLES / NANOVDB_BUILD_BENCHMARK | OFF / OFF |
|
||||
NanoVDB Unit Tests | NanoVDB Unit Test suite | NANOVDB_BUILD_UNITTESTS | OFF |
|
||||
Documentation | The OpenVDB doxygen documentation | OPENVDB_BUILD_DOCS | OFF |
|
||||
|
||||
|
||||
@@ -233,6 +240,7 @@ DCC | Supported Version | OpenVDB ABI |
|
||||
-------- | ----------------- | ----------- |
|
||||
Houdini | 18.0 | 6 |
|
||||
Houdini | 18.5 | 7 |
|
||||
Houdini | 19.0 | 8 |
|
||||
Maya | 2017 | Any |
|
||||
Maya | 2018 | Any |
|
||||
Maya | 2019 | Any |
|
||||
@@ -251,7 +259,7 @@ Package | Description
|
||||
-------------- | --------------------------------------------------------------- | ------------------ |
|
||||
CMake | Cross-platform family of tools designed to help build software | All |
|
||||
C++14 Compiler | Matching Houdini compiler and version | All |
|
||||
Boost | Components: system, iostreams, python, thread | All |
|
||||
Boost | Components: iostreams, python, thread | All |
|
||||
GoogleTest | A unit testing framework module for C++ | Unit Tests |
|
||||
CppUnit | A unit testing framework module for C++ | Unit Tests (AX) |
|
||||
GLFW | Simple API for OpenGL development | OpenVDB View |
|
||||
@@ -340,7 +348,7 @@ Package | Description
|
||||
-------------- | --------------------------------------------------------------- | -------------------------------- |
|
||||
CMake | Cross-platform family of tools designed to help build software | All |
|
||||
C++14 Compiler | Matching Houdini compiler and version | All |
|
||||
Boost | Components: system, iostreams, python, thread | All |
|
||||
Boost | Components: iostreams, python, thread | All |
|
||||
ZLIB | Compression library for disk serialization compression | All |
|
||||
Blosc | Recommended dependency for improved disk compression | All* |
|
||||
GoogleTest | A unit testing framework module for C++ | Unit Tests |
|
||||
@@ -508,7 +516,7 @@ You can add the below CMake snippet to your main `CMakeLists.txt` to bring in
|
||||
OpenVDB as a dependency:
|
||||
|
||||
@code{.cmake}
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
list(APPEND CMAKE_MODULE_PATH "/location/of/openvdb/install/lib/cmake/OpenVDB")
|
||||
find_package(OpenVDB REQUIRED)
|
||||
target_link_libraries(myapp OpenVDB::openvdb)
|
||||
|
||||
+178
-18
@@ -2,27 +2,76 @@
|
||||
|
||||
@page changes Release Notes
|
||||
|
||||
@htmlonly <a name="v9_0_0_changes"></a>@endhtmlonly
|
||||
@htmlonly <a name="v9_0_1_changes"></a>@endhtmlonly
|
||||
@par
|
||||
<B>Version 9.0.0</B> - <I>In development</I>
|
||||
<B>Version 9.0.1</B> - <I>In Development</I>
|
||||
|
||||
@par
|
||||
ABI changes:
|
||||
- Added transient data to the RootNode, InternalNode and LeafNode.
|
||||
|
||||
|
||||
@htmlonly <a name="v8_2_0_changes"></a>@endhtmlonly
|
||||
@par
|
||||
<B>Version 8.2.0</B> - <I>In development</I>
|
||||
Bug Fixes:
|
||||
- Minor fix to move assignment operator in nanovdb/util/HostBuffer.h.
|
||||
This could potentially be a problem on Windows debug builds (unconfirmed).
|
||||
- Minor fix to range in openvdb/tools/LevelSetSphere.h. This could result
|
||||
in data races for multi-threaded execution (unconfirmed) [Reported by Tommy Hinks]
|
||||
- Fixed a bug with Tree::combineExtended which wouldn't propagate the resulting active state when a destination tile overlapped a source child node. [Reported by @frapit]
|
||||
- Fix unit tests failures with Blosc versions >= 1.19.0.
|
||||
|
||||
@par
|
||||
New features:
|
||||
- Added tools::countActiveLeafVoxels(), tools::countInactiveVoxels(),
|
||||
tools::countInactiveLeafVoxels() and tools::activeTiles() to perform
|
||||
multi-threaded counting. The Tree methods now use these implementations.
|
||||
- Added support for AMD's HIP API in NanoVDB [Contributed by Blender Foundation]
|
||||
- Added bindings mechanism to AX to allow differing data and AX attribute names (@) in Point and Volume executables.
|
||||
- Added support for OpenVDB AX on Windows.
|
||||
|
||||
@par
|
||||
Improvements:
|
||||
- Added a --thread [n] argument to the vdb_ax binary.
|
||||
- Added a --copy-file-metadata option to vdb_ax. This behaviour is now off by default.
|
||||
- Added support for multiple input files with the vdb_ax binary using -i. Positional arguments as input files are deprecated.
|
||||
- Added tools::minMax() which supports multithreaded evaluation of active minimum and maximum values. Grid::evalMinMax() has been deprecated. [Contributed by Greg Hurst]
|
||||
|
||||
@par
|
||||
Build:
|
||||
- Regenerated AX grammar with Flex 2.6.4 and Bison 3.8.2.
|
||||
- Improved locating NumPy in CMake when multiple python versions are installed.
|
||||
- Fixed an issue which could report Python as missing when using CMake 3.18 and later on some systems. [Reported by Sam James]
|
||||
|
||||
@par
|
||||
Houdini:
|
||||
- Added Attribute Bindings to AX SOP to allow differently named AX attributes (@) and target point attributes/volumes.
|
||||
- Fix race condition in OpenVDB Merge SOP that could cause crashes
|
||||
or merged VDBs to not be deleted.
|
||||
|
||||
@htmlonly <a name="v9_0_0_changes"></a>@endhtmlonly
|
||||
@par
|
||||
<B>Version 9.0.0</B> - <I>October 29, 2021</I>
|
||||
|
||||
@par
|
||||
<BLOCKQUOTE>
|
||||
This version introduces ABI changes relative to older major releases, so to
|
||||
preserve ABI compatibility it might be necessary to define the macro
|
||||
<TT>OPENVDB_ABI_VERSION_NUMBER=</TT><I>N</I>, where, for example,
|
||||
<I>N</I> is 7 for Houdini 18.5 and 8 for Houdini 19.0.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
@par
|
||||
<BLOCKQUOTE>
|
||||
Official release of NanoVDB, which for the first time offers GPU support for
|
||||
static sparse volumes in OpenVDB. See the
|
||||
<A HREF="https://academysoftwarefoundation.github.io/openvdb/NanoVDB_MainPage.html">documentation</A>
|
||||
for details.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
@par
|
||||
New features:
|
||||
- Faster build times from support for explicit template instantiation,
|
||||
which is enabled by default for most of the tools.
|
||||
- Added support for OpenEXR 3 and TBB 2021.
|
||||
- Added transient data to the RootNode, InternalNode, and LeafNode.
|
||||
|
||||
@par
|
||||
Improvements:
|
||||
- Added tools::countActiveLeafVoxels(), tools::countInactiveVoxels(),
|
||||
tools::countInactiveLeafVoxels() and tools::activeTiles() to perform
|
||||
multi-threaded counting. The Tree methods now use these implementations.
|
||||
- Moved from the deprecated TBB task scheduler to TBB arenas. Various
|
||||
methods now respect the TBB arena state they were invoked from.
|
||||
- Introduced a new thread/Threading.h header to consolidate calls to
|
||||
@@ -33,11 +82,120 @@ Improvements:
|
||||
hue, saturation and value inputs to RGB values and vice-versa.
|
||||
- PointDataGrid conversion can now be performed using 32-bit float arrays.
|
||||
- Improved support for size_t grid types on systems where size_t is a unique
|
||||
type
|
||||
type.
|
||||
[Contributed by Brecht Van Lommel]
|
||||
- Minor performance improvements to dilation calls in fast sweeping algorithms
|
||||
- Add support for dilation in one direction and extending a field in one
|
||||
direction
|
||||
direction in fast sweeping algorithms.
|
||||
- Added PNG support to vdb_render which can be enabled with during CMake with
|
||||
-DUSE_PNG=ON.
|
||||
- Explicit template instantiation has been enabled by default for most of the
|
||||
tools. This pre-compiles template instantiations into the core library to
|
||||
reduce the time spent compiling code in downstream libraries or applications.
|
||||
- Added a python binding for OpenVDB AX which allows you to invoke accelerated
|
||||
AX code from the python module.
|
||||
|
||||
@par
|
||||
Bug Fixes:
|
||||
- Fixed a bug where ax::run() would crash if it could not parse a single statement.
|
||||
|
||||
@par
|
||||
ABI changes:
|
||||
- Added transient data to the RootNode, InternalNode, and LeafNode.
|
||||
|
||||
@par
|
||||
API changes:
|
||||
- DynamicNodeManager can now set one grain size for threading across leaf nodes
|
||||
and another for threading across non-leaf nodes.
|
||||
- StringGrid and StringTrees are deprecated.
|
||||
- The NullInterrupter is now a virtual base class to help reduce compile-time
|
||||
instantiation cost.
|
||||
|
||||
@par
|
||||
Houdini:
|
||||
- Fix crash in VDB Combine in Copy B mode if the second input has
|
||||
more VDBs than the first.
|
||||
- VDB Vector Merge SOP is now VDB Vector From Scalar SOP to distinguish
|
||||
it from the VDB Merge SOP. It keeps the same internal name so this
|
||||
is merely a label change.
|
||||
- Add option to pass in OPENVDB_DSO_NAMES to CMake to configure which Houdini
|
||||
DSOs are compiled.
|
||||
- VDB Activate SOP now has an option for the expansion pattern to use
|
||||
for dilation.
|
||||
- The label for Voxels to Expand is now Expand Voxels to match Houdini.
|
||||
- Fix bug to allow VDB LOD SOPs to be chained together.
|
||||
- SOP Extrapolate supports dilation in one direction and extending a field in
|
||||
one (domain) direction.
|
||||
- The default OpenVDB ABI is now 8 for Houdini versions > 18.5.
|
||||
- VDB Visualize Tree SOP is now multi-threaded and provides slicing and color
|
||||
remapping.
|
||||
- A new HoudiniInterrupter has been added that derives from the NullInterrupter
|
||||
and the Interrupter is now deprecated. All the SOPs have been updated to use
|
||||
the new HoudiniInterrupter.
|
||||
- Add a sanitizer in SOP OpenVDB Extrapolate when expanding a narrow-band
|
||||
level-set with a dilation value of 0, which will result in no operation.
|
||||
|
||||
@par
|
||||
Build:
|
||||
- Added support for TBB 2021.
|
||||
- Enabled the OPENVDB_FUTURE_DEPRECATION variable by default to warn on
|
||||
upcoming deprecations.
|
||||
- Introduced a OPENVDB_DOXYGEN_INTERNAL CMake variable which is ON by
|
||||
default and removes the majority of internal namespaces from the
|
||||
generated doxygen.
|
||||
- Improved the doxygen deprecation listings, folder layouts and fixes
|
||||
issues when using later versions of doxygen.
|
||||
- Build fixes for MinGW on Windows.
|
||||
[Contributed by Brecht Sanders]
|
||||
- Added support for OpenEXR 3.
|
||||
[Contributed by Cary Phillips]
|
||||
- Added an OPENVDB_NAMESPACE_SUFFIX CMake string option which provides the
|
||||
ability to customise the VDB namespace.
|
||||
- The Python Module now appends the base directory defined by Python_SITELIB
|
||||
to the default install path (typically dist-packages or site-packages).
|
||||
[Contributed by Ignacio Vizzo]
|
||||
- As of this release, VFX Reference Platform 2019 is no longer supported.
|
||||
CMake now issues deprecation warnings for 2020 VFX Reference Platform
|
||||
version dependencies.
|
||||
- Build fixes for OpenVDB AX with C++17 and greater.
|
||||
- Bumped the new blosc version future minimum to 1.17.0.
|
||||
- OpenEXR is now optional for vdb_render. It can be enabled with
|
||||
-DUSE_EXR=ON.
|
||||
|
||||
|
||||
@htmlonly <a name="v8_2_0_changes"></a>@endhtmlonly
|
||||
@par
|
||||
<B>Version 8.2.0</B> - <I>November 24, 2021</I>
|
||||
|
||||
@par
|
||||
<BLOCKQUOTE>
|
||||
Added support for TBB 2021.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
@par
|
||||
<BLOCKQUOTE>
|
||||
Added support for OpenEXR 3. This is contributed by Cary Phillips.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
@par
|
||||
Improvements:
|
||||
- Added tools::countActiveLeafVoxels(), tools::countInactiveVoxels(),
|
||||
tools::countInactiveLeafVoxels() and tools::activeTiles() to perform
|
||||
multi-threaded counting. The Tree methods now use these implementations.
|
||||
- Moved from the deprecated TBB task scheduler to TBB arenas. Various
|
||||
methods now respect the TBB arena state they were invoked from.
|
||||
- Introduced a new thread/Threading.h header to consolidate calls to
|
||||
third-party threading methods.
|
||||
- Minor performance improvements to dilation calls in fast sweeping
|
||||
algorithms.
|
||||
- Added hsvtogrb() and rgbtohsv() AX helper functions for converting
|
||||
hue, saturation and value inputs to RGB values and vice-versa.
|
||||
- PointDataGrid conversion can now be performed using 32-bit float arrays.
|
||||
- Improved support for size_t grid types on systems where size_t is a unique
|
||||
type.
|
||||
[Contributed by Brecht Van Lommel]
|
||||
- Minor performance improvements to dilation calls in fast sweeping algorithms.
|
||||
- Add support for dilation in one direction and extending a field in one
|
||||
direction in fast sweeping algorithms.
|
||||
|
||||
@par
|
||||
API changes:
|
||||
@@ -62,6 +220,8 @@ Houdini:
|
||||
- The default OpenVDB ABI is now 8 for Houdini versions > 18.5.
|
||||
- VDB Visualize Tree SOP is now multi-threaded and provides slicing and color
|
||||
remapping.
|
||||
- Add a sanitizer in SOP OpenVDB Extrapolate when expanding a narrow-band
|
||||
level-set with a dilation value of 0, which will result in no operation.
|
||||
|
||||
@par
|
||||
Build:
|
||||
@@ -73,14 +233,14 @@ Build:
|
||||
generated doxygen.
|
||||
- Improved the doxygen deprecation listings, folder layouts and fixes
|
||||
issues when using later versions of doxygen.
|
||||
- Build fixes for MinGW on Windows
|
||||
- Build fixes for MinGW on Windows.
|
||||
[Contributed by Brecht Sanders]
|
||||
- Added support for OpenEXR 3
|
||||
- Added support for OpenEXR 3.
|
||||
[Contributed by Cary Phillips]
|
||||
- Added an OPENVDB_NAMESPACE_SUFFIX CMake string option which provides the
|
||||
ability to customise the VDB namespace.
|
||||
- The Python Module now appends the base directory defined by Python_SITELIB
|
||||
to the default install path (typically dist-packages or site-packages)
|
||||
to the default install path (typically dist-packages or site-packages).
|
||||
[Contributed by Ignacio Vizzo]
|
||||
|
||||
|
||||
|
||||
+48
-44
@@ -35,17 +35,18 @@ Reference Platform, but for those that do, their specified versions are
|
||||
|
||||
@section depComponents OpenVDB Components
|
||||
|
||||
Component | Requirements | Optional
|
||||
----------------------- | ------------------------------------------------------------------------------------ | --------
|
||||
OpenVDB Core Library | CMake, C++14 compiler, TBB::tbb, Boost::system, Boost::iostream | Blosc, ZLib, Log4cplus, IlmBase::Half
|
||||
OpenVDB Print | Core Library dependencies | -
|
||||
OpenVDB LOD | Core Library dependencies | -
|
||||
OpenVDB Render | Core Library dependencies, OpenEXR, IlmBase | -
|
||||
OpenVDB View | Core Library dependencies, OpenGL, GLFW3, GLEW* | -
|
||||
OpenVDB Python | Core Library dependencies, Python, Boost::python | Boost::numpy, NumPy
|
||||
OpenVDB AX | Core Library dependencies, LLVM | Bison, Flex
|
||||
OpenVDB UnitTests | Core Library dependencies, GoogleTest | CppUnit**
|
||||
OpenVDB Documentation | Doxygen | -
|
||||
Component | Requirements | Optional
|
||||
----------------------- | ------------------------------------------------- | --------
|
||||
OpenVDB Core Library | CMake, C++14 compiler, TBB::tbb, Boost::iostream | Blosc, ZLib, Log4cplus, IlmBase::Half
|
||||
OpenVDB Print | Core Library dependencies | -
|
||||
OpenVDB LOD | Core Library dependencies | -
|
||||
OpenVDB Render | Core Library dependencies | OpenEXR, IlmBase, libpng
|
||||
OpenVDB View | Core Library dependencies, OpenGL, GLFW3, GLEW* | -
|
||||
OpenVDB Python | Core Library dependencies, Python, Boost::python | Boost::numpy, NumPy
|
||||
OpenVDB AX | Core Library dependencies, LLVM | Bison, Flex
|
||||
NanoVDB | - | Core Library, CUDA, TBB, Blosc, ZLib
|
||||
OpenVDB UnitTests | Core Library dependencies, GoogleTest | CppUnit**
|
||||
OpenVDB Documentation | Doxygen | -
|
||||
|
||||
- @b * GLEW is only required for building the vdb_view binary on Windows.
|
||||
- @b ** CppUnit is only required for building the AX unit tests.
|
||||
@@ -65,23 +66,24 @@ IlmBase | 2.2** | 2.3 | Used half precision floating points and
|
||||
OpenEXR | 2.2** | 2.3 | EXR serialization support | Y | Y | http://www.openexr.com
|
||||
TBB | 2018 | 2018 | Threading Building Blocks - template library for task parallelism | Y | Y | https://www.threadingbuildingblocks.org
|
||||
ZLIB | 1.2.7 | Latest | Compression library for disk serialization compression | Y | Y | https://www.zlib.net
|
||||
Boost | 1.66 | 1.66 | Components: system, iostreams, python, numpy | Y | Y | https://www.boost.org
|
||||
Boost | 1.66 | 1.66 | Components: iostreams, python, numpy | Y | Y | https://www.boost.org
|
||||
LLVM | 6.0.0 | 8.0.0 | Target-independent code generation | Y | Y | https://llvm.org/
|
||||
Bison | 3.0.0 | 3.0.5 | General-purpose parser generator | Y | Y | https://www.gnu.org/software/gcc
|
||||
Flex | 2.6 | 2.6.4 | Fast lexical analyzer generator | Y | Y | https://github.com/westes/flex
|
||||
Python | 2.7 | 2.7 | The python interpreter and libraries for C++/python bindings | Y | Y | https://www.python.org
|
||||
NumPy | 1.14.0 | 1.14.0 | Scientific computing with Python | Y | Y | http://www.numpy.org
|
||||
GoogleTest | 1.8 | Latest | A unit testing framework module for C++ | Y | Y | https://github.com/google/googletest
|
||||
GoogleTest | 1.10 | Latest | A unit testing framework module for C++ | Y | Y | https://github.com/google/googletest
|
||||
CppUnit | 1.10 | Latest | A unit testing framework module for C++ | N | Y | https://freedesktop.org/wiki/Software/cppunit
|
||||
Blosc | 1.5.0 | 1.5.0 | Recommended dependency for improved disk compression | N | N* | https://github.com/Blosc/c-blosc/releases
|
||||
Blosc | 1.17.0* | 1.17.0 | Recommended dependency for improved disk compression | Y | Y | https://github.com/Blosc/c-blosc/releases
|
||||
Log4cplus | 1.1.2 | Latest | An optional dependency for improved OpenVDB Logging | Y | Y | https://github.com/log4cplus/log4cplus
|
||||
libpng | - | Latest | Library for manipulating PNG images | Y | Y | http://www.libpng.org/pub/png/libpng.html
|
||||
GLFW | 3.1 | Latest | Simple API for OpenGL development | Y | Y | https://www.glfw.org
|
||||
OpenGL | 3.2 | Latest | Environment for developing portable graphics applications | Y | Y | https://www.opengl.org
|
||||
GLEW | 1.0.0 | Latest | A cross-platform OpenGL extension loading library. | Y | Y | http://glew.sourceforge.net
|
||||
CUDA | - | Latest | Parallel computing platform for graphical processing units. | Y | N | https://developer.nvidia.com/cuda-downloads
|
||||
Doxygen | 1.8.8 | 1.8.11 | Documentation generation from C++ | Y | Y | http://www.doxygen.nl
|
||||
|
||||
- @b * Blosc 1.16 is only available through Homebrew and currently requires
|
||||
[manual](@ref depManInstall) installation for 1.5.
|
||||
- @b * See the note in [known issues](@ref depKnownIssues) regarding supported blosc versions.
|
||||
|
||||
- @b ** IlmBase/OpenEXR 2.2 is supported as Houdini 18.0 is shipped with
|
||||
VFX Reference Platform 2019, except for using older versions of these
|
||||
@@ -100,6 +102,23 @@ Doxygen | 1.8.8 | 1.8.11 | Documentation generation from C++
|
||||
RuntimeError: FATAL: module compiled as little endian, but detected different endianness at runtime.
|
||||
@endcode
|
||||
|
||||
- @b Blosc: OpenVDB has historically used an old version of blosc (1.5.0) to
|
||||
serialize .vdb files. OpenVDB is moving to a new blosc version minimum of 1.17.0.
|
||||
We have tested a range of blosc versions and found that the following versions
|
||||
are NOT compatible with OpenVDB caches written using blosc 1.5.0. Additionally
|
||||
these versions of blosc may generally not be compatible with OpenVDB itself.
|
||||
Avoid using these versions and upgrade to the new minimum of 1.17.0 where
|
||||
possible.
|
||||
|
||||
- All versions from 1.11.0 through to, but excluding, 1.14.0.
|
||||
- Versions 1.16.0 and 1.16.1.
|
||||
|
||||
For more information see:
|
||||
|
||||
- https://www.blosc.org/posts/new-forward-compat-policy/
|
||||
- https://github.com/Blosc/c-blosc/issues/260
|
||||
- https://github.com/Blosc/c-blosc/issues/261
|
||||
|
||||
@section depInstallingDependencies Installing Dependencies
|
||||
|
||||
This section details a number of ways to get you up and running with the
|
||||
@@ -107,20 +126,17 @@ required OpenVDB dependencies.
|
||||
|
||||
@subsection depUsingAptGet Using UNIX apt-get
|
||||
|
||||
@b Note: Blosc and CppUnit are unavailable using apt-get. See the other
|
||||
package manager methods or the [manual installation](@ref depManInstall)
|
||||
options.
|
||||
@b Note:CppUnit is unavailable using apt-get. See the other package manager
|
||||
methods or the [manual installation](@ref depManInstall) options.
|
||||
|
||||
@code{.sh}
|
||||
#!/bin/bash
|
||||
# Core library
|
||||
apt-get install cmake # CMake
|
||||
apt-get install libilmbase-dev # IlmBase
|
||||
apt-get install libopenexr-dev # OpenEXR
|
||||
apt-get install libtbb-dev # TBB
|
||||
apt-get install zlibc # zlib
|
||||
apt-get install libboost-system-dev # Boost::system
|
||||
apt-get install libboost-iostreams-dev # Boost::iostream
|
||||
apt-get install libblosc-dev # Blosc
|
||||
# AX
|
||||
apt-get install llvm-8-dev # LLVM
|
||||
# Python
|
||||
@@ -129,12 +145,17 @@ apt-get install libboost-numpy-dev # Boost::numpy
|
||||
apt-get install python-dev # Python
|
||||
apt-get install python-numpy # NumPy
|
||||
# Optional
|
||||
apt-get install libpng-dev # libpng
|
||||
apt-get install libilmbase-dev # IlmBase
|
||||
apt-get install libopenexr-dev # OpenEXR
|
||||
apt-get install liblog4cplus-dev # Log4cplus
|
||||
apt-get install googletest # GoogleTest
|
||||
# vdb_view
|
||||
apt-get install libglfw3-dev # GLFW
|
||||
# Documentation
|
||||
apt-get install doxygen # doxygen
|
||||
# CUDA for NanoVDB
|
||||
apt-get install nvidia-cuda-toolkit # CUDA
|
||||
@endcode
|
||||
|
||||
@subsection depUsingHomebrew Using Homebrew
|
||||
@@ -142,20 +163,14 @@ apt-get install doxygen # doxygen
|
||||
[Homebrew](https://brew.sh/) is a package manager for UNIX systems and is
|
||||
an alternative to apt-get or manual installation from source.
|
||||
|
||||
@b Note: Homebrew installs blosc 1.16 by default with no option for previous
|
||||
versions. OpenVDB recommends Blosc version 1.5 as there are known issues with
|
||||
using later versions of blosc. See the
|
||||
[manual installation](@ref depManInstall) options.
|
||||
|
||||
@code{.sh}
|
||||
#!/bin/bash
|
||||
# Core library
|
||||
brew install cmake # CMake
|
||||
brew install ilmbase # IlmBase
|
||||
brew install openexr # OpenEXR
|
||||
brew install tbb # TBB
|
||||
brew install zlib # zlib
|
||||
brew install boost # Boost
|
||||
brew install c-blosc # blosc
|
||||
# AX
|
||||
brew install llvm # LLVM
|
||||
# Python
|
||||
@@ -167,6 +182,10 @@ brew install gtest # GoogleTest
|
||||
brew install cppunit # CppUnit
|
||||
# vdb_view
|
||||
brew install glfw # GLFW
|
||||
# vdb_render
|
||||
brew install ilmbase # IlmBase
|
||||
brew install openexr # OpenEXR
|
||||
brew install libpng # libpng
|
||||
# Documentation
|
||||
brew install doxygen # Doxygen
|
||||
@endcode
|
||||
@@ -178,21 +197,6 @@ Below are manual installation methods for these packages. Note that you will
|
||||
have to provide your chosen installation locations to the OpenVDB CMake build
|
||||
system when building OpenVDB.
|
||||
|
||||
@b Blosc
|
||||
|
||||
@code{.sh}
|
||||
#!/bin/bash
|
||||
wget https://github.com/Blosc/c-blosc/archive/v1.5.0.zip
|
||||
unzip v1.5.0.zip
|
||||
cd c-blosc-1.5.0
|
||||
# Install to users home directory - you may customise this location
|
||||
mkdir -p $HOME/blosc
|
||||
# Requires CMake
|
||||
cmake -DCMAKE_INSTALL_PREFIX=$HOME/blosc
|
||||
make
|
||||
make install
|
||||
@endcode
|
||||
|
||||
@b CppUnit (for AX Unit Tests)
|
||||
|
||||
@code{.sh}
|
||||
|
||||
@@ -51,6 +51,10 @@ See @subpage openvdbax "OpenVDB AX" for the AX documentation.
|
||||
See the @subpage houdini "Houdini Cookbook" for help on implementing Houdini nodes.
|
||||
@endif
|
||||
|
||||
@if NANOVDB
|
||||
See @subpage NanoVDB_MainPage "NanoVDB" for the NanoVDB documentation.
|
||||
@endif
|
||||
|
||||
Contributors, please familiarize yourselves with our
|
||||
@subpage codingStyle "coding standards".
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# FAQ {#NanoVDB_FAQ}
|
||||
|
||||
* **What is NanoVDB?**
|
||||
|
||||
As the name indicates it's a mini-version of the much bigger OpenVDB library, both in terms of functionality and scope. In fact, a stand-alone C++11 implementation of NanoVDB is available in the file [NanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/NanoVDB.h) and the C99 equivalent in the files [CNanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/CNanoVDB.h), and [PNanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/PNanoVDB.h). However, NanoVDB offers one major advantage over OpenVDB, namely support for GPUs. In short, NanoVDB is a standalone static-topology implementation of the well-known sparse volumetric VDB data structure. In other words, while values can be modified in a NanoVDB grid its tree topology cannot.
|
||||
|
||||
**What graphics API does NanoVDB support?**
|
||||
|
||||
We have tested NanoVDB with CUDA, OpenCL, OpenGL, DirectX 12, OptiX, Vulkan, HLSL, and GLSL. We are also working on adding support for WebGL.
|
||||
|
||||
* **What are the advantages of NanoVDB?**
|
||||
|
||||
Other then the fact that it runs on the GPU, NanoVDB offers several other advantages over OpenVDB. For its limited applications it's generally faster, uses slightly less memory, is implemented in few header files, and has virtually no dependencies on external libraries (other then C++11 or C99). While NanoVDB inherits most of the memory and data access advantages of OpenVDB (e.g. fast random-access by means of inverse tree-traversal), the improved memory layout of NanoVDB actually results in faster read access performance.
|
||||
|
||||
* **What are the limitations of NanoVDB?**
|
||||
|
||||
Other than the fact that NanoVDB obviously lacks many of the features and tools of OpenVDB, the most important limitation of NanoVDB is the fact that it *assumes the topology of the tree structure to be static*. Thus, it is possible to modify the values in a NanoVDB grid, but not its topology, e.g. see [modify_nanovdb_thrust.cu](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/examples/ex_modify_nanovdb_thrust/modify_nanovdb_thrust.cu).
|
||||
|
||||
* **Does NanoVDB work on the CPU as well as the GPU?**
|
||||
|
||||
Yes! In fact, it provides performance advantages on the CPU over OpenVDB, primarily due to the defragmented and more cache-friendly memory layout for spatially coherent voxel access.
|
||||
|
||||
* **What is NanoVDB intended for?**
|
||||
|
||||
Rendering (e.g. ray-tracing) on the GPU or CPU, and other applications that require fast random access into a sparse volumetric data structure (e.g. collision detection for cloth simulations or static boundary conditions in fluid simulations). Additionally, since NanoVDB is essentially a slimmed-down version of the core data structure in OpenVDB, NanoVDB also serves as a great tool to learn about the implementation details of VDB, and can even serve as a starting point for your own sparse data structure.
|
||||
|
||||
* **Does NanoVDB depend on and require CUDA?**
|
||||
|
||||
No, NanoVDB is by design agnostic and works with most graphics APIs, e.g. OpenGL, OpenCL, OptiX, CUDA, HLSL, GLSL, DirectX, and even the CPU! The data structure itself (defined in [NanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/NanoVDB.h) and [PNanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/PNanoVDB.h)) only depends on C++11 or C99. However, some of the auxiliary math classes are optionally optimized with intrinsic CUDA calls (e.g. fma in Vec3) and some of the [Allocator](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/util/CudaDeviceBuffer.h) uses CUDA for explicit memory management. It should be straightforward to replace (or remove) these CUDA dependencies if you so desire.
|
||||
|
||||
* **How does the data structure of NanoVDB compare to that of OpenVDB?**
|
||||
|
||||
Conceptually they are essentially identical (NanoVDB uses the exact same tree configuration), but there are some implementation differences to minimize dependencies on external libraries in NanoVDB (e.g. no boost and std containers), and more importantly, NanoVDB has additional meta-data encoded in tree nodes specifically to accelerate ray-tracing (e.g. min/max values and AABB of active values). Also, NanoVDB is pointer-less and occupies a contiguous block of memory, i.e. de-fragmentized relative to OpenVDB. Effectively, NanoVDB is a linearized version of the well-known OpenVDB data structure with a few additional information baked into the tree nodes!
|
||||
|
||||
* **Are there known issues with NanoVDB?**
|
||||
|
||||
While the are currently no known bugs, there are certainly lots of room for improvements and enhancements. If you have issues or ideas for new feature in NanoVDB please let us know, e.g by submitting a [Github issue](https://github.com/AcademySoftwareFoundation/openvdb/issues).
|
||||
@@ -0,0 +1,154 @@
|
||||
# NanoVDB Hello World Examples {#NanoVDB_HelloWorld}
|
||||
|
||||
[The first example](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/examples/ex_openvdb_to_nanovdb_accessor/openvdb_to_nanovdb_accessor.cc) shows how to convert an OpenVDB level set sphere into a NanoVDB level set, use accessors to print out multiple values from both grids, and save the NanoVDB grid to file. Note that **this example depends on both OpenVDB and NanoVDB**.
|
||||
|
||||
```cpp
|
||||
#include <openvdb/tools/LevelSetSphere.h> // replace with your own dependencies for generating the OpenVDB grid
|
||||
#include <nanovdb/util/OpenToNanoVDB.h> // converter from OpenVDB to NanoVDB (includes NanoVDB.h and GridManager.h)
|
||||
#include <nanovdb/util/IO.h>
|
||||
|
||||
// Convert an openvdb level set sphere into a nanovdb, use accessors to print out multiple values from both
|
||||
// grids and save the NanoVDB grid to file.
|
||||
// Note, main depends on BOTH OpenVDB and NanoVDB.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
// Create an OpenVDB grid (here a level set surface but replace this with your own code)
|
||||
auto srcGrid = openvdb::tools::createLevelSetSphere<openvdb::FloatGrid>(100.0f, openvdb::Vec3f(0.0f), 1.0f);
|
||||
|
||||
// Convert the OpenVDB grid, srcGrid, into a NanoVDB grid handle.
|
||||
auto handle = nanovdb::openToNanoVDB(*srcGrid);
|
||||
|
||||
// Define a (raw) pointer to the NanoVDB grid on the host. Note we match the value type of the srcGrid!
|
||||
auto* dstGrid = handle.grid<float>();
|
||||
|
||||
if (!dstGrid)
|
||||
throw std::runtime_error("GridHandle does not contain a grid with value type float");
|
||||
|
||||
// Get accessors for the two grids. Note that accessors only accelerate repeated access!
|
||||
auto dstAcc = dstGrid->getAccessor();
|
||||
auto srcAcc = srcGrid->getAccessor();
|
||||
|
||||
// Access and print out a cross-section of the narrow-band level set from the two grids
|
||||
for (int i = 97; i < 104; ++i) {
|
||||
printf("(%3i,0,0) OpenVDB cpu: % -4.2f, NanoVDB cpu: % -4.2f\n", i, srcAcc.getValue(openvdb::Coord(i, 0, 0)), dstAcc.getValue(nanovdb::Coord(i, 0, 0)));
|
||||
}
|
||||
|
||||
nanovdb::io::writeGrid("data/sphere.nvdb", handle); // Write the NanoVDB grid to file and throw if writing fails
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
[The second example](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/examples/ex_read_nanovdb_sphere_accessor/read_nanovdb_sphere_accessor.cc) reads a NanoVDB grid from a file (the one saved in the previous example) and prints out multiple values. Note that **this example does not depend on OpenVDB (nor CUDA), only NanoVDB**.
|
||||
|
||||
```cpp
|
||||
#include <nanovdb/util/IO.h> // this is required to read (and write) NanoVDB files on the host
|
||||
|
||||
/// @brief Read a NanoVDB grid from a file and print out multiple values.
|
||||
///
|
||||
/// @note Note This example does NOT depend on OpenVDB (nor CUDA), only NanoVDB.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
auto handle = nanovdb::io::readGrid("data/sphere.nvdb"); // reads first grid from file
|
||||
|
||||
auto* grid = handle.grid<float>(); // get a (raw) pointer to a NanoVDB grid of value type float
|
||||
|
||||
if (!grid)
|
||||
throw std::runtime_error("File did not contain a grid with value type float");
|
||||
|
||||
auto acc = grid->getAccessor(); // create an accessor for fast access to multiple values
|
||||
for (int i = 97; i < 104; ++i) {
|
||||
printf("(%3i,0,0) NanoVDB cpu: % -4.2f\n", i, acc.getValue(nanovdb::Coord(i, 0, 0)));
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
[The third example](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/examples/ex_read_nanovdb_sphere_accessor_cuda/read_nanovdb_sphere_accessor_cuda.cc) reads a NanoVDB grid from a file (the one saved in the first example) and prints out multiple values on both the CPU and GPU. Note that **this example does NOT depend on OpenVDB, only NanoVDB and CUDA**.
|
||||
|
||||
```cpp
|
||||
#include <nanovdb/util/IO.h> // this is required to read (and write) NanoVDB files on the host
|
||||
#include <nanovdb/DefaultCudaAllocator.h> // required for CUDA memory management
|
||||
|
||||
extern "C" void launch_kernels(const nanovdb::NanoGrid<float>*,
|
||||
const nanovdb::NanoGrid<float>*,
|
||||
cudaStream_t stream);
|
||||
|
||||
/// @brief Read a NanoVDB grid from a file and print out multiple values on both the cpu and gpu.
|
||||
///
|
||||
/// @note Note This example does NOT depend on OpenVDB, only NanoVDB and CUDA.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
// returns a GridHandle using CUDA for memory management.
|
||||
auto handle = nanovdb::io::readGrid<nanovdb::CudaDeviceBuffer>("data/sphere.nvdb");
|
||||
|
||||
cudaStream_t stream; // Create a CUDA stream to allow for asynchronous copy of pinned CUDA memory.
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
handle.deviceUpload(stream, false); // Copy the NanoVDB grid to the GPU asynchronously
|
||||
|
||||
auto* cpuGrid = handle.grid<float>(); // get a (raw) pointer to a NanoVDB grid of value type float on the CPU
|
||||
auto* deviceGrid = handle.deviceGrid<float>(); // get a (raw) pointer to a NanoVDB grid of value type float on the GPU
|
||||
|
||||
if (!deviceGrid || !cpuGrid)
|
||||
throw std::runtime_error("GridHandle did not contain a grid with value type float");
|
||||
|
||||
launch_kernels(deviceGrid, cpuGrid, stream); // Call a host method to print a grid values on both the CPU and GPU
|
||||
|
||||
cudaStreamDestroy(stream); // Destroy the CUDA stream
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
NVCC requires the CUDA kernel to be defined in [a separate .cu file](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/examples/ex_read_nanovdb_sphere_accessor_cuda/read_nanovdb_sphere_accessor_cuda.cu):
|
||||
|
||||
```cpp
|
||||
#include <nanovdb/NanoVDB.h> // this defined the core tree data structure of NanoVDB accessible on both the host and device
|
||||
#include <stdio.h> // for printf
|
||||
|
||||
// This is called by the host only
|
||||
void cpu_kernel(const nanovdb::NanoGrid<float>* cpuGrid)
|
||||
{
|
||||
auto cpuAcc = cpuGrid->getAccessor();
|
||||
for (int i = 97; i < 104; ++i) {
|
||||
printf("(%3i,0,0) NanoVDB cpu: % -4.2f\n", i, cpuAcc.getValue(nanovdb::Coord(i, 0, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
// This is called by the device only
|
||||
__global__ void gpu_kernel(const nanovdb::NanoGrid<float>* deviceGrid)
|
||||
{
|
||||
if (threadIdx.x > 6)
|
||||
return;
|
||||
int i = 97 + threadIdx.x;
|
||||
auto gpuAcc = deviceGrid->getAccessor();
|
||||
printf("(%3i,0,0) NanoVDB gpu: % -4.2f\n", i, gpuAcc.getValue(nanovdb::Coord(i, 0, 0)));
|
||||
}
|
||||
|
||||
// This is called by the client code on the host
|
||||
extern "C" void launch_kernels(const nanovdb::NanoGrid<float>* deviceGrid,
|
||||
const nanovdb::NanoGrid<float>* cpuGrid,
|
||||
cudaStream_t stream)
|
||||
{
|
||||
// Launch the device kernel asynchronously
|
||||
gpu_kernel<<<1, 64, 0, stream>>>(deviceGrid);
|
||||
|
||||
// Launch the host "kernel" (synchronously)
|
||||
cpu_kernel(cpuGrid);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,55 @@
|
||||
# Build instructions {#NanoVDB_HowToBuild}
|
||||
|
||||
Note that NanoVDB can be built in many different ways, in the sense that its many external dependencies are optional. This includes OpenVDB, TBB, graphics APIs like CUDA, OpenGL, and OpenCL, as well as compression like ZLIB and BLOSC.
|
||||
However, since the core data structure in [NanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/NanoVDB.h) is self-contained, client code may only depend on this single header file.
|
||||
|
||||
Also, note that if the environment variable `VDB_DATA_PATH` is set to a directory containing the OpenVDB files from [the OpenVDB web site](http://www.openvdb.org/download), they will be used for the unit and the benchmark tests. Else a simple narrow-band level set sphere is used. Set the environment variable `VDB_SCRATCH_PATH` to define the path to where images generated in the benchmark tests are stored (defaults to the build directory).
|
||||
|
||||
[//]: # (TODO: add back OPTIX, OPENCL, and OPENGL when these options are added back)
|
||||
To explicitly remove a dependency, `X`, add the argument `-DNANOVDB_USE_X=OFF` where `X = {OPENVDB, TBB, BLOSC, ZLIB, CUDA}`. These options are set in the [NanoVDB root CMakeLists.txt](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/CMakeLists.txt). The same file also defines options to build NanoVDB examples, benchmarks, unit-tests, and command-line tools. The default values for these options are `OFF`. A user can override each of these options by passing, for example, `-DNANOVDB_BUILD_UNITTESTS=ON` flag while running cmake from the command line.
|
||||
|
||||
To see the compiler arguments add `-DCMAKE_VERBOSE_MAKEFILE=ON`.
|
||||
|
||||
## First example: building NanoVDB and OpenVDB core
|
||||
|
||||
NanoVDB is now a module of the larger OpenVDB project. A user can build both libraries together. This will build the OpenVDB core library, install the NanoVDB header files, and build the NanoVDB command-line tools in the `build/nanovdb/cmd` directory. From the 'root' OpenVDB project directory (change the dependency paths to match your environment):
|
||||
```console
|
||||
foo@bar:~$ mkdir build
|
||||
foo@bar:~$ cd build
|
||||
foo@bar:~$ cmake .. -DUSE_NANOVDB=ON -DTBB_ROOT=/path/to/tbb -DBOOST_ROOT=/path/to/boost -DBLOSC_ROOT=/path/to/blosc -DCMAKE_INSTALL_PREFIX=/install/path
|
||||
foo@bar:~$ make -j 4 && make install
|
||||
```
|
||||
Note that the default value of `NANOVDB_USE_OPENVDB` is linked to `OPENVDB_BUILD_CORE` option and can be overriden by passing on `-DNANOVDB_USE_OPENVDB=OFF`. The `Boost` library is included because it is a requirement for building OpenVDB.
|
||||
|
||||
In general, CMake will try to find every optional dependency when a user opts to add an additional dependency. Be sure to check the CMake log to see what dependencies were **not** found.
|
||||
|
||||
## Second example: NanoVDB with no dependencies
|
||||
|
||||
From the 'root' OpenVDB project directory:
|
||||
```console
|
||||
foo@bar:~$ mkdir build
|
||||
foo@bar:~$ cd build
|
||||
foo@bar:~$ cmake .. -DUSE_NANOVDB=ON -DOPENVDB_BUILD_CORE=OFF -DOPENVDB_BUILD_BINARIES=OFF -DNANOVDB_USE_TBB=OFF -DNANOVDB_USE_BLOSC=OFF -DNANOVDB_USE_ZLIB=OFF -DCMAKE_INSTALL_PREFIX=/install/path
|
||||
foo@bar:~$ make -j 4 && make install
|
||||
```
|
||||
|
||||
Another option is to build it from the NanoVDB directory itself, which is much simpler:
|
||||
```console
|
||||
foo@bar:~$ cd nanovdb/nanovdb
|
||||
foo@bar:~$ mkdir build
|
||||
foo@bar:~$ cd build
|
||||
foo@bar:~$ cmake .. -DCMAKE_INSTALL_PREFIX=/install/path
|
||||
foo@bar:~$ make -j 4 && make install
|
||||
```
|
||||
Both options will install the NanoVDB header files to the `/install/path` as well as building `nanovdb_print` and `nanovdb_validate` executable. The path where these executables are installed will be different: in the first option they will be under `build/nanovdb/cmd` directory; whilst in the second option they will be under the `build/cmd/` directory.
|
||||
|
||||
## Third example: build 'everything' in NanoVDB along with OpenVDB core
|
||||
|
||||
From the root OpenVDB directory:
|
||||
```console
|
||||
foo@bar:~$ mkdir build
|
||||
foo@bar:~$ cd build
|
||||
foo@bar:~$ cmake .. -DUSE_NANOVDB=ON -DNANOVDB_BUILD_UNITTESTS=ON -DNANOVDB_BUILD_EXAMPLES=ON -DNANOVDB_BUILD_BENCHMARK=ON -DNANOVDB_USE_INTRINSICS=ON -DNANOVDB_USE_CUDA=ON -DNANOVDB_CUDA_KEEP_PTX=ON -DTBB_ROOT=/path/to/tbb -DBOOST_ROOT=/path/to/boost -DBLOSC_ROOT=/path/to/blosc -DGTEST_ROOT=/path/to/gtest -DCMAKE_INSTALL_PREFIX=/install/path
|
||||
foo@bar:~$ make -j 4 && make install
|
||||
```
|
||||
Note that if you already have the correct version of OpenVDB pre-installed, you can configure CMake to link against that library by passing the arguments `-DOPENVDB_BUILD_CORE=OFF -DOPENVDB_BUILD_BINARIES=OFF -DOPENVDB_ROOT=/path/to/openvdb` when invoking `cmake`.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Source tree structure {#NanoVDB_SourceTree}
|
||||
|
||||
#### Overview of the directory tree of NanoVDB.
|
||||
|
||||
* [NanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/NanoVDB.h) C++11 implementation of the core data structure and its access methods.
|
||||
* [CNanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/CNanoVDB.h) Incomplete but useable C99 implementation of the core data structure and its access methods. Designed in particular for use in OpenCL kernels. Note that this relies on zero-sized arrays for the _reserved padding, so will not work on all compilers (with MSVC being a particular example)
|
||||
* [PNanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/PNanoVDB.h) C99 implementation of the core data structure and its access methods. More complete coverage than CNanoVDB. This version is pointer-less and supports virtually all graphics APIs.
|
||||
* [util/GridHandle.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/util/GridHandle.h) defines a handler for the memory allocated to a NanoVDB grid.
|
||||
* [util/IO.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/util/IO.h) implements I/O support.
|
||||
* [util/OpenToNanoVDB.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/util/OpenToNanoVDB.h) defines the converter from OpenVDB to NanoVDB and obviously depends on the OpenVDB library (as the only header file).
|
||||
* [Ray.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/util/Ray.h) Ray class.
|
||||
* [HDDA.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/util/HDDA.h) HDDA related.
|
||||
* [SampleFromVoxels.h](https://github.com/AcademySoftwareFoundation/openvdb/blob/master/nanovdb/nanovdb/util/SampleFromVoxels.h) interpolation.
|
||||
|
||||
```bash
|
||||
foo@bar:~$ tree
|
||||
.
|
||||
├── nanovdb
|
||||
│ ├── CNanoVDB.h
|
||||
│ ├── NanoVDB.h
|
||||
│ ├── PNanoVDB.h
|
||||
│ └── util
|
||||
│ ├── CSampleFromVoxels.h
|
||||
│ ├── CudaDeviceBuffer.h
|
||||
| ├── DitherLUT.h
|
||||
│ ├── ForEach.h
|
||||
│ ├── GridBuilder.h
|
||||
│ ├── GridChecksum.h
|
||||
│ ├── GridHandle.h
|
||||
│ ├── GridStats.h
|
||||
│ ├── GridValidator.h
|
||||
│ ├── HDDA.h
|
||||
│ ├── HostBuffer.h
|
||||
│ ├── Invoke.h
|
||||
│ ├── IO.h
|
||||
│ ├── NanoToOpenVDB.h
|
||||
│ ├── OpenToNanoVDB.h
|
||||
| ├── Primitives.h
|
||||
│ ├── Range.h
|
||||
│ ├── Ray.h
|
||||
| ├── Reduce.h
|
||||
| ├── SampleFromVoxels.h
|
||||
| └── Stencils.h
|
||||
```
|
||||
@@ -0,0 +1,8 @@
|
||||
# NanoVDB {#NanoVDB_MainPage}
|
||||
|
||||
Welcome to the NanoVDB documentation page.
|
||||
|
||||
* @ref NanoVDB_HowToBuild
|
||||
* @ref NanoVDB_FAQ
|
||||
* @ref NanoVDB_SourceTree
|
||||
* @ref NanoVDB_HelloWorld
|
||||
@@ -0,0 +1,273 @@
|
||||
# Copyright Contributors to the OpenVDB Project
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
#[=======================================================================[
|
||||
|
||||
CMake Configuration for NanoVDB
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(NanoVDB LANGUAGES C CXX)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
###############################################################################
|
||||
|
||||
message(STATUS "----------------------------------------------------")
|
||||
message(STATUS "--------------- Configuring NanoVDB ----------------")
|
||||
message(STATUS "----------------------------------------------------")
|
||||
|
||||
###############################################################################
|
||||
# add options
|
||||
###############################################################################
|
||||
|
||||
option(NANOVDB_BUILD_TOOLS "Build command-line tools" ON)
|
||||
option(NANOVDB_BUILD_UNITTESTS "Build Unit tests" OFF)
|
||||
option(NANOVDB_BUILD_EXAMPLES "Build examples" OFF)
|
||||
option(NANOVDB_BUILD_BENCHMARK "Build benchmark in examples" OFF)
|
||||
|
||||
option(NANOVDB_USE_INTRINSICS "Build with hardware intrinsics support" OFF)
|
||||
option(NANOVDB_USE_CUDA "Build with CUDA support" OFF)
|
||||
option(NANOVDB_CUDA_KEEP_PTX "Keep CUDA PTX" OFF)
|
||||
|
||||
option(NANOVDB_USE_OPENVDB "Build with OpenVDB support" OFF)
|
||||
option(NANOVDB_USE_BLOSC "Build with BLOSC support" ${USE_BLOSC})
|
||||
option(NANOVDB_USE_ZLIB "Build with ZLIB support" ${USE_ZLIB})
|
||||
option(NANOVDB_USE_TBB "Build with TBB support" ${USE_TBB})
|
||||
option(NANOVDB_USE_MAGICAVOXEL "Build with MagicaVoxel support" OFF)
|
||||
|
||||
option(NANOVDB_ALLOW_FETCHCONTENT
|
||||
"Allow FetchContent to download missing dependencies" OFF)
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
# sanitize user input
|
||||
|
||||
if(NANOVDB_USE_OPENVDB)
|
||||
if(NOT NANOVDB_USE_TBB)
|
||||
message(FATAL_ERROR "Invalid CMake build configuration:
|
||||
NANOVDB_USE_OPENVDB : [ON]
|
||||
NANOVDB_USE_TBB : [OFF]
|
||||
If you are linking NanoVDB against OpenVDB, then you
|
||||
need to use TBB, (i.e. -DNANOVDB_USE_TBB=ON).")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
enable_testing()
|
||||
|
||||
# Add our cmake modules
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../cmake")
|
||||
|
||||
if(UNIX)
|
||||
# For CMake's find Threads module which brings in pthread - This flag
|
||||
# forces the compiler -pthread flag vs -lpthread
|
||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_BUILD_UNITTESTS OR NANOVDB_BUILD_BENCHMARK)
|
||||
find_package(GTest REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_CUDA)
|
||||
set(CMAKE_CUDA_STANDARD 11)
|
||||
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
|
||||
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
|
||||
# Allow the user to provide CMAKE_CUDA_ARCHITECTURES
|
||||
if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
|
||||
set(CMAKE_CUDA_ARCHITECTURES 75)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
enable_language(CUDA)
|
||||
|
||||
set(NANOVDB_CUDA_EXTENDED_LAMBDA "--expt-extended-lambda")
|
||||
if(CUDA_VERSION_MAJOR GREATER_EQUAL 11)
|
||||
set(NANOVDB_CUDA_EXTENDED_LAMBDA "--extended-lambda")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CUDA_FLAGS "${NANOVDB_CUDA_EXTENDED_LAMBDA} -use_fast_math -lineinfo ${CMAKE_CUDA_FLAGS}")
|
||||
|
||||
# workaround for win32 bug when nvcc "--keep" is used.
|
||||
if(WIN32)
|
||||
if(NANOVDB_CUDA_KEEP_PTX)
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/Release")
|
||||
set(CMAKE_CUDA_FLAGS_RELEASE
|
||||
" --source-in-ptx --keep ${CMAKE_CUDA_FLAGS_RELEASE}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# If a CMAKE_MSVC_RUNTIME_LIBRARY has not been provided and we're building
|
||||
# against openvdb, match the CRT that openvdb has been built against. This
|
||||
# setting is automatically propagated to CXX files but not CUDA sources, so
|
||||
# the VDB_MSVC_RUNTIME_SELECTION variables is used on targets with .cu files
|
||||
if(NOT CMAKE_MSVC_RUNTIME_LIBRARY AND NANOVDB_USE_OPENVDB AND OPENVDB_BUILD_CORE)
|
||||
get_target_property(VDB_MSVC_RUNTIME_SELECTION openvdb MSVC_RUNTIME_LIBRARY)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_OPENVDB)
|
||||
if(NOT OPENVDB_BUILD_CORE AND NOT TARGET OpenVDB::openvdb)
|
||||
find_package(OpenVDB REQUIRED COMPONENTS openvdb)
|
||||
# disable the shared libs that OpenVDB's cmake switches ON.
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_TBB AND NOT TARGET TBB::tbb)
|
||||
find_package(TBB REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_BLOSC AND NOT TARGET Blosc::blosc)
|
||||
find_package(Blosc REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_ZLIB AND NOT TARGET ZLIB::ZLIB)
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_MAGICAVOXEL)
|
||||
if(NANOVDB_ALLOW_FETCHCONTENT)
|
||||
if(NOT ogt_POPULATED)
|
||||
message(STATUS "Downloading ogt...")
|
||||
|
||||
FetchContent_Declare(
|
||||
ogt
|
||||
GIT_REPOSITORY https://github.com/jpaver/opengametools.git
|
||||
GIT_TAG master)
|
||||
|
||||
FetchContent_GetProperties(ogt)
|
||||
if(NOT ogt_POPULATED)
|
||||
FetchContent_Populate(ogt)
|
||||
set(NANOVDB_OGT_INCLUDE_DIRECTORY ${ogt_SOURCE_DIR}/src)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
# Installation
|
||||
###############################################################################
|
||||
|
||||
# NanoVDB header files
|
||||
set(NANOVDB_INCLUDE_FILES
|
||||
CNanoVDB.h
|
||||
NanoVDB.h
|
||||
PNanoVDB.h
|
||||
)
|
||||
|
||||
# NanoVDB util header files
|
||||
set(NANOVDB_INCLUDE_UTILFILES
|
||||
util/CSampleFromVoxels.h
|
||||
util/CudaDeviceBuffer.h
|
||||
util/DitherLUT.h
|
||||
util/ForEach.h
|
||||
util/GridBuilder.h
|
||||
util/GridChecksum.h
|
||||
util/GridHandle.h
|
||||
util/GridStats.h
|
||||
util/GridValidator.h
|
||||
util/HDDA.h
|
||||
util/HostBuffer.h
|
||||
util/Invoke.h
|
||||
util/IO.h
|
||||
util/NanoToOpenVDB.h
|
||||
util/NodeManager.h
|
||||
util/OpenToNanoVDB.h
|
||||
util/Primitives.h
|
||||
util/Range.h
|
||||
util/Ray.h
|
||||
util/Reduce.h
|
||||
util/SampleFromVoxels.h
|
||||
util/Stencils.h
|
||||
)
|
||||
|
||||
add_library(nanovdb INTERFACE)
|
||||
target_include_directories(nanovdb INTERFACE ../)
|
||||
target_compile_options(nanovdb INTERFACE
|
||||
"$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-invalid-offsetof>"
|
||||
"$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/bigobj>")
|
||||
|
||||
if(WIN32)
|
||||
target_compile_definitions(nanovdb INTERFACE -DNOMINMAX -D_USE_MATH_DEFINES)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_INTRINSICS)
|
||||
target_compile_definitions(nanovdb INTERFACE -DNANOVDB_USE_INTRINSICS)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_OPENVDB)
|
||||
if(NOT OPENVDB_BUILD_CORE)
|
||||
target_link_libraries(nanovdb INTERFACE OpenVDB::openvdb)
|
||||
else()
|
||||
target_link_libraries(nanovdb INTERFACE openvdb)
|
||||
endif()
|
||||
target_compile_definitions(nanovdb INTERFACE -DNANOVDB_USE_OPENVDB)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_TBB)
|
||||
target_link_libraries(nanovdb INTERFACE TBB::tbb)
|
||||
target_compile_definitions(nanovdb INTERFACE -DNANOVDB_USE_TBB)
|
||||
if(WIN32)
|
||||
# this prevents tbb_debug.lib issue on windows
|
||||
target_compile_definitions(nanovdb INTERFACE -DTBB_USE_PREVIEW_BINARY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_BLOSC)
|
||||
target_link_libraries(nanovdb INTERFACE Blosc::blosc)
|
||||
target_compile_definitions(nanovdb INTERFACE -DNANOVDB_USE_BLOSC)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_ZLIB)
|
||||
target_link_libraries(nanovdb INTERFACE ZLIB::ZLIB)
|
||||
target_compile_definitions(nanovdb INTERFACE -DNANOVDB_USE_ZIP)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_CUDA)
|
||||
target_compile_definitions(nanovdb INTERFACE -DNANOVDB_USE_CUDA)
|
||||
if(NOT CMAKE_CUDA_ARCHITECTURES)
|
||||
target_compile_options(nanovdb INTERFACE
|
||||
"$<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:-arch=sm_75>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NANOVDB_USE_MAGICAVOXEL)
|
||||
target_compile_definitions(nanovdb INTERFACE -DNANOVDB_USE_MAGICAVOXEL)
|
||||
target_include_directories(nanovdb INTERFACE ${NANOVDB_OGT_INCLUDE_DIRECTORY})
|
||||
endif()
|
||||
|
||||
if(TARGET Threads::Threads)
|
||||
target_link_libraries(nanovdb INTERFACE Threads::Threads)
|
||||
endif()
|
||||
|
||||
set(NANOVDB_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/nanovdb)
|
||||
set(NANOVDB_INSTALL_UTILDIR ${NANOVDB_INSTALL_INCLUDEDIR}/util)
|
||||
|
||||
install(FILES ${NANOVDB_INCLUDE_FILES} DESTINATION ${NANOVDB_INSTALL_INCLUDEDIR})
|
||||
install(FILES ${NANOVDB_INCLUDE_UTILFILES} DESTINATION ${NANOVDB_INSTALL_UTILDIR})
|
||||
|
||||
###############################################################################
|
||||
# Options
|
||||
###############################################################################
|
||||
|
||||
if(NANOVDB_BUILD_TOOLS)
|
||||
add_subdirectory(cmd)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_BUILD_UNITTESTS)
|
||||
add_subdirectory(unittest)
|
||||
endif()
|
||||
|
||||
if(NANOVDB_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
@@ -0,0 +1,715 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//
|
||||
// Simple C-wrapper for the nanovdb structure
|
||||
// Meant for systems where you lack a C++ compiler.
|
||||
//
|
||||
#ifndef __CNANOVDB__
|
||||
#define __CNANOVDB__
|
||||
|
||||
#define CNANOVDB_DATA_ALIGNMENT 32
|
||||
#define CNANOVDB_ALIGNMENT_PADDING(x, n) (-(x) & ((n)-1))
|
||||
|
||||
#define USE_SINGLE_ROOT_KEY
|
||||
|
||||
#ifdef __OPENCL_VERSION__
|
||||
|
||||
#define CNANOVDB_GLOBAL __global
|
||||
#define RESTRICT restrict
|
||||
|
||||
// OpenCL doesn't define these basic types:
|
||||
typedef unsigned long uint64_t;
|
||||
typedef long int64_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
#else
|
||||
|
||||
#define CNANOVDB_GLOBAL
|
||||
#define RESTRICT __restrict
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
enum cnanovdb_GridType
|
||||
{
|
||||
cnanovdb_GridType_Unknown = 0,
|
||||
cnanovdb_GridType_Float = 1,
|
||||
cnanovdb_GridType_Double = 2,
|
||||
cnanovdb_GridType_Int16 = 3,
|
||||
cnanovdb_GridType_Int32 = 4,
|
||||
cnanovdb_GridType_Int64 = 5,
|
||||
cnanovdb_GridType_Vec3f = 6,
|
||||
cnanovdb_GridType_Vec3d = 7,
|
||||
cnanovdb_GridType_Mask = 8,
|
||||
cnanovdb_GridType_FP16 = 9,
|
||||
cnanovdb_GridType_End = 10
|
||||
};
|
||||
|
||||
#define ROOT_LEVEL 3
|
||||
|
||||
#define DEFINEMASK_int(LOG2DIM, SIZE) \
|
||||
typedef struct \
|
||||
{ \
|
||||
uint64_t mWords[SIZE >> 6]; \
|
||||
} cnanovdb_mask##LOG2DIM; \
|
||||
\
|
||||
static void cnanovdb_mask##LOG2DIM##_clear(CNANOVDB_GLOBAL cnanovdb_mask##LOG2DIM *RESTRICT mask) \
|
||||
{ for (uint32_t i = 0; i < (SIZE >> 6); i++) mask->mWords[i] = 0; } \
|
||||
\
|
||||
static bool cnanovdb_mask##LOG2DIM##_isOn(const CNANOVDB_GLOBAL cnanovdb_mask##LOG2DIM *RESTRICT mask, uint32_t n) \
|
||||
{ return 0 != (mask->mWords[n >> 6] & (((uint64_t)(1)) << (n & 63))); } \
|
||||
/**/
|
||||
|
||||
#define DEFINEMASK(LOG2DIM) \
|
||||
DEFINEMASK_int(LOG2DIM, (1U << (3*LOG2DIM)))
|
||||
|
||||
#define INSTANTIATE(LOG2DIM) \
|
||||
DEFINEMASK(LOG2DIM)
|
||||
|
||||
INSTANTIATE(3)
|
||||
INSTANTIATE(4)
|
||||
INSTANTIATE(5)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float mMatF[9]; // r,c = 3*r + c
|
||||
float mInvMatF[9]; // r,c = 3*r + c
|
||||
float mVecF[3];
|
||||
float mTaperF;
|
||||
double mMatD[9]; // r,c = 3*r + c
|
||||
double mInvMatD[9]; // r,c = 3*r + c
|
||||
double mVecD[3];
|
||||
double mTaperD;
|
||||
} cnanovdb_map;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float mVec[3];
|
||||
} cnanovdb_Vec3F;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32_t mVec[3];
|
||||
} cnanovdb_coord;
|
||||
|
||||
static int
|
||||
cnanovdb_coord_compare(const CNANOVDB_GLOBAL cnanovdb_coord *a, const cnanovdb_coord *b)
|
||||
{
|
||||
if (a->mVec[0] < b->mVec[0])
|
||||
return -1;
|
||||
if (a->mVec[0] > b->mVec[0])
|
||||
return 1;
|
||||
if (a->mVec[1] < b->mVec[1])
|
||||
return -1;
|
||||
if (a->mVec[1] > b->mVec[1])
|
||||
return 1;
|
||||
if (a->mVec[2] < b->mVec[2])
|
||||
return -1;
|
||||
if (a->mVec[2] > b->mVec[2])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_SINGLE_ROOT_KEY
|
||||
static uint64_t
|
||||
cnanovdb_coord_to_key(const cnanovdb_coord *RESTRICT ijk)
|
||||
{
|
||||
// Define to workaround a bug with 64-bit shifts in the AMD OpenCL compiler.
|
||||
#if defined(AVOID_64BIT_SHIFT)
|
||||
uint2 key = (uint2)( ((uint32_t)ijk->mVec[2]) >> 12, 0) |
|
||||
(uint2)((((uint32_t)ijk->mVec[1]) >> 12) << 21,
|
||||
((uint32_t)ijk->mVec[1]) >> 23) |
|
||||
(uint2)(0, (((uint32_t)ijk->mVec[0]) >> 12) << 10);
|
||||
return *(uint64_t *)&key;
|
||||
#else
|
||||
return ((uint64_t) (((uint32_t)ijk->mVec[2]) >> 12)) |
|
||||
(((uint64_t) (((uint32_t)ijk->mVec[1]) >> 12)) << 21) |
|
||||
(((uint64_t) (((uint32_t)ijk->mVec[0]) >> 12)) << 42);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static void
|
||||
cnanovdb_coord_to_key(cnanovdb_coord *RESTRICT key, const cnanovdb_coord *RESTRICT ijk)
|
||||
{
|
||||
key->mVec[0] = ijk->mVec[0] & ~((1u << 12) - 1u);
|
||||
key->mVec[1] = ijk->mVec[1] & ~((1u << 12) - 1u);
|
||||
key->mVec[2] = ijk->mVec[2] & ~((1u << 12) - 1u);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cnanovdb_map_apply(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_map *RESTRICT map, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
float sx = src->mVec[0];
|
||||
float sy = src->mVec[1];
|
||||
float sz = src->mVec[2];
|
||||
dst->mVec[0] = sx * map->mMatF[0] + sy * map->mMatF[1] + sz * map->mMatF[2] + map->mVecF[0];
|
||||
dst->mVec[1] = sx * map->mMatF[3] + sy * map->mMatF[4] + sz * map->mMatF[5] + map->mVecF[1];
|
||||
dst->mVec[2] = sx * map->mMatF[6] + sy * map->mMatF[7] + sz * map->mMatF[8] + map->mVecF[2];
|
||||
}
|
||||
|
||||
static void
|
||||
cnanovdb_map_applyInverse(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_map *RESTRICT map, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
float sx = src->mVec[0] - map->mVecF[0];
|
||||
float sy = src->mVec[1] - map->mVecF[1];
|
||||
float sz = src->mVec[2] - map->mVecF[2];
|
||||
dst->mVec[0] = sx * map->mInvMatF[0] + sy * map->mInvMatF[1] + sz * map->mInvMatF[2];
|
||||
dst->mVec[1] = sx * map->mInvMatF[3] + sy * map->mInvMatF[4] + sz * map->mInvMatF[5];
|
||||
dst->mVec[2] = sx * map->mInvMatF[6] + sy * map->mInvMatF[7] + sz * map->mInvMatF[8];
|
||||
}
|
||||
|
||||
static void
|
||||
cnanovdb_map_applyJacobi(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_map *RESTRICT map, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
float sx = src->mVec[0];
|
||||
float sy = src->mVec[1];
|
||||
float sz = src->mVec[2];
|
||||
dst->mVec[0] = sx * map->mMatF[0] + sy * map->mMatF[1] + sz * map->mMatF[2];
|
||||
dst->mVec[1] = sx * map->mMatF[3] + sy * map->mMatF[4] + sz * map->mMatF[5];
|
||||
dst->mVec[2] = sx * map->mMatF[6] + sy * map->mMatF[7] + sz * map->mMatF[8];
|
||||
}
|
||||
|
||||
static void
|
||||
cnanovdb_map_applyInverseJacobi(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_map *RESTRICT map, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
float sx = src->mVec[0];
|
||||
float sy = src->mVec[1];
|
||||
float sz = src->mVec[2];
|
||||
dst->mVec[0] = sx * map->mInvMatF[0] + sy * map->mInvMatF[1] + sz * map->mInvMatF[2];
|
||||
dst->mVec[1] = sx * map->mInvMatF[3] + sy * map->mInvMatF[4] + sz * map->mInvMatF[5];
|
||||
dst->mVec[2] = sx * map->mInvMatF[6] + sy * map->mInvMatF[7] + sz * map->mInvMatF[8];
|
||||
}
|
||||
|
||||
static void
|
||||
cnanovdb_map_applyIJT(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_map *RESTRICT map, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
float sx = src->mVec[0];
|
||||
float sy = src->mVec[1];
|
||||
float sz = src->mVec[2];
|
||||
dst->mVec[0] = sx * map->mInvMatF[0] + sy * map->mInvMatF[3] + sz * map->mInvMatF[6];
|
||||
dst->mVec[1] = sx * map->mInvMatF[1] + sy * map->mInvMatF[4] + sz * map->mInvMatF[7];
|
||||
dst->mVec[2] = sx * map->mInvMatF[2] + sy * map->mInvMatF[5] + sz * map->mInvMatF[8];
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int64_t mByteOffset; // byte offset to the blind data, relative to the GridData.
|
||||
uint64_t mElementCount; // number of elements, e.g. point count
|
||||
uint32_t mFlags; // flags
|
||||
uint32_t mSemantic; // semantic meaning of the data.
|
||||
uint32_t mDataClass; // 4 bytes
|
||||
uint32_t mDataType; // 4 bytes
|
||||
char mName[256];
|
||||
uint8_t _reserved[CNANOVDB_ALIGNMENT_PADDING(sizeof(int64_t)+sizeof(uint64_t)+2*sizeof(uint32_t)+2*sizeof(uint32_t)+256*sizeof(char), CNANOVDB_DATA_ALIGNMENT)];
|
||||
} cnanovdb_gridblindmetadata;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t mMagic; // 8B magic to validate it is valid grid data.
|
||||
uint64_t mChecksum; // 8B. Checksum of grid buffer.
|
||||
uint32_t mVersion;// 4B. compacted major.minor.path version number.
|
||||
uint32_t mFlags; // 4B. flags for grid.
|
||||
uint32_t mGridIndex;// 4B. Index of this grid in the buffer
|
||||
uint32_t mGridCount; // 4B. Total number of grids in the buffer
|
||||
uint64_t mGridSize; // 8B. byte count of this entire grid occupied in the buffer.
|
||||
char mGridName[256]; // 256B
|
||||
cnanovdb_map mMap; // 264B. affine transformation between index and world space in both single and double precision
|
||||
double mBBox[6]; // 48B. floating-point bounds of active values in WORLD SPACE
|
||||
double mVoxelSize[3]; // 24B. size of a voxel in world units
|
||||
uint32_t mGridClass; // 4B.
|
||||
uint32_t mGridType; // 4B.
|
||||
uint64_t mBlindMetadataOffset; // 8B. offset of GridBlindMetaData structures.
|
||||
int32_t mBlindMetadataCount; // 4B. count of GridBlindMetaData structures.
|
||||
uint32_t _reserved[CNANOVDB_ALIGNMENT_PADDING(8 + 8 + 4 + 4 + 4 + 4 + 8 + 256 + 24 + 24 + sizeof(cnanovdb_map) + 24 + 4 + 4 + 8 + 4, CNANOVDB_DATA_ALIGNMENT) / 4];
|
||||
} cnanovdb_griddata;
|
||||
|
||||
static void
|
||||
cnanovdb_griddata_worldToIndex(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_griddata *RESTRICT grid, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
cnanovdb_map_applyInverse(dst, &grid->mMap, src);
|
||||
}
|
||||
|
||||
static void
|
||||
cnanovdb_griddata_indexToWorld(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_griddata *RESTRICT grid, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
cnanovdb_map_apply(dst, &grid->mMap, src);
|
||||
}
|
||||
|
||||
static void
|
||||
cnanovdb_griddata_worldToIndexDir(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_griddata *RESTRICT grid, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
cnanovdb_map_applyInverseJacobi(dst, &grid->mMap, src);
|
||||
}
|
||||
|
||||
static void
|
||||
cnanovdb_griddata_indexToWorldDir(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_griddata *RESTRICT grid, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
cnanovdb_map_applyJacobi(dst, &grid->mMap, src);
|
||||
}
|
||||
|
||||
static void
|
||||
cnanovdb_griddata_applyIJT(cnanovdb_Vec3F *dst, const CNANOVDB_GLOBAL cnanovdb_griddata *RESTRICT grid, const cnanovdb_Vec3F *src)
|
||||
{
|
||||
cnanovdb_map_applyIJT(dst, &grid->mMap, src);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t mNodeOffset[ROOT_LEVEL + 1];
|
||||
uint32_t mNodeCount[ROOT_LEVEL];
|
||||
uint32_t mTileCount[ROOT_LEVEL];
|
||||
uint64_t mVoxelCount;
|
||||
uint8_t _reserved[CNANOVDB_ALIGNMENT_PADDING(4*sizeof(uint64_t)+(3+3)*sizeof(uint32_t)+sizeof(uint64_t), CNANOVDB_DATA_ALIGNMENT)];
|
||||
} cnanovdb_treedata;
|
||||
|
||||
static const CNANOVDB_GLOBAL cnanovdb_treedata *
|
||||
cnanovdb_griddata_tree(const CNANOVDB_GLOBAL cnanovdb_griddata *RESTRICT griddata)
|
||||
{
|
||||
return (const CNANOVDB_GLOBAL cnanovdb_treedata *)(griddata + 1);
|
||||
}
|
||||
|
||||
#define CREATE_TILEENTRY(VALUETYPE, SUFFIX) \
|
||||
typedef union \
|
||||
{ \
|
||||
VALUETYPE value; \
|
||||
uint64_t child; \
|
||||
} cnanovdb_tileentry##SUFFIX; \
|
||||
/**/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cnanovdb_coord mKey;
|
||||
const CNANOVDB_GLOBAL void *mNode[4];
|
||||
} cnanovdb_readaccessor;
|
||||
|
||||
|
||||
static void
|
||||
cnanovdb_readaccessor_insert(cnanovdb_readaccessor *RESTRICT acc, int childlevel, const CNANOVDB_GLOBAL void *RESTRICT node, const cnanovdb_coord *RESTRICT ijk)
|
||||
{
|
||||
acc->mNode[childlevel] = node;
|
||||
acc->mKey.mVec[0] = ijk->mVec[0];
|
||||
acc->mKey.mVec[1] = ijk->mVec[1];
|
||||
acc->mKey.mVec[2] = ijk->mVec[2];
|
||||
}
|
||||
|
||||
#define CREATE_LEAF_NODE_int(LEVEL, LOG2DIM, CHILDTOTAL, TOTAL, MASK, VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
typedef struct \
|
||||
{ \
|
||||
cnanovdb_coord mBBox_min; \
|
||||
uint8_t mBBoxDif[3]; \
|
||||
uint8_t mFlags; \
|
||||
cnanovdb_mask##LOG2DIM mValueMask; \
|
||||
VALUETYPE mMinimum; \
|
||||
VALUETYPE mMaximum; \
|
||||
STATSTYPE mAverage; \
|
||||
STATSTYPE mStdDevi; \
|
||||
uint32_t _reserved[ CNANOVDB_ALIGNMENT_PADDING(sizeof(cnanovdb_mask##LOG2DIM)+2*sizeof(VALUETYPE)+2*sizeof(STATSTYPE)+sizeof(cnanovdb_coord)+sizeof(uint8_t[3])+sizeof(uint8_t), CNANOVDB_DATA_ALIGNMENT)/4]; \
|
||||
VALUETYPE mVoxels[1u << (3*LOG2DIM)]; \
|
||||
} cnanovdb_node##LEVEL##SUFFIX; \
|
||||
\
|
||||
static uint32_t \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
return ( ( ( ijk->mVec[0] & MASK ) >> CHILDTOTAL ) << ( 2 * LOG2DIM ) ) + \
|
||||
( ( ( ijk->mVec[1] & MASK ) >> CHILDTOTAL ) << ( LOG2DIM ) ) + \
|
||||
( ( ijk->mVec[2] & MASK ) >> CHILDTOTAL ); \
|
||||
} \
|
||||
\
|
||||
static VALUETYPE \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_getValue(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
|
||||
return node->mVoxels[n]; \
|
||||
} \
|
||||
\
|
||||
static VALUETYPE \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_getValueAndCache(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT /* DO NOT REMOVE: Required for C99 compliance */ acc) \
|
||||
{ \
|
||||
(void)(acc); \
|
||||
uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
|
||||
return node->mVoxels[n]; \
|
||||
} \
|
||||
\
|
||||
static bool \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_isActive(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
|
||||
if (cnanovdb_mask##LOG2DIM##_isOn(&node->mValueMask, n)) \
|
||||
return true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
static bool \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_isActiveAndCache(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT /* DO NOT REMOVE: Required for C99 compliance */ acc) \
|
||||
{ \
|
||||
(void)(acc); \
|
||||
uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
|
||||
if (cnanovdb_mask##LOG2DIM##_isOn(&node->mValueMask, n)) \
|
||||
return true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
static const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX * \
|
||||
cnanovdb_tree_getNode##LEVEL##SUFFIX(const CNANOVDB_GLOBAL cnanovdb_treedata *RESTRICT tree, uint64_t i) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *basenode = (const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *)((CNANOVDB_GLOBAL uint8_t *)(tree) + tree->mNodeOffset[LEVEL]); \
|
||||
return basenode + i; \
|
||||
} \
|
||||
\
|
||||
/**/
|
||||
|
||||
#define CREATE_LEAF_NODE(LEVEL, LOG2DIM, TOTAL, VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
CREATE_LEAF_NODE_int(LEVEL, LOG2DIM, (TOTAL-LOG2DIM), TOTAL, ((1u << TOTAL) - 1u), VALUETYPE, STATSTYPE, SUFFIX)
|
||||
|
||||
#define CREATE_INTERNAL_NODE_int(CHILDLEVEL, LEVEL, LOG2DIM, CHILDTOTAL, TOTAL, MASK, VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
typedef struct \
|
||||
{ \
|
||||
cnanovdb_coord mBBox_min, mBBox_max; \
|
||||
int32_t mOffset; \
|
||||
uint32_t mFlags; \
|
||||
cnanovdb_mask##LOG2DIM mValueMask, mChildMask; \
|
||||
VALUETYPE mMinimum, mMaximum; \
|
||||
STATSTYPE mAverage, mStdDevi; \
|
||||
uint8_t _reserved[CNANOVDB_ALIGNMENT_PADDING(sizeof(cnanovdb_mask##LOG2DIM)+sizeof(VALUETYPE)*2+sizeof(STATSTYPE)*2+sizeof(cnanovdb_coord)*2+sizeof(int32_t)+sizeof(uint32_t), CNANOVDB_DATA_ALIGNMENT)]; \
|
||||
cnanovdb_tileentry##SUFFIX mTable[1u << (3*LOG2DIM)]; \
|
||||
} cnanovdb_node##LEVEL##SUFFIX; \
|
||||
\
|
||||
static uint32_t \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
return ( ( ( ijk->mVec[0] & MASK ) >> CHILDTOTAL ) << ( 2 * LOG2DIM ) ) + \
|
||||
( ( ( ijk->mVec[1] & MASK ) >> CHILDTOTAL ) << ( LOG2DIM ) ) + \
|
||||
( ( ijk->mVec[2] & MASK ) >> CHILDTOTAL ); \
|
||||
} \
|
||||
\
|
||||
static const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX * \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_getChild(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, uint32_t n) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *childnode = (const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *)( ((CNANOVDB_GLOBAL uint8_t *)node) + node->mTable[n].child); \
|
||||
return childnode; \
|
||||
} \
|
||||
\
|
||||
static VALUETYPE \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_getValue(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
|
||||
if (cnanovdb_mask##LOG2DIM##_isOn(&node->mChildMask, n)) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *child = cnanovdb_node##LEVEL##SUFFIX##_getChild(node, n); \
|
||||
return cnanovdb_node##CHILDLEVEL##SUFFIX##_getValue(child, ijk); \
|
||||
} \
|
||||
return node->mTable[n].value; \
|
||||
} \
|
||||
\
|
||||
static VALUETYPE \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_getValueAndCache(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT acc) \
|
||||
{ \
|
||||
uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
|
||||
if (cnanovdb_mask##LOG2DIM##_isOn(&node->mChildMask, n)) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *child = cnanovdb_node##LEVEL##SUFFIX##_getChild(node, n); \
|
||||
cnanovdb_readaccessor_insert(acc, CHILDLEVEL, child, ijk); \
|
||||
return cnanovdb_node##CHILDLEVEL##SUFFIX##_getValueAndCache(child, ijk, acc); \
|
||||
} \
|
||||
return node->mTable[n].value; \
|
||||
} \
|
||||
\
|
||||
static bool \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_isActive(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
|
||||
if (cnanovdb_mask##LOG2DIM##_isOn(&node->mChildMask, n)) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *child = cnanovdb_node##LEVEL##SUFFIX##_getChild(node, n); \
|
||||
return cnanovdb_node##CHILDLEVEL##SUFFIX##_isActive(child, ijk); \
|
||||
} \
|
||||
return cnanovdb_mask##LOG2DIM##_isOn(&node->mValueMask, n) ? true : false; \
|
||||
} \
|
||||
\
|
||||
static bool \
|
||||
cnanovdb_node##LEVEL##SUFFIX##_isActiveAndCache(const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *RESTRICT node, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT acc) \
|
||||
{ \
|
||||
uint32_t n = cnanovdb_node##LEVEL##SUFFIX##_CoordToOffset(ijk); \
|
||||
if (cnanovdb_mask##LOG2DIM##_isOn(&node->mChildMask, n)) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_node##CHILDLEVEL##SUFFIX *child = cnanovdb_node##LEVEL##SUFFIX##_getChild(node, n); \
|
||||
cnanovdb_readaccessor_insert(acc, CHILDLEVEL, child, ijk); \
|
||||
return cnanovdb_node##CHILDLEVEL##SUFFIX##_isActiveAndCache(child, ijk, acc); \
|
||||
} \
|
||||
return cnanovdb_mask##LOG2DIM##_isOn(&node->mValueMask, n) ? true : false; \
|
||||
} \
|
||||
\
|
||||
static const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX * \
|
||||
cnanovdb_tree_getNode##LEVEL##SUFFIX(const CNANOVDB_GLOBAL cnanovdb_treedata *RESTRICT tree, uint64_t i) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *basenode = (const CNANOVDB_GLOBAL cnanovdb_node##LEVEL##SUFFIX *)((CNANOVDB_GLOBAL uint8_t *)(tree) + tree->mNodeOffset[LEVEL]); \
|
||||
return basenode + i; \
|
||||
} \
|
||||
\
|
||||
/**/
|
||||
|
||||
#define CREATE_INTERNAL_NODE(CHILDLEVEL, LEVEL, LOG2DIM, TOTAL, VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
CREATE_INTERNAL_NODE_int(CHILDLEVEL, LEVEL, LOG2DIM, (TOTAL-LOG2DIM), TOTAL, ((1u << TOTAL) - 1u), VALUETYPE, STATSTYPE, SUFFIX)
|
||||
|
||||
|
||||
#ifdef USE_SINGLE_ROOT_KEY
|
||||
#define DEFINE_KEY(KEY) \
|
||||
uint64_t KEY;
|
||||
#define KEYSIZE sizeof(uint64_t)
|
||||
|
||||
#define KEYSEARCH(SUFFIX) \
|
||||
uint64_t key; \
|
||||
key = cnanovdb_coord_to_key(ijk); \
|
||||
\
|
||||
for (int i = low; i < high; i++) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = tiles + i; \
|
||||
if (tile->key == key) \
|
||||
return tile; \
|
||||
} \
|
||||
/**/
|
||||
#else
|
||||
#define DEFINE_KEY(KEY) \
|
||||
cnanovdb_coord KEY;
|
||||
#define KEYSIZE sizeof(cnanovdb_coord)
|
||||
#define KEYSEARCH(SUFFIX) \
|
||||
cnanovdb_coord key; \
|
||||
cnanovdb_coord_to_key(&key, ijk); \
|
||||
\
|
||||
while (low != high) \
|
||||
{ \
|
||||
int32_t mid = low + (( high - low ) >> 1 ); \
|
||||
const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = tiles + mid; \
|
||||
\
|
||||
int keycmp = cnanovdb_coord_compare(&tile->key, &key); \
|
||||
if (keycmp == 0) \
|
||||
{ \
|
||||
return tile; \
|
||||
} \
|
||||
\
|
||||
if (keycmp < 0) \
|
||||
low = mid + 1; \
|
||||
else \
|
||||
high = mid; \
|
||||
} \
|
||||
/**/
|
||||
#endif
|
||||
|
||||
|
||||
#define CREATE_ROOTDATA(VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
typedef struct \
|
||||
{ \
|
||||
DEFINE_KEY(key); \
|
||||
int64_t child; \
|
||||
uint32_t state; \
|
||||
VALUETYPE value; \
|
||||
uint8_t _reserved[CNANOVDB_ALIGNMENT_PADDING(sizeof(KEYSIZE)+sizeof(VALUETYPE)+sizeof(int64_t)+sizeof(uint32_t), CNANOVDB_DATA_ALIGNMENT)]; \
|
||||
} cnanovdb_rootdata_tile##SUFFIX; \
|
||||
\
|
||||
typedef struct \
|
||||
{ \
|
||||
cnanovdb_coord mBBox_min, mBBox_max; \
|
||||
uint32_t mTableSize; \
|
||||
VALUETYPE mBackground; \
|
||||
VALUETYPE mMinimum, mMaximum; \
|
||||
STATSTYPE mAverage, mStdDevi; \
|
||||
uint32_t _reserved[CNANOVDB_ALIGNMENT_PADDING(sizeof(cnanovdb_coord)*2+sizeof(uint32_t)+sizeof(VALUETYPE)*3+sizeof(STATSTYPE)*2, CNANOVDB_DATA_ALIGNMENT)/4]; \
|
||||
} cnanovdb_rootdata##SUFFIX; \
|
||||
\
|
||||
static const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX * \
|
||||
cnanovdb_treedata_root##SUFFIX(const CNANOVDB_GLOBAL cnanovdb_treedata *RESTRICT treedata) \
|
||||
{ \
|
||||
return (const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *) ((const CNANOVDB_GLOBAL uint8_t *)(treedata) + treedata->mNodeOffset[ROOT_LEVEL]); \
|
||||
} \
|
||||
\
|
||||
static const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX * \
|
||||
cnanovdb_rootdata##SUFFIX##_getTile(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, uint32_t n) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *basetile = (const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *) (rootdata + 1); \
|
||||
return basetile + n; \
|
||||
} \
|
||||
\
|
||||
static const CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX * \
|
||||
cnanovdb_rootdata##SUFFIX##_getChild(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *RESTRICT tile) \
|
||||
{ \
|
||||
CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *basenode = (CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *) (((CNANOVDB_GLOBAL uint8_t *) rootdata) + tile->child); \
|
||||
return basenode; \
|
||||
} \
|
||||
\
|
||||
static const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX * \
|
||||
cnanovdb_rootdata##SUFFIX##_findTile(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
int32_t low = 0, high = rootdata->mTableSize; \
|
||||
const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tiles = cnanovdb_rootdata##SUFFIX##_getTile(rootdata, 0); \
|
||||
\
|
||||
KEYSEARCH(SUFFIX) \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static VALUETYPE \
|
||||
cnanovdb_rootdata##SUFFIX##_getValue(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = cnanovdb_rootdata##SUFFIX##_findTile(rootdata, ijk); \
|
||||
if (!tile) \
|
||||
return rootdata->mBackground; \
|
||||
if (tile->child == 0) \
|
||||
return tile->value; \
|
||||
return cnanovdb_node2##SUFFIX##_getValue( cnanovdb_rootdata##SUFFIX##_getChild(rootdata, tile), ijk ); \
|
||||
} \
|
||||
\
|
||||
static VALUETYPE \
|
||||
cnanovdb_rootdata##SUFFIX##_getValueAndCache(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT acc) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = cnanovdb_rootdata##SUFFIX##_findTile(rootdata, ijk); \
|
||||
if (!tile) \
|
||||
return rootdata->mBackground; \
|
||||
if (tile->child == 0) \
|
||||
return tile->value; \
|
||||
const CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *child = cnanovdb_rootdata##SUFFIX##_getChild(rootdata, tile); \
|
||||
cnanovdb_readaccessor_insert(acc, 2, child, ijk); \
|
||||
return cnanovdb_node2##SUFFIX##_getValueAndCache( child, ijk, acc ); \
|
||||
} \
|
||||
\
|
||||
static bool \
|
||||
cnanovdb_rootdata##SUFFIX##_isActive(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = cnanovdb_rootdata##SUFFIX##_findTile(rootdata, ijk); \
|
||||
if (!tile) \
|
||||
return false; \
|
||||
if (tile->child == 0) \
|
||||
return tile->state; \
|
||||
return cnanovdb_node2##SUFFIX##_isActive( cnanovdb_rootdata##SUFFIX##_getChild(rootdata, tile), ijk ); \
|
||||
} \
|
||||
\
|
||||
static bool \
|
||||
cnanovdb_rootdata##SUFFIX##_isActiveAndCache(const CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *RESTRICT rootdata, const cnanovdb_coord *RESTRICT ijk, cnanovdb_readaccessor *RESTRICT acc) \
|
||||
{ \
|
||||
const CNANOVDB_GLOBAL cnanovdb_rootdata_tile##SUFFIX *tile = cnanovdb_rootdata##SUFFIX##_findTile(rootdata, ijk); \
|
||||
if (!tile) \
|
||||
return false; \
|
||||
if (tile->child == 0) \
|
||||
return tile->state; \
|
||||
const CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *child = cnanovdb_rootdata##SUFFIX##_getChild(rootdata, tile); \
|
||||
cnanovdb_readaccessor_insert(acc, 2, child, ijk); \
|
||||
return cnanovdb_node2##SUFFIX##_isActiveAndCache( child, ijk, acc ); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
|
||||
inline void
|
||||
cnanovdb_readaccessor_init(cnanovdb_readaccessor *RESTRICT acc,
|
||||
const CNANOVDB_GLOBAL void /*cnanovdb_rootdata* */ *RESTRICT rootdata)
|
||||
{
|
||||
acc->mNode[0] = acc->mNode[1] = acc->mNode[2] = 0;
|
||||
acc->mNode[3] = rootdata;
|
||||
}
|
||||
|
||||
#define DEFINE_ISCACHED(LEVEL, MASK) \
|
||||
inline bool \
|
||||
cnanovdb_readaccessor_isCached##LEVEL(cnanovdb_readaccessor *RESTRICT acc, int32_t dirty) \
|
||||
{ \
|
||||
if (!acc->mNode[LEVEL]) \
|
||||
return false; \
|
||||
if (dirty & ~MASK) \
|
||||
{ \
|
||||
acc->mNode[LEVEL] = 0; \
|
||||
return false; \
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
/**/
|
||||
|
||||
DEFINE_ISCACHED(0, ((1u << 3) - 1u) )
|
||||
DEFINE_ISCACHED(1, ((1u << 7) - 1u) )
|
||||
DEFINE_ISCACHED(2, ((1u << 12) - 1u) )
|
||||
|
||||
inline int32_t
|
||||
cnanovdb_readaccessor_computeDirty(const cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_coord *RESTRICT ijk)
|
||||
{
|
||||
return (ijk->mVec[0] ^ acc->mKey.mVec[0]) |
|
||||
(ijk->mVec[1] ^ acc->mKey.mVec[1]) |
|
||||
(ijk->mVec[2] ^ acc->mKey.mVec[2]);
|
||||
}
|
||||
|
||||
#define CREATE_ACCESSOR(VALUETYPE, SUFFIX) \
|
||||
inline VALUETYPE \
|
||||
cnanovdb_readaccessor_getValue##SUFFIX(cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
int32_t dirty = cnanovdb_readaccessor_computeDirty(acc, ijk); \
|
||||
\
|
||||
if (cnanovdb_readaccessor_isCached0(acc, dirty)) \
|
||||
return cnanovdb_node0##SUFFIX##_getValue( ((CNANOVDB_GLOBAL cnanovdb_node0##SUFFIX *) acc->mNode[0]), ijk); \
|
||||
if (cnanovdb_readaccessor_isCached1(acc, dirty)) \
|
||||
return cnanovdb_node1##SUFFIX##_getValueAndCache( ((CNANOVDB_GLOBAL cnanovdb_node1##SUFFIX *) acc->mNode[1]), ijk, acc); \
|
||||
if (cnanovdb_readaccessor_isCached2(acc, dirty)) \
|
||||
return cnanovdb_node2##SUFFIX##_getValueAndCache( ((CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *) acc->mNode[2]), ijk, acc); \
|
||||
\
|
||||
return cnanovdb_rootdata##SUFFIX##_getValueAndCache( ((CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *)acc->mNode[3]), ijk, acc); \
|
||||
} \
|
||||
\
|
||||
inline bool \
|
||||
cnanovdb_readaccessor_isActive##SUFFIX(cnanovdb_readaccessor *RESTRICT acc, const cnanovdb_coord *RESTRICT ijk) \
|
||||
{ \
|
||||
int32_t dirty = cnanovdb_readaccessor_computeDirty(acc, ijk); \
|
||||
\
|
||||
if (cnanovdb_readaccessor_isCached0(acc, dirty)) \
|
||||
return cnanovdb_node0##SUFFIX##_isActive( ((CNANOVDB_GLOBAL cnanovdb_node0##SUFFIX *) acc->mNode[0]), ijk); \
|
||||
if (cnanovdb_readaccessor_isCached1(acc, dirty)) \
|
||||
return cnanovdb_node1##SUFFIX##_isActiveAndCache( ((CNANOVDB_GLOBAL cnanovdb_node1##SUFFIX *) acc->mNode[1]), ijk, acc); \
|
||||
if (cnanovdb_readaccessor_isCached2(acc, dirty)) \
|
||||
return cnanovdb_node2##SUFFIX##_isActiveAndCache( ((CNANOVDB_GLOBAL cnanovdb_node2##SUFFIX *) acc->mNode[2]), ijk, acc); \
|
||||
\
|
||||
return cnanovdb_rootdata##SUFFIX##_isActiveAndCache( ((CNANOVDB_GLOBAL cnanovdb_rootdata##SUFFIX *)acc->mNode[3]), ijk, acc); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
|
||||
#define CREATE_GRIDTYPE(VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
CREATE_TILEENTRY(VALUETYPE, SUFFIX) \
|
||||
CREATE_LEAF_NODE(0, 3, 3, VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
CREATE_INTERNAL_NODE(0, 1, 4, 7, VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
CREATE_INTERNAL_NODE(1, 2, 5, 12, VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
CREATE_ROOTDATA(VALUETYPE, STATSTYPE, SUFFIX) \
|
||||
CREATE_ACCESSOR(VALUETYPE, SUFFIX) \
|
||||
/**/
|
||||
|
||||
CREATE_GRIDTYPE(float, float, F)
|
||||
CREATE_GRIDTYPE(cnanovdb_Vec3F, float, F3)
|
||||
|
||||
static int
|
||||
cnanovdb_griddata_valid(const CNANOVDB_GLOBAL cnanovdb_griddata *RESTRICT grid)
|
||||
{
|
||||
if (!grid)
|
||||
return 0;
|
||||
if (grid->mMagic != 0x304244566f6e614eUL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
cnanovdb_griddata_validF(const CNANOVDB_GLOBAL cnanovdb_griddata *RESTRICT grid)
|
||||
{
|
||||
if (!cnanovdb_griddata_valid(grid))
|
||||
return 0;
|
||||
if (grid->mGridType != cnanovdb_GridType_Float)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
cnanovdb_griddata_validF3(const CNANOVDB_GLOBAL cnanovdb_griddata *RESTRICT grid)
|
||||
{
|
||||
if (!cnanovdb_griddata_valid(grid))
|
||||
return 0;
|
||||
if (grid->mGridType != cnanovdb_GridType_Vec3f)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
<img src="https://www.openvdb.org/images/nanovdb_logo.png" height="150">
|
||||
|
||||
# NanoVDB:
|
||||
A lightweight GPU friendly version of VDB initially targeting rendering applications.
|
||||
|
||||
* [Build instructions for make and cmake](docs/HowToBuild.md)
|
||||
* [Frequently asked questions](docs/FAQ.md)
|
||||
* [Grid cells vs grid nodes](docs/GridCells_vs_GridNodes/Main.pdf)
|
||||
* [Source tree](docs/SourceTree.md)
|
||||
* [Examples](docs/HelloWorld.md)
|
||||
|
||||
### Copyright Contributors to the OpenVDB Project
|
||||
### SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
[](https://circleci.com/gh/NVIDIA-Omniverse/NanoVDB)
|
||||
@@ -0,0 +1,48 @@
|
||||
# Copyright Contributors to the OpenVDB Project
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
#[=======================================================================[
|
||||
|
||||
CMake Configuration for NanoVDB Command Line Tools
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(NanoVDBExamples LANGUAGES CXX)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
###############################################################################
|
||||
|
||||
message(STATUS "----------------------------------------------------")
|
||||
message(STATUS "--------- Configuring NanoVDB Cmd Tools ------------")
|
||||
message(STATUS "----------------------------------------------------")
|
||||
|
||||
###############################################################################
|
||||
# -----------------------------------------------------------------------------
|
||||
# workaround for win32 bug when nvcc "--keep" is used.
|
||||
if(WIN32 AND NANOVDB_CUDA_KEEP_PTX)
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/Release")
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
if(NOT NANOVDB_USE_OPENVDB)
|
||||
message(WARNING " - OpenVDB required to build nanovdb_convert. Skipping.")
|
||||
else()
|
||||
add_executable(nanovdb_convert convert/nanovdb_convert.cc)
|
||||
target_link_libraries(nanovdb_convert PRIVATE nanovdb)
|
||||
install(TARGETS nanovdb_convert RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# nanovdb_print
|
||||
add_executable(nanovdb_print print/nanovdb_print.cc)
|
||||
target_link_libraries(nanovdb_print PRIVATE nanovdb)
|
||||
install(TARGETS nanovdb_print RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# nanovdb_validate
|
||||
add_executable(nanovdb_validate validate/nanovdb_validate.cc)
|
||||
target_link_libraries(nanovdb_validate PRIVATE nanovdb)
|
||||
install(TARGETS nanovdb_validate RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
@@ -0,0 +1,311 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/*!
|
||||
\file nanovdb_convert.cc
|
||||
|
||||
\author Ken Museth
|
||||
|
||||
\date May 21, 2020
|
||||
|
||||
\brief Command-line tool that converts between openvdb and nanovdb files
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
#include <nanovdb/util/IO.h> // this is required to read (and write) NanoVDB files on the host
|
||||
#include <nanovdb/util/OpenToNanoVDB.h>
|
||||
#include <nanovdb/util/NanoToOpenVDB.h>
|
||||
|
||||
void usage [[noreturn]] (const std::string& progName, int exitStatus = EXIT_FAILURE)
|
||||
{
|
||||
std::cerr << "\nUsage: " << progName << " [options] *.vdb output.nvdb\n"
|
||||
<< "Which: converts one or more OpenVDB files to a single NanoVDB file\n\n"
|
||||
<< "Usage: " << progName << " [options] *.nvdb output.vdb\n"
|
||||
<< "Which: converts one or more NanoVDB files to a single OpenVDB file\n\n"
|
||||
<< "Options:\n"
|
||||
<< "-a,--abs-error float\t Absolute error tolerance used for variable bit depth quantization\n"
|
||||
<< "-b,--blosc\tUse BLOSC compression on the output file\n"
|
||||
<< "-c,--checksum mode\t where mode={none, partial, full}\n"
|
||||
<< "-d,--dither\tApply dithering during blocked compression\n"
|
||||
<< "-f,--force\tOverwrite output file if it already exists\n"
|
||||
<< "--fp4\tQuantize float grids to 4 bits\n"
|
||||
<< "--fp8\tQuantize float grids to 8 bits\n"
|
||||
<< "--fp16\tQuantize float grids to 16 bits\n"
|
||||
<< "--fpN\tQuantize float grids to variable bit depth (use -a or -r to specify a tolerance)\n"
|
||||
<< "-g,--grid name\tConvert all grids matching the specified string name\n"
|
||||
<< "-h,--help\tPrints this message\n"
|
||||
<< "-r,--rel-error float\t Relative error tolerance used for variable bit depth quantization\n"
|
||||
<< "-s,--stats mode\t where mode={none, bbox, extrema, all}\n"
|
||||
<< "-v,--verbose\tPrint verbose information to the terminal\n"
|
||||
<< "--version\tPrint version information to the terminal\n"
|
||||
<< "-z,--zip\tUse ZIP compression on the output file\n";
|
||||
exit(exitStatus);
|
||||
}
|
||||
|
||||
void version [[noreturn]] (const char* progName, int exitStatus = EXIT_SUCCESS)
|
||||
{
|
||||
printf("\n%s was build against NanoVDB version %s\n", progName, nanovdb::Version().c_str());
|
||||
exit(exitStatus);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int exitStatus = EXIT_SUCCESS;
|
||||
|
||||
nanovdb::io::Codec codec = nanovdb::io::Codec::NONE;// compression codec for the file
|
||||
nanovdb::StatsMode sMode = nanovdb::StatsMode::Default;
|
||||
nanovdb::ChecksumMode cMode = nanovdb::ChecksumMode::Default;
|
||||
nanovdb::GridType qMode = nanovdb::GridType::Unknown;//specify the quantization mode
|
||||
bool verbose = false, overwrite = false, dither = false, absolute = true;
|
||||
float tolerance = -1.0f;
|
||||
std::string gridName;
|
||||
std::vector<std::string> fileNames;
|
||||
auto toLowerCase = [](std::string &str) {
|
||||
std::transform(str.begin(), str.end(), str.begin(),[](unsigned char c){return std::tolower(c);});
|
||||
};
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string arg = argv[i];
|
||||
if (arg[0] == '-') {
|
||||
if (arg == "-v" || arg == "--verbose") {
|
||||
verbose = true;
|
||||
} else if (arg == "--version") {
|
||||
version(argv[0]);
|
||||
} else if (arg == "-f" || arg == "--force") {
|
||||
overwrite = true;
|
||||
} else if (arg == "--fp4") {
|
||||
qMode = nanovdb::GridType::Fp4;
|
||||
} else if (arg == "--fp8") {
|
||||
qMode = nanovdb::GridType::Fp8;
|
||||
} else if (arg == "--fp16") {
|
||||
qMode = nanovdb::GridType::Fp16;
|
||||
} else if (arg == "--fpN") {
|
||||
qMode = nanovdb::GridType::FpN;
|
||||
} else if (arg == "-h" || arg == "--help") {
|
||||
usage(argv[0], EXIT_SUCCESS);
|
||||
} else if (arg == "-b" || arg == "--blosc") {
|
||||
codec = nanovdb::io::Codec::BLOSC;
|
||||
} else if (arg == "-d" || arg == "--dither") {
|
||||
dither = true;
|
||||
} else if (arg == "-z" || arg == "--zip") {
|
||||
codec = nanovdb::io::Codec::ZIP;
|
||||
} else if (arg == "-c" || arg == "--checksum") {
|
||||
if (i + 1 == argc) {
|
||||
std::cerr << "Expected a mode to follow the -c,--checksum option\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
std::string str(argv[++i]);
|
||||
toLowerCase(str);
|
||||
if (str == "none") {
|
||||
cMode = nanovdb::ChecksumMode::Disable;
|
||||
} else if (str == "partial") {
|
||||
cMode = nanovdb::ChecksumMode::Partial;
|
||||
} else if (str == "full") {
|
||||
cMode = nanovdb::ChecksumMode::Full;
|
||||
} else {
|
||||
std::cerr << "Expected one of the following checksum modes: {none, partial, full}\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
} else if (arg == "-s" || arg == "--stats") {
|
||||
if (i + 1 == argc) {
|
||||
std::cerr << "Expected a mode to follow the -s,--stats option\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
std::string str(argv[++i]);
|
||||
toLowerCase(str);
|
||||
if (str == "none") {
|
||||
sMode = nanovdb::StatsMode::Disable;
|
||||
} else if (str == "bbox") {
|
||||
sMode = nanovdb::StatsMode::BBox;
|
||||
} else if (str == "extrema") {
|
||||
sMode = nanovdb::StatsMode::MinMax;
|
||||
} else if (str == "all") {
|
||||
sMode = nanovdb::StatsMode::All;
|
||||
} else {
|
||||
std::cerr << "Expected one of the following stats modes: {none, bbox, extrema, all}\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
} else if (arg == "-a" || arg == "--abs-error") {
|
||||
if (i + 1 == argc) {
|
||||
std::cerr << "Expected a float to follow the -a,--abs-error option\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
qMode = nanovdb::GridType::FpN;
|
||||
absolute = true;
|
||||
tolerance = atof(argv[++i]);
|
||||
}
|
||||
} else if (arg == "-r" || arg == "--rel-error") {
|
||||
if (i + 1 == argc) {
|
||||
std::cerr << "Expected a float to follow the -r,--rel-error option\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
qMode = nanovdb::GridType::FpN;
|
||||
absolute = false;
|
||||
tolerance = atof(argv[++i]);
|
||||
}
|
||||
} else if (arg == "-g" || arg == "--grid") {
|
||||
if (i + 1 == argc) {
|
||||
std::cerr << "Expected a grid name to follow the -g,--grid option\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
gridName.assign(argv[++i]);
|
||||
}
|
||||
} else {
|
||||
std::cerr << "\nIllegal option: \"" << arg << "\"\n";
|
||||
usage(argv[0]);
|
||||
}
|
||||
} else if (!arg.empty()) {
|
||||
fileNames.push_back(arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (fileNames.size() < 2) {
|
||||
std::cerr << "Expected at least one input file followed by exactly one output file\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
}
|
||||
const std::string outputFile = fileNames.back();
|
||||
const std::string ext = outputFile.substr(outputFile.find_last_of(".") + 1);
|
||||
bool toNanoVDB = false;
|
||||
if (ext == "nvdb") {
|
||||
toNanoVDB = true;
|
||||
} else if (ext != "vdb") {
|
||||
std::cerr << "Unrecognized file extension: \"" << ext << "\"\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
fileNames.pop_back();
|
||||
|
||||
if (!overwrite) {
|
||||
std::ifstream is(outputFile, std::ios::in | std::ios::binary);
|
||||
if (is.peek() != std::ifstream::traits_type::eof()) {
|
||||
std::cout << "Overwrite the existing output file named \"" << outputFile << "\"? [Y]/N: ";
|
||||
std::string answer;
|
||||
getline(std::cin, answer);
|
||||
toLowerCase(answer);
|
||||
if (!answer.empty() && answer != "y" && answer != "yes") {
|
||||
std::cout << "Please specify a different output file" << std::endl;
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
openvdb::initialize();
|
||||
|
||||
// Note, unlike OpenVDB, NanoVDB allows for multiple write operations into the same output file stream.
|
||||
// Hence, NanoVDB grids can be read, converted and written to file one at a time whereas all
|
||||
// the OpenVDB grids has to be written to file in a single operation.
|
||||
|
||||
auto openToNano = [&](const openvdb::GridBase::Ptr& base)
|
||||
{
|
||||
if (auto floatGrid = openvdb::GridBase::grid<openvdb::FloatGrid>(base)) {
|
||||
switch (qMode) {
|
||||
case nanovdb::GridType::Fp4: {
|
||||
nanovdb::OpenToNanoVDB<float, nanovdb::Fp4> s;
|
||||
s.enableDithering(dither);
|
||||
return s(*floatGrid, sMode, cMode, verbose ? 1 : 0);
|
||||
}
|
||||
case nanovdb::GridType::Fp8: {
|
||||
nanovdb::OpenToNanoVDB<float, nanovdb::Fp8> s;
|
||||
s.enableDithering(dither);
|
||||
return s(*floatGrid, sMode, cMode, verbose ? 1 : 0);
|
||||
}
|
||||
case nanovdb::GridType::Fp16: {
|
||||
nanovdb::OpenToNanoVDB<float, nanovdb::Fp16> s;
|
||||
s.enableDithering(dither);
|
||||
return s(*floatGrid, sMode, cMode, verbose ? 1 : 0);
|
||||
}
|
||||
case nanovdb::GridType::FpN: {
|
||||
if (absolute) {
|
||||
nanovdb::OpenToNanoVDB<float, nanovdb::FpN, nanovdb::AbsDiff> s;
|
||||
s.enableDithering(dither);
|
||||
s.oracle() = nanovdb::AbsDiff(tolerance);
|
||||
return s(*floatGrid, sMode, cMode, verbose ? 1 : 0);
|
||||
} else {
|
||||
nanovdb::OpenToNanoVDB<float, nanovdb::FpN, nanovdb::RelDiff> s;
|
||||
s.enableDithering(dither);
|
||||
s.oracle() = nanovdb::RelDiff(tolerance);
|
||||
return s(*floatGrid, sMode, cMode, verbose ? 1 : 0);
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}// end of switch
|
||||
}
|
||||
return nanovdb::openToNanoVDB(base, sMode, cMode, verbose ? 1 : 0);
|
||||
};
|
||||
try {
|
||||
if (toNanoVDB) { // OpenVDB -> NanoVDB
|
||||
std::ofstream os(outputFile, std::ios::out | std::ios::binary);
|
||||
for (auto& inputFile : fileNames) {
|
||||
if (inputFile.substr(inputFile.find_last_of(".") + 1) != "vdb") {
|
||||
std::cerr << "Since the last file has extension .nvdb the remaining input files were expected to have extensions .vdb\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
}
|
||||
if (verbose)
|
||||
std::cout << "Opening OpenVDB file named \"" << inputFile << "\"" << std::endl;
|
||||
openvdb::io::File file(inputFile);
|
||||
file.open(false); //disable delayed loading
|
||||
if (gridName.empty()) {// convert all grid in the file
|
||||
auto grids = file.getGrids();
|
||||
for (auto& grid : *grids) {
|
||||
if (verbose) {
|
||||
std::cout << "Converting OpenVDB grid named \"" << grid->getName() << "\" to NanoVDB" << std::endl;
|
||||
}
|
||||
auto handle = openToNano(grid);
|
||||
nanovdb::io::writeGrid(os, handle, codec);
|
||||
} // loop over OpenVDB grids in file
|
||||
} else {// convert only grid with matching name
|
||||
auto grid = file.readGrid(gridName);
|
||||
if (verbose) {
|
||||
std::cout << "Converting OpenVDB grid named \"" << grid->getName() << "\" to NanoVDB" << std::endl;
|
||||
}
|
||||
auto handle = openToNano(grid);
|
||||
nanovdb::io::writeGrid(os, handle, codec);
|
||||
}
|
||||
} // loop over input files
|
||||
} else { // NanoVDB -> OpenVDB
|
||||
openvdb::io::File file(outputFile);
|
||||
openvdb::GridPtrVecPtr grids(new openvdb::GridPtrVec());
|
||||
for (auto& inputFile : fileNames) {
|
||||
if (inputFile.substr(inputFile.find_last_of(".") + 1) != "nvdb") {
|
||||
std::cerr << "Since the last file has extension .vdb the remaining input files were expected to have extensions .nvdb\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
}
|
||||
if (verbose)
|
||||
std::cout << "Opening NanoVDB file named \"" << inputFile << "\"" << std::endl;
|
||||
if (gridName.empty()) {
|
||||
auto handles = nanovdb::io::readGrids(inputFile, verbose);
|
||||
for (auto &h : handles) {
|
||||
if (verbose)
|
||||
std::cout << "Converting NanoVDB grid named \"" << h.gridMetaData()->shortGridName() << "\" to OpenVDB" << std::endl;
|
||||
grids->push_back(nanoToOpenVDB(h));
|
||||
}
|
||||
} else {
|
||||
auto handle = nanovdb::io::readGrid(inputFile, gridName);
|
||||
if (!handle) {
|
||||
std::cerr << "File did not contain a NanoVDB grid named \"" << gridName << "\"\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
}
|
||||
if (verbose)
|
||||
std::cout << "Converting NanoVDB grid named \"" << handle.gridMetaData()->shortGridName() << "\" to OpenVDB" << std::endl;
|
||||
grids->push_back(nanoToOpenVDB(handle));
|
||||
}
|
||||
} // loop over input files
|
||||
file.write(*grids);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
exitStatus = EXIT_FAILURE;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Exception oof unexpected type caught" << std::endl;
|
||||
exitStatus = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/*!
|
||||
\file nanovdb_print.cc
|
||||
|
||||
\author Ken Museth
|
||||
|
||||
\date May 21, 2020
|
||||
|
||||
\brief Command-line tool that prints information about grids in a nanovdb file
|
||||
*/
|
||||
|
||||
#include <nanovdb/util/IO.h> // this is required to read (and write) NanoVDB files on the host
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
void usage [[noreturn]] (const std::string& progName, int exitStatus = EXIT_FAILURE)
|
||||
{
|
||||
std::cerr << "\nUsage: " << progName << " [options] *.nvdb\n"
|
||||
<< "Which: Prints grid information from one or more NanoVDB files\n\n"
|
||||
<< "Options:\n"
|
||||
<< "-g,--grid name\tPrint all grids matching the specified string name\n"
|
||||
<< "-h,--help\tPrints this message\n"
|
||||
<< "-l,--long\tPrints out extra grid information\n"
|
||||
<< "-s,--short\tOnly prints out a minimum amount of grid information\n"
|
||||
<< "-v,--verbose\tPrint information about the meaning of the labels\n"
|
||||
<< "--version\tPrint version information to the terminal\n";
|
||||
exit(exitStatus);
|
||||
}
|
||||
|
||||
void version [[noreturn]] (const char* progName, int exitStatus = EXIT_SUCCESS)
|
||||
{
|
||||
printf("\n%s was build against NanoVDB version %s\n", progName, nanovdb::Version().c_str());
|
||||
exit(exitStatus);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int exitStatus = EXIT_SUCCESS;
|
||||
|
||||
enum Mode : int { Short = 0,
|
||||
Default = 1,
|
||||
Long = 2 } mode = Default;
|
||||
bool verbose = false;
|
||||
std::string gridName;
|
||||
std::vector<std::string> fileNames;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string arg = argv[i];
|
||||
if (arg[0] == '-') {
|
||||
if (arg == "-h" || arg == "--help") {
|
||||
usage(argv[0], EXIT_SUCCESS);
|
||||
} else if (arg == "--version") {
|
||||
version(argv[0]);
|
||||
} else if (arg == "-s" || arg == "--short") {
|
||||
mode = Short;
|
||||
} else if (arg == "-l" || arg == "--long") {
|
||||
mode = Long;
|
||||
} else if (arg == "-v" || arg == "--verbose") {
|
||||
verbose = true;
|
||||
} else if (arg == "-g" || arg == "--grid") {
|
||||
if (i + 1 == argc) {
|
||||
std::cerr << "\nExpected a grid name to follow the -g,--grid option\n";
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
gridName.assign(argv[++i]);
|
||||
}
|
||||
} else {
|
||||
std::cerr << "\nIllegal option: \"" << arg << "\"\n";
|
||||
usage(argv[0]);
|
||||
}
|
||||
} else if (!arg.empty()) {
|
||||
fileNames.push_back(arg);
|
||||
}
|
||||
}
|
||||
if (fileNames.size() == 0) {
|
||||
std::cerr << "\nExpected at least one input NanoVDB file\n";
|
||||
usage(argv[0]);
|
||||
}
|
||||
const auto nameKey = nanovdb::io::stringHash(gridName);
|
||||
|
||||
auto format = [](uint64_t b) {
|
||||
std::stringstream ss;
|
||||
ss << std::setprecision(4);
|
||||
if (b >> 40) {
|
||||
ss << double(b) / double(1ULL << 40) << " TB";
|
||||
} else if (b >> 30) {
|
||||
ss << double(b) / double(1ULL << 30) << " GB";
|
||||
} else if (b >> 20) {
|
||||
ss << double(b) / double(1ULL << 20) << " MB";
|
||||
} else if (b >> 10) {
|
||||
ss << double(b) / double(1ULL << 10) << " KB";
|
||||
} else {
|
||||
ss << b << " Bytes";
|
||||
}
|
||||
return ss.str();
|
||||
};
|
||||
|
||||
const int padding = 2;
|
||||
|
||||
auto width = [&](size_t& n, const std::string& str) {
|
||||
const auto size = str.length() + padding;
|
||||
if (size > n)
|
||||
n = size;
|
||||
};
|
||||
auto vec3RToStr = [](const nanovdb::Vec3R& v) {
|
||||
std::stringstream ss;
|
||||
ss << std::setprecision(3);
|
||||
ss << "(" << v[0] << "," << v[1] << "," << v[2] << ")";
|
||||
return ss.str();
|
||||
};
|
||||
auto wbboxToStr = [](const nanovdb::BBox<nanovdb::Vec3d>& bbox) {
|
||||
std::stringstream ss;
|
||||
if (bbox.empty()) {
|
||||
ss << "empty grid";
|
||||
} else {
|
||||
ss << std::setprecision(3);
|
||||
ss << "(" << bbox[0][0] << "," << bbox[0][1] << "," << bbox[0][2] << ")";
|
||||
ss << " -> ";
|
||||
ss << "(" << bbox[1][0] << "," << bbox[1][1] << "," << bbox[1][2] << ")";
|
||||
}
|
||||
return ss.str();
|
||||
};
|
||||
auto ibboxToStr = [](const nanovdb::CoordBBox& bbox) {
|
||||
std::stringstream ss;
|
||||
if (bbox.empty()) {
|
||||
ss << "empty grid";
|
||||
} else {
|
||||
ss << "(" << bbox[0][0] << "," << bbox[0][1] << "," << bbox[0][2] << ")";
|
||||
ss << " -> ";
|
||||
ss << "(" << bbox[1][0] << "," << bbox[1][1] << "," << bbox[1][2] << ")";
|
||||
}
|
||||
return ss.str();
|
||||
};
|
||||
auto resToStr = [](const nanovdb::CoordBBox& bbox) {
|
||||
std::stringstream ss;
|
||||
auto dim = bbox.dim();
|
||||
ss << dim[0] << " x " << dim[1] << " x " << dim[2];
|
||||
return ss.str();
|
||||
};
|
||||
auto nodesToStr = [](const uint32_t* nodes) {
|
||||
std::stringstream ss;
|
||||
ss << nodes[2] << "->" << nodes[1] << "->" << nodes[0];
|
||||
return ss.str();
|
||||
};
|
||||
|
||||
try {
|
||||
for (auto& file : fileNames) {
|
||||
auto list = nanovdb::io::readGridMetaData(file);
|
||||
if (!gridName.empty()) {
|
||||
std::vector<nanovdb::io::GridMetaData> tmp;
|
||||
for (auto& m : list) {
|
||||
if (nameKey == m.nameKey && gridName == m.gridName)
|
||||
tmp.emplace_back(m);
|
||||
}
|
||||
list = tmp;
|
||||
}
|
||||
if (list.size() == 0)
|
||||
continue;
|
||||
const auto numberWidth = std::to_string(list.size()).length() + padding;
|
||||
auto nameWidth = std::string("Name").length() + padding;
|
||||
auto typeWidth = std::string("Type").length() + padding;
|
||||
auto classWidth = std::string("Class").length() + padding;
|
||||
auto codecWidth = std::string("Codec").length() + padding;
|
||||
auto ibboxWidth = std::string("Index Bounding Box").length() + padding;
|
||||
auto wbboxWidth = std::string("World BBox").length() + padding;
|
||||
auto sizeWidth = std::string("Size").length() + padding;
|
||||
auto fileWidth = std::string("File").length() + padding;
|
||||
auto voxelsWidth = std::string("# Voxels").length() + padding;
|
||||
auto voxelSizeWidth = std::string("Scale").length() + padding;
|
||||
auto versionWidth = std::string("Version").length() + padding;
|
||||
auto configWidth = std::string("32^3->16^3->8^3").length() + padding;
|
||||
auto tileWidth = std::string("# Active tiles").length() + padding;
|
||||
auto resWidth = std::string("Resolution").length() + padding;
|
||||
for (auto& m : list) {
|
||||
width(nameWidth, m.gridName);
|
||||
width(typeWidth, nanovdb::toStr(m.gridType));
|
||||
width(classWidth, nanovdb::toStr(m.gridClass));
|
||||
width(codecWidth, nanovdb::io::toStr(m.codec));
|
||||
width(wbboxWidth, wbboxToStr(m.worldBBox));
|
||||
width(ibboxWidth, ibboxToStr(m.indexBBox));
|
||||
width(resWidth, resToStr(m.indexBBox));
|
||||
width(sizeWidth, format(m.gridSize));
|
||||
width(fileWidth, format(m.fileSize));
|
||||
width(versionWidth, std::string(m.version.c_str()));
|
||||
width(configWidth, nodesToStr(m.nodeCount));
|
||||
width(tileWidth, nodesToStr(m.tileCount));
|
||||
width(voxelsWidth, std::to_string(m.voxelCount));
|
||||
width(voxelSizeWidth, vec3RToStr(m.voxelSize));
|
||||
}
|
||||
std::cout << "\nThe file \"" << file << "\" contains the following ";
|
||||
if (list.size()>1) {
|
||||
std::cout << list.size() << " grids:\n";
|
||||
} else {
|
||||
std::cout << "grid:\n";
|
||||
}
|
||||
std::cout << std::left << std::setw(numberWidth) << "#"
|
||||
<< std::left << std::setw(nameWidth) << "Name"
|
||||
<< std::left << std::setw(typeWidth) << "Type";
|
||||
if (mode != Short) {
|
||||
std::cout << std::left << std::setw(classWidth) << "Class"
|
||||
<< std::left << std::setw(versionWidth) << "Version"
|
||||
<< std::left << std::setw(codecWidth) << "Codec"
|
||||
<< std::left << std::setw(sizeWidth) << "Size"
|
||||
<< std::left << std::setw(fileWidth) << "File"
|
||||
<< std::left << std::setw(voxelSizeWidth) << "Scale";
|
||||
}
|
||||
std::cout << std::left << std::setw(voxelsWidth) << "# Voxels"
|
||||
<< std::left << std::setw(resWidth) << "Resolution";
|
||||
if (mode == Long) {
|
||||
std::cout << std::left << std::setw(configWidth) << "32^3->16^3->8^3"
|
||||
<< std::left << std::setw(tileWidth) << "# Active tiles"
|
||||
<< std::left << std::setw(ibboxWidth) << "Index Bounding Box"
|
||||
<< std::left << std::setw(wbboxWidth) << "World Bounding Box";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
int n = 0;
|
||||
for (auto& m : list) {
|
||||
if (!gridName.empty() && (nameKey != m.nameKey || gridName != m.gridName))
|
||||
continue;
|
||||
std::cout << std::left << std::setw(numberWidth) << ++n
|
||||
<< std::left << std::setw(nameWidth) << m.gridName
|
||||
<< std::left << std::setw(typeWidth) << nanovdb::toStr(m.gridType);
|
||||
if (mode != Short) {
|
||||
std::cout << std::left << std::setw(classWidth) << nanovdb::toStr(m.gridClass)
|
||||
<< std::left << std::setw(versionWidth) << std::string(m.version.c_str())
|
||||
<< std::left << std::setw(codecWidth) << nanovdb::io::toStr(m.codec)
|
||||
<< std::left << std::setw(sizeWidth) << format(m.gridSize)
|
||||
<< std::left << std::setw(fileWidth) << format(m.fileSize)
|
||||
<< std::left << std::setw(voxelSizeWidth) << vec3RToStr(m.voxelSize);
|
||||
}
|
||||
std::cout << std::left << std::setw(voxelsWidth) << m.voxelCount
|
||||
<< std::left << std::setw(resWidth) << resToStr(m.indexBBox);
|
||||
if (mode == Long) {
|
||||
std::cout << std::left << std::setw(configWidth) << nodesToStr(m.nodeCount)
|
||||
<< std::left << std::setw(tileWidth) << nodesToStr(m.tileCount)
|
||||
<< std::left << std::setw(ibboxWidth) << ibboxToStr(m.indexBBox)
|
||||
<< std::left << std::setw(wbboxWidth) << wbboxToStr(m.worldBBox);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
if (verbose) {
|
||||
size_t w = 0;
|
||||
switch (mode) {
|
||||
case Mode::Short:
|
||||
width(w, "\"Name\":");
|
||||
width(w, "\"Type\":");
|
||||
width(w, "\"# Voxels\":");
|
||||
width(w, "\"Resolution\":");
|
||||
std::cout << std::left << std::setw(w) << "\n\"Name\":" << "name of a grid. Note that it is optional and hence might be empty."
|
||||
<< std::left << std::setw(w) << "\n\"Type\":" << "static type of the values in a grid, e.g. float, vec3f etc."
|
||||
<< std::left << std::setw(w) << "\n\"# Voxels\":" << "total number of active values in a grid."
|
||||
<< std::left << std::setw(w) << "\n\"Resolution\":" << "Efficient resolution of all the active values in a grid!\n";
|
||||
break;
|
||||
case Mode::Default:
|
||||
width(w, "\"Name\":");
|
||||
width(w, "\"Type\":");
|
||||
width(w, "\"Class\":");
|
||||
width(w, "\"Version\":");
|
||||
width(w, "\"Codec\":");
|
||||
width(w, "\"Size\":");
|
||||
width(w, "\"File\":");
|
||||
width(w, "\"Scale\":");
|
||||
width(w, "\"# Voxels\":");
|
||||
width(w, "\"Resolution\":");
|
||||
std::cout << std::left << std::setw(w) << "\n\"Name\":" << "name of a grid. Note that it is optional and hence might be empty."
|
||||
<< std::left << std::setw(w) << "\n\"Type\":" << "static type of the values in a grid, e.g. float, vec3f etc."
|
||||
<< std::left << std::setw(w) << "\n\"Class\":" << "class of the grid, e.g. FOG for Fog volume, LS for level set, etc."
|
||||
<< std::left << std::setw(w) << "\n\"Version\":" << "major.minor.patch version numbers of the grid."
|
||||
<< std::left << std::setw(w) << "\n\"Codec\":" << "codec of the optional compression applied to the out-of-core grid, i.e. on disk."
|
||||
<< std::left << std::setw(w) << "\n\"Size\":" << "In-core memory footprint of the grid, i.e. in ram."
|
||||
<< std::left << std::setw(w) << "\n\"File\":" << "Out-of-core memory footprint of the grid, i.e. on disk."
|
||||
<< std::left << std::setw(w) << "\n\"Scale\":" << "Scale of the grid, i.e. the size of a voxel in world units."
|
||||
<< std::left << std::setw(w) << "\n\"# Voxels\":" << "total number of active values in a grid."
|
||||
<< std::left << std::setw(w) << "\n\"Resolution\":" << "Efficient resolution of all the active values in a grid!\n";
|
||||
break;
|
||||
case Mode::Long:
|
||||
width(w, "\"Name\":");
|
||||
width(w, "\"Type\":");
|
||||
width(w, "\"Class\":");
|
||||
width(w, "\"Version\":");
|
||||
width(w, "\"Codec\":");
|
||||
width(w, "\"Size\":");
|
||||
width(w, "\"File\":");
|
||||
width(w, "\"Scale\":");
|
||||
width(w, "\"# Voxels\":");
|
||||
width(w, "\"Resolution\":");
|
||||
width(w, "\"32^3->16^3->8^3\":");
|
||||
width(w, "\"# Active tiles\":");
|
||||
width(w, "\"Index Bounding Box\":");
|
||||
width(w, "\"World Bounding Box\":");
|
||||
std::cout << std::left << std::setw(w) << "\n\"Name\":" << "name of a grid. Note that it is optional and hence might be empty."
|
||||
<< std::left << std::setw(w) << "\n\"Type\":" << "static type of the values in a grid, e.g. float, vec3f etc."
|
||||
<< std::left << std::setw(w) << "\n\"Class\":" << "class of the grid, e.g. FOG for Fog volume, LS for level set, etc."
|
||||
<< std::left << std::setw(w) << "\n\"Version\":" << "major.minor.patch version numbers of the grid."
|
||||
<< std::left << std::setw(w) << "\n\"Codec\":" << "codec of the optional compression applied to the out-of-core grid, i.e. on disk."
|
||||
<< std::left << std::setw(w) << "\n\"Size\":" << "In-core memory footprint of the grid, e.g. in RAM on the CPU."
|
||||
<< std::left << std::setw(w) << "\n\"File\":" << "Out-of-core memory footprint of the grid, i.e. compressed on disk."
|
||||
<< std::left << std::setw(w) << "\n\"Scale\":" << "Scale of the grid, i.e. the size of a voxel in world units."
|
||||
<< std::left << std::setw(w) << "\n\"# Voxels\":" << "total number of active values in a grid. Note this includes both active tiles and voxels."
|
||||
<< std::left << std::setw(w) << "\n\"Resolution\":" << "Efficient resolution of all the active values in a grid!"
|
||||
<< std::left << std::setw(w) << "\n\"32^3->16^3->8^3\":" << "Number of nodes at each level of the tree structure from the root to leaf level."
|
||||
<< std::left << std::setw(w) << "\n\"# Active tiles\":" << "Number of active tiles at each level of the tree structure from the root to leaf level."
|
||||
<< std::left << std::setw(w) << "\n\"Index Bounding Box\":" << "coordinate bounding box of all the active values in a grid. Note that both min and max coordinates are inclusive!"
|
||||
<< std::left << std::setw(w) << "\n\"World Bounding Box\":" << "world-space bounding box of all the active values in a grid. Note that min is inclusive and max is exclusive!\n";
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Internal error in switch!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
exitStatus = EXIT_FAILURE;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Exception oof unexpected type caught" << std::endl;
|
||||
exitStatus = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/*!
|
||||
\file nanovdb_validate.cc
|
||||
|
||||
\author Ken Museth
|
||||
|
||||
\date October 13, 2020
|
||||
|
||||
\brief Command-line tool that validates Grids in nanovdb files
|
||||
*/
|
||||
|
||||
#include <nanovdb/util/IO.h> // this is required to read (and write) NanoVDB files on the host
|
||||
#include <nanovdb/util/GridValidator.h>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
void usage [[noreturn]] (const std::string& progName, int exitStatus = EXIT_FAILURE)
|
||||
{
|
||||
std::cerr << "\nUsage: " << progName << " [options] *.nvdb\n"
|
||||
<< "Which: Validates grids in one or more NanoVDB files\n\n"
|
||||
<< "Options:\n"
|
||||
<< "-g,--grid name\tOnly validate grids matching the specified string name\n"
|
||||
<< "-h,--help\tPrints this message\n"
|
||||
<< "-v,--verbose\tPrint verbose information information useful for debugging\n"
|
||||
<< "--version\tPrint version information to the terminal\n";
|
||||
exit(exitStatus);
|
||||
}
|
||||
|
||||
void version [[noreturn]] (const char* progName, int exitStatus = EXIT_SUCCESS)
|
||||
{
|
||||
printf("\n%s was build against NanoVDB version %s\n", progName, nanovdb::Version().c_str());
|
||||
exit(exitStatus);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int exitStatus = EXIT_SUCCESS;
|
||||
|
||||
bool verbose = false;
|
||||
bool detailed = true;
|
||||
std::string gridName;
|
||||
std::vector<std::string> fileNames;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string arg = argv[i];
|
||||
if (arg[0] == '-') {
|
||||
if (arg == "-h" || arg == "--help") {
|
||||
usage(argv[0], EXIT_SUCCESS);
|
||||
} else if (arg == "--version") {
|
||||
version(argv[0]);
|
||||
} else if (arg == "-v" || arg == "--verbose") {
|
||||
verbose = true;
|
||||
} else if (arg == "-g" || arg == "--grid") {
|
||||
if (i + 1 == argc) {
|
||||
std::cerr << "\nExpected a grid name to follow the -g,--grid option\n";
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
gridName.assign(argv[++i]);
|
||||
}
|
||||
} else {
|
||||
std::cerr << "\nIllegal option: \"" << arg << "\"\n";
|
||||
usage(argv[0]);
|
||||
}
|
||||
} else if (!arg.empty()) {
|
||||
fileNames.push_back(arg);
|
||||
}
|
||||
}
|
||||
if (fileNames.size() == 0) {
|
||||
std::cerr << "\nExpected at least one input NanoVDB file\n";
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
const auto nameKey = nanovdb::io::stringHash(gridName);
|
||||
|
||||
try {
|
||||
for (auto& file : fileNames) {
|
||||
auto list = nanovdb::io::readGridMetaData(file);
|
||||
if (!gridName.empty()) {
|
||||
std::vector<nanovdb::io::GridMetaData> tmp;
|
||||
for (auto& m : list) {
|
||||
if (nameKey == m.nameKey && gridName == m.gridName)
|
||||
tmp.emplace_back(m);
|
||||
}
|
||||
list = tmp;
|
||||
}
|
||||
if (list.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "\nThe file \"" << file << "\" contains the following matching " << list.size() << " grid(s):\n";
|
||||
}
|
||||
|
||||
for (auto& m : list) {
|
||||
auto handle = nanovdb::io::readGrid(file, m.gridName);
|
||||
auto gridType = handle.gridType();
|
||||
bool test = false;
|
||||
if (gridType == nanovdb::GridType::End) {
|
||||
std::cerr << "GridHandle was empty\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
} else if (auto* grid = handle.grid<float>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<nanovdb::Vec3f>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<uint32_t>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<int32_t>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<int16_t>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<int64_t>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<int16_t>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<double>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<nanovdb::Vec3d>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<nanovdb::ValueMask>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<nanovdb::Rgba8>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<nanovdb::Fp4>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<nanovdb::Fp8>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<nanovdb::Fp16>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<nanovdb::FpN>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else if (auto* grid = handle.grid<bool>()) {
|
||||
test = isValid(*grid, detailed, verbose);
|
||||
} else {
|
||||
std::cerr << "Unsupported GridType: \"" << nanovdb::toStr(gridType) << "\"\n" << std::endl;
|
||||
usage(argv[0]);
|
||||
}
|
||||
if (verbose) {
|
||||
std::cout << "Grid named \"" << m.gridName << "\": " << (test ? "passed" : "failed") << std::endl;
|
||||
} else if (!test) {
|
||||
std::cout << "Grid named \"" << m.gridName << "\": failed" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
exitStatus = EXIT_FAILURE;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Exception oof unexpected type caught" << std::endl;
|
||||
exitStatus = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# find_package(doxygen REQUIRED dot )
|
||||
if(WIN32)
|
||||
set(DOXYGEN_EXECUTABLE "C:/Program Files/doxygen/bin/doxygen.exe")
|
||||
else()
|
||||
set(DOXYGEN_EXECUTABLE "doxygen")
|
||||
endif()
|
||||
|
||||
message(STATUS "DOXYGEN_EXECUTABLE = ${DOXYGEN_EXECUTABLE}")
|
||||
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/doxygen-config DOXYGEN_CONFIG_CONTENT)
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cmake-doxygen-config
|
||||
${DOXYGEN_CONFIG_CONTENT})
|
||||
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/cmake-doxygen-config
|
||||
"OUTPUT_DIRECTORY=\"${CMAKE_CURRENT_BINARY_DIR}/docs\"\n")
|
||||
|
||||
add_custom_target(
|
||||
nanovdb_docs
|
||||
SOURCES doxygen-config
|
||||
doc.md
|
||||
codingstyle.txt
|
||||
FAQ.md
|
||||
SourceTree.md
|
||||
HowToBuild.md
|
||||
HelloWorld.md
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/cmake-doxygen-config
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen"
|
||||
VERBATIM)
|
||||
|
||||
install(
|
||||
CODE "EXECUTE_PROCESS(COMMAND \"${CMAKE_COMMAND}\" --build \"${PROJECT_BINARY_DIR}\" --target nanovdb_docs)"
|
||||
)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/docs/html DESTINATION docs)
|
||||
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
|
||||
@page codingStyle Coding Style
|
||||
|
||||
@section Introduction
|
||||
|
||||
NanoVDB coding practices.
|
||||
|
||||
@section sStyleContents Contents
|
||||
- @ref sNamingConventions
|
||||
- @ref sNamespaceConventions
|
||||
- @ref sClassConventions
|
||||
- @ref sClassMethods
|
||||
- @ref sClassInstanceVariables
|
||||
- @ref sClassStaticVariables
|
||||
- @ref sLocalVariablesAndArguments
|
||||
- @ref sConstants
|
||||
- @ref sEnumerationNames
|
||||
- @ref sEnumerationValues
|
||||
- @ref sTypedefs
|
||||
- @ref sGlobalVariables
|
||||
- @ref sGlobalFunctions
|
||||
- @ref sBooleans
|
||||
- @ref sPractices
|
||||
- @ref sGeneral
|
||||
- @ref sFormatting
|
||||
- @ref sIncludeStatements
|
||||
- @ref sComments
|
||||
- @ref sPrimitiveTypes
|
||||
- @ref sMacros
|
||||
- @ref sClasses
|
||||
- @ref sConditionalStatements
|
||||
- @ref sNamespaces
|
||||
- @ref sExceptions
|
||||
- @ref sTemplates
|
||||
- @ref sMiscellaneous
|
||||
|
||||
@section sNamingConventions Naming Conventions
|
||||
|
||||
|
||||
@subsection sNamespaceConventions Namespaces
|
||||
-# Lowercase words, keep simple and short (e.g., @c tools, @c tree).
|
||||
-# Use @c internal (or @c detail) or <TT><I>module</I>_internal</TT>
|
||||
for symbols such as templates that must be defined in header files
|
||||
but that are implementation details not intended for public use.
|
||||
|
||||
|
||||
@subsection sClassConventions Classes and Structs
|
||||
-# Mixed case; first letter uppercase (e.g., @c AffineMap, @c TreeIterator)
|
||||
-# Do not use a prefix.
|
||||
|
||||
|
||||
@subsection sClassMethods Class Methods
|
||||
-# Mixed case; first letter lowercase (e.g., <TT>getAccessor()</TT>, <TT>gridType()</TT>)
|
||||
-# Accessor methods that return a member variable by reference or a primitive type
|
||||
by value are just the variable name (e.g., <TT>Grid::tree()</TT>).
|
||||
-# Accessor methods that involve construction of objects or other computations are
|
||||
@c get + the variable name (e.g., <TT>Grid::getAccessor()</TT>).
|
||||
-# Simple mutators are @c set + the variable name (e.g., <TT>Grid::setTree(tree);</TT>).
|
||||
|
||||
|
||||
@subsection sClassInstanceVariables Class Instance Variables
|
||||
-# Mixed case; always prefixed by @c m (e.g., @c mTree, @c mTransform)
|
||||
-# The @c m prefix may be omitted for members of <TT>struct</TT>s
|
||||
used in the public API (e.g., <TT>struct Color { float r, g, b; }</TT>).
|
||||
|
||||
|
||||
@subsection sClassStaticVariables Class Static Variables
|
||||
-# Mixed case; always prefixed by @c s (e.g., @c sInitialized)
|
||||
|
||||
|
||||
@subsection sLocalVariablesAndArguments Local Variables and Arguments
|
||||
-# Use mixed case with an initial lower case letter (e.g., @c ijk, @c offset,
|
||||
@c range, @c rhsValue).
|
||||
|
||||
|
||||
@subsection sConstants Constants
|
||||
-# All uppercase; words separated by underscores. If not in a namespace or
|
||||
local to a source file, then prefixed with the library name in all caps
|
||||
(e.g., @c HALF_FLOAT_TYPENAME_SUFFIX, @c ZIP_COMPRESSION_LEVEL)
|
||||
|
||||
|
||||
@subsection sEnumerationNames Enumeration Names
|
||||
-# Mixed case; first letter uppercase (e.g., @c GridClass, @c VecType)
|
||||
|
||||
|
||||
@subsection sEnumerationValues Enumeration Values
|
||||
-# With @c enum, all uppercase with words separated by underscores
|
||||
(e.g., @c GRID_LEVEL_SET, @c VEC_INVARIANT) and with a common prefix
|
||||
-# With <TT>enum class</TT>, mixed case with the first letter uppercase
|
||||
(e.g., @c GridClass::Unknown, @c GridClass::LevelSet)
|
||||
|
||||
|
||||
@subsection sTypedefs Typedefs
|
||||
-# Mixed case; first letter uppercase (e.g., @c ConstPtr, @c ValueType)
|
||||
-# Do not use a prefix.
|
||||
|
||||
|
||||
@subsection sGlobalVariables Global Variables
|
||||
-# Mixed case; always prefixed by @c g (e.g., @c gRegistry)
|
||||
-# In general, try to use class static data instead of globals.
|
||||
|
||||
|
||||
@subsection sGlobalFunctions Global Functions
|
||||
-# Mixed case; always prefixed by @c g (e.g., <TT>gFunc()</TT>).
|
||||
-# In general, try to use class static members instead of global functions.
|
||||
|
||||
|
||||
@subsection sBooleans Booleans
|
||||
-# When naming boolean functions and variables, use names that read as a
|
||||
condition (e.g., <TT>if (grid.empty())</TT>,
|
||||
<TT>if (matrix.isInvertible())</TT>).
|
||||
|
||||
|
||||
@section sPractices Practices
|
||||
|
||||
|
||||
@subsection sGeneral General
|
||||
-# Code must compile without any warning messages at the default warning level.
|
||||
-# Prefer the C++ Standard Library to the C Standard Library.
|
||||
-# Restrict variables to the smallest scopes possible, and avoid defining
|
||||
local variables before giving them values. Prefer declarations inside
|
||||
conditionals: <TT>if (Grid::Ptr grid = createGrid()) { ... }</TT> instead of
|
||||
<TT>Grid::Ptr grid = createGrid(); if (grid) { ... }</TT>
|
||||
-# For new files, be sure to use the right license boilerplate per our license
|
||||
policy.
|
||||
|
||||
|
||||
@subsection sFormatting Formatting
|
||||
-# Indentation is 4 spaces. Do not use tabs.
|
||||
-# Lines are no more than 100 characters long.
|
||||
-# Use Unix-style carriage returns ("\n") rather than Windows/DOS ones ("\r\n").
|
||||
-# Do not leave debug <TT>printf</TT>s or other debugging code lying around.
|
||||
-# Leave a blank line between a group of variable declarations and other code.
|
||||
-# Leave a space after the keywords @c if, @c switch, @c while, @c do, @c for,
|
||||
and @c return.
|
||||
-# Leave a space on each side of binary operators such as @c +, @c -, @c *, @c /, @c &&,
|
||||
and @c ||. For clarity in mathematical situations, you may omit the spaces on
|
||||
either side of @c * and @c / operators to emphasize their precedence over @c + and @c -.
|
||||
-# Do not leave a space between any dereferencing operator
|
||||
(such as @c *, @c &, @c [], @c ->, or @c .) and its operands.
|
||||
-# In parameter lists, leave a space after each comma.
|
||||
-# Do not leave a space after an opening parenthesis or before a closing
|
||||
parenthesis.
|
||||
-# Parentheses should be used to clarify operator precedence in expressions.
|
||||
-# Do not leave a space before an end-of-statement semicolon.
|
||||
-# Do not use literal tabs in strings or character constants. Rather, use
|
||||
spaces or "\t".
|
||||
-# If a parameter list is too long, break it between parameters. Group related
|
||||
parameters on lines if appropriate.
|
||||
-# Modified spacing is allowed to vertically align repetitive expressions.
|
||||
-# Always begin numeric constants with a digit (e.g., 0.001 not .001).
|
||||
-# Use K&R-style brace placement in public code.
|
||||
-# You may leave off braces for simple, single line flow control statements.
|
||||
-# The return type in a function definition should go on a line by itself.
|
||||
|
||||
|
||||
@subsection sIncludeStatements Include Statements
|
||||
-# Always use double quotes ("") to include header files that live in the same
|
||||
directory as your source code.
|
||||
-# Use angle brackets (<>) to include header files from outside a file’s
|
||||
directory.
|
||||
-# Do not use absolute paths in include directives.
|
||||
-# If there is a header corresponding to a given source file, list it first,
|
||||
followed by other local headers, library headers and then system headers.
|
||||
|
||||
|
||||
@subsection sHeaderFiles Header Files
|
||||
-# Header files have a <TT>.h</TT> extension.
|
||||
-# All header files should be bracketed by @c \#ifdef "guard" statements.
|
||||
-# In class definitions, list public, then protected, then private members.
|
||||
-# List methods before variables.
|
||||
-# Fully prototype all public functions and use descriptive naming for each
|
||||
argument.
|
||||
-# Declare every function defined in a header but outside a class definition
|
||||
explicitly as @c inline.
|
||||
-# Prefer forward declarations to @c \#include directives in headers.
|
||||
-# Do not take advantage of indirect inclusion of header files.
|
||||
-# Do not use anonymous namespaces in header files.
|
||||
|
||||
|
||||
@subsection sSourceFiles Source Files
|
||||
-# Source files have a <TT>.cc</TT> extension.
|
||||
-# Properly prototype all file static functions with usefully named arguments.
|
||||
-# Whenever possible, put variables and functions in an anonymous namespace.
|
||||
-# Avoid global variables.
|
||||
|
||||
|
||||
@subsection sComments Comments
|
||||
-# Use @c // style comments instead of / * * / style, even for multi-line
|
||||
comments.
|
||||
-# Use multi-line comments to describe following paragraphs of code.
|
||||
-# Use end-of-line comments to describe variable declarations or to clarify a
|
||||
single statement.
|
||||
-# Large blocks of code should be commented out with <TT>\#if 0</TT> and @c \#endif.
|
||||
-# Do not leave obsolete code fragments within comments as an historical trail.
|
||||
-# Document public code with Doxygen comments, formatted as follows:
|
||||
@verbatim
|
||||
/// @brief Create a new grid of type @c GridType classified as a "Level Set",
|
||||
/// i.e., a narrow-band level set.
|
||||
///
|
||||
/// @param voxelSize the size of a voxel in world units
|
||||
/// @param halfWidth the half width of the narrow band in voxel units
|
||||
///
|
||||
/// @details The voxel size and the narrow band half width define the grid's
|
||||
/// background value as halfWidth*voxelWidth. The transform is linear
|
||||
/// with a uniform scaling only corresponding to the specified voxel size.
|
||||
///
|
||||
/// @note It is generally advisable to specify a half-width of the narrow band
|
||||
/// that is larger than one voxel unit, otherwise zero crossings are not guaranteed.
|
||||
template<typename GridType>
|
||||
typename GridType::Ptr createLevelSet(
|
||||
Real voxelSize = 1.0, Real halfWidth = LEVEL_SET_HALF_WIDTH);
|
||||
@endverbatim
|
||||
|
||||
|
||||
@subsection sPrimitiveTypes Primitive Types
|
||||
-# Avoid writing code that is dependent on the bit size of primitive values,
|
||||
but when specific bit sizes are required, use explicitly-sized types such as
|
||||
@c int32_t or @c uint64_t.
|
||||
|
||||
|
||||
@subsection sMacros Macros
|
||||
-# Avoid macros for constants. Use global static constants instead. (Local
|
||||
static constants are not guaranteed to be initialized in a thread-safe manner.)
|
||||
-# Avoid macro functions. Use @c inline and templates instead.
|
||||
|
||||
|
||||
@subsection sClasses Classes
|
||||
-# Constructors that can be called with only one argument should be prefixed
|
||||
with the @c explicit keyword to avoid unintended type conversions.
|
||||
-# Never call virtual methods from destructors.
|
||||
-# If you have a copy constructor, make sure you have an assignment operator.
|
||||
-# If you have an assignment operator, you probably need a copy constructor.
|
||||
-# If you have data members that are pointers to dynamically allocated memory,
|
||||
make sure you have a copy constructor and an assignment operator, both of
|
||||
which do the right thing with that memory.
|
||||
-# Classes which are to be subclassed always have a virtual destructor, even if
|
||||
it is empty.
|
||||
-# Check against self assignment and return <TT>*this</TT> in assignment
|
||||
operators.
|
||||
-# Declare methods as @c const wherever possible.
|
||||
-# Declare object-valued input arguments as const references wherever
|
||||
possible. Primitives may be passed by value, however.
|
||||
-# Arithmetic, logical, bitwise, dereference, and address of operators should
|
||||
only be used when their semantics are clear, obvious, and unambiguous.
|
||||
-# The application operator [ () ] is allowed for functors.
|
||||
-# Conversion operators should be avoided.
|
||||
-# Never return const references to stack allocated or implicitly computed
|
||||
objects.
|
||||
-# If a class does not have a copy constructor and/or assignment operator,
|
||||
consider creating a private unimplemented copy constructor and/or assignment
|
||||
operator to prevent automatically generated versions from being used.
|
||||
|
||||
|
||||
@subsection sConditionalStatements Conditional Statements
|
||||
-# For test expressions, use a form that indicates as clearly as possible the
|
||||
types of operands by avoiding implicit casts.
|
||||
-# Assignments that occur within conditional statements must have no effect in
|
||||
the enclosing scope.
|
||||
-# Allow for arithmetic imprecision when comparing floating point values.
|
||||
-# In switch statements, always comment fallthroughs and empty cases.
|
||||
|
||||
|
||||
@section sNamespaces Namespaces
|
||||
-# Namespaces should be used whenever possible.
|
||||
-# Avoid pulling in entire namespaces with @c using directives
|
||||
(e.g., <TT>using namespace std;</TT>).
|
||||
-# @c using declarations are allowed for individual symbols (e.g.,
|
||||
<TT>using std::vector;</TT>), but they should never appear in a header file.
|
||||
-# Define global operators in the namespace of their arguments.
|
||||
-# Namespaces are not indented.
|
||||
|
||||
|
||||
@subsection sExceptions Exceptions
|
||||
-# Appropriate use of exceptions is encouraged.
|
||||
-# Methods should declare all exceptions they might throw using comments,
|
||||
but not exception specifications.
|
||||
-# Throw scope local exception instances, not pointers or references or globals.
|
||||
-# Catch exceptions by reference.
|
||||
-# Never allow an exception to escape from a destructor.
|
||||
|
||||
|
||||
@subsection sTemplates Templates
|
||||
-# Use @c typename rather than @c class when declaring template type parameters.
|
||||
|
||||
|
||||
@subsection sMiscellaneous Miscellaneous
|
||||
-# Don’t use pointers to run through arrays of non-primitive types. Use explicit array indexing, iterators or generic algorithms instead.
|
||||
-# Use C++ casts (<TT>static_cast<int>(x)</TT> or <TT>int(x)</TT>),
|
||||
not C casts (<TT>(int)x</TT>).
|
||||
-# Multiple variables of the same data type may be declared on the same line
|
||||
if closely related.
|
||||
-# Library code must never deliberately terminate the application in response
|
||||
to an error condition.
|
||||
-# Avoid using malloc/free when new/delete can be used instead.
|
||||
-# Avoid @c goto.
|
||||
-# Avoid \"magic numbers\". Use named constants when necessary.
|
||||
-# If you use typeid/typeinfo, be aware that although all runtimes support
|
||||
<TT>typeinfo::name()</TT>, the format of the string it returns varies
|
||||
between compilers and even for a given compiler the value is not guaranteed
|
||||
to be unique.
|
||||
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,115 @@
|
||||
# Copyright Contributors to the OpenVDB Project
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
#[=======================================================================[
|
||||
|
||||
CMake Configuration for NanoVDB Examples
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(NanoVDBExamples LANGUAGES CXX)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
###############################################################################
|
||||
|
||||
message(STATUS "----------------------------------------------------")
|
||||
message(STATUS "---------- Configuring NanoVDB Examples ------------")
|
||||
message(STATUS "----------------------------------------------------")
|
||||
|
||||
###############################################################################
|
||||
|
||||
if(WIN32)
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/Release")
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------`
|
||||
# helper function
|
||||
# -----------------------------------------------------------------------------`
|
||||
function(NANOVDB_EXAMPLE)
|
||||
set(options OPENVDB)
|
||||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs)
|
||||
cmake_parse_arguments(NANOVDB_EXAMPLE
|
||||
"${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
set(EXAMPLE_NAME ${NANOVDB_EXAMPLE_NAME})
|
||||
set(EXAMPLE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/${EXAMPLE_NAME}")
|
||||
|
||||
file(GLOB EXAMPLE_HEADER_FILES
|
||||
${EXAMPLE_ROOT}/*.h
|
||||
${EXAMPLE_ROOT}/*.inl
|
||||
${EXAMPLE_ROOT}/*.hh
|
||||
${EXAMPLE_ROOT}/*.hpp
|
||||
${EXAMPLE_ROOT}/*.cuh)
|
||||
|
||||
file(GLOB EXAMPLE_SOURCE_FILES
|
||||
${EXAMPLE_ROOT}/*.c
|
||||
${EXAMPLE_ROOT}/*.cc
|
||||
${EXAMPLE_ROOT}/*.cpp)
|
||||
|
||||
file(GLOB EXAMPLE_SOURCE_CUDA_FILES ${EXAMPLE_ROOT}/*.cu)
|
||||
|
||||
# configure CUDA
|
||||
if(NOT NANOVDB_USE_CUDA AND EXAMPLE_SOURCE_CUDA_FILES)
|
||||
message(WARNING " - CUDA required to build ${EXAMPLE_NAME}. Skipping.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NANOVDB_EXAMPLE_OPENVDB AND NOT NANOVDB_USE_OPENVDB)
|
||||
message(WARNING " - OpenVDB required to build ${EXAMPLE_NAME}. Skipping.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_executable(${EXAMPLE_NAME}
|
||||
${EXAMPLE_SOURCE_FILES}
|
||||
${EXAMPLE_SOURCE_CUDA_FILES}
|
||||
${EXAMPLE_HEADER_FILES})
|
||||
|
||||
# Propagate MSVC Runtime from the OpenVDB library (if VDB_MSVC_RUNTIME_SELECTION
|
||||
# has been set then we're building and linking against OpenVDB, see the root
|
||||
# NanoVDB CMakeLists.txt)
|
||||
if(VDB_MSVC_RUNTIME_SELECTION)
|
||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES
|
||||
MSVC_RUNTIME_LIBRARY ${VDB_MSVC_RUNTIME_SELECTION})
|
||||
endif()
|
||||
|
||||
target_include_directories(${EXAMPLE_NAME} PUBLIC ex_util)
|
||||
target_link_libraries(${EXAMPLE_NAME} PRIVATE nanovdb)
|
||||
|
||||
install(TARGETS ${EXAMPLE_NAME} DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples)
|
||||
endfunction()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
if(NANOVDB_BUILD_BENCHMARK)
|
||||
add_subdirectory(benchmark)
|
||||
endif()
|
||||
|
||||
nanovdb_example(NAME "ex_make_custom_nanovdb")
|
||||
nanovdb_example(NAME "ex_make_funny_nanovdb")
|
||||
nanovdb_example(NAME "ex_make_typed_grids")
|
||||
nanovdb_example(NAME "ex_make_nanovdb_sphere")
|
||||
nanovdb_example(NAME "ex_write_nanovdb_grids")
|
||||
nanovdb_example(NAME "ex_openvdb_to_nanovdb" OPENVDB)
|
||||
nanovdb_example(NAME "ex_openvdb_to_nanovdb_accessor" OPENVDB)
|
||||
nanovdb_example(NAME "ex_openvdb_to_nanovdb_cuda" OPENVDB)
|
||||
nanovdb_example(NAME "ex_read_nanovdb_sphere")
|
||||
nanovdb_example(NAME "ex_read_nanovdb_sphere_accessor")
|
||||
nanovdb_example(NAME "ex_read_nanovdb_sphere_accessor_cuda")
|
||||
nanovdb_example(NAME "ex_modify_nanovdb_thrust")
|
||||
nanovdb_example(NAME "ex_map_pool_buffer")
|
||||
nanovdb_example(NAME "ex_bump_pool_buffer")
|
||||
nanovdb_example(NAME "ex_collide_level_set")
|
||||
nanovdb_example(NAME "ex_raytrace_fog_volume")
|
||||
nanovdb_example(NAME "ex_raytrace_level_set")
|
||||
|
||||
if(NANOVDB_USE_MAGICAVOXEL)
|
||||
nanovdb_example(NAME "ex_vox_to_nanovdb")
|
||||
endif()
|
||||
# add_subdirectory(ex_sph_benchmark)
|
||||
|
||||
# many of the sample projects depend on a data directory. This allows Debug
|
||||
# launching from the cmake binary working directory.
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/data")
|
||||
@@ -0,0 +1,108 @@
|
||||
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @file BenchKernels_dense.cu
|
||||
///
|
||||
/// @author Ken Museth
|
||||
///
|
||||
/// @brief CUDA kernel for a simple ray-tracing benchmark test.
|
||||
|
||||
#include "DenseGrid.h"
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h> // for CUDA memory management
|
||||
#include <nanovdb/util/Ray.h> // for nanovdb::Ray
|
||||
#include <nanovdb/util/HDDA.h> // for nanovdb::DDA
|
||||
|
||||
#include "Image.h"
|
||||
#include "Camera.h"
|
||||
|
||||
// Comment out to disable timing of the CUDA kernel
|
||||
#define CUDA_TIMING
|
||||
|
||||
// This is called by the device
|
||||
__global__ void render_kernel(const nanovdb::DenseGrid<float>& grid,
|
||||
const nanovdb::Camera<float>& camera,
|
||||
nanovdb::Image& img)
|
||||
{
|
||||
using RealT = float;
|
||||
using Vec3T = nanovdb::Vec3<RealT>;
|
||||
using CoordT = nanovdb::Coord;
|
||||
using RayT = nanovdb::Ray<RealT>;
|
||||
using ColorRGB = nanovdb::Image::ColorRGB;
|
||||
|
||||
const int w = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
const int h = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
if (w >= img.width() || h >= img.height()) return;
|
||||
RayT ray = camera.getRay(img.u(w), img.v(h));// ray in world space
|
||||
ray = ray.worldToIndexF(grid);// ray in index space
|
||||
if (ray.clip(grid.indexBBox().expandBy(-1))) {// clip to the index bounding box
|
||||
nanovdb::DDA<RayT> dda(ray);
|
||||
const float v0 = grid.getValue(dda.voxel());
|
||||
while( dda.step() ) {
|
||||
CoordT ijk = dda.voxel();
|
||||
const float v1 = grid.getValue(ijk);
|
||||
if (v0*v1>0) continue;
|
||||
#if 1// second-order central difference
|
||||
Vec3T grad(grid.getValue(ijk.offsetBy(1,0,0)) - grid.getValue(ijk.offsetBy(-1,0,0)),
|
||||
grid.getValue(ijk.offsetBy(0,1,0)) - grid.getValue(ijk.offsetBy(0,-1,0)),
|
||||
grid.getValue(ijk.offsetBy(0,0,1)) - grid.getValue(ijk.offsetBy(0,0,-1)));
|
||||
#else// first order single-sided difference
|
||||
Vec3T grad(-v0);
|
||||
ijk[0] += 1;
|
||||
grad[0] += grid.getValue(ijk);
|
||||
ijk[0] -= 1;
|
||||
ijk[1] += 1;
|
||||
grad[1] += grid.getValue(ijk);
|
||||
ijk[1] -= 1;
|
||||
ijk[2] += 1;
|
||||
grad[2] += grid.getValue(ijk);
|
||||
#endif
|
||||
grad *= rnorm3df(grad[0], grad[1], grad[2]);
|
||||
img(w, h) = ColorRGB(abs(grad.dot(ray.dir())), 0, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const int checkerboard = 1 << 7;
|
||||
img(w, h) = ((h & checkerboard) ^ (w & checkerboard)) ? ColorRGB(1, 1, 1) : ColorRGB(0, 0, 0);
|
||||
}
|
||||
|
||||
// This is called by the host
|
||||
extern "C" float launch_kernels(const nanovdb::DenseGridHandle<nanovdb::CudaDeviceBuffer>& gridHandle,
|
||||
nanovdb::ImageHandle<nanovdb::CudaDeviceBuffer>& imgHandle,
|
||||
const nanovdb::Camera<float>* camera,
|
||||
cudaStream_t stream)
|
||||
{
|
||||
const auto* img = imgHandle.image(); // host image!
|
||||
auto round = [](int a, int b) { return (a + b - 1) / b; };
|
||||
const dim3 threadsPerBlock(8, 8), numBlocks(round(img->width(), threadsPerBlock.x), round(img->height(), threadsPerBlock.y));
|
||||
auto* deviceGrid = gridHandle.deviceGrid<float>(); // note this cannot be de-referenced since it points to a memory address on the GPU!
|
||||
auto* deviceImage = imgHandle.deviceImage(); // note this cannot be de-referenced since it points to a memory address on the GPU!
|
||||
assert(deviceGrid && deviceImage);
|
||||
|
||||
#ifdef CUDA_TIMING
|
||||
cudaEvent_t start, stop;
|
||||
cudaEventCreate(&start);
|
||||
cudaEventCreate(&stop);
|
||||
cudaEventRecord(start, stream);
|
||||
#endif
|
||||
|
||||
// kernal syntax: <<<blocks per grid, threads per block, dynamic shared memory per block, stream >>>
|
||||
render_kernel<<<numBlocks, threadsPerBlock, 0, stream>>>(*deviceGrid, *camera, *deviceImage);
|
||||
|
||||
float elapsedTime = 0.0f;
|
||||
#ifdef CUDA_TIMING
|
||||
cudaEventRecord(stop, stream);
|
||||
cudaEventSynchronize(stop);
|
||||
|
||||
cudaEventElapsedTime(&elapsedTime, start, stop);
|
||||
//printf("DenseGrid: GPU kernel with %i rays ... completed in %5.3f milliseconds\n", imgHandle.image()->size(), elapsedTime);
|
||||
cudaError_t errCode = cudaGetLastError();
|
||||
if (errCode != cudaSuccess) {
|
||||
fprintf(stderr, "CUDA Runtime Error: %s %s %d\n", cudaGetErrorString(errCode), __FILE__, __LINE__);
|
||||
exit(errCode);
|
||||
}
|
||||
cudaEventDestroy(start);
|
||||
cudaEventDestroy(stop);
|
||||
#endif
|
||||
return elapsedTime;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @file BenchKernels.cu
|
||||
///
|
||||
/// @author Ken Museth
|
||||
///
|
||||
/// @brief CUDA kernel for a simple ray-tracing benchmark test.
|
||||
|
||||
#include <nanovdb/util/GridHandle.h> // for nanovdb::GridHandle
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h> // for CUDA memory management
|
||||
#include <nanovdb/util/Ray.h> // for nanovdb::Ray
|
||||
#include <nanovdb/util/HDDA.h> // for nanovdb::ZeroCrossing
|
||||
|
||||
#include "Image.h"
|
||||
#include "Camera.h"
|
||||
|
||||
// Comment out to disable timing of the CUDA kernel
|
||||
#define CUDA_TIMING
|
||||
|
||||
// This is called by the device
|
||||
template <typename T>
|
||||
__global__ void render_kernel(const nanovdb::NanoGrid<T>& grid,
|
||||
const nanovdb::Camera<float>& camera,
|
||||
nanovdb::Image& img)
|
||||
{
|
||||
using RealT = float;
|
||||
using Vec3T = nanovdb::Vec3<RealT>;
|
||||
using CoordT = nanovdb::Coord;
|
||||
using RayT = nanovdb::Ray<RealT>;
|
||||
using ColorRGB = nanovdb::Image::ColorRGB;
|
||||
|
||||
const int w = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
const int h = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
if (w >= img.width() || h >= img.height())
|
||||
return;
|
||||
|
||||
const auto& tree = grid.tree();
|
||||
const auto& bbox = tree.bbox();
|
||||
RayT ray = camera.getRay(img.u(w), img.v(h));
|
||||
ray = ray.worldToIndexF(grid);
|
||||
|
||||
auto acc = tree.getAccessor();
|
||||
CoordT ijk;
|
||||
float t;
|
||||
float v0;
|
||||
if (nanovdb::ZeroCrossing(ray, acc, ijk, v0, t)) {
|
||||
#if 1// second-order central difference
|
||||
Vec3T grad(acc.getValue(ijk.offsetBy(1,0,0)) - acc.getValue(ijk.offsetBy(-1,0,0)),
|
||||
acc.getValue(ijk.offsetBy(0,1,0)) - acc.getValue(ijk.offsetBy(0,-1,0)),
|
||||
acc.getValue(ijk.offsetBy(0,0,1)) - acc.getValue(ijk.offsetBy(0,0,-1)));
|
||||
#else// first order single-sided difference
|
||||
Vec3T grad(-v0);
|
||||
ijk[0] += 1;
|
||||
grad[0] += acc.getValue(ijk);
|
||||
ijk[0] -= 1;
|
||||
ijk[1] += 1;
|
||||
grad[1] += acc.getValue(ijk);
|
||||
ijk[1] -= 1;
|
||||
ijk[2] += 1;
|
||||
grad[2] += acc.getValue(ijk);
|
||||
#endif
|
||||
grad *= rnorm3df(grad[0], grad[1], grad[2]);
|
||||
img(w, h) = ColorRGB(abs(grad.dot(ray.dir())), 0, 0);
|
||||
} else {
|
||||
const int checkerboard = 1 << 7;
|
||||
img(w, h) = ((h & checkerboard) ^ (w & checkerboard)) ? ColorRGB(1, 1, 1) : ColorRGB(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// This is called by the host
|
||||
extern "C" float launch_kernels(const nanovdb::GridHandle<nanovdb::CudaDeviceBuffer>& gridHandle,
|
||||
nanovdb::ImageHandle<nanovdb::CudaDeviceBuffer>& imgHandle,
|
||||
const nanovdb::Camera<float>* camera,
|
||||
cudaStream_t stream)
|
||||
{
|
||||
using BuildT = nanovdb::FpN;
|
||||
const auto* img = imgHandle.image(); // host image!
|
||||
auto round = [](int a, int b) { return (a + b - 1) / b; };
|
||||
const dim3 threadsPerBlock(8, 8), numBlocks(round(img->width(), threadsPerBlock.x), round(img->height(), threadsPerBlock.y));
|
||||
auto* deviceGrid = gridHandle.deviceGrid<BuildT>(); // note this cannot be de-referenced since it points to a memory address on the GPU!
|
||||
auto* deviceImage = imgHandle.deviceImage(); // note this cannot be de-referenced since it points to a memory address on the GPU!
|
||||
assert(deviceGrid && deviceImage);
|
||||
|
||||
#ifdef CUDA_TIMING
|
||||
cudaEvent_t start, stop;
|
||||
cudaEventCreate(&start);
|
||||
cudaEventCreate(&stop);
|
||||
cudaEventRecord(start, stream);
|
||||
#endif
|
||||
|
||||
// kernal syntax: <<<blocks per grid, threads per block, dynamic shared memory per block, stream >>>
|
||||
render_kernel<<<numBlocks, threadsPerBlock, 0, stream>>>(*deviceGrid, *camera, *deviceImage);
|
||||
|
||||
float elapsedTime = 0.0f;
|
||||
#ifdef CUDA_TIMING
|
||||
cudaEventRecord(stop, stream);
|
||||
cudaEventSynchronize(stop);
|
||||
|
||||
cudaEventElapsedTime(&elapsedTime, start, stop);
|
||||
//printf("NanoVDB: GPU kernel with %i rays ... completed in %5.3f milliseconds\n", imgHandle.image()->size(), elapsedTime);
|
||||
cudaError_t errCode = cudaGetLastError();
|
||||
if (errCode != cudaSuccess) {
|
||||
fprintf(stderr, "CUDA Runtime Error: %s %s %d\n", cudaGetErrorString(errCode), __FILE__, __LINE__);
|
||||
exit(errCode);
|
||||
}
|
||||
cudaEventDestroy(start);
|
||||
cudaEventDestroy(stop);
|
||||
#endif
|
||||
return elapsedTime;
|
||||
}
|
||||
@@ -0,0 +1,721 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @file Benchmark.cc
|
||||
///
|
||||
/// @author Ken Museth
|
||||
///
|
||||
/// @brief A simple ray-tracing benchmark test.
|
||||
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/Ray.h>
|
||||
#include <nanovdb/util/HDDA.h>
|
||||
#include <nanovdb/util/Primitives.h>
|
||||
#include <nanovdb/util/SampleFromVoxels.h>
|
||||
#include "Image.h"
|
||||
#include "Camera.h"
|
||||
#include "../ex_util/CpuTimer.h"
|
||||
|
||||
#include "DenseGrid.h"
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
#endif
|
||||
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
#include <nanovdb/util/OpenToNanoVDB.h>
|
||||
|
||||
#include <openvdb/openvdb.h>
|
||||
#include <openvdb/tools/LevelSetSphere.h>
|
||||
#include <openvdb/tools/LevelSetPlatonic.h>
|
||||
#include <openvdb/tools/RayIntersector.h>
|
||||
#include <openvdb/math/Ray.h>
|
||||
#include <openvdb/math/Transform.h>
|
||||
#endif
|
||||
|
||||
#if defined(NANOVDB_USE_TBB)
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/blocked_range2d.h>
|
||||
#endif
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace nanovdb {
|
||||
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, const CoordBBox& b)
|
||||
{
|
||||
os << "(" << b[0][0] << "," << b[0][1] << "," << b[0][2] << ") ->"
|
||||
<< "(" << b[1][0] << "," << b[1][1] << "," << b[1][2] << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, const Coord& ijk)
|
||||
{
|
||||
os << "(" << ijk[0] << "," << ijk[1] << "," << ijk[2] << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, const Vec3<T>& v)
|
||||
{
|
||||
os << "(" << v[0] << "," << v[1] << "," << v[2] << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// define the environment variable VDB_DATA_PATH to use models from the web
|
||||
// e.g. setenv VDB_DATA_PATH /home/kmu/dev/data/vdb
|
||||
// or export VDB_DATA_PATH=/Users/ken/dev/data/vdb
|
||||
|
||||
// define the environment variable VDB_SCRATCH_PATH to specify the directory where image are saved
|
||||
|
||||
// The fixture for testing class.
|
||||
class Benchmark : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
Benchmark() {}
|
||||
|
||||
~Benchmark() override {}
|
||||
|
||||
// If the constructor and destructor are not enough for setting up
|
||||
// and cleaning up each test, you can define the following methods:
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
// Code here will be called immediately after the constructor (right
|
||||
// before each test).
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
// Code here will be called immediately after each test (right
|
||||
// before the destructor).
|
||||
}
|
||||
std::string getEnvVar(const std::string& name, const std::string def = "") const
|
||||
{
|
||||
const char* str = std::getenv(name.c_str());
|
||||
return str == nullptr ? def : std::string(str);
|
||||
}
|
||||
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
openvdb::FloatGrid::Ptr getSrcGrid(int verbose = 1)
|
||||
{
|
||||
openvdb::FloatGrid::Ptr grid;
|
||||
const std::string path = this->getEnvVar("VDB_DATA_PATH");
|
||||
if (path.empty()) { // create a narrow-band level set sphere
|
||||
std::cout << "\tSet the environment variable \"VDB_DATA_PATH\" to a directory\n"
|
||||
<< "\tcontaining OpenVDB level sets files. They can be downloaded\n"
|
||||
<< "\there: https://www.openvdb.org/download/" << std::endl;
|
||||
const float radius = 50.0f;
|
||||
const openvdb::Vec3f center(0.0f, 0.0f, 0.0f);
|
||||
const float voxelSize = 0.1f, width = 3.0f;
|
||||
if (verbose > 0) {
|
||||
std::stringstream ss;
|
||||
ss << "Generating level set sphere with a radius of " << radius << " voxels";
|
||||
mTimer.start(ss.str());
|
||||
}
|
||||
#if 1 // choose between a sphere or one of five platonic solids
|
||||
grid = openvdb::tools::createLevelSetSphere<openvdb::FloatGrid>(radius, center, voxelSize, width);
|
||||
grid->setName("ls_sphere");
|
||||
#else
|
||||
const int faces[5] = {4, 6, 8, 12, 20};
|
||||
grid = openvdb::tools::createLevelSetPlatonic<openvdb::FloatGrid>(faces[4], radius, center, voxelSize, width);
|
||||
grid->setName("ls_platonic");
|
||||
#endif
|
||||
} else {
|
||||
openvdb::initialize();
|
||||
const std::vector<std::string> models = {"armadillo.vdb", "buddha.vdb", "bunny.vdb", "crawler.vdb", "dragon.vdb", "iss.vdb", "space.vdb", "torus_knot_helix.vdb", "utahteapot.vdb", "bunny_cloud.vdb", "wdas_cloud.vdb"};
|
||||
const std::string fileName = path + "/" + models[4]; //
|
||||
if (verbose > 0)
|
||||
mTimer.start("Reading grid from the file \"" + fileName + "\"");
|
||||
openvdb::io::File file(fileName);
|
||||
file.open(false); //disable delayed loading
|
||||
grid = openvdb::gridPtrCast<openvdb::FloatGrid>(file.readGrid(file.beginName().gridName()));
|
||||
}
|
||||
if (verbose > 0)
|
||||
mTimer.stop();
|
||||
if (verbose > 1)
|
||||
grid->print(std::cout, 3);
|
||||
return grid;
|
||||
}
|
||||
#endif
|
||||
nanovdb::CpuTimer<> mTimer;
|
||||
}; // Benchmark
|
||||
|
||||
TEST_F(Benchmark, Ray)
|
||||
{
|
||||
using RealT = float;
|
||||
using Vec3T = nanovdb::Vec3<RealT>;
|
||||
using CoordT = nanovdb::Coord;
|
||||
using CoordBBoxT = nanovdb::BBox<CoordT>;
|
||||
using BBoxT = nanovdb::BBox<Vec3T>;
|
||||
using RayT = nanovdb::Ray<RealT>;
|
||||
|
||||
{// clip ray against an index bbox
|
||||
// test bbox clip
|
||||
const Vec3T dir(-1.0, 2.0, 3.0);
|
||||
const Vec3T eye(2.0, 1.0, 1.0);
|
||||
RealT t0 = 0.1, t1 = 12589.0;
|
||||
RayT ray(eye, dir, t0, t1);
|
||||
|
||||
// intersects the two faces of the box perpendicular to the y-axis!
|
||||
EXPECT_TRUE(ray.clip(CoordBBoxT(CoordT(0, 2, 2), CoordT(2, 4, 6))));
|
||||
//std::cerr << "t0 = " << ray.t0() << ", ray.t1() = " << ray.t1() << std::endl;
|
||||
//std::cerr << "ray(0.5) = " << ray(0.5) << std::endl;
|
||||
//std::cerr << "ray(1.5) = " << ray(1.5) << std::endl;
|
||||
//std::cerr << "ray(2.0) = " << ray(2.0) << std::endl;
|
||||
EXPECT_EQ(0.5, ray.t0());
|
||||
EXPECT_EQ(2.0, ray.t1());
|
||||
EXPECT_EQ(ray(0.5)[1], 2); //lower y component of intersection
|
||||
EXPECT_EQ(ray(2.0)[1], 5); //higher y component of intersection
|
||||
|
||||
ray.reset(eye, dir, t0, t1);
|
||||
// intersects the lower edge anlong the z-axis of the box
|
||||
EXPECT_TRUE(ray.clip(BBoxT(Vec3T(1.5, 2.0, 2.0), Vec3T(4.5, 4.0, 6.0))));
|
||||
EXPECT_EQ(0.5, ray.t0());
|
||||
EXPECT_EQ(0.5, ray.t1());
|
||||
EXPECT_EQ(ray(0.5)[0], 1.5); //lower y component of intersection
|
||||
EXPECT_EQ(ray(0.5)[1], 2.0); //higher y component of intersection
|
||||
|
||||
ray.reset(eye, dir, t0, t1);
|
||||
// no intersections
|
||||
EXPECT_TRUE(!ray.clip(CoordBBoxT(CoordT(4, 2, 2), CoordT(6, 4, 6))));
|
||||
EXPECT_EQ(t0, ray.t0());
|
||||
EXPECT_EQ(t1, ray.t1());
|
||||
}
|
||||
{// clip ray against an real bbox
|
||||
// test bbox clip
|
||||
const Vec3T dir(-1.0, 2.0, 3.0);
|
||||
const Vec3T eye(2.0, 1.0, 1.0);
|
||||
RealT t0 = 0.1, t1 = 12589.0;
|
||||
RayT ray(eye, dir, t0, t1);
|
||||
|
||||
// intersects the two faces of the box perpendicular to the y-axis!
|
||||
EXPECT_TRUE( ray.clip(CoordBBoxT(CoordT(0, 2, 2), CoordT(2, 4, 6)).asReal<double>()) );
|
||||
//std::cerr << "t0 = " << ray.t0() << ", ray.t1() = " << ray.t1() << std::endl;
|
||||
//std::cerr << "ray(0.5) = " << ray(0.5) << std::endl;
|
||||
//std::cerr << "ray(1.5) = " << ray(1.5) << std::endl;
|
||||
//std::cerr << "ray(2.0) = " << ray(2.0) << std::endl;
|
||||
EXPECT_EQ(0.5, ray.t0());
|
||||
EXPECT_EQ(2.0, ray.t1());
|
||||
EXPECT_EQ(ray(0.5)[1], 2); //lower y component of intersection
|
||||
EXPECT_EQ(ray(1.5)[1], 4); //higher y component of intersection
|
||||
|
||||
ray.reset(eye, dir, t0, t1);
|
||||
// intersects the lower edge along the z-axis of the box
|
||||
EXPECT_TRUE( ray.clip(BBoxT(Vec3T(1.5, 2.0, 2.0), Vec3T(4.5, 4.0, 6.0))) );
|
||||
EXPECT_EQ(0.5, ray.t0());
|
||||
EXPECT_EQ(0.5, ray.t1());
|
||||
EXPECT_EQ(ray(0.5)[0], 1.5); //lower y component of intersection
|
||||
EXPECT_EQ(ray(0.5)[1], 2.0); //higher y component of intersection
|
||||
|
||||
ray.reset(eye, dir, t0, t1);
|
||||
// no intersections
|
||||
EXPECT_TRUE(!ray.clip(CoordBBoxT(CoordT(4, 2, 2), CoordT(6, 4, 6)).asReal<double>()) );
|
||||
EXPECT_EQ(t0, ray.t0());
|
||||
EXPECT_EQ(t1, ray.t1());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Benchmark, HDDA)
|
||||
{
|
||||
using RealT = float;
|
||||
using CoordT = nanovdb::Coord;
|
||||
using RayT = nanovdb::Ray<RealT>;
|
||||
using Vec3T = RayT::Vec3T;
|
||||
|
||||
{ // basic test
|
||||
using DDAT = nanovdb::HDDA<RayT, CoordT>;
|
||||
const RayT::Vec3T dir(1.0, 0.0, 0.0);
|
||||
const RayT::Vec3T eye(-1.0, 0.0, 0.0);
|
||||
const RayT ray(eye, dir);
|
||||
DDAT dda(ray, 1 << (3 + 4 + 5));
|
||||
EXPECT_EQ(nanovdb::Delta<RealT>::value(), dda.time());
|
||||
EXPECT_EQ(1.0, dda.next());
|
||||
dda.step();
|
||||
EXPECT_EQ(1.0, dda.time());
|
||||
EXPECT_EQ(4096 + 1.0, dda.next());
|
||||
}
|
||||
{ // Check for the notorious +-0 issue!
|
||||
using DDAT = nanovdb::HDDA<RayT, CoordT>;
|
||||
|
||||
const Vec3T dir1(1.0, 0.0, 0.0);
|
||||
const Vec3T eye1(2.0, 0.0, 0.0);
|
||||
const RayT ray1(eye1, dir1);
|
||||
DDAT dda1(ray1, 1 << 3);
|
||||
dda1.step();
|
||||
|
||||
const Vec3T dir2(1.0, -0.0, -0.0);
|
||||
const Vec3T eye2(2.0, 0.0, 0.0);
|
||||
const RayT ray2(eye2, dir2);
|
||||
DDAT dda2(ray2, 1 << 3);
|
||||
dda2.step();
|
||||
|
||||
const Vec3T dir3(1.0, -1e-9, -1e-9);
|
||||
const Vec3T eye3(2.0, 0.0, 0.0);
|
||||
const RayT ray3(eye3, dir3);
|
||||
DDAT dda3(ray3, 1 << 3);
|
||||
dda3.step();
|
||||
|
||||
const Vec3T dir4(1.0, -1e-9, -1e-9);
|
||||
const Vec3T eye4(2.0, 0.0, 0.0);
|
||||
const RayT ray4(eye3, dir4);
|
||||
DDAT dda4(ray4, 1 << 3);
|
||||
dda4.step();
|
||||
|
||||
EXPECT_EQ(dda1.time(), dda2.time());
|
||||
EXPECT_EQ(dda2.time(), dda3.time());
|
||||
EXPECT_EQ(dda3.time(), dda4.time());
|
||||
EXPECT_EQ(dda1.next(), dda2.next());
|
||||
EXPECT_EQ(dda2.next(), dda3.next());
|
||||
EXPECT_EQ(dda3.next(), dda4.next());
|
||||
}
|
||||
{ // test voxel traversal along both directions of each axis
|
||||
using DDAT = nanovdb::HDDA<RayT>;
|
||||
const Vec3T eye(0, 0, 0);
|
||||
for (int s = -1; s <= 1; s += 2) {
|
||||
for (int a = 0; a < 3; ++a) {
|
||||
const int d[3] = {s * (a == 0), s * (a == 1), s * (a == 2)};
|
||||
const Vec3T dir(d[0], d[1], d[2]);
|
||||
RayT ray(eye, dir);
|
||||
DDAT dda(ray, 1 << 0);
|
||||
for (int i = 1; i <= 10; ++i) {
|
||||
EXPECT_TRUE(dda.step());
|
||||
EXPECT_EQ(i, dda.time());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ // test Node traversal along both directions of each axis
|
||||
using DDAT = nanovdb::HDDA<RayT, CoordT>;
|
||||
const Vec3T eye(0, 0, 0);
|
||||
|
||||
for (int s = -1; s <= 1; s += 2) {
|
||||
for (int a = 0; a < 3; ++a) {
|
||||
const int d[3] = {s * (a == 0), s * (a == 1), s * (a == 2)};
|
||||
const Vec3T dir(d[0], d[1], d[2]);
|
||||
RayT ray(eye, dir);
|
||||
DDAT dda(ray, 1 << 3);
|
||||
for (int i = 1; i <= 10; ++i) {
|
||||
EXPECT_TRUE(dda.step());
|
||||
EXPECT_EQ(8 * i, dda.time());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ // test accelerated Node traversal along both directions of each axis
|
||||
using DDAT = nanovdb::HDDA<RayT, CoordT>;
|
||||
const Vec3T eye(0, 0, 0);
|
||||
|
||||
for (int s = -1; s <= 1; s += 2) {
|
||||
for (int a = 0; a < 3; ++a) {
|
||||
const int d[3] = {s * (a == 0), s * (a == 1), s * (a == 2)};
|
||||
const Vec3T dir(2 * d[0], 2 * d[1], 2 * d[2]);
|
||||
RayT ray(eye, dir);
|
||||
DDAT dda(ray, 1 << 3);
|
||||
double next = 0;
|
||||
for (int i = 1; i <= 10; ++i) {
|
||||
EXPECT_TRUE(dda.step());
|
||||
EXPECT_EQ(4 * i, dda.time());
|
||||
if (i > 1) {
|
||||
EXPECT_EQ(dda.time(), next);
|
||||
}
|
||||
next = dda.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // HDDA
|
||||
|
||||
|
||||
TEST_F(Benchmark, DenseGrid)
|
||||
{
|
||||
{// CoordT = nanovdb::Coord
|
||||
using GridT = nanovdb::DenseGrid<float>;
|
||||
const nanovdb::Coord min(-10,0,10), max(10,20,30), pos(0,5,20);
|
||||
const nanovdb::CoordBBox bbox( min, max );
|
||||
auto handle = GridT::create(min, max);
|
||||
auto *grid = handle.grid<float>();
|
||||
EXPECT_TRUE(grid);
|
||||
EXPECT_TRUE(grid->test(min));
|
||||
EXPECT_TRUE(grid->test(max));
|
||||
EXPECT_TRUE(grid->test(pos));
|
||||
EXPECT_EQ( uint64_t(21*21*21), bbox.volume() );
|
||||
EXPECT_EQ( bbox.volume(), grid->size() );
|
||||
EXPECT_EQ( 0u, grid->coordToOffset(min) );
|
||||
float *p = grid->values();
|
||||
for (uint64_t i=0; i<grid->size(); ++i) {
|
||||
*p++ = 0.0f;
|
||||
}
|
||||
EXPECT_EQ( 0.0f, grid->getValue(min) );
|
||||
EXPECT_EQ( 0.0f, grid->getValue(pos) );
|
||||
EXPECT_EQ( 0.0f, grid->getValue(max) );
|
||||
grid->setValue(pos, 1.0f);
|
||||
EXPECT_EQ( 0.0f, grid->getValue(min) );
|
||||
EXPECT_EQ( 1.0f, grid->getValue(pos) );
|
||||
EXPECT_EQ( 0.0f, grid->getValue(max) );
|
||||
for (auto it = bbox.begin(); it; ++it) {
|
||||
auto &ijk = *it;
|
||||
EXPECT_TRUE(grid->test(ijk));
|
||||
if (ijk == pos) {
|
||||
EXPECT_EQ( 1.0f, grid->getValue(ijk) );
|
||||
} else {
|
||||
EXPECT_EQ( 0.0f, grid->getValue(ijk) );
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(nanovdb::GridType::Float, grid->gridType());
|
||||
EXPECT_EQ(nanovdb::GridClass::Unknown, grid->gridClass());
|
||||
EXPECT_EQ(bbox, grid->indexBBox());
|
||||
EXPECT_EQ(nanovdb::Vec3d(min[0], min[1], min[2]), grid->worldBBox()[0]);
|
||||
EXPECT_EQ(nanovdb::Vec3d(max[0]+1, max[1]+1, max[2]+1), grid->worldBBox()[1]);
|
||||
EXPECT_EQ(nanovdb::Vec3d(1.0), grid->voxelSize());
|
||||
nanovdb::io::writeDense(handle, "data/dense.vol");
|
||||
//nanovdb::io::writeDense(*grid, "data/dense.vol");
|
||||
}
|
||||
{// CoordT = nanovdb::Coord
|
||||
auto handle = nanovdb::io::readDense<>("data/dense.vol");
|
||||
const nanovdb::Coord min(-10,0,10), max(10,20,30), pos(0,5,20);
|
||||
const nanovdb::CoordBBox bbox( min, max );
|
||||
auto *grid = handle.grid<float>();
|
||||
EXPECT_TRUE(grid);
|
||||
EXPECT_TRUE(grid->test(min));
|
||||
EXPECT_TRUE(grid->test(max));
|
||||
EXPECT_TRUE(grid->test(pos));
|
||||
EXPECT_EQ( uint64_t(21*21*21), bbox.volume() );
|
||||
EXPECT_EQ( bbox.volume(), grid->size() );
|
||||
EXPECT_EQ( 0u, grid->coordToOffset(min) );
|
||||
EXPECT_EQ( 0.0f, grid->getValue(min) );
|
||||
EXPECT_EQ( 1.0f, grid->getValue(pos) );
|
||||
EXPECT_EQ( 0.0f, grid->getValue(max) );
|
||||
EXPECT_EQ(min, grid->min());
|
||||
EXPECT_EQ(max, grid->max());
|
||||
for (auto it = bbox.begin(); it; ++it) {
|
||||
auto &ijk = *it;
|
||||
EXPECT_TRUE(grid->test(ijk));
|
||||
if (ijk == pos) {
|
||||
EXPECT_EQ( 1.0f, grid->getValue(ijk) );
|
||||
} else {
|
||||
EXPECT_EQ( 0.0f, grid->getValue(ijk) );
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(nanovdb::GridType::Float, grid->gridType());
|
||||
EXPECT_EQ(nanovdb::GridClass::Unknown, grid->gridClass());
|
||||
EXPECT_EQ(bbox, grid->indexBBox());
|
||||
EXPECT_EQ(nanovdb::Vec3d(min[0], min[1], min[2]), grid->worldBBox()[0]);
|
||||
EXPECT_EQ(nanovdb::Vec3d(max[0]+1, max[1]+1, max[2]+1), grid->worldBBox()[1]);
|
||||
EXPECT_EQ(nanovdb::Vec3d(1.0), grid->voxelSize());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
TEST_F(Benchmark, OpenVDB_CPU)
|
||||
{
|
||||
using GridT = openvdb::FloatGrid;
|
||||
using CoordT = openvdb::Coord;
|
||||
using ColorRGB = nanovdb::Image::ColorRGB;
|
||||
using RealT = float;
|
||||
using Vec3T = openvdb::math::Vec3<RealT>;
|
||||
using RayT = openvdb::math::Ray<RealT>;
|
||||
|
||||
const std::string image_path = this->getEnvVar("VDB_SCRATCH_PATH", ".");
|
||||
|
||||
auto srcGrid = this->getSrcGrid();
|
||||
mTimer.start("Generating NanoVDB grid");
|
||||
auto handle = nanovdb::openToNanoVDB(*srcGrid, nanovdb::StatsMode::BBox, nanovdb::ChecksumMode::Disable, /*verbose=*/0);
|
||||
mTimer.restart("Writing NanoVDB grid");
|
||||
#if defined(NANOVDB_USE_BLOSC)
|
||||
nanovdb::io::writeGrid("data/test.nvdb", handle, nanovdb::io::Codec::BLOSC);
|
||||
#elif defined(NANOVDB_USE_ZIP)
|
||||
nanovdb::io::writeGrid("data/test.nvdb", handle, nanovdb::io::Codec::ZIP);
|
||||
#else
|
||||
nanovdb::io::writeGrid("data/test.nvdb", handle, nanovdb::io::Codec::NONE);
|
||||
#endif
|
||||
mTimer.stop();
|
||||
|
||||
{// convert and write DenseGRid
|
||||
mTimer.start("Generating DenseGrid");
|
||||
auto dHandle = nanovdb::convertToDense(*handle.grid<float>());
|
||||
mTimer.restart("Writing DenseGrid");
|
||||
nanovdb::io::writeDense(dHandle, "data/test.vol");
|
||||
mTimer.stop();
|
||||
}
|
||||
|
||||
const int width = 1280, height = 720;
|
||||
const RealT vfov = 25.0f, aspect = RealT(width) / height, radius = 300.0f;
|
||||
const auto bbox = srcGrid->evalActiveVoxelBoundingBox();
|
||||
const openvdb::Vec3d center(0.5 * (bbox.max()[0] + bbox.min()[0]),
|
||||
0.5 * (bbox.max()[1] + bbox.min()[1]),
|
||||
0.5 * (bbox.max()[2] + bbox.min()[2]));
|
||||
const Vec3T lookat = srcGrid->indexToWorld(center), up(0, -1, 0);
|
||||
auto eye = [&lookat, &radius](int angle) {
|
||||
const RealT theta = angle * M_PI / 180.0f;
|
||||
return lookat + radius * Vec3T(sin(theta), 0, cos(theta));
|
||||
};
|
||||
|
||||
nanovdb::Camera<RealT, Vec3T, RayT> camera(eye(0), lookat, up, vfov, aspect);
|
||||
|
||||
nanovdb::ImageHandle<> imgHandle(width, height);
|
||||
auto* img = imgHandle.image();
|
||||
|
||||
auto kernel2D = [&](const tbb::blocked_range2d<int>& r) {
|
||||
openvdb::tools::LevelSetRayIntersector<GridT, openvdb::tools::LinearSearchImpl<GridT, 0, RealT>, GridT::TreeType::RootNodeType::ChildNodeType::LEVEL, RayT> tester(*srcGrid);
|
||||
const RealT wScale = 1.0f / width, hScale = 1.0f / height;
|
||||
auto acc = srcGrid->getAccessor();
|
||||
CoordT ijk;
|
||||
Vec3T xyz;
|
||||
float v;
|
||||
for (int w = r.rows().begin(); w != r.rows().end(); ++w) {
|
||||
for (int h = r.cols().begin(); h != r.cols().end(); ++h) {
|
||||
const RayT wRay = camera.getRay(w * wScale, h * hScale);
|
||||
RayT iRay = wRay.applyInverseMap(*srcGrid->transform().baseMap());
|
||||
if (tester.intersectsIS(iRay, xyz)) {
|
||||
ijk = openvdb::Coord::floor(xyz);
|
||||
v = acc.getValue(ijk);
|
||||
Vec3T grad(-v);
|
||||
ijk[0] += 1;
|
||||
grad[0] += acc.getValue(ijk);
|
||||
ijk[0] -= 1;
|
||||
ijk[1] += 1;
|
||||
grad[1] += acc.getValue(ijk);
|
||||
ijk[1] -= 1;
|
||||
ijk[2] += 1;
|
||||
grad[2] += acc.getValue(ijk);
|
||||
grad.normalize();
|
||||
(*img)(w, h) = ColorRGB(std::abs(grad.dot(iRay.dir())), 0, 0);
|
||||
} else {
|
||||
const int checkerboard = 1 << 7;
|
||||
(*img)(w, h) = ((h & checkerboard) ^ (w & checkerboard)) ? ColorRGB(1, 1, 1) : ColorRGB(0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}; // kernel
|
||||
|
||||
for (int angle = 0; angle < 6; ++angle) {
|
||||
camera.update(eye(angle), lookat, up, vfov, aspect);
|
||||
std::stringstream ss;
|
||||
ss << "OpenVDB: CPU kernel with " << img->size() << " rays";
|
||||
tbb::blocked_range2d<int> range2D(0, img->width(), 0, img->height());
|
||||
mTimer.start(ss.str());
|
||||
#if 1
|
||||
tbb::parallel_for(range2D, kernel2D);
|
||||
#else
|
||||
kernel2D(range2D);
|
||||
#endif
|
||||
mTimer.stop();
|
||||
//mTimer.start("Write image to file");
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
ss << image_path << "/openvdb_cpu_" << std::setfill('0') << std::setw(3) << angle << ".ppm";
|
||||
img->writePPM(ss.str(), "Benchmark test");
|
||||
//mTimer.stop();
|
||||
} // loop over angle
|
||||
} // OpenVDB_CPU
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
TEST_F(Benchmark, DenseGrid_CPU)
|
||||
{
|
||||
using CoordT = nanovdb::Coord;
|
||||
using ColorRGB = nanovdb::Image::ColorRGB;
|
||||
using RealT = float;
|
||||
using Vec3T = nanovdb::Vec3<RealT>;
|
||||
using RayT = nanovdb::Ray<RealT>;
|
||||
|
||||
auto handle = nanovdb::io::readDense("data/test.vol");
|
||||
auto* grid = handle.grid<float>();
|
||||
EXPECT_TRUE(grid);
|
||||
EXPECT_TRUE(grid->isLevelSet());
|
||||
|
||||
const int width = 1280, height = 720;
|
||||
const RealT vfov = 25.0f, aspect = RealT(width) / height, radius = 300.0f;
|
||||
const auto bbox = grid->worldBBox();
|
||||
const Vec3T lookat(0.5 * (bbox.min() + bbox.max())), up(0, -1, 0);
|
||||
auto eye = [&lookat, &radius](int angle) {
|
||||
const RealT theta = angle * M_PI / 180.0f;
|
||||
return lookat + radius * Vec3T(sin(theta), 0, cos(theta));
|
||||
};
|
||||
|
||||
nanovdb::Camera<RealT> camera(eye(0), lookat, up, vfov, aspect);
|
||||
|
||||
nanovdb::ImageHandle<> imgHandle(width, height);
|
||||
auto* img = imgHandle.image();
|
||||
|
||||
auto kernel2D = [&](int x0, int y0, int x1, int y1) {
|
||||
const RealT wScale = 1.0f / width, hScale = 1.0f / height;
|
||||
for (int w = x0; w != x1; ++w) {
|
||||
for (int h = y0; h != y1; ++h) {
|
||||
RayT ray = camera.getRay(w * wScale, h * hScale);
|
||||
ray = ray.worldToIndexF(*grid);
|
||||
if (!ray.clip(grid->indexBBox().expandBy(-1))) continue;
|
||||
nanovdb::DDA<RayT> dda(ray);
|
||||
CoordT ijk = dda.voxel();
|
||||
EXPECT_TRUE(grid->test(ijk));
|
||||
const float v0 = grid->getValue(ijk);
|
||||
bool hit = false;
|
||||
while( !hit && dda.step() ) {
|
||||
ijk = dda.voxel();
|
||||
EXPECT_TRUE(grid->test(ijk));
|
||||
const float v1 = grid->getValue(ijk);
|
||||
if (v0*v1>0) continue;
|
||||
Vec3T grad(-v1);
|
||||
ijk[0] += 1;
|
||||
grad[0] += grid->getValue(ijk);
|
||||
ijk[0] -= 1;
|
||||
ijk[1] += 1;
|
||||
grad[1] += grid->getValue(ijk);
|
||||
ijk[1] -= 1;
|
||||
ijk[2] += 1;
|
||||
grad[2] += grid->getValue(ijk);
|
||||
grad.normalize();
|
||||
(*img)(w, h) = ColorRGB(std::abs(grad.dot(ray.dir())), 0, 0);
|
||||
hit = true;
|
||||
}
|
||||
if (!hit) {
|
||||
const int checkerboard = 1 << 7;
|
||||
(*img)(w, h) = ((h & checkerboard) ^ (w & checkerboard)) ? ColorRGB(1, 1, 1) : ColorRGB(0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}; // kernel
|
||||
|
||||
for (int angle = 0; angle < 6; ++angle) {
|
||||
camera.update(eye(angle), lookat, up, vfov, aspect);
|
||||
std::stringstream ss;
|
||||
ss << "DenseGrid: CPU kernel with " << img->size() << " rays";
|
||||
mTimer.start(ss.str());
|
||||
#if defined(NANOVDB_USE_TBB)
|
||||
tbb::blocked_range2d<int> range(0, img->width(), 0, img->height());
|
||||
tbb::parallel_for(range, [&](const tbb::blocked_range2d<int>& r) {
|
||||
kernel2D(r.rows().begin(), r.cols().begin(), r.rows().end(), r.cols().end());
|
||||
});
|
||||
#else
|
||||
kernel2D(0, 0, img->width(), img->height());
|
||||
#endif
|
||||
mTimer.stop();
|
||||
//mTimer.start("Write image to file");
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
ss << "./dense_cpu_" << std::setfill('0') << std::setw(3) << angle << ".ppm";
|
||||
img->writePPM(ss.str(), "Benchmark test");
|
||||
//mTimer.stop();
|
||||
} // loop over angle
|
||||
} // DenseGrid_CPU
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
|
||||
// Convenience function for checking CUDA runtime API results
|
||||
// can be wrapped around any runtime API call. No-op in release builds.
|
||||
#define cudaCheck(ans) \
|
||||
{ \
|
||||
gpuAssert((ans), __FILE__, __LINE__); \
|
||||
}
|
||||
|
||||
static inline bool gpuAssert(cudaError_t code, const char* file, int line, bool abort = true)
|
||||
{
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
if (code != cudaSuccess) {
|
||||
fprintf(stderr, "CUDA Runtime Error: %s %s %d\n", cudaGetErrorString(code), file, line);
|
||||
if (abort)
|
||||
exit(code);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void launch_kernels(const nanovdb::GridHandle<nanovdb::CudaDeviceBuffer>&,
|
||||
nanovdb::ImageHandle<nanovdb::CudaDeviceBuffer>&,
|
||||
const nanovdb::Camera<float>*,
|
||||
cudaStream_t stream);
|
||||
|
||||
TEST_F(Benchmark, NanoVDB_GPU)
|
||||
{
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
using RealT = float;
|
||||
using Vec3T = nanovdb::Vec3<RealT>;
|
||||
using CameraT = nanovdb::Camera<RealT>;
|
||||
|
||||
const std::string image_path = this->getEnvVar("VDB_SCRATCH_PATH", ".");
|
||||
|
||||
// The first CUDA run time call initializes the CUDA sub-system (loads the runtime API) which takes time!
|
||||
int deviceCount;
|
||||
cudaGetDeviceCount(&deviceCount);
|
||||
for (int device = 0; device < deviceCount; ++device) {
|
||||
cudaDeviceProp deviceProp;
|
||||
cudaGetDeviceProperties(&deviceProp, device);
|
||||
printf("Device %d has compute capability %d.%d.\n",
|
||||
device,
|
||||
deviceProp.major,
|
||||
deviceProp.minor);
|
||||
}
|
||||
cudaSetDevice(0);
|
||||
|
||||
cudaStream_t stream;
|
||||
cudaCheck(cudaStreamCreate(&stream));
|
||||
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
auto handle = nanovdb::io::readGrid<BufferT>("data/test.nvdb");
|
||||
#else
|
||||
auto handle = nanovdb::createLevelSetTorus<float, float, BufferT>(100.0f, 50.0f);
|
||||
#endif
|
||||
//auto handle = nanovdb::io::readGrid<BufferT>("data/test.nvdb");
|
||||
const auto* grid = handle.grid<float>();
|
||||
EXPECT_TRUE(grid);
|
||||
EXPECT_TRUE(grid->isLevelSet());
|
||||
EXPECT_FALSE(grid->isFogVolume());
|
||||
handle.deviceUpload(stream, false);
|
||||
|
||||
std::cout << "\nRay-tracing NanoVDB grid named \"" << grid->gridName() << "\"" << std::endl;
|
||||
|
||||
const int width = 1280, height = 720;
|
||||
const RealT vfov = 25.0f, aspect = RealT(width) / height, radius = 300.0f;
|
||||
const auto bbox = grid->worldBBox();
|
||||
const Vec3T lookat(0.5 * (bbox.min() + bbox.max())), up(0, -1, 0);
|
||||
auto eye = [&lookat, &radius](int angle) {
|
||||
const RealT theta = angle * M_PI / 180.0f;
|
||||
return lookat + radius * Vec3T(sin(theta), 0, cos(theta));
|
||||
};
|
||||
CameraT *host_camera, *dev_camera;
|
||||
cudaCheck(cudaMalloc((void**)&dev_camera, sizeof(CameraT))); // un-managed memory on the device
|
||||
cudaCheck(cudaMallocHost((void**)&host_camera, sizeof(CameraT)));
|
||||
|
||||
nanovdb::ImageHandle<BufferT> imgHandle(width, height);
|
||||
auto* img = imgHandle.image();
|
||||
imgHandle.deviceUpload(stream, false);
|
||||
|
||||
for (int angle = 0; angle < 6; ++angle) {
|
||||
std::stringstream ss;
|
||||
ss << "NanoVDB: GPU kernel with " << img->size() << " rays";
|
||||
host_camera->update(eye(angle), lookat, up, vfov, aspect);
|
||||
cudaCheck(cudaMemcpyAsync(dev_camera, host_camera, sizeof(CameraT), cudaMemcpyHostToDevice, stream));
|
||||
mTimer.start(ss.str());
|
||||
launch_kernels(handle, imgHandle, dev_camera, stream);
|
||||
mTimer.stop();
|
||||
|
||||
//mTimer.start("Write image to file");
|
||||
imgHandle.deviceDownload(stream);
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
ss << image_path << "/nanovdb_gpu_" << std::setfill('0') << std::setw(3) << angle << ".ppm";
|
||||
img->writePPM(ss.str(), "Benchmark test");
|
||||
//mTimer.stop();
|
||||
|
||||
} //frame number angle
|
||||
|
||||
cudaCheck(cudaStreamDestroy(stream));
|
||||
cudaCheck(cudaFree(host_camera));
|
||||
cudaCheck(cudaFree(dev_camera));
|
||||
} // NanoVDB_GPU
|
||||
#endif
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @file Benchmark_nano.cc
|
||||
///
|
||||
/// @author Ken Museth
|
||||
///
|
||||
/// @brief A super lightweight and portable ray-tracing benchmark
|
||||
/// that only depends on NanoVDB (not OpenVDB) and CUDA.
|
||||
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
#include "Image.h"
|
||||
#include "Camera.h"
|
||||
#include "DenseGrid.h"
|
||||
#include "../ex_util/CpuTimer.h"
|
||||
|
||||
#include <iomanip>// for std::setfill and std::setw
|
||||
|
||||
|
||||
// Convenience function for checking CUDA runtime API results
|
||||
// can be wrapped around any runtime API call. No-op in release builds.
|
||||
#define cudaCheck(ans) \
|
||||
{ \
|
||||
gpuAssert((ans), __FILE__, __LINE__); \
|
||||
}
|
||||
|
||||
static inline bool gpuAssert(cudaError_t code, const char* file, int line, bool abort = true)
|
||||
{
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
if (code != cudaSuccess) {
|
||||
fprintf(stderr, "CUDA Runtime Error: %s %s %d\n", cudaGetErrorString(code), file, line);
|
||||
if (abort)
|
||||
exit(code);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" float launch_kernels(const nanovdb::DenseGridHandle<nanovdb::CudaDeviceBuffer>&,
|
||||
nanovdb::ImageHandle<nanovdb::CudaDeviceBuffer>&,
|
||||
const nanovdb::Camera<float>*,
|
||||
cudaStream_t stream);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
using RealT = float;
|
||||
using Vec3T = nanovdb::Vec3<RealT>;
|
||||
using CameraT = nanovdb::Camera<RealT>;
|
||||
nanovdb::CpuTimer<> timer;
|
||||
|
||||
if (argc!=2) {
|
||||
std::cerr << "Usage: " << argv[0] << " path/level_set.vol" << std::endl;
|
||||
//std::cerr << "To generate an input file: nanovdb_convert dragon.vdb dragon.nvdb\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The first CUDA run time call initializes the CUDA sub-system (loads the runtime API) which takes time!
|
||||
int deviceCount;
|
||||
cudaGetDeviceCount(&deviceCount);
|
||||
for (int device = 0; device < deviceCount; ++device) {
|
||||
cudaDeviceProp deviceProp;
|
||||
cudaGetDeviceProperties(&deviceProp, device);
|
||||
printf("Device %d has compute capability %d.%d.\n",
|
||||
device,
|
||||
deviceProp.major,
|
||||
deviceProp.minor);
|
||||
}
|
||||
cudaSetDevice(0);
|
||||
|
||||
cudaStream_t stream;
|
||||
cudaCheck(cudaStreamCreate(&stream));
|
||||
|
||||
auto handle = nanovdb::io::readDense<BufferT>(argv[1]);
|
||||
|
||||
const auto* grid = handle.grid<float>();
|
||||
if (!grid || !grid->isLevelSet()) {
|
||||
std::cerr << "Error loading NanoVDB level set from file" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
handle.deviceUpload(stream, false);
|
||||
std::cout << "\nRay-tracing DenseGrid of size "
|
||||
<< (grid->gridSize() >> 20) << " MB" << std::endl;
|
||||
|
||||
const int width = 1280, height = 720;
|
||||
const RealT vfov = 25.0f, aspect = RealT(width) / height, radius = 300.0f;
|
||||
const auto bbox = grid->worldBBox();
|
||||
const Vec3T lookat(0.5 * (bbox.min() + bbox.max())), up(0, -1, 0);
|
||||
auto eye = [&lookat, &radius](int angle) {
|
||||
const RealT theta = angle * M_PI / 180.0f;
|
||||
return lookat + radius * Vec3T(sin(theta), 0, cos(theta));
|
||||
};
|
||||
CameraT *host_camera, *dev_camera;
|
||||
cudaCheck(cudaMalloc((void**)&dev_camera, sizeof(CameraT))); // un-managed memory on the device
|
||||
cudaCheck(cudaMallocHost((void**)&host_camera, sizeof(CameraT)));
|
||||
|
||||
nanovdb::ImageHandle<BufferT> imgHandle(width, height);
|
||||
auto* img = imgHandle.image();
|
||||
imgHandle.deviceUpload(stream, false);
|
||||
|
||||
float elapsedTime = 0.0f;
|
||||
const int maxAngle = 360;
|
||||
for (int angle = 0; angle < maxAngle; ++angle) {
|
||||
host_camera->update(eye(angle), lookat, up, vfov, aspect);
|
||||
cudaCheck(cudaMemcpyAsync(dev_camera, host_camera, sizeof(CameraT), cudaMemcpyHostToDevice, stream));
|
||||
elapsedTime += launch_kernels(handle, imgHandle, dev_camera, stream);
|
||||
|
||||
//timer.start("Write image to file");
|
||||
imgHandle.deviceDownload(stream);
|
||||
std::stringstream ss;
|
||||
ss << "./dense_gpu_" << std::setfill('0') << std::setw(3) << angle << ".ppm";
|
||||
img->writePPM(ss.str(), "Benchmark test");
|
||||
//timer.stop();
|
||||
|
||||
} //frame number angle
|
||||
|
||||
cudaCheck(cudaStreamDestroy(stream));
|
||||
cudaCheck(cudaFree(host_camera));
|
||||
cudaCheck(cudaFree(dev_camera));
|
||||
|
||||
printf("\nRay-traced %i different frames, each with %i rays, in %5.3f ms.\nThis corresponds to an average of %5.3f ms per frame or %5.3f FPS!\n",
|
||||
maxAngle, imgHandle.image()->size(), elapsedTime, elapsedTime/maxAngle, 1000.0f*maxAngle/elapsedTime);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @file Benchmark_nano.cc
|
||||
///
|
||||
/// @author Ken Museth
|
||||
///
|
||||
/// @brief A super lightweight and portable ray-tracing benchmark
|
||||
/// that only depends on NanoVDB (not OpenVDB) and CUDA.
|
||||
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
#include "Image.h"
|
||||
#include "Camera.h"
|
||||
#include "../ex_util/CpuTimer.h"
|
||||
|
||||
#include <iomanip>// for std::setfill and std::setw
|
||||
|
||||
|
||||
// Convenience function for checking CUDA runtime API results
|
||||
// can be wrapped around any runtime API call. No-op in release builds.
|
||||
#define cudaCheck(ans) \
|
||||
{ \
|
||||
gpuAssert((ans), __FILE__, __LINE__); \
|
||||
}
|
||||
|
||||
static inline bool gpuAssert(cudaError_t code, const char* file, int line, bool abort = true)
|
||||
{
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
if (code != cudaSuccess) {
|
||||
fprintf(stderr, "CUDA Runtime Error: %s %s %d\n", cudaGetErrorString(code), file, line);
|
||||
if (abort)
|
||||
exit(code);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" float launch_kernels(const nanovdb::GridHandle<nanovdb::CudaDeviceBuffer>&,
|
||||
nanovdb::ImageHandle<nanovdb::CudaDeviceBuffer>&,
|
||||
const nanovdb::Camera<float>*,
|
||||
cudaStream_t stream);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
using ValueT = float;
|
||||
using BuildT = nanovdb::FpN;
|
||||
using Vec3T = nanovdb::Vec3<ValueT>;
|
||||
using CameraT = nanovdb::Camera<ValueT>;
|
||||
nanovdb::CpuTimer<> timer;
|
||||
|
||||
if (argc!=2) {
|
||||
std::cerr << "Usage: " << argv[0] << " path/level_set.nvdb" << std::endl;
|
||||
std::cerr << "To generate an input file: nanovdb_convert dragon.vdb dragon.nvdb\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The first CUDA run time call initializes the CUDA sub-system (loads the runtime API) which takes time!
|
||||
int deviceCount;
|
||||
cudaGetDeviceCount(&deviceCount);
|
||||
for (int device = 0; device < deviceCount; ++device) {
|
||||
cudaDeviceProp deviceProp;
|
||||
cudaGetDeviceProperties(&deviceProp, device);
|
||||
printf("Device %d has compute capability %d.%d.\n",
|
||||
device,
|
||||
deviceProp.major,
|
||||
deviceProp.minor);
|
||||
}
|
||||
cudaSetDevice(0);
|
||||
int driverVersion, runtimeVersion;
|
||||
cudaDriverGetVersion(&driverVersion);
|
||||
cudaRuntimeGetVersion(&runtimeVersion);
|
||||
printf("CUDA driver version:\t%i.%i\n", driverVersion/1000, (driverVersion%1000)/10);
|
||||
printf("CUDA runtime version:\t%i.%i\n", runtimeVersion/1000, (runtimeVersion%1000)/10);
|
||||
|
||||
cudaStream_t stream;
|
||||
cudaCheck(cudaStreamCreate(&stream));
|
||||
|
||||
auto handle = nanovdb::io::readGrid<BufferT>(argv[1]);
|
||||
|
||||
const auto* grid = handle.grid<BuildT>();
|
||||
if (!grid || !grid->isLevelSet()) {
|
||||
std::cerr << "Error loading NanoVDB level set from file" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
handle.deviceUpload(stream, false);
|
||||
std::cout << "\nRay-tracing NanoVDB grid named \"" << grid->gridName() << "\" of size "
|
||||
<< (grid->gridSize() >> 20) << " MB" << std::endl;
|
||||
|
||||
const int width = 1280, height = 720;
|
||||
const ValueT vfov = 25.0f, aspect = ValueT(width) / height, radius = 300.0f;
|
||||
const auto bbox = grid->worldBBox();
|
||||
const Vec3T lookat(0.5 * (bbox.min() + bbox.max())), up(0, -1, 0);
|
||||
auto eye = [&lookat, &radius](int angle) {
|
||||
const ValueT theta = angle * M_PI / 180.0f;
|
||||
return lookat + radius * Vec3T(sin(theta), 0, cos(theta));
|
||||
};
|
||||
CameraT *host_camera, *dev_camera;
|
||||
cudaCheck(cudaMalloc((void**)&dev_camera, sizeof(CameraT))); // un-managed memory on the device
|
||||
cudaCheck(cudaMallocHost((void**)&host_camera, sizeof(CameraT)));
|
||||
|
||||
nanovdb::ImageHandle<BufferT> imgHandle(width, height);
|
||||
auto* img = imgHandle.image();
|
||||
imgHandle.deviceUpload(stream, false);
|
||||
|
||||
float elapsedTime = 0.0f;
|
||||
const int maxAngle = 360;
|
||||
for (int angle = 0; angle < maxAngle; ++angle) {
|
||||
host_camera->update(eye(angle), lookat, up, vfov, aspect);
|
||||
cudaCheck(cudaMemcpyAsync(dev_camera, host_camera, sizeof(CameraT), cudaMemcpyHostToDevice, stream));
|
||||
elapsedTime += launch_kernels(handle, imgHandle, dev_camera, stream);
|
||||
|
||||
//timer.start("Write image to file");
|
||||
imgHandle.deviceDownload(stream);
|
||||
#if 1
|
||||
std::stringstream ss;
|
||||
ss << "./nanovdb_gpu_" << std::setfill('0') << std::setw(3) << angle << ".ppm";
|
||||
img->writePPM(ss.str(), "Benchmark test");
|
||||
#endif
|
||||
//timer.stop();
|
||||
|
||||
} //frame number angle
|
||||
|
||||
cudaCheck(cudaStreamDestroy(stream));
|
||||
cudaCheck(cudaFree(host_camera));
|
||||
cudaCheck(cudaFree(dev_camera));
|
||||
|
||||
printf("\nRay-traced %i different frames, each with %i rays, in %5.3f ms.\nThis corresponds to an average of %5.3f ms per frame or %5.3f FPS!\n",
|
||||
maxAngle, imgHandle.image()->size(), elapsedTime, elapsedTime/maxAngle, 1000.0f*maxAngle/elapsedTime);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
# Copyright Contributors to the OpenVDB Project
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
#[=======================================================================[
|
||||
|
||||
CMake Configuration for NanoVDB Benchmark
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(NanoVDBBenchmark LANGUAGES CXX)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
###############################################################################
|
||||
|
||||
message(STATUS "----------------------------------------------------")
|
||||
message(STATUS "---------- Configuring NanoVDB Benchmark -----------")
|
||||
message(STATUS "----------------------------------------------------")
|
||||
|
||||
###############################################################################
|
||||
|
||||
if(WIN32 AND NANOVDB_CUDA_KEEP_PTX)
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/Release")
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# TODO: Benchmark should probably not require gtest.
|
||||
if(NOT TARGET GTest::GTest)
|
||||
message(WARNING " - GTest required to build benchmark. Skipping.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# many of the sample projects depend on a data directory. This allows Debug
|
||||
# launching from the cmake binary working directory.
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/data")
|
||||
|
||||
set(BENCHMARK_SOURCES Benchmark.cc Camera.h Image.h)
|
||||
|
||||
if(NANOVDB_USE_CUDA)
|
||||
list(APPEND BENCHMARK_SOURCES BenchKernels_nano.cu)
|
||||
|
||||
add_executable(benchmark_nano Benchmark_nano.cc BenchKernels_nano.cu)
|
||||
add_executable(benchmark_dense Benchmark_dense.cc BenchKernels_dense.cu)
|
||||
|
||||
target_link_libraries(benchmark_nano PRIVATE nanovdb)
|
||||
target_link_libraries(benchmark_dense PRIVATE nanovdb)
|
||||
|
||||
# Propagate MSVC Runtime from the OpenVDB library (if VDB_MSVC_RUNTIME_SELECTION
|
||||
# has been set then we're building and linking against OpenVDB, see the root
|
||||
# NanoVDB CMakeLists.txt)
|
||||
if(VDB_MSVC_RUNTIME_SELECTION)
|
||||
set_target_properties(benchmark_nano PROPERTIES
|
||||
MSVC_RUNTIME_LIBRARY ${VDB_MSVC_RUNTIME_SELECTION})
|
||||
set_target_properties(benchmark_dense PROPERTIES
|
||||
MSVC_RUNTIME_LIBRARY ${VDB_MSVC_RUNTIME_SELECTION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
add_executable(benchmark ${BENCHMARK_SOURCES})
|
||||
target_link_libraries(benchmark PRIVATE nanovdb GTest::GTest GTest::Main)
|
||||
|
||||
# Propagate MSVC Runtime from the OpenVDB library (if VDB_MSVC_RUNTIME_SELECTION
|
||||
# has been set then we're building and linking against OpenVDB, see the root
|
||||
# NanoVDB CMakeLists.txt)
|
||||
if(VDB_MSVC_RUNTIME_SELECTION)
|
||||
set_target_properties(benchmark PROPERTIES
|
||||
MSVC_RUNTIME_LIBRARY ${VDB_MSVC_RUNTIME_SELECTION})
|
||||
endif()
|
||||
|
||||
install(TARGETS benchmark DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples)
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @file Camera.h
|
||||
///
|
||||
/// @author Ken Museth
|
||||
///
|
||||
/// @brief A simple camera class.
|
||||
|
||||
#ifndef NANOVDB_CAMERA_H_HAS_BEEN_INCLUDED
|
||||
#define NANOVDB_CAMERA_H_HAS_BEEN_INCLUDED
|
||||
|
||||
#include <nanovdb/NanoVDB.h> // for Vec3
|
||||
#include <nanovdb/util/Ray.h>
|
||||
|
||||
namespace nanovdb {
|
||||
|
||||
/// @brief A minimal perspective camera for ray generation
|
||||
template<typename RealT = float, typename Vec3T = Vec3<RealT>, typename RayT = Ray<RealT>>
|
||||
class Camera
|
||||
{
|
||||
Vec3T mEye, mW, mU, mV;
|
||||
|
||||
__hostdev__ void init(RealT vfov, RealT aspect)
|
||||
{
|
||||
const RealT halfHeight = RealT(tan(vfov * 3.14159265358979323846 / 360));
|
||||
const RealT halfWidth = aspect * halfHeight;
|
||||
mW = halfWidth * mU + halfHeight * mV + mW; // remove eye here and in getRay
|
||||
mU *= 2 * halfWidth;
|
||||
mV *= 2 * halfHeight;
|
||||
}
|
||||
|
||||
public:
|
||||
/// @brief default Ctor.
|
||||
Camera() = default;
|
||||
|
||||
/// @brief Ctor. // vfov is top to bottom in degrees
|
||||
/// @note up is assumed to be a unit-vector
|
||||
__hostdev__ Camera(const Vec3T& eye, const Vec3T& lookat, const Vec3T& up, RealT vfov, RealT aspect)
|
||||
: mEye(eye)
|
||||
, mW((eye - lookat).normalize())
|
||||
, mU(up.cross(mW))
|
||||
, mV(up)
|
||||
{
|
||||
this->init(vfov, aspect);
|
||||
}
|
||||
__hostdev__ void update(const Vec3T& eye, const Vec3T& lookat, const Vec3T& up, RealT vfov, RealT aspect)
|
||||
{
|
||||
mEye = eye;
|
||||
mV = up;
|
||||
mW = mEye - lookat;
|
||||
mW.normalize();
|
||||
mU = mV.cross(mW);
|
||||
this->init(vfov, aspect);
|
||||
}
|
||||
/// @brief {u,v} are are assumed to be [0,1]
|
||||
__hostdev__ RayT getRay(RealT u, RealT v) const {
|
||||
auto dir = u * mU + v * mV - mW;
|
||||
dir.normalize();
|
||||
return RayT(mEye, dir);
|
||||
}
|
||||
|
||||
__hostdev__ const Vec3T& P() const { return mEye; }
|
||||
__hostdev__ const Vec3T& U() const { return mU; }
|
||||
__hostdev__ const Vec3T& V() const { return mV; }
|
||||
__hostdev__ const Vec3T& W() const { return mW; }
|
||||
|
||||
}; // Camera
|
||||
|
||||
} // namespace nanovdb
|
||||
|
||||
#endif // NANOVDB_CAMERA_HAS_BEEN_INCLUDED
|
||||
@@ -0,0 +1,487 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @file DenseGrid.h
|
||||
///
|
||||
/// @author Ken Museth
|
||||
///
|
||||
/// @brief Simple dense grid class.
|
||||
|
||||
#ifndef NANOVDB_DENSEGRID_H_HAS_BEEN_INCLUDED
|
||||
#define NANOVDB_DENSEGRID_H_HAS_BEEN_INCLUDED
|
||||
|
||||
#include <stdint.h>// for uint64_t
|
||||
#include <fstream> // for std::ifstream
|
||||
#include <nanovdb/util/HostBuffer.h>// for default Buffer
|
||||
#include <nanovdb/util/ForEach.h>
|
||||
#include <nanovdb/NanoVDB.h>// for Map, GridClass, GridType and and Coord
|
||||
|
||||
|
||||
// use 4x4x4 tiles for better cache coherence
|
||||
// else it uses dense indexing which is slow!
|
||||
// 0 means disable, 1 is 2x2x2, 2 is 4x4x4 and 3 is 8x8x8
|
||||
#define LOG2_TILE_SIZE 2
|
||||
|
||||
namespace nanovdb {
|
||||
|
||||
// forward decleration
|
||||
template<typename BufferT = HostBuffer>
|
||||
class DenseGridHandle;
|
||||
|
||||
#define DENSE_MAGIC_NUMBER 0x42445665736e6544UL // "DenseVDB" in hex - little endian (uint64_t)
|
||||
|
||||
|
||||
struct DenseData
|
||||
{
|
||||
Map mMap;// defined in NanoVDB.h
|
||||
CoordBBox mIndexBBox;// min/max of bbox
|
||||
BBox<Vec3R> mWorldBBox;// 48B. floating-point AABB of active values in WORLD SPACE (2 x 3 doubles)
|
||||
Vec3R mVoxelSize;
|
||||
GridClass mGridClass;// defined in NanoVDB.h
|
||||
GridType mGridType; // defined in NanoVDB.h
|
||||
uint64_t mY, mX;//strides in the y and x direction
|
||||
uint64_t mSize;
|
||||
|
||||
__hostdev__ Coord dim() const { return mIndexBBox.dim(); }
|
||||
|
||||
// Affine transformations based on double precision
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyMap(const Vec3T& xyz) const { return mMap.applyMap(xyz); } // Pos: index -> world
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyInverseMap(const Vec3T& xyz) const { return mMap.applyInverseMap(xyz); } // Pos: world -> index
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyJacobian(const Vec3T& xyz) const { return mMap.applyJacobian(xyz); } // Dir: index -> world
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyInverseJacobian(const Vec3T& xyz) const { return mMap.applyInverseJacobian(xyz); } // Dir: world -> index
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyIJT(const Vec3T& xyz) const { return mMap.applyIJT(xyz); }
|
||||
// Affine transformations based on single precision
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyMapF(const Vec3T& xyz) const { return mMap.applyMapF(xyz); } // Pos: index -> world
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyInverseMapF(const Vec3T& xyz) const { return mMap.applyInverseMapF(xyz); } // Pos: world -> index
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyJacobianF(const Vec3T& xyz) const { return mMap.applyJacobianF(xyz); } // Dir: index -> world
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyInverseJacobianF(const Vec3T& xyz) const { return mMap.applyInverseJacobianF(xyz); } // Dir: world -> index
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T applyIJTF(const Vec3T& xyz) const { return mMap.applyIJTF(xyz); }
|
||||
};
|
||||
/// @brief Simple dense grid class
|
||||
/// @note ZYX is the memory-layout in VDB. It leads to nested
|
||||
/// for-loops of the order x, y, z.
|
||||
template<typename ValueT>
|
||||
class DenseGrid : private DenseData
|
||||
{
|
||||
#if LOG2_TILE_SIZE > 0
|
||||
static constexpr uint32_t TileLog2 = LOG2_TILE_SIZE, TileMask = (1 << TileLog2) - 1, TileDim = 1 << (3*TileLog2);
|
||||
#endif
|
||||
using DenseData = DenseData;
|
||||
|
||||
public:
|
||||
using ValueType = ValueT;
|
||||
|
||||
template<typename BufferT = HostBuffer>
|
||||
inline static DenseGridHandle<BufferT> create(Coord min, // min inclusive index coordinate
|
||||
Coord max, // max inclusive index coordinate
|
||||
double dx = 1.0, //voxel size
|
||||
const Vec3d& p0 = Vec3d(0.0), // origin
|
||||
GridClass gridClass = GridClass::Unknown,
|
||||
const BufferT& allocator = BufferT());
|
||||
|
||||
__hostdev__ DenseGrid(const DenseGrid&) = delete;
|
||||
__hostdev__ ~DenseGrid() = delete;
|
||||
__hostdev__ DenseGrid& operator=(const DenseGrid&) = delete;
|
||||
|
||||
__hostdev__ uint64_t size() const { return mIndexBBox.volume(); }
|
||||
__hostdev__ inline uint64_t coordToOffset(const Coord &ijk) const;
|
||||
__hostdev__ inline bool test(const Coord &ijk) const;
|
||||
__hostdev__ uint64_t memUsage() const {return mSize;}
|
||||
__hostdev__ uint64_t gridSize() const {return this->memUsage();}
|
||||
__hostdev__ const Coord& min() const { return mIndexBBox[0]; }
|
||||
__hostdev__ const Coord& max() const { return mIndexBBox[1]; }
|
||||
__hostdev__ inline bool isValidType() const;
|
||||
|
||||
/// @brief Return a const reference to the Map for this grid
|
||||
__hostdev__ const Map& map() const { return DenseData::mMap; }
|
||||
|
||||
// @brief Return a const reference to the size of a voxel in world units
|
||||
__hostdev__ const Vec3R& voxelSize() const { return DenseData::mVoxelSize; }
|
||||
|
||||
/// @brief world to index space transformation
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T worldToIndex(const Vec3T& xyz) const { return this->applyInverseMap(xyz); }
|
||||
|
||||
/// @brief world to index space transformation
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T indexToWorld(const Vec3T& xyz) const { return this->applyMap(xyz); }
|
||||
|
||||
/// @brief transformation from index space direction to world space direction
|
||||
/// @warning assumes dir to be normalized
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T indexToWorldDir(const Vec3T& dir) const { return this->applyJacobian(dir); }
|
||||
|
||||
/// @brief transformation from world space direction to index space direction
|
||||
/// @warning assumes dir to be normalized
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T worldToIndexDir(const Vec3T& dir) const { return this->applyInverseJacobian(dir); }
|
||||
|
||||
/// @brief transform the gradient from index space to world space.
|
||||
/// @details Applies the inverse jacobian transform map.
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T indexToWorldGrad(const Vec3T& grad) const { return this->applyIJT(grad); }
|
||||
|
||||
/// @brief world to index space transformation
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T worldToIndexF(const Vec3T& xyz) const { return this->applyInverseMapF(xyz); }
|
||||
|
||||
/// @brief index to world space transformation
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T indexToWorldF(const Vec3T& xyz) const { return this->applyMapF(xyz); }
|
||||
|
||||
/// @brief transformation from index space direction to world space direction
|
||||
/// @warning assumes dir to be normalized
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T indexToWorldDirF(const Vec3T& dir) const { return this->applyJacobianF(dir); }
|
||||
|
||||
/// @brief transformation from world space direction to index space direction
|
||||
/// @warning assumes dir to be normalized
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T worldToIndexDirF(const Vec3T& dir) const { return this->applyInverseJacobianF(dir); }
|
||||
|
||||
/// @brief Transforms the gradient from index space to world space.
|
||||
/// @details Applies the inverse jacobian transform map.
|
||||
template<typename Vec3T>
|
||||
__hostdev__ Vec3T indexToWorldGradF(const Vec3T& grad) const { return DenseData::applyIJTF(grad); }
|
||||
|
||||
/// @brief Computes a AABB of active values in world space
|
||||
__hostdev__ const BBox<Vec3R>& worldBBox() const { return DenseData::mWorldBBox; }
|
||||
|
||||
__hostdev__ bool isLevelSet() const { return DenseData::mGridClass == GridClass::LevelSet; }
|
||||
__hostdev__ bool isFogVolume() const { return DenseData::mGridClass == GridClass::FogVolume; }
|
||||
|
||||
/// @brief Computes a AABB of active values in index space
|
||||
///
|
||||
/// @note This method is returning a floating point bounding box and not a CoordBBox. This makes
|
||||
/// it more useful for clipping rays.
|
||||
__hostdev__ const CoordBBox& indexBBox() const { return mIndexBBox; }
|
||||
|
||||
__hostdev__ const GridType& gridType() const { return DenseData::mGridType; }
|
||||
__hostdev__ const GridClass& gridClass() const { return DenseData::mGridClass; }
|
||||
|
||||
__hostdev__ DenseData* data() { return reinterpret_cast<DenseData*>(this); }
|
||||
__hostdev__ const DenseData* data() const { return reinterpret_cast<const DenseData*>(this); }
|
||||
|
||||
__hostdev__ ValueT* values() { return reinterpret_cast<ValueT*>(this+1);}
|
||||
__hostdev__ const ValueT* values() const { return reinterpret_cast<const ValueT*>(this+1); }
|
||||
|
||||
__hostdev__ inline const ValueT& getValue(const Coord &ijk) const;
|
||||
__hostdev__ inline void setValue(const Coord &ijk, const ValueT &v);
|
||||
}; // Grid
|
||||
|
||||
template<typename ValueT>
|
||||
template<typename BufferT>
|
||||
DenseGridHandle<BufferT>
|
||||
DenseGrid<ValueT>::create(Coord min,
|
||||
Coord max,
|
||||
double dx, //voxel size
|
||||
const Vec3d& p0, // origin
|
||||
GridClass gridClass,
|
||||
const BufferT& allocator)
|
||||
{
|
||||
if (dx <= 0) {
|
||||
throw std::runtime_error("GridBuilder: voxel size is zero or negative");
|
||||
}
|
||||
max += Coord(1,1,1);// now max is exclusive
|
||||
|
||||
#if LOG2_TILE_SIZE > 0
|
||||
const uint64_t dim[3] = {(uint64_t(max[0] - min[0]) + TileMask) >> TileLog2,
|
||||
(uint64_t(max[1] - min[1]) + TileMask) >> TileLog2,
|
||||
(uint64_t(max[2] - min[2]) + TileMask) >> TileLog2};
|
||||
const uint64_t size = sizeof(DenseGrid) + sizeof(ValueT)*TileDim*dim[0]*dim[1]*dim[2];
|
||||
#else
|
||||
const uint64_t dim[3] = {uint64_t(max[0] - min[0]),
|
||||
uint64_t(max[1] - min[1]),
|
||||
uint64_t(max[2] - min[2])};
|
||||
const uint64_t size = sizeof(DenseGrid) + sizeof(ValueT)*dim[0]*dim[1]*dim[2];
|
||||
#endif
|
||||
|
||||
DenseGridHandle<BufferT> handle(allocator.create(size));
|
||||
DenseGrid* grid = reinterpret_cast<DenseGrid*>(handle.data());
|
||||
grid->mSize = size;
|
||||
const double Tx = p0[0], Ty = p0[1], Tz = p0[2];
|
||||
const double mat[4][4] = {
|
||||
{dx, 0.0, 0.0, 0.0}, // row 0
|
||||
{0.0, dx, 0.0, 0.0}, // row 1
|
||||
{0.0, 0.0, dx, 0.0}, // row 2
|
||||
{Tx, Ty, Tz, 1.0}, // row 3
|
||||
};
|
||||
const double invMat[4][4] = {
|
||||
{1 / dx, 0.0, 0.0, 0.0}, // row 0
|
||||
{0.0, 1 / dx, 0.0, 0.0}, // row 1
|
||||
{0.0, 0.0, 1 / dx, 0.0}, // row 2
|
||||
{-Tx, -Ty, -Tz, 1.0}, // row 3
|
||||
};
|
||||
|
||||
grid->mMap.set(mat, invMat, 1.0);
|
||||
for (int i=0; i<3; ++i) {
|
||||
grid->mIndexBBox[0][i] = min[i];
|
||||
grid->mIndexBBox[1][i] = max[i] - 1;
|
||||
}
|
||||
grid->mWorldBBox[0] = grid->mWorldBBox[1] = grid->mMap.applyMap(Vec3d(min[0], min[1], min[2]));
|
||||
grid->mWorldBBox.expand(grid->mMap.applyMap(Vec3d(min[0], min[1], max[2])));
|
||||
grid->mWorldBBox.expand(grid->mMap.applyMap(Vec3d(min[0], max[1], min[2])));
|
||||
grid->mWorldBBox.expand(grid->mMap.applyMap(Vec3d(max[0], min[1], min[2])));
|
||||
grid->mWorldBBox.expand(grid->mMap.applyMap(Vec3d(max[0], max[1], min[2])));
|
||||
grid->mWorldBBox.expand(grid->mMap.applyMap(Vec3d(max[0], min[1], max[2])));
|
||||
grid->mWorldBBox.expand(grid->mMap.applyMap(Vec3d(min[0], max[1], max[2])));
|
||||
grid->mWorldBBox.expand(grid->mMap.applyMap(Vec3d(max[0], max[1], max[2])));
|
||||
grid->mVoxelSize = grid->mMap.applyMap(Vec3d(1)) - grid->mMap.applyMap(Vec3d(0));
|
||||
if (gridClass == GridClass::LevelSet && !is_floating_point<ValueT>::value)
|
||||
throw std::runtime_error("Level sets are expected to be floating point types");
|
||||
if (gridClass == GridClass::FogVolume && !is_floating_point<ValueT>::value)
|
||||
throw std::runtime_error("Fog volumes are expected to be floating point types");
|
||||
grid->mGridClass = gridClass;
|
||||
grid->mGridType = mapToGridType<ValueT>();
|
||||
grid->mY = dim[2];
|
||||
grid->mX = dim[2] * dim[1];
|
||||
return handle;
|
||||
}
|
||||
|
||||
template<typename ValueT>
|
||||
bool DenseGrid<ValueT>::test(const Coord &ijk) const
|
||||
{
|
||||
return (ijk[0]>=mIndexBBox[0][0]) && (ijk[0]<=mIndexBBox[1][0]) &&
|
||||
(ijk[1]>=mIndexBBox[0][1]) && (ijk[1]<=mIndexBBox[1][1]) &&
|
||||
(ijk[2]>=mIndexBBox[0][2]) && (ijk[2]<=mIndexBBox[1][2]);
|
||||
}
|
||||
|
||||
template<typename ValueT>
|
||||
uint64_t DenseGrid<ValueT>::coordToOffset(const Coord &ijk) const
|
||||
{
|
||||
assert(this->test(ijk));
|
||||
#if LOG2_TILE_SIZE > 0
|
||||
const uint32_t x = ijk[0] - mIndexBBox[0][0];
|
||||
const uint32_t y = ijk[1] - mIndexBBox[0][1];
|
||||
const uint32_t z = ijk[2] - mIndexBBox[0][2];
|
||||
return ((mX*(x>>TileLog2) + mY*(y>>TileLog2) + (z>>TileLog2))<<(3*TileLog2)) +
|
||||
((x&TileMask)<<(2*TileLog2)) + ((y&TileMask)<<TileLog2) + (z&TileMask);
|
||||
#else
|
||||
return uint64_t(ijk[0]-mIndexBBox[0][0])*mX +
|
||||
uint64_t(ijk[1]-mIndexBBox[0][1])*mY +
|
||||
uint64_t(ijk[2]-mIndexBBox[0][2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename ValueT>
|
||||
const ValueT& DenseGrid<ValueT>::getValue(const Coord &ijk) const
|
||||
{
|
||||
return this->values()[this->coordToOffset(ijk)];
|
||||
}
|
||||
|
||||
template<typename ValueT>
|
||||
void DenseGrid<ValueT>::setValue(const Coord &ijk, const ValueT &value)
|
||||
{
|
||||
this->values()[this->coordToOffset(ijk)] = value;
|
||||
}
|
||||
|
||||
template<typename ValueT>
|
||||
bool DenseGrid<ValueT>::isValidType() const
|
||||
{
|
||||
return std::is_same<float, ValueT>::value ? mGridType == GridType::Float : false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
namespace io{
|
||||
|
||||
template<typename ValueT>
|
||||
void writeDense(const DenseGrid<ValueT> &grid, const char* fileName)
|
||||
{
|
||||
std::ofstream os(fileName, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
if (!os.is_open()) {
|
||||
throw std::runtime_error("Unable to open file for output");
|
||||
}
|
||||
const uint64_t tmp[2] = {DENSE_MAGIC_NUMBER, grid.memUsage()};
|
||||
os.write(reinterpret_cast<const char*>(tmp), 2*sizeof(uint64_t));
|
||||
os.write(reinterpret_cast<const char*>(&grid), tmp[1]);
|
||||
}
|
||||
|
||||
template<typename BufferT>
|
||||
void writeDense(const DenseGridHandle<BufferT> &handle, const char* fileName)
|
||||
{
|
||||
std::ofstream os(fileName, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
if (!os.is_open()) {
|
||||
throw std::runtime_error("Unable to open file for output");
|
||||
}
|
||||
const uint64_t tmp[2] = {DENSE_MAGIC_NUMBER, handle.size()};
|
||||
os.write(reinterpret_cast<const char*>(tmp), 2*sizeof(uint64_t));
|
||||
os.write(reinterpret_cast<const char*>(handle.data()), tmp[1]);
|
||||
}
|
||||
|
||||
template<typename BufferT = HostBuffer>
|
||||
DenseGridHandle<BufferT>
|
||||
readDense(const char* fileName, const BufferT& allocator = BufferT())
|
||||
{
|
||||
std::ifstream is(fileName, std::ios::in | std::ios::binary);
|
||||
if (!is.is_open()) {
|
||||
throw std::runtime_error("Unable to open file for input");
|
||||
}
|
||||
uint64_t tmp[2];
|
||||
is.read(reinterpret_cast<char*>(tmp), 2*sizeof(uint64_t));
|
||||
if (tmp[0] != DENSE_MAGIC_NUMBER) {
|
||||
throw std::runtime_error("This is not a dense NanoVDB file!");
|
||||
}
|
||||
DenseGridHandle<BufferT> handle(allocator.create(tmp[1]));
|
||||
is.read(reinterpret_cast<char*>(handle.data()), tmp[1]);
|
||||
return handle;
|
||||
}
|
||||
}// namespace io
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/// @brief Converts a NanoVDB grid to a DenseGrid
|
||||
template<typename GridT, typename BufferT = HostBuffer>
|
||||
DenseGridHandle<BufferT> convertToDense(const GridT &grid, const BufferT& allocator = BufferT())
|
||||
{
|
||||
using ValueT = typename GridT::ValueType;
|
||||
using DenseT = DenseGrid<ValueT>;
|
||||
const Coord min = grid.indexBBox().min(), max = grid.indexBBox().max() + Coord(1,1,1);// max is exclusive!
|
||||
#if LOG2_TILE_SIZE > 0
|
||||
static constexpr uint32_t TileLog2 = LOG2_TILE_SIZE, TileMask = (1 << TileLog2) - 1, TileDim = 1 << (3*TileLog2);
|
||||
const uint64_t dim[3] = {(uint64_t(max[0] - min[0]) + TileMask) >> TileLog2,
|
||||
(uint64_t(max[1] - min[1]) + TileMask) >> TileLog2,
|
||||
(uint64_t(max[2] - min[2]) + TileMask) >> TileLog2};
|
||||
const uint64_t size = sizeof(DenseT) + sizeof(ValueT)*TileDim*dim[0]*dim[1]*dim[2];
|
||||
#else
|
||||
const uint64_t dim[3] = {uint64_t(max[0] - min[0]),
|
||||
uint64_t(max[1] - min[1]),
|
||||
uint64_t(max[2] - min[2])};
|
||||
const uint64_t size = sizeof(DenseT) + sizeof(ValueT)*dim[0]*dim[1]*dim[2];
|
||||
#endif
|
||||
|
||||
DenseGridHandle<BufferT> handle( allocator.create(size) );
|
||||
auto *dense = reinterpret_cast<DenseT*>(handle.data());
|
||||
auto *data = dense->data();
|
||||
|
||||
// copy DenseData
|
||||
data->mMap = grid.map();
|
||||
data->mIndexBBox = grid.indexBBox();
|
||||
data->mWorldBBox = grid.worldBBox();
|
||||
data->mVoxelSize = grid.voxelSize();
|
||||
data->mGridClass = grid.gridClass();
|
||||
data->mGridType = grid.gridType();
|
||||
data->mY = dim[2];
|
||||
data->mX = dim[2] * dim[1];
|
||||
data->mSize = size;
|
||||
|
||||
// copy values
|
||||
auto kernel = [&](const Range<1,int> &r) {
|
||||
auto acc = grid.getAccessor();
|
||||
Coord ijk;
|
||||
for (ijk[0] = r.begin(); ijk[0] < r.end(); ++ijk[0]) {
|
||||
for (ijk[1] = min[1]; ijk[1] < max[1]; ++ijk[1]) {
|
||||
for (ijk[2] = min[2]; ijk[2] < max[2]; ++ijk[2]) {
|
||||
dense->setValue(ijk, acc.getValue(ijk));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Range<1,int> range(min[0], max[0]);
|
||||
#if 1
|
||||
forEach(range, kernel);
|
||||
#else
|
||||
kernel(range);
|
||||
#endif
|
||||
|
||||
return handle;
|
||||
}
|
||||
/////////////////////////////////////////////
|
||||
|
||||
template<typename BufferT>
|
||||
class DenseGridHandle
|
||||
{
|
||||
BufferT mBuffer;
|
||||
|
||||
public:
|
||||
DenseGridHandle(BufferT&& resources) { mBuffer = std::move(resources); }
|
||||
|
||||
DenseGridHandle() = default;
|
||||
/// @brief Disallow copy-construction
|
||||
DenseGridHandle(const DenseGridHandle&) = delete;
|
||||
/// @brief Disallow copy assignment operation
|
||||
DenseGridHandle& operator=(const DenseGridHandle&) = delete;
|
||||
/// @brief Move copy assignment operation
|
||||
DenseGridHandle& operator=(DenseGridHandle&& other) noexcept
|
||||
{
|
||||
mBuffer = std::move(other.mBuffer);
|
||||
return *this;
|
||||
}
|
||||
/// @brief Move copy-constructor
|
||||
DenseGridHandle(DenseGridHandle&& other) noexcept { mBuffer = std::move(other.mBuffer); }
|
||||
/// @brief Default destructor
|
||||
~DenseGridHandle() { this->reset(); }
|
||||
|
||||
void reset() { mBuffer.clear(); }
|
||||
|
||||
BufferT& buffer() { return mBuffer; }
|
||||
const BufferT& buffer() const { return mBuffer; }
|
||||
|
||||
/// @brief Returns a non-const pointer to the data.
|
||||
///
|
||||
/// @warning Note that the return pointer can be NULL if the DenseGridHandle was not initialized
|
||||
uint8_t* data() {return mBuffer.data();}
|
||||
|
||||
/// @brief Returns a const pointer to the data.
|
||||
///
|
||||
/// @warning Note that the return pointer can be NULL if the DenseGridHandle was not initialized
|
||||
const uint8_t* data() const {return mBuffer.data();}
|
||||
|
||||
/// @brief Returns the size in bytes of the raw memory buffer managed by this DenseGridHandle's allocator.
|
||||
uint64_t size() const { return mBuffer.size();}
|
||||
|
||||
/// @brief Returns a const pointer to the NanoVDB grid encoded in the DenseGridHandle.
|
||||
///
|
||||
/// @warning Note that the return pointer can be NULL if the DenseGridHandle was not initialized or the template
|
||||
/// parameter does not match!
|
||||
template<typename ValueT>
|
||||
const DenseGrid<ValueT>* grid() const
|
||||
{
|
||||
using GridT = const DenseGrid<ValueT>;
|
||||
GridT* grid = reinterpret_cast<GridT*>(mBuffer.data());
|
||||
return (grid && grid->isValidType()) ? grid : nullptr;
|
||||
}
|
||||
|
||||
template<typename ValueT>
|
||||
DenseGrid<ValueT>* grid()
|
||||
{
|
||||
using GridT = DenseGrid<ValueT>;
|
||||
GridT* grid = reinterpret_cast<GridT*>(mBuffer.data());
|
||||
return (grid && grid->isValidType()) ? grid : nullptr;
|
||||
}
|
||||
|
||||
template<typename ValueT, typename U = BufferT>
|
||||
typename std::enable_if<BufferTraits<U>::hasDeviceDual, const DenseGrid<ValueT>*>::type
|
||||
deviceGrid() const
|
||||
{
|
||||
using GridT = const DenseGrid<ValueT>;
|
||||
bool isValidType = reinterpret_cast<GridT*>(mBuffer.data())->isValidType();
|
||||
GridT* grid = reinterpret_cast<GridT*>(mBuffer.deviceData());
|
||||
return (grid && isValidType) ? grid : nullptr;
|
||||
}
|
||||
|
||||
template<typename U = BufferT>
|
||||
typename std::enable_if<BufferTraits<U>::hasDeviceDual, void>::type
|
||||
deviceUpload(void* stream = nullptr, bool sync = true) {
|
||||
mBuffer.deviceUpload(stream, sync);
|
||||
}
|
||||
|
||||
template<typename U = BufferT>
|
||||
typename std::enable_if<BufferTraits<U>::hasDeviceDual, void>::type
|
||||
deviceDownload(void* stream = nullptr, bool sync = true) {
|
||||
mBuffer.deviceDownload(stream, sync);
|
||||
}
|
||||
}; // DenseGridHandle
|
||||
|
||||
} // namespace nanovdb
|
||||
|
||||
#endif // NANOVDB_DENSEGRID_HAS_BEEN_INCLUDED
|
||||
@@ -0,0 +1,159 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/*!
|
||||
\file Image.h
|
||||
|
||||
\author Ken Museth
|
||||
|
||||
\date January 8, 2020
|
||||
|
||||
\brief A simple image class that uses pinned memory for fast GPU transfer
|
||||
|
||||
\warning This class is only included to support benchmark-tests.
|
||||
*/
|
||||
|
||||
#ifndef NANOVDB_IMAGE_H_HAS_BEEN_INCLUDED
|
||||
#define NANOVDB_IMAGE_H_HAS_BEEN_INCLUDED
|
||||
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <string> // for std::string
|
||||
#include <fstream> // for std::ofstream
|
||||
#include <cassert>
|
||||
|
||||
#include <nanovdb/util/HostBuffer.h>
|
||||
|
||||
#if defined(NANOVDB_USE_TBB)
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/blocked_range2d.h>
|
||||
#endif
|
||||
|
||||
namespace nanovdb {
|
||||
|
||||
struct ImageData
|
||||
{
|
||||
int mWidth, mHeight, mSize;
|
||||
float mScale[2];
|
||||
ImageData(int w, int h)
|
||||
: mWidth(w)
|
||||
, mHeight(h)
|
||||
, mSize(w * h)
|
||||
, mScale{1.0f / w, 1.0f / h}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// @note Can only be constructed by an ImageHandle
|
||||
class Image : private ImageData
|
||||
{
|
||||
using DataT = ImageData;
|
||||
|
||||
public:
|
||||
struct ColorRGB
|
||||
{
|
||||
uint8_t r, g, b;
|
||||
__hostdev__ ColorRGB(float _r, float _g, float _b)
|
||||
: r(uint8_t(_r * 255.0f))
|
||||
, g(uint8_t(_g * 255.0f))
|
||||
, b(uint8_t(_b * 255.0f))
|
||||
{
|
||||
}
|
||||
};
|
||||
void clear(int log2 = 7);
|
||||
__hostdev__ int width() const { return DataT::mWidth; }
|
||||
__hostdev__ int height() const { return DataT::mHeight; }
|
||||
__hostdev__ int size() const { return DataT::mSize; }
|
||||
__hostdev__ float u(int w) const { return w * mScale[0]; }
|
||||
__hostdev__ float v(int h) const { return h * mScale[1]; }
|
||||
__hostdev__ inline ColorRGB& operator()(int w, int h);
|
||||
void writePPM(const std::string& fileName, const std::string& comment = "width height 255");
|
||||
}; // Image
|
||||
|
||||
template<typename BufferT = HostBuffer>
|
||||
class ImageHandle
|
||||
{
|
||||
BufferT mBuffer;
|
||||
|
||||
public:
|
||||
ImageHandle(int width, int height, int log2 = 7);
|
||||
|
||||
const Image* image() const { return reinterpret_cast<const Image*>(mBuffer.data()); }
|
||||
|
||||
Image* image() { return reinterpret_cast<Image*>(mBuffer.data()); }
|
||||
|
||||
template<typename U = BufferT>
|
||||
typename std::enable_if<BufferTraits<U>::hasDeviceDual, const Image*>::type
|
||||
deviceImage() const { return reinterpret_cast<const Image*>(mBuffer.deviceData()); }
|
||||
|
||||
template<typename U = BufferT>
|
||||
typename std::enable_if<BufferTraits<U>::hasDeviceDual, Image*>::type
|
||||
deviceImage() { return reinterpret_cast<Image*>(mBuffer.deviceData()); }
|
||||
|
||||
template<typename U = BufferT>
|
||||
typename std::enable_if<BufferTraits<U>::hasDeviceDual, void>::type
|
||||
deviceUpload(void* stream = nullptr, bool sync = true) { mBuffer.deviceUpload(stream, sync); }
|
||||
|
||||
template<typename U = BufferT>
|
||||
typename std::enable_if<BufferTraits<U>::hasDeviceDual, void>::type
|
||||
deviceDownload(void* stream = nullptr, bool sync = true) { mBuffer.deviceDownload(stream, sync); }
|
||||
};
|
||||
|
||||
template<typename BufferT>
|
||||
ImageHandle<BufferT>::ImageHandle(int width, int height, int log2)
|
||||
: mBuffer(sizeof(ImageData) + width * height * sizeof(Image::ColorRGB))
|
||||
{
|
||||
ImageData data(width, height);
|
||||
*reinterpret_cast<ImageData*>(mBuffer.data()) = data;
|
||||
this->image()->clear(log2); // clear pixels or set background
|
||||
}
|
||||
|
||||
inline void Image::clear(int log2)
|
||||
{
|
||||
ColorRGB* ptr = &(*this)(0, 0);
|
||||
if (log2 < 0) {
|
||||
for (auto* end = ptr + ImageData::mSize; ptr != end;)
|
||||
*ptr++ = ColorRGB(0, 0, 0);
|
||||
} else {
|
||||
const int checkerboard = 1 << log2;
|
||||
|
||||
auto kernel2D = [&](int x0, int y0, int x1, int y1) {
|
||||
for (int h = y0; h != y1; ++h) {
|
||||
const int n = h & checkerboard;
|
||||
ColorRGB* p = ptr + h * ImageData::mWidth;
|
||||
for (int w = x0; w != x1; ++w) {
|
||||
*(p + w) = (n ^ (w & checkerboard)) ? ColorRGB(1, 1, 1) : ColorRGB(0, 0, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(NANOVDB_USE_TBB)
|
||||
tbb::blocked_range2d<int> range(0, ImageData::mWidth, 0, ImageData::mHeight);
|
||||
tbb::parallel_for(range, [&](const tbb::blocked_range2d<int>& r) {
|
||||
kernel2D(r.rows().begin(), r.cols().begin(), r.rows().end(), r.cols().end());
|
||||
});
|
||||
#else
|
||||
kernel2D(0, 0, ImageData::mWidth, ImageData::mHeight);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
inline Image::ColorRGB& Image::operator()(int w, int h)
|
||||
{
|
||||
assert(w < ImageData::mWidth);
|
||||
assert(h < ImageData::mHeight);
|
||||
return *(reinterpret_cast<ColorRGB*>((uint8_t*)this + sizeof(ImageData)) + w + h * ImageData::mWidth);
|
||||
}
|
||||
|
||||
inline void Image::writePPM(const std::string& fileName, const std::string& comment)
|
||||
{
|
||||
std::ofstream os(fileName, std::ios::out | std::ios::binary);
|
||||
if (os.fail())
|
||||
throw std::runtime_error("Unable to open file named \"" + fileName + "\" for output");
|
||||
os << "P6\n#" << comment << "\n"
|
||||
<< this->width() << " " << this->height() << "\n255\n";
|
||||
os.write((const char*)&(*this)(0, 0), this->size() * sizeof(ColorRGB));
|
||||
}
|
||||
|
||||
} // namespace nanovdb
|
||||
|
||||
#endif // end of NANOVDB_IMAGE_H_HAS_BEEN_INCLUDED
|
||||
@@ -0,0 +1,131 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/util/Primitives.h>
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/HostBuffer.h>
|
||||
#include <algorithm>
|
||||
|
||||
//////////////////////////////////////////////
|
||||
class BumpPoolAllocatorContext
|
||||
{
|
||||
public:
|
||||
uint64_t mNextFreeOffset;
|
||||
nanovdb::HostBuffer mPoolSlab;
|
||||
|
||||
BumpPoolAllocatorContext(uint64_t size)
|
||||
: mNextFreeOffset(0)
|
||||
{
|
||||
mPoolSlab.init(size);
|
||||
std::cout << "Created BumpPoolAllocatorContext" << std::endl;
|
||||
}
|
||||
|
||||
~BumpPoolAllocatorContext()
|
||||
{
|
||||
mPoolSlab.clear();
|
||||
std::cout << "Destroyed BumpPoolAllocatorContext" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
// This is an example of a custom Buffer with has a persistent state allocator ("mState") within it.
|
||||
// It must have methods for "clear", "data" (both const and non-const variants), and "size".
|
||||
// It must also include a static "create" method.
|
||||
class PoolBuffer
|
||||
{
|
||||
uint64_t mOffset = -1;
|
||||
uint64_t mSize = 0;
|
||||
std::shared_ptr<BumpPoolAllocatorContext> mState;
|
||||
|
||||
public:
|
||||
PoolBuffer() = default;
|
||||
PoolBuffer(const PoolBuffer&) = delete;
|
||||
PoolBuffer& operator=(const PoolBuffer&) = delete;
|
||||
PoolBuffer(PoolBuffer&&) = default;
|
||||
PoolBuffer& operator=(PoolBuffer&&) = default;
|
||||
|
||||
// Initialize the stateful allocator.
|
||||
void initialize(uint64_t size)
|
||||
{
|
||||
if (!mState) {
|
||||
mState = std::make_shared<BumpPoolAllocatorContext>(size);
|
||||
}
|
||||
}
|
||||
|
||||
// Mandatory.
|
||||
// Create a buffer instance (optionally using the context as a hint)
|
||||
static PoolBuffer create(uint64_t size, const PoolBuffer* context)
|
||||
{
|
||||
if (!context || !context->mState) {
|
||||
throw std::runtime_error("context has not been created.");
|
||||
}
|
||||
|
||||
PoolBuffer buffer;
|
||||
buffer.mState = context->mState;
|
||||
buffer.mOffset = context->mState->mNextFreeOffset;
|
||||
buffer.mSize = size;
|
||||
context->mState->mNextFreeOffset += size;
|
||||
|
||||
printf("Creating resources offset(%d) size(%d)\n", (int)buffer.mOffset, (int)buffer.mSize);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Mandatory.
|
||||
// Clear the buffer data.
|
||||
void clear()
|
||||
{
|
||||
// nothing to do, as this is a simple "bump" allocator.
|
||||
}
|
||||
|
||||
// Mandatory.
|
||||
// Return the size of the buffer data.
|
||||
uint64_t size() const { return mSize; }
|
||||
|
||||
// Mandatory.
|
||||
// Return non-const pointer to the buffer data.
|
||||
uint8_t* data() { return mState->mPoolSlab.data() + mOffset; }
|
||||
|
||||
// Mandatory.
|
||||
// Return const pointer to the buffer data.
|
||||
const uint8_t* data() const { return mState->mPoolSlab.data() + mOffset; }
|
||||
};
|
||||
|
||||
// we specify this trait to avoid declaring the "device...(...)" convenience methods.
|
||||
// By default, "hasDeviceDual" is false for a Buffer, but we are just being overly explicit here.
|
||||
namespace nanovdb {
|
||||
template<>
|
||||
struct BufferTraits<PoolBuffer>
|
||||
{
|
||||
static const bool hasDeviceDual = false;
|
||||
};
|
||||
} // namespace nanovdb
|
||||
|
||||
int main()
|
||||
{
|
||||
PoolBuffer bufferContext;
|
||||
// We must initialize the stateful allocator.
|
||||
bufferContext.initialize(1 << 26);
|
||||
|
||||
try {
|
||||
std::vector<nanovdb::GridHandle<PoolBuffer>> gridHdls;
|
||||
|
||||
// create two grids...
|
||||
gridHdls.push_back(nanovdb::createLevelSetSphere(100.0f, nanovdb::Vec3f(-20, 0, 0), 1.0, 3.0, nanovdb::Vec3R(0), "spheref", nanovdb::StatsMode::BBox, nanovdb::ChecksumMode::Partial, -1.0f, false, bufferContext));
|
||||
gridHdls.push_back(nanovdb::createLevelSetSphere(100.0, nanovdb::Vec3d( 20, 0, 0), 1.0, 3.0, nanovdb::Vec3R(0), "sphered", nanovdb::StatsMode::BBox, nanovdb::ChecksumMode::Partial, -1.0f, false, bufferContext));
|
||||
|
||||
// Get a (raw) pointer to the NanoVDB grid form the GridManager.
|
||||
auto* dstGrid = gridHdls[0].grid<float>();
|
||||
if (!dstGrid)
|
||||
throw std::runtime_error("GridHandle does not contain a grid with value type float");
|
||||
|
||||
// Access and print out a single value (inside the level set) from both grids
|
||||
printf("NanoVDB cpu: %4.2f\n", dstGrid->tree().getValue(nanovdb::Coord(99, 0, 0)));
|
||||
|
||||
// Write the NanoVDB grids to file and throw if writing fails
|
||||
nanovdb::io::writeGrids<PoolBuffer, std::vector>("data/spheres.nvdb", gridHdls, nanovdb::io::Codec::NONE, 2);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <nanovdb/NanoVDB.h>
|
||||
#include "ComputePrimitives.h"
|
||||
|
||||
// http://www.burtleburtle.net/bob/hash/doobs.html
|
||||
inline __hostdev__ uint32_t hash(uint32_t x)
|
||||
{
|
||||
x += (x << 10u);
|
||||
x ^= (x >> 6u);
|
||||
x += (x << 3u);
|
||||
x ^= (x >> 11u);
|
||||
x += (x << 15u);
|
||||
return x;
|
||||
}
|
||||
|
||||
inline __hostdev__ float randomf(uint32_t s)
|
||||
{
|
||||
return hash(s) / float(0xffffffffu);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/Primitives.h>
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
#else
|
||||
using BufferT = nanovdb::HostBuffer;
|
||||
#endif
|
||||
|
||||
extern void runNanoVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int numPoints, BufferT& positionBuffer, BufferT& velocityBuffer);
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
extern void runOpenVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int numPoints, BufferT& positionBuffer, BufferT& velocityBuffer);
|
||||
#endif
|
||||
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
try {
|
||||
nanovdb::GridHandle<BufferT> handle;
|
||||
if (ac > 1) {
|
||||
handle = nanovdb::io::readGrid<BufferT>(av[1]);
|
||||
std::cout << "Loaded NanoVDB grid[" << handle.gridMetaData()->shortGridName() << "]...\n";
|
||||
} else {
|
||||
handle = nanovdb::createLevelSetSphere<float, float, BufferT>(100.0f, nanovdb::Vec3f(-20, 0, 0), 1.0, 3.0, nanovdb::Vec3R(0), "sphere");
|
||||
}
|
||||
|
||||
if (handle.gridMetaData()->isLevelSet() == false) {
|
||||
throw std::runtime_error("Grid must be a level set");
|
||||
}
|
||||
|
||||
const int numIterations = 100;
|
||||
|
||||
const int numPoints = 10000000;
|
||||
|
||||
BufferT positionBuffer;
|
||||
positionBuffer.init(numPoints * sizeof(float) * 3);
|
||||
BufferT velocityBuffer;
|
||||
velocityBuffer.init(numPoints * sizeof(float) * 3);
|
||||
|
||||
runNanoVDB(handle, numIterations, numPoints, positionBuffer, velocityBuffer);
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
runOpenVDB(handle, numIterations, numPoints, positionBuffer, velocityBuffer);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/GridBuilder.h>
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
#include <nanovdb/util/Ray.h>
|
||||
#include <nanovdb/util/HDDA.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
#else
|
||||
using BufferT = nanovdb::HostBuffer;
|
||||
#endif
|
||||
|
||||
using namespace nanovdb;
|
||||
|
||||
template<typename UpdateOp>
|
||||
float updateParticles(bool useCuda, const UpdateOp op, int numPoints, Vec3f* positions, Vec3f* velocities, const Grid<FloatTree>* grid)
|
||||
{
|
||||
using ClockT = std::chrono::high_resolution_clock;
|
||||
auto t0 = ClockT::now();
|
||||
|
||||
computeForEach(
|
||||
useCuda, numPoints, 512, __FILE__, __LINE__, [op, positions, velocities, grid] __hostdev__(int start, int end) {
|
||||
for (int i = start; i < end; ++i) {
|
||||
op(i, positions, velocities, grid);
|
||||
}
|
||||
});
|
||||
computeSync(useCuda, __FILE__, __LINE__);
|
||||
|
||||
auto t1 = ClockT::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count() / 1000.f;
|
||||
return duration;
|
||||
}
|
||||
|
||||
void runNanoVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int numPoints, BufferT& positionBuffer, BufferT& velocityBuffer)
|
||||
{
|
||||
using namespace nanovdb;
|
||||
|
||||
auto* h_grid = handle.grid<float>();
|
||||
if (!h_grid)
|
||||
throw std::runtime_error("GridHandle does not contain a FloatGrid");
|
||||
|
||||
Vec3f* h_positions = reinterpret_cast<Vec3f*>(positionBuffer.data());
|
||||
computeFill(false, h_positions, 0, sizeof(Vec3f) * numPoints);
|
||||
|
||||
Vec3f* h_velocities = reinterpret_cast<Vec3f*>(velocityBuffer.data());
|
||||
computeFill(false, h_velocities, 0, sizeof(Vec3f) * numPoints);
|
||||
|
||||
Vec3f wBBoxDim = Vec3f(h_grid->worldBBox().dim());
|
||||
Vec3f wBBoxBottomCenter = Vec3f(h_grid->worldBBox().min()) + wBBoxDim * Vec3f(0.5f, 0, 0.5f);
|
||||
|
||||
const float dt = 0.01f;
|
||||
|
||||
auto collisionResponse = [] __hostdev__(Vec3f pos, Vec3f nextPos, Vec3f normal, float d, Vec3f& outP, Vec3f& outV) {
|
||||
Vec3f delta = (nextPos - pos).normalize() * d;
|
||||
outP = nextPos + delta;
|
||||
outV = outV - 2.0f * (outV.dot(normal) * normal);
|
||||
};
|
||||
|
||||
auto collideOp = [collisionResponse, dt] __hostdev__(const Grid<FloatTree>* grid, Vec3f wPos, Vec3f& wNextPos, Vec3f wVel, Vec3f& wNextVel) {
|
||||
// transform the position to grid index-space...
|
||||
Vec3f iNextPos = grid->worldToIndexF(wNextPos);
|
||||
// the grid index coordinate.
|
||||
auto ijk = Coord::Floor(iNextPos);
|
||||
// get an accessor.
|
||||
auto& tree = grid->tree();
|
||||
auto acc = tree.getAccessor();
|
||||
if (tree.isActive(ijk)) { // are we inside the narrow band?
|
||||
auto wDistance = acc.getValue(ijk);
|
||||
if (wDistance <= 0) { // are we inside the levelset?
|
||||
// get the normal for collision resolution.
|
||||
Vec3f normal(-wDistance);
|
||||
ijk[0] += 1;
|
||||
normal[0] += acc.getValue(ijk);
|
||||
ijk[0] -= 1;
|
||||
ijk[1] += 1;
|
||||
normal[1] += acc.getValue(ijk);
|
||||
ijk[1] -= 1;
|
||||
ijk[2] += 1;
|
||||
normal[2] += acc.getValue(ijk);
|
||||
normal.normalize();
|
||||
|
||||
// handle collision response with the surface.
|
||||
collisionResponse(wPos, wNextPos, normal, wDistance, wNextPos, wNextVel);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto updateOp = [wBBoxBottomCenter, wBBoxDim, collideOp, dt] __hostdev__(int i, Vec3f* positions, Vec3f* velocities, const Grid<FloatTree>* grid) {
|
||||
Vec3f v = velocities[i];
|
||||
Vec3f p = positions[i];
|
||||
// gravity.
|
||||
Vec3f a = Vec3f(0, -9.8f, 0);
|
||||
// integrate.
|
||||
Vec3f nextP = p + v * dt + a * dt * dt;
|
||||
Vec3f nextV = v + a * dt;
|
||||
|
||||
//printf("%f %f %f\n", p[0], p[1], p[2]);
|
||||
|
||||
if (nextP[1] < 0) {
|
||||
// emit at top.
|
||||
nextP = Vec3f(randomf(i * 2 + 0), wBBoxDim[1], randomf(i * 2 + 1));
|
||||
nextV = Vec3f(0, 0, 0);
|
||||
} else {
|
||||
// collision response...
|
||||
collideOp(grid, p, nextP, v, nextV);
|
||||
}
|
||||
|
||||
positions[i] = nextP;
|
||||
velocities[i] = nextV;
|
||||
};
|
||||
|
||||
{
|
||||
float durationAvg = 0;
|
||||
for (int i = 0; i < numIterations; ++i) {
|
||||
float duration = updateParticles(false, updateOp, numPoints, h_positions, h_velocities, h_grid);
|
||||
//std::cout << "Duration(NanoVDB-Host) = " << duration << " ms" << std::endl;
|
||||
durationAvg += duration;
|
||||
}
|
||||
durationAvg /= numIterations;
|
||||
std::cout << "Average Duration(NanoVDB-Host) = " << durationAvg << " ms" << std::endl;
|
||||
}
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
|
||||
handle.deviceUpload();
|
||||
|
||||
auto* d_grid = handle.deviceGrid<float>();
|
||||
if (!d_grid)
|
||||
throw std::runtime_error("GridHandle does not contain a valid device grid");
|
||||
|
||||
positionBuffer.deviceUpload();
|
||||
Vec3f* d_positions = reinterpret_cast<Vec3f*>(positionBuffer.deviceData());
|
||||
|
||||
velocityBuffer.deviceUpload();
|
||||
Vec3f* d_velocities = reinterpret_cast<Vec3f*>(velocityBuffer.deviceData());
|
||||
|
||||
{
|
||||
float durationAvg = 0;
|
||||
for (int i = 0; i < numIterations; ++i) {
|
||||
float duration = updateParticles(true, updateOp, numPoints, d_positions, d_velocities, d_grid);
|
||||
//std::cout << "Duration(NanoVDB-Cuda) = " << duration << " ms" << std::endl;
|
||||
durationAvg += duration;
|
||||
}
|
||||
durationAvg /= numIterations;
|
||||
std::cout << "Average Duration(NanoVDB-Cuda) = " << durationAvg << " ms" << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
|
||||
#include <openvdb/openvdb.h>
|
||||
#include <openvdb/math/Ray.h>
|
||||
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
#include <nanovdb/util/NanoToOpenVDB.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
#else
|
||||
using BufferT = nanovdb::HostBuffer;
|
||||
#endif
|
||||
|
||||
void runOpenVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int numPoints, BufferT& positionBuffer, BufferT& velocityBuffer)
|
||||
{
|
||||
using GridT = openvdb::FloatGrid;
|
||||
using CoordT = openvdb::Coord;
|
||||
using RealT = float;
|
||||
using Vec3T = openvdb::math::Vec3<RealT>;
|
||||
using RayT = openvdb::math::Ray<RealT>;
|
||||
|
||||
auto srcGrid = nanovdb::nanoToOpenVDB(handle);
|
||||
std::cout << "Exporting to OpenVDB grid[" << srcGrid->getName() << "]...\n";
|
||||
|
||||
auto h_grid = (GridT*)srcGrid.get();
|
||||
|
||||
// Not yet implemented...
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/util/GridBuilder.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/// @brief Creates a NanoVDB grids with custom values and access them.
|
||||
///
|
||||
/// @note This example only depends on NanoVDB.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
nanovdb::GridBuilder<float> builder(0.0f);
|
||||
auto acc = builder.getAccessor();
|
||||
acc.setValue(nanovdb::Coord(1, 2, 3), 1.0f);
|
||||
|
||||
printf("GridBuilder: (%i,%i,%i)=%4.2f\t", 1, 2, 3, acc.getValue(nanovdb::Coord(1, 2, 3)));
|
||||
printf("GridBuilder: (%i,%i,%i)=%4.2f\n", 1, 2,-3, acc.getValue(nanovdb::Coord(1, 2,-3)));
|
||||
|
||||
auto handle = builder.getHandle<>();
|
||||
auto* dstGrid = handle.grid<float>(); // Get a (raw) pointer to the NanoVDB grid form the GridManager.
|
||||
if (!dstGrid)
|
||||
throw std::runtime_error("GridHandle does not contain a grid with value type float");
|
||||
|
||||
printf("NanoVDB cpu: (%i,%i,%i)=%4.2f\t", 1, 2, 3, dstGrid->tree().getValue(nanovdb::Coord(1, 2, 3)));
|
||||
printf("NanoVDB cpu: (%i,%i,%i)=%4.2f\n", 1, 2,-3, dstGrid->tree().getValue(nanovdb::Coord(1, 2,-3)));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/util/GridBuilder.h>
|
||||
#include <nanovdb/util/IO.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/// @brief Creates a NanoVDB grids with custom values and access them.
|
||||
///
|
||||
/// @note This example only depends on NanoVDB.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
const float background = 5.0f;
|
||||
nanovdb::GridBuilder<float> builder(background, nanovdb::GridClass::LevelSet);
|
||||
auto acc = builder.getAccessor();
|
||||
const int size = 500;
|
||||
auto func = [&](const nanovdb::Coord &ijk){
|
||||
float v = 40.0f + 50.0f*(cos(ijk[0]*0.1f)*sin(ijk[1]*0.1f) +
|
||||
cos(ijk[1]*0.1f)*sin(ijk[2]*0.1f) +
|
||||
cos(ijk[2]*0.1f)*sin(ijk[0]*0.1f));
|
||||
v = nanovdb::Max(v, nanovdb::Vec3f(ijk).length() - size);// CSG intersection with a sphere
|
||||
return v > background ? background : v < -background ? -background : v;// clamp value
|
||||
};
|
||||
builder(func, nanovdb::CoordBBox(nanovdb::Coord(-size),nanovdb::Coord(size)));
|
||||
|
||||
auto handle = builder.getHandle<>();
|
||||
nanovdb::io::writeGrid("data/funny.nvdb", handle, nanovdb::io::Codec::BLOSC);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/util/Primitives.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/// @brief Creates a NanoVDB grids of a level set sphere and accesses a value.
|
||||
///
|
||||
/// @note This example only depends on NanoVDB.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
auto handle = nanovdb::createLevelSetSphere(100.0f);
|
||||
|
||||
auto* dstGrid = handle.grid<float>(); // Get a (raw) pointer to the NanoVDB grid form the GridManager.
|
||||
if (!dstGrid)
|
||||
throw std::runtime_error("GridHandle does not contain a grid with value type float");
|
||||
|
||||
// Access and print out a single value (inside the level set) from both grids
|
||||
printf("NanoVDB cpu: %4.2f\n", dstGrid->tree().getValue(nanovdb::Coord(99, 0, 0)));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/util/GridBuilder.h>
|
||||
#include <nanovdb/util/IO.h>
|
||||
|
||||
// Helper struct to create a default value for the type.
|
||||
// We use a helper struct so we can specialize it for different types.
|
||||
template<typename ValueT, bool isFloatingPoint = !std::is_integral<ValueT>::value>
|
||||
struct makeDefaultValue
|
||||
{
|
||||
inline ValueT operator()(const nanovdb::Coord& /*ijk*/, int /*radius*/) const
|
||||
{
|
||||
return ValueT(1);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ValueT>
|
||||
struct makeDefaultValue<ValueT, false>
|
||||
{
|
||||
inline ValueT operator()(const nanovdb::Coord& /*ijk*/, int /*radius*/) const
|
||||
{
|
||||
return ValueT(1);
|
||||
}
|
||||
};
|
||||
|
||||
void buildGridForType(std::vector<nanovdb::GridHandle<>>&)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
void buildGridForType(std::vector<nanovdb::GridHandle<>>& gridHandles, T const& bgValue, Ts const&... rest)
|
||||
{
|
||||
using ValueT = T;
|
||||
std::string typeNameStr = typeid(T).name();
|
||||
|
||||
try {
|
||||
|
||||
nanovdb::GridBuilder<ValueT> builder(bgValue);
|
||||
auto acc = builder.getAccessor();
|
||||
|
||||
const int radius = 16;
|
||||
|
||||
for (int z = -radius; z <= radius; ++z) {
|
||||
for (int y = -radius; y <= radius; ++y) {
|
||||
for (int x = -radius; x <= radius; ++x) {
|
||||
const auto ijk = nanovdb::Coord(x, y, z);
|
||||
if (nanovdb::Vec3f(ijk).length() <= radius)
|
||||
acc.setValue(ijk, makeDefaultValue<ValueT>()(ijk, radius));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gridHandles.push_back(builder.template getHandle<>(1.0, nanovdb::Vec3d(0), typeNameStr));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
|
||||
buildGridForType(gridHandles, rest...);
|
||||
}
|
||||
|
||||
/// @brief Creates a NanoVDB grids for each GridType.
|
||||
///
|
||||
/// @note This example only depends on NanoVDB.
|
||||
int main()
|
||||
{
|
||||
std::vector<nanovdb::GridHandle<>> gridHandles;
|
||||
try {
|
||||
/*
|
||||
GridType : uint32_t { Unknown = 0,
|
||||
Float = 1,
|
||||
Double = 2,
|
||||
Int16 = 3,
|
||||
Int32 = 4,
|
||||
Int64 = 5,
|
||||
Vec3f = 6,
|
||||
Vec3d = 7,
|
||||
Mask = 8,
|
||||
FP16 = 9,
|
||||
UInt32 = 10,
|
||||
End = 11 };
|
||||
*/
|
||||
|
||||
buildGridForType(gridHandles, float(0), double(0), int16_t(0), int32_t(0), int64_t(0), uint32_t(0), nanovdb::Vec3f(0) /*, nanovdb::Vec3d(0)*/ /*, bool(false)*/ /*, uint16_t(0)*/);
|
||||
|
||||
nanovdb::io::writeGrids<nanovdb::HostBuffer, std::vector>("data/custom_types.nvdb", gridHandles);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/util/Primitives.h>
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/HostBuffer.h>
|
||||
#include <algorithm>
|
||||
|
||||
//////////////////////////////////////////////
|
||||
class MapPoolAllocatorContext
|
||||
{
|
||||
public:
|
||||
uint64_t mNextUniqueId;
|
||||
std::map<uint64_t, std::shared_ptr<nanovdb::HostBuffer>> mGridBufferMap;
|
||||
|
||||
MapPoolAllocatorContext()
|
||||
: mNextUniqueId(0)
|
||||
{
|
||||
std::cout << "Creating MapPoolAllocatorContext" << std::endl;
|
||||
}
|
||||
|
||||
~MapPoolAllocatorContext()
|
||||
{
|
||||
mGridBufferMap.clear();
|
||||
std::cout << "Destroyed MapPoolAllocatorContext" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
// Note: we use std::enable_shared_from_this so that we can construct a GridHandle
|
||||
// in the createGridHandle method.
|
||||
class MapPoolBuffer
|
||||
{
|
||||
MapPoolBuffer(const MapPoolBuffer&) = delete;
|
||||
MapPoolBuffer& operator=(const MapPoolBuffer&) = delete;
|
||||
|
||||
public:
|
||||
uint64_t mId = -1;
|
||||
std::shared_ptr<nanovdb::HostBuffer> mBuffer;
|
||||
std::shared_ptr<MapPoolAllocatorContext> mState;
|
||||
|
||||
public:
|
||||
void initialize()
|
||||
{
|
||||
if (!mState) {
|
||||
mState = std::make_shared<MapPoolAllocatorContext>();
|
||||
}
|
||||
}
|
||||
|
||||
MapPoolBuffer() = default;
|
||||
|
||||
MapPoolBuffer(MapPoolBuffer&& other)
|
||||
{
|
||||
mId = other.mId;
|
||||
other.mId = -1;
|
||||
mBuffer = std::move(other.mBuffer);
|
||||
mState = std::move(other.mState);
|
||||
}
|
||||
|
||||
MapPoolBuffer& operator=(MapPoolBuffer&& other)
|
||||
{
|
||||
mId = other.mId;
|
||||
other.mId = -1;
|
||||
mBuffer = std::move(other.mBuffer);
|
||||
mState = std::move(other.mState);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static MapPoolBuffer create(uint64_t size, const MapPoolBuffer* context)
|
||||
{
|
||||
MapPoolBuffer buffer;
|
||||
|
||||
if (!context || !context->mState) {
|
||||
throw std::runtime_error("context has not been created.");
|
||||
}
|
||||
|
||||
buffer.mState = context->mState;
|
||||
if (!buffer.mState)
|
||||
buffer.mState = std::make_shared<MapPoolAllocatorContext>();
|
||||
buffer.mId = buffer.mState->mNextUniqueId++;
|
||||
buffer.mBuffer = std::make_shared<nanovdb::HostBuffer>(size);
|
||||
buffer.mState->mGridBufferMap.emplace(buffer.mId, buffer.mBuffer);
|
||||
|
||||
printf("Creating resources id(%d) buffer(%p)\n", (int)buffer.mId, buffer.mBuffer.get());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (mBuffer.use_count() == 2) {
|
||||
mState->mGridBufferMap.erase(mId);
|
||||
printf("Destroying resources id(%d) buffer(%p)\n", (int)mId, mBuffer.get());
|
||||
}
|
||||
mId = -1;
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
|
||||
uint64_t size() const { return getBuffer(mId).size(); }
|
||||
uint8_t* data() { return getBuffer(mId).data(); }
|
||||
const uint8_t* data() const { return getBuffer(mId).data(); }
|
||||
|
||||
std::vector<uint64_t> getGridKeys() const
|
||||
{
|
||||
std::vector<uint64_t> keys;
|
||||
std::transform(
|
||||
mState->mGridBufferMap.begin(),
|
||||
mState->mGridBufferMap.end(),
|
||||
std::back_inserter(keys),
|
||||
[](const std::map<uint64_t, std::shared_ptr<nanovdb::HostBuffer>>::value_type& pair) { return pair.first; });
|
||||
return keys;
|
||||
}
|
||||
|
||||
MapPoolBuffer copy(uint64_t id) const
|
||||
{
|
||||
MapPoolBuffer buffer;
|
||||
buffer.mState = mState;
|
||||
buffer.mId = id;
|
||||
buffer.mBuffer = mState->mGridBufferMap[id];
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
const nanovdb::HostBuffer& getBuffer(uint64_t id) const
|
||||
{
|
||||
auto it = mState->mGridBufferMap.find(id);
|
||||
assert(it != mState->mGridBufferMap.end());
|
||||
return *it->second.get();
|
||||
}
|
||||
|
||||
nanovdb::HostBuffer& getBuffer(uint64_t id)
|
||||
{
|
||||
auto it = mState->mGridBufferMap.find(id);
|
||||
assert(it != mState->mGridBufferMap.end());
|
||||
return *it->second.get();
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// this parent scope allocator contains a std::map of buffers.
|
||||
// this allocator also acts as a manager for the grid resources,
|
||||
// and allows multiple GridHandles to point to the same data!
|
||||
MapPoolBuffer bufferContext;
|
||||
bufferContext.initialize();
|
||||
|
||||
nanovdb::GridHandle<MapPoolBuffer> anotherHdl;
|
||||
|
||||
try {
|
||||
std::vector<nanovdb::GridHandle<MapPoolBuffer>> gridHdls;
|
||||
|
||||
// create two grids...
|
||||
gridHdls.push_back(nanovdb::createLevelSetSphere(100.0f, nanovdb::Vec3f(-20, 0, 0), 1.0, 3.0, nanovdb::Vec3R(0), "spheref", nanovdb::StatsMode::BBox, nanovdb::ChecksumMode::Partial, -1.0f, false, bufferContext));
|
||||
gridHdls.push_back(nanovdb::createLevelSetSphere(100.0, nanovdb::Vec3d( 20, 0, 0), 1.0, 3.0, nanovdb::Vec3R(0), "sphered", nanovdb::StatsMode::BBox, nanovdb::ChecksumMode::Partial, -1.0f, false, bufferContext));
|
||||
|
||||
// share grid[0]'s buffer into a parent-scope handle to prevent deletion.
|
||||
anotherHdl = nanovdb::GridHandle<MapPoolBuffer>(bufferContext.copy(gridHdls[0].buffer().mId));
|
||||
|
||||
// use the gridAllocator to dump the buffers.
|
||||
for (auto& it : bufferContext.getGridKeys()) {
|
||||
// create a temporary GridHandle so we can parse the GridMetaData.
|
||||
auto hdl = nanovdb::GridHandle<MapPoolBuffer>(bufferContext.copy(it));
|
||||
printf("key = %d, buffer = %p, gridName = %s\n", (int)hdl.buffer().mId, hdl.data(), hdl.gridMetaData()->shortGridName());
|
||||
}
|
||||
|
||||
// Get a (raw) pointer to the NanoVDB grid form the GridManager.
|
||||
auto* dstGrid = gridHdls[0].grid<float>();
|
||||
if (!dstGrid)
|
||||
throw std::runtime_error("GridHandle does not contain a grid with value type float");
|
||||
|
||||
// Access and print out a single value (inside the level set) from both grids
|
||||
printf("NanoVDB cpu: %4.2f\n", dstGrid->tree().getValue(nanovdb::Coord(99, 0, 0)));
|
||||
|
||||
// Write the NanoVDB grids to file and throw if writing fails
|
||||
nanovdb::io::writeGrids<MapPoolBuffer, std::vector>("data/spheres.nvdb", gridHdls, nanovdb::io::Codec::NONE, 2);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
|
||||
// use the gridAllocator to dump the buffers.
|
||||
for (auto& it : bufferContext.getGridKeys()) {
|
||||
// create a temporary GridHandle so we can parse the GridMetaData.
|
||||
auto hdl = nanovdb::GridHandle<MapPoolBuffer>(bufferContext.copy(it));
|
||||
printf("key = %d, buffer = %p, gridName = %s\n", (int)hdl.buffer().mId, hdl.data(), hdl.gridMetaData()->shortGridName());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @brief This examples demonstrates how values in a NanpVDB grid can be
|
||||
/// modified on the device. It depends on NanoVDB and CUDA thrust.
|
||||
|
||||
#include <thrust/iterator/counting_iterator.h>
|
||||
#include <thrust/for_each.h>
|
||||
|
||||
#include <nanovdb/util/Primitives.h>
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
|
||||
void scaleActiveVoxels(nanovdb::FloatGrid *grid_d, uint64_t leafCount, float scale)
|
||||
{
|
||||
auto kernel = [grid_d, scale] __device__ (const uint64_t n) {
|
||||
auto *leaf_d = grid_d->tree().getFirstNode<0>() + (n >> 9);// this only works if grid->isSequential<0>() == true
|
||||
const int i = n & 511;
|
||||
const float v = scale * leaf_d->getValue(i);
|
||||
if (leaf_d->isActive(i)) {
|
||||
leaf_d->setValueOnly(i, v);// only possible execution divergence
|
||||
}
|
||||
};
|
||||
|
||||
thrust::counting_iterator<uint64_t, thrust::device_system_tag> iter(0);
|
||||
thrust::for_each(iter, iter + 512*leafCount, kernel);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
// Create an NanoVDB grid of a sphere at the origin with radius 100 and voxel size 1.
|
||||
auto handle = nanovdb::createLevelSetSphere<float, float, nanovdb::CudaDeviceBuffer>(100.0f);
|
||||
using GridT = nanovdb::FloatGrid;
|
||||
|
||||
handle.deviceUpload(0, false); // Copy the NanoVDB grid to the GPU asynchronously
|
||||
|
||||
const GridT* grid = handle.grid<float>(); // get a (raw) const pointer to a NanoVDB grid of value type float on the CPU
|
||||
GridT* deviceGrid = handle.deviceGrid<float>(); // get a (raw) pointer to a NanoVDB grid of value type float on the GPU
|
||||
|
||||
if (!deviceGrid || !grid) {
|
||||
throw std::runtime_error("GridHandle did not contain a grid with value type float");
|
||||
}
|
||||
if (!grid->isSequential<0>()) {
|
||||
throw std::runtime_error("Grid does not support sequential access to leaf nodes!");
|
||||
}
|
||||
|
||||
std::cout << "Value before scaling = " << grid->tree().getValue(nanovdb::Coord(101,0,0)) << std::endl;
|
||||
|
||||
scaleActiveVoxels(deviceGrid, grid->tree().nodeCount(0), 2.0f);
|
||||
|
||||
handle.deviceDownload(0, true); // Copy the NanoVDB grid to the CPU synchronously
|
||||
|
||||
std::cout << "Value after scaling = " << grid->tree().getValue(nanovdb::Coord(101,0,0)) << std::endl;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <openvdb/tools/LevelSetSphere.h> // replace with your own dependencies for generating the OpenVDB grid
|
||||
#include <nanovdb/util/OpenToNanoVDB.h> // converter from OpenVDB to NanoVDB (includes NanoVDB.h and GridManager.h)
|
||||
#include <nanovdb/util/IO.h>
|
||||
|
||||
/// @brief Convert an openvdb level set sphere into a nanovdb, access a single value in both grids, and save NanoVDB to file.
|
||||
///
|
||||
/// @note This example depends on both OpenVDB and NanoVDB.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
// Create an OpenVDB grid of a sphere at the origin with radius 100 and voxel size 1.
|
||||
auto srcGrid = openvdb::tools::createLevelSetSphere<openvdb::FloatGrid>(100.0f, openvdb::Vec3f(0.0f), 1.0f);
|
||||
|
||||
auto handle = nanovdb::openToNanoVDB(*srcGrid); // Convert from OpenVDB to NanoVDB and return a shared pointer to a GridHandle.
|
||||
|
||||
auto* dstGrid = handle.grid<float>(); // Get a (raw) pointer to the NanoVDB grid form the GridManager.
|
||||
if (!dstGrid)
|
||||
throw std::runtime_error("GridHandle does not contain a grid with value type float");
|
||||
|
||||
// Access and print out a single value (inside the level set) from both grids
|
||||
printf("OpenVDB cpu: %4.2f\n", srcGrid->tree().getValue(openvdb::Coord(99, 0, 0)));
|
||||
printf("NanoVDB cpu: %4.2f\n", dstGrid->tree().getValue(nanovdb::Coord(99, 0, 0)));
|
||||
|
||||
nanovdb::io::writeGrid("data/sphere2.nvdb", handle); // Write the NanoVDB grid to file and throw if writing fails
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <openvdb/tools/LevelSetSphere.h> // replace with your own dependencies for generating the OpenVDB grid
|
||||
#include <nanovdb/util/OpenToNanoVDB.h> // converter from OpenVDB to NanoVDB (includes NanoVDB.h and GridManager.h)
|
||||
#include <nanovdb/util/IO.h>
|
||||
|
||||
// Convert an openvdb level set sphere into a nanovdb, use accessors to print out multiple values from both
|
||||
// grids and save the NanoVDB grid to file.
|
||||
// Note, main depends on BOTH OpenVDB and NanoVDB.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
// Create an OpenVDB grid (here a level set surface but replace this with your own code)
|
||||
auto srcGrid = openvdb::tools::createLevelSetSphere<openvdb::FloatGrid>(100.0f, openvdb::Vec3f(0.0f), 1.0f);
|
||||
|
||||
// Convert the OpenVDB grid, srcGrid, into a NanoVDB grid handle.
|
||||
auto handle = nanovdb::openToNanoVDB(*srcGrid);
|
||||
|
||||
// Define a (raw) pointer to the NanoVDB grid on the host. Note we match the value type of the srcGrid!
|
||||
auto* dstGrid = handle.grid<float>();
|
||||
|
||||
if (!dstGrid)
|
||||
throw std::runtime_error("GridHandle does not contain a grid with value type float");
|
||||
|
||||
// Get accessors for the two grids. Note that accessors only accelerate repeated access!
|
||||
auto dstAcc = dstGrid->getAccessor();
|
||||
auto srcAcc = srcGrid->getAccessor();
|
||||
|
||||
// Access and print out a cross-section of the narrow-band level set from the two grids
|
||||
for (int i = 97; i < 104; ++i) {
|
||||
printf("(%3i,0,0) OpenVDB cpu: % -4.2f, NanoVDB cpu: % -4.2f\n", i, srcAcc.getValue(openvdb::Coord(i, 0, 0)), dstAcc.getValue(nanovdb::Coord(i, 0, 0)));
|
||||
}
|
||||
|
||||
nanovdb::io::writeGrid("data/sphere.nvdb", handle); // Write the NanoVDB grid to file and throw if writing fails
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <openvdb/tools/LevelSetSphere.h> // replace with your own dependencies for generating the OpenVDB grid
|
||||
#include <nanovdb/util/OpenToNanoVDB.h> // converter from OpenVDB to NanoVDB (includes NanoVDB.h and GridManager.h)
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
|
||||
extern "C" void launch_kernels(const nanovdb::NanoGrid<float>*,
|
||||
const nanovdb::NanoGrid<float>*,
|
||||
cudaStream_t stream);
|
||||
|
||||
/// @brief This examples depends on OpenVDB, NanoVDB and CUDA.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
// Create an OpenVDB grid of a sphere at the origin with radius 100 and voxel size 1.
|
||||
auto srcGrid = openvdb::tools::createLevelSetSphere<openvdb::FloatGrid>(100.0f, openvdb::Vec3f(0.0f), 1.0f);
|
||||
|
||||
// Converts the OpenVDB to NanoVDB and returns a GridHandle that uses CUDA for memory management.
|
||||
auto handle = nanovdb::openToNanoVDB<nanovdb::CudaDeviceBuffer>(*srcGrid);
|
||||
|
||||
cudaStream_t stream; // Create a CUDA stream to allow for asynchronous copy of pinned CUDA memory.
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
handle.deviceUpload(stream, false); // Copy the NanoVDB grid to the GPU asynchronously
|
||||
|
||||
auto* grid = handle.grid<float>(); // get a (raw) pointer to a NanoVDB grid of value type float on the CPU
|
||||
auto* deviceGrid = handle.deviceGrid<float>(); // get a (raw) pointer to a NanoVDB grid of value type float on the GPU
|
||||
|
||||
if (!deviceGrid || !grid)
|
||||
throw std::runtime_error("GridHandle did not contain a grid with value type float");
|
||||
|
||||
launch_kernels(deviceGrid, grid, stream); // Call a host method to print a grid value on both the CPU and GPU
|
||||
|
||||
cudaStreamDestroy(stream); // Destroy the CUDA stream
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/NanoVDB.h> // this defined the core tree data structure of NanoVDB accessable on both the host and device
|
||||
#include <stdio.h> // for printf
|
||||
|
||||
// This is called by the host only
|
||||
void cpu_kernel(const nanovdb::NanoGrid<float>* cpuGrid)
|
||||
{
|
||||
printf("NanoVDB cpu; %4.2f\n", cpuGrid->tree().getValue(nanovdb::Coord(99, 0, 0)));
|
||||
}
|
||||
|
||||
// This is called by the device only
|
||||
__global__ void gpu_kernel(const nanovdb::NanoGrid<float>* deviceGrid)
|
||||
{
|
||||
printf("NanoVDB gpu: %4.2f\n", deviceGrid->tree().getValue(nanovdb::Coord(99, 0, 0)));
|
||||
}
|
||||
|
||||
// This is called by the client code on the host
|
||||
extern "C" void launch_kernels(const nanovdb::NanoGrid<float>* deviceGrid,
|
||||
const nanovdb::NanoGrid<float>* cpuGrid,
|
||||
cudaStream_t stream)
|
||||
{
|
||||
gpu_kernel<<<1, 1, 0, stream>>>(deviceGrid); // Launch the device kernel asynchronously
|
||||
|
||||
cpu_kernel(cpuGrid); // Launch the host "kernel" (synchronously)
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <nanovdb/NanoVDB.h>
|
||||
#include "ComputePrimitives.h"
|
||||
|
||||
inline __hostdev__ uint32_t CompactBy1(uint32_t x)
|
||||
{
|
||||
x &= 0x55555555;
|
||||
x = (x ^ (x >> 1)) & 0x33333333;
|
||||
x = (x ^ (x >> 2)) & 0x0f0f0f0f;
|
||||
x = (x ^ (x >> 4)) & 0x00ff00ff;
|
||||
x = (x ^ (x >> 8)) & 0x0000ffff;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline __hostdev__ uint32_t SeparateBy1(uint32_t x)
|
||||
{
|
||||
x &= 0x0000ffff;
|
||||
x = (x ^ (x << 8)) & 0x00ff00ff;
|
||||
x = (x ^ (x << 4)) & 0x0f0f0f0f;
|
||||
x = (x ^ (x << 2)) & 0x33333333;
|
||||
x = (x ^ (x << 1)) & 0x55555555;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline __hostdev__ void mortonDecode(uint32_t code, uint32_t& x, uint32_t& y)
|
||||
{
|
||||
x = CompactBy1(code);
|
||||
y = CompactBy1(code >> 1);
|
||||
}
|
||||
|
||||
inline __hostdev__ void mortonEncode(uint32_t& code, uint32_t x, uint32_t y)
|
||||
{
|
||||
code = SeparateBy1(x) | (SeparateBy1(y) << 1);
|
||||
}
|
||||
|
||||
template<typename RenderFn, typename GridT>
|
||||
inline float renderImage(bool useCuda, const RenderFn renderOp, int width, int height, float* image, const GridT* grid)
|
||||
{
|
||||
using ClockT = std::chrono::high_resolution_clock;
|
||||
auto t0 = ClockT::now();
|
||||
|
||||
computeForEach(
|
||||
useCuda, width * height, 512, __FILE__, __LINE__, [renderOp, image, grid] __hostdev__(int start, int end) {
|
||||
renderOp(start, end, image, grid);
|
||||
});
|
||||
computeSync(useCuda, __FILE__, __LINE__);
|
||||
|
||||
auto t1 = ClockT::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count() / 1000.f;
|
||||
return duration;
|
||||
}
|
||||
|
||||
inline void saveImage(const std::string& filename, int width, int height, const float* image)
|
||||
{
|
||||
const auto isLittleEndian = []() -> bool {
|
||||
static int x = 1;
|
||||
static bool result = reinterpret_cast<uint8_t*>(&x)[0] == 1;
|
||||
return result;
|
||||
};
|
||||
|
||||
float scale = 1.0f;
|
||||
if (isLittleEndian())
|
||||
scale = -scale;
|
||||
|
||||
std::fstream fs(filename, std::ios::out | std::ios::binary);
|
||||
if (!fs.is_open()) {
|
||||
throw std::runtime_error("Unable to open file: " + filename);
|
||||
}
|
||||
|
||||
fs << "Pf\n"
|
||||
<< width << "\n"
|
||||
<< height << "\n"
|
||||
<< scale << "\n";
|
||||
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
float r = image[i];
|
||||
fs.write((char*)&r, sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Vec3T>
|
||||
struct RayGenOp
|
||||
{
|
||||
float mWBBoxDimZ;
|
||||
Vec3T mWBBoxCenter;
|
||||
|
||||
inline RayGenOp(float wBBoxDimZ, Vec3T wBBoxCenter)
|
||||
: mWBBoxDimZ(wBBoxDimZ)
|
||||
, mWBBoxCenter(wBBoxCenter)
|
||||
{
|
||||
}
|
||||
|
||||
inline __hostdev__ void operator()(int i, int w, int h, Vec3T& outOrigin, Vec3T& outDir) const
|
||||
{
|
||||
// perspective camera along Z-axis...
|
||||
uint32_t x, y;
|
||||
#if 0
|
||||
mortonDecode(i, x, y);
|
||||
#else
|
||||
x = i % w;
|
||||
y = i / w;
|
||||
#endif
|
||||
const float fov = 45.f;
|
||||
const float u = (float(x) + 0.5f) / w;
|
||||
const float v = (float(y) + 0.5f) / h;
|
||||
const float aspect = w / float(h);
|
||||
const float Px = (2.f * u - 1.f) * tanf(fov / 2 * 3.14159265358979323846f / 180.f) * aspect;
|
||||
const float Py = (2.f * v - 1.f) * tanf(fov / 2 * 3.14159265358979323846f / 180.f);
|
||||
const Vec3T origin = mWBBoxCenter + Vec3T(0, 0, mWBBoxDimZ);
|
||||
Vec3T dir(Px, Py, -1.f);
|
||||
dir.normalize();
|
||||
outOrigin = origin;
|
||||
outDir = dir;
|
||||
}
|
||||
};
|
||||
|
||||
struct CompositeOp
|
||||
{
|
||||
inline __hostdev__ void operator()(float* outImage, int i, int w, int h, float value, float alpha) const
|
||||
{
|
||||
uint32_t x, y;
|
||||
int offset;
|
||||
#if 0
|
||||
mortonDecode(i, x, y);
|
||||
offset = x + y * w;
|
||||
#else
|
||||
x = i % w;
|
||||
y = i / w;
|
||||
offset = i;
|
||||
#endif
|
||||
|
||||
// checkerboard background...
|
||||
const int mask = 1 << 7;
|
||||
const float bg = ((x & mask) ^ (y & mask)) ? 1.0f : 0.5f;
|
||||
outImage[offset] = alpha * value + (1.0f - alpha) * bg;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/Primitives.h>
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
#else
|
||||
using BufferT = nanovdb::HostBuffer;
|
||||
#endif
|
||||
|
||||
extern void runNanoVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int width, int height, BufferT& imageBuffer);
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
extern void runOpenVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int width, int height, BufferT& imageBuffer);
|
||||
#endif
|
||||
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
try {
|
||||
nanovdb::GridHandle<BufferT> handle;
|
||||
if (ac > 1) {
|
||||
handle = nanovdb::io::readGrid<BufferT>(av[1]);
|
||||
std::cout << "Loaded NanoVDB grid[" << handle.gridMetaData()->shortGridName() << "]...\n";
|
||||
} else {
|
||||
handle = nanovdb::createFogVolumeSphere<float, float, BufferT>(100.0f, nanovdb::Vec3f(-20, 0, 0), 1.0, 3.0, nanovdb::Vec3d(0), "sphere");
|
||||
}
|
||||
|
||||
if (handle.gridMetaData()->isFogVolume() == false) {
|
||||
throw std::runtime_error("Grid must be a fog volume");
|
||||
}
|
||||
|
||||
const int numIterations = 50;
|
||||
|
||||
const int width = 1024;
|
||||
const int height = 1024;
|
||||
BufferT imageBuffer;
|
||||
imageBuffer.init(width * height * sizeof(float));
|
||||
|
||||
runNanoVDB(handle, numIterations, width, height, imageBuffer);
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
runOpenVDB(handle, numIterations, width, height, imageBuffer);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
#include <nanovdb/util/Ray.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
#else
|
||||
using BufferT = nanovdb::HostBuffer;
|
||||
#endif
|
||||
|
||||
void runNanoVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int width, int height, BufferT& imageBuffer)
|
||||
{
|
||||
using GridT = nanovdb::FloatGrid;
|
||||
using CoordT = nanovdb::Coord;
|
||||
using RealT = float;
|
||||
using Vec3T = nanovdb::Vec3<RealT>;
|
||||
using RayT = nanovdb::Ray<RealT>;
|
||||
|
||||
auto* h_grid = handle.grid<float>();
|
||||
if (!h_grid)
|
||||
throw std::runtime_error("GridHandle does not contain a valid host grid");
|
||||
|
||||
float* h_outImage = reinterpret_cast<float*>(imageBuffer.data());
|
||||
|
||||
float wBBoxDimZ = (float)h_grid->worldBBox().dim()[2] * 2;
|
||||
Vec3T wBBoxCenter = Vec3T(h_grid->worldBBox().min() + h_grid->worldBBox().dim() * 0.5f);
|
||||
nanovdb::CoordBBox treeIndexBbox = h_grid->tree().bbox();
|
||||
std::cout << "Bounds: "
|
||||
<< "[" << treeIndexBbox.min()[0] << "," << treeIndexBbox.min()[1] << "," << treeIndexBbox.min()[2] << "] -> ["
|
||||
<< treeIndexBbox.max()[0] << "," << treeIndexBbox.max()[1] << "," << treeIndexBbox.max()[2] << "]" << std::endl;
|
||||
|
||||
RayGenOp<Vec3T> rayGenOp(wBBoxDimZ, wBBoxCenter);
|
||||
CompositeOp compositeOp;
|
||||
|
||||
auto renderOp = [width, height, rayGenOp, compositeOp, treeIndexBbox] __hostdev__(int start, int end, float* image, const GridT* grid) {
|
||||
// get an accessor.
|
||||
auto acc = grid->tree().getAccessor();
|
||||
|
||||
for (int i = start; i < end; ++i) {
|
||||
Vec3T rayEye;
|
||||
Vec3T rayDir;
|
||||
rayGenOp(i, width, height, rayEye, rayDir);
|
||||
// generate ray.
|
||||
RayT wRay(rayEye, rayDir);
|
||||
// transform the ray to the grid's index-space.
|
||||
RayT iRay = wRay.worldToIndexF(*grid);
|
||||
// clip to bounds.
|
||||
if (iRay.clip(treeIndexBbox) == false) {
|
||||
compositeOp(image, i, width, height, 0.0f, 0.0f);
|
||||
return;
|
||||
}
|
||||
// integrate...
|
||||
const float dt = 0.5f;
|
||||
float transmittance = 1.0f;
|
||||
for (float t = iRay.t0(); t < iRay.t1(); t += dt) {
|
||||
float sigma = acc.getValue(CoordT::Floor(iRay(t))) * 0.1f;
|
||||
transmittance *= 1.0f - sigma * dt;
|
||||
}
|
||||
// write transmittance.
|
||||
compositeOp(image, i, width, height, 0.0f, 1.0f - transmittance);
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
float durationAvg = 0;
|
||||
for (int i = 0; i < numIterations; ++i) {
|
||||
float duration = renderImage(false, renderOp, width, height, h_outImage, h_grid);
|
||||
//std::cout << "Duration(NanoVDB-Host) = " << duration << " ms" << std::endl;
|
||||
durationAvg += duration;
|
||||
}
|
||||
durationAvg /= numIterations;
|
||||
std::cout << "Average Duration(NanoVDB-Host) = " << durationAvg << " ms" << std::endl;
|
||||
|
||||
saveImage("raytrace_fog_volume-nanovdb-host.pfm", width, height, (float*)imageBuffer.data());
|
||||
}
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
handle.deviceUpload();
|
||||
|
||||
auto* d_grid = handle.deviceGrid<float>();
|
||||
if (!d_grid)
|
||||
throw std::runtime_error("GridHandle does not contain a valid device grid");
|
||||
|
||||
imageBuffer.deviceUpload();
|
||||
float* d_outImage = reinterpret_cast<float*>(imageBuffer.deviceData());
|
||||
|
||||
{
|
||||
float durationAvg = 0;
|
||||
for (int i = 0; i < numIterations; ++i) {
|
||||
float duration = renderImage(true, renderOp, width, height, d_outImage, d_grid);
|
||||
//std::cout << "Duration(NanoVDB-Cuda) = " << duration << " ms" << std::endl;
|
||||
durationAvg += duration;
|
||||
}
|
||||
durationAvg /= numIterations;
|
||||
std::cout << "Average Duration(NanoVDB-Cuda) = " << durationAvg << " ms" << std::endl;
|
||||
|
||||
imageBuffer.deviceDownload();
|
||||
saveImage("raytrace_fog_volume-nanovdb-cuda.pfm", width, height, (float*)imageBuffer.data());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
|
||||
#include <openvdb/openvdb.h>
|
||||
#include <openvdb/math/Ray.h>
|
||||
#include <openvdb/tools/LevelSetSphere.h>
|
||||
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
#include <nanovdb/util/NanoToOpenVDB.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
#else
|
||||
using BufferT = nanovdb::HostBuffer;
|
||||
#endif
|
||||
|
||||
void runOpenVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int width, int height, BufferT& imageBuffer)
|
||||
{
|
||||
using GridT = openvdb::FloatGrid;
|
||||
using CoordT = openvdb::Coord;
|
||||
using RealT = float;
|
||||
using Vec3T = openvdb::math::Vec3<RealT>;
|
||||
using RayT = openvdb::math::Ray<RealT>;
|
||||
|
||||
auto srcGrid = nanovdb::nanoToOpenVDB(handle);
|
||||
std::cout << "Exporting to OpenVDB grid[" << srcGrid->getName() << "]...\n";
|
||||
|
||||
auto h_grid = (GridT*)srcGrid.get();
|
||||
|
||||
float* h_outImage = reinterpret_cast<float*>(imageBuffer.data());
|
||||
|
||||
auto indexBBox = h_grid->evalActiveVoxelBoundingBox();
|
||||
auto gridXform = h_grid->transformPtr();
|
||||
auto worldBBox = gridXform->indexToWorld(indexBBox);
|
||||
float wBBoxDimZ = (float)worldBBox.extents()[2] * 2;
|
||||
Vec3T wBBoxCenter = Vec3T(worldBBox.min() + worldBBox.extents() * 0.5f);
|
||||
|
||||
RayGenOp<Vec3T> rayGenOp(wBBoxDimZ, wBBoxCenter);
|
||||
CompositeOp compositeOp;
|
||||
|
||||
openvdb::CoordBBox treeIndexBbox;
|
||||
treeIndexBbox = h_grid->evalActiveVoxelBoundingBox();
|
||||
std::cout << "Bounds: " << treeIndexBbox << std::endl;
|
||||
|
||||
auto renderOp = [width, height, rayGenOp, compositeOp, treeIndexBbox] __hostdev__(int start, int end, float* image, const GridT* grid) {
|
||||
// get an accessor.
|
||||
auto acc = grid->getAccessor();
|
||||
|
||||
for (int i = start; i < end; ++i) {
|
||||
Vec3T rayEye;
|
||||
Vec3T rayDir;
|
||||
rayGenOp(i, width, height, rayEye, rayDir);
|
||||
// generate ray.
|
||||
RayT wRay(rayEye, rayDir);
|
||||
// transform the ray to the grid's index-space.
|
||||
RayT iRay = wRay.worldToIndex(*grid);
|
||||
// clip to bounds.
|
||||
if (iRay.clip(treeIndexBbox) == false) {
|
||||
compositeOp(image, i, width, height, 0.0f, 0.0f);
|
||||
return;
|
||||
}
|
||||
// integrate...
|
||||
const float dt = 0.5f;
|
||||
float transmittance = 1.0f;
|
||||
for (float t = iRay.t0(); t < iRay.t1(); t += dt) {
|
||||
float sigma = acc.getValue(CoordT::floor(iRay(t))) * 0.1f;
|
||||
transmittance *= 1.0f - sigma * dt;
|
||||
}
|
||||
// write transmittance.
|
||||
compositeOp(image, i, width, height, 0.0f, 1.0f - transmittance);
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
float durationAvg = 0;
|
||||
for (int i = 0; i < numIterations; ++i) {
|
||||
float duration = renderImage(false, renderOp, width, height, h_outImage, h_grid);
|
||||
//std::cout << "Duration(OpenVDB-Host) = " << duration << " ms" << std::endl;
|
||||
durationAvg += duration;
|
||||
}
|
||||
durationAvg /= numIterations;
|
||||
std::cout << "Average Duration(OpenVDB-Host) = " << durationAvg << " ms" << std::endl;
|
||||
|
||||
saveImage("raytrace_fog_volume-openvdb-host.pfm", width, height, (float*)imageBuffer.data());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,144 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <nanovdb/NanoVDB.h>
|
||||
#include "ComputePrimitives.h"
|
||||
|
||||
inline __hostdev__ uint32_t CompactBy1(uint32_t x)
|
||||
{
|
||||
x &= 0x55555555;
|
||||
x = (x ^ (x >> 1)) & 0x33333333;
|
||||
x = (x ^ (x >> 2)) & 0x0f0f0f0f;
|
||||
x = (x ^ (x >> 4)) & 0x00ff00ff;
|
||||
x = (x ^ (x >> 8)) & 0x0000ffff;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline __hostdev__ uint32_t SeparateBy1(uint32_t x)
|
||||
{
|
||||
x &= 0x0000ffff;
|
||||
x = (x ^ (x << 8)) & 0x00ff00ff;
|
||||
x = (x ^ (x << 4)) & 0x0f0f0f0f;
|
||||
x = (x ^ (x << 2)) & 0x33333333;
|
||||
x = (x ^ (x << 1)) & 0x55555555;
|
||||
return x;
|
||||
}
|
||||
|
||||
inline __hostdev__ void mortonDecode(uint32_t code, uint32_t& x, uint32_t& y)
|
||||
{
|
||||
x = CompactBy1(code);
|
||||
y = CompactBy1(code >> 1);
|
||||
}
|
||||
|
||||
inline __hostdev__ void mortonEncode(uint32_t& code, uint32_t x, uint32_t y)
|
||||
{
|
||||
code = SeparateBy1(x) | (SeparateBy1(y) << 1);
|
||||
}
|
||||
|
||||
template<typename RenderFn, typename GridT>
|
||||
inline float renderImage(bool useCuda, const RenderFn renderOp, int width, int height, float* image, const GridT* grid)
|
||||
{
|
||||
using ClockT = std::chrono::high_resolution_clock;
|
||||
auto t0 = ClockT::now();
|
||||
|
||||
computeForEach(
|
||||
useCuda, width * height, 512, __FILE__, __LINE__, [renderOp, image, grid] __hostdev__(int start, int end) {
|
||||
renderOp(start, end, image, grid);
|
||||
});
|
||||
computeSync(useCuda, __FILE__, __LINE__);
|
||||
|
||||
auto t1 = ClockT::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count() / 1000.f;
|
||||
return duration;
|
||||
}
|
||||
|
||||
inline void saveImage(const std::string& filename, int width, int height, const float* image)
|
||||
{
|
||||
const auto isLittleEndian = []() -> bool {
|
||||
static int x = 1;
|
||||
static bool result = reinterpret_cast<uint8_t*>(&x)[0] == 1;
|
||||
return result;
|
||||
};
|
||||
|
||||
float scale = 1.0f;
|
||||
if (isLittleEndian())
|
||||
scale = -scale;
|
||||
|
||||
std::fstream fs(filename, std::ios::out | std::ios::binary);
|
||||
if (!fs.is_open()) {
|
||||
throw std::runtime_error("Unable to open file: " + filename);
|
||||
}
|
||||
|
||||
fs << "Pf\n"
|
||||
<< width << "\n"
|
||||
<< height << "\n"
|
||||
<< scale << "\n";
|
||||
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
float r = image[i];
|
||||
fs.write((char*)&r, sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Vec3T>
|
||||
struct RayGenOp
|
||||
{
|
||||
float mWBBoxDimZ;
|
||||
Vec3T mWBBoxCenter;
|
||||
|
||||
inline RayGenOp(float wBBoxDimZ, Vec3T wBBoxCenter)
|
||||
: mWBBoxDimZ(wBBoxDimZ)
|
||||
, mWBBoxCenter(wBBoxCenter)
|
||||
{
|
||||
}
|
||||
|
||||
inline __hostdev__ void operator()(int i, int w, int h, Vec3T& outOrigin, Vec3T& outDir) const
|
||||
{
|
||||
// perspective camera along Z-axis...
|
||||
uint32_t x, y;
|
||||
#if 0
|
||||
mortonDecode(i, x, y);
|
||||
#else
|
||||
x = i % w;
|
||||
y = i / w;
|
||||
#endif
|
||||
const float fov = 45.f;
|
||||
const float u = (float(x) + 0.5f) / w;
|
||||
const float v = (float(y) + 0.5f) / h;
|
||||
const float aspect = w / float(h);
|
||||
const float Px = (2.f * u - 1.f) * tanf(fov / 2 * 3.14159265358979323846f / 180.f) * aspect;
|
||||
const float Py = (2.f * v - 1.f) * tanf(fov / 2 * 3.14159265358979323846f / 180.f);
|
||||
const Vec3T origin = mWBBoxCenter + Vec3T(0, 0, mWBBoxDimZ);
|
||||
Vec3T dir(Px, Py, -1.f);
|
||||
dir.normalize();
|
||||
outOrigin = origin;
|
||||
outDir = dir;
|
||||
}
|
||||
};
|
||||
|
||||
struct CompositeOp
|
||||
{
|
||||
inline __hostdev__ void operator()(float* outImage, int i, int w, int h, float value, float alpha) const
|
||||
{
|
||||
uint32_t x, y;
|
||||
int offset;
|
||||
#if 0
|
||||
mortonDecode(i, x, y);
|
||||
offset = x + y * w;
|
||||
#else
|
||||
x = i % w;
|
||||
y = i / w;
|
||||
offset = i;
|
||||
#endif
|
||||
|
||||
// checkerboard background...
|
||||
const int mask = 1 << 7;
|
||||
const float bg = ((x & mask) ^ (y & mask)) ? 1.0f : 0.5f;
|
||||
outImage[offset] = alpha * value + (1.0f - alpha) * bg;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/Primitives.h>
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
#else
|
||||
using BufferT = nanovdb::HostBuffer;
|
||||
#endif
|
||||
|
||||
extern void runNanoVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int width, int height, BufferT& imageBuffer);
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
extern void runOpenVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int width, int height, BufferT& imageBuffer);
|
||||
#endif
|
||||
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
try {
|
||||
nanovdb::GridHandle<BufferT> handle;
|
||||
if (ac > 1) {
|
||||
handle = nanovdb::io::readGrid<BufferT>(av[1]);
|
||||
std::cout << "Loaded NanoVDB grid[" << handle.gridMetaData()->shortGridName() << "]...\n";
|
||||
} else {
|
||||
handle = nanovdb::createLevelSetSphere<float, float, BufferT>(100.0f, nanovdb::Vec3f(-20, 0, 0), 1.0, 3.0, nanovdb::Vec3d(0), "sphere");
|
||||
}
|
||||
|
||||
if (handle.gridMetaData()->isLevelSet() == false) {
|
||||
throw std::runtime_error("Grid must be a level set");
|
||||
}
|
||||
|
||||
const int numIterations = 50;
|
||||
|
||||
const int width = 1024;
|
||||
const int height = 1024;
|
||||
BufferT imageBuffer;
|
||||
imageBuffer.init(width * height * sizeof(float));
|
||||
|
||||
runNanoVDB(handle, numIterations, width, height, imageBuffer);
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
runOpenVDB(handle, numIterations, width, height, imageBuffer);
|
||||
#endif
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
|
||||
#include <nanovdb/util/IO.h>
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
#include <nanovdb/util/Ray.h>
|
||||
#include <nanovdb/util/HDDA.h>
|
||||
#include <nanovdb/util/GridBuilder.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
#else
|
||||
using BufferT = nanovdb::HostBuffer;
|
||||
#endif
|
||||
|
||||
void runNanoVDB(nanovdb::GridHandle<BufferT>& handle, int numIterations, int width, int height, BufferT& imageBuffer)
|
||||
{
|
||||
using GridT = nanovdb::FloatGrid;
|
||||
using CoordT = nanovdb::Coord;
|
||||
using RealT = float;
|
||||
using Vec3T = nanovdb::Vec3<RealT>;
|
||||
using RayT = nanovdb::Ray<RealT>;
|
||||
|
||||
auto* h_grid = handle.grid<float>();
|
||||
if (!h_grid)
|
||||
throw std::runtime_error("GridHandle does not contain a valid host grid");
|
||||
|
||||
float* h_outImage = reinterpret_cast<float*>(imageBuffer.data());
|
||||
|
||||
float wBBoxDimZ = (float)h_grid->worldBBox().dim()[2] * 2;
|
||||
Vec3T wBBoxCenter = Vec3T(h_grid->worldBBox().min() + h_grid->worldBBox().dim() * 0.5f);
|
||||
nanovdb::CoordBBox treeIndexBbox = h_grid->tree().bbox();
|
||||
std::cout << "Bounds: "
|
||||
<< "[" << treeIndexBbox.min()[0] << "," << treeIndexBbox.min()[1] << "," << treeIndexBbox.min()[2] << "] -> ["
|
||||
<< treeIndexBbox.max()[0] << "," << treeIndexBbox.max()[1] << "," << treeIndexBbox.max()[2] << "]" << std::endl;
|
||||
|
||||
RayGenOp<Vec3T> rayGenOp(wBBoxDimZ, wBBoxCenter);
|
||||
CompositeOp compositeOp;
|
||||
|
||||
auto renderOp = [width, height, rayGenOp, compositeOp, treeIndexBbox, wBBoxDimZ] __hostdev__(int start, int end, float* image, const GridT* grid) {
|
||||
// get an accessor.
|
||||
auto acc = grid->tree().getAccessor();
|
||||
|
||||
for (int i = start; i < end; ++i) {
|
||||
Vec3T rayEye;
|
||||
Vec3T rayDir;
|
||||
rayGenOp(i, width, height, rayEye, rayDir);
|
||||
// generate ray.
|
||||
RayT wRay(rayEye, rayDir);
|
||||
// transform the ray to the grid's index-space.
|
||||
RayT iRay = wRay.worldToIndexF(*grid);
|
||||
// intersect...
|
||||
float t0;
|
||||
CoordT ijk;
|
||||
float v;
|
||||
if (nanovdb::ZeroCrossing(iRay, acc, ijk, v, t0)) {
|
||||
// write distance to surface. (we assume it is a uniform voxel)
|
||||
float wT0 = t0 * float(grid->voxelSize()[0]);
|
||||
compositeOp(image, i, width, height, wT0 / (wBBoxDimZ * 2), 1.0f);
|
||||
} else {
|
||||
// write background value.
|
||||
compositeOp(image, i, width, height, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
float durationAvg = 0;
|
||||
for (int i = 0; i < numIterations; ++i) {
|
||||
float duration = renderImage(false, renderOp, width, height, h_outImage, h_grid);
|
||||
//std::cout << "Duration(NanoVDB-Host) = " << duration << " ms" << std::endl;
|
||||
durationAvg += duration;
|
||||
}
|
||||
durationAvg /= numIterations;
|
||||
std::cout << "Average Duration(NanoVDB-Host) = " << durationAvg << " ms" << std::endl;
|
||||
|
||||
saveImage("raytrace_level_set-nanovdb-host.pfm", width, height, (float*)imageBuffer.data());
|
||||
}
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
handle.deviceUpload();
|
||||
|
||||
auto* d_grid = handle.deviceGrid<float>();
|
||||
if (!d_grid)
|
||||
throw std::runtime_error("GridHandle does not contain a valid device grid");
|
||||
|
||||
imageBuffer.deviceUpload();
|
||||
float* d_outImage = reinterpret_cast<float*>(imageBuffer.deviceData());
|
||||
|
||||
{
|
||||
float durationAvg = 0;
|
||||
for (int i = 0; i < numIterations; ++i) {
|
||||
float duration = renderImage(true, renderOp, width, height, d_outImage, d_grid);
|
||||
//std::cout << "Duration(NanoVDB-Cuda) = " << duration << " ms" << std::endl;
|
||||
durationAvg += duration;
|
||||
}
|
||||
durationAvg /= numIterations;
|
||||
std::cout << "Average Duration(NanoVDB-Cuda) = " << durationAvg << " ms" << std::endl;
|
||||
|
||||
imageBuffer.deviceDownload();
|
||||
saveImage("raytrace_level_set-nanovdb-cuda.pfm", width, height, (float*)imageBuffer.data());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#if defined(NANOVDB_USE_OPENVDB)
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
|
||||
#include <openvdb/openvdb.h>
|
||||
#include <openvdb/math/Ray.h>
|
||||
#include <openvdb/tools/RayIntersector.h>
|
||||
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h>
|
||||
#include <nanovdb/util/NanoToOpenVDB.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
using BufferT = nanovdb::CudaDeviceBuffer;
|
||||
#else
|
||||
using BufferT = nanovdb::HostBuffer;
|
||||
#endif
|
||||
|
||||
void runOpenVDB(nanovdb::GridHandle<nanovdb::CudaDeviceBuffer>& handle, int numIterations, int width, int height, BufferT& imageBuffer)
|
||||
{
|
||||
using GridT = openvdb::FloatGrid;
|
||||
using CoordT = openvdb::Coord;
|
||||
using RealT = float;
|
||||
using Vec3T = openvdb::math::Vec3<RealT>;
|
||||
using RayT = openvdb::math::Ray<RealT>;
|
||||
|
||||
#if 1
|
||||
auto srcGrid = nanovdb::nanoToOpenVDB(handle);
|
||||
std::cout << "Exporting to OpenVDB grid[" << srcGrid->getName() << "]...\n";
|
||||
#else
|
||||
openvdb::initialize();
|
||||
std::string filename = "C:/Users/william/Downloads/dragon.vdb";
|
||||
openvdb::io::File file(filename);
|
||||
file.open(false); //disable delayed loading
|
||||
auto srcGrid = file.readGrid<BufferT>("ls_dragon");
|
||||
std::cout << "Loading OpenVDB grid[" << srcGrid->getName() << "]...\n";
|
||||
#endif
|
||||
|
||||
auto h_grid = (GridT*)srcGrid.get();
|
||||
|
||||
float* h_outImage = reinterpret_cast<float*>(imageBuffer.data());
|
||||
|
||||
auto indexBBox = h_grid->evalActiveVoxelBoundingBox();
|
||||
auto gridXform = h_grid->transformPtr();
|
||||
auto worldBBox = gridXform->indexToWorld(indexBBox);
|
||||
float wBBoxDimZ = (float)worldBBox.extents()[2] * 2;
|
||||
Vec3T wBBoxCenter = Vec3T(worldBBox.min() + worldBBox.extents() * 0.5f);
|
||||
|
||||
RayGenOp<Vec3T> rayGenOp(wBBoxDimZ, wBBoxCenter);
|
||||
CompositeOp compositeOp;
|
||||
|
||||
openvdb::CoordBBox treeIndexBbox;
|
||||
treeIndexBbox = h_grid->evalActiveVoxelBoundingBox();
|
||||
std::cout << "Bounds: " << treeIndexBbox << std::endl;
|
||||
|
||||
auto renderOp = [width, height, rayGenOp, compositeOp, treeIndexBbox, wBBoxDimZ] __hostdev__(int start, int end, float* image, const GridT* grid) {
|
||||
openvdb::tools::LevelSetRayIntersector<GridT, openvdb::tools::LinearSearchImpl<GridT, 0, RealT>, GridT::TreeType::RootNodeType::ChildNodeType::LEVEL, RayT> intersector(*grid);
|
||||
for (int i = start; i < end; ++i) {
|
||||
Vec3T rayEye;
|
||||
Vec3T rayDir;
|
||||
rayGenOp(i, width, height, rayEye, rayDir);
|
||||
// generate ray.
|
||||
RayT wRay(rayEye, rayDir);
|
||||
// transform the ray to the grid's index-space.
|
||||
RayT iRay = wRay.worldToIndex(*grid);
|
||||
// intersect...
|
||||
float t0;
|
||||
if (intersector.intersectsIS(iRay, t0)) {
|
||||
// write distance to surface. (we assume it is a uniform voxel)
|
||||
float wT0 = t0 * float(grid->voxelSize()[0]);
|
||||
compositeOp(image, i, width, height, wT0 / (wBBoxDimZ * 2), 1.0f);
|
||||
} else {
|
||||
// write background value.
|
||||
compositeOp(image, i, width, height, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
float durationAvg = 0;
|
||||
for (int i = 0; i < numIterations; ++i) {
|
||||
float duration = renderImage(false, renderOp, width, height, h_outImage, h_grid);
|
||||
//std::cout << "Duration(OpenVDB-Host) = " << duration << " ms" << std::endl;
|
||||
durationAvg += duration;
|
||||
}
|
||||
durationAvg /= numIterations;
|
||||
std::cout << "Average Duration(OpenVDB-Host) = " << durationAvg << " ms" << std::endl;
|
||||
|
||||
saveImage("raytrace_level_set-openvdb-host.pfm", width, height, (float*)imageBuffer.data());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/util/IO.h>
|
||||
|
||||
/// @brief Read a NanoVDB grid form file, check pointer and access a single value
|
||||
///
|
||||
/// @note This example does NOT dpend on OpenVDB (or CUDA), only NanoVDB.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
auto handle = nanovdb::io::readGrid("data/sphere.nvdb"); // read first grid in file
|
||||
|
||||
auto* grid = handle.grid<float>(); // get a (raw) pointer to the first NanoVDB grid of value type float
|
||||
|
||||
if (grid == nullptr)
|
||||
throw std::runtime_error("File did not contain a grid with value type float");
|
||||
|
||||
// Access and print out a single value in the NanoVDB grid
|
||||
printf("NanoVDB cpu: %4.2f\n", grid->tree().getValue(nanovdb::Coord(99, 0, 0)));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#include <nanovdb/util/IO.h> // this is required to read (and write) NanoVDB files on the host
|
||||
|
||||
/// @brief Read a NanoVDB grid from a file and print out multiple values.
|
||||
///
|
||||
/// @note Note This example does NOT depend on OpenVDB (nor CUDA), only NanoVDB.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
auto handle = nanovdb::io::readGrid("data/sphere.nvdb"); // reads first grid from file
|
||||
|
||||
auto* grid = handle.grid<float>(); // get a (raw) pointer to a NanoVDB grid of value type float
|
||||
|
||||
if (!grid)
|
||||
throw std::runtime_error("File did not contain a grid with value type float");
|
||||
|
||||
auto acc = grid->getAccessor(); // create an accessor for fast access to multiple values
|
||||
for (int i = 97; i < 104; ++i) {
|
||||
printf("(%3i,0,0) NanoVDB cpu: % -4.2f\n", i, acc.getValue(nanovdb::Coord(i, 0, 0)));
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/util/IO.h> // this is required to read (and write) NanoVDB files on the host
|
||||
#include <nanovdb/util/CudaDeviceBuffer.h> // required for CUDA memory management
|
||||
|
||||
extern "C" void launch_kernels(const nanovdb::NanoGrid<float>*,
|
||||
const nanovdb::NanoGrid<float>*,
|
||||
cudaStream_t stream);
|
||||
|
||||
/// @brief Read a NanoVDB grid from a file and print out multiple values on both the cpu and gpu.
|
||||
///
|
||||
/// @note Note This example does NOT depend on OpenVDB, only NanoVDB and CUDA.
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
// returns a GridHandle using CUDA for memory management.
|
||||
auto handle = nanovdb::io::readGrid<nanovdb::CudaDeviceBuffer>("data/sphere.nvdb");
|
||||
|
||||
cudaStream_t stream; // Create a CUDA stream to allow for asynchronous copy of pinned CUDA memory.
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
handle.deviceUpload(stream, false); // Copy the NanoVDB grid to the GPU asynchronously
|
||||
|
||||
auto* cpuGrid = handle.grid<float>(); // get a (raw) pointer to a NanoVDB grid of value type float on the CPU
|
||||
auto* deviceGrid = handle.deviceGrid<float>(); // get a (raw) pointer to a NanoVDB grid of value type float on the GPU
|
||||
|
||||
if (!deviceGrid || !cpuGrid)
|
||||
throw std::runtime_error("GridHandle did not contain a grid with value type float");
|
||||
|
||||
launch_kernels(deviceGrid, cpuGrid, stream); // Call a host method to print a grid values on both the CPU and GPU
|
||||
|
||||
cudaStreamDestroy(stream); // Destroy the CUDA stream
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "An exception occurred: \"" << e.what() << "\"" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <nanovdb/NanoVDB.h> // this defined the core tree data structure of NanoVDB accessable on both the host and device
|
||||
#include <stdio.h> // for printf
|
||||
|
||||
// This is called by the host only
|
||||
void cpu_kernel(const nanovdb::NanoGrid<float>* cpuGrid)
|
||||
{
|
||||
auto cpuAcc = cpuGrid->getAccessor();
|
||||
for (int i = 97; i < 104; ++i) {
|
||||
printf("(%3i,0,0) NanoVDB cpu: % -4.2f\n", i, cpuAcc.getValue(nanovdb::Coord(i, 0, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
// This is called by the device only
|
||||
__global__ void gpu_kernel(const nanovdb::NanoGrid<float>* deviceGrid)
|
||||
{
|
||||
if (threadIdx.x > 6)
|
||||
return;
|
||||
int i = 97 + threadIdx.x;
|
||||
auto gpuAcc = deviceGrid->getAccessor();
|
||||
printf("(%3i,0,0) NanoVDB gpu: % -4.2f\n", i, gpuAcc.getValue(nanovdb::Coord(i, 0, 0)));
|
||||
}
|
||||
|
||||
// This is called by the client code on the host
|
||||
extern "C" void launch_kernels(const nanovdb::NanoGrid<float>* deviceGrid,
|
||||
const nanovdb::NanoGrid<float>* cpuGrid,
|
||||
cudaStream_t stream)
|
||||
{
|
||||
// Launch the device kernel asynchronously
|
||||
gpu_kernel<<<1, 64, 0, stream>>>(deviceGrid);
|
||||
|
||||
// Launch the host "kernel" (synchronously)
|
||||
cpu_kernel(cpuGrid);
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @file ComputePrimitives.h
|
||||
/// @brief A collection of parallel compute primitives
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(NANOVDB_USE_CUDA)
|
||||
#include <cuda_runtime_api.h>
|
||||
#endif
|
||||
|
||||
#if defined(NANOVDB_USE_TBB)
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/blocked_range.h>
|
||||
#endif
|
||||
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
|
||||
|
||||
// forward compatibility for C++14 Standard Library
|
||||
namespace cxx14 {
|
||||
template<std::size_t...>
|
||||
struct index_sequence
|
||||
{
|
||||
};
|
||||
|
||||
template<std::size_t N, std::size_t... Is>
|
||||
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...>
|
||||
{
|
||||
};
|
||||
|
||||
template<std::size_t... Is>
|
||||
struct make_index_sequence<0, Is...> : index_sequence<Is...>
|
||||
{
|
||||
};
|
||||
} // namespace cxx14
|
||||
|
||||
#if defined(__CUDACC__)
|
||||
|
||||
static inline bool checkCUDA(cudaError_t result, const char* file, const int line)
|
||||
{
|
||||
if (result != cudaSuccess) {
|
||||
std::cerr << "CUDA Runtime API error " << result << " in file " << file << ", line " << line << " : " << cudaGetErrorString(result) << ".\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define NANOVDB_CUDA_SAFE_CALL(x) checkCUDA(x, __FILE__, __LINE__)
|
||||
|
||||
static inline void checkErrorCUDA(cudaError_t result, const char* file, const int line)
|
||||
{
|
||||
if (result != cudaSuccess) {
|
||||
std::cerr << "CUDA Runtime API error " << result << " in file " << file << ", line " << line << " : " << cudaGetErrorString(result) << ".\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#define NANOVDB_CUDA_CHECK_ERROR(result, file, line) checkErrorCUDA(result, file, line)
|
||||
|
||||
#endif
|
||||
|
||||
template<typename Fn, typename... Args>
|
||||
class ApplyFunc
|
||||
{
|
||||
public:
|
||||
ApplyFunc(int count, int blockSize, const Fn& fn, Args... args)
|
||||
: mCount(count)
|
||||
, mBlockSize(blockSize)
|
||||
, mArgs(args...)
|
||||
, mFunc(fn)
|
||||
{
|
||||
}
|
||||
|
||||
template<std::size_t... Is>
|
||||
void call(int start, int end, cxx14::index_sequence<Is...>) const
|
||||
{
|
||||
mFunc(start, end, std::get<Is>(mArgs)...);
|
||||
}
|
||||
|
||||
void operator()(int i) const
|
||||
{
|
||||
int start = i * mBlockSize;
|
||||
int end = i * mBlockSize + mBlockSize;
|
||||
if (end > mCount)
|
||||
end = mCount;
|
||||
call(start, end, cxx14::make_index_sequence<sizeof...(Args)>());
|
||||
}
|
||||
|
||||
#if defined(NANOVDB_USE_TBB)
|
||||
void operator()(const tbb::blocked_range<int>& r) const
|
||||
{
|
||||
int start = r.begin();
|
||||
int end = r.end();
|
||||
if (end > mCount)
|
||||
end = mCount;
|
||||
call(start, end, cxx14::make_index_sequence<sizeof...(Args)>());
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
int mCount;
|
||||
int mBlockSize;
|
||||
Fn mFunc;
|
||||
std::tuple<Args...> mArgs;
|
||||
};
|
||||
|
||||
#if defined(__CUDACC__)
|
||||
|
||||
template<int WorkPerThread, typename FnT, typename... Args>
|
||||
__global__ void parallelForKernel(int numItems, FnT f, Args... args)
|
||||
{
|
||||
for (int j=0;j<WorkPerThread;++j)
|
||||
{
|
||||
int i = threadIdx.x + blockIdx.x * blockDim.x + j * blockDim.x * gridDim.x;
|
||||
if (i < numItems)
|
||||
f(i, i + 1, args...);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void computeSync(bool useCuda, const char* file, int line)
|
||||
{
|
||||
#if defined(__CUDACC__)
|
||||
if (useCuda) {
|
||||
NANOVDB_CUDA_CHECK_ERROR(cudaDeviceSynchronize(), file, line);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void computeFill(bool useCuda, void* data, uint8_t value, size_t size)
|
||||
{
|
||||
if (useCuda) {
|
||||
#if defined(__CUDACC__)
|
||||
cudaMemset(data, value, size);
|
||||
#endif
|
||||
} else {
|
||||
std::memset(data, value, size);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FunctorT, typename... Args>
|
||||
inline void computeForEach(bool useCuda, int numItems, int blockSize, const char* file, int line, const FunctorT& op, Args... args)
|
||||
{
|
||||
if (numItems == 0)
|
||||
return;
|
||||
|
||||
if (useCuda) {
|
||||
#if defined(__CUDACC__)
|
||||
static const int WorkPerThread = 1;
|
||||
int blockCount = ((numItems/WorkPerThread) + (blockSize - 1)) / blockSize;
|
||||
parallelForKernel<WorkPerThread, FunctorT, Args...><<<blockCount, blockSize, 0, 0>>>(numItems, op, args...);
|
||||
NANOVDB_CUDA_CHECK_ERROR(cudaGetLastError(), file, line);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(NANOVDB_USE_TBB)
|
||||
tbb::blocked_range<int> range(0, numItems, blockSize);
|
||||
tbb::parallel_for(range, ApplyFunc<FunctorT, Args...>(numItems, blockSize, op, args...));
|
||||
#else
|
||||
for (int i = 0; i < numItems; ++i)
|
||||
op(i, i + 1, args...);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
inline void computeDownload(bool useCuda, void* dst, const void* src, size_t size)
|
||||
{
|
||||
if (useCuda) {
|
||||
#if defined(__CUDACC__)
|
||||
cudaMemcpy(dst, src, size, cudaMemcpyDeviceToHost);
|
||||
#endif
|
||||
} else {
|
||||
std::memcpy(dst, src, size);
|
||||
}
|
||||
}
|
||||
|
||||
inline void computeCopy(bool useCuda, void* dst, const void* src, size_t size)
|
||||
{
|
||||
if (useCuda) {
|
||||
#if defined(__CUDACC__)
|
||||
cudaMemcpy(dst, src, size, cudaMemcpyDeviceToDevice);
|
||||
#endif
|
||||
} else {
|
||||
std::memcpy(dst, src, size);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright Contributors to the OpenVDB Project
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
/// @file CpuTimer.h
|
||||
///
|
||||
/// @author Ken Museth
|
||||
///
|
||||
/// @brief A simple timing class
|
||||
|
||||
#ifndef NANOVDB_CPU_TIMER_H_HAS_BEEN_INCLUDED
|
||||
#define NANOVDB_CPU_TIMER_H_HAS_BEEN_INCLUDED
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
namespace nanovdb {
|
||||
|
||||
template <typename Accuracy = std::chrono::milliseconds>
|
||||
class CpuTimer
|
||||
{
|
||||
std::chrono::high_resolution_clock::time_point mStart;
|
||||
public:
|
||||
CpuTimer() {}
|
||||
void start(const std::string &msg, std::ostream& os = std::cerr) {
|
||||
os << msg << " ... " << std::flush;
|
||||
mStart = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
void restart(const std::string &msg, std::ostream& os = std::cerr) {
|
||||
this->stop();
|
||||
os << msg << " ... " << std::flush;
|
||||
mStart = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
void stop(std::ostream& os = std::cerr)
|
||||
{
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto diff = std::chrono::duration_cast<Accuracy>(end - mStart).count();
|
||||
os << "completed in " << diff;
|
||||
if (std::is_same<Accuracy, std::chrono::microseconds>::value) {// resolved at compile-time
|
||||
os << " microseconds" << std::endl;
|
||||
} else if (std::is_same<Accuracy, std::chrono::milliseconds>::value) {
|
||||
os << " milliseconds" << std::endl;
|
||||
} else if (std::is_same<Accuracy, std::chrono::seconds>::value) {
|
||||
os << " seconds" << std::endl;
|
||||
} else {
|
||||
os << " unknown time unit" << std::endl;
|
||||
}
|
||||
}
|
||||
};// CpuTimer
|
||||
|
||||
} // namespace nanovdb
|
||||
|
||||
#endif // NANOVDB_CPU_TIMER_HAS_BEEN_INCLUDED
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user