OpenVDB 9.0.0
VolumeExecutable.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4/// @file compiler/VolumeExecutable.h
5///
6/// @authors Nick Avramoussis, Francisco Gochez, Richard Jones
7///
8/// @brief The VolumeExecutable, produced by the OpenVDB AX Compiler for
9/// execution over Numerical OpenVDB Grids.
10///
11
12#ifndef OPENVDB_AX_COMPILER_VOLUME_EXECUTABLE_HAS_BEEN_INCLUDED
13#define OPENVDB_AX_COMPILER_VOLUME_EXECUTABLE_HAS_BEEN_INCLUDED
14
15#include "CustomData.h"
16#include "AttributeRegistry.h"
17
18#include <openvdb/version.h>
19#include <openvdb/Grid.h>
20
21#include <unordered_map>
22
23class TestVolumeExecutable;
24
25namespace llvm {
26class ExecutionEngine;
27class LLVMContext;
28}
29
30namespace openvdb {
32namespace OPENVDB_VERSION_NAME {
33namespace ax {
34
35class Compiler;
36
37/// @brief Object that encapsulates compiled AX code which can be executed on a
38/// collection of VDB volume grids. Executables are created by the compiler
39/// and hold the final immutable JIT compiled function and context.
40/// @details The VolumeExecutable is returned from the ax::Compiler when
41/// compiling AX code for volume execution. The class represents a typical AX
42/// executable object; immutable except for execution settings and implements
43/// 'execute' functions which can be called multiple times for arbitrary sets
44/// of inputs. The intended usage of these executables is to configure their
45/// runtime arguments and then call VolumeExecutable::execute with your VDBs.
46/// For example:
47/// @code
48/// VolumeExecutable::Ptr exe = compiler.compile<VolumeExecutable>("@a += 1");
49/// exe->setTreeExecutionLevel(0); // only process leaf nodes
50/// exe->setValueIterator(VolumeExecutable::IterType::ALL); // process all values
51/// exe->execute(vdbs); // run on a set of vdbs
52/// exe->execute(grid); // run on a single vdb
53/// @endcode
54///
55/// The Volume executable is initialised with specific configurable settings:
56/// - Iteration Level: min=0, max=RootNode::Level.
57/// By default, processes the entire VDB tree hierarchy.
58/// @sa setTreeExecutionLevel
59/// - Iteration Type: ON
60/// By default, processes ACTIVE values.
61/// @sa setValueIterator
62/// - Active Tile Streaming: ON, OFF or AUTO depending on AX code.
63/// By default, if AX detects that the AX program may produce unique
64/// values for leaf level voxels that would otherwise comprise a
65/// given active tile, this setting is set to ON or AUTO. Otherwise it is
66/// set to OFF.
67/// @sa setActiveTileStreaming
68/// - Grain sizes: 1:32
69/// The default grain sizes passed to the tbb partitioner for leaf level
70/// processing and active tile processing.
71/// @sa setGrainSize
72/// @sa setActiveTileStreamingGrainSize
73///
74/// For more in depth information, see the @ref vdbaxcompilerexe documentation.
76{
77public:
78 using Ptr = std::shared_ptr<VolumeExecutable>;
80
81 /// @brief Copy constructor. Shares the LLVM constructs but deep copies the
82 /// settings. Multiple copies of an executor can be used at the same time
83 /// safely.
85
86 ////////////////////////////////////////////////////////
87
88 ///@{
89 /// @brief Run this volume executable binary on target volumes.
90 /// @details This method reads from the stored settings on the executable
91 /// to determine certain behaviour and runs the JIT compiled function
92 /// across every valid VDB value. Topology may be changed, deleted or
93 /// created.
94 ///
95 /// This method is thread safe; it can be run concurrently from the same
96 /// VolumeExecutable instance on different inputs.
97 ///
98 /// @param grids The VDB Volumes to process
99 void execute(openvdb::GridPtrVec& grids) const;
100 void execute(openvdb::GridBase& grids) const;
101 ///@}
102
103 ////////////////////////////////////////////////////////
104
105 /// @brief Set the behaviour when missing grids are accessed. Default
106 /// behaviour is true, which creates them with default transforms and
107 /// background values
108 /// @param flag Enables or disables the creation of missing attributes
109 void setCreateMissing(const bool flag);
110 /// @return Whether this executable will generate new grids.
111 bool getCreateMissing() const;
112
113 /// @brief Set the execution level for this executable. This controls what
114 /// nodes are processed when execute is called. Possible values depend on
115 /// the OpenVDB configuration in use, however a value of 0 will always
116 /// correspond to the lowest level (leaf-level). By default, the min
117 /// level is zero (LeafNodeType::LEVEL) and the max level is the root
118 /// node's level (RootNodeType::LEVEL). In other words, the default
119 /// execution level settings process the whole of the tree.
120 /// @note A value larger that the number of levels in the tree (i.e. larger
121 /// than the root node's level) will cause this method to throw a runtime
122 /// error.
123 /// @param min The minimum tree execution level to set
124 /// @param max The maximum tree execution level to set
126 /// @param level The tree execution level to set. Calls setTreeExecutionLevel
127 /// with min and max arguments as level.
128 void setTreeExecutionLevel(const Index level);
129 /// @brief Get the tree execution levels.
130 /// @param min The minimum tree execution level
131 /// @param max The maximum tree execution level
133
134 /// @brief The streaming type of active tiles during execution.
135 /// @param ON active tiles are temporarily densified (converted to leaf
136 /// level voxels) on an "as needed" basis and the subsequent voxel
137 /// values are processed. The temporarily densified node is added to the
138 /// tree only if a non constant voxel buffer is produced. Otherwise a
139 /// child tile may be created or the original tile's value may simply be
140 /// modified.
141 /// @param OFF tile topologies are left unchanged and their single value is
142 /// processed.
143 /// @param AUTO the volume executable analyzes the compiled kernel and
144 /// attempts to determine if expansion of active tiles would lead to
145 /// different, non-constant values in the respective voxels. This is
146 /// done on a per grid basis; ultimately each execution will be set to
147 /// ON or OFF. This option will always fall back to ON if there is any
148 /// chance the kernel may produce child nodes
149 ///
150 /// @note The volume executable always runs an AUTO check on creation and
151 /// will set itself to ON (if all grids always need child nodes), OFF (if
152 /// grids never need child nodes) or remains as AUTO (if this depends on
153 /// which grid is being processed).
154 ///
155 /// @details When an AX kernel is run over coarser levels of the tree (i.e.
156 /// not leaf voxels), it is often desirable to densify these areas into
157 /// unique voxels such that they can each receive a unique value. For
158 /// example, consider the following AX code which assigns a vector volume
159 /// to the world space position of each voxel:
160 /// @code
161 /// v@v = getvoxelpws();
162 /// @endcode
163 /// Active tiles hold a single value but comprise an area greater than
164 /// that of a single voxel. As the above kernel varies with respect to
165 /// a nodes position, we'd need to replace these tiles with leaf voxels
166 /// to get unique per node values. The stream flag is initialised to ON
167 /// in this case.
168 ///
169 /// This behaviour, however, is not always desirable .i.e:
170 /// @code
171 /// v@v = {1,2,3};
172 /// @endcode
173 /// In this instance, all values within a volume receive the same value
174 /// and are not dependent on any spatially or iteratively varying
175 /// metrics. The stream flag is set to OFF.
176 ///
177 /// The AUTO flag is set in cases where the runtime access pattern of the
178 /// inputs determines streaming:
179 /// @code
180 /// f@density = f@mask;
181 /// f@mask = 0;
182 /// @endcode
183 /// In this instance, the runtime topology and values of \@mask determines
184 /// whether child topology needs to be created in \@density, but \@mask
185 /// itself does not need streaming. Streaming will be set to ON for
186 /// density but OFF for mask.
187 ///
188 /// @note This behaviour is only applied to active tiles. If the value
189 /// iterator is set to OFF, this option is ignored.
190 /// @warning This option can generate large amounts of leaf level voxels.
191 /// It is recommended to use a good concurrent memory allocator (such as
192 /// jemalloc) for the best performance.
193 enum class Streaming { ON, OFF, AUTO };
194 /// @brief Controls the behaviour of expansion of active tiles.
195 /// @param s The behaviour to set
197 /// @return The current stream behaviour.
199 /// @return The current stream behaviour for a particular grid. This is
200 /// either ON or OFF.
201 /// @param name The name of the grid to query
202 /// @param type The grids type
203 Streaming getActiveTileStreaming(const std::string& name,
204 const ast::tokens::CoreType& type) const;
205
206 enum class IterType { ON, OFF, ALL };
207 /// @brief Set the value iterator type to use with this executable. Options
208 /// are ON, OFF, ALL. Default is ON.
209 /// @param iter The value iterator type to set
210 void setValueIterator(const IterType& iter);
211 /// @return The current value iterator type
213
214 ///@{
215 /// @brief Set the threading grain sizes used when iterating over nodes
216 /// in a VDB.
217 /// @details Two grain sizes are provided, the first of which (g1) is used
218 /// to determine the chunk size of nodes which are not being streamed (see
219 /// setActiveTileStream). Leaf node execution always uses this grain size.
220 /// The default value for g1 is 1 which is typically appropriate for most
221 /// AX kernels.
222 /// The second grain size is used when streaming execution over active
223 /// tiles in a VDB. This execution model differs significantly from
224 /// typical leaf node execution due to the potential for substantially
225 /// more memory to be allocated. The default value is 32, which works well
226 /// for the default configuration of OpenVDB. If streaming is disabled,
227 /// this value has no effect.
228 /// @note Setting g1 or g2 to zero has the effect of disabling
229 /// multi-threading for the respective node executions. Setting both to
230 /// zero will disable all multi-threading performed by the execute method.
231 void setGrainSize(const size_t g1);
232 void setActiveTileStreamingGrainSize(const size_t g2);
233 /// @return The current g1 grain size
234 /// @sa setGrainSize
235 size_t getGrainSize() const;
236 /// @return The current g2 grain size
237 /// @sa setActiveTileStreamingGrainSize
239 ///@}
240
241
242
243 ////////////////////////////////////////////////////////
244
245 /// @return The tree execution level.
246 [[deprecated]] Index getTreeExecutionLevel() const;
247
248 ////////////////////////////////////////////////////////
249
250 // foward declaration of settings for this executable
251 struct Settings;
252
253private:
254 friend class Compiler;
255 friend class ::TestVolumeExecutable;
256
257 /// @brief Constructor, expected to be invoked by the compiler. Should not
258 /// be invoked directly.
259 /// @param context Shared pointer to an llvm:LLVMContext associated with the
260 /// execution engine
261 /// @param engine Shared pointer to an llvm::ExecutionEngine used to build
262 /// functions. Context should be the associated LLVMContext
263 /// @param accessRegistry Registry of volumes accessed by AX code
264 /// @param customData Custom data which will be shared by this executable.
265 /// It can be used to retrieve external data from within the AX code
266 /// @param functions A map of function names to physical memory addresses
267 /// which were built by llvm using engine
268 /// @param tree The AST linked to this executable. The AST is not stored
269 /// after compilation but can be used during construction of the exe to
270 /// infer some pre/post processing optimisations.
271 VolumeExecutable(const std::shared_ptr<const llvm::LLVMContext>& context,
272 const std::shared_ptr<const llvm::ExecutionEngine>& engine,
273 const AttributeRegistry::ConstPtr& accessRegistry,
274 const CustomData::ConstPtr& customData,
275 const std::unordered_map<std::string, uint64_t>& functions,
276 const ast::Tree& tree);
277
278private:
279 // The Context and ExecutionEngine must exist _only_ for object lifetime
280 // management. The ExecutionEngine must be destroyed before the Context
281 const std::shared_ptr<const llvm::LLVMContext> mContext;
282 const std::shared_ptr<const llvm::ExecutionEngine> mExecutionEngine;
283 const AttributeRegistry::ConstPtr mAttributeRegistry;
284 const CustomData::ConstPtr mCustomData;
285 const std::unordered_map<std::string, uint64_t> mFunctionAddresses;
286 std::unique_ptr<Settings> mSettings;
287};
288
289} // namespace ax
290} // namespace OPENVDB_VERSION_NAME
291} // namespace openvdb
292
293#endif // OPENVDB_AX_COMPILER_VOLUME_EXECUTABLE_HAS_BEEN_INCLUDED
294
These classes contain lists of expected attributes and volumes which are populated by compiler during...
Access to the CustomData class which can provide custom user user data to the OpenVDB AX Compiler.
Abstract base class for typed grids.
Definition: Grid.h:78
std::shared_ptr< const AttributeRegistry > ConstPtr
Definition: AttributeRegistry.h:42
The compiler class. This holds an llvm context and set of compiler options, and constructs executable...
Definition: Compiler.h:50
std::shared_ptr< const CustomData > ConstPtr
Definition: CustomData.h:38
Object that encapsulates compiled AX code which can be executed on a collection of VDB volume grids....
Definition: VolumeExecutable.h:76
void setActiveTileStreamingGrainSize(const size_t g2)
Set the threading grain sizes used when iterating over nodes in a VDB.
void setCreateMissing(const bool flag)
Set the behaviour when missing grids are accessed. Default behaviour is true, which creates them with...
void execute(openvdb::GridBase &grids) const
Run this volume executable binary on target volumes.
void getTreeExecutionLevel(Index &min, Index &max) const
Get the tree execution levels.
Streaming getActiveTileStreaming() const
std::shared_ptr< VolumeExecutable > Ptr
Definition: VolumeExecutable.h:78
void setValueIterator(const IterType &iter)
Set the value iterator type to use with this executable. Options are ON, OFF, ALL....
void setActiveTileStreaming(const Streaming &s)
Controls the behaviour of expansion of active tiles.
void setGrainSize(const size_t g1)
Set the threading grain sizes used when iterating over nodes in a VDB.
Streaming getActiveTileStreaming(const std::string &name, const ast::tokens::CoreType &type) const
void setTreeExecutionLevel(const Index min, const Index max)
Set the execution level for this executable. This controls what nodes are processed when execute is c...
Streaming
The streaming type of active tiles during execution.
Definition: VolumeExecutable.h:193
void setTreeExecutionLevel(const Index level)
IterType
Definition: VolumeExecutable.h:206
void execute(openvdb::GridPtrVec &grids) const
Run this volume executable binary on target volumes.
size_t getActiveTileStreamingGrainSize() const
VolumeExecutable(const VolumeExecutable &other)
Copy constructor. Shares the LLVM constructs but deep copies the settings. Multiple copies of an exec...
Definition: Compiler.h:31
CoreType
Definition: Tokens.h:32
@ ALL
Definition: IndexIterator.h:43
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:103
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:514
Index32 Index
Definition: Types.h:54
Definition: Exceptions.h:13
A Tree is the highest concrete (non-abstract) node in the entire AX AST hierarchy....
Definition: AST.h:562
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202