[a3cefaa] | 1 | #ifndef _VULKAN_BUFFER_H
|
---|
| 2 | #define _VULKAN_BUFFER_H
|
---|
| 3 |
|
---|
| 4 | #include <iostream>
|
---|
| 5 | #include <vector>
|
---|
| 6 |
|
---|
| 7 | using namespace std;
|
---|
| 8 |
|
---|
| 9 | /*
|
---|
| 10 | * This class is intended to be used with Storage Buffers and Uniform Buffers.
|
---|
| 11 | */
|
---|
| 12 |
|
---|
| 13 | template<class T>
|
---|
| 14 | class VulkanBuffer {
|
---|
| 15 |
|
---|
| 16 | public:
|
---|
| 17 |
|
---|
| 18 | size_t alignment;
|
---|
| 19 | size_t capacity;
|
---|
| 20 | size_t numObjects;
|
---|
| 21 |
|
---|
| 22 | VulkanBuffer();
|
---|
| 23 | VulkanBuffer(size_t capacity, size_t minOffsetAlignment);
|
---|
| 24 | VulkanBuffer(vector<T>* vData, size_t capacity);
|
---|
| 25 | ~VulkanBuffer();
|
---|
| 26 |
|
---|
| 27 | VulkanBuffer<T>& operator=(const VulkanBuffer<T>& other);
|
---|
| 28 |
|
---|
| 29 | T* data();
|
---|
| 30 | void* mappedData(); // TODO: Maybe rename this to just mapped()
|
---|
| 31 |
|
---|
[1abebc1] | 32 | // TODO: Add a resize function
|
---|
| 33 |
|
---|
[a3cefaa] | 34 | private:
|
---|
| 35 |
|
---|
| 36 | T* srcData; // TODO: Rename this to something else probably and rename rawData to data
|
---|
| 37 | vector<T>* vData;
|
---|
| 38 |
|
---|
| 39 | // Remember that this is a pointer to the mapped video memory
|
---|
| 40 | // Maybe rename it to mappedData or something to make that clearer
|
---|
| 41 | void* rawData;
|
---|
| 42 | };
|
---|
| 43 |
|
---|
| 44 | // Currently, for SSBOs, I store the per-object values (usually just the model matrix), on each object, so they
|
---|
| 45 | // are not in their own array and therefore cannot be pushed to the GPU as one block. The updates must happen
|
---|
| 46 | // separately per object.
|
---|
| 47 |
|
---|
| 48 | // Since Sascha WIllems' dynamic UBO example works the same way (iirc), I can implement dynamic UBOs like that as well
|
---|
| 49 | // for now. Would be nice to plan for potentially storing the ubo data on the CPU in a contiguous block in the future,
|
---|
| 50 | // assuming that would make updates easier. Keep in mind that this only makes sense if all or most of the objects
|
---|
| 51 | // in the ubo get updated every frame.
|
---|
| 52 |
|
---|
| 53 | // ============================= TODO: Also, check when it makes sense to have a staging buffer for copying data to the GPU
|
---|
| 54 | // and see if I actually need to use it everywhere I currently am. I think this is mentioned in Sascha WIllems dubo example
|
---|
| 55 | // or some other Vulkan website I recently bookmarked
|
---|
| 56 |
|
---|
| 57 | template<class T>
|
---|
| 58 | VulkanBuffer<T>::VulkanBuffer()
|
---|
| 59 | : alignment(0)
|
---|
| 60 | , capacity(0)
|
---|
| 61 | , numObjects(0)
|
---|
| 62 | , srcData(nullptr)
|
---|
| 63 | , rawData(nullptr)
|
---|
| 64 | , vData(nullptr) {
|
---|
| 65 | }
|
---|
| 66 |
|
---|
| 67 | template<class T>
|
---|
| 68 | VulkanBuffer<T>::VulkanBuffer(size_t capacity, size_t minOffsetAlignment)
|
---|
| 69 | : alignment(sizeof(T))
|
---|
| 70 | , capacity(capacity)
|
---|
| 71 | , numObjects(0)
|
---|
| 72 | , srcData(nullptr)
|
---|
| 73 | , rawData(nullptr)
|
---|
| 74 | , vData(nullptr) {
|
---|
| 75 | if (minOffsetAlignment > 0) {
|
---|
| 76 | alignment = (alignment + minOffsetAlignment - 1) & ~(minOffsetAlignment - 1);
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | srcData = (T*)malloc(capacity * alignment);
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | template<class T>
|
---|
| 83 | VulkanBuffer<T>::VulkanBuffer(vector<T>* vData, size_t capacity)
|
---|
| 84 | : alignment(sizeof(T))
|
---|
| 85 | , capacity(capacity)
|
---|
| 86 | , numObjects(0)
|
---|
| 87 | , srcData(nullptr)
|
---|
| 88 | , rawData(nullptr)
|
---|
| 89 | , vData(vData) {
|
---|
| 90 | // TODO: Allocate initial capacity in vector
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | template<class T>
|
---|
| 94 | VulkanBuffer<T>::~VulkanBuffer() {
|
---|
| 95 | if (srcData != nullptr) {
|
---|
| 96 | free(srcData);
|
---|
| 97 | }
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | template<class T>
|
---|
| 101 | VulkanBuffer<T>& VulkanBuffer<T>::operator=(const VulkanBuffer<T>& other) {
|
---|
| 102 | if (this == &other) {
|
---|
| 103 | return *this;
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | /*
|
---|
| 107 | // assume *this manages a reusable resource, such as a heap-allocated buffer mArray
|
---|
| 108 | if (size != other.size) { // resource in *this cannot be reused
|
---|
| 109 | delete[] mArray; // release resource in *this
|
---|
| 110 | mArray = nullptr;
|
---|
| 111 | size = 0; // preserve invariants in case next line throws
|
---|
| 112 | mArray = new int[other.size]; // allocate resource in *this
|
---|
| 113 | size = other.size;
|
---|
| 114 | }
|
---|
| 115 | */
|
---|
| 116 |
|
---|
| 117 | if (srcData != nullptr) {
|
---|
| 118 | free(srcData);
|
---|
| 119 | srcData = nullptr;
|
---|
| 120 | }
|
---|
| 121 |
|
---|
| 122 | alignment = other.alignment;
|
---|
| 123 | capacity = other.capacity;
|
---|
| 124 |
|
---|
| 125 | srcData = (T*)malloc(capacity * alignment);
|
---|
| 126 | // TODO: Check for failure
|
---|
| 127 |
|
---|
| 128 | memcpy(srcData, other.srcData, capacity * alignment);
|
---|
| 129 |
|
---|
| 130 | return *this;
|
---|
| 131 | }
|
---|
| 132 |
|
---|
| 133 | template<class T>
|
---|
| 134 | T* VulkanBuffer<T>::data() {
|
---|
| 135 | if (srcData != nullptr) {
|
---|
| 136 | return srcData;
|
---|
| 137 | } else {
|
---|
| 138 | return vData->data();
|
---|
| 139 | }
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | template<class T>
|
---|
| 143 | void* VulkanBuffer<T>::mappedData() {
|
---|
| 144 | return rawData;
|
---|
| 145 | }
|
---|
| 146 |
|
---|
| 147 | #endif // _VULKAN_BUFFER_H
|
---|