Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0/ | ||
3 | |||
4 | /// @file compiler/AttributeRegistry.h | ||
5 | /// | ||
6 | /// @authors Nick Avramoussis, Francisco Gochez | ||
7 | /// | ||
8 | /// @brief These classes contain lists of expected attributes and volumes | ||
9 | /// which are populated by compiler during its internal code generation. | ||
10 | /// These will then be requested from the inputs to the executable | ||
11 | /// when execute is called. In this way, accesses are requested at | ||
12 | /// execution time, allowing the executable objects to be shared and | ||
13 | /// stored. | ||
14 | /// | ||
15 | |||
16 | #ifndef OPENVDB_AX_COMPILER_TARGET_REGISTRY_HAS_BEEN_INCLUDED | ||
17 | #define OPENVDB_AX_COMPILER_TARGET_REGISTRY_HAS_BEEN_INCLUDED | ||
18 | |||
19 | #include "../ast/AST.h" | ||
20 | #include "../ast/Tokens.h" | ||
21 | #include "../ast/Scanners.h" | ||
22 | |||
23 | #include <openvdb/version.h> | ||
24 | #include <openvdb/Types.h> | ||
25 | #include <openvdb/util/Name.h> | ||
26 | |||
27 | #include <unordered_map> | ||
28 | |||
29 | namespace openvdb { | ||
30 | OPENVDB_USE_VERSION_NAMESPACE | ||
31 | namespace OPENVDB_VERSION_NAME { | ||
32 | |||
33 | namespace ax { | ||
34 | |||
35 | /// @brief This class stores a list of access names, types and their dependency | ||
36 | /// connections. | ||
37 | /// | ||
38 | 1537 | class AttributeRegistry | |
39 | { | ||
40 | public: | ||
41 | using Ptr = std::shared_ptr<AttributeRegistry>; | ||
42 | using ConstPtr = std::shared_ptr<const AttributeRegistry>; | ||
43 | |||
44 | /// @brief Registered access details, including its name, type and whether | ||
45 | /// a write handle is required | ||
46 | /// | ||
47 | struct AccessData | ||
48 | { | ||
49 | /// @brief Storage for access name, type and writesTo details | ||
50 | /// @param name The name of the access | ||
51 | /// @param type The typename of the access | ||
52 | /// @param readsFrom Whether the access is read from | ||
53 | /// @param writesTo Whether the access is written to | ||
54 | AccessData(const Name& name, | ||
55 | const ast::tokens::CoreType type, | ||
56 | const bool readsFrom, | ||
57 | const bool writesTo) | ||
58 |
1/2✓ Branch 1 taken 5132 times.
✗ Branch 2 not taken.
|
10149 | : mAttrib(name, type) |
59 | , mAccess(readsFrom, writesTo) | ||
60 | , mUses() | ||
61 | , mDependencies() {} | ||
62 | |||
63 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5062 times.
|
5402 | bool reads() const { return mAccess.first; } |
64 |
8/8✓ Branch 0 taken 286 times.
✓ Branch 1 taken 9866 times.
✓ Branch 2 taken 146 times.
✓ Branch 3 taken 4940 times.
✓ Branch 4 taken 9996 times.
✓ Branch 5 taken 139 times.
✓ Branch 6 taken 4915 times.
✓ Branch 7 taken 139 times.
|
30427 | bool writes() const { return mAccess.second; } |
65 | 50328 | const std::string tokenname() const { return mAttrib.tokenname(); } | |
66 | const std::string& name() const { return mAttrib.name(); } | ||
67 | ast::tokens::CoreType type() const { return mAttrib.type(); } | ||
68 | const std::vector<const AccessData*>& deps() const { return mDependencies; } | ||
69 | const std::vector<const AccessData*>& uses() const { return mUses; } | ||
70 | |||
71 | 128215 | bool dependson(const AccessData* data) const { | |
72 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 128215 times.
|
128215 | assert(data); |
73 |
2/2✓ Branch 0 taken 27843 times.
✓ Branch 1 taken 124770 times.
|
152613 | for (auto& dep : mDependencies) { |
74 |
2/2✓ Branch 0 taken 3445 times.
✓ Branch 1 taken 24398 times.
|
27843 | if (dep == data) return true; |
75 | } | ||
76 | 124770 | return false; | |
77 | } | ||
78 | |||
79 | bool affectsothers() const { | ||
80 |
4/4✓ Branch 0 taken 212 times.
✓ Branch 1 taken 3541 times.
✓ Branch 2 taken 972 times.
✓ Branch 3 taken 4581 times.
|
9306 | for (auto& dep : mUses) { |
81 |
5/6✓ Branch 0 taken 186 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 334 times.
✓ Branch 3 taken 638 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 334 times.
|
1184 | if (dep != this) return true; |
82 | } | ||
83 | return false; | ||
84 | } | ||
85 | |||
86 | private: | ||
87 | friend AttributeRegistry; | ||
88 | |||
89 | const ast::Attribute mAttrib; | ||
90 | const std::pair<bool, bool> mAccess; | ||
91 | std::vector<const AccessData*> mUses; // Accesses which depend on this access | ||
92 | std::vector<const AccessData*> mDependencies; // Accesses which this access depends on | ||
93 | }; | ||
94 | |||
95 | using AccessDataVec = std::vector<AccessData>; | ||
96 | |||
97 | inline static AttributeRegistry::Ptr create(const ast::Tree& tree); | ||
98 | |||
99 | inline bool isReadable(const std::string& name, const ast::tokens::CoreType type) const | ||
100 | { | ||
101 | return this->accessPattern(name, type).first; | ||
102 | } | ||
103 | |||
104 | /// @brief Returns whether or not an access is required to be written to. | ||
105 | /// If no access with this name has been registered, returns false | ||
106 | /// @param name The name of the access | ||
107 | /// @param type The type of the access | ||
108 | inline bool isWritable(const std::string& name, const ast::tokens::CoreType type) const | ||
109 | { | ||
110 | return this->accessPattern(name, type).second; | ||
111 | } | ||
112 | |||
113 | inline std::pair<bool,bool> | ||
114 | accessPattern(const std::string& name, const ast::tokens::CoreType type) const | ||
115 | { | ||
116 | auto* data = this->get(name, type); | ||
117 | if (!data) return std::pair<bool,bool>(false,false); | ||
118 | return data->mAccess; | ||
119 | } | ||
120 | |||
121 | /// @brief Returns whether or not an access is registered. | ||
122 | /// @param name The name of the access | ||
123 | /// @param type The type of the access | ||
124 | inline bool isRegistered(const std::string& name, const ast::tokens::CoreType type) const | ||
125 | { | ||
126 | return this->accessIndex(name, type) != -1; | ||
127 | } | ||
128 | |||
129 | /// @brief Returns whether or not an access is registered. | ||
130 | /// @param name The name of the access | ||
131 | /// @param type The type of the access | ||
132 | inline int64_t | ||
133 | 10145 | accessIndex(const std::string& name, | |
134 | const ast::tokens::CoreType type) const | ||
135 | { | ||
136 | int64_t i = 0; | ||
137 |
1/2✓ Branch 0 taken 68747 times.
✗ Branch 1 not taken.
|
68747 | for (const auto& data : mAccesses) { |
138 |
4/4✓ Branch 0 taken 49015 times.
✓ Branch 1 taken 19732 times.
✓ Branch 2 taken 10145 times.
✓ Branch 3 taken 38870 times.
|
68747 | if (data.type() == type && data.name() == name) { |
139 | 10145 | return i; | |
140 | } | ||
141 | 58602 | ++i; | |
142 | } | ||
143 | ✗ | return -1; | |
144 | } | ||
145 | |||
146 | const AccessData* | ||
147 | 1428 | get(const std::string& name, const ast::tokens::CoreType type) const | |
148 | { | ||
149 |
2/2✓ Branch 0 taken 8219 times.
✓ Branch 1 taken 3 times.
|
8222 | for (const auto& data : mAccesses) { |
150 |
2/2✓ Branch 0 taken 6520 times.
✓ Branch 1 taken 1699 times.
|
8219 | if ((type == ast::tokens::UNKNOWN || data.type() == type) |
151 |
3/4✓ Branch 0 taken 8219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1425 times.
✓ Branch 3 taken 5095 times.
|
14739 | && data.name() == name) { |
152 | 1425 | return &data; | |
153 | } | ||
154 | } | ||
155 | 3 | return nullptr; | |
156 | } | ||
157 | |||
158 | /// @brief Returns a const reference to the vector of registered accesss | ||
159 | inline const AccessDataVec& data() const { return mAccesses; } | ||
160 | |||
161 | void print(std::ostream& os) const; | ||
162 | |||
163 | private: | ||
164 | AttributeRegistry() : mAccesses() {} | ||
165 | |||
166 | /// @brief Add an access to the registry, returns an index into | ||
167 | /// the registry for that access | ||
168 | /// @param name The name of the access | ||
169 | /// @param type The typename of the access | ||
170 | /// @param writesTo Whether the access is required to be writeable | ||
171 | /// | ||
172 | inline void | ||
173 | addData(const Name& name, | ||
174 | const ast::tokens::CoreType type, | ||
175 | const bool readsfrom, | ||
176 | const bool writesto) { | ||
177 |
1/2✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
|
10149 | mAccesses.emplace_back(name, type, readsfrom, writesto); |
178 | 10149 | } | |
179 | |||
180 | AccessDataVec mAccesses; | ||
181 | }; | ||
182 | |||
183 | |||
184 | ///////////////////////////////////////////////////////////////////// | ||
185 | ///////////////////////////////////////////////////////////////////// | ||
186 | |||
187 | |||
188 | 1537 | inline AttributeRegistry::Ptr AttributeRegistry::create(const ast::Tree& tree) | |
189 | { | ||
190 | 1537 | AttributeRegistry::Ptr registry(new AttributeRegistry()); | |
191 | 1537 | std::vector<std::string> read, write, all; | |
192 |
1/2✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
|
1537 | ast::catalogueAttributeTokens(tree, &read, &write, &all); |
193 | |||
194 |
1/2✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
|
1537 | size_t idx = 0; |
195 | std::unordered_map<std::string, size_t> indexmap; | ||
196 | |||
197 | auto dataBuilder = | ||
198 | 4611 | [&](const std::vector<std::string>& attribs, | |
199 | const bool readFlag, | ||
200 | const bool writeFlag) | ||
201 | { | ||
202 | std::string name, type; | ||
203 |
2/2✓ Branch 0 taken 10149 times.
✓ Branch 1 taken 4611 times.
|
14760 | for (const auto& attrib : attribs) { |
204 |
1/2✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
|
10149 | ast::Attribute::nametypeFromToken(attrib, &name, &type); |
205 | const ast::tokens::CoreType typetoken = | ||
206 | 10149 | ast::tokens::tokenFromTypeString(type); | |
207 |
1/2✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
|
10149 | registry->addData(name, typetoken, readFlag, writeFlag); |
208 |
1/2✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
|
10149 | indexmap[attrib] = idx++; |
209 | } | ||
210 | 4611 | }; | |
211 | |||
212 | // insert all data | ||
213 | |||
214 |
1/2✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
|
1537 | dataBuilder(read, true, false); |
215 |
1/2✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
|
1537 | dataBuilder(write, false, true); |
216 |
1/2✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
|
1537 | dataBuilder(all, true, true); |
217 | |||
218 | 4611 | auto depBuilder = [&](const std::vector<std::string>& attribs) { | |
219 | |||
220 | std::string name, type; | ||
221 |
2/2✓ Branch 0 taken 10149 times.
✓ Branch 1 taken 4611 times.
|
14760 | for (const auto& attrib : attribs) { |
222 |
1/2✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
|
10149 | ast::Attribute::nametypeFromToken(attrib, &name, &type); |
223 | const ast::tokens::CoreType typetoken = | ||
224 | 10149 | ast::tokens::tokenFromTypeString(type); | |
225 | |||
226 | 2277 | std::vector<std::string> deps; | |
227 |
1/2✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
|
10149 | ast::attributeDependencyTokens(tree, name, typetoken, deps); |
228 |
2/2✓ Branch 0 taken 7872 times.
✓ Branch 1 taken 2277 times.
|
10149 | if (deps.empty()) continue; |
229 | |||
230 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 2277 times.
✓ Branch 5 taken 2277 times.
✗ Branch 6 not taken.
|
5062 | assert(indexmap.find(attrib) != indexmap.cend()); |
231 | 2277 | const size_t index = indexmap.at(attrib); | |
232 | 2277 | AccessData& access = registry->mAccesses[index]; | |
233 |
2/2✓ Branch 0 taken 2785 times.
✓ Branch 1 taken 2277 times.
|
5062 | for (const std::string& dep : deps) { |
234 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 2785 times.
✓ Branch 4 taken 2785 times.
✗ Branch 5 not taken.
|
2785 | assert(indexmap.find(dep) != indexmap.cend()); |
235 | 2785 | const size_t depindex = indexmap.at(dep); | |
236 |
1/2✓ Branch 1 taken 2785 times.
✗ Branch 2 not taken.
|
2785 | access.mDependencies.emplace_back(®istry->mAccesses[depindex]); |
237 | } | ||
238 | } | ||
239 | 4611 | }; | |
240 | |||
241 | // initialize dependencies | ||
242 | |||
243 |
1/2✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
|
1537 | depBuilder(read); |
244 |
1/2✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
|
1537 | depBuilder(write); |
245 |
1/2✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
|
1537 | depBuilder(all); |
246 | |||
247 | // Update usage from deps | ||
248 | |||
249 |
2/2✓ Branch 0 taken 10149 times.
✓ Branch 1 taken 1537 times.
|
11686 | for (AccessData& access : registry->mAccesses) { |
250 |
2/2✓ Branch 0 taken 127353 times.
✓ Branch 1 taken 10149 times.
|
137502 | for (const AccessData& next : registry->mAccesses) { |
251 | // don't skip self depends as it may write to itself | ||
252 | // i.e. @a = @a + 1; should add a self usage | ||
253 |
2/2✓ Branch 1 taken 2785 times.
✓ Branch 2 taken 124568 times.
|
127353 | if (next.dependson(&access)) { |
254 |
1/2✓ Branch 1 taken 2785 times.
✗ Branch 2 not taken.
|
2785 | access.mUses.emplace_back(&next); |
255 | } | ||
256 | } | ||
257 | } | ||
258 | |||
259 | 1537 | return registry; | |
260 | } | ||
261 | |||
262 | inline void AttributeRegistry::print(std::ostream& os) const | ||
263 | { | ||
264 | size_t idx = 0; | ||
265 | for (const auto& data : mAccesses) { | ||
266 | os << "Attribute: " << data.name() << ", type: " << | ||
267 | ast::tokens::typeStringFromToken(data.type()) << '\n'; | ||
268 | os << " " << "Index : " << idx << '\n'; | ||
269 | os << std::boolalpha; | ||
270 | os << " " << "Reads From : " << data.reads() << '\n'; | ||
271 | os << " " << "Writes To : " << data.writes() << '\n'; | ||
272 | os << std::noboolalpha; | ||
273 | os << " " << "Dependencies : " << data.mDependencies.size() << '\n'; | ||
274 | for (const auto& dep : data.mDependencies) { | ||
275 | os << " " << "Attribute: " << dep->name() << " type: " << | ||
276 | ast::tokens::typeStringFromToken(dep->type()) << '\n'; | ||
277 | } | ||
278 | os << " " << "Usage : " << data.mUses.size() << '\n'; | ||
279 | for (const auto& dep : data.mUses) { | ||
280 | os << " " << "Attribute: " << dep->name() << " type: " << | ||
281 | ast::tokens::typeStringFromToken(dep->type()) << '\n'; | ||
282 | } | ||
283 | os << '\n'; | ||
284 | ++idx; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | } // namespace ax | ||
289 | } // namespace OPENVDB_VERSION_NAME | ||
290 | } // namespace openvdb | ||
291 | |||
292 | #endif // OPENVDB_AX_COMPILER_TARGET_REGISTRY_HAS_BEEN_INCLUDED | ||
293 | |||
294 |