Cogs.Core
BuffersGL20.cpp
1#include "BuffersGL20.h"
2
3namespace {
9 GLuint createBuffer(GLenum target, const void * data, size_t size, const GLenum usage = GL_STATIC_DRAW)
10 {
11 GLuint bufferId;
12
13 glGenBuffers(1, &bufferId);
14 glBindBuffer(target, bufferId);
15 glBufferData(target, static_cast<GLsizeiptr>(size), data, usage);
16
17 return bufferId;
18 }
19}
20
21Cogs::VertexBufferHandle Cogs::BuffersGL20::loadVertexBuffer(const void * vertexData, const size_t count, VertexFormatHandle vertexFormat)
22{
23 auto format = getVertexFormat(vertexFormat);
24 const size_t size = count * format->size;
25
26 GLuint bufferId = createBuffer(GL_ARRAY_BUFFER, vertexData, size);
27 BufferGL20 buffer = {
28 bufferId,
29 GL_INVALID_INDEX,
30 size,
31 count,
32 GL_ARRAY_BUFFER,
33 {format},
34 std::vector<uint8_t>(),
36 };
37
38 bufferMemoryConsumption += buffer.size;
39 return this->buffers.addResource(std::move(buffer));
40}
41
42Cogs::VertexBufferHandle Cogs::BuffersGL20::loadVertexBuffer(const void * vertexData, const size_t count, const VertexFormat & vertexFormat)
43{
44 return loadVertexBuffer(vertexData, count, createVertexFormat(vertexFormat.elements.data(), vertexFormat.elements.size()));
45}
46
48{
49 this->releaseBuffer(vertexBufferHandle);
50}
51
52Cogs::IndexBufferHandle Cogs::BuffersGL20::loadIndexBuffer(const void * indexData, const size_t count, const size_t indexSize)
53{
54 assert(indexSize == sizeof(GLuint) || indexSize == sizeof(GLushort));
55
56 GLuint bufferId = createBuffer(GL_ELEMENT_ARRAY_BUFFER, indexData, count * indexSize);
57
58 BufferGL20 buffer = { bufferId, GL_INVALID_INDEX, count * indexSize, count, GL_ELEMENT_ARRAY_BUFFER, {}, std::vector<uint8_t>(), MapMode::Read };
59 buffer.indexSize = (indexSize == sizeof(GLuint)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
60
61 bufferMemoryConsumption += buffer.size;
62 return this->buffers.addResource(std::move(buffer));
63}
64
66{
67 this->releaseBuffer(indexBufferHandle);
68}
69
70Cogs::InputLayoutHandle Cogs::BuffersGL20::loadInputLayout(const VertexFormatHandle * vertexFormats, const size_t count, EffectHandle /*effectHandle*/)
71{
72 InputLayoutGL20 inputLayout = {};
73
74 assert(count < sizeof(inputLayout.formats)/sizeof(inputLayout.formats[0]));
75 for (size_t i = 0; i < count; ++i) {
76 inputLayout.formats[i] = getVertexFormat(vertexFormats[i]);
77 }
78 inputLayout.numFormats = count;
79
80 return this->inputLayouts.addResource(std::move(inputLayout));
81}
82
84{
85 this->inputLayouts.removeResource(handle);
86}
87
88Cogs::BufferHandle Cogs::BuffersGL20::loadBuffer(const void * data, const size_t size, Usage::EUsage usage, uint32_t accessMode, uint32_t bindFlags, uint32_t /*stride*/)
89{
90 unsigned int bindFlagsGl = 0;
91
92 if (bindFlags == 0) bindFlagsGl = GL_ARRAY_BUFFER;
93 bindFlagsGl |= bindFlags & BindFlags::VertexBuffer ? GL_ARRAY_BUFFER : 0;
94 bindFlagsGl |= bindFlags & BindFlags::IndexBuffer ? GL_ELEMENT_ARRAY_BUFFER : 0;
95 bindFlagsGl |= bindFlags & BindFlags::ConstantBuffer ? GL_UNIFORM_BUFFER : 0;
96 bindFlagsGl |= bindFlags & BindFlags::RawBuffer ? GL_SHADER_STORAGE_BUFFER : 0;
97 bindFlagsGl |= bindFlags & BindFlags::StructuredBuffer ? GL_SHADER_STORAGE_BUFFER : 0;
98 bindFlagsGl |= bindFlags & BindFlags::StructuredBufferWithCounter ? GL_SHADER_STORAGE_BUFFER : 0;
99
100 GLenum usageMode = GL_STREAM_COPY;
101 switch (usage)
102 {
104 switch (accessMode)
105 {
106 case AccessMode::Read: usageMode = GL_STREAM_READ; break;
107 case AccessMode::Write: usageMode = GL_STREAM_DRAW; break;
108 default: usageMode = GL_STREAM_COPY; break;
109 }
110 break;
112 switch (accessMode)
113 {
114 case AccessMode::Read: usageMode = GL_STATIC_READ; break;
115 case AccessMode::Write: usageMode = GL_STATIC_DRAW; break;
116 default: usageMode = GL_STATIC_COPY; break;
117 }
118 break;
120 switch (accessMode)
121 {
122 case AccessMode::Read: usageMode = GL_DYNAMIC_READ; break;
123 case AccessMode::Write: usageMode = GL_DYNAMIC_DRAW; break;
124 default: usageMode = GL_DYNAMIC_COPY; break;
125 }
126 break;
128 switch (accessMode)
129 {
130 case AccessMode::Read: usageMode = GL_STREAM_READ; break;
131 case AccessMode::Write: usageMode = GL_STREAM_DRAW; break;
132 default: usageMode = GL_STREAM_COPY; break;
133 }
134 break;
135 default:
136 break;
137 }
138
139
140 BufferGL20 buffer = { GL_INVALID_INDEX, GL_INVALID_INDEX, size, 0, bindFlagsGl, {}, std::vector<uint8_t>(), MapMode::Read };
141
142 buffer.bufferId = createBuffer(bindFlagsGl, data, size, usageMode);
143
145 buffer.counterBufferId = createBuffer(GL_COPY_WRITE_BUFFER, nullptr, sizeof(GLuint), GL_DYNAMIC_COPY);
146 }
147
148 if (bindFlags & BindFlags::VertexBuffer) {
149 RegisterGPUResource(glBufferFakeAddress(buffer.bufferId), buffer.size, MemBlockType::GPUVertexBuffer);
150 }
151 else if (bindFlags & BindFlags::IndexBuffer) {
152 RegisterGPUResource(glBufferFakeAddress(buffer.bufferId), buffer.size, MemBlockType::GPUIndexBuffer);
153 }
154 else if (bindFlags & BindFlags::ConstantBuffer) {
155 RegisterGPUResource(glBufferFakeAddress(buffer.bufferId), buffer.size, MemBlockType::GPUConstantBuffer);
156 }
157 else {
158 RegisterGPUResource(glBufferFakeAddress(buffer.bufferId), buffer.size, MemBlockType::GPUBuffer);
159 }
160
161 bufferMemoryConsumption += buffer.size;
162 return this->buffers.addResource(std::move(buffer));
163}
164
165
166void Cogs::BuffersGL20::retrieveSubBuffer(void * data, BufferHandle source, const size_t offset, const size_t size)
167{
168 assert(HandleIsValid(source) && "Source buffer handle must be valid.");
169 const auto & sourceBuffer = this->buffers[source];
170 assert((offset + size <= sourceBuffer.size) && "Requested read outside source buffer.");
171
172#ifndef __APPLE__
173 if (glGetNamedBufferSubData) {
174 glGetNamedBufferSubData(sourceBuffer.bufferId, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), data);
175 }
176 else
177#endif
178 {
179 glBindBuffer(sourceBuffer.target, sourceBuffer.bufferId);
180 glGetBufferSubData(sourceBuffer.target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), data);
181 glBindBuffer(sourceBuffer.target, 0);
182 }
183}
184
186{
187 auto & buffer = this->buffers[bufferHandle];
188
189 if (buffer.bufferId != GL_INVALID_INDEX) {
190 UnregisterGPUResource(glBufferFakeAddress(buffer.bufferId));
191 glDeleteBuffers(1, &buffer.bufferId);
192 buffer.bufferId = GL_INVALID_INDEX;
193 }
194
195 if (buffer.counterBufferId != GL_INVALID_INDEX) {
196 glDeleteBuffers(1, &buffer.counterBufferId);
197 buffer.counterBufferId = GL_INVALID_INDEX;
198 }
199
200 bufferMemoryConsumption -= buffer.size;
201 this->buffers.removeResource(bufferHandle);
202}
203
205{
206 {
207 std::vector<BufferHandle> handles;
208 for (auto & buffer : buffers) {
209 handles.push_back(buffers.getHandle(buffer));
210 }
211
212 for (auto & handle : handles) {
213 releaseBuffer(handle);
214 }
215 }
216 {
217 std::vector<InputLayoutHandle> handles;
218 for (auto & layout : inputLayouts) {
219 handles.push_back(inputLayouts.getHandle(layout));
220 }
221
222 for (auto & handle : handles) {
223 releaseInputLayout(handle);
224 }
225 }
226}
227
229{
230 auto & buffer = this->buffers[handle];
231#ifndef __APPLE__
232 glObjectLabel(GL_BUFFER, buffer.bufferId, static_cast<GLsizei>(name.size()), name.data());
233#else
234 (void)buffer;
235 (void)name;
236#endif
237}
239{
240 auto & buffer = this->buffers[handle];
241#ifndef __APPLE__
242 glObjectLabel(GL_BUFFER, buffer.bufferId, static_cast<GLsizei>(name.size()), name.data());
243#else
244 (void)buffer;
245 (void)name;
246#endif
247}
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:24
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
Definition: StringView.h:171
constexpr size_t size() const noexcept
Get the size of the string.
Definition: StringView.h:178
@ Read
The buffer can be mapped and read from by the CPU after creation.
Definition: Flags.h:48
@ Write
The buffer can be mapped and written to by the CPU after creation.
Definition: Flags.h:50
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
Definition: Flags.h:72
@ StructuredBufferWithCounter
The buffer can be bound as a structured buffer and read or written from shaders, with an additional a...
Definition: Flags.h:82
@ VertexBuffer
The buffer can be bound as input to the vertex shader stage as a vertex buffer.
Definition: Flags.h:68
@ RawBuffer
The buffer can be bound as a byte address buffer and read or written from shaders.
Definition: Flags.h:78
@ IndexBuffer
The buffer can be bound as input to the vertex shader stage as an index buffer.
Definition: Flags.h:70
@ StructuredBuffer
The buffer can be bound as a structured buffer and read or written from shaders.
Definition: Flags.h:80
void releaseResources() override
Releases all allocated buffer resources.
BufferHandle loadBuffer(const void *data, const size_t size, Usage::EUsage usage, uint32_t accessMode, uint32_t bindFlags, uint32_t stride=0) override
Loads a new buffer using the given data to populate the buffer.
Definition: BuffersGL20.cpp:88
void releaseInputLayout(InputLayoutHandle vertexFormatHandle) override
Releases the input layout with the given inputLayoutHandle.
Definition: BuffersGL20.cpp:83
VertexBufferHandle loadVertexBuffer(const void *data, const size_t count, const VertexFormat &format) override
Loads a new vertex buffer and populates it with the given data.
Definition: BuffersGL20.cpp:42
IndexBufferHandle loadIndexBuffer(const void *data, const size_t count, const size_t indexSize) override
Loads a new index buffer and populates it with the given indexData.
Definition: BuffersGL20.cpp:52
void releaseBuffer(BufferHandle bufferHandle) override
Releases the buffer with the given bufferHandle.
void releaseIndexBuffer(IndexBufferHandle indexBufferHandle) override
Releases the index buffer with the given handle.
Definition: BuffersGL20.cpp:65
void annotate(BufferHandle handle, const StringView &name) override
Associate a name with an object for use in graphics debugging.
InputLayoutHandle loadInputLayout(const VertexFormatHandle *vertexFormats, const size_t count, EffectHandle effectHandle) override
Loads a new input layout to map vertex flow between vertex buffers with the given vertexFormats to ef...
Definition: BuffersGL20.cpp:70
void retrieveSubBuffer(void *data, BufferHandle source, const size_t offset, const size_t size) override
Retrieves the contents of a buffer.
void releaseVertexBuffer(VertexBufferHandle vertexBufferHandle) override
Release the vertex buffer with the given handle.
Definition: BuffersGL20.cpp:47
EUsage
Usage enumeration.
Definition: Flags.h:24
@ Static
Buffer will be loaded once and used to render many subsequent frames without any updates.
Definition: Flags.h:28
@ Default
Default usage.
Definition: Flags.h:26
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30
@ Staging
Definition: Flags.h:33
Vertex format structure used to describe a single vertex for the input assembler.
Definition: VertexFormat.h:60
std::vector< VertexElement > elements
Vector containing all vertex elements of this format.
Definition: VertexFormat.h:62