vsg: include/vsg/core/Array.h Source File

vsg 1.1.13 VulkanSceneGraph library

Loading...
Searching...
No Matches
Array.h
1#pragma once
2
3/* <editor-fold desc="MIT License">
4
5Copyright(c) 2018 Robert Osfield
6
7Permission 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
9The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
11THE 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 template<> \
30 constexpr const char* type_name<const N>() noexcept { return "vsg::" #N; }
31
32namespace vsg
33{
34 template<typename T>
35 class VSG_TEMPLATE_DECLSPEC Array : public Data
36 {
37 public:
38 using value_type = T;
39 using iterator = stride_iterator<value_type>;
40 using const_iterator = stride_iterator<const value_type>;
41
42 Array() :
43 _data(nullptr),
44 _size(0) {}
45
46 Array(const Array& rhs, const CopyOp copyop = {}) :
47 Data(rhs, copyop),
48 _data(nullptr),
49 _size(rhs._size)
50 {
51 if (_size != 0)
52 {
53 _data = _allocate(_size);
54 auto dest_v = _data;
55 for (const auto& v : rhs) *(dest_v++) = v;
56 }
57 dirty();
58 }
59
60 explicit Array(uint32_t numElements, Properties in_properties = {}) :
61 Data(in_properties, sizeof(value_type)),
62 _data(_allocate(numElements)),
63 _size(numElements) { dirty(); }
64
65 Array(uint32_t numElements, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) :
66 Data(in_properties, sizeof(value_type)),
67 _data(data),
68 _size(numElements)
69 {
70 setMipmapLayout(mipmapLayout);
71 dirty();
72 }
73
74 Array(uint32_t numElements, const value_type& value, Properties in_properties = {}) :
75 Data(in_properties, sizeof(value_type)),
76 _data(_allocate(numElements)),
77 _size(numElements)
78 {
79 for (auto& v : *this) v = value;
80 dirty();
81 }
82
83 Array(ref_ptr<Data> data, uint32_t offset, uint32_t stride, uint32_t numElements, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) :
84 Data(),
85 _data(nullptr),
86 _size(0)
87 {
88 assign(data, offset, stride, numElements, in_properties, mipmapLayout);
89 }
90
91 explicit Array(std::initializer_list<value_type> l) :
92 _data(_allocate(l.size())),
93 _size(static_cast<uint32_t>(l.size()))
94 {
95 properties.stride = sizeof(value_type);
96
97 iterator itr = begin();
98 for (const value_type& v : l) { (*itr++) = v; }
99
100 dirty();
101 }
102
103 explicit Array(ref_ptr<Data> data, uint32_t offset, uint32_t stride, std::initializer_list<value_type> l) :
104 _data(nullptr),
105 _size(0)
106 {
107 assign(data, offset, stride, static_cast<uint32_t>(l.size()));
108
109 iterator itr = begin();
110 for (const value_type& v : l) { (*itr++) = v; }
111
112 dirty();
113 }
114
115 template<typename... Args>
116 static ref_ptr<Array> create(Args&&... args)
117 {
118 return ref_ptr<Array>(new Array(std::forward<Args>(args)...));
119 }
120
121 template<typename... Args>
122 static ref_ptr<Array> create_if(bool flag, Args&&... args)
123 {
124 if (flag)
125 return ref_ptr<Array>(new Array(std::forward<Args>(args)...));
126 else
127 return {};
128 }
129
130 static ref_ptr<Array> create(std::initializer_list<value_type> l)
131 {
132 return ref_ptr<Array>(new Array(l));
133 }
134
135 static ref_ptr<Array> create(ref_ptr<Data> data, uint32_t offset, uint32_t stride, std::initializer_list<value_type> l)
136 {
137 return ref_ptr<Array>(new Array(data, offset, stride, l));
138 }
139
140 ref_ptr<Object> clone(const CopyOp& copyop = {}) const override
141 {
142 return ref_ptr<Array>(new Array(*this, copyop));
143 }
144
145 size_t sizeofObject() const noexcept override { return sizeof(Array); }
146 const char* className() const noexcept override { return type_name<Array>(); }
147 const std::type_info& type_info() const noexcept override { return typeid(*this); }
148 bool is_compatible(const std::type_info& type) const noexcept override { return typeid(Array) == type || Data::is_compatible(type); }
149
150 // implementation provided by Visitor.h
151 void accept(Visitor& visitor) override;
152 void accept(ConstVisitor& visitor) const override;
153
154 void read(Input& input) override
155 {
156 size_t original_total_size = size();
157
158 Data::read(input);
159
160 uint32_t width_size = input.readValue<uint32_t>("size");
161
162 if (auto data_storage = input.readObject<Data>("storage"))
163 {
164 uint32_t offset = input.readValue<uint32_t>("offset");
165 assign(data_storage, offset, properties.stride, width_size, properties);
166 return;
167 }
168
169 if (input.matchPropertyName("data"))
170 {
171 properties.stride = sizeof(value_type);
172 _size = width_size;
173 _storage = nullptr;
174 size_t new_total_size = computeValueCountIncludingMipmaps();
175
176 if (_data) // if data exists already may be able to reuse it
177 {
178 if (original_total_size != new_total_size) // if existing data is a different size delete old, and create new
179 {
180 clear();
181
182 _data = _allocate(new_total_size);
183 }
184 }
185 else // allocate space for data
186 {
187 _data = _allocate(new_total_size);
188 }
189
190 if (_data) input.read(new_total_size, _data);
191
192 dirty();
193 }
194 }
195
196 void write(Output& output) const override
197 {
198 Data::write(output);
199
200 output.writeValue<uint32_t>("size", _size);
201 output.writeObject("storage", _storage);
202 if (_storage)
203 {
204 auto offset = (reinterpret_cast<uintptr_t>(_data) - reinterpret_cast<uintptr_t>(_storage->dataPointer()));
205 output.writeValue<uint32_t>("offset", offset);
206 return;
207 }
208
209 output.writePropertyName("data");
210 output.write(size(), _data);
211 output.writeEndOfLine();
212 }
213
214 size_t size() const { return (properties.mipLevels <= 1) ? _size : computeValueCountIncludingMipmaps(); }
215
216 bool available() const { return _data != nullptr; }
217 bool empty() const { return _data == nullptr; }
218
219 void clear()
220 {
221 _delete();
222
223 _size = 0;
224 _data = nullptr;
225 _storage = nullptr;
226 }
227
228 Array& operator=(const Array& rhs)
229 {
230 if (&rhs == this) return *this;
231
232 clear();
233
234 _copy(rhs);
235
236 _size = rhs._size;
237
238 if (_size != 0)
239 {
240 _data = _allocate(_size);
241 auto dest_v = _data;
242 for (const auto& v : rhs) *(dest_v++) = v;
243 }
244
245 dirty();
246
247 return *this;
248 }
249
250 void assign(uint32_t numElements, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr)
251 {
252 _delete();
253
254 properties = in_properties;
255 properties.stride = sizeof(value_type);
256 _size = numElements;
257 _data = data;
258 _storage = nullptr;
259
260 setMipmapLayout(mipmapLayout);
261
262 dirty();
263 }
264
265 void assign(ref_ptr<Data> storage, uint32_t offset, uint32_t stride, uint32_t numElements, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr)
266 {
267 _delete();
268
269 _storage = storage;
270 properties = in_properties;
271 properties.stride = stride;
272 if (_storage && _storage->dataPointer())
273 {
274 _data = reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_storage->dataPointer()) + offset);
275 _size = numElements;
276 }
277 else
278 {
279 _data = nullptr;
280 _size = 0;
281 }
282
283 setMipmapLayout(mipmapLayout);
284
285 dirty();
286 }
287
288 // 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.
289 // when the data is stored in a separate vsg::Data object then return nullptr and do not attempt to release data.
290 void* dataRelease() override
291 {
292 if (!_storage)
293 {
294 void* tmp = _data;
295 _data = nullptr;
296 _size = 0;
297 return tmp;
298 }
299 else
300 {
301 return nullptr;
302 }
303 }
304
305 size_t valueSize() const override { return sizeof(value_type); }
306 size_t valueCount() const override { return size(); }
307
308 bool dataAvailable() const override { return available(); }
309 size_t dataSize() const override { return size() * properties.stride; }
310
311 void* dataPointer() override { return _data; }
312 const void* dataPointer() const override { return _data; }
313
314 void* dataPointer(size_t i) override { return data(i); }
315 const void* dataPointer(size_t i) const override { return data(i); }
316
317 uint32_t dimensions() const override { return 1; }
318
319 uint32_t width() const override { return _size; }
320 uint32_t height() const override { return 1; }
321 uint32_t depth() const override { return 1; }
322
323 value_type* data() { return _data; }
324 const value_type* data() const { return _data; }
325
326 inline value_type* data(size_t i) { return reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_data) + i * static_cast<size_t>(properties.stride)); }
327 inline const value_type* data(size_t i) const { return reinterpret_cast<const value_type*>(reinterpret_cast<const uint8_t*>(_data) + i * static_cast<size_t>(properties.stride)); }
328
329 value_type& operator[](size_t i) { return *data(i); }
330 const value_type& operator[](size_t i) const { return *data(i); }
331
332 value_type& at(size_t i) { return *data(i); }
333 const value_type& at(size_t i) const { return *data(i); }
334
335 void set(size_t i, const value_type& v) { *data(i) = v; }
336
337 Data* storage() { return _storage; }
338 const Data* storage() const { return _storage; }
339
340 iterator begin() { return iterator{_data, properties.stride}; }
341 const_iterator begin() const { return const_iterator{_data, properties.stride}; }
342
343 iterator end() { return iterator{data(_size), properties.stride}; }
344 const_iterator end() const { return const_iterator{data(_size), properties.stride}; }
345
346 protected:
347 virtual ~Array()
348 {
349 _delete();
350 }
351
352 value_type* _allocate(size_t size) const
353 {
354 if (size == 0)
355 return nullptr;
356 else if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
357 return new value_type[size];
358 else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
359 return new (std::malloc(sizeof(value_type) * size)) value_type[size];
360 else
361 return new (vsg::allocate(sizeof(value_type) * size, ALLOCATOR_AFFINITY_DATA)) value_type[size];
362 }
363
364 void _delete()
365 {
366 if (!_storage && _data)
367 {
368 if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
369 delete[] _data;
370 else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
371 std::free(_data);
372 else if (properties.allocatorType != 0)
373 vsg::deallocate(_data);
374 }
375
376 _clear();
377 }
378
379 private:
380 value_type* _data;
381 uint32_t _size;
382 ref_ptr<Data> _storage;
383 };
384
386 VSG_array(stringArray, std::string);
387
389 VSG_array(byteArray, int8_t);
390 VSG_array(ubyteArray, uint8_t);
391 VSG_array(shortArray, int16_t);
392 VSG_array(ushortArray, uint16_t);
393 VSG_array(intArray, int32_t);
394 VSG_array(uintArray, uint32_t);
395 VSG_array(floatArray, float);
396 VSG_array(doubleArray, double);
397
398 VSG_array(quatArray, quat);
399 VSG_array(dquatArray, dquat);
400
401 VSG_array(vec2Array, vec2);
402 VSG_array(vec3Array, vec3);
403 VSG_array(vec4Array, vec4);
404
405 VSG_array(dvec2Array, dvec2);
406 VSG_array(dvec3Array, dvec3);
407 VSG_array(dvec4Array, dvec4);
408
409 VSG_array(bvec2Array, bvec2);
410 VSG_array(bvec3Array, bvec3);
411 VSG_array(bvec4Array, bvec4);
412
413 VSG_array(ubvec2Array, ubvec2);
414 VSG_array(ubvec3Array, ubvec3);
415 VSG_array(ubvec4Array, ubvec4);
416
417 VSG_array(svec2Array, svec2);
418 VSG_array(svec3Array, svec3);
419 VSG_array(svec4Array, svec4);
420
421 VSG_array(usvec2Array, usvec2);
422 VSG_array(usvec3Array, usvec3);
423 VSG_array(usvec4Array, usvec4);
424
425 VSG_array(ivec2Array, ivec2);
426 VSG_array(ivec3Array, ivec3);
427 VSG_array(ivec4Array, ivec4);
428
429 VSG_array(uivec2Array, uivec2);
430 VSG_array(uivec3Array, uivec3);
431 VSG_array(uivec4Array, uivec4);
432
433 VSG_array(mat4Array, mat4);
434 VSG_array(dmat4Array, dmat4);
435
436 VSG_array(block64Array, block64);
437 VSG_array(block128Array, block128);
438
439} // namespace vsg
vsg::Array
Definition Array.h:36
vsg::Array::type_info
const std::type_info & type_info() const noexcept override
return the std::type_info of this Object
Definition Array.h:147
vsg::Array::clone
ref_ptr< Object > clone(const CopyOp &copyop={}) const override
Definition Array.h:140
vsg::CopyOp
Definition Object.h:42
vsg::Data::properties
Properties properties
properties of the data such as format, origin, stride, dataVariance etc.
Definition Data.h:169
vsg::Data::setMipmapLayout
void setMipmapLayout(MipmapLayout *mipmapData)
set the MipmapLayout, only required when the data contains mipmaps that use block compressed formats ...
vsg::Data::dirty
void dirty()
increment the ModifiedCount to signify the data has been modified
Definition Data.h:203
vsg::MipmapLayout
Definition MipmapLayout.h:24
vsg::ref_ptr
Definition ref_ptr.h:22
vsg::Data::Properties
Definition Data.h:121
vsg::block128
Definition Data.h:49
vsg::block64
Definition Data.h:43
vsg::stride_iterator
Definition Data.h:69