buffer.h 4.99 KB
Newer Older
1
2
#ifndef INCLUDE_BUFFER_H
#define INCLUDE_BUFFER_H
3
4
5
6
7

// --- STDLIB ---------------------------------------------
#include <vector>

// --- EXTERN ---------------------------------------------
8
#include <util/opengl.h>
unknown's avatar
unknown committed
9
#include <util/templates.h>
10
11
12

// --- INTERN ---------------------------------------------

13
namespace glare::core
14
{
15
16
	template<gl::BufferType TBuffer>
	class Buffer
17
	{
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
	public:
		Buffer();
		Buffer(Buffer& other) = delete;
		Buffer& operator=(Buffer& other) = delete;
		Buffer(Buffer&& other) = default;
		Buffer& operator=(Buffer&& other) = default;
		~Buffer();

		void bind() const;
		void bind(unsigned point) const;
		void unbind() const;

		unsigned id() const;
		uint64_t residentAddress() const;

		bool resident() const;
		uint64_t makeResident(gl::Access access);
		void makeNonResident() const;

		template<typename T> void upload(size_t count, const T* data, gl::BufferUsage usage) const;
		template<typename T> void upload(const std::vector<T>& data, gl::BufferUsage usage) const;
		template<typename T = uint8_t> void reserve(size_t count, gl::BufferUsage usage) const;
		template<typename T> std::vector<T> download(size_t count, size_t offset = 0) const;

		template<typename TReturn = void> TReturn* map(size_t count, size_t offset, gl::BufferMapBit flags) const;
		template<typename TReturn = void> TReturn* map(size_t count, gl::BufferMapBit flags) const;
		void unmap() const;

	protected:
		gl::handle::buffer m_handle;
		uint64_t m_resident_address = 0;
	};

	// -------------------------------------------------------------------------------------------------------------------------
	// --- IMPLEMENTATIONS -----------------------------------------------------------------------------------------------------
	// -------------------------------------------------------------------------------------------------------------------------

	template<gl::BufferType TBuffer> Buffer<TBuffer>::Buffer() {}

	template<gl::BufferType TBuffer>
	Buffer<TBuffer>::~Buffer()
	{
		makeNonResident();
	}
62

63
64
65
66
67
	template<gl::BufferType TBuffer>
	void Buffer<TBuffer>::bind() const
	{
		gl::bindBuffer(TBuffer, m_handle);
	}
68

69
70
71
72
73
74
	template<gl::BufferType TBuffer>
	void Buffer<TBuffer>::bind(unsigned point) const
	{
		bind();
		gl::bindBufferBase(TBuffer, point, m_handle);
	}
75

76
77
78
79
80
	template<gl::BufferType TBuffer>
	void Buffer<TBuffer>::unbind() const
	{
		gl::bindBuffer(TBuffer, 0);
	}
81

82
83
84
85
86
	template<gl::BufferType TBuffer>
	unsigned Buffer<TBuffer>::id() const
	{
		return m_handle;
	}
87

88
89
90
91
92
	template<gl::BufferType TBuffer>
	uint64_t Buffer<TBuffer>::residentAddress() const
	{
		return m_resident_address;
	}
93

94
95
96
97
98
	template<gl::BufferType TBuffer>
	bool Buffer<TBuffer>::resident() const
	{
		return gl::isNamedBufferResident(m_handle);
	}
99

100
101
102
103
	template<gl::BufferType TBuffer>
	uint64_t Buffer<TBuffer>::makeResident(gl::Access access)
	{
		if (!resident())
104
		{
105
106
107
			bind();
			gl::makeNamedBufferResident(m_handle, access);
			gl::getNamedBufferParameterui64v(m_handle, gl::GetNamedBufferParameters::eGPUAddress, &m_resident_address);
108
		}
109
110
111
		assert(resident());
		return m_resident_address;
	}
112

113
114
115
116
	template<gl::BufferType TBuffer>
	void Buffer<TBuffer>::makeNonResident() const
	{
		if (resident())
117
		{
118
			gl::makeNamedBufferNonResident(m_handle);
119
		}
120
	}
121

122
123
124
125
126
127
	template<gl::BufferType TBuffer>
	template<typename T>
	void Buffer<TBuffer>::upload(size_t count, const T* data, gl::BufferUsage usage) const
	{
		gl::namedBufferData(m_handle, sizeof(T) * count, data, usage);
	}
128

129
130
131
132
133
134
	template<gl::BufferType TBuffer>
	template<typename T>
	void Buffer<TBuffer>::upload(const std::vector<T>& data, gl::BufferUsage usage) const
	{
		gl::namedBufferData(m_handle, sizeof(T) * data.size(), data.data(), usage);
	}
135

136
137
138
139
140
141
	template<gl::BufferType TBuffer>
	template<typename T>
	void Buffer<TBuffer>::reserve(size_t count, gl::BufferUsage usage) const
	{
		upload<T>(count, nullptr, usage);
	}
142

143
144
145
146
147
148
149
150
151
	template<gl::BufferType TBuffer>
	template<typename T>
	std::vector<T> Buffer<TBuffer>::download(size_t count, size_t offset) const
	{
		std::vector<T> out(count);
		memcpy(out.data(), map(count, offset, gl::BufferMapBit::eRead), count * sizeof(T));
		unmap();
		return out;
	}
152

153
154
155
156
157
158
159
160
	template<gl::BufferType TBuffer>
	template<typename TReturn>
	TReturn* Buffer<TBuffer>::map(size_t count, size_t offset, gl::BufferMapBit flags) const
	{
		// as you can't do sizeof(void), you can set it equivalent to 8 bit.
		using measure_t = templates::decide_on_t<std::is_same<void, TReturn>::value, uint8_t, TReturn>;
		return reinterpret_cast<TReturn*>(gl::mapNamedBufferRange(m_handle, offset * sizeof(measure_t), count * sizeof(measure_t), flags));
	}
161

162
163
164
165
166
167
	template<gl::BufferType TBuffer>
	template<typename TReturn>
	TReturn* Buffer<TBuffer>::map(size_t count, gl::BufferMapBit flags) const
	{
		return map<TReturn>(count, 0, flags);
	}
168

169
170
171
172
	template<gl::BufferType TBuffer>
	void Buffer<TBuffer>::unmap() const
	{
		gl::unmapNamedBuffer(m_handle);
173
174
175
	}
}

176
#endif //INCLUDE_BUFFER_H