RavEngine
Loading...
Searching...
No Matches
VRAMVector.hpp
1#pragma once
2#include <RGL/RGL.hpp>
3#include <RGL/Buffer.hpp>
4#include <RGL/Device.hpp>
5#include <cassert>
6
7namespace RavEngine {
8
10 void TrashOldVector(RGLBufferPtr buffer);
11 RGLDevicePtr owningDevice = nullptr;
13 RGLBufferPtr buffer = nullptr;
14 };
15
20 template<typename T, bool GPUWritable = false>
21 struct VRAMVector : public VRAMVectorBase {
22 using size_type = uint32_t;
23 using index_type = uint32_t;
24 using difference_type = uint32_t;
25
26 struct iterator {
27 T* data = nullptr;
28 void operator++(int discard) {
29 data++;
30 }
31
32 iterator operator++() {
33 return iterator{ data + 1 };
34 }
35
36 iterator operator+(index_type i) {
37 return iterator{.data = data + i};
38 }
39
40 T& operator*() {
41 return *(data);
42 }
43
44 difference_type operator-(const iterator& other) const{
45 return data - other.data;
46 }
47
48 };
50 T* data = nullptr;
51
52 const_iterator(iterator i) : data(i.data) {}
53
54 const T& operator*() {
55 return *(data);
56 }
57
58 const_iterator operator+(index_type i) {
59 return const_iterator(data + i);
60 }
61
62 void operator++(int discard) {
63 data++;
64 }
65 const_iterator operator++() {
66 return const_iterator{ data + 1 };
67 }
68 };
69
70 constexpr static uint32_t initialSize = 16;
71
72 RGL::BufferConfig settings{
73 initialSize,
74 {.StorageBuffer = true, .VertexBuffer = true},
75 sizeof(T),
76 RGL::BufferAccess::Shared,
77 {
78 .Transfersource = true,
79 .Writable = GPUWritable,
80 .debugName = "VRAMVector Buffer"
81 }
82 };
83
84 size_type nValues = 0; // current capacity is stored in the Settings struct
85
86 VRAMVector(){
87 reserve(initialSize);
88 }
89
90 VRAMVector(size_type numValues){
91 resize(numValues);
92 }
93
94 VRAMVector(const VRAMVector&) = delete; // disallow copying
95
96 VRAMVector(VRAMVector&& other){ // move construction
97 if (buffer) {
98 TrashOldVector(buffer);
99 }
100 buffer = std::move(other.buffer);
101 nValues = other.nValues;
102 settings = other.settings;
103 }
104
105 VRAMVector& operator=(VRAMVector&& other){
106 if (&other != this){
107 if (buffer) {
108 TrashOldVector(buffer);
109 }
110 buffer = std::move(other.buffer);
111 nValues = other.nValues;
112 settings = other.settings;
113 }
114 return *this;
115 }
116
117 ~VRAMVector() {
118 TrashOldVector(buffer);
119 }
120
121 auto data() {
122 return static_cast<T*>(buffer->GetMappedDataPtr());
123 }
124
125 auto data() const{
126 return static_cast<T*>(buffer->GetMappedDataPtr());
127 }
128
129 auto size() const {
130 return nValues;
131 }
132
133 auto capacity() const {
134 return settings.nElements;
135 }
136
141 nValues = allocatedElements;
142 }
143
148 void reserve(size_type newSize) {
149 auto oldbuffer = buffer;
150
151 settings.nElements = newSize;
152 buffer = owningDevice->CreateBuffer(settings);
153 buffer->MapMemory();
154 if (oldbuffer) {
155 // copy over old data
156 buffer->UpdateBufferData({oldbuffer->GetMappedDataPtr(), size() * sizeof(T)});
157 TrashOldVector(oldbuffer);
158 }
159 assert(buffer->GetMappedDataPtr() != nullptr); // BUG: buffer reserve did not leave underlying in mapped state. Check buffer trashing logic
160 }
161
166 void resize(size_type newSize) {
168 nValues = newSize;
169 }
170
171 void grow() {
172 reserve(settings.nElements * 2);
173 }
174
175 bool reserveIfNeeded() {
176 if (nValues == settings.nElements) {
177 grow();
178 return true;
179 }
180 return false;
181 }
182
183 template<typename ... Args>
184 auto& emplace_back(Args&& ... args) {
185 auto didreserve = reserveIfNeeded();
186 T* newAddr = data() + size();
187 auto valueptr = new(newAddr) T{ args... };
188 assert(newAddr == valueptr); // BUG: new did not return the pointer it was passed
189 nValues++;
190 return *valueptr;
191 }
192
193 void push_back(const T& value) {
194 reserveIfNeeded();
195 this->operator[](size()) = value;
196 nValues++;
197 }
198
199 void at(index_type i) {
200 if (i >= 0 && i < size()) {
201 return this->operator[](i);
202 }
203 else {
204 throw std::out_of_range("index out of bounds");
205 }
206 }
207
208 auto& operator[](index_type i) {
209 return *(data() + i);
210 }
211
212 const auto& operator[](index_type i) const {
213 return *(data() + i);
214 }
215
216 void erase(index_type i) {
217 (data() + i)->~T();
218 if (i == size() - 1) {
219 nValues--;
220 }
221 }
222
223 void erase(iterator i) {
224 erase(uintptr_t(i.data - data()));
225 }
226
227 void erase(const_iterator i) {
228 erase(uintptr_t(i.data - data()));
229 }
230
231 void pop_back() {
232 erase(size() - 1);
233 }
234
235 auto begin() {
236 return iterator{data()};
237 }
238 auto end() {
239 return iterator{data() + nValues };
240 }
241
242 auto& back() {
243 index_type i = 1;
244 if (size() >= 0) {
245 i = size();
246 }
247 return this->operator[](i - 1);
248 }
249
250 auto begin() const {
251 return const_iterator{ data()};
252 }
253
254 auto end() const {
255 return const_iterator{ data() + nValues };
256 }
257 };
258}
Definition concurrentqueue.h:747
Definition Animation.hpp:6
Definition Buffer.hpp:21
Definition VRAMVector.hpp:9
Definition VRAMVector.hpp:49
Definition VRAMVector.hpp:26
Definition VRAMVector.hpp:21
void reserve(size_type newSize)
Definition VRAMVector.hpp:148
void resize(size_type newSize)
Definition VRAMVector.hpp:166
void _setElementCount(uint32_t allocatedElements)
Definition VRAMVector.hpp:140