source: opengl-game/vulkan-buffer.hpp@ a3cefaa

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

Move SSBO resizing and pipeline recreation checks out of addObject() and into updateScene() so that those operations are only done at most once per pipeline per frame, using vkUpdateDescriptorSets() instead of recreating the whole graphics pipeline, and create a VulkanBuffer class for managing data related to uniform buffers and shader storage buffers, move objectCapacity and numObjects out of GraphicsPipeline_vulkan and use VulkanBuffer to manage them instead

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