OpenVDB: openvdb_ax/compiler/VolumeExecutable.h Source File

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