1 // Copyright 2019-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 // ========================================================================== //
5 // This is a shared ISPC and C++ header, which contains the internal data
6 // types used to represent VDB trees.
7 // ========================================================================== //
8 
9 #pragma once
10 
11 #include "VKLDataType.h"
12 #include "VKLFilter.h"
13 #include "ispc_cpp_interop.h"
14 
15 // ========================================================================== //
16 // Tree topology information. The file vdb_topology.h is generated
17 // from vdb_topology.h.in, and defines both VKL_VDB_NUM_LEVELS and, for
18 // each <level> in {0, VKL_VDB_NUM_LEVELS-1}:
19 //  VKL_VDB_LOG_RES_<level>:       The base two logarithm of the storage
20 //                                 resolution of nodes on this level.
21 //  VKL_VDB_STORAGE_RES_<level>:   The storage resolution of nodes on this
22 //                                 level.
23 //  VKL_VDB_NUM_VOXELS_<level>:    The number of voxels stored in a node on
24 //                                 this level.
25 //  VKL_VDB_TOTAL_LOG_RES_<level>: The base two logarithm of the domain
26 //                                 resolution on this level.
27 //  VKL_VDB_RES_<level>:           The domain resolution on this level.
28 //
29 //  This file also defines macros
30 //
31 //  __vkl_vdb_iterate_levels_<level>(macro) (see __vkl_vdb_iterate_levels below)
32 //  __vkl_vdb_map_offset_to_voxel_<level>(univary, offset)
33 //  __vkl_vdb_3d_to_linear_<level>(offx, offy, offz)
34 //  __vkl_vdb_map_offset_to_lindex_<level>(offset_3d)
35 // ========================================================================== //
36 //
37 #include "openvkl/vdb/topology.h"  // This file is generated by cmake.
38 
39 // ========================================================================== //
40 // The following are runtime versions of the constants described above,
41 // to be used when the level is not known at runtime.
42 // ========================================================================== //
43 
vklVdbNumLevels()44 inline VKL_INTEROP_CONSTEXPR VKL_INTEROP_UNIFORM vkl_uint32 vklVdbNumLevels()
45 {
46   return VKL_VDB_NUM_LEVELS;
47 }
48 
49 #define __vkl_vdb_switch_case(Level, Prefix) \
50   case Level:                                \
51     return Prefix##Level;
52 
53 #define __vkl_vdb_define_topology_functions(univary)                         \
54   inline univary vkl_uint32 vklVdbLevelLogRes(univary vkl_uint32 level)      \
55   {                                                                          \
56     switch (level) {                                                         \
57       __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,                      \
58                                  VKL_VDB_LOG_RES_) default : return 0;       \
59     }                                                                        \
60   }                                                                          \
61   inline univary vkl_uint32 vklVdbLevelResShift(univary vkl_uint32 level)    \
62   {                                                                          \
63     return vklVdbLevelLogRes(level);                                         \
64   }                                                                          \
65   inline univary vkl_uint32 vklVdbLevelTotalLogRes(univary vkl_uint32 level) \
66   {                                                                          \
67     switch (level) {                                                         \
68       __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,                      \
69                                  VKL_VDB_TOTAL_LOG_RES_) default : return 0; \
70     }                                                                        \
71   }                                                                          \
72   inline univary vkl_uint32 vklVdbLevelStorageRes(univary vkl_uint32 level)  \
73   {                                                                          \
74     switch (level) {                                                         \
75       __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,                      \
76                                  VKL_VDB_STORAGE_RES_) default : return 0;   \
77     }                                                                        \
78   }                                                                          \
79   inline univary vkl_uint32 vklVdbLevelRes(univary vkl_uint32 level)         \
80   {                                                                          \
81     switch (level) {                                                         \
82       __vkl_vdb_iterate_levels_0(                                            \
83           __vkl_vdb_switch_case,                                             \
84           VKL_VDB_RES_) /* Special case: we use this to determine cell       \
85                            resolution. */                                    \
86           case VKL_VDB_NUM_LEVELS : return 1;                                \
87     default:                                                                 \
88       return 0;                                                              \
89     }                                                                        \
90   }                                                                          \
91   inline univary vkl_uint32 vklVdbLevelNumVoxels(univary vkl_uint32 level)   \
92   {                                                                          \
93     switch (level) {                                                         \
94       __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,                      \
95                                  VKL_VDB_NUM_VOXELS_) default : return 0;    \
96     }                                                                        \
97   }
98 
__vkl_interop_univary(__vkl_vdb_define_topology_functions)99 __vkl_interop_univary(__vkl_vdb_define_topology_functions)
100 #undef __vkl_vdb_define_topology_functions
101 #undef __vkl_vdb_switch_case
102 
103 // ========================================================================== //
104 // Functions that help with index computations.
105 // ========================================================================== //
106 
107 #define __vkl_vdb_switch_case(Level, Macro, ...) \
108   __vkl_vdb_expand(case Level : return Macro##_##Level(__VA_ARGS__));
109 
110     /*
111      * Map a 1D domain offset w.r.t. the root node to an offset inside the
112      * surrounding voxel on the given level.
113      */
114     inline VKL_INTEROP_UNIFORM vkl_uint64
115     vklVdbDomainOffsetToVoxel(VKL_INTEROP_UNIFORM vkl_uint32 level,
116                               VKL_INTEROP_UNIFORM vkl_uint32 offset)
117 {
118   switch (level) {
119     __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,
120                                __vkl_vdb_domain_offset_to_voxel_uniform,
121                                offset) default : return 0;
122   }
123 }
124 
125 /*
126  * Map a 3D offset to a linear index. Note that vdb volume store
127  * data in z-major order!
128  */
129 inline VKL_INTEROP_UNIFORM vkl_uint64
vklVdb3DToLinear(VKL_INTEROP_UNIFORM vkl_uint32 level,VKL_INTEROP_UNIFORM vkl_uint64 offsetX,VKL_INTEROP_UNIFORM vkl_uint64 offsetY,VKL_INTEROP_UNIFORM vkl_uint64 offsetZ)130 vklVdb3DToLinear(VKL_INTEROP_UNIFORM vkl_uint32 level,
131                  VKL_INTEROP_UNIFORM vkl_uint64 offsetX,
132                  VKL_INTEROP_UNIFORM vkl_uint64 offsetY,
133                  VKL_INTEROP_UNIFORM vkl_uint64 offsetZ)
134 {
135   switch (level) {
136     __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,
137                                __vkl_vdb_3d_to_linear_uniform,
138                                offsetX,
139                                offsetY,
140                                offsetZ) default : return 0;
141   }
142 }
143 
144 /*
145  * Map a 3D domain offset w.r.t. to the root node to a linear voxel index
146  * inside the surrounding voxel on the given level.
147  */
148 inline VKL_INTEROP_UNIFORM vkl_uint64
vklVdbDomainOffsetToLinear(VKL_INTEROP_UNIFORM vkl_uint32 level,VKL_INTEROP_UNIFORM vkl_uint64 offsetX,VKL_INTEROP_UNIFORM vkl_uint64 offsetY,VKL_INTEROP_UNIFORM vkl_uint64 offsetZ)149 vklVdbDomainOffsetToLinear(VKL_INTEROP_UNIFORM vkl_uint32 level,
150                            VKL_INTEROP_UNIFORM vkl_uint64 offsetX,
151                            VKL_INTEROP_UNIFORM vkl_uint64 offsetY,
152                            VKL_INTEROP_UNIFORM vkl_uint64 offsetZ)
153 {
154   switch (level) {
155     __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,
156                                __vkl_vdb_domain_offset_to_linear_uniform,
157                                offsetX,
158                                offsetY,
159                                offsetZ) default : return 0;
160   }
161 }
162 
163 #if defined(ISPC)
164 
165 // Varying versions of the above. We do not use __vkl_interop_univary here
166 // because there is no standard way to handle empty __VA_ARGS__, which happen
167 // in C++ when univary expands to nothing.
168 // This also conveniently leads to better error messages.
169 
170 /*
171  * Map a 1D domain offset w.r.t. the root node to an offset inside the
172  * surrounding voxel on the given level.
173  */
vklVdbDomainOffsetToVoxel(varying vkl_uint32 level,varying vkl_uint32 offset)174 inline varying vkl_uint64 vklVdbDomainOffsetToVoxel(varying vkl_uint32 level,
175                                                     varying vkl_uint32 offset)
176 {
177   switch (level) {
178     __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,
179                                __vkl_vdb_domain_offset_to_voxel_varying,
180                                offset) default : return 0;
181   }
182 }
183 
184 /*
185  * Map a 3D offset to a linear index. Note that vdb volume store
186  * data in z-major order!
187  */
vklVdb3DToLinear(varying vkl_uint32 level,varying vkl_uint64 offsetX,varying vkl_uint64 offsetY,varying vkl_uint64 offsetZ)188 inline varying vkl_uint64 vklVdb3DToLinear(varying vkl_uint32 level,
189                                            varying vkl_uint64 offsetX,
190                                            varying vkl_uint64 offsetY,
191                                            varying vkl_uint64 offsetZ)
192 {
193   switch (level) {
194     __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,
195                                __vkl_vdb_3d_to_linear_varying,
196                                offsetX,
197                                offsetY,
198                                offsetZ) default : return 0;
199   }
200 }
201 
202 /*
203  * Map a 3D domain offset w.r.t. to the root node to a linear voxel index
204  * inside the surrounding voxel on the given level.
205  */
vklVdbDomainOffsetToLinear(varying vkl_uint32 level,varying vkl_uint64 offsetX,varying vkl_uint64 offsetY,varying vkl_uint64 offsetZ)206 inline varying vkl_uint64 vklVdbDomainOffsetToLinear(varying vkl_uint32 level,
207                                                      varying vkl_uint64 offsetX,
208                                                      varying vkl_uint64 offsetY,
209                                                      varying vkl_uint64 offsetZ)
210 {
211   switch (level) {
212     __vkl_vdb_iterate_levels_0(__vkl_vdb_switch_case,
213                                __vkl_vdb_domain_offset_to_linear_varying,
214                                offsetX,
215                                offsetY,
216                                offsetZ) default : return 0;
217   }
218 }
219 
220 #endif
221 
222 #undef __vkl_vdb_switch_case
223