GCC Code Coverage Report


Directory: ./
File: openvdb_ax/openvdb_ax/codegen/PointLeafLocalData.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 42 44 95.5%
Functions: 8 8 100.0%
Branches: 35 46 76.1%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file codegen/PointLeafLocalData.h
5 ///
6 /// @authors Nick Avramoussis
7 ///
8 /// @brief Thread/Leaf local data used during execution over OpenVDB Points
9 ///
10
11 #ifndef OPENVDB_AX_COMPILER_LEAF_LOCAL_DATA_HAS_BEEN_INCLUDED
12 #define OPENVDB_AX_COMPILER_LEAF_LOCAL_DATA_HAS_BEEN_INCLUDED
13
14 #include <openvdb/openvdb.h>
15 #include <openvdb/version.h>
16 #include <openvdb/points/AttributeArray.h>
17 #include <openvdb/points/PointAttribute.h>
18 #include <openvdb/points/PointDataGrid.h>
19 #include <openvdb/points/PointGroup.h>
20
21 namespace openvdb {
22 OPENVDB_USE_VERSION_NAMESPACE
23 namespace OPENVDB_VERSION_NAME {
24
25 namespace ax {
26 namespace codegen {
27
28 namespace codegen_internal {
29
30
31 /// @brief Various functions can request the use and initialization of point data from within
32 /// the kernel that does not use the standard attribute handle methods. This data can
33 /// then be accessed after execution to perform post-processes such as adding new groups,
34 /// adding new string attributes or updating positions.
35 ///
36 /// @note Due to the way string handles work, string write attribute handles cannot
37 /// be constructed in parallel, nor can read handles retrieve values in parallel
38 /// if there is a chance the shared metadata is being written to (with set()).
39 /// As the compiler allows for any arbitrary string setting/getting, leaf local
40 /// maps are used for temporary storage per point. The maps use the string array
41 /// pointers as a key for later synchronization.
42 ///
43 struct PointLeafLocalData
44 {
45 using UniquePtr = std::unique_ptr<PointLeafLocalData>;
46 using GroupArrayT = openvdb::points::GroupAttributeArray;
47 using GroupHandleT = openvdb::points::GroupWriteHandle;
48
49 using PointStringMap = std::map<uint64_t, std::string>;
50 using StringArrayMap = std::map<points::AttributeArray*, PointStringMap>;
51
52 using LeafNode = openvdb::points::PointDataTree::LeafNodeType;
53
54 /// @brief Construct a new data object to keep track of various data objects
55 /// created per leaf by the point compute generator.
56 ///
57 /// @param count The number of points within the current leaf, used to initialize
58 /// the size of new arrays
59 ///
60 PointLeafLocalData(const size_t count)
61 1486 : mPointCount(count)
62 , mArrays()
63 , mOffset(0)
64 , mHandles()
65 1486 , mStringMap() {}
66
67 ////////////////////////////////////////////////////////////////////////
68
69 /// Group methods
70
71 /// @brief Return a group write handle to a specific group name, creating the
72 /// group array if it doesn't exist. This includes either registering a
73 /// new offset or allocating an entire array. The returned handle is
74 /// guaranteed to be valid.
75 ///
76 /// @param name The group name
77 ///
78 43 inline GroupHandleT* getOrInsert(const std::string& name)
79 {
80 43 GroupHandleT* ptr = get(name);
81
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30 times.
43 if (ptr) return ptr;
82
83 static const size_t maxGroupsInArray =
84 #if (OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER > 7 || \
85 (OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER >= 7 && \
86 OPENVDB_LIBRARY_MINOR_VERSION_NUMBER >= 1))
87
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
13 points::AttributeSet::Descriptor::groupBits();
88 #else
89 // old removed method
90 points::point_group_internal::GroupInfo::groupBits();
91 #endif
92
93
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
13 if (mArrays.empty() || mOffset == maxGroupsInArray) {
94
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(mPointCount < static_cast<size_t>(std::numeric_limits<openvdb::Index>::max()));
95
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 mArrays.emplace_back(new GroupArrayT(static_cast<openvdb::Index>(mPointCount)));
96 6 mOffset = 0;
97 }
98
99 GroupArrayT* array = mArrays.back().get();
100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 assert(array);
101
102 13 std::unique_ptr<GroupHandleT>& handle = mHandles[name];
103
1/2
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
26 handle.reset(new GroupHandleT(*array, mOffset++));
104 13 return handle.get();
105 }
106
107 /// @brief Return a group write handle to a specific group name if it exists.
108 /// Returns a nullptr if no group exists of the given name
109 ///
110 /// @param name The group name
111 ///
112 86 inline GroupHandleT* get(const std::string& name) const
113 {
114
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 39 times.
86 const auto iter = mHandles.find(name);
115
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 39 times.
86 if (iter == mHandles.end()) return nullptr;
116 47 return iter->second.get();
117 }
118
119 /// @brief Return true if a valid group handle exists
120 ///
121 /// @param name The group name
122 ///
123 inline bool hasGroup(const std::string& name) const {
124
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 return mHandles.find(name) != mHandles.end();
125 }
126
127 /// @brief Populate a set with all the groups which have been inserted into
128 /// this object. Used to compute a final set of all new groups which
129 /// have been created across all leaf nodes
130 ///
131 /// @param groups The set to populate
132 ///
133 1486 inline void getGroups(std::set<std::string>& groups) const {
134
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1486 times.
1499 for (const auto& iter : mHandles) {
135 13 groups.insert(iter.first);
136 }
137 1486 }
138
139 /// @brief Compact all arrays stored on this object. This does not invalidate
140 /// any active write handles.
141 ///
142 1486 inline void compact() {
143
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1486 times.
1492 for (auto& array : mArrays) array->compact();
144 1486 }
145
146
147 ////////////////////////////////////////////////////////////////////////
148
149 /// String methods
150
151 /// @brief Get any new string data associated with a particular point on a
152 /// particular string attribute array. Returns true if data was set,
153 /// false if no data was found.
154 ///
155 /// @param array The array pointer to use as a key lookup
156 /// @param idx The point index
157 /// @param data The string to set if data is stored
158 ///
159 inline bool
160 225 getNewStringData(const points::AttributeArray* array, const uint64_t idx, std::string& data) const {
161
2/2
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 188 times.
225 const auto arrayMapIter = mStringMap.find(const_cast<points::AttributeArray*>(array));
162
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 188 times.
225 if (arrayMapIter == mStringMap.end()) return false;
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 const auto iter = arrayMapIter->second.find(idx);
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (iter == arrayMapIter->second.end()) return false;
165 data = iter->second;
166 return true;
167 }
168
169 /// @brief Set new string data associated with a particular point on a
170 /// particular string attribute array.
171 ///
172 /// @param array The array pointer to use as a key lookup
173 /// @param idx The point index
174 /// @param data The string to set
175 ///
176 inline void
177 185 setNewStringData(points::AttributeArray* array, const uint64_t idx, const std::string& data) {
178 185 mStringMap[array][idx] = data;
179 185 }
180
181 /// @brief Remove any new string data associated with a particular point on a
182 /// particular string attribute array. Does nothing if no data exists
183 ///
184 /// @param array The array pointer to use as a key lookup
185 /// @param idx The point index
186 ///
187 inline void
188 25 removeNewStringData(points::AttributeArray* array, const uint64_t idx) {
189
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 const auto arrayMapIter = mStringMap.find(array);
190
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (arrayMapIter == mStringMap.end()) return;
191 arrayMapIter->second.erase(idx);
192 if (arrayMapIter->second.empty()) mStringMap.erase(arrayMapIter);
193 }
194
195 /// @brief Insert all new point strings stored across all collected string
196 /// attribute arrays into a StringMetaInserter. Returns false if the
197 /// inserter was not accessed and true if it was potentially modified.
198 ///
199 /// @param inserter The string meta inserter to update
200 ///
201 inline bool
202 1486 insertNewStrings(points::StringMetaInserter& inserter) const {
203
2/2
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 1486 times.
1634 for (const auto& arrayIter : mStringMap) {
204
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 148 times.
333 for (const auto& iter : arrayIter.second) {
205 185 inserter.insert(iter.second);
206 }
207 }
208 1486 return !mStringMap.empty();
209 }
210
211 /// @brief Returns a const reference to the string array map
212 ///
213 inline const StringArrayMap& getStringArrayMap() const {
214 return mStringMap;
215 }
216
217 private:
218
219 const size_t mPointCount;
220 std::vector<std::unique_ptr<GroupArrayT>> mArrays;
221 points::GroupType mOffset;
222 std::map<std::string, std::unique_ptr<GroupHandleT>> mHandles;
223 StringArrayMap mStringMap;
224 };
225
226 } // codegen_internal
227
228 } // namespace compiler
229 } // namespace ax
230 } // namespace OPENVDB_VERSION_NAME
231 } // namespace openvdb
232
233 #endif // OPENVDB_AX_COMPILER_LEAF_LOCAL_DATA_HAS_BEEN_INCLUDED
234
235