OpenVDB  12.0.0
AttributeRegistry.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-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 #include <openvdb/util/Assert.h>
27 
28 #include <unordered_map>
29 
30 namespace openvdb {
32 namespace OPENVDB_VERSION_NAME {
33 
34 namespace ax {
35 
36 /// @brief This class stores a list of access names, types and their dependency
37 /// connections.
38 ///
40 {
41 public:
42  using Ptr = std::shared_ptr<AttributeRegistry>;
43  using ConstPtr = std::shared_ptr<const AttributeRegistry>;
44 
45  /// @brief Registered access details, including its name, type and whether
46  /// a write handle is required
47  ///
48  struct AccessData
49  {
50  /// @brief Storage for access name, type and writesTo details
51  /// @param name The name of the access
52  /// @param type The typename of the access
53  /// @param readsFrom Whether the access is read from
54  /// @param writesTo Whether the access is written to
55  AccessData(const Name& name,
56  const ast::tokens::CoreType type,
57  const bool readsFrom,
58  const bool writesTo)
59  : mAttrib(name, type)
60  , mAccess(readsFrom, writesTo)
61  , mUses()
62  , mDependencies() {}
63 
64  bool reads() const { return mAccess.first; }
65  bool writes() const { return mAccess.second; }
66  const std::string tokenname() const { return mAttrib.tokenname(); }
67  const std::string& name() const { return mAttrib.name(); }
68  ast::tokens::CoreType type() const { return mAttrib.type(); }
69  const std::vector<const AccessData*>& deps() const { return mDependencies; }
70  const std::vector<const AccessData*>& uses() const { return mUses; }
71 
72  bool dependson(const AccessData* data) const {
73  OPENVDB_ASSERT(data);
74  for (auto& dep : mDependencies) {
75  if (dep == data) return true;
76  }
77  return false;
78  }
79 
80  bool affectsothers() const {
81  for (auto& dep : mUses) {
82  if (dep != this) return true;
83  }
84  return false;
85  }
86 
87  private:
88  friend AttributeRegistry;
89 
90  const ast::Attribute mAttrib;
91  const std::pair<bool, bool> mAccess;
92  std::vector<const AccessData*> mUses; // Accesses which depend on this access
93  std::vector<const AccessData*> mDependencies; // Accesses which this access depends on
94  };
95 
96  using AccessDataVec = std::vector<AccessData>;
97 
98  inline static AttributeRegistry::Ptr create(const ast::Tree& tree);
99 
100  inline bool isReadable(const std::string& name, const ast::tokens::CoreType type) const
101  {
102  return this->accessPattern(name, type).first;
103  }
104 
105  /// @brief Returns whether or not an access is required to be written to.
106  /// If no access with this name has been registered, returns false
107  /// @param name The name of the access
108  /// @param type The type of the access
109  inline bool isWritable(const std::string& name, const ast::tokens::CoreType type) const
110  {
111  return this->accessPattern(name, type).second;
112  }
113 
114  inline std::pair<bool,bool>
115  accessPattern(const std::string& name, const ast::tokens::CoreType type) const
116  {
117  auto* data = this->get(name, type);
118  if (!data) return std::pair<bool,bool>(false,false);
119  return data->mAccess;
120  }
121 
122  /// @brief Returns whether or not an access is registered.
123  /// @param name The name of the access
124  /// @param type The type of the access
125  inline bool isRegistered(const std::string& name, const ast::tokens::CoreType type) const
126  {
127  return this->accessIndex(name, type) != -1;
128  }
129 
130  /// @brief Returns whether or not an access is registered.
131  /// @param name The name of the access
132  /// @param type The type of the access
133  inline int64_t
134  accessIndex(const std::string& name,
135  const ast::tokens::CoreType type) const
136  {
137  int64_t i = 0;
138  for (const auto& data : mAccesses) {
139  if (data.type() == type && data.name() == name) {
140  return i;
141  }
142  ++i;
143  }
144  return -1;
145  }
146 
147  const AccessData*
148  get(const std::string& name, const ast::tokens::CoreType type) const
149  {
150  for (const auto& data : mAccesses) {
151  if ((type == ast::tokens::UNKNOWN || data.type() == type)
152  && data.name() == name) {
153  return &data;
154  }
155  }
156  return nullptr;
157  }
158 
159  /// @brief Returns a const reference to the vector of registered accesss
160  inline const AccessDataVec& data() const { return mAccesses; }
161 
162  void print(std::ostream& os) const;
163 
164 private:
165  AttributeRegistry() : mAccesses() {}
166 
167  /// @brief Add an access to the registry, returns an index into
168  /// the registry for that access
169  /// @param name The name of the access
170  /// @param type The typename of the access
171  /// @param writesTo Whether the access is required to be writeable
172  ///
173  inline void
174  addData(const Name& name,
175  const ast::tokens::CoreType type,
176  const bool readsfrom,
177  const bool writesto) {
178  mAccesses.emplace_back(name, type, readsfrom, writesto);
179  }
180 
181  AccessDataVec mAccesses;
182 };
183 
184 
185 /////////////////////////////////////////////////////////////////////
186 /////////////////////////////////////////////////////////////////////
187 
188 
189 inline AttributeRegistry::Ptr AttributeRegistry::create(const ast::Tree& tree)
190 {
192  std::vector<std::string> read, write, all;
193  ast::catalogueAttributeTokens(tree, &read, &write, &all);
194 
195  size_t idx = 0;
196  std::unordered_map<std::string, size_t> indexmap;
197 
198  auto dataBuilder =
199  [&](const std::vector<std::string>& attribs,
200  const bool readFlag,
201  const bool writeFlag)
202  {
203  std::string name, type;
204  for (const auto& attrib : attribs) {
205  ast::Attribute::nametypeFromToken(attrib, &name, &type);
206  const ast::tokens::CoreType typetoken =
208  registry->addData(name, typetoken, readFlag, writeFlag);
209  indexmap[attrib] = idx++;
210  }
211  };
212 
213  // insert all data
214 
215  dataBuilder(read, true, false);
216  dataBuilder(write, false, true);
217  dataBuilder(all, true, true);
218 
219  auto depBuilder = [&](const std::vector<std::string>& attribs) {
220 
221  std::string name, type;
222  for (const auto& attrib : attribs) {
223  ast::Attribute::nametypeFromToken(attrib, &name, &type);
224  const ast::tokens::CoreType typetoken =
226 
227  std::vector<std::string> deps;
228  ast::attributeDependencyTokens(tree, name, typetoken, deps);
229  if (deps.empty()) continue;
230 
231  OPENVDB_ASSERT(indexmap.find(attrib) != indexmap.cend());
232  const size_t index = indexmap.at(attrib);
233  AccessData& access = registry->mAccesses[index];
234  for (const std::string& dep : deps) {
235  OPENVDB_ASSERT(indexmap.find(dep) != indexmap.cend());
236  const size_t depindex = indexmap.at(dep);
237  access.mDependencies.emplace_back(&registry->mAccesses[depindex]);
238  }
239  }
240  };
241 
242  // initialize dependencies
243 
244  depBuilder(read);
245  depBuilder(write);
246  depBuilder(all);
247 
248  // Update usage from deps
249 
250  for (AccessData& access : registry->mAccesses) {
251  for (const AccessData& next : registry->mAccesses) {
252  // don't skip self depends as it may write to itself
253  // i.e. @a = @a + 1; should add a self usage
254  if (next.dependson(&access)) {
255  access.mUses.emplace_back(&next);
256  }
257  }
258  }
259 
260  return registry;
261 }
262 
263 inline void AttributeRegistry::print(std::ostream& os) const
264 {
265  size_t idx = 0;
266  for (const auto& data : mAccesses) {
267  os << "Attribute: " << data.name() << ", type: " <<
268  ast::tokens::typeStringFromToken(data.type()) << '\n';
269  os << " " << "Index : " << idx << '\n';
270  os << std::boolalpha;
271  os << " " << "Reads From : " << data.reads() << '\n';
272  os << " " << "Writes To : " << data.writes() << '\n';
273  os << std::noboolalpha;
274  os << " " << "Dependencies : " << data.mDependencies.size() << '\n';
275  for (const auto& dep : data.mDependencies) {
276  os << " " << "Attribute: " << dep->name() << " type: " <<
277  ast::tokens::typeStringFromToken(dep->type()) << '\n';
278  }
279  os << " " << "Usage : " << data.mUses.size() << '\n';
280  for (const auto& dep : data.mUses) {
281  os << " " << "Attribute: " << dep->name() << " type: " <<
282  ast::tokens::typeStringFromToken(dep->type()) << '\n';
283  }
284  os << '\n';
285  ++idx;
286  }
287 }
288 
289 } // namespace ax
290 } // namespace OPENVDB_VERSION_NAME
291 } // namespace openvdb
292 
293 #endif // OPENVDB_AX_COMPILER_TARGET_REGISTRY_HAS_BEEN_INCLUDED
294 
std::pair< bool, bool > accessPattern(const std::string &name, const ast::tokens::CoreType type) const
Definition: AttributeRegistry.h:115
Attributes represent any access to a primitive value, typically associated with the &#39;@&#39; symbol syntax...
Definition: AST.h:1874
const std::string & name() const
Definition: AttributeRegistry.h:67
A Tree is the highest concrete (non-abstract) node in the entire AX AST hierarchy. It represents an entire conversion of a valid AX string.
Definition: AST.h:562
bool reads() const
Definition: AttributeRegistry.h:64
std::shared_ptr< AttributeRegistry > Ptr
Definition: AttributeRegistry.h:42
std::vector< AccessData > AccessDataVec
Definition: AttributeRegistry.h:96
bool isRegistered(const std::string &name, const ast::tokens::CoreType type) const
Returns whether or not an access is registered.
Definition: AttributeRegistry.h:125
OPENVDB_AX_API void print(const ast::Node &node, const bool numberStatements=true, std::ostream &os=std::cout, const char *indent=" ")
Writes a descriptive printout of a Node hierarchy into a target stream.
bool writes() const
Definition: AttributeRegistry.h:65
const std::vector< const AccessData * > & deps() const
Definition: AttributeRegistry.h:69
bool affectsothers() const
Definition: AttributeRegistry.h:80
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
CoreType
Definition: Tokens.h:31
Definition: Exceptions.h:13
AccessData(const Name &name, const ast::tokens::CoreType type, const bool readsFrom, const bool writesTo)
Storage for access name, type and writesTo details.
Definition: AttributeRegistry.h:55
OPENVDB_AX_API void catalogueAttributeTokens(const ast::Node &node, std::vector< std::string > *readOnly, std::vector< std::string > *writeOnly, std::vector< std::string > *readWrite)
Parse all attributes into three unique vectors which represent how they are accessed within the synta...
ast::tokens::CoreType type() const
Definition: AttributeRegistry.h:68
const std::vector< const AccessData * > & uses() const
Definition: AttributeRegistry.h:70
std::string typeStringFromToken(const CoreType type)
Definition: Tokens.h:118
bool dependson(const AccessData *data) const
Definition: AttributeRegistry.h:72
OPENVDB_AX_API void attributeDependencyTokens(const ast::Tree &tree, const std::string &name, const tokens::CoreType type, std::vector< std::string > &dependencies)
Populate a list of attribute names which the given attribute depends on.
Registered access details, including its name, type and whether a write handle is required...
Definition: AttributeRegistry.h:48
const AccessDataVec & data() const
Returns a const reference to the vector of registered accesss.
Definition: AttributeRegistry.h:160
This class stores a list of access names, types and their dependency connections. ...
Definition: AttributeRegistry.h:39
CoreType tokenFromTypeString(const std::string &type)
Definition: Tokens.h:66
int64_t accessIndex(const std::string &name, const ast::tokens::CoreType type) const
Returns whether or not an access is registered.
Definition: AttributeRegistry.h:134
std::string Name
Definition: Name.h:19
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
const std::string tokenname() const
Definition: AttributeRegistry.h:66
std::shared_ptr< const AttributeRegistry > ConstPtr
Definition: AttributeRegistry.h:43
bool isReadable(const std::string &name, const ast::tokens::CoreType type) const
Definition: AttributeRegistry.h:100
bool isWritable(const std::string &name, const ast::tokens::CoreType type) const
Returns whether or not an access is required to be written to. If no access with this name has been r...
Definition: AttributeRegistry.h:109
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218