vsg 1.1.13
VulkanSceneGraph library
Loading...
Searching...
No Matches
Array2D.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#include <vsg/maths/mat4.h>
17#include <vsg/maths/vec2.h>
18#include <vsg/maths/vec3.h>
19#include <vsg/maths/vec4.h>
20
21#include <vsg/io/Input.h>
22#include <vsg/io/Output.h>
23
24#define VSG_array2D(N, T) \
25 using N = Array2D<T>; \
26 template<> \
27 constexpr const char* type_name<N>() noexcept { return "vsg::" #N; }
28
29namespace vsg
30{
31
32 template<typename T>
33 class VSG_TEMPLATE_DECLSPEC Array2D : public Data
34 {
35 public:
36 using value_type = T;
37 using iterator = stride_iterator<value_type>;
38 using const_iterator = stride_iterator<const value_type>;
39
40 Array2D() :
41 _data(nullptr),
42 _width(0),
43 _height(0) {}
44
45 Array2D(const Array2D& rhs, const CopyOp copyop = {}) :
46 Data(rhs, copyop),
47 _data(nullptr),
48 _width(rhs._width),
49 _height(rhs._height)
50 {
51 _data = _allocate(static_cast<size_t>(_width) * static_cast<size_t>(_height));
52 if (_data)
53 {
54 auto dest_v = _data;
55 for (const auto& v : rhs) *(dest_v++) = v;
56 dirty();
57 }
58 }
59
60 Array2D(uint32_t width, uint32_t height, Properties in_properties = {}) :
61 Data(in_properties, sizeof(value_type)),
62 _data(nullptr),
63 _width(width),
64 _height(height)
65 {
66 _data = _allocate(static_cast<size_t>(_width) * static_cast<size_t>(_height));
67 dirty();
68 }
69
70 Array2D(uint32_t width, uint32_t height, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) :
71 Data(in_properties, sizeof(value_type)),
72 _data(data),
73 _width(width),
74 _height(height)
75 {
76 setMipmapLayout(mipmapLayout);
77 dirty();
78 }
79
80 Array2D(uint32_t width, uint32_t height, const value_type& value, Properties in_properties = {}) :
81 Data(in_properties, sizeof(value_type)),
82 _data(nullptr),
83 _width(width),
84 _height(height)
85 {
86 _data = _allocate(static_cast<size_t>(_width) * static_cast<size_t>(_height));
87 if (_data)
88 {
89 for (auto& v : *this) v = value;
90 dirty();
91 }
92 }
93
94 Array2D(ref_ptr<Data> data, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) :
95 Data(),
96 _data(nullptr),
97 _width(0),
98 _height(0)
99 {
100 assign(data, offset, stride, width, height, in_properties, mipmapLayout);
101 }
102
103 template<typename... Args>
104 static ref_ptr<Array2D> create(Args&&... args)
105 {
106 return ref_ptr<Array2D>(new Array2D(std::forward<Args>(args)...));
107 }
108
109 template<typename... Args>
110 static ref_ptr<Array2D> create_if(bool flag, Args&&... args)
111 {
112 if (flag)
113 return ref_ptr<Array2D>(new Array2D(std::forward<Args>(args)...));
114 else
115 return {};
116 }
117
118 ref_ptr<Object> clone(const CopyOp& copyop = {}) const override
119 {
120 return ref_ptr<Array2D>(new Array2D(*this, copyop));
121 }
122
123 size_t sizeofObject() const noexcept override { return sizeof(Array2D); }
124 const char* className() const noexcept override { return type_name<Array2D>(); }
125 const std::type_info& type_info() const noexcept override { return typeid(*this); }
126 bool is_compatible(const std::type_info& type) const noexcept override { return typeid(Array2D) == type || Data::is_compatible(type); }
127
128 // implementation provided by Visitor.h
129 void accept(Visitor& visitor) override;
130 void accept(ConstVisitor& visitor) const override;
131
132 void read(Input& input) override
133 {
134 size_t original_size = size();
135
136 Data::read(input);
137
138 uint32_t w = input.readValue<uint32_t>("width");
139 uint32_t h = input.readValue<uint32_t>("height");
140
141 if (auto data_storage = input.readObject<Data>("storage"))
142 {
143 uint32_t offset = input.readValue<uint32_t>("offset");
144 assign(data_storage, offset, properties.stride, w, h, properties);
145 return;
146 }
147
148 if (input.matchPropertyName("data"))
149 {
150 properties.stride = sizeof(value_type);
151 _width = w;
152 _height = h;
153 _storage = nullptr;
154
155 size_t new_size = computeValueCountIncludingMipmaps();
156
157 if (_data) // if data exists already may be able to reuse it
158 {
159 if (original_size != new_size) // if existing data is a different size delete old, and create new
160 {
161 _delete();
162 _data = _allocate(new_size);
163 }
164 }
165 else // allocate space for data
166 {
167 _data = _allocate(new_size);
168 }
169
170 if (_data) input.read(new_size, _data);
171
172 dirty();
173 }
174 }
175
176 void write(Output& output) const override
177 {
178 Data::write(output);
179
180 output.writeValue<uint32_t>("width", _width);
181 output.writeValue<uint32_t>("height", _height);
182
183 output.writeObject("storage", _storage);
184 if (_storage)
185 {
186 auto offset = (reinterpret_cast<uintptr_t>(_data) - reinterpret_cast<uintptr_t>(_storage->dataPointer()));
187 output.writeValue<uint32_t>("offset", offset);
188 return;
189 }
190
191 output.writePropertyName("data");
192 output.write(valueCount(), _data);
193 output.writeEndOfLine();
194 }
195
196 size_t size() const { return (properties.mipLevels <= 1) ? (static_cast<size_t>(_width) * static_cast<size_t>(_height)) : computeValueCountIncludingMipmaps(); }
197
198 bool available() const { return _data != nullptr; }
199 bool empty() const { return _data == nullptr; }
200
201 void clear()
202 {
203 _delete();
204
205 _width = 0;
206 _height = 0;
207 _data = nullptr;
208 _storage = nullptr;
209 }
210
211 Array2D& operator=(const Array2D& rhs)
212 {
213 if (&rhs == this) return *this;
214
215 clear();
216
217 _copy(rhs);
218
219 _width = rhs._width;
220 _height = rhs._height;
221
222 _data = _allocate(static_cast<size_t>(_width) * static_cast<size_t>(_height));
223 if (_data)
224 {
225 auto dest_v = _data;
226 for (const auto& v : rhs) *(dest_v++) = v;
227 }
228
229 dirty();
230
231 return *this;
232 }
233
234 void assign(uint32_t width, uint32_t height, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr)
235 {
236 _delete();
237
238 properties = in_properties;
239 properties.stride = sizeof(value_type);
240 _width = width;
241 _height = height;
242 _data = data;
243 _storage = nullptr;
244
245 setMipmapLayout(mipmapLayout);
246
247 dirty();
248 }
249
250 void assign(ref_ptr<Data> storage, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr)
251 {
252 _delete();
253
254 _storage = storage;
255 properties = in_properties;
256 properties.stride = stride;
257 if (_storage && _storage->dataPointer())
258 {
259 _data = reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_storage->dataPointer()) + offset);
260 _width = width;
261 _height = height;
262 }
263 else
264 {
265 _data = nullptr;
266 _width = 0;
267 _height = 0;
268 }
269
270 setMipmapLayout(mipmapLayout);
271
272 dirty();
273 }
274
275 // release the data so that ownership can be passed on, the local data pointer and size is set to 0 so that destruction of Array will not result in the data being deleted.
276 // if the data is stored in a separate vsg::Data object then return nullptr and do not attempt to release data.
277 void* dataRelease() override
278 {
279 if (!_storage)
280 {
281 void* tmp = _data;
282 _data = nullptr;
283 _width = 0;
284 _height = 0;
285 return tmp;
286 }
287 else
288 {
289 return nullptr;
290 }
291 }
292
293 size_t valueSize() const override { return sizeof(value_type); }
294 size_t valueCount() const override { return size(); }
295
296 bool dataAvailable() const override { return available(); }
297 size_t dataSize() const override { return size() * properties.stride; }
298
299 void* dataPointer() override { return _data; }
300 const void* dataPointer() const override { return _data; }
301
302 void* dataPointer(size_t i) override { return data(i); }
303 const void* dataPointer(size_t i) const override { return data(i); }
304
305 uint32_t dimensions() const override { return 2; }
306 uint32_t width() const override { return _width; }
307 uint32_t height() const override { return _height; }
308 uint32_t depth() const override { return 1; }
309
310 value_type* data() { return _data; }
311 const value_type* data() const { return _data; }
312
313 inline value_type* data(size_t i) { return reinterpret_cast<value_type*>(reinterpret_cast<uint8_t*>(_data) + i * static_cast<size_t>(properties.stride)); }
314 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)); }
315
316 size_t index(uint32_t i, uint32_t j) const noexcept { return static_cast<size_t>(j) * static_cast<size_t>(_width) + static_cast<size_t>(i); }
317
318 value_type& operator[](size_t i) { return *data(i); }
319 const value_type& operator[](size_t i) const { return *data(i); }
320
321 value_type& at(size_t i) { return *data(i); }
322 const value_type& at(size_t i) const { return *data(i); }
323
324 value_type& operator()(uint32_t i, uint32_t j) { return *data(index(i, j)); }
325 const value_type& operator()(uint32_t i, uint32_t j) const { return *data(index(i, j)); }
326
327 value_type& at(uint32_t i, uint32_t j) { return *data(index(i, j)); }
328 const value_type& at(uint32_t i, uint32_t j) const { return *data(index(i, j)); }
329
330 void set(size_t i, const value_type& v) { *data(i) = v; }
331 void set(uint32_t i, uint32_t j, const value_type& v) { *data(index(i, j)) = v; }
332
333 Data* storage() { return _storage; }
334 const Data* storage() const { return _storage; }
335
336 iterator begin() { return iterator{_data, properties.stride}; }
337 const_iterator begin() const { return const_iterator{_data, properties.stride}; }
338
339 iterator end() { return iterator{data(_width * _height), properties.stride}; }
340 const_iterator end() const { return const_iterator{data(_width * _height), properties.stride}; }
341
342 protected:
343 virtual ~Array2D()
344 {
345 _delete();
346 }
347
348 value_type* _allocate(size_t size) const
349 {
350 if (size == 0)
351 return nullptr;
352 else if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
353 return new value_type[size];
354 else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
355 return new (std::malloc(sizeof(value_type) * size)) value_type[size];
356 else
357 return new (vsg::allocate(sizeof(value_type) * size, ALLOCATOR_AFFINITY_DATA)) value_type[size];
358 }
359
360 void _delete()
361 {
362 if (!_storage && _data)
363 {
364 if (properties.allocatorType == ALLOCATOR_TYPE_NEW_DELETE)
365 delete[] _data;
366 else if (properties.allocatorType == ALLOCATOR_TYPE_MALLOC_FREE)
367 std::free(_data);
368 else if (properties.allocatorType != 0)
369 vsg::deallocate(_data);
370 }
371
372 _clear();
373 }
374
375 private:
376 value_type* _data;
377 uint32_t _width;
378 uint32_t _height;
379 ref_ptr<Data> _storage;
380 };
381
382 VSG_array2D(byteArray2D, int8_t);
383 VSG_array2D(ubyteArray2D, uint8_t);
384 VSG_array2D(shortArray2D, int16_t);
385 VSG_array2D(ushortArray2D, uint16_t);
386 VSG_array2D(intArray2D, int32_t);
387 VSG_array2D(uintArray2D, uint32_t);
388 VSG_array2D(floatArray2D, float);
389 VSG_array2D(doubleArray2D, double);
390
391 VSG_array2D(vec2Array2D, vec2);
392 VSG_array2D(vec3Array2D, vec3);
393 VSG_array2D(vec4Array2D, vec4);
394
395 VSG_array2D(dvec2Array2D, dvec2);
396 VSG_array2D(dvec3Array2D, dvec3);
397 VSG_array2D(dvec4Array2D, dvec4);
398
399 VSG_array2D(bvec2Array2D, bvec2);
400 VSG_array2D(bvec3Array2D, bvec3);
401 VSG_array2D(bvec4Array2D, bvec4);
402
403 VSG_array2D(ubvec2Array2D, ubvec2);
404 VSG_array2D(ubvec3Array2D, ubvec3);
405 VSG_array2D(ubvec4Array2D, ubvec4);
406
407 VSG_array2D(svec2Array2D, svec2);
408 VSG_array2D(svec3Array2D, svec3);
409 VSG_array2D(svec4Array2D, svec4);
410
411 VSG_array2D(usvec2Array2D, usvec2);
412 VSG_array2D(usvec3Array2D, usvec3);
413 VSG_array2D(usvec4Array2D, usvec4);
414
415 VSG_array2D(ivec2Array2D, ivec2);
416 VSG_array2D(ivec3Array2D, ivec3);
417 VSG_array2D(ivec4Array2D, ivec4);
418
419 VSG_array2D(uivec2Array2D, uivec2);
420 VSG_array2D(uivec3Array2D, uivec3);
421 VSG_array2D(uivec4Array2D, uivec4);
422
423 VSG_array2D(block64Array2D, block64);
424 VSG_array2D(block128Array2D, block128);
425
426} // namespace vsg
Definition Array2D.h:34
ref_ptr< Object > clone(const CopyOp &copyop={}) const override
Definition Array2D.h:118
const std::type_info & type_info() const noexcept override
return the std::type_info of this Object
Definition Array2D.h:125
Definition Object.h:42
void setMipmapLayout(MipmapLayout *mipmapData)
set the MipmapLayout, only required when the data contains mipmaps that use block compressed formats ...
void dirty()
increment the ModifiedCount to signify the data has been modified
Definition Data.h:203
Definition MipmapLayout.h:24
Definition ref_ptr.h:22
Definition Data.h:121
Definition Data.h:49
Definition Data.h:43
Definition Data.h:69