Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | /// @file compiler/PointExecutable.cc | ||
5 | |||
6 | #include "PointExecutable.h" | ||
7 | #include "Logger.h" | ||
8 | |||
9 | #include "openvdb_ax/ast/Scanners.h" | ||
10 | #include "openvdb_ax/Exceptions.h" | ||
11 | // @TODO refactor so we don't have to include PointComputeGenerator.h, | ||
12 | // but still have the functions defined in one place | ||
13 | #include "openvdb_ax/codegen/PointComputeGenerator.h" | ||
14 | #include "openvdb_ax/codegen/PointLeafLocalData.h" | ||
15 | #include "openvdb_ax/codegen/Codecs.h" | ||
16 | |||
17 | #include <openvdb/Types.h> | ||
18 | |||
19 | #include <openvdb/points/AttributeArray.h> | ||
20 | #include <openvdb/points/PointAttribute.h> | ||
21 | #include <openvdb/points/PointConversion.h> // ConversionTraits | ||
22 | #include <openvdb/points/PointDataGrid.h> | ||
23 | #include <openvdb/points/PointGroup.h> | ||
24 | #include <openvdb/points/PointMask.h> | ||
25 | #include <openvdb/points/PointMove.h> | ||
26 | #include <openvdb/points/PointDelete.h> | ||
27 | |||
28 | namespace openvdb { | ||
29 | OPENVDB_USE_VERSION_NAMESPACE | ||
30 | namespace OPENVDB_VERSION_NAME { | ||
31 | |||
32 | namespace ax { | ||
33 | |||
34 | struct PointExecutable::Settings | ||
35 | { | ||
36 | bool mCreateMissing = true; | ||
37 | size_t mGrainSize = 1; | ||
38 | std::string mGroup = ""; | ||
39 | //IterType mValueIterator = IterType::ON; | ||
40 | bool mPostDelete = false; | ||
41 | AttributeBindings mBindings; | ||
42 | }; | ||
43 | |||
44 | namespace { | ||
45 | |||
46 | /// @brief Point Kernel types | ||
47 | /// | ||
48 | using KernelValueFunctionPtr = std::add_pointer<codegen::PointKernelAttributeArray::Signature>::type; | ||
49 | using KernelBufferRangeFunctionPtr = std::add_pointer<codegen::PointKernelBufferRange::Signature>::type; | ||
50 | using PointLeafLocalData = codegen::codegen_internal::PointLeafLocalData; | ||
51 | |||
52 | #ifndef NDEBUG | ||
53 | inline bool supported(const ast::tokens::CoreType type) | ||
54 | { | ||
55 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
|
89 | switch (type) { |
56 | case ast::tokens::BOOL : return true; | ||
57 | case ast::tokens::CHAR : return true; | ||
58 | case ast::tokens::INT16 : return true; | ||
59 | case ast::tokens::INT32 : return true; | ||
60 | case ast::tokens::INT64 : return true; | ||
61 | case ast::tokens::FLOAT : return true; | ||
62 | case ast::tokens::DOUBLE : return true; | ||
63 | case ast::tokens::VEC2I : return true; | ||
64 | case ast::tokens::VEC2F : return true; | ||
65 | case ast::tokens::VEC2D : return true; | ||
66 | case ast::tokens::VEC3I : return true; | ||
67 | case ast::tokens::VEC3F : return true; | ||
68 | case ast::tokens::VEC3D : return true; | ||
69 | case ast::tokens::VEC4I : return true; | ||
70 | case ast::tokens::VEC4F : return true; | ||
71 | case ast::tokens::VEC4D : return true; | ||
72 | case ast::tokens::MAT3F : return true; | ||
73 | case ast::tokens::MAT3D : return true; | ||
74 | case ast::tokens::MAT4F : return true; | ||
75 | case ast::tokens::MAT4D : return true; | ||
76 | case ast::tokens::STRING : return true; | ||
77 | case ast::tokens::UNKNOWN : | ||
78 | default : return false; | ||
79 | } | ||
80 | } | ||
81 | #endif | ||
82 | |||
83 | 5089 | struct PointAttributeInfo | |
84 | { | ||
85 | PointAttributeInfo(const std::string& name, | ||
86 | const ast::tokens::CoreType type, | ||
87 | const bool write) | ||
88 | 5089 | : mName(name) | |
89 | , mType(type) | ||
90 |
0/4✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
5089 | , mWrite(write) {} |
91 | std::string mName; | ||
92 | ast::tokens::CoreType mType; | ||
93 | bool mWrite; | ||
94 | }; | ||
95 | |||
96 | /// @brief Shared data for the parallel operator | ||
97 | struct OpData | ||
98 | { | ||
99 | KernelValueFunctionPtr mKernelAttributeArray; | ||
100 | KernelBufferRangeFunctionPtr mKernelBufferRange; | ||
101 | const CustomData* mCustomData; | ||
102 | const AttributeRegistry* mAttributeRegistry; | ||
103 | size_t mIterMode; // 0 = OFF, 1 = ON, 2 = ALL | ||
104 | const math::Transform* mTransform; | ||
105 | points::AttributeSet::Descriptor::GroupIndex mGroupIndex; | ||
106 | std::string mPositionAttribute; | ||
107 | std::pair<bool,bool> mPositionAccess; | ||
108 | bool mUseBufferKernel; | ||
109 | std::vector<PointAttributeInfo> mAttributeInfo; | ||
110 | }; | ||
111 | |||
112 | /// @brief The arguments of the generated function | ||
113 | /// | ||
114 | struct PointFunctionArguments | ||
115 | { | ||
116 | using LeafT = points::PointDataTree::LeafNodeType; | ||
117 | |||
118 | /// @brief Base untyped handle struct for container storage | ||
119 | struct Handles | ||
120 | { | ||
121 | using UniquePtr = std::unique_ptr<Handles>; | ||
122 | virtual ~Handles() = default; | ||
123 | }; | ||
124 | |||
125 | /// @brief A wrapper around a VDB Points Attribute Handle, allowing for | ||
126 | /// typed storage of a read or write handle. This is used for | ||
127 | /// automatic memory management and void pointer passing into the | ||
128 | /// generated point functions | ||
129 | template <typename ValueT> | ||
130 | struct ReadHandle final : public Handles | ||
131 | { | ||
132 | using UniquePtr = std::unique_ptr<ReadHandle<ValueT>>; | ||
133 | using HandleTraits = points::point_conversion_internal::ConversionTraits<ValueT>; | ||
134 | using HandleT = typename HandleTraits::Handle; | ||
135 | 12 | ReadHandle(const LeafT& leaf, const Index idx) | |
136 | ✗ | : mHandle(HandleTraits::handleFromLeaf(leaf, idx)) {} | |
137 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
24 | ~ReadHandle() override final = default; |
138 | const std::unique_ptr<HandleT> mHandle; | ||
139 | }; | ||
140 | |||
141 | template <typename ValueT> | ||
142 | struct WriteHandle final : public Handles | ||
143 | { | ||
144 | using UniquePtr = std::unique_ptr<WriteHandle<ValueT>>; | ||
145 | using HandleTraits = points::point_conversion_internal::ConversionTraits<ValueT>; | ||
146 | using HandleT = typename HandleTraits::WriteHandle; | ||
147 | 372 | WriteHandle(LeafT& leaf, const Index idx) | |
148 |
19/40✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 20 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 16 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 4 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 4 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 4 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 8 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 32 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 4 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 44 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 4 times.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✓ Branch 58 taken 12 times.
✗ Branch 59 not taken.
|
408 | : mHandle(HandleTraits::writeHandleFromLeaf(leaf, idx)) {} |
149 |
1/2✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
|
1152 | ~WriteHandle() override final = default; |
150 | const std::unique_ptr<HandleT> mHandle; | ||
151 | }; | ||
152 | |||
153 | /////////////////////////////////////////////////////////////////////// | ||
154 | /////////////////////////////////////////////////////////////////////// | ||
155 | |||
156 | 1486 | PointFunctionArguments(const OpData& data, | |
157 | LeafT& leaf, | ||
158 | PointLeafLocalData* const leafLocalData) | ||
159 | 1486 | : mData(data) | |
160 | , mAttributeSet(&leaf.attributeSet()) | ||
161 | , mHandlesOrBuffers() | ||
162 | , mAttributeHandles() | ||
163 | , mVoidGroupHandles() | ||
164 | , mGroupHandles() | ||
165 | 1486 | , mLeafLocalData(leafLocalData) | |
166 | { | ||
167 | // add attributes based on the order and existence in the attribute registry | ||
168 |
2/2✓ Branch 0 taken 10150 times.
✓ Branch 1 taken 1486 times.
|
11636 | for (const auto& iter : mData.mAttributeInfo) { |
169 |
1/2✓ Branch 1 taken 10150 times.
✗ Branch 2 not taken.
|
10150 | this->addAttributeHandle(leaf, iter.mName, iter.mType, iter.mWrite); |
170 | } | ||
171 | |||
172 | // add groups | ||
173 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 1461 times.
|
1486 | const auto& map = mAttributeSet->descriptor().groupMap(); |
174 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 1461 times.
|
1486 | if (!map.empty()) { |
175 | // add all groups based on their offset within the attribute set - the offset can | ||
176 | // then be used as a key when retrieving groups from the linearized array, which | ||
177 | // is provided by the attribute set argument | ||
178 | std::map<size_t, std::string> orderedGroups; | ||
179 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 25 times.
|
63 | for (const auto& iter : map) { |
180 |
1/2✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
|
38 | orderedGroups[iter.second] = iter.first; |
181 | } | ||
182 | |||
183 | // add a handle at every offset up to and including the max offset. If the | ||
184 | // offset is not in use, we just use a null pointer as this will never be | ||
185 | // accessed | ||
186 | 25 | const size_t maxOffset = orderedGroups.crbegin()->first; | |
187 | 25 | auto iter = orderedGroups.begin(); | |
188 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 25 times.
|
63 | for (size_t i = 0; i <= maxOffset; ++i) { |
189 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | if (iter->first == i) { |
190 |
1/2✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
|
38 | this->addGroupWriteHandle(leaf, iter->second); |
191 | ++iter; | ||
192 | } | ||
193 | else { | ||
194 | // empty handle at this index | ||
195 | this->addNullGroupHandle(); | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | 1486 | } | |
200 | |||
201 | inline auto bindValueKernel() | ||
202 | { | ||
203 | using FunctionTraitsT = codegen::PointKernelAttributeArray::FunctionTraitsT; | ||
204 | using ReturnT = FunctionTraitsT::ReturnType; | ||
205 | |||
206 | 64 | return [&](const openvdb::Coord& origin, void* buffer, bool active, const size_t index) -> ReturnT { | |
207 | 64 | mData.mKernelAttributeArray(static_cast<FunctionTraitsT::Arg<0>::Type>(mData.mCustomData), | |
208 | reinterpret_cast<FunctionTraitsT::Arg<1>::Type>(origin.data()), | ||
209 | static_cast<FunctionTraitsT::Arg<2>::Type>(buffer), | ||
210 | static_cast<FunctionTraitsT::Arg<3>::Type>(active), | ||
211 | static_cast<FunctionTraitsT::Arg<4>::Type>(index), | ||
212 | static_cast<FunctionTraitsT::Arg<5>::Type>(nullptr/*mData.mVoidTransforms.data()*/), | ||
213 | static_cast<FunctionTraitsT::Arg<6>::Type>(mHandlesOrBuffers.data()), | ||
214 | static_cast<FunctionTraitsT::Arg<7>::Type>(mFlags.data()), | ||
215 | 64 | static_cast<FunctionTraitsT::Arg<8>::Type>(mAttributeSet), | |
216 | static_cast<FunctionTraitsT::Arg<9>::Type>(mVoidGroupHandles.data()), | ||
217 | 64 | static_cast<FunctionTraitsT::Arg<10>::Type>(mLeafLocalData)); | |
218 | 120 | }; | |
219 | } | ||
220 | |||
221 | inline auto bindRangeKernel() | ||
222 | { | ||
223 | using FunctionTraitsT = codegen::PointKernelBufferRange::FunctionTraitsT; | ||
224 | using ReturnT = FunctionTraitsT::ReturnType; | ||
225 | |||
226 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1430 times.
|
1430 | assert(mData.mUseBufferKernel); |
227 | |||
228 | 1430 | return [&](const openvdb::Coord& origin, void* buffer, Index64* mask, const size_t size) -> ReturnT { | |
229 | 1430 | mData.mKernelBufferRange(static_cast<FunctionTraitsT::Arg<0>::Type>(mData.mCustomData), | |
230 | reinterpret_cast<FunctionTraitsT::Arg<1>::Type>(origin.data()), | ||
231 | static_cast<FunctionTraitsT::Arg<2>::Type>(buffer), | ||
232 | static_cast<FunctionTraitsT::Arg<3>::Type>(mask), | ||
233 | static_cast<FunctionTraitsT::Arg<4>::Type>(size), | ||
234 | static_cast<FunctionTraitsT::Arg<5>::Type>(2/*mData.mIterMode*/), | ||
235 | static_cast<FunctionTraitsT::Arg<6>::Type>(nullptr/*mData.mVoidTransforms.data()*/), | ||
236 | static_cast<FunctionTraitsT::Arg<7>::Type>(mHandlesOrBuffers.data()), | ||
237 | static_cast<FunctionTraitsT::Arg<8>::Type>(mFlags.data()), | ||
238 | 1430 | static_cast<FunctionTraitsT::Arg<9>::Type>(mAttributeSet), | |
239 | static_cast<FunctionTraitsT::Arg<10>::Type>(mVoidGroupHandles.data()), | ||
240 | 1430 | static_cast<FunctionTraitsT::Arg<11>::Type>(mLeafLocalData)); | |
241 | 2860 | }; | |
242 | } | ||
243 | |||
244 | template <typename ValueT> | ||
245 | 574 | inline void addHandle(LeafT& leaf, const size_t pos) | |
246 | { | ||
247 | 574 | uint64_t flag = 0; | |
248 | const points::AttributeArray& array = leaf.constAttributeArray(pos); | ||
249 |
2/2✓ Branch 1 taken 285 times.
✓ Branch 2 taken 2 times.
|
574 | if (array.isUniform()) flag |= uint64_t(1) << 63; |
250 | |||
251 | // @todo if the array is shared we should probably make it unique? | ||
252 | |||
253 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
254 |
2/2✓ Branch 0 taken 275 times.
✓ Branch 1 taken 12 times.
|
574 | if (mData.mUseBufferKernel) { |
255 | 550 | const_cast<points::AttributeArray&>(array).loadData(); | |
256 | const char* data = array.constDataAsByteArray(); | ||
257 | 550 | void* ptr = static_cast<void*>(const_cast<char*>(data)); | |
258 | 550 | mHandlesOrBuffers.emplace_back(ptr); | |
259 | const codegen::Codec* codec = | ||
260 |
2/4✓ Branch 2 taken 275 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 275 times.
✗ Branch 7 not taken.
|
1100 | codegen::getCodec(ast::tokens::tokenFromTypeString(array.valueType()), array.codecType()); |
261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
|
550 | if (codec) flag |= codec->flag(); |
262 | } | ||
263 | else { | ||
264 |
1/2✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
24 | typename ReadHandle<ValueT>::UniquePtr handle(new ReadHandle<ValueT>(leaf, Index(pos))); |
265 |
1/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
24 | mHandlesOrBuffers.emplace_back(handle->mHandle.get()); |
266 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
24 | mAttributeHandles.emplace_back(std::move(handle)); |
267 | } | ||
268 | #else | ||
269 | assert(!mData.mUseBufferKernel); | ||
270 | typename ReadHandle<ValueT>::UniquePtr handle(new ReadHandle<ValueT>(leaf, Index(pos))); | ||
271 | mHandlesOrBuffers.emplace_back(handle->mHandle.get()); | ||
272 | mAttributeHandles.emplace_back(std::move(handle)); | ||
273 | #endif | ||
274 | |||
275 | 574 | mFlags.emplace_back(flag); | |
276 | } | ||
277 | |||
278 | template <typename ValueT> | ||
279 | 19726 | inline void addWriteHandle(LeafT& leaf, const size_t pos) | |
280 | { | ||
281 | 19726 | uint64_t flag = 0; | |
282 | 19726 | points::AttributeArray& array = leaf.attributeArray(pos); | |
283 | 19726 | array.expand(); | |
284 | |||
285 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
286 |
2/2✓ Branch 0 taken 9491 times.
✓ Branch 1 taken 372 times.
|
19726 | if (mData.mUseBufferKernel) { |
287 | 18982 | array.loadData(); | |
288 | const char* data = array.constDataAsByteArray(); | ||
289 | 18982 | void* ptr = static_cast<void*>(const_cast<char*>(data)); | |
290 | 18982 | mHandlesOrBuffers.emplace_back(ptr); | |
291 | const codegen::Codec* codec = | ||
292 |
2/4✓ Branch 2 taken 9491 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 9491 times.
✗ Branch 7 not taken.
|
37964 | codegen::getCodec(ast::tokens::tokenFromTypeString(array.valueType()), array.codecType()); |
293 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9482 times.
|
18982 | if (codec) flag |= codec->flag(); |
294 |
2/4✓ Branch 1 taken 9491 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9491 times.
|
18982 | assert(array.isDataLoaded() && !array.isUniform()); |
295 | } | ||
296 | else { | ||
297 |
1/2✓ Branch 2 taken 168 times.
✗ Branch 3 not taken.
|
744 | typename WriteHandle<ValueT>::UniquePtr handle(new WriteHandle<ValueT>(leaf, Index(pos))); |
298 |
1/4✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
744 | mHandlesOrBuffers.emplace_back(handle->mHandle.get()); |
299 |
1/2✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
|
744 | mAttributeHandles.emplace_back(std::move(handle)); |
300 | } | ||
301 | #else | ||
302 | assert(!mData.mUseBufferKernel); | ||
303 | typename WriteHandle<ValueT>::UniquePtr handle(new WriteHandle<ValueT>(leaf, Index(pos))); | ||
304 | mHandlesOrBuffers.emplace_back(handle->mHandle.get()); | ||
305 | mAttributeHandles.emplace_back(std::move(handle)); | ||
306 | #endif | ||
307 | |||
308 | 19726 | mFlags.emplace_back(flag); | |
309 | } | ||
310 | |||
311 | inline void addGroupHandle(const LeafT& leaf, const std::string& name) | ||
312 | { | ||
313 | assert(leaf.attributeSet().descriptor().hasGroup(name)); | ||
314 | mGroupHandles.emplace_back(new points::GroupHandle(leaf.groupHandle(name))); | ||
315 | mVoidGroupHandles.emplace_back(static_cast<void*>(mGroupHandles.back().get())); | ||
316 | } | ||
317 | |||
318 | 38 | inline void addGroupWriteHandle(LeafT& leaf, const std::string& name) | |
319 | { | ||
320 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
|
38 | assert(leaf.attributeSet().descriptor().hasGroup(name)); |
321 |
1/2✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
38 | mGroupHandles.emplace_back(new points::GroupWriteHandle(leaf.groupWriteHandle(name))); |
322 | 38 | mVoidGroupHandles.emplace_back(static_cast<void*>(mGroupHandles.back().get())); | |
323 | 38 | } | |
324 | |||
325 | ✗ | inline void addNullGroupHandle() { mVoidGroupHandles.emplace_back(nullptr); } | |
326 | |||
327 | inline void | ||
328 |
1/2✓ Branch 0 taken 10150 times.
✗ Branch 1 not taken.
|
10150 | addAttributeHandle(LeafT& leaf, const std::string& name, const ast::tokens::CoreType type, const bool write) |
329 | { | ||
330 | // assert so the executer can be marked as noexcept (assuming nothing throws in compute) | ||
331 | ✗ | assert(supported(type) && "Could not retrieve attribute handle from unsupported type"); | |
332 |
20/22✓ Branch 0 taken 1796 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 136 times.
✓ Branch 3 taken 1172 times.
✓ Branch 4 taken 396 times.
✓ Branch 5 taken 1121 times.
✓ Branch 6 taken 1592 times.
✓ Branch 7 taken 196 times.
✓ Branch 8 taken 196 times.
✓ Branch 9 taken 196 times.
✓ Branch 10 taken 300 times.
✓ Branch 11 taken 493 times.
✓ Branch 12 taken 520 times.
✓ Branch 13 taken 260 times.
✓ Branch 14 taken 264 times.
✓ Branch 15 taken 276 times.
✓ Branch 16 taken 248 times.
✓ Branch 17 taken 276 times.
✓ Branch 18 taken 256 times.
✓ Branch 19 taken 276 times.
✓ Branch 20 taken 180 times.
✗ Branch 21 not taken.
|
10150 | switch (type) { |
333 | 1796 | case ast::tokens::BOOL : return this->addAttributeHandleTyped<bool>(leaf, name, write); | |
334 | ✗ | case ast::tokens::CHAR : return this->addAttributeHandleTyped<char>(leaf, name, write); | |
335 | 136 | case ast::tokens::INT16 : return this->addAttributeHandleTyped<int16_t>(leaf, name, write); | |
336 | 1172 | case ast::tokens::INT32 : return this->addAttributeHandleTyped<int32_t>(leaf, name, write); | |
337 | 396 | case ast::tokens::INT64 : return this->addAttributeHandleTyped<int64_t>(leaf, name, write); | |
338 | 1121 | case ast::tokens::FLOAT : return this->addAttributeHandleTyped<float>(leaf, name, write); | |
339 | 1592 | case ast::tokens::DOUBLE : return this->addAttributeHandleTyped<double>(leaf, name, write); | |
340 | 196 | case ast::tokens::VEC2I : return this->addAttributeHandleTyped<math::Vec2<int32_t>>(leaf, name, write); | |
341 | 196 | case ast::tokens::VEC2F : return this->addAttributeHandleTyped<math::Vec2<float>>(leaf, name, write); | |
342 | 196 | case ast::tokens::VEC2D : return this->addAttributeHandleTyped<math::Vec2<double>>(leaf, name, write); | |
343 | 300 | case ast::tokens::VEC3I : return this->addAttributeHandleTyped<math::Vec3<int32_t>>(leaf, name, write); | |
344 | 493 | case ast::tokens::VEC3F : return this->addAttributeHandleTyped<math::Vec3<float>>(leaf, name, write); | |
345 | 520 | case ast::tokens::VEC3D : return this->addAttributeHandleTyped<math::Vec3<double>>(leaf, name, write); | |
346 | 260 | case ast::tokens::VEC4I : return this->addAttributeHandleTyped<math::Vec4<int32_t>>(leaf, name, write); | |
347 | 264 | case ast::tokens::VEC4F : return this->addAttributeHandleTyped<math::Vec4<float>>(leaf, name, write); | |
348 | 276 | case ast::tokens::VEC4D : return this->addAttributeHandleTyped<math::Vec4<double>>(leaf, name, write); | |
349 | 248 | case ast::tokens::MAT3F : return this->addAttributeHandleTyped<math::Mat3<float>>(leaf, name, write); | |
350 | 276 | case ast::tokens::MAT3D : return this->addAttributeHandleTyped<math::Mat3<double>>(leaf, name, write); | |
351 | 256 | case ast::tokens::MAT4F : return this->addAttributeHandleTyped<math::Mat4<float>>(leaf, name, write); | |
352 | 276 | case ast::tokens::MAT4D : return this->addAttributeHandleTyped<math::Mat4<double>>(leaf, name, write); | |
353 | 180 | case ast::tokens::STRING : return this->addAttributeHandleTyped<std::string>(leaf, name, write); | |
354 | case ast::tokens::UNKNOWN : | ||
355 | default : return; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | private: | ||
360 | template <typename ValueType> | ||
361 | inline void | ||
362 | 20300 | addAttributeHandleTyped(LeafT& leaf, const std::string& name, const bool write) | |
363 | { | ||
364 | 20300 | const size_t pos = leaf.attributeSet().find(name); | |
365 | //assert(!leaf.attributeSet().isShared(pos)); | ||
366 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10150 times.
|
20300 | assert(pos != openvdb::points::AttributeSet::INVALID_POS); |
367 |
2/2✓ Branch 0 taken 9863 times.
✓ Branch 1 taken 287 times.
|
20300 | if (write) this->addWriteHandle<ValueType>(leaf, pos); |
368 | 574 | else this->addHandle<ValueType>(leaf, pos); | |
369 | } | ||
370 | |||
371 | private: | ||
372 | const OpData& mData; | ||
373 | const points::AttributeSet* const mAttributeSet; | ||
374 | std::vector<void*> mHandlesOrBuffers; | ||
375 | std::vector<Handles::UniquePtr> mAttributeHandles; | ||
376 | std::vector<uint64_t> mFlags; | ||
377 | std::vector<void*> mVoidGroupHandles; | ||
378 | std::vector<points::GroupHandle::UniquePtr> mGroupHandles; | ||
379 | PointLeafLocalData* const mLeafLocalData; | ||
380 | }; | ||
381 | |||
382 | |||
383 | /////////////////////////////////////////////////////////////////////////// | ||
384 | /////////////////////////////////////////////////////////////////////////// | ||
385 | |||
386 | |||
387 | template<typename FilterT = openvdb::points::NullFilter> | ||
388 | struct PointExecuterDeformer | ||
389 | { | ||
390 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | PointExecuterDeformer(const std::string& positionAttribute, |
391 | const FilterT& filter = FilterT()) | ||
392 | : mFilter(filter) | ||
393 | , mPws(nullptr) | ||
394 |
1/4✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | , mPositionAttribute(positionAttribute) {} |
395 | |||
396 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | PointExecuterDeformer(const PointExecuterDeformer& other) |
397 | : mFilter(other.mFilter) | ||
398 | , mPws(nullptr) | ||
399 |
2/8✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
20 | , mPositionAttribute(other.mPositionAttribute) {} |
400 | |||
401 | template <typename LeafT> | ||
402 | 40 | void reset(const LeafT& leaf, const size_t) | |
403 | { | ||
404 | ✗ | mFilter.reset(leaf); | |
405 |
1/2✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
|
40 | mPws.reset(new points::AttributeHandle<Vec3f>(leaf.constAttributeArray(mPositionAttribute))); |
406 | } | ||
407 | |||
408 | template <typename IterT> | ||
409 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
56 | void apply(Vec3d& position, const IterT& iter) const |
410 | { | ||
411 | ✗ | if (mFilter.valid(iter)) { | |
412 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
56 | assert(mPws); |
413 | 56 | position = Vec3d(mPws->get(*iter)); | |
414 | } | ||
415 | } | ||
416 | |||
417 | FilterT mFilter; | ||
418 | points::AttributeHandle<Vec3f>::UniquePtr mPws; | ||
419 | const std::string& mPositionAttribute; | ||
420 | }; | ||
421 | |||
422 | /// @brief VDB Points executer for a compiled function pointer | ||
423 | struct PointExecuterOp | ||
424 | { | ||
425 | using LeafManagerT = openvdb::tree::LeafManager<openvdb::points::PointDataTree>; | ||
426 | using LeafNode = openvdb::points::PointDataTree::LeafNodeType; | ||
427 | using GroupFilter = openvdb::points::GroupFilter; | ||
428 | |||
429 | PointExecuterOp(const OpData& data, | ||
430 | std::vector<PointLeafLocalData::UniquePtr>& leafLocalData) | ||
431 | 748 | : mData(data) | |
432 | 748 | , mLeafLocalData(leafLocalData) {} | |
433 | |||
434 | template<typename FilterT = openvdb::points::NullFilter> | ||
435 | inline std::unique_ptr<points::AttributeWriteHandle<Vec3f>> | ||
436 | 24 | initPositions(LeafNode& leaf, const FilterT& filter = FilterT()) const | |
437 | { | ||
438 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
|
72 | points::AttributeHandle<Vec3f> positions(leaf.constAttributeArray("P")); |
439 | std::unique_ptr<points::AttributeWriteHandle<Vec3f>> | ||
440 |
3/6✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
|
24 | pws(new points::AttributeWriteHandle<Vec3f>(leaf.attributeArray(mData.mPositionAttribute))); |
441 | |||
442 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
|
60 | for (auto iter = leaf.beginIndexAll(filter); iter; ++iter) { |
443 | 36 | const Index idx = *iter; | |
444 |
3/6✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
|
36 | const openvdb::Vec3f pos = positions.get(idx) + iter.getCoord().asVec3s(); |
445 |
3/8✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
36 | pws->set(idx, mData.mTransform->indexToWorld(pos)); |
446 | } | ||
447 | |||
448 | 24 | return pws; | |
449 | } | ||
450 | |||
451 | 1486 | void operator()(LeafNode& leaf, size_t idx) const | |
452 | { | ||
453 | 1486 | auto& leafLocalData = mLeafLocalData[idx]; | |
454 | 1486 | leafLocalData.reset(new PointLeafLocalData(leaf.getLastValue())); | |
455 | |||
456 | 1486 | const bool group = mData.mGroupIndex.first != points::AttributeSet::INVALID_POS; | |
457 | |||
458 | // if we are using position we need to initialise the world space storage | ||
459 | 1486 | std::unique_ptr<points::AttributeWriteHandle<Vec3f>> pws; | |
460 |
3/4✓ Branch 0 taken 1474 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1474 times.
|
1486 | if (mData.mPositionAccess.first || mData.mPositionAccess.second) { |
461 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (group) { |
462 | const GroupFilter filter(mData.mGroupIndex); | ||
463 | ✗ | pws = this->initPositions(leaf, filter); | |
464 | } | ||
465 | else { | ||
466 |
1/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
12 | pws = this->initPositions(leaf); |
467 | } | ||
468 | } | ||
469 | |||
470 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
2972 | PointFunctionArguments args(mData, leaf, leafLocalData.get()); |
471 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
1486 | void* buffer = static_cast<void*>(leaf.buffer().data()); |
472 | |||
473 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1478 times.
|
1486 | if (group) { |
474 | 8 | const auto kernel = args.bindValueKernel(); | |
475 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | const GroupFilter filter(mData.mGroupIndex); |
476 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto iter = leaf.beginIndex<LeafNode::ValueAllCIter, GroupFilter>(filter); |
477 |
4/6✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
12 | for (; iter; ++iter) kernel(leaf.origin(), buffer, /*active*/true, *iter); |
478 | } | ||
479 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1430 times.
|
1478 | else if (!mData.mUseBufferKernel) { |
480 | 48 | const auto kernel = args.bindValueKernel(); | |
481 | auto iter = leaf.beginIndexAll(); | ||
482 |
4/6✓ Branch 0 taken 60 times.
✓ Branch 1 taken 48 times.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 60 times.
✗ Branch 8 not taken.
|
108 | for (; iter; ++iter) kernel(leaf.origin(), buffer, /*active*/true, *iter); |
483 | } | ||
484 | else { | ||
485 |
1/2✓ Branch 1 taken 1430 times.
✗ Branch 2 not taken.
|
1430 | const auto kernel = args.bindRangeKernel(); |
486 | Index64* masks = &(leaf.getValueMask().template getWord<Index64>(0)); | ||
487 |
1/2✓ Branch 1 taken 1430 times.
✗ Branch 2 not taken.
|
1430 | kernel(leaf.origin(), buffer, masks, size_t(LeafNode::NUM_VOXELS)); |
488 | } | ||
489 | |||
490 | // if not writing to position (i.e. post sorting) collapse the temporary attribute | ||
491 | |||
492 |
4/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1474 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10 times.
|
1486 | if (pws && !mData.mPositionAccess.second) { |
493 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | pws->collapse(); |
494 | pws.reset(); | ||
495 | } | ||
496 | |||
497 | // as multiple groups can be stored in a single array, attempt to compact the | ||
498 | // arrays directly so that we're not trying to call compact multiple times | ||
499 | // unsuccessfully | ||
500 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
1486 | leafLocalData->compact(); |
501 | 1486 | } | |
502 | |||
503 | void operator()(const LeafManagerT::LeafRange& range) const | ||
504 | { | ||
505 | for (auto leaf = range.begin(); leaf; ++leaf) { | ||
506 | (*this)(*leaf, leaf.pos()); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | private: | ||
511 | const OpData& mData; | ||
512 | std::vector<PointLeafLocalData::UniquePtr>& mLeafLocalData; | ||
513 | }; | ||
514 | |||
515 | 92 | inline NamePair typePairFromToken(const ast::tokens::CoreType type) | |
516 | { | ||
517 |
9/22✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 21 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 13 times.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 26 times.
✗ Branch 21 not taken.
|
92 | switch (type) { |
518 | ✗ | case ast::tokens::BOOL : return points::TypedAttributeArray<bool>::attributeType(); | |
519 | ✗ | case ast::tokens::CHAR : return points::TypedAttributeArray<char>::attributeType(); | |
520 | 2 | case ast::tokens::INT16 : return points::TypedAttributeArray<int16_t>::attributeType(); | |
521 | 20 | case ast::tokens::INT32 : return points::TypedAttributeArray<int32_t>::attributeType(); | |
522 | 2 | case ast::tokens::INT64 : return points::TypedAttributeArray<int64_t>::attributeType(); | |
523 | 21 | case ast::tokens::FLOAT : return points::TypedAttributeArray<float>::attributeType(); | |
524 | 2 | case ast::tokens::DOUBLE : return points::TypedAttributeArray<double>::attributeType(); | |
525 | ✗ | case ast::tokens::VEC2I : return points::TypedAttributeArray<math::Vec2<int32_t>>::attributeType(); | |
526 | ✗ | case ast::tokens::VEC2F : return points::TypedAttributeArray<math::Vec2<float>>::attributeType(); | |
527 | ✗ | case ast::tokens::VEC2D : return points::TypedAttributeArray<math::Vec2<double>>::attributeType(); | |
528 | 4 | case ast::tokens::VEC3I : return points::TypedAttributeArray<math::Vec3<int32_t>>::attributeType(); | |
529 | 13 | case ast::tokens::VEC3F : return points::TypedAttributeArray<math::Vec3<float>>::attributeType(); | |
530 | 2 | case ast::tokens::VEC3D : return points::TypedAttributeArray<math::Vec3<double>>::attributeType(); | |
531 | ✗ | case ast::tokens::VEC4I : return points::TypedAttributeArray<math::Vec4<int32_t>>::attributeType(); | |
532 | ✗ | case ast::tokens::VEC4F : return points::TypedAttributeArray<math::Vec4<float>>::attributeType(); | |
533 | ✗ | case ast::tokens::VEC4D : return points::TypedAttributeArray<math::Vec4<double>>::attributeType(); | |
534 | ✗ | case ast::tokens::MAT3F : return points::TypedAttributeArray<math::Mat3<float>>::attributeType(); | |
535 | ✗ | case ast::tokens::MAT3D : return points::TypedAttributeArray<math::Mat3<double>>::attributeType(); | |
536 | ✗ | case ast::tokens::MAT4F : return points::TypedAttributeArray<math::Mat4<float>>::attributeType(); | |
537 | ✗ | case ast::tokens::MAT4D : return points::TypedAttributeArray<math::Mat4<double>>::attributeType(); | |
538 | 26 | case ast::tokens::STRING : return points::StringAttributeArray::attributeType(); | |
539 | case ast::tokens::UNKNOWN : | ||
540 | default : { | ||
541 | return NamePair(); | ||
542 | } | ||
543 | } | ||
544 | } | ||
545 | |||
546 | 751 | void processAttributes(points::PointDataGrid& grid, | |
547 | std::vector<PointAttributeInfo>& attributeInfo, | ||
548 | std::pair<bool,bool>& positionAccess, | ||
549 | std::string& posWS, | ||
550 | const AttributeRegistry& registry, | ||
551 | const AttributeBindings& bindings, | ||
552 | const bool createMissing, | ||
553 | Logger& logger) | ||
554 | { | ||
555 | const auto leafIter = grid.tree().cbeginLeaf(); | ||
556 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | assert(leafIter); |
557 | |||
558 | 751 | attributeInfo.reserve(registry.data().size()); | |
559 | |||
560 | // append attributes | ||
561 | |||
562 |
2/2✓ Branch 0 taken 5089 times.
✓ Branch 1 taken 749 times.
|
5838 | for (const auto& iter : registry.data()) { |
563 | // get the corresponding point attributes | ||
564 | const std::string* nameptr = bindings.dataNameBoundTo(iter.name()); | ||
565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5089 times.
|
10087 | if (!nameptr) continue; |
566 | const std::string& name = *nameptr; | ||
567 | const points::AttributeSet::Descriptor& desc = leafIter->attributeSet().descriptor(); | ||
568 | |||
569 | // handle position separately as we need to create temp storage during execution | ||
570 | // create temporary world space position attribute if P is being accessed | ||
571 | // @todo should avoid actually adding this attribute to the tree as its temporary | ||
572 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5083 times.
|
5089 | if (name == "P") { |
573 | positionAccess = {iter.reads(), iter.writes()}; | ||
574 |
3/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
|
12 | posWS = desc.uniqueName("__P"); |
575 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | points::appendAttribute<openvdb::Vec3f>(grid.tree(), posWS); |
576 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | attributeInfo.emplace_back(posWS, ast::tokens::VEC3F, positionAccess.second); |
577 | 6 | continue; | |
578 | } | ||
579 | // add the data name to the attribute info | ||
580 |
1/2✓ Branch 1 taken 5083 times.
✗ Branch 2 not taken.
|
5083 | attributeInfo.emplace_back(name, iter.type(), iter.writes()); |
581 | |||
582 |
1/2✓ Branch 1 taken 5083 times.
✗ Branch 2 not taken.
|
5083 | const size_t pos = desc.find(name); |
583 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5081 times.
|
5083 | if (!createMissing && pos == points::AttributeSet::INVALID_POS) { |
584 |
6/12✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
|
14 | logger.error("Attribute \"" + name + "\" does not exist on grid \"" + grid.getName() + "\"." |
585 |
8/14✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
|
8 | + (name != iter.name() ? "[bound to \"" + iter.name() + " \"]" : "")); |
586 | ✗ | continue; | |
587 | } | ||
588 | |||
589 |
2/2✓ Branch 0 taken 4992 times.
✓ Branch 1 taken 89 times.
|
5081 | if (pos != points::AttributeSet::INVALID_POS) { |
590 |
1/2✓ Branch 1 taken 4992 times.
✗ Branch 2 not taken.
|
4992 | const points::AttributeArray* const array = leafIter->attributeSet().getConst(pos); |
591 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4992 times.
|
4992 | assert(array); |
592 |
2/4✓ Branch 1 taken 4992 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4992 times.
|
4992 | if (array->stride() > 1) { |
593 | ✗ | logger.warning("Attribute \"" + name + (name != iter.name() ? "\" [bound to \"" + iter.name() + "\"]" : "\"") | |
594 | ✗ | + " on grid \"" + grid.getName() + "\"is a strided (array) attribute. " | |
595 | ✗ | "Reading or writing to this attribute with @" + name + " will only access the first element."); | |
596 | } | ||
597 | |||
598 |
1/2✓ Branch 1 taken 4992 times.
✗ Branch 2 not taken.
|
4992 | const NamePair& type = desc.type(pos); |
599 | const ast::tokens::CoreType typetoken = | ||
600 | 4992 | ast::tokens::tokenFromTypeString(type.first); | |
601 | |||
602 |
3/4✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4928 times.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
|
5056 | if (typetoken != iter.type() && |
603 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
|
128 | !(type.second == "str" && iter.type() == ast::tokens::STRING)) { |
604 | ✗ | logger.error("Mismatching attributes types. Attribute \"" + name + | |
605 | ✗ | (name != iter.name() ? "\" [bound to \"" + iter.name() + "\"]" : "\"") + | |
606 | ✗ | " on grid \"" + grid.getName() + "\" exists of type \"" + type.first + | |
607 | ✗ | "\" but has been accessed with type \"" + | |
608 | ✗ | ast::tokens::typeStringFromToken(iter.type()) + "\""); | |
609 | } | ||
610 | 4992 | continue; | |
611 | } | ||
612 | |||
613 | ✗ | assert(supported(iter.type())); | |
614 |
1/2✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
|
178 | const NamePair type = typePairFromToken(iter.type()); |
615 |
1/2✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
|
89 | points::appendAttribute(grid.tree(), name, type); |
616 | } | ||
617 | 749 | } | |
618 | |||
619 | 749 | bool checkCodecs(const points::AttributeSet::Descriptor& desc, | |
620 | const AttributeRegistry& registry, | ||
621 | const AttributeBindings& bindings, | ||
622 | const std::string& posWS) | ||
623 | { | ||
624 |
2/2✓ Branch 0 taken 4999 times.
✓ Branch 1 taken 725 times.
|
5724 | for (const auto& iter : registry.data()) { |
625 | // no support for strings yet (we should just use the cbind) | ||
626 |
2/2✓ Branch 0 taken 4975 times.
✓ Branch 1 taken 24 times.
|
4999 | if (iter.type() == ast::tokens::STRING) return false; |
627 | |||
628 | // if this type has no possible codec, continue | ||
629 |
1/2✓ Branch 1 taken 4975 times.
✗ Branch 2 not taken.
|
4975 | const auto* codecs = codegen::getTypeSupportedCodecs(iter.type()); |
630 |
2/2✓ Branch 0 taken 4151 times.
✓ Branch 1 taken 824 times.
|
5780 | if (!codecs) continue; |
631 | |||
632 |
1/2✓ Branch 1 taken 824 times.
✗ Branch 2 not taken.
|
824 | std::string name = iter.name(); |
633 | const std::string* nameptr = bindings.dataNameBoundTo(name); | ||
634 |
1/2✓ Branch 0 taken 824 times.
✗ Branch 1 not taken.
|
824 | if (nameptr) name = *nameptr; |
635 | ✗ | else if (name == "P") name = posWS; | |
636 | |||
637 |
2/4✓ Branch 1 taken 824 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 824 times.
✗ Branch 5 not taken.
|
824 | const std::string& codec = desc.type(desc.find(name)).second; |
638 | |||
639 | // null codecs can be ignored | ||
640 |
3/4✓ Branch 1 taken 824 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 805 times.
✓ Branch 5 taken 19 times.
|
824 | if (codec == std::string(points::NullCodec::name())) continue; |
641 | |||
642 | // unknown codec in use, fall back to cbinding | ||
643 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if (codecs->find(codec) == codecs->cend()) return false; |
644 | } | ||
645 | |||
646 | 725 | return true; | |
647 | } | ||
648 | |||
649 | } // anonymous namespace | ||
650 | |||
651 | 757 | PointExecutable::PointExecutable(const std::shared_ptr<const llvm::LLVMContext>& context, | |
652 | const std::shared_ptr<const llvm::ExecutionEngine>& engine, | ||
653 | const AttributeRegistry::ConstPtr& attributeRegistry, | ||
654 | const CustomData::ConstPtr& customData, | ||
655 | const std::unordered_map<std::string, uint64_t>& functions, | ||
656 | 757 | const ast::Tree& ast) | |
657 | : mContext(context) | ||
658 | , mExecutionEngine(engine) | ||
659 | , mAttributeRegistry(attributeRegistry) | ||
660 | , mCustomData(customData) | ||
661 | , mFunctionAddresses(functions) | ||
662 |
2/4✓ Branch 1 taken 757 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 757 times.
✗ Branch 5 not taken.
|
757 | , mSettings(new Settings) |
663 | { | ||
664 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 757 times.
|
757 | assert(mContext); |
665 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 757 times.
|
757 | assert(mExecutionEngine); |
666 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 757 times.
|
757 | assert(mAttributeRegistry); |
667 | |||
668 | // parse the AST for known functions which require pre/post processing | ||
669 |
2/4✓ Branch 1 taken 757 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 757 times.
✗ Branch 5 not taken.
|
757 | mSettings->mPostDelete = ast::callsFunction(ast, "deletepoint"); |
670 | |||
671 | // Set up the default attribute bindings | ||
672 |
2/2✓ Branch 0 taken 5085 times.
✓ Branch 1 taken 757 times.
|
5842 | for (const auto& iter : mAttributeRegistry->data()) { |
673 |
1/2✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
|
5085 | mSettings->mBindings.set(iter.name(), iter.name()); |
674 | } | ||
675 | 757 | } | |
676 | |||
677 | ✗ | PointExecutable::PointExecutable(const PointExecutable& other) | |
678 | : mContext(other.mContext) | ||
679 | , mExecutionEngine(other.mExecutionEngine) | ||
680 | , mAttributeRegistry(other.mAttributeRegistry) | ||
681 | , mCustomData(other.mCustomData) | ||
682 | , mFunctionAddresses(other.mFunctionAddresses) | ||
683 | ✗ | , mSettings(new Settings(*other.mSettings)) { | |
684 | } | ||
685 | |||
686 | 757 | PointExecutable::~PointExecutable() {} | |
687 | |||
688 | 751 | void PointExecutable::execute(openvdb::points::PointDataGrid& grid) const | |
689 | { | ||
690 | using LeafManagerT = openvdb::tree::LeafManager<openvdb::points::PointDataTree>; | ||
691 | |||
692 | Logger* logger; | ||
693 | 748 | std::unique_ptr<Logger> log; | |
694 | if (true) { | ||
695 | /// @note This branch exists for forwards compatibility with upcoming | ||
696 | /// changes to allow a logger to be provided to the executables | ||
697 |
3/8✓ Branch 3 taken 751 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 751 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
|
3007 | log.reset(new Logger([](const std::string& error) { |
698 |
1/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
12 | OPENVDB_THROW(AXExecutionError, error); |
699 |
2/4✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 751 times.
✗ Branch 5 not taken.
|
751 | })); |
700 | logger = log.get(); | ||
701 | } | ||
702 | |||
703 | const auto leafIter = grid.tree().cbeginLeaf(); | ||
704 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | if (!leafIter) { |
705 |
0/8✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
3 | logger->warning("PointDataGrid \"" + grid.getName() + "\" is empty."); |
706 | ✗ | return; | |
707 | } | ||
708 | |||
709 | // Initialize the shared op data | ||
710 | 748 | OpData data; | |
711 | |||
712 | // create any missing attributes and handle temp ws position storage | ||
713 | data.mPositionAccess = {false, false}; | ||
714 | 751 | processAttributes(grid, data.mAttributeInfo, data.mPositionAccess, data.mPositionAttribute, | |
715 | 751 | *mAttributeRegistry, mSettings->mBindings, | |
716 |
2/2✓ Branch 1 taken 749 times.
✓ Branch 2 taken 2 times.
|
751 | mSettings->mCreateMissing, *logger); |
717 | |||
718 | 749 | data.mKernelAttributeArray = | |
719 | reinterpret_cast<KernelValueFunctionPtr> | ||
720 |
2/4✓ Branch 1 taken 749 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 749 times.
✗ Branch 5 not taken.
|
1498 | (mFunctionAddresses.at(codegen::PointKernelAttributeArray::getDefaultName())); |
721 | 749 | data.mKernelBufferRange = | |
722 | reinterpret_cast<KernelBufferRangeFunctionPtr> | ||
723 |
4/6✓ Branch 1 taken 749 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 749 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 745 times.
|
1498 | (mFunctionAddresses.at(codegen::PointKernelBufferRange::getDefaultName())); |
724 | 749 | data.mTransform = &grid.transform(); | |
725 | 749 | data.mCustomData = mCustomData.get(); | |
726 | 749 | data.mGroupIndex.first = openvdb::points::AttributeSet::INVALID_POS; | |
727 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 745 times.
|
749 | data.mAttributeRegistry = mAttributeRegistry.get(); |
728 | //data.mPositionAccess = mAttributeRegistry->accessPattern("P", ast::tokens::VEC3F); | ||
729 | |||
730 | // init the internal dead group if necessary | ||
731 | |||
732 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 745 times.
|
749 | if (mSettings->mPostDelete) { |
733 | // @todo This group is hard coded in the deletepoint function call - we | ||
734 | // should perhaps instead pass in a unique group string to the point kernel | ||
735 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
|
8 | if (leafIter->attributeSet().descriptor().hasGroup("__ax_dead")) { |
736 | ✗ | logger->warning("Input points grid \"" + grid.getName() + "\" contains the " | |
737 | "internal point group \"__ax_dead\" which is used for deleting points. " | ||
738 | "points in this group may also be removed."); | ||
739 | } | ||
740 | else { | ||
741 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
8 | points::appendGroup(grid.tree(), "__ax_dead"); |
742 | } | ||
743 | } | ||
744 | |||
745 | const bool usingGroup = !mSettings->mGroup.empty(); | ||
746 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 746 times.
|
749 | if (usingGroup) { |
747 |
3/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
|
3 | if (!leafIter->attributeSet().descriptor().hasGroup(mSettings->mGroup)) { |
748 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
|
4 | logger->error("Requested point group \"" + mSettings->mGroup + |
749 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
7 | "\" on grid \"" + grid.getName() + "\" does not exist."); |
750 | } | ||
751 | else { | ||
752 | data.mGroupIndex = | ||
753 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | leafIter->attributeSet().groupIndex(mSettings->mGroup); |
754 | } | ||
755 | } | ||
756 | |||
757 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 748 times.
|
748 | if (logger->hasError()) return; |
758 | |||
759 | // Compute whether we can use the accelerated kernel | ||
760 | // @note Assumes attributes are valid (i.e. has errored out if they are not) | ||
761 | |||
762 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
763 |
2/2✓ Branch 0 taken 746 times.
✓ Branch 1 taken 2 times.
|
748 | if (!usingGroup) { |
764 | const auto& desc = leafIter->attributeSet().descriptor(); | ||
765 | 746 | data.mUseBufferKernel = checkCodecs(desc, *mAttributeRegistry, | |
766 |
1/2✓ Branch 1 taken 746 times.
✗ Branch 2 not taken.
|
746 | mSettings->mBindings, |
767 | data.mPositionAttribute); | ||
768 | } | ||
769 | else { | ||
770 | // if a group has been specified we can't use the buffer range yet | ||
771 | 2 | data.mUseBufferKernel = false; | |
772 | } | ||
773 | #else | ||
774 | // can't access data buffers until ABI >= 9 | ||
775 | data.mUseBufferKernel = false; | ||
776 | #endif | ||
777 | |||
778 | // execute | ||
779 | |||
780 |
1/2✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
|
1496 | LeafManagerT leafManager(grid.tree()); |
781 |
2/4✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 748 times.
✗ Branch 5 not taken.
|
1496 | std::vector<PointLeafLocalData::UniquePtr> leafLocalData(leafManager.leafCount()); |
782 | 748 | const bool threaded = mSettings->mGrainSize > 0; | |
783 | |||
784 | PointExecuterOp executerOp(data, leafLocalData); | ||
785 |
1/2✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
|
748 | leafManager.foreach(executerOp, threaded, mSettings->mGrainSize); |
786 | |||
787 | // Check to see if any new data has been added and apply it accordingly | ||
788 | |||
789 | std::set<std::string> groups; | ||
790 | bool newStrings = false; | ||
791 | |||
792 | { | ||
793 | points::StringMetaInserter | ||
794 |
2/4✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 748 times.
✗ Branch 5 not taken.
|
1496 | inserter(leafIter->attributeSet().descriptorPtr()->getMetadata()); |
795 |
2/2✓ Branch 0 taken 1486 times.
✓ Branch 1 taken 748 times.
|
2234 | for (const auto& leafData : leafLocalData) { |
796 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
1486 | leafData->getGroups(groups); |
797 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
1486 | newStrings |= leafData->insertNewStrings(inserter); |
798 | } | ||
799 | } | ||
800 | |||
801 | // append and copy over newly created groups | ||
802 | // @todo We should just be able to steal the arrays and compact | ||
803 | // groups but the API for this isn't very nice at the moment | ||
804 | |||
805 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 748 times.
|
759 | for (const auto& name : groups) { |
806 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | points::appendGroup(grid.tree(), name); |
807 | } | ||
808 | |||
809 | // add new groups and set strings | ||
810 | |||
811 |
1/2✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
|
748 | leafManager.foreach( |
812 | 1486 | [&groups, &leafLocalData, newStrings] (auto& leaf, size_t idx) { | |
813 | |||
814 | PointLeafLocalData::UniquePtr& leafData = leafLocalData[idx]; | ||
815 | |||
816 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1486 times.
|
1499 | for (const auto& name : groups) { |
817 | |||
818 | // Attempt to get the group handle out of the leaf local data form this | ||
819 | // leaf. This may not exist as although all of the unique set are appended | ||
820 | // to the tree (above), not every leaf may have been directly touched | ||
821 | // by every new group. Some leaf nodes may not require any bit mask copying | ||
822 | |||
823 | 13 | points::GroupWriteHandle* tmpHandle = leafData->get(name); | |
824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!tmpHandle) continue; |
825 | |||
826 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | points::GroupWriteHandle handle = leaf.groupWriteHandle(name); |
827 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
|
13 | if (tmpHandle->isUniform()) { |
828 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
|
12 | handle.collapse(tmpHandle->get(0)); |
829 | } | ||
830 | else { | ||
831 | const openvdb::Index size = tmpHandle->size(); | ||
832 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (openvdb::Index i = 0; i < size; ++i) { |
833 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | handle.set(i, tmpHandle->get(i)); |
834 | } | ||
835 | } | ||
836 | } | ||
837 | |||
838 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1438 times.
|
1486 | if (newStrings) { |
839 | 48 | const MetaMap& metadata = leaf.attributeSet().descriptor().getMetadata(); | |
840 | const PointLeafLocalData::StringArrayMap& stringArrayMap = leafData->getStringArrayMap(); | ||
841 | |||
842 |
2/2✓ Branch 0 taken 148 times.
✓ Branch 1 taken 48 times.
|
196 | for (const auto& arrayIter : stringArrayMap) { |
843 | 148 | points::StringAttributeWriteHandle::Ptr handle = | |
844 |
1/2✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
|
148 | points::StringAttributeWriteHandle::create(*(arrayIter.first), metadata); |
845 | |||
846 |
2/2✓ Branch 0 taken 185 times.
✓ Branch 1 taken 148 times.
|
333 | for (const auto& iter : arrayIter.second) { |
847 |
1/2✓ Branch 1 taken 185 times.
✗ Branch 2 not taken.
|
185 | handle->set(static_cast<Index>(iter.first), iter.second); |
848 | } | ||
849 | } | ||
850 | } | ||
851 | 1486 | }, threaded, mSettings->mGrainSize); | |
852 | |||
853 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 744 times.
|
748 | if (data.mPositionAccess.second) { |
854 | // if position is writable, sort the points | ||
855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (usingGroup) { |
856 | openvdb::points::GroupFilter filter(data.mGroupIndex); | ||
857 | ✗ | PointExecuterDeformer<openvdb::points::GroupFilter> deformer(data.mPositionAttribute, filter); | |
858 | ✗ | openvdb::points::movePoints(grid, deformer); | |
859 | } | ||
860 | else { | ||
861 | PointExecuterDeformer<> deformer(data.mPositionAttribute); | ||
862 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
4 | openvdb::points::movePoints(grid, deformer); |
863 | } | ||
864 | } | ||
865 | |||
866 |
3/4✓ Branch 0 taken 742 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 742 times.
|
748 | if (data.mPositionAccess.first || data.mPositionAccess.second) { |
867 | // remove temporary world space storage | ||
868 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | points::dropAttribute(grid.tree(), data.mPositionAttribute); |
869 | } | ||
870 | |||
871 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 744 times.
|
748 | if (mSettings->mPostDelete) { |
872 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
8 | points::deleteFromGroup(grid.tree(), "__ax_dead", false, /*drop=*/true); |
873 | } | ||
874 | } | ||
875 | |||
876 | |||
877 | ///////////////////////////////////////////// | ||
878 | ///////////////////////////////////////////// | ||
879 | |||
880 | |||
881 | 725 | void PointExecutable::setCreateMissing(const bool flag) | |
882 | { | ||
883 | 725 | mSettings->mCreateMissing = flag; | |
884 | 725 | } | |
885 | |||
886 | ✗ | bool PointExecutable::getCreateMissing() const | |
887 | { | ||
888 | ✗ | return mSettings->mCreateMissing; | |
889 | } | ||
890 | |||
891 | // void PointExecutable::setValueIterator(const PointExecutable::IterType& iter) | ||
892 | // { | ||
893 | // mSettings->mValueIterator = iter; | ||
894 | // } | ||
895 | |||
896 | // PointExecutable::IterType PointExecutable::getValueIterator() const | ||
897 | // { | ||
898 | // return mSettings->mValueIterator; | ||
899 | // } | ||
900 | |||
901 | ✗ | void PointExecutable::setGrainSize(const size_t grain) | |
902 | { | ||
903 | ✗ | mSettings->mGrainSize = grain; | |
904 | } | ||
905 | |||
906 | ✗ | size_t PointExecutable::getGrainSize() const | |
907 | { | ||
908 | ✗ | return mSettings->mGrainSize; | |
909 | } | ||
910 | |||
911 | 1 | void PointExecutable::setGroupExecution(const std::string& group) | |
912 | { | ||
913 | 1 | mSettings->mGroup = group; | |
914 | 1 | } | |
915 | |||
916 | ✗ | const std::string& PointExecutable::getGroupExecution() const | |
917 | { | ||
918 | ✗ | return mSettings->mGroup; | |
919 | } | ||
920 | |||
921 | 19 | void PointExecutable::setAttributeBindings(const AttributeBindings& bindings) | |
922 | { | ||
923 | //@todo: warn when inferred P, Cd, N etc are bound they default to vec3f | ||
924 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 19 times.
|
38 | for (const auto& binding : bindings.axToDataMap()) { |
925 | 19 | mSettings->mBindings.set(binding.first, binding.second); | |
926 | } | ||
927 | |||
928 | // check the registry to make sure everything is bound | ||
929 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 18 times.
|
53 | for (const auto& access : mAttributeRegistry->data()) { |
930 | if (!mSettings->mBindings.isBoundAXName(access.name())) { | ||
931 | if (bindings.isBoundDataName(access.name())) { | ||
932 |
6/14✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
|
8 | OPENVDB_THROW(AXExecutionError, "AX attribute \"@" |
933 | + access.name() + "\" not bound to any point attribute." | ||
934 | " Point attribute \"" + access.name() + "\" bound to \"@" | ||
935 | + *bindings.axNameBoundTo(access.name()) + "\"."); | ||
936 | } | ||
937 | else { | ||
938 | // rebind to itself as it may have been unbound | ||
939 | // by a previous set call | ||
940 | 1 | mSettings->mBindings.set(access.name(), access.name()); | |
941 | } | ||
942 | } | ||
943 | } | ||
944 | 18 | } | |
945 | |||
946 | 1 | const AttributeBindings& PointExecutable::getAttributeBindings() const | |
947 | { | ||
948 | 1 | return mSettings->mBindings; | |
949 | } | ||
950 | |||
951 | // | ||
952 | |||
953 | 3 | bool PointExecutable::usesAcceleratedKernel(const points::PointDataTree& tree) const | |
954 | { | ||
955 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (tree.empty()) return true; |
956 | |||
957 | // deep copy the Descriptor | ||
958 | |||
959 | const auto leafIter = tree.cbeginLeaf(); | ||
960 | points::AttributeSet::Descriptor::Ptr desc( | ||
961 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | new points::AttributeSet::Descriptor(leafIter->attributeSet().descriptor())); |
962 | |||
963 | // add any attributes which don't exist for the codec check | ||
964 | |||
965 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
|
18 | for (const auto& iter : mAttributeRegistry->data()) { |
966 | // get the corresponding point attributes | ||
967 | const std::string* nameptr = mSettings->mBindings.dataNameBoundTo(iter.name()); | ||
968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (!nameptr) continue; |
969 | const std::string& name = *nameptr; | ||
970 |
2/4✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
|
15 | if (points::AttributeSet::INVALID_POS == desc->find(name)) { |
971 | ✗ | const NamePair type = typePairFromToken(iter.type()); | |
972 | ✗ | desc = desc->duplicateAppend(name, type); | |
973 | } | ||
974 | } | ||
975 | |||
976 | // If P is being written or read from it is implicitly converted | ||
977 | // to an uncompressed attribute, so make sure P is not compressed | ||
978 | |||
979 |
6/12✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
9 | desc = desc->duplicateDrop({desc->find("P")}); |
980 |
3/8✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
6 | desc = desc->duplicateAppend("P", typePairFromToken(ast::tokens::CoreType::VEC3F)); |
981 | |||
982 |
3/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
6 | return checkCodecs(*desc, *mAttributeRegistry, |
983 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | mSettings->mBindings, "P"); |
984 | } | ||
985 | |||
986 | |||
987 | } // namespace ax | ||
988 | } // namespace OPENVDB_VERSION_NAME | ||
989 | } // namespace openvdb | ||
990 | |||
991 |