1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file codegen/PointFunctions.cc
5 ///
6 /// @authors Nick Avramoussis, Richard Jones
7 ///
8 /// @brief Contains the function objects that define the functions used in
9 /// point compute function generation, to be inserted into the
10 /// FunctionRegistry. These define the functions available when operating
11 /// on points. Also includes the definitions for the point attribute
12 /// retrieval and setting.
13 ///
14
15 #include "Functions.h"
16 #include "FunctionTypes.h"
17 #include "Types.h"
18 #include "Utils.h"
19 #include "PointLeafLocalData.h"
20
21 #include "../ast/Tokens.h"
22 #include "../compiler/CompilerOptions.h"
23 #include "../Exceptions.h"
24
25 #include <openvdb/openvdb.h>
26 #include <openvdb/points/PointDataGrid.h>
27
28 #include <unordered_map>
29
30 namespace openvdb {
31 OPENVDB_USE_VERSION_NAMESPACE
32 namespace OPENVDB_VERSION_NAME {
33
34 namespace ax {
35 namespace codegen {
36
37 namespace
38 {
39
40 #define OPENVDB_AX_CHECK_MODULE_CONTEXT(B) \
41 { \
42 const llvm::Function* F = B.GetInsertBlock()->getParent(); \
43 const llvm::Module* M = F ? F->getParent() : nullptr; \
44 if (!M || M->getName() != "ax.point.module") { \
45 OPENVDB_THROW(AXCompilerError, "Function \"" << (F ? F->getName().str() : "unknown") << \
46 "\" cannot be called for the current target:\"" << (M ? M->getName().str() : "unknown") << \
47 "\". This function only runs on OpenVDB Point Grids."); \
48 } \
49 }
50
51 /// @brief Retrieve a group handle from an expected vector of handles using the offset
52 /// pointed to by the engine data. Note that HandleT should only ever be a GroupHandle
53 /// or GroupWriteHandle object
54 template <typename HandleT>
55 inline HandleT*
groupHandle(const std::string & name,void ** groupHandles,const void * const data)56 groupHandle(const std::string& name, void** groupHandles, const void* const data)
57 {
58 const openvdb::points::AttributeSet* const attributeSet =
59 static_cast<const openvdb::points::AttributeSet*>(data);
60
61 const size_t groupIdx = attributeSet->groupOffset(name);
62 if (groupIdx == openvdb::points::AttributeSet::INVALID_POS) return nullptr;
63
64 return static_cast<HandleT*>(groupHandles[groupIdx]);
65 }
66
67 }
68
ax_ingroup(const FunctionOptions & op)69 inline FunctionGroup::UniquePtr ax_ingroup(const FunctionOptions& op)
70 {
71 static auto ingroup =
72 [](const codegen::String* const name,
73 const uint64_t index,
74 void** groupHandles,
75 const void* const leafDataPtr,
76 const void* const data) -> bool
77 {
78 assert(name);
79 assert(index < static_cast<uint64_t>(std::numeric_limits<openvdb::Index>::max()));
80
81 if (name->size() == 0) return false;
82 if (!groupHandles) return false;
83
84 const std::string nameStr = name->str();
85 const openvdb::points::GroupHandle* handle =
86 groupHandle<openvdb::points::GroupHandle>(nameStr, groupHandles, data);
87 if (handle) return handle->get(static_cast<openvdb::Index>(index));
88
89 // If the handle doesn't exist, check to see if any new groups have
90 // been added
91 const codegen_internal::PointLeafLocalData* const leafData =
92 static_cast<const codegen_internal::PointLeafLocalData*>(leafDataPtr);
93 handle = leafData->get(nameStr);
94 return handle ? handle->get(static_cast<openvdb::Index>(index)) : false;
95 };
96
97 using InGroup = bool(const codegen::String* const,
98 const uint64_t,
99 void**,
100 const void* const,
101 const void* const);
102
103 return FunctionBuilder("_ingroup")
104 .addSignature<InGroup>(ingroup)
105 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
106 .addParameterAttribute(2, llvm::Attribute::ReadOnly)
107 .addParameterAttribute(2, llvm::Attribute::NoAlias)
108 .addParameterAttribute(3, llvm::Attribute::ReadOnly)
109 .addParameterAttribute(3, llvm::Attribute::NoAlias)
110 .addParameterAttribute(4, llvm::Attribute::ReadOnly)
111 .addParameterAttribute(4, llvm::Attribute::NoAlias)
112 .addFunctionAttribute(llvm::Attribute::ReadOnly)
113 .addFunctionAttribute(llvm::Attribute::NoRecurse)
114 // @note handle->get can throw, so no unwind. Maybe use getUnsafe?
115 .setConstantFold(false)
116 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
117 .setDocumentation("Internal function for querying point group data")
118 .get();
119 }
120
axingroup(const FunctionOptions & op)121 inline FunctionGroup::UniquePtr axingroup(const FunctionOptions& op)
122 {
123 static auto generate =
124 [op](const std::vector<llvm::Value*>& args,
125 llvm::IRBuilder<>& B) -> llvm::Value*
126 {
127 OPENVDB_AX_CHECK_MODULE_CONTEXT(B);
128 // Pull out parent function arguments
129 llvm::Function* compute = B.GetInsertBlock()->getParent();
130 llvm::Value* point_index = extractArgument(compute, "point_index");
131 llvm::Value* group_handles = extractArgument(compute, "group_handles");
132 llvm::Value* leaf_data = extractArgument(compute, "leaf_data");
133 llvm::Value* attribute_set = extractArgument(compute, "attribute_set");
134 assert(point_index);
135 assert(group_handles);
136 assert(leaf_data);
137 assert(attribute_set);
138
139 std::vector<llvm::Value*> input(args);
140 input.emplace_back(point_index);
141 input.emplace_back(group_handles);
142 input.emplace_back(leaf_data);
143 input.emplace_back(attribute_set);
144 return ax_ingroup(op)->execute(input, B);
145 };
146
147 return FunctionBuilder("ingroup")
148 .addSignature<bool(const codegen::String* const)>(generate)
149 .addDependency("_ingroup")
150 .setEmbedIR(true)
151 .setConstantFold(false)
152 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
153 .setDocumentation( "Return whether or not the current point is "
154 "a member of the given group name. This returns false if the group does "
155 "not exist.")
156 .get();
157 }
158
axeditgroup(const FunctionOptions & op)159 inline FunctionGroup::UniquePtr axeditgroup(const FunctionOptions& op)
160 {
161 static auto editgroup =
162 [](const codegen::String* const name,
163 const uint64_t index,
164 void** groupHandles,
165 void* const leafDataPtr,
166 const void* const data,
167 const bool flag)
168 {
169 assert(name);
170 if (name->size() == 0) return;
171
172 // Get the group handle out of the pre-existing container of handles if they
173 // exist
174
175 const std::string nameStr = name->str();
176 openvdb::points::GroupWriteHandle* handle = nullptr;
177 if (groupHandles) {
178 handle = groupHandle<openvdb::points::GroupWriteHandle>(nameStr, groupHandles, data);
179 }
180
181 if (!handle) {
182 codegen_internal::PointLeafLocalData* const leafData =
183 static_cast<codegen_internal::PointLeafLocalData*>(leafDataPtr);
184
185 // If we are setting membership and the handle doesn't exist, create in in
186 // the set of new data thats being added
187 if (!flag && !leafData->hasGroup(nameStr)) return;
188 handle = leafData->getOrInsert(nameStr);
189 assert(handle);
190 }
191
192 // set the group membership
193 handle->set(static_cast<openvdb::Index>(index), flag);
194 };
195
196 static auto editgroupcstar =
197 [](const char* const name,
198 const uint64_t index,
199 void** groupHandles,
200 void* const leafDataPtr,
201 const void* const data,
202 const bool flag)
203 {
204 const codegen::String str(name);
205 editgroup(&str, index, groupHandles, leafDataPtr, data, flag);
206 };
207
208 using EditGroup = void(const codegen::String* const,
209 const uint64_t,
210 void**,
211 void* const,
212 const void* const,
213 const bool);
214
215 using EditGroupCstar = void(const char* const,
216 const uint64_t,
217 void**,
218 void* const,
219 const void* const,
220 const bool);
221
222 return FunctionBuilder("editgroup")
223 .addSignature<EditGroup>(editgroup)
224 .addSignature<EditGroupCstar>(editgroupcstar)
225 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
226 .addParameterAttribute(2, llvm::Attribute::ReadOnly)
227 .addParameterAttribute(3, llvm::Attribute::ReadOnly)
228 .addParameterAttribute(4, llvm::Attribute::ReadOnly)
229 .setConstantFold(false)
230 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
231 .setDocumentation("Internal function for setting point group data")
232 .get();
233 }
234
axaddtogroup(const FunctionOptions & op)235 inline FunctionGroup::UniquePtr axaddtogroup(const FunctionOptions& op)
236 {
237 static auto generate =
238 [op](const std::vector<llvm::Value*>& args,
239 llvm::IRBuilder<>& B) -> llvm::Value*
240 {
241 OPENVDB_AX_CHECK_MODULE_CONTEXT(B);
242 // Pull out parent function arguments
243 llvm::Function* compute = B.GetInsertBlock()->getParent();
244 llvm::Value* point_index = extractArgument(compute, "point_index");
245 llvm::Value* group_handles = extractArgument(compute, "group_handles");
246 llvm::Value* leaf_data = extractArgument(compute, "leaf_data");
247 llvm::Value* attribute_set = extractArgument(compute, "attribute_set");
248 assert(point_index);
249 assert(group_handles);
250 assert(leaf_data);
251 assert(attribute_set);
252
253 std::vector<llvm::Value*> input(args);
254 input.emplace_back(point_index);
255 input.emplace_back(group_handles);
256 input.emplace_back(leaf_data);
257 input.emplace_back(attribute_set);
258 input.emplace_back(llvm::ConstantInt::get(LLVMType<bool>::get(B.getContext()), true));
259 return axeditgroup(op)->execute(input, B);
260 };
261
262 return FunctionBuilder("addtogroup")
263 .addSignature<void(const codegen::String* const)>(generate)
264 .addSignature<void(const char* const)>(generate) // to support axdeletepoint() @todo fix
265 .addDependency("editgroup")
266 .setEmbedIR(true)
267 .setConstantFold(false)
268 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
269 .setDocumentation("Add the current point to the given group "
270 "name, effectively setting its membership to true. If the group does not "
271 "exist, it is implicitly created. This function has no effect if the point "
272 "already belongs to the given group.")
273 .get();
274 }
275
axremovefromgroup(const FunctionOptions & op)276 inline FunctionGroup::UniquePtr axremovefromgroup(const FunctionOptions& op)
277 {
278 static auto generate =
279 [op](const std::vector<llvm::Value*>& args,
280 llvm::IRBuilder<>& B) -> llvm::Value*
281 {
282 // Pull out parent function arguments
283 OPENVDB_AX_CHECK_MODULE_CONTEXT(B);
284 llvm::Function* compute = B.GetInsertBlock()->getParent();
285 llvm::Value* point_index = extractArgument(compute, "point_index");
286 llvm::Value* group_handles = extractArgument(compute, "group_handles");
287 llvm::Value* leaf_data = extractArgument(compute, "leaf_data");
288 llvm::Value* attribute_set = extractArgument(compute, "attribute_set");
289 assert(point_index);
290 assert(group_handles);
291 assert(leaf_data);
292 assert(attribute_set);
293
294 std::vector<llvm::Value*> input(args);
295 input.emplace_back(point_index);
296 input.emplace_back(group_handles);
297 input.emplace_back(leaf_data);
298 input.emplace_back(attribute_set);
299 input.emplace_back(llvm::ConstantInt::get(LLVMType<bool>::get(B.getContext()), false));
300 return axeditgroup(op)->execute(input, B);
301 };
302
303 return FunctionBuilder("removefromgroup")
304 .addSignature<void(const codegen::String* const)>(generate)
305 .addDependency("editgroup")
306 .setEmbedIR(true)
307 .setConstantFold(false)
308 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
309 .setDocumentation("Remove the current point from the "
310 "given group name, effectively setting its membership to false. This "
311 "function has no effect if the group does not exist.")
312 .get();
313 }
314
axdeletepoint(const FunctionOptions & op)315 inline FunctionGroup::UniquePtr axdeletepoint(const FunctionOptions& op)
316 {
317 static auto generate =
318 [op](const std::vector<llvm::Value*>&,
319 llvm::IRBuilder<>& B) -> llvm::Value*
320 {
321 // args guaranteed to be empty
322 const std::string deadGroup = "__ax_dead";
323 llvm::Constant* loc = llvm::cast<llvm::Constant>(B.CreateGlobalStringPtr(deadGroup.c_str())); // char*
324 return axaddtogroup(op)->execute({loc}, B);
325 };
326
327 return FunctionBuilder("deletepoint")
328 .addSignature<void()>(generate)
329 .addDependency("addtogroup")
330 .addFunctionAttribute(llvm::Attribute::AlwaysInline)
331 .setEmbedIR(true) // axaddtogroup needs access to parent function arguments
332 .setConstantFold(false)
333 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
334 .setDocumentation("Delete the current point from the point set. Note that this does not "
335 "stop AX execution - any additional AX commands will be executed on the "
336 "point and it will remain accessible until the end of execution.")
337 .get();
338 }
339
axsetattribute(const FunctionOptions & op)340 inline FunctionGroup::UniquePtr axsetattribute(const FunctionOptions& op)
341 {
342 static auto setattribptr =
343 [](void* attributeHandle, uint64_t index, const auto value)
344 {
345 using ValueType = typename std::remove_const
346 <typename std::remove_pointer
347 <decltype(value)>::type>::type;
348 using AttributeHandleType = openvdb::points::AttributeWriteHandle<ValueType>;
349
350 assert(attributeHandle);
351 assert(value);
352 assert(index < static_cast<uint64_t>(std::numeric_limits<openvdb::Index>::max()));
353
354 AttributeHandleType* handle = static_cast<AttributeHandleType*>(attributeHandle);
355 handle->set(static_cast<openvdb::Index>(index), *value);
356 };
357
358 static auto setattribstr =
359 [](void* attributeHandle,
360 const uint64_t index,
361 const codegen::String* value,
362 void* const leafDataPtr)
363 {
364 using AttributeHandleType = openvdb::points::StringAttributeWriteHandle;
365
366 assert(attributeHandle);
367 assert(value);
368 assert(leafDataPtr);
369 assert(index < static_cast<uint64_t>(std::numeric_limits<openvdb::Index>::max()));
370
371 const std::string s = value->str();
372 AttributeHandleType* const handle =
373 static_cast<AttributeHandleType*>(attributeHandle);
374 codegen_internal::PointLeafLocalData* const leafData =
375 static_cast<codegen_internal::PointLeafLocalData*>(leafDataPtr);
376
377 // Check to see if the string exists in the metadata cache. If so, set the string and
378 // remove any new data associated with it, otherwise set the new data
379
380 if (handle->contains(s)) {
381 handle->set(static_cast<openvdb::Index>(index), s);
382 leafData->removeNewStringData(&(handle->array()), index);
383 }
384 else {
385 leafData->setNewStringData(&(handle->array()), index, s);
386 }
387 };
388
389 static auto setattrib =
390 [](void* attributeHandle,
391 uint64_t index,
392 const auto value) {
393 setattribptr(attributeHandle, index, &value);
394 };
395
396 using SetAttribD = void(void*, uint64_t, const double);
397 using SetAttribF = void(void*, uint64_t, const float);
398 using SetAttribI64 = void(void*, uint64_t, const int64_t);
399 using SetAttribI32 = void(void*, uint64_t, const int32_t);
400 using SetAttribI16 = void(void*, uint64_t, const int16_t);
401 using SetAttribB = void(void*, uint64_t, const bool);
402 using SetAttribV2D = void(void*, uint64_t, const openvdb::math::Vec2<double>*);
403 using SetAttribV2F = void(void*, uint64_t, const openvdb::math::Vec2<float>*);
404 using SetAttribV2I = void(void*, uint64_t, const openvdb::math::Vec2<int32_t>*);
405 using SetAttribV3D = void(void*, uint64_t, const openvdb::math::Vec3<double>*);
406 using SetAttribV3F = void(void*, uint64_t, const openvdb::math::Vec3<float>*);
407 using SetAttribV3I = void(void*, uint64_t, const openvdb::math::Vec3<int32_t>*);
408 using SetAttribV4D = void(void*, uint64_t, const openvdb::math::Vec4<double>*);
409 using SetAttribV4F = void(void*, uint64_t, const openvdb::math::Vec4<float>*);
410 using SetAttribV4I = void(void*, uint64_t, const openvdb::math::Vec4<int32_t>*);
411 using SetAttribM3D = void(void*, uint64_t, const openvdb::math::Mat3<double>*);
412 using SetAttribM3F = void(void*, uint64_t, const openvdb::math::Mat3<float>*);
413 using SetAttribM4D = void(void*, uint64_t, const openvdb::math::Mat4<double>*);
414 using SetAttribM4F = void(void*, uint64_t, const openvdb::math::Mat4<float>*);
415 using SetAttribStr = void(void*, uint64_t, const codegen::String*, void* const);
416
417 return FunctionBuilder("setattribute")
418 .addSignature<SetAttribD>((SetAttribD*)(setattrib))
419 .addSignature<SetAttribF>((SetAttribF*)(setattrib))
420 .addSignature<SetAttribI64>((SetAttribI64*)(setattrib))
421 .addSignature<SetAttribI32>((SetAttribI32*)(setattrib))
422 .addSignature<SetAttribI16>((SetAttribI16*)(setattrib))
423 .addSignature<SetAttribB>((SetAttribB*)(setattrib))
424 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
425 .addFunctionAttribute(llvm::Attribute::NoRecurse)
426 .setConstantFold(false)
427 .addSignature<SetAttribV2D>((SetAttribV2D*)(setattribptr))
428 .addSignature<SetAttribV2F>((SetAttribV2F*)(setattribptr))
429 .addSignature<SetAttribV2I>((SetAttribV2I*)(setattribptr))
430 .addSignature<SetAttribV3D>((SetAttribV3D*)(setattribptr))
431 .addSignature<SetAttribV3F>((SetAttribV3F*)(setattribptr))
432 .addSignature<SetAttribV3I>((SetAttribV3I*)(setattribptr))
433 .addSignature<SetAttribV4D>((SetAttribV4D*)(setattribptr))
434 .addSignature<SetAttribV4F>((SetAttribV4F*)(setattribptr))
435 .addSignature<SetAttribV4I>((SetAttribV4I*)(setattribptr))
436 .addSignature<SetAttribM3D>((SetAttribM3D*)(setattribptr))
437 .addSignature<SetAttribM3F>((SetAttribM3F*)(setattribptr))
438 .addSignature<SetAttribM4D>((SetAttribM4D*)(setattribptr))
439 .addSignature<SetAttribM4F>((SetAttribM4F*)(setattribptr))
440 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
441 .addParameterAttribute(2, llvm::Attribute::ReadOnly)
442 .addFunctionAttribute(llvm::Attribute::NoRecurse)
443 .setConstantFold(false)
444 .addSignature<SetAttribStr>((SetAttribStr*)(setattribstr))
445 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
446 .addParameterAttribute(2, llvm::Attribute::ReadOnly)
447 .addParameterAttribute(3, llvm::Attribute::ReadOnly)
448 .addFunctionAttribute(llvm::Attribute::NoRecurse)
449 .setConstantFold(false)
450 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
451 .setDocumentation("Internal function for setting the value of a point attribute.")
452 .get();
453 }
454
axgetattribute(const FunctionOptions & op)455 inline FunctionGroup::UniquePtr axgetattribute(const FunctionOptions& op)
456 {
457 static auto getattrib =
458 [](void* attributeHandle, uint64_t index, auto value)
459 {
460 using ValueType = typename std::remove_const
461 <typename std::remove_pointer
462 <decltype(value)>::type>::type;
463 // typedef is a read handle. As write handles are derived types this
464 // is okay and lets us define the handle types outside IR for attributes that are
465 // only being read!
466 using AttributeHandleType = openvdb::points::AttributeHandle<ValueType>;
467
468 assert(value);
469 assert(attributeHandle);
470 assert(index < static_cast<uint64_t>(std::numeric_limits<openvdb::Index>::max()));
471
472 AttributeHandleType* handle = static_cast<AttributeHandleType*>(attributeHandle);
473 (*value) = handle->get(static_cast<openvdb::Index>(index));
474 };
475
476 static auto getattribstr =
477 [](void* attributeHandle,
478 uint64_t index,
479 codegen::String* value,
480 const void* const leafDataPtr)
481 {
482 using AttributeHandleType = openvdb::points::StringAttributeHandle;
483
484 assert(value);
485 assert(attributeHandle);
486 assert(leafDataPtr);
487 assert(index < static_cast<uint64_t>(std::numeric_limits<openvdb::Index>::max()));
488
489 AttributeHandleType* const handle =
490 static_cast<AttributeHandleType*>(attributeHandle);
491 const codegen_internal::PointLeafLocalData* const leafData =
492 static_cast<const codegen_internal::PointLeafLocalData*>(leafDataPtr);
493
494 std::string data;
495 if (!leafData->getNewStringData(&(handle->array()), index, data)) {
496 handle->get(data, static_cast<openvdb::Index>(index));
497 }
498
499 *value = data;
500 };
501
502 using GetAttribD = void(void*, uint64_t, double*);
503 using GetAttribF = void(void*, uint64_t, float*);
504 using GetAttribI64 = void(void*, uint64_t, int64_t*);
505 using GetAttribI32 = void(void*, uint64_t, int32_t*);
506 using GetAttribI16 = void(void*, uint64_t, int16_t*);
507 using GetAttribB = void(void*, uint64_t, bool*);
508 using GetAttribV2D = void(void*, uint64_t, openvdb::math::Vec2<double>*);
509 using GetAttribV2F = void(void*, uint64_t, openvdb::math::Vec2<float>*);
510 using GetAttribV2I = void(void*, uint64_t, openvdb::math::Vec2<int32_t>*);
511 using GetAttribV3D = void(void*, uint64_t, openvdb::math::Vec3<double>*);
512 using GetAttribV3F = void(void*, uint64_t, openvdb::math::Vec3<float>*);
513 using GetAttribV3I = void(void*, uint64_t, openvdb::math::Vec3<int32_t>*);
514 using GetAttribV4D = void(void*, uint64_t, openvdb::math::Vec4<double>*);
515 using GetAttribV4F = void(void*, uint64_t, openvdb::math::Vec4<float>*);
516 using GetAttribV4I = void(void*, uint64_t, openvdb::math::Vec4<int32_t>*);
517 using GetAttribM3D = void(void*, uint64_t, openvdb::math::Mat3<double>*);
518 using GetAttribM3F = void(void*, uint64_t, openvdb::math::Mat3<float>*);
519 using GetAttribM4D = void(void*, uint64_t, openvdb::math::Mat4<double>*);
520 using GetAttribM4F = void(void*, uint64_t, openvdb::math::Mat4<float>*);
521 using GetAttribStr = void(void*, uint64_t, codegen::String*, const void* const);
522
523 return FunctionBuilder("getattribute")
524 .addSignature<GetAttribD>((GetAttribD*)(getattrib))
525 .addSignature<GetAttribF>((GetAttribF*)(getattrib))
526 .addSignature<GetAttribI64>((GetAttribI64*)(getattrib))
527 .addSignature<GetAttribI32>((GetAttribI32*)(getattrib))
528 .addSignature<GetAttribI16>((GetAttribI16*)(getattrib))
529 .addSignature<GetAttribB>((GetAttribB*)(getattrib))
530 .addSignature<GetAttribV2D>((GetAttribV2D*)(getattrib))
531 .addSignature<GetAttribV2F>((GetAttribV2F*)(getattrib))
532 .addSignature<GetAttribV2I>((GetAttribV2I*)(getattrib))
533 .addSignature<GetAttribV3D>((GetAttribV3D*)(getattrib))
534 .addSignature<GetAttribV3F>((GetAttribV3F*)(getattrib))
535 .addSignature<GetAttribV3I>((GetAttribV3I*)(getattrib))
536 .addSignature<GetAttribV4D>((GetAttribV4D*)(getattrib))
537 .addSignature<GetAttribV4F>((GetAttribV4F*)(getattrib))
538 .addSignature<GetAttribV4I>((GetAttribV4I*)(getattrib))
539 .addSignature<GetAttribM3D>((GetAttribM3D*)(getattrib))
540 .addSignature<GetAttribM3F>((GetAttribM3F*)(getattrib))
541 .addSignature<GetAttribM4D>((GetAttribM4D*)(getattrib))
542 .addSignature<GetAttribM4F>((GetAttribM4F*)(getattrib))
543 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
544 .addFunctionAttribute(llvm::Attribute::NoRecurse)
545 .setConstantFold(false)
546 .addSignature<GetAttribStr>((GetAttribStr*)(getattribstr))
547 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
548 .addParameterAttribute(3, llvm::Attribute::ReadOnly)
549 .addFunctionAttribute(llvm::Attribute::NoRecurse)
550 .setConstantFold(false)
551 .setPreferredImpl(op.mPrioritiseIR ? FunctionBuilder::IR : FunctionBuilder::C)
552 .setDocumentation("Internal function for getting the value of a point attribute.")
553 .get();
554 }
555
556
557 ////////////////////////////////////////////////////////////////////////
558 ////////////////////////////////////////////////////////////////////////
559
560
insertVDBPointFunctions(FunctionRegistry & registry,const FunctionOptions * options)561 void insertVDBPointFunctions(FunctionRegistry& registry,
562 const FunctionOptions* options)
563 {
564 const bool create = options && !options->mLazyFunctions;
565 auto add = [&](const std::string& name,
566 const FunctionRegistry::ConstructorT creator,
567 const bool internal = false)
568 {
569 if (create) registry.insertAndCreate(name, creator, *options, internal);
570 else registry.insert(name, creator, internal);
571 };
572
573 // point functions
574
575 add("addtogroup", axaddtogroup);
576 add("ingroup", axingroup);
577 add("removefromgroup",axremovefromgroup);
578 add("deletepoint", axdeletepoint);
579 add("_ingroup", ax_ingroup, true);
580 add("editgroup", axeditgroup, true);
581 add("getattribute", axgetattribute, true);
582 add("setattribute", axsetattribute, true);
583 }
584
585 } // namespace codegen
586 } // namespace ax
587 } // namespace openvdb_version
588 } // namespace openvdb
589
590
591