vsg  1.1.0
VulkanSceneGraph library
Array.h
1 #pragma once
2 
3 /* <editor-fold desc="MIT License">
4 
5 Copyright(c) 2018 Robert Osfield
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 
9 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 
13 </editor-fold> */
14 
15 #include <vsg/core/Data.h>
16 
17 #include <vsg/maths/mat4.h>
18 #include <vsg/maths/vec2.h>
19 #include <vsg/maths/vec3.h>
20 #include <vsg/maths/vec4.h>
21 
22 #include <vsg/io/Input.h>
23 #include <vsg/io/Output.h>
24 
25 #define VSG_array(N, T) \
26  using N = Array<T>; \
27  template<> \
28  constexpr const char* type_name<N>() noexcept { return "vsg::" #N; }
29 
30 namespace vsg
31 {
32 
33  template<typename T>
34  class Array : public Data
35  {
36  public:
37  using value_type = T;
40 
41  Array() :
42  _data(nullptr),
43  _size(0) {}
44 
45  Array(const Array& rhs) :
46  Data(rhs.properties, sizeof(value_type)),
47  _data(nullptr),
48  _size(rhs._size)
49  {
50  if (_size != 0)
51  {
52  _data = _allocate(_size);
53  auto dest_v = _data;
54  for (auto& v : rhs) *(dest_v++) = v;
55  }
56  dirty();
57  }
58 
59  explicit Array(uint32_t numElements, Properties in_properties = {}) :
60  Data(in_properties, sizeof(value_type)),
61  _data(_allocate(numElements)),
62  _size(numElements) { dirty(); }
63 
64  Array(uint32_t numElements, value_type* data, Properties in_properties = {}) :
65  Data(in_properties, sizeof(value_type)),
66  _data(data),
67  _size(numElements) { dirty(); }
68 
69  Array(uint32_t numElements, const value_type& value, Properties in_properties = {}) :
70  Data(in_properties, sizeof(value_type)),
71  _data(_allocate(numElements)),
72  _size(numElements)
73  {
74  for (auto& v : *this) v = value;
75  dirty();
76  }
77 
78  Array(ref_ptr<Data> data, uint32_t offset, uint32_t stride, uint32_t numElements, Properties in_properties = {}) :
79  Data(),
80  _data(nullptr),
81  _size(0)
82  {
83  assign(data, offset, stride, numElements, in_properties);
84  }
85 
86  explicit Array(std::initializer_list<value_type> l) :
87  _data(_allocate(l.size())),
88  _size(static_cast<uint32_t>(l.size()))
89  {
90  properties.stride = sizeof(value_type);
91 
92  iterator itr = begin();
93  for (const value_type& v : l) { (*itr++) = v; }
94 
95  dirty();
96  }
97 
98  explicit Array(ref_ptr<Data> data, uint32_t offset, uint32_t stride, std::initializer_list<value_type> l) :
99  _data(nullptr),
100  _size(0)
101  {
102  assign(data, offset, stride, l.size());
103 
104  iterator itr = begin();
105  for (const value_type& v : l) { (*itr++) = v; }
106 
107  dirty();
108  }
109 
110  template<typename... Args>
111  static ref_ptr<Array> create(Args&&... args)
112  {
113  return ref_ptr<Array>(new Array(args...));
114  }
115 
116  static ref_ptr<Array> create(std::initializer_list<value_type> l)
117  {
118  return ref_ptr<Array>(new Array(l));
119  }
120 
121  static ref_ptr<Array> create(ref_ptr<Data> data, uint32_t offset, uint32_t stride, std::initializer_list<value_type> l)
122  {
123  return ref_ptr<Array>(new Array(data, offset, stride, l));
124  }
125 
126  ref_ptr<Data> clone() const override
127  {
128  return ref_ptr<Array>(new Array(*this));
129  }
130 
131  size_t sizeofObject() const noexcept override { return sizeof(Array); }
132  const char* className() const noexcept override { return type_name<Array>(); }
133  const std::type_info& type_info() const noexcept override { return typeid(*this); }
134  bool is_compatible(const std::type_info& type) const noexcept override { return typeid(Array) == type || Data::is_compatible(type); }
135 
136  // implementation provided by Visitor.h
137  void accept(Visitor& visitor) override;
138  void accept(ConstVisitor& visitor) const override;
139 
140  void read(Input& input) override
141  {
142  size_t original_total_size = size();
143 
144  Data::read(input);
145 
146  uint32_t width_size = input.readValue<uint32_t>("size");
147 
148  if (auto data_storage = input.readObject<Data>("storage"))
149  {
150  uint32_t offset = input.readValue<uint32_t>("offset");
151  assign(data_storage, offset, properties.stride, width_size, properties);
152  return;
153  }
154 
155  if (input.matchPropertyName("data"))
156  {
157  size_t new_total_size = computeValueCountIncludingMipmaps(width_size, 1, 1, properties.maxNumMipmaps);
158 
159  if (_data) // if data exists already may be able to reuse it
160  {
161  if (original_total_size != new_total_size) // if existing data is a different size delete old, and create new
162  {
163  clear();
164 
165  _data = _allocate(new_total_size);
166  }
167  }
168  else // allocate space for data
169  {
170  _data = _allocate(new_total_size);
171  }
172 
173  properties.stride = sizeof(value_type);
174  _size = width_size;
175  _storage = nullptr;
176 
177  if (_data) input.read(new_total_size, _data);
178 
179  dirty();
180  }
181  }
182 
183  void write(Output& output) const override
184  {
185  Data::write(output);
186 
187  output.writeValue<uint32_t>("size", _size);
188  output.writeObject("storage", _storage);
189  if (_storage)
190  {
191  auto offset = (reinterpret_cast<uintptr_t>(_data) - reinterpret_cast<uintptr_t>(_storage->dataPointer()));
192  output.writeValue<uint32_t>("offset", offset);
193  return;
194  }
195 
196  output.writePropertyName("data");
197  output.write(size(), _data);
198  output.writeEndOfLine();
199  }
200 
201  size_t size() const { return (properties.maxNumMipmaps <= 1) ? _size : computeValueCountIncludingMipmaps(_size, 1, 1, properties.maxNumMipmaps); }
202 
203  bool available() const { return _data != nullptr; }
204  bool empty() const { return _data == nullptr; }
205 
206  void clear()
207  {
208  _delete();
209 
210  _size = 0;
211  _data = nullptr;
212  _storage = nullptr;
213  }
214 
215  Array& operator=(const Array& rhs)
216  {
217  if (&rhs == this) return *this;
218 
219  clear();
220 
221  properties = rhs.properties;
222  _size = rhs._size;
223 
224  if (_size != 0)
225  {
226  _data = _allocate(_size);
227  auto dest_v = _data;
228  for (auto& v : rhs) *(dest_v++) = v;
229  }
230 
231  dirty();
232 
233  return *this;
234  }
235 
236  void assign(uint32_t numElements, value_type* data, Properties in_properties = {})
237  {
238  _delete();
239 
240  properties = in_properties;
241  properties.stride = sizeof(value_type);
242  _size = numElements;
243  _data = data;
244  _storage = nullptr;
245 
246  dirty();
247  }
248 
249  void assign(ref_ptr<Data> storage, uint32_t offset, uint32_t stride, uint32_t numElements, Properties in_properties = {})
250  {
251  _delete();
252 
253  _storage = storage;
254  properties = in_properties;
255  properties.stride = stride;
256  if (_storage && _storage->dataPointer())
257  {
258  _data = reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_storage->dataPointer()) + offset);
259  _size = numElements;
260  }
261  else
262  {
263  _data = nullptr;
264  _size = 0;
265  }
266 
267  dirty();
268  }
269 
270  // release the data so that ownership can be passed on, the local data pointer and size is set to 0 and destruction of Array will not result in the data being deleted.
271  // when the data is stored in a separate vsg::Data object then return nullptr and do not attempt to release data.
272  void* dataRelease() override
273  {
274  if (!_storage)
275  {
276  void* tmp = _data;
277  _data = nullptr;
278  _size = 0;
279  return tmp;
280  }
281  else
282  {
283  return nullptr;
284  }
285  }
286 
287  size_t valueSize() const override { return sizeof(value_type); }
288  size_t valueCount() const override { return size(); }
289 
290  bool dataAvailable() const override { return available(); }
291  size_t dataSize() const override { return size() * properties.stride; }
292 
293  void* dataPointer() override { return _data; }
294  const void* dataPointer() const override { return _data; }
295 
296  void* dataPointer(size_t i) override { return data(i); }
297  const void* dataPointer(size_t i) const override { return data(i); }
298 
299  uint32_t dimensions() const override { return 1; }
300 
301  uint32_t width() const override { return _size; }
302  uint32_t height() const override { return 1; }
303  uint32_t depth() const override { return 1; }
304 
305  value_type* data() { return _data; }
306  const value_type* data() const { return _data; }
307 
308  inline value_type* data(size_t i) { return reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_data) + i * properties.stride); }
309  inline const value_type* data(size_t i) const { return reinterpret_cast<const value_type*>(reinterpret_cast<const uint8_t*>(_data) + i * properties.stride); }
310 
311  value_type& operator[](size_t i) { return *data(i); }
312  const value_type& operator[](size_t i) const { return *data(i); }
313 
314  value_type& at(size_t i) { return *data(i); }
315  const value_type& at(size_t i) const { return *data(i); }
316 
317  void set(size_t i, const value_type& v) { *data(i) = v; }
318 
319  Data* storage() { return _storage; }
320  const Data* storage() const { return _storage; }
321 
322  iterator begin() { return iterator{_data, properties.stride}; }
323  const_iterator begin() const { return const_iterator{_data, properties.stride}; }
324 
325  iterator end() { return iterator{data(_size), properties.stride}; }
326  const_iterator end() const { return const_iterator{data(_size), properties.stride}; }
327 
328  protected:
329  virtual ~Array()
330  {
331  _delete();
332  }
333 
334  value_type* _allocate(size_t size) const
335  {
336  if (size == 0)
337  return nullptr;
338  else if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
339  return new value_type[size];
340  else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
341  return new (std::malloc(sizeof(value_type) * size)) value_type[size];
342  else
343  return new (vsg::allocate(sizeof(value_type) * size, ALLOCATOR_AFFINITY_DATA)) value_type[size];
344  }
345 
346  void _delete()
347  {
348  if (!_storage && _data)
349  {
350  if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
351  delete[] _data;
352  else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
353  std::free(_data);
354  else if (properties.allocatorType != 0)
355  vsg::deallocate(_data);
356  }
357  }
358 
359  private:
360  value_type* _data;
361  uint32_t _size;
362  ref_ptr<Data> _storage;
363  };
364 
365  VSG_array(byteArray, int8_t);
366  VSG_array(ubyteArray, uint8_t);
367  VSG_array(shortArray, int16_t);
368  VSG_array(ushortArray, uint16_t);
369  VSG_array(intArray, int32_t);
370  VSG_array(uintArray, uint32_t);
371  VSG_array(floatArray, float);
372  VSG_array(doubleArray, double);
373 
374  VSG_array(vec2Array, vec2);
375  VSG_array(vec3Array, vec3);
376  VSG_array(vec4Array, vec4);
377 
378  VSG_array(dvec2Array, dvec2);
379  VSG_array(dvec3Array, dvec3);
380  VSG_array(dvec4Array, dvec4);
381 
382  VSG_array(bvec2Array, bvec2);
383  VSG_array(bvec3Array, bvec3);
384  VSG_array(bvec4Array, bvec4);
385 
386  VSG_array(ubvec2Array, ubvec2);
387  VSG_array(ubvec3Array, ubvec3);
388  VSG_array(ubvec4Array, ubvec4);
389 
390  VSG_array(svec2Array, svec2);
391  VSG_array(svec3Array, svec3);
392  VSG_array(svec4Array, svec4);
393 
394  VSG_array(usvec2Array, usvec2);
395  VSG_array(usvec3Array, usvec3);
396  VSG_array(usvec4Array, usvec4);
397 
398  VSG_array(ivec2Array, ivec2);
399  VSG_array(ivec3Array, ivec3);
400  VSG_array(ivec4Array, ivec4);
401 
402  VSG_array(uivec2Array, uivec2);
403  VSG_array(uivec3Array, uivec3);
404  VSG_array(uivec4Array, uivec4);
405 
406  VSG_array(mat4Array, mat4);
407  VSG_array(dmat4Array, dmat4);
408 
409  VSG_array(block64Array, block64);
410  VSG_array(block128Array, block128);
411 
412 } // namespace vsg
Definition: Array.h:35
const std::type_info & type_info() const noexcept override
return the std::type_info of this Object
Definition: Array.h:133
Definition: Data.h:110
Properties properties
properties of the data such as format, origin, stride, dataVariance etc.
Definition: Data.h:161
void dirty()
increment the ModifiedCount to signify the data has been modified
Definition: Data.h:196
Definition: ref_ptr.h:22
Definition: Data.h:116
AllocatorType allocatorType
hint as to how the data values may change during the lifetime of the vsg::Data.
Definition: Data.h:131
Definition: Data.h:66