1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file codegen/VolumeFunctions.cc
5 ///
6 /// @authors Nick Avramoussis, Richard Jones
7 ///
8 /// @brief Contains the function objects that define the functions used in
9 /// volume compute function generation, to be inserted into the FunctionRegistry.
10 /// These define the functions available when operating on volumes.
11 /// Also includes the definitions for the volume value retrieval and setting.
12 ///
13
14 #include "Functions.h"
15 #include "FunctionTypes.h"
16 #include "Types.h"
17 #include "Utils.h"
18
19 #include "openvdb_ax/compiler/CompilerOptions.h"
20 #include "openvdb_ax/Exceptions.h"
21
22 #include <openvdb/version.h>
23
24 #include <unordered_map>
25 #include <cstdlib>
26 #include <cstring>
27
28 namespace openvdb {
29 OPENVDB_USE_VERSION_NAMESPACE
30 namespace OPENVDB_VERSION_NAME {
31
32 namespace ax {
33 namespace codegen {
34
35
36 namespace {
37
38 #define OPENVDB_AX_CHECK_MODULE_CONTEXT(B) \
39 { \
40 const llvm::Function* F = B.GetInsertBlock()->getParent(); \
41 const llvm::Module* M = F ? F->getParent() : nullptr; \
42 if (!M || M->getName() != "ax.volume.module") { \
43 OPENVDB_THROW(AXCompilerError, "Function \"" << (F ? F->getName().str() : "unknown") << \
44 "\" cannot be called for the current target:\"" << (M ? M->getName().str() : "unknown") << \
45 "\". This function only runs on OpenVDB Grids (not OpenVDB Point Grids)."); \
46 } \
47 }
48
49 }
50
axcoordtooffset(const FunctionOptions & op)51 inline FunctionGroup::UniquePtr axcoordtooffset(const FunctionOptions& op)
52 {
53 using LeafNodeT = openvdb::BoolGrid::TreeType::LeafNodeType;
54
55 /// @warning This function assumes that the node in question is a LeafNode!
56 /// This means that the result of this method is ONLY correct if the
57 /// origin points to an existing leaf node, OR if the offset is zero.
58 /// Currently the VolumeExectuable processes non-leaf nodes (active tiles)
59 /// individually, so the offset for these nodes is always zero. Should
60 /// we need to processes a non-leaf node with a non-zero offset, this
61 /// function should be extended to take a "level" param from the parent
62 /// which identifies the node level and can thus be used to call the
63 /// appropriate offset logic.
64
65 static auto generate = [](const std::vector<llvm::Value*>& args,
66 llvm::IRBuilder<>& B) -> llvm::Value*
67 {
68 assert(args.size() == 1);
69 OPENVDB_AX_CHECK_MODULE_CONTEXT(B);
70 llvm::Value* x = B.CreateConstGEP2_64(args[0], 0, 0);
71 llvm::Value* y = B.CreateConstGEP2_64(args[0], 0, 1);
72 llvm::Value* z = B.CreateConstGEP2_64(args[0], 0, 2);
73 llvm::Value* dimmin1 = LLVMType<int32_t>::get(B.getContext(), int32_t(LeafNodeT::DIM-1u));
74 llvm::Value* l2d2 = LLVMType<int32_t>::get(B.getContext(), int32_t(2*LeafNodeT::LOG2DIM));
75 llvm::Value* l2d = LLVMType<int32_t>::get(B.getContext(), int32_t(LeafNodeT::LOG2DIM));
76
77 // ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
78 x = B.CreateLoad(x);
79 x = binaryOperator(x, dimmin1, ast::tokens::BITAND, B);
80 x = binaryOperator(x, l2d2, ast::tokens::SHIFTLEFT, B);
81
82 // ((xyz[1] & (DIM-1u)) << Log2Dim)
83 y = B.CreateLoad(y);
84 y = binaryOperator(y, dimmin1, ast::tokens::BITAND, B);
85 y = binaryOperator(y, l2d, ast::tokens::SHIFTLEFT, B);
86
87 // (xyz[2] & (DIM-1u))
88 z = B.CreateLoad(z);
89 z = binaryOperator(z, dimmin1, ast::tokens::BITAND, B);
90
91 return
92 binaryOperator(z,
93 binaryOperator(x, y, ast::tokens::PLUS, B),
94 ast::tokens::PLUS, B);
95 };
96
97 static auto coordtooffset =
98 [](const openvdb::math::Vec3<int32_t>* iscoord)
99 {
100 const openvdb::Coord* ijk = reinterpret_cast<const openvdb::Coord*>(iscoord);
101 return int32_t(LeafNodeT::coordToOffset(*ijk));
102 };
103
104 return FunctionBuilder("coordtooffset")
105 .addSignature<int32_t(const openvdb::math::Vec3<int32_t>*)>(generate,
106 (int32_t(*)(const openvdb::math::Vec3<int32_t>*))(coordtooffset))
107 .setArgumentNames({"coord"})
108 .addFunctionAttribute(llvm::Attribute::ReadOnly)
109 .addFunctionAttribute(llvm::Attribute::NoRecurse)
110 .addFunctionAttribute(llvm::Attribute::NoUnwind)
111 .addFunctionAttribute(llvm::Attribute::AlwaysInline)
112 .setConstantFold(op.mConstantFoldCBindings)
113 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
114 .setDocumentation("Return the linear table offset of the given global or local coordinates.")
115 .get();
116 }
117
axoffsettocoord(const FunctionOptions & op)118 inline FunctionGroup::UniquePtr axoffsettocoord(const FunctionOptions& op)
119 {
120 using LeafNodeT = openvdb::BoolGrid::TreeType::LeafNodeType;
121
122 /// @warning This function assumes that the node in question is a LeafNode!
123 /// This means that the result of this method is ONLY correct if the
124 /// origin points to an existing leaf node, OR if the offset is zero.
125 /// Currently the VolumeExectuable processes non-leaf nodes (active tiles)
126 /// individually, so the offset for these nodes is always zero. Should
127 /// we need to processes a non-leaf node with a non-zero offset, this
128 /// function should be extended to take a "level" param from the parent
129 /// which identifies the node level and can thus be used to call the
130 /// appropriate offset logic.
131
132 static auto generate = [](const std::vector<llvm::Value*>& args,
133 llvm::IRBuilder<>& B) -> llvm::Value*
134 {
135 assert(args.size() == 2);
136 OPENVDB_AX_CHECK_MODULE_CONTEXT(B);
137
138 llvm::Value* ijk = args[0];
139 llvm::Value* offset = args[1];
140
141 llvm::Value* l2d2 = LLVMType<int32_t>::get(B.getContext(), int32_t(2*LeafNodeT::LOG2DIM));
142 llvm::Value* l2d = LLVMType<int32_t>::get(B.getContext(), int32_t(LeafNodeT::LOG2DIM));
143
144 // (offset >> 2*Log2Dim)
145 llvm::Value* x = binaryOperator(offset, l2d2, ast::tokens::SHIFTRIGHT, B);
146 B.CreateStore(x, B.CreateConstGEP2_64(ijk, 0, 0));
147
148 // (offset &= ((1<<2*Log2Dim)-1))
149 static constexpr int32_t ymask = ((1<<2*LeafNodeT::LOG2DIM)-1);
150 offset = binaryOperator(offset, B.getInt32(ymask), ast::tokens::BITAND, B);
151
152 // (n >> Log2Dim)
153 llvm::Value* y = binaryOperator(offset, l2d, ast::tokens::SHIFTRIGHT, B);
154 B.CreateStore(y, B.CreateConstGEP2_64(ijk, 0, 1));
155
156 // (n & ((1<<Log2Dim)-1))
157 static constexpr int32_t zmask = ((1<<LeafNodeT::LOG2DIM)-1);
158 llvm::Value* z = binaryOperator(offset, B.getInt32(zmask), ast::tokens::BITAND, B);
159 B.CreateStore(z, B.CreateConstGEP2_64(ijk, 0, 2));
160 return nullptr;
161 };
162
163 static auto offsetToCoord =
164 [](openvdb::math::Vec3<int32_t>* out, const int32_t offset)
165 {
166 *out = LeafNodeT::offsetToLocalCoord(offset).asVec3i();
167 };
168
169 using OffsetToCoordT = void(openvdb::math::Vec3<int32_t>*, const int32_t);
170
171 return FunctionBuilder("offsettocoord")
172 .addSignature<OffsetToCoordT, true>(generate, (OffsetToCoordT*)(offsetToCoord))
173 .setArgumentNames({"offset"})
174 .addParameterAttribute(0, llvm::Attribute::NoAlias)
175 .addParameterAttribute(0, llvm::Attribute::WriteOnly)
176 .addParameterAttribute(0, llvm::Attribute::NoCapture)
177 .addFunctionAttribute(llvm::Attribute::NoUnwind)
178 .addFunctionAttribute(llvm::Attribute::NoRecurse)
179 .addFunctionAttribute(llvm::Attribute::AlwaysInline)
180 .setConstantFold(op.mConstantFoldCBindings)
181 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
182 .setDocumentation("")
183 .get();
184 }
185
axoffsettoglobalcoord(const FunctionOptions & op)186 inline FunctionGroup::UniquePtr axoffsettoglobalcoord(const FunctionOptions& op)
187 {
188 using LeafNodeT = openvdb::BoolGrid::TreeType::LeafNodeType;
189
190 /// @warning This function assumes that the node in question is a LeafNode!
191 /// This means that the result of this method is ONLY correct if the
192 /// origin points to an existing leaf node, OR if the offset is zero.
193 /// Currently the VolumeExectuable processes non-leaf nodes (active tiles)
194 /// individually, so the offset for these nodes is always zero. Should
195 /// we need to processes a non-leaf node with a non-zero offset, this
196 /// function should be extended to take a "level" param from the parent
197 /// which identifies the node level and can thus be used to call the
198 /// appropriate offset logic.
199
200 auto generate = [op](const std::vector<llvm::Value*>& args,
201 llvm::IRBuilder<>& B) -> llvm::Value*
202 {
203 assert(args.size() == 3);
204 OPENVDB_AX_CHECK_MODULE_CONTEXT(B);
205
206 llvm::Value* result = args[0];
207 llvm::Value* offset = args[1];
208 llvm::Value* origin = args[2];
209
210 llvm::Value* local = axoffsettocoord(op)->execute({offset}, B);
211
212 for (size_t i = 0; i < 3; ++i){
213 llvm::Value* lx = B.CreateConstGEP2_64(local, 0, i);
214 llvm::Value* ox = B.CreateConstGEP2_64(origin, 0, i);
215 ox = binaryOperator(B.CreateLoad(ox), B.CreateLoad(lx), ast::tokens::PLUS, B);
216 B.CreateStore(ox, B.CreateConstGEP2_64(result, 0, i));
217 }
218
219 return nullptr;
220 };
221
222 static auto offsetToGlobalCoord =
223 [](openvdb::math::Vec3<int32_t>* out, const int32_t offset, const openvdb::math::Vec3<int32_t>* in)
224 {
225 auto coord = LeafNodeT::offsetToLocalCoord(offset);
226 out->x() = coord.x() + in->x();
227 out->y() = coord.y() + in->y();
228 out->z() = coord.z() + in->z();
229 };
230
231 using OffsetToGlobalCoordT = void(openvdb::math::Vec3<int32_t>*,const int32_t,const openvdb::math::Vec3<int32_t>*);
232
233 return FunctionBuilder("offsettoglobalcoord")
234 .addSignature<OffsetToGlobalCoordT, true>(generate, (OffsetToGlobalCoordT*)(offsetToGlobalCoord))
235 .setArgumentNames({"offset", "coord"})
236 .addParameterAttribute(0, llvm::Attribute::NoAlias)
237 .addParameterAttribute(0, llvm::Attribute::WriteOnly)
238 .addParameterAttribute(2, llvm::Attribute::NoAlias)
239 .addParameterAttribute(2, llvm::Attribute::ReadOnly)
240 .addFunctionAttribute(llvm::Attribute::NoUnwind)
241 .addFunctionAttribute(llvm::Attribute::AlwaysInline)
242 .setConstantFold(op.mConstantFoldCBindings)
243 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
244 .setDocumentation("")
245 .get();
246 }
247
axindextoworld(const FunctionOptions & op)248 inline FunctionGroup::UniquePtr axindextoworld(const FunctionOptions& op)
249 {
250 static auto indexToWorld =
251 [](openvdb::math::Vec3<double>* out,
252 const openvdb::math::Vec3<int32_t>* coord,
253 const void* transform)
254 {
255 const openvdb::math::Transform* const transformPtr =
256 static_cast<const openvdb::math::Transform*>(transform);
257 const openvdb::Coord* ijk = reinterpret_cast<const openvdb::Coord*>(coord);
258 *out = transformPtr->indexToWorld(*ijk);
259 };
260
261 using IndexToWorldT = void(openvdb::math::Vec3<double>*, const openvdb::math::Vec3<int32_t>*, const void*);
262
263 return FunctionBuilder("indextoworld")
264 .addSignature<IndexToWorldT, true>((IndexToWorldT*)(indexToWorld))
265 .setArgumentNames({"coord", "transform"})
266 .addParameterAttribute(0, llvm::Attribute::NoAlias)
267 .addParameterAttribute(0, llvm::Attribute::WriteOnly)
268 .addParameterAttribute(1, llvm::Attribute::NoAlias)
269 .addParameterAttribute(1, llvm::Attribute::ReadOnly)
270 .addFunctionAttribute(llvm::Attribute::NoUnwind)
271 .addFunctionAttribute(llvm::Attribute::AlwaysInline)
272 .setConstantFold(false)
273 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
274 .setDocumentation("Converted the given index space coordiante to a world space value based on the currently executing volume.")
275 .get();
276 }
277
axgetcoord(const FunctionOptions & op)278 inline FunctionGroup::UniquePtr axgetcoord(const FunctionOptions& op)
279 {
280 auto generate = [op](const std::vector<llvm::Value*>&,
281 llvm::IRBuilder<>& B) -> llvm::Value*
282 {
283 // Pull out parent function arguments
284 llvm::Function* compute = B.GetInsertBlock()->getParent();
285 OPENVDB_AX_CHECK_MODULE_CONTEXT(B);
286 llvm::Value* origin = extractArgument(compute, "origin");
287 llvm::Value* offset = extractArgument(compute, "offset");
288 return axoffsettoglobalcoord(op)->execute({offset, origin}, B);
289 };
290
291 return FunctionBuilder("getcoord")
292 .addSignature<openvdb::math::Vec3<int32_t>*()>(generate)
293 .setEmbedIR(true)
294 .setConstantFold(false)
295 .addDependency("offsettoglobalcoord")
296 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
297 .setDocumentation("Returns the current voxel's ijk index space coordiante.")
298 .get();
299 }
300
301 template <size_t Index>
axgetcoord(const FunctionOptions & op)302 inline FunctionGroup::UniquePtr axgetcoord(const FunctionOptions& op)
303 {
304 static_assert(Index <= 2, "Invalid index for axgetcoord");
305
306 auto generate = [op](const std::vector<llvm::Value*>&,
307 llvm::IRBuilder<>& B) -> llvm::Value*
308 {
309 llvm::Value* coord = axgetcoord(op)->execute({}, B);
310 return B.CreateLoad(B.CreateConstGEP2_64(coord, 0, Index));
311 };
312
313 return FunctionBuilder((Index == 0 ? "getcoordx" : Index == 1 ? "getcoordy" : "getcoordz"))
314 .addSignature<int32_t()>(generate)
315 .setEmbedIR(true)
316 .setConstantFold(false)
317 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
318 .addDependency("getcoord")
319 .setDocumentation((
320 Index == 0 ? "Returns the current voxel's X index value in index space as an integer." :
321 Index == 1 ? "Returns the current voxel's Y index value in index space as an integer." :
322 "Returns the current voxel's Z index value in index space as an integer."))
323 .get();
324 }
325
axgetvoxelpws(const FunctionOptions & op)326 inline FunctionGroup::UniquePtr axgetvoxelpws(const FunctionOptions& op)
327 {
328 auto generate = [op](const std::vector<llvm::Value*>&,
329 llvm::IRBuilder<>& B) -> llvm::Value*
330 {
331 OPENVDB_AX_CHECK_MODULE_CONTEXT(B);
332 llvm::Function* compute = B.GetInsertBlock()->getParent();
333 llvm::Value* transform = extractArgument(compute, "transforms");
334 llvm::Value* wi = extractArgument(compute, "write_index");
335 transform = B.CreateGEP(transform, wi);
336 transform = B.CreateLoad(transform);
337 llvm::Value* coord = axgetcoord(op)->execute({}, B);
338 return axindextoworld(op)->execute({coord, transform}, B);
339 };
340
341 return FunctionBuilder("getvoxelpws")
342 .addSignature<openvdb::math::Vec3<double>*()>(generate)
343 .setEmbedIR(true)
344 .setConstantFold(false)
345 .addDependency("getcoord")
346 .addDependency("indextoworld")
347 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
348 .setDocumentation("Returns the current voxel's position in world space as a vector float.")
349 .get();
350 }
351
axisactive(const FunctionOptions & op)352 inline FunctionGroup::UniquePtr axisactive(const FunctionOptions& op)
353 {
354 static auto generate = [](const std::vector<llvm::Value*>&,
355 llvm::IRBuilder<>& B) -> llvm::Value*
356 {
357 OPENVDB_AX_CHECK_MODULE_CONTEXT(B);
358 // Pull out parent function arguments
359 llvm::Function* compute = B.GetInsertBlock()->getParent();
360 return extractArgument(compute, "active");
361 };
362
363 return FunctionBuilder("isactive")
364 .addSignature<bool()>(generate)
365 .setEmbedIR(true)
366 .setConstantFold(false)
367 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
368 .setDocumentation("Returns whether the current voxel or tile is active.")
369 .get();
370 }
371
axsetvoxel(const FunctionOptions & op)372 inline FunctionGroup::UniquePtr axsetvoxel(const FunctionOptions& op)
373 {
374 static auto setvoxelptr =
375 [](void* accessor,
376 const openvdb::math::Vec3<int32_t>* coord,
377 const int32_t level,
378 const bool ison,
379 const auto value)
380 {
381 using ValueType = typename std::remove_const
382 <typename std::remove_pointer
383 <decltype(value)>::type>::type;
384 using GridType = typename openvdb::BoolGrid::ValueConverter<ValueType>::Type;
385 using RootNodeType = typename GridType::TreeType::RootNodeType;
386 using AccessorType = typename GridType::Accessor;
387
388 assert(accessor);
389 assert(coord);
390
391 // set value only to avoid changing topology
392 const openvdb::Coord* ijk = reinterpret_cast<const openvdb::Coord*>(coord);
393 AccessorType* const accessorPtr = static_cast<AccessorType*>(accessor);
394
395 if (level != -1) {
396 assert(level >= 0);
397 accessorPtr->addTile(Index(level), *ijk, *value, ison);
398 }
399 else {
400 // Check the depth to avoid creating voxel topology for higher levels
401 // @note This option is not configurable outside of the executable
402 const int depth = accessorPtr->getValueDepth(*ijk);
403 if (depth == static_cast<int>(RootNodeType::LEVEL)) {
404 // voxel/leaf level
405 assert(accessorPtr->probeConstLeaf(*ijk));
406 if (ison) accessorPtr->setValueOn(*ijk, *value);
407 else accessorPtr->setValueOff(*ijk, *value);
408 }
409 else {
410 // If the current depth is not the maximum (i.e voxel/leaf level) then
411 // we're iterating over tiles of an internal node (NodeT0 is the leaf level).
412 // We can't call setValueOnly or other variants as this will forcer voxel
413 // topology to be created. Whilst the VolumeExecutables runs in such a
414 // way that this is safe, it's not desirable; we just want to change the
415 // tile value. There is no easy way to do this; we have to set a new tile
416 // with the same active state.
417 // @warning This code assume that getValueDepth() is always called to force
418 // a node cache.
419 using NodeT1 = typename AccessorType::NodeT1;
420 using NodeT2 = typename AccessorType::NodeT2;
421 if (NodeT1* node = accessorPtr->template getNode<NodeT1>()) {
422 const openvdb::Index index = node->coordToOffset(*ijk);
423 assert(node->isChildMaskOff(index));
424 node->addTile(index, *value, ison);
425 }
426 else if (NodeT2* node = accessorPtr->template getNode<NodeT2>()) {
427 const openvdb::Index index = node->coordToOffset(*ijk);
428 assert(node->isChildMaskOff(index));
429 node->addTile(index, *value, ison);
430 }
431 else {
432 const int level = RootNodeType::LEVEL - depth;
433 accessorPtr->addTile(level, *ijk, *value, ison);
434 }
435 }
436 }
437 };
438
439 static auto setvoxelstr =
440 [](void* accessor,
441 const openvdb::math::Vec3<int32_t>* coord,
442 const int32_t level,
443 const bool ison,
444 codegen::String* value)
445 {
446 const std::string copy(value->str());
447 setvoxelptr(accessor, coord, level, ison, ©);
448 };
449
450 static auto setvoxel =
451 [](void* accessor,
452 const openvdb::math::Vec3<int32_t>* coord,
453 const int32_t level,
454 const bool ison,
455 const auto value) {
456 setvoxelptr(accessor, coord, level, ison, &value);
457 };
458
459 using SetVoxelD = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const double);
460 using SetVoxelF = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const float);
461 using SetVoxelI64 = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const int64_t);
462 using SetVoxelI32 = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const int32_t);
463 using SetVoxelI16 = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const int16_t);
464 using SetVoxelB = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const bool);
465 using SetVoxelV2D = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Vec2<double>*);
466 using SetVoxelV2F = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Vec2<float>*);
467 using SetVoxelV2I = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Vec2<int32_t>*);
468 using SetVoxelV3D = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Vec3<double>*);
469 using SetVoxelV3F = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Vec3<float>*);
470 using SetVoxelV3I = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Vec3<int32_t>*);
471 using SetVoxelV4D = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Vec4<double>*);
472 using SetVoxelV4F = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Vec4<float>*);
473 using SetVoxelV4I = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Vec4<int32_t>*);
474 using SetVoxelM3D = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Mat3<double>*);
475 using SetVoxelM3F = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Mat3<float>*);
476 using SetVoxelM4D = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Mat4<double>*);
477 using SetVoxelM4F = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, const openvdb::math::Mat4<float>*);
478 using SetVoxelStr = void(void*, const openvdb::math::Vec3<int32_t>*, const int32_t, const bool, codegen::String*);
479
480 return FunctionBuilder("setvoxel")
481 .addSignature<SetVoxelD>((SetVoxelD*)(setvoxel))
482 .addSignature<SetVoxelF>((SetVoxelF*)(setvoxel))
483 .addSignature<SetVoxelI64>((SetVoxelI64*)(setvoxel))
484 .addSignature<SetVoxelI32>((SetVoxelI32*)(setvoxel))
485 .addSignature<SetVoxelI16>((SetVoxelI16*)(setvoxel))
486 .addSignature<SetVoxelB>((SetVoxelB*)(setvoxel))
487 .addParameterAttribute(0, llvm::Attribute::NoAlias)
488 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
489 .addParameterAttribute(0, llvm::Attribute::NoCapture)
490 .addParameterAttribute(1, llvm::Attribute::ReadOnly)
491 .addParameterAttribute(1, llvm::Attribute::NoCapture)
492 .addFunctionAttribute(llvm::Attribute::NoUnwind)
493 .addFunctionAttribute(llvm::Attribute::NoRecurse)
494 .setConstantFold(false)
495 .addSignature<SetVoxelV2D>((SetVoxelV2D*)(setvoxelptr))
496 .addSignature<SetVoxelV2F>((SetVoxelV2F*)(setvoxelptr))
497 .addSignature<SetVoxelV2I>((SetVoxelV2I*)(setvoxelptr))
498 .addSignature<SetVoxelV3D>((SetVoxelV3D*)(setvoxelptr))
499 .addSignature<SetVoxelV3F>((SetVoxelV3F*)(setvoxelptr))
500 .addSignature<SetVoxelV3I>((SetVoxelV3I*)(setvoxelptr))
501 .addSignature<SetVoxelV4D>((SetVoxelV4D*)(setvoxelptr))
502 .addSignature<SetVoxelV4F>((SetVoxelV4F*)(setvoxelptr))
503 .addSignature<SetVoxelV4I>((SetVoxelV4I*)(setvoxelptr))
504 .addSignature<SetVoxelM3D>((SetVoxelM3D*)(setvoxelptr))
505 .addSignature<SetVoxelM3F>((SetVoxelM3F*)(setvoxelptr))
506 .addSignature<SetVoxelM4D>((SetVoxelM4D*)(setvoxelptr))
507 .addSignature<SetVoxelM4F>((SetVoxelM4F*)(setvoxelptr))
508 .addSignature<SetVoxelStr>((SetVoxelStr*)(setvoxelstr))
509 .addParameterAttribute(0, llvm::Attribute::NoAlias)
510 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
511 .addParameterAttribute(0, llvm::Attribute::NoCapture)
512 .addParameterAttribute(1, llvm::Attribute::ReadOnly)
513 .addParameterAttribute(1, llvm::Attribute::NoCapture)
514 .addParameterAttribute(4, llvm::Attribute::NoAlias)
515 .addParameterAttribute(4, llvm::Attribute::ReadOnly)
516 .addParameterAttribute(4, llvm::Attribute::NoCapture)
517 .addFunctionAttribute(llvm::Attribute::NoUnwind)
518 .addFunctionAttribute(llvm::Attribute::NoRecurse)
519 .setConstantFold(false)
520 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
521 .setDocumentation("Internal function for setting the value of a voxel.")
522 .get();
523 }
524
axgetvoxel(const FunctionOptions & op)525 inline FunctionGroup::UniquePtr axgetvoxel(const FunctionOptions& op)
526 {
527 static auto getvoxel =
528 [](void* accessor,
529 const openvdb::math::Vec3<int32_t>* coord,
530 auto value)
531 {
532 using ValueType = typename std::remove_pointer<decltype(value)>::type;
533 using GridType = typename openvdb::BoolGrid::ValueConverter<ValueType>::Type;
534 using AccessorType = typename GridType::Accessor;
535
536 assert(accessor);
537 assert(coord);
538 assert(value);
539
540 const openvdb::Coord* ijk = reinterpret_cast<const openvdb::Coord*>(coord);
541 (*value) = static_cast<const AccessorType*>(accessor)->getValue(*ijk);
542 };
543
544 static auto getvoxelstr =
545 [](void* accessor,
546 const openvdb::math::Vec3<int32_t>* coord,
547 codegen::String* value)
548 {
549 using GridType = openvdb::BoolGrid::ValueConverter<std::string>::Type;
550 using AccessorType = GridType::Accessor;
551
552 assert(accessor);
553 assert(coord);
554 assert(value);
555
556 const openvdb::Coord* ijk = reinterpret_cast<const openvdb::Coord*>(coord);
557 const std::string& str = static_cast<const AccessorType*>(accessor)->getValue(*ijk);
558 // Copy the string to AX's required representation
559 *value = str;
560 };
561
562 static auto getvoxel_s2t =
563 [](void* accessor,
564 void* sourceTransform,
565 void* targetTransform,
566 const openvdb::math::Vec3<int32_t>* origin,
567 const int32_t offset,
568 auto value)
569 {
570 using ValueType = typename std::remove_pointer<decltype(value)>::type;
571 using GridType = typename openvdb::BoolGrid::ValueConverter<ValueType>::Type;
572 using LeafNodeT = typename GridType::TreeType::LeafNodeType;
573 using AccessorType = typename GridType::Accessor;
574
575 assert(accessor);
576 assert(origin);
577 assert(sourceTransform);
578 assert(targetTransform);
579
580 const AccessorType* const accessorPtr = static_cast<const AccessorType*>(accessor);
581 const openvdb::math::Transform* const sourceTransformPtr =
582 static_cast<const openvdb::math::Transform*>(sourceTransform);
583 const openvdb::math::Transform* const targetTransformPtr =
584 static_cast<const openvdb::math::Transform*>(targetTransform);
585
586 const openvdb::Coord* ijk = reinterpret_cast<const openvdb::Coord*>(origin);
587 auto coord = *ijk + LeafNodeT::offsetToLocalCoord(offset);
588 coord = targetTransformPtr->worldToIndexCellCentered(sourceTransformPtr->indexToWorld(coord));
589 (*value) = accessorPtr->getValue(coord);
590 };
591
592 static auto getvoxelstr_s2t =
593 [](void* accessor,
594 void* sourceTransform,
595 void* targetTransform,
596 const openvdb::math::Vec3<int32_t>* origin,
597 const int32_t offset,
598 codegen::String* value)
599 {
600 using GridType = typename openvdb::BoolGrid::ValueConverter<std::string>::Type;
601 using LeafNodeT = typename GridType::TreeType::LeafNodeType;
602 using AccessorType = typename GridType::Accessor;
603
604 assert(accessor);
605 assert(origin);
606 assert(sourceTransform);
607 assert(targetTransform);
608
609 const AccessorType* const accessorPtr = static_cast<const AccessorType*>(accessor);
610 const openvdb::math::Transform* const sourceTransformPtr =
611 static_cast<const openvdb::math::Transform*>(sourceTransform);
612 const openvdb::math::Transform* const targetTransformPtr =
613 static_cast<const openvdb::math::Transform*>(targetTransform);
614
615 const openvdb::Coord* ijk = reinterpret_cast<const openvdb::Coord*>(origin);
616 auto coord = *ijk + LeafNodeT::offsetToLocalCoord(offset);
617 coord = targetTransformPtr->worldToIndexCellCentered(sourceTransformPtr->indexToWorld(coord));
618 const std::string& str = accessorPtr->getValue(coord);
619 // Copy the string to AX's required representation
620 *value = str;
621 };
622
623 using GetVoxelS2T_D = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, double*);
624 using GetVoxelS2T_F = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, float*);
625 using GetVoxelS2T_I64 = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, int64_t*);
626 using GetVoxelS2T_I32 = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, int32_t*);
627 using GetVoxelS2T_I16 = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, int16_t*);
628 using GetVoxelS2T_B = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, bool*);
629 using GetVoxelS2T_V2D = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Vec2<double>*);
630 using GetVoxelS2T_V2F = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Vec2<float>*);
631 using GetVoxelS2T_V2I = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Vec2<int32_t>*);
632 using GetVoxelS2T_V3D = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Vec3<double>*);
633 using GetVoxelS2T_V3F = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Vec3<float>*);
634 using GetVoxelS2T_V3I = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Vec3<int32_t>*);
635 using GetVoxelS2T_V4D = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Vec4<double>*);
636 using GetVoxelS2T_V4F = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Vec4<float>*);
637 using GetVoxelS2T_V4I = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Vec4<int32_t>*);
638 using GetVoxelS2T_M3D = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Mat3<double>*);
639 using GetVoxelS2T_M3F = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Mat3<float>*);
640 using GetVoxelS2T_M4D = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Mat4<double>*);
641 using GetVoxelS2T_M4F = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, openvdb::math::Mat4<float>*);
642 using GetVoxelS2T_Str = void(void*, void*, void*, const openvdb::math::Vec3<int32_t>*, int32_t, codegen::String*);
643
644 using GetVoxelD = void(void*, const openvdb::math::Vec3<int32_t>*, double*);
645 using GetVoxelF = void(void*, const openvdb::math::Vec3<int32_t>*, float*);
646 using GetVoxelI64 = void(void*, const openvdb::math::Vec3<int32_t>*, int64_t*);
647 using GetVoxelI32 = void(void*, const openvdb::math::Vec3<int32_t>*, int32_t*);
648 using GetVoxelI16 = void(void*, const openvdb::math::Vec3<int32_t>*, int16_t*);
649 using GetVoxelB = void(void*, const openvdb::math::Vec3<int32_t>*, bool*);
650 using GetVoxelV2D = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Vec2<double>*);
651 using GetVoxelV2F = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Vec2<float>*);
652 using GetVoxelV2I = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Vec2<int32_t>*);
653 using GetVoxelV3D = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Vec3<double>*);
654 using GetVoxelV3F = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Vec3<float>*);
655 using GetVoxelV3I = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Vec3<int32_t>*);
656 using GetVoxelV4D = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Vec4<double>*);
657 using GetVoxelV4F = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Vec4<float>*);
658 using GetVoxelV4I = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Vec4<int32_t>*);
659 using GetVoxelM3D = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Mat3<double>*);
660 using GetVoxelM3F = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Mat3<float>*);
661 using GetVoxelM4D = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Mat4<double>*);
662 using GetVoxelM4F = void(void*, const openvdb::math::Vec3<int32_t>*, openvdb::math::Mat4<float>*);
663 using GetVoxelStr = void(void*, const openvdb::math::Vec3<int32_t>*, codegen::String*);
664
665 return FunctionBuilder("getvoxel")
666 .addSignature<GetVoxelD>((GetVoxelD*)(getvoxel))
667 .addSignature<GetVoxelF>((GetVoxelF*)(getvoxel))
668 .addSignature<GetVoxelI64>((GetVoxelI64*)(getvoxel))
669 .addSignature<GetVoxelI32>((GetVoxelI32*)(getvoxel))
670 .addSignature<GetVoxelI16>((GetVoxelI16*)(getvoxel))
671 .addSignature<GetVoxelB>((GetVoxelB*)(getvoxel))
672 .addSignature<GetVoxelV2D>((GetVoxelV2D*)(getvoxel))
673 .addSignature<GetVoxelV2F>((GetVoxelV2F*)(getvoxel))
674 .addSignature<GetVoxelV2I>((GetVoxelV2I*)(getvoxel))
675 .addSignature<GetVoxelV3D>((GetVoxelV3D*)(getvoxel))
676 .addSignature<GetVoxelV3F>((GetVoxelV3F*)(getvoxel))
677 .addSignature<GetVoxelV3I>((GetVoxelV3I*)(getvoxel))
678 .addSignature<GetVoxelV4D>((GetVoxelV4D*)(getvoxel))
679 .addSignature<GetVoxelV4F>((GetVoxelV4F*)(getvoxel))
680 .addSignature<GetVoxelV4I>((GetVoxelV4I*)(getvoxel))
681 .addSignature<GetVoxelM3F>((GetVoxelM3F*)(getvoxel))
682 .addSignature<GetVoxelM3D>((GetVoxelM3D*)(getvoxel))
683 .addSignature<GetVoxelM4F>((GetVoxelM4F*)(getvoxel))
684 .addSignature<GetVoxelM4D>((GetVoxelM4D*)(getvoxel))
685 .addSignature<GetVoxelStr>((GetVoxelStr*)(getvoxelstr))
686 .addParameterAttribute(0, llvm::Attribute::NoAlias)
687 .addParameterAttribute(1, llvm::Attribute::NoAlias)
688 .addParameterAttribute(1, llvm::Attribute::ReadOnly)
689 .addParameterAttribute(2, llvm::Attribute::WriteOnly)
690 .addParameterAttribute(2, llvm::Attribute::NoAlias)
691 .addFunctionAttribute(llvm::Attribute::NoUnwind)
692 .addFunctionAttribute(llvm::Attribute::NoRecurse)
693 .setConstantFold(false)
694 .addSignature<GetVoxelS2T_D>((GetVoxelS2T_D*)(getvoxel_s2t))
695 .addSignature<GetVoxelS2T_F>((GetVoxelS2T_F*)(getvoxel_s2t))
696 .addSignature<GetVoxelS2T_I64>((GetVoxelS2T_I64*)(getvoxel_s2t))
697 .addSignature<GetVoxelS2T_I32>((GetVoxelS2T_I32*)(getvoxel_s2t))
698 .addSignature<GetVoxelS2T_I16>((GetVoxelS2T_I16*)(getvoxel_s2t))
699 .addSignature<GetVoxelS2T_B>((GetVoxelS2T_B*)(getvoxel_s2t))
700 .addSignature<GetVoxelS2T_V2D>((GetVoxelS2T_V2D*)(getvoxel_s2t))
701 .addSignature<GetVoxelS2T_V2F>((GetVoxelS2T_V2F*)(getvoxel_s2t))
702 .addSignature<GetVoxelS2T_V2I>((GetVoxelS2T_V2I*)(getvoxel_s2t))
703 .addSignature<GetVoxelS2T_V3D>((GetVoxelS2T_V3D*)(getvoxel_s2t))
704 .addSignature<GetVoxelS2T_V3F>((GetVoxelS2T_V3F*)(getvoxel_s2t))
705 .addSignature<GetVoxelS2T_V3I>((GetVoxelS2T_V3I*)(getvoxel_s2t))
706 .addSignature<GetVoxelS2T_V4D>((GetVoxelS2T_V4D*)(getvoxel_s2t))
707 .addSignature<GetVoxelS2T_V4F>((GetVoxelS2T_V4F*)(getvoxel_s2t))
708 .addSignature<GetVoxelS2T_V4I>((GetVoxelS2T_V4I*)(getvoxel_s2t))
709 .addSignature<GetVoxelS2T_M3F>((GetVoxelS2T_M3F*)(getvoxel_s2t))
710 .addSignature<GetVoxelS2T_M3D>((GetVoxelS2T_M3D*)(getvoxel_s2t))
711 .addSignature<GetVoxelS2T_M4F>((GetVoxelS2T_M4F*)(getvoxel_s2t))
712 .addSignature<GetVoxelS2T_M4D>((GetVoxelS2T_M4D*)(getvoxel_s2t))
713 .addSignature<GetVoxelS2T_Str>((GetVoxelS2T_Str*)(getvoxelstr_s2t))
714 .addParameterAttribute(0, llvm::Attribute::NoAlias)
715 .addParameterAttribute(1, llvm::Attribute::NoAlias)
716 .addParameterAttribute(1, llvm::Attribute::ReadOnly)
717 .addParameterAttribute(2, llvm::Attribute::ReadOnly)
718 .addParameterAttribute(3, llvm::Attribute::WriteOnly)
719 .addParameterAttribute(3, llvm::Attribute::NoAlias)
720 .addFunctionAttribute(llvm::Attribute::NoUnwind)
721 .addFunctionAttribute(llvm::Attribute::NoRecurse)
722 .setConstantFold(false)
723 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
724 .setDocumentation("Internal function for setting the value of a voxel.")
725 .get();
726 }
727
axprobevalue(const FunctionOptions & op)728 inline FunctionGroup::UniquePtr axprobevalue(const FunctionOptions& op)
729 {
730 static auto probe =
731 [](void* accessor,
732 const openvdb::math::Vec3<int32_t>* coord,
733 bool* ison,
734 auto value)
735 {
736 using ValueType = typename std::remove_pointer<decltype(value)>::type;
737 using GridType = typename openvdb::BoolGrid::ValueConverter<ValueType>::Type;
738 using AccessorType = typename GridType::Accessor;
739
740 assert(accessor);
741 assert(coord);
742 assert(value);
743 assert(ison);
744
745 const openvdb::Coord* ijk = reinterpret_cast<const openvdb::Coord*>(coord);
746 *ison = static_cast<const AccessorType*>(accessor)->probeValue(*ijk, *value);
747 };
748
749 static auto probestr =
750 [](void* accessor,
751 const openvdb::math::Vec3<int32_t>* coord,
752 bool* ison,
753 codegen::String* value)
754 {
755 using GridType = openvdb::BoolGrid::ValueConverter<std::string>::Type;
756 using AccessorType = GridType::Accessor;
757
758 assert(accessor);
759 assert(coord);
760 assert(value);
761 assert(ison);
762
763 const openvdb::Coord* ijk = reinterpret_cast<const openvdb::Coord*>(coord);
764
765 std::string str;
766 *ison = static_cast<const AccessorType*>(accessor)->probeValue(*ijk, str);
767 // Copy the string to AX's required representation
768 *value = str;
769 };
770
771 using ProbeValueD = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, double*);
772 using ProbeValueF = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, float*);
773 using ProbeValueI64 = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, int64_t*);
774 using ProbeValueI32 = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, int32_t*);
775 using ProbeValueI16 = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, int16_t*);
776 using ProbeValueB = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, bool*);
777 using ProbeValueV2D = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Vec2<double>*);
778 using ProbeValueV2F = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Vec2<float>*);
779 using ProbeValueV2I = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Vec2<int32_t>*);
780 using ProbeValueV3D = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Vec3<double>*);
781 using ProbeValueV3F = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Vec3<float>*);
782 using ProbeValueV3I = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Vec3<int32_t>*);
783 using ProbeValueV4D = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Vec4<double>*);
784 using ProbeValueV4F = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Vec4<float>*);
785 using ProbeValueV4I = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Vec4<int32_t>*);
786 using ProbeValueM3D = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Mat3<double>*);
787 using ProbeValueM3F = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Mat3<float>*);
788 using ProbeValueM4D = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Mat4<double>*);
789 using ProbeValueM4F = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, openvdb::math::Mat4<float>*);
790 using ProbeValueStr = void(void*, const openvdb::math::Vec3<int32_t>*, bool*, codegen::String*);
791
792 return FunctionBuilder("probevalue")
793 .addSignature<ProbeValueD>((ProbeValueD*)(probe))
794 .addSignature<ProbeValueF>((ProbeValueF*)(probe))
795 .addSignature<ProbeValueI64>((ProbeValueI64*)(probe))
796 .addSignature<ProbeValueI32>((ProbeValueI32*)(probe))
797 .addSignature<ProbeValueI16>((ProbeValueI16*)(probe))
798 .addSignature<ProbeValueB>((ProbeValueB*)(probe))
799 .addSignature<ProbeValueV2D>((ProbeValueV2D*)(probe))
800 .addSignature<ProbeValueV2F>((ProbeValueV2F*)(probe))
801 .addSignature<ProbeValueV2I>((ProbeValueV2I*)(probe))
802 .addSignature<ProbeValueV3D>((ProbeValueV3D*)(probe))
803 .addSignature<ProbeValueV3F>((ProbeValueV3F*)(probe))
804 .addSignature<ProbeValueV3I>((ProbeValueV3I*)(probe))
805 .addSignature<ProbeValueV4D>((ProbeValueV4D*)(probe))
806 .addSignature<ProbeValueV4F>((ProbeValueV4F*)(probe))
807 .addSignature<ProbeValueV4I>((ProbeValueV4I*)(probe))
808 .addSignature<ProbeValueM3F>((ProbeValueM3F*)(probe))
809 .addSignature<ProbeValueM3D>((ProbeValueM3D*)(probe))
810 .addSignature<ProbeValueM4F>((ProbeValueM4F*)(probe))
811 .addSignature<ProbeValueM4D>((ProbeValueM4D*)(probe))
812 .addSignature<ProbeValueStr>((ProbeValueStr*)(probestr))
813 .addParameterAttribute(0, llvm::Attribute::NoAlias)
814 .addParameterAttribute(1, llvm::Attribute::NoAlias)
815 .addParameterAttribute(1, llvm::Attribute::ReadOnly)
816 .addParameterAttribute(2, llvm::Attribute::WriteOnly)
817 .addParameterAttribute(2, llvm::Attribute::NoAlias)
818 .addParameterAttribute(3, llvm::Attribute::WriteOnly)
819 .addParameterAttribute(3, llvm::Attribute::NoAlias)
820 .addFunctionAttribute(llvm::Attribute::NoUnwind)
821 .addFunctionAttribute(llvm::Attribute::NoRecurse)
822 .setConstantFold(false)
823 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
824 .setDocumentation("Internal function for getting the value of a voxel and its active state.")
825 .get();
826 }
827
828 ////////////////////////////////////////////////////////////////////////
829 ////////////////////////////////////////////////////////////////////////
830
insertVDBVolumeFunctions(FunctionRegistry & registry,const FunctionOptions * options)831 void insertVDBVolumeFunctions(FunctionRegistry& registry,
832 const FunctionOptions* options)
833 {
834 const bool create = options && !options->mLazyFunctions;
835 auto add = [&](const std::string& name,
836 const FunctionRegistry::ConstructorT creator,
837 const bool internal = false)
838 {
839 if (create) registry.insertAndCreate(name, creator, *options, internal);
840 else registry.insert(name, creator, internal);
841 };
842
843 // volume functions
844
845 add("coordtooffset", axcoordtooffset, true);
846 add("offsettocoord", axoffsettocoord, true);
847 add("offsettoglobalcoord", axoffsettoglobalcoord, true);
848 add("indextoworld", axindextoworld, true);
849
850 add("getcoord", axgetcoord);
851 add("getcoordx", axgetcoord<0>);
852 add("getcoordy", axgetcoord<1>);
853 add("getcoordz", axgetcoord<2>);
854 add("getvoxelpws", axgetvoxelpws);
855 add("isactive", axisactive, true); // needs tests
856
857 add("getvoxel", axgetvoxel, true);
858 add("setvoxel", axsetvoxel, true);
859 add("probevalue", axprobevalue, true);
860 }
861
862 } // namespace codegen
863 } // namespace ax
864 } // namespace OPENVDB_VERSION_NAME
865 } // namespace openvdb
866
867