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,
34 {format},
35 std::vector<uint8_t>(),
37 };
38
39 BufferHandle handle = this->buffers.addResource(std::move(buffer));
41 return handle;
42}
43
44Cogs::VertexBufferHandle Cogs::BuffersGL20::loadVertexBuffer(const void * vertexData, const size_t count, const VertexFormat & vertexFormat)
45{
46 return loadVertexBuffer(vertexData, count, createVertexFormat(vertexFormat.elements.data(), vertexFormat.elements.size()));
47}
48
50{
51 this->releaseBuffer(vertexBufferHandle);
52}
53
54Cogs::IndexBufferHandle Cogs::BuffersGL20::loadIndexBuffer(const void * indexData, const size_t count, const size_t indexSize)
55{
56 assert(indexSize == sizeof(GLuint) || indexSize == sizeof(GLushort));
57
58 GLuint bufferId = createBuffer(GL_ELEMENT_ARRAY_BUFFER, indexData, count * indexSize);
59
60 BufferGL20 buffer = { bufferId, GL_INVALID_INDEX, count * indexSize, count, GL_ELEMENT_ARRAY_BUFFER, BindFlags::IndexBuffer, {}, std::vector<uint8_t>(), MapMode::Read };
61 buffer.indexSize = (indexSize == sizeof(GLuint)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
62
63 BufferHandle handle = this->buffers.addResource(std::move(buffer));
64 recordBufferCreate(handle, BindFlags::IndexBuffer, count * indexSize);
65 return handle;
66}
67
69{
70 this->releaseBuffer(indexBufferHandle);
71}
72
73Cogs::InputLayoutHandle Cogs::BuffersGL20::loadInputLayout(const VertexFormatHandle * vertexFormats, const size_t count, EffectHandle /*effectHandle*/)
74{
75 InputLayoutGL20 inputLayout = {};
76
77 assert(count < sizeof(inputLayout.formats)/sizeof(inputLayout.formats[0]));
78 for (size_t i = 0; i < count; ++i) {
79 inputLayout.formats[i] = getVertexFormat(vertexFormats[i]);
80 }
81 inputLayout.numFormats = count;
82
83 return this->inputLayouts.addResource(std::move(inputLayout));
84}
85
87{
88 this->inputLayouts.removeResource(handle);
89}
90
91Cogs::BufferHandle Cogs::BuffersGL20::loadBuffer(const void * data, const size_t size, Usage::EUsage usage, uint32_t accessMode, uint32_t bindFlags, uint32_t /*stride*/)
92{
93 unsigned int bindFlagsGl = 0;
94
95 if (bindFlags == 0) bindFlagsGl = GL_ARRAY_BUFFER;
96 bindFlagsGl |= bindFlags & BindFlags::VertexBuffer ? GL_ARRAY_BUFFER : 0;
97 bindFlagsGl |= bindFlags & BindFlags::IndexBuffer ? GL_ELEMENT_ARRAY_BUFFER : 0;
98 bindFlagsGl |= bindFlags & BindFlags::ConstantBuffer ? GL_UNIFORM_BUFFER : 0;
99 bindFlagsGl |= bindFlags & BindFlags::RawBuffer ? GL_SHADER_STORAGE_BUFFER : 0;
100 bindFlagsGl |= bindFlags & BindFlags::StructuredBuffer ? GL_SHADER_STORAGE_BUFFER : 0;
101 bindFlagsGl |= bindFlags & BindFlags::StructuredBufferWithCounter ? GL_SHADER_STORAGE_BUFFER : 0;
102
103 GLenum usageMode = GL_STREAM_COPY;
104 switch (usage)
105 {
107 switch (accessMode)
108 {
109 case AccessMode::Read: usageMode = GL_STREAM_READ; break;
110 case AccessMode::Write: usageMode = GL_STREAM_DRAW; break;
111 default: usageMode = GL_STREAM_COPY; break;
112 }
113 break;
115 switch (accessMode)
116 {
117 case AccessMode::Read: usageMode = GL_STATIC_READ; break;
118 case AccessMode::Write: usageMode = GL_STATIC_DRAW; break;
119 default: usageMode = GL_STATIC_COPY; break;
120 }
121 break;
123 switch (accessMode)
124 {
125 case AccessMode::Read: usageMode = GL_DYNAMIC_READ; break;
126 case AccessMode::Write: usageMode = GL_DYNAMIC_DRAW; break;
127 default: usageMode = GL_DYNAMIC_COPY; break;
128 }
129 break;
131 switch (accessMode)
132 {
133 case AccessMode::Read: usageMode = GL_STREAM_READ; break;
134 case AccessMode::Write: usageMode = GL_STREAM_DRAW; break;
135 default: usageMode = GL_STREAM_COPY; break;
136 }
137 break;
138 default:
139 break;
140 }
141
142
143 BufferGL20 buffer = { GL_INVALID_INDEX, GL_INVALID_INDEX, size, 0, bindFlagsGl, bindFlags, {}, std::vector<uint8_t>(), MapMode::Read };
144
145 buffer.bufferId = createBuffer(bindFlagsGl, data, size, usageMode);
146
148 buffer.counterBufferId = createBuffer(GL_COPY_WRITE_BUFFER, nullptr, sizeof(GLuint), GL_DYNAMIC_COPY);
149 }
150
151 if (bindFlags & BindFlags::VertexBuffer) {
152 RegisterGPUResource(glBufferFakeAddress(buffer.bufferId), buffer.size, MemBlockType::GPUVertexBuffer);
153 }
154 else if (bindFlags & BindFlags::IndexBuffer) {
155 RegisterGPUResource(glBufferFakeAddress(buffer.bufferId), buffer.size, MemBlockType::GPUIndexBuffer);
156 }
157 else if (bindFlags & BindFlags::ConstantBuffer) {
158 RegisterGPUResource(glBufferFakeAddress(buffer.bufferId), buffer.size, MemBlockType::GPUConstantBuffer);
159 }
160 else {
161 RegisterGPUResource(glBufferFakeAddress(buffer.bufferId), buffer.size, MemBlockType::GPUBuffer);
162 }
163
164 BufferHandle handle = this->buffers.addResource(std::move(buffer));
165 recordBufferCreate(handle, static_cast<BindFlags::EBindFlags>(bindFlags), size);
166 return handle;
167}
168
169
170void Cogs::BuffersGL20::retrieveSubBuffer(void * data, BufferHandle source, const size_t offset, const size_t size)
171{
172 assert(HandleIsValid(source) && "Source buffer handle must be valid.");
173 const auto & sourceBuffer = this->buffers[source];
174 assert((offset + size <= sourceBuffer.size) && "Requested read outside source buffer.");
175
176#ifndef __APPLE__
177 if (glGetNamedBufferSubData) {
178 glGetNamedBufferSubData(sourceBuffer.bufferId, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), data);
179 }
180 else
181#endif
182 {
183 glBindBuffer(sourceBuffer.target, sourceBuffer.bufferId);
184 glGetBufferSubData(sourceBuffer.target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), data);
185 glBindBuffer(sourceBuffer.target, 0);
186 }
187}
188
190{
191 if (!HandleIsValid(bufferHandle)) return;
192
193 auto & buffer = this->buffers[bufferHandle];
194
195 if (buffer.bufferId != GL_INVALID_INDEX) {
196 UnregisterGPUResource(glBufferFakeAddress(buffer.bufferId));
197 glDeleteBuffers(1, &buffer.bufferId);
198 buffer.bufferId = GL_INVALID_INDEX;
199 }
200
201 if (buffer.counterBufferId != GL_INVALID_INDEX) {
202 glDeleteBuffers(1, &buffer.counterBufferId);
203 buffer.counterBufferId = GL_INVALID_INDEX;
204 }
205
206 recordBufferRelease(bufferHandle, static_cast<BindFlags::EBindFlags>(buffer.bindFlags), buffer.size);
207 this->buffers.removeResource(bufferHandle);
208}
209
211{
212 {
213 std::vector<BufferHandle> handles;
214 for (auto & buffer : buffers) {
215 handles.push_back(buffers.getHandle(buffer));
216 }
217
218 for (auto & handle : handles) {
219 releaseBuffer(handle);
220 }
221 }
222 {
223 std::vector<InputLayoutHandle> handles;
224 for (auto & layout : inputLayouts) {
225 handles.push_back(inputLayouts.getHandle(layout));
226 }
227
228 for (auto & handle : handles) {
229 releaseInputLayout(handle);
230 }
231 }
232}
233
235{
236 auto & buffer = this->buffers[handle];
237#ifndef __APPLE__
238 glObjectLabel(GL_BUFFER, buffer.bufferId, static_cast<GLsizei>(name.size()), name.data());
239#else
240 (void)buffer;
241 (void)name;
242#endif
243}
245{
246 auto & buffer = this->buffers[handle];
247#ifndef __APPLE__
248 glObjectLabel(GL_BUFFER, buffer.bufferId, static_cast<GLsizei>(name.size()), name.data());
249#else
250 (void)buffer;
251 (void)name;
252#endif
253}
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:50
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
Definition: StringView.h:197
constexpr size_t size() const noexcept
Get the size of the string.
Definition: StringView.h:204
@ 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
EBindFlags
Bind flags enumeration.
Definition: Flags.h:64
@ 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 recordBufferCreate(BufferHandle handle, BindFlags::EBindFlags bindFlags, size_t bytes)
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:91
void releaseInputLayout(InputLayoutHandle vertexFormatHandle) override
Releases the input layout with the given inputLayoutHandle.
Definition: BuffersGL20.cpp:86
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:44
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:54
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:68
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:73
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:49
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