source: opengl-game/vulkan-buffer.hpp@ 5ea0a37

feature/imgui-sdl
Last change on this file since 5ea0a37 was 5ea0a37, checked in by Dmitry Portnoy <dportnoy@…>, 4 years ago

Add a function to VulkanBuffer to return a pointer to the buffer memory, and replace the use of updateBufferSet with copyDataToMemory to update all the data for a single pipeline in one call

  • Property mode set to 100644
File size: 5.4 KB
RevLine 
[a3cefaa]1#ifndef _VULKAN_BUFFER_H
2#define _VULKAN_BUFFER_H
3
4/*
5* This class is intended to be used with Storage Buffers and Uniform Buffers.
6*/
7
8template<class T>
9class VulkanBuffer {
10
11 public:
12
[8dcbf62]13 // TODO: Make these private (maybe make a getter for numObjects)
14 // Externally, they are only used in resizeBufferSet
[a3cefaa]15 size_t capacity;
[6bac215]16
17 // temp field to help with ubo+ssbo resizing until they are added to this class
18 // See if I need a separate field for this or if I can use other fields to check for this
19 // Maybe compare uniform or storage buffer size to the size of the memory allocated here
20 bool resized;
[a3cefaa]21
22 VulkanBuffer();
[b7fc3c2]23 VulkanBuffer(size_t capacity, size_t range, size_t minOffsetAlignment);
[6bac215]24
25 VulkanBuffer(const VulkanBuffer<T>&) = delete;
26 VulkanBuffer(VulkanBuffer<T>&& other);
27
[a3cefaa]28 ~VulkanBuffer();
29
[6bac215]30 VulkanBuffer<T>& operator=(const VulkanBuffer<T>&) = delete;
31 VulkanBuffer<T>& operator=(VulkanBuffer<T>&& other) noexcept;
32
[5ea0a37]33 size_t memorySize();
34
35 T* data(); // Not sure I need to expose this
[a3cefaa]36
[6486ba8]37 T& get(uint32_t index);
[8dcbf62]38 void add(T obj);
[a3cefaa]39
[5ea0a37]40 void resize();
[1abebc1]41
[a3cefaa]42 private:
43
[8dcbf62]44 size_t alignment;
[b7fc3c2]45 size_t range;
[6486ba8]46 //size_t capacity;
[6bac215]47 size_t numObjects;
[8dcbf62]48
[6486ba8]49 T* rawData;
50 vector<void*> mappedData;
[b7fc3c2]51
52 size_t memRequirement(size_t capacity);
[6486ba8]53 size_t memOffset(uint32_t index);
[a3cefaa]54};
55
56// Currently, for SSBOs, I store the per-object values (usually just the model matrix), on each object, so they
57// are not in their own array and therefore cannot be pushed to the GPU as one block. The updates must happen
58// separately per object.
59
60// Since Sascha WIllems' dynamic UBO example works the same way (iirc), I can implement dynamic UBOs like that as well
61// for now. Would be nice to plan for potentially storing the ubo data on the CPU in a contiguous block in the future,
62// assuming that would make updates easier. Keep in mind that this only makes sense if all or most of the objects
63// in the ubo get updated every frame.
64
65// ============================= TODO: Also, check when it makes sense to have a staging buffer for copying data to the GPU
66// and see if I actually need to use it everywhere I currently am. I think this is mentioned in Sascha WIllems dubo example
67// or some other Vulkan website I recently bookmarked
68
69template<class T>
70VulkanBuffer<T>::VulkanBuffer()
71 : alignment(0)
[b7fc3c2]72 , range(0)
[a3cefaa]73 , capacity(0)
74 , numObjects(0)
[6bac215]75 , resized(false)
[a3cefaa]76 , rawData(nullptr)
[6486ba8]77 , mappedData() {
[a3cefaa]78}
79
80template<class T>
[b7fc3c2]81VulkanBuffer<T>::VulkanBuffer(size_t capacity, size_t range, size_t minOffsetAlignment)
82 : alignment(range)
83 , range(range / sizeof(T))
[a3cefaa]84 , capacity(capacity)
85 , numObjects(0)
[6bac215]86 , resized(false)
[a3cefaa]87 , rawData(nullptr)
[6486ba8]88 , mappedData() {
[a3cefaa]89 if (minOffsetAlignment > 0) {
90 alignment = (alignment + minOffsetAlignment - 1) & ~(minOffsetAlignment - 1);
91 }
92
[6486ba8]93 rawData = (T*)malloc(memRequirement(capacity));
[a3cefaa]94}
95
[6bac215]96template<class T>
97VulkanBuffer<T>::VulkanBuffer(VulkanBuffer<T>&& other) {
98 // TODO: Implement
99}
100
[a3cefaa]101template<class T>
102VulkanBuffer<T>::~VulkanBuffer() {
[6486ba8]103 if (rawData != nullptr) {
104 free(rawData);
[a3cefaa]105 }
106}
107
108template<class T>
[6bac215]109VulkanBuffer<T>& VulkanBuffer<T>::operator=(VulkanBuffer<T>&& other) noexcept {
110 if (this != &other) {
111 capacity = other.capacity;
112 numObjects = other.numObjects;
113 resized = other.resized;
[a3cefaa]114
[6bac215]115 alignment = other.alignment;
[b7fc3c2]116 range = other.range;
[a3cefaa]117
[5ea0a37]118 mappedData = other.mappedData;
119
[6486ba8]120 if (rawData != nullptr) {
121 free(rawData);
[6bac215]122 }
[a3cefaa]123
[6486ba8]124 rawData = other.rawData;
[a3cefaa]125
[6bac215]126 other.capacity = 0;
127 other.numObjects = 0;
[b7fc3c2]128 other.range = 0;
[a3cefaa]129
[5ea0a37]130 other.mappedData.clear();
[6486ba8]131 other.rawData = nullptr;
[6bac215]132 }
[a3cefaa]133
134 return *this;
135}
136
[6bac215]137template<class T>
[5ea0a37]138size_t VulkanBuffer<T>::memorySize() {
139 return memRequirement(capacity);
140}
141
142template<class T>
143T* VulkanBuffer<T>::data() {
144 return rawData;
[6bac215]145}
146
[6486ba8]147template<class T>
148T& VulkanBuffer<T>::get(uint32_t index) {
149 // TODO: Check that index < numObjects
150
151 T* obj = (T*)((size_t)rawData + memOffset(index));
152 return *obj;
153}
154
[a3cefaa]155template<class T>
[8dcbf62]156void VulkanBuffer<T>::add(T obj) {
[5ea0a37]157 // TODO: Maybe copy this to the resize() function and call that function here
[6bac215]158 if (numObjects == capacity) {
159 // Once I add Vulkan buffer objects in here, make sure this doesn't overlap with resizeBufferSet
160 resized = true;
161
[6486ba8]162 size_t oldMemReq = memRequirement(capacity);
163
[6bac215]164 capacity *= 2;
[6486ba8]165
166 size_t newMemReq = memRequirement(capacity);
167
168 T* newData = (T*)malloc(newMemReq);
169 // TODO: Check for failure
170
171 memcpy(newData, rawData, oldMemReq);
172
173 free(rawData);
174 rawData = newData;
[6bac215]175 }
176
[6486ba8]177 T* ptr = (T*)((size_t)rawData + memOffset(numObjects));
178 *ptr = obj;
179
[8dcbf62]180 numObjects++;
[a3cefaa]181}
182
[b7fc3c2]183template<class T>
[5ea0a37]184void VulkanBuffer<T>::resize() {
185 resized = false;
[b7fc3c2]186}
187
188template<class T>
189size_t VulkanBuffer<T>::memRequirement(size_t capacity) {
190 return (capacity / range) * alignment + (capacity % range) * sizeof(T);
191}
192
[6486ba8]193template<class T>
194size_t VulkanBuffer<T>::memOffset(uint32_t index) {
195 return (index / range) * alignment + (index % range) * sizeof(T);
196}
197
[a3cefaa]198#endif // _VULKAN_BUFFER_H
Note: See TracBrowser for help on using the repository browser.