OpenVDB  9.0.1
AttributeRegistry.h
Go to the documentation of this file.
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 {
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 ///
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  : mAttrib(name, type)
59  , mAccess(readsFrom, writesTo)
60  , mUses()
61  , mDependencies() {}
62 
63  bool reads() const { return mAccess.first; }
64  bool writes() const { return mAccess.second; }
65  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  bool dependson(const AccessData* data) const {
72  assert(data);
73  for (auto& dep : mDependencies) {
74  if (dep == data) return true;
75  }
76  return false;
77  }
78 
79  bool affectsothers() const {
80  for (auto& dep : mUses) {
81  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  accessIndex(const std::string& name,
134  const ast::tokens::CoreType type) const
135  {
136  int64_t i = 0;
137  for (const auto& data : mAccesses) {
138  if (data.type() == type && data.name() == name) {
139  return i;
140  }
141  ++i;
142  }
143  return -1;
144  }
145 
146  const AccessData*
147  get(const std::string& name, const ast::tokens::CoreType type) const
148  {
149  for (const auto& data : mAccesses) {
150  if ((type == ast::tokens::UNKNOWN || data.type() == type)
151  && data.name() == name) {
152  return &data;
153  }
154  }
155  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  mAccesses.emplace_back(name, type, readsfrom, writesto);
178  }
179 
180  AccessDataVec mAccesses;
181 };
182 
183 
184 /////////////////////////////////////////////////////////////////////
185 /////////////////////////////////////////////////////////////////////
186 
187 
188 inline AttributeRegistry::Ptr AttributeRegistry::create(const ast::Tree& tree)
189 {
191  std::vector<std::string> read, write, all;
192  ast::catalogueAttributeTokens(tree, &read, &write, &all);
193 
194  size_t idx = 0;
195  std::unordered_map<std::string, size_t> indexmap;
196 
197  auto dataBuilder =
198  [&](const std::vector<std::string>& attribs,
199  const bool readFlag,
200  const bool writeFlag)
201  {
202  std::string name, type;
203  for (const auto& attrib : attribs) {
204  ast::Attribute::nametypeFromToken(attrib, &name, &type);
205  const ast::tokens::CoreType typetoken =
207  registry->addData(name, typetoken, readFlag, writeFlag);
208  indexmap[attrib] = idx++;
209  }
210  };
211 
212  // insert all data
213 
214  dataBuilder(read, true, false);
215  dataBuilder(write, false, true);
216  dataBuilder(all, true, true);
217 
218  auto depBuilder = [&](const std::vector<std::string>& attribs) {
219 
220  std::string name, type;
221  for (const auto& attrib : attribs) {
222  ast::Attribute::nametypeFromToken(attrib, &name, &type);
223  const ast::tokens::CoreType typetoken =
225 
226  std::vector<std::string> deps;
227  ast::attributeDependencyTokens(tree, name, typetoken, deps);
228  if (deps.empty()) continue;
229 
230  assert(indexmap.find(attrib) != indexmap.cend());
231  const size_t index = indexmap.at(attrib);
232  AccessData& access = registry->mAccesses[index];
233  for (const std::string& dep : deps) {
234  assert(indexmap.find(dep) != indexmap.cend());
235  const size_t depindex = indexmap.at(dep);
236  access.mDependencies.emplace_back(&registry->mAccesses[depindex]);
237  }
238  }
239  };
240 
241  // initialize dependencies
242 
243  depBuilder(read);
244  depBuilder(write);
245  depBuilder(all);
246 
247  // Update usage from deps
248 
249  for (AccessData& access : registry->mAccesses) {
250  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  if (next.dependson(&access)) {
254  access.mUses.emplace_back(&next);
255  }
256  }
257  }
258 
259  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 
bool dependson(const AccessData *data) const
Definition: AttributeRegistry.h:71
std::pair< bool, bool > accessPattern(const std::string &name, const ast::tokens::CoreType type) const
Definition: AttributeRegistry.h:114
bool isReadable(const std::string &name, const ast::tokens::CoreType type) const
Definition: AttributeRegistry.h:99
bool isRegistered(const std::string &name, const ast::tokens::CoreType type) const
Returns whether or not an access is registered.
Definition: AttributeRegistry.h:124
CoreType tokenFromTypeString(const std::string &type)
Definition: Tokens.h:66
bool writes() const
Definition: AttributeRegistry.h:64
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:54
static fileSize_t write(std::ostream &os, const GridHandle< BufferT > &handle, Codec codec)
const std::string & name() const
Definition: AttributeRegistry.h:66
std::string typeStringFromToken(const CoreType type)
Definition: Tokens.h:118
const std::string tokenname() const
Definition: AttributeRegistry.h:65
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.
static void read(std::istream &is, GridHandle< BufferT > &handle, Codec codec)
CoreType
Definition: Tokens.h:31
const std::vector< const AccessData * > & uses() const
Definition: AttributeRegistry.h:69
std::string Name
Definition: Name.h:17
const std::vector< const AccessData * > & deps() const
Definition: AttributeRegistry.h:68
bool affectsothers() const
Definition: AttributeRegistry.h:79
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:108
Definition: Exceptions.h:13
int64_t accessIndex(const std::string &name, const ast::tokens::CoreType type) const
Returns whether or not an access is registered.
Definition: AttributeRegistry.h:133
std::shared_ptr< const AttributeRegistry > ConstPtr
Definition: AttributeRegistry.h:42
ast::tokens::CoreType type() const
Definition: AttributeRegistry.h:67
std::vector< AccessData > AccessDataVec
Definition: AttributeRegistry.h:95
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...
Registered access details, including its name, type and whether a write handle is required...
Definition: AttributeRegistry.h:47
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:561
This class stores a list of access names, types and their dependency connections. ...
Definition: AttributeRegistry.h:38
const AccessDataVec & data() const
Returns a const reference to the vector of registered accesss.
Definition: AttributeRegistry.h:159
std::shared_ptr< AttributeRegistry > Ptr
Definition: AttributeRegistry.h:41
Attributes represent any access to a primitive value, typically associated with the &#39;@&#39; symbol syntax...
Definition: AST.h:1873
bool reads() const
Definition: AttributeRegistry.h:63
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
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.
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202