1#include "../Base/ContextCommon.h"
3#include "ContextGLES30.h"
4#include "BuffersGLES30.h"
5#include "CapabilitiesGLES30.h"
6#include "EffectsGLES30.h"
7#include "FormatsGLES30.h"
15#if defined(COGS_WGL) && (defined(COGSRENDERING_GFX_ANNOTATE) || defined(OSOMP_EnableProfiler))
20 BufferGLES30& buffer = buffers[handle];
22#if defined( OSOMP_EnableProfiler )
23 OsoMPAttribute attribute = { COGSMEM_NameAttribute, ATTRIBUTETYPE_String };
25 std::string name_(name);
26 attribute.mData.mText = name_.c_str();
27 RegisterGPUResourceAttributes(glBufferFakeAddress(buffer.bufferId), &attribute, 1);
30#if defined(COGSRENDERING_GFX_ANNOTATE)
31 if (glObjectLabelKHR && handle && name) {
32 glObjectLabelKHR(GL_BUFFER_KHR, buffer.bufferId,
static_cast<GLsizei
>(name.length()), name.data());
41 BufferGLES30& buffer = buffers[handle];
43#if defined( OSOMP_EnableProfiler )
44 OsoMPAttribute attribute = { COGSMEM_NameAttribute, ATTRIBUTETYPE_String };
46 std::string name_(name);
47 attribute.mData.mText = name_.c_str();
48 RegisterGPUResourceAttributes(glBufferFakeAddress(buffer.bufferId), &attribute, 1);
51#if defined(COGSRENDERING_GFX_ANNOTATE)
52 if (glObjectLabelKHR && name) {
53 glObjectLabelKHR(GL_BUFFER_KHR, buffer.bufferId,
static_cast<GLsizei
>(name.length()), name.data());
64 const uint32_t stride = getSize(vertexFormat);
65 const size_t size = count * stride;
69 auto& buffer = buffers[handle];
71 auto formatHandle = createVertexFormat(vertexFormat.
elements.data(), vertexFormat.
elements.size());
73 buffer.vertexFormat = getVertexFormat(formatHandle);
74 buffer.target = OpenGLES30::BufferTarget::ArrayBuffer;
76 assert(buffer.vertexFormat);
83 return loadVertexBuffer(vertexData, count, *VertexFormats::getVertexFormat(vertexFormatHandle));
88 releaseBuffer(vertexBufferHandle);
93 return loadBuffer(indexData,
94 static_cast<uint32_t
>(count * indexSize),
96 static_cast<uint32_t
>(indexSize));
101 releaseBuffer(indexBufferHandle);
107 inputLayout.numFormats = count;
109 const uint32_t maxInputs = (uint32_t)capabilities->getDeviceCapabilities().MaxVertexInputElements;
111 for (
size_t i = 0; i < count; ++i) {
112 const VertexFormat* vertexFormat = VertexFormats::getVertexFormat(vertexFormats[i]);
114 inputLayout.formats[i] = getVertexFormat(vertexFormats[i]);
116 if (maxInputs <= vertexFormat->elements.size()) {
117 LOG_ERROR(logger,
"Input element count exceeds limit set by GL_MAX_VERTEX_ATTRIBS.");
121 return inputLayouts.addResource(inputLayout);
126 inputLayouts.removeResource(vertexFormatHandle);
131 if constexpr (
sizeof(uint32_t) <
sizeof(
size_t)) {
132 if (std::numeric_limits<uint32_t>::max() < size) {
133 LOG_ERROR(logger,
"Buffer size %zu larger than 32-bits is unsupported.", size);
139 if (bindFlags &
BindFlags::ShaderResource) { LOG_WARNING(logger,
"loadBuffer: OpenGLES30 loadBuffer does not support ShaderResource flag."); }
140 if (bindFlags &
BindFlags::RawBuffer) { LOG_WARNING(logger,
"loadBuffer: OpenGLES30 loadBuffer does not support RawBuffer flag."); }
141 if (bindFlags &
BindFlags::StructuredBuffer) { LOG_WARNING(logger,
"loadBuffer: OpenGLES30 loadBuffer does not support StructuredBuffer flag."); }
145 buffer.
size = uint32_t(size);
154 buffer.
target = OpenGLES30::BufferTarget::ArrayBuffer;
158 LOG_ERROR_ONCE(logger,
"loadBuffer: Buffer with mixed vertex and index data is explicitly not supported by WebGL");
161 LOG_WARNING_ONCE(logger,
"loadBuffer: Buffer with mixed vertex and index data is explicitly not supported by WebGL");
167 buffer.
target = OpenGLES30::BufferTarget::ElementArrayBuffer;
178 LOG_ERROR_ONCE(logger,
"loadBuffer: IndexBuffer with unsupported stride %u", stride);
184 buffer.
target = OpenGLES30::BufferTarget::UniformBuffer;
187 buffer.
size = (buffer.
size + 15) & ~15;
191 buffer.
target = OpenGLES30::BufferTarget::TransformFeedbackBuffer;
194 buffer.
target = OpenGLES30::BufferTarget::CopyReadBuffer;
197 GLenum usage = GL_STATIC_DRAW;
201 usage = GL_STATIC_DRAW;
204 usage = GL_DYNAMIC_DRAW;
208 usage = GL_STREAM_READ;
212 assert(
false &&
"Illegal usage mode");
216 GLenum glTarget = context->bindBufferCopy(OpenGLES30::BufferTarget::CopyWriteBuffer, buffer);
217 glBufferData(glTarget,
static_cast<GLsizeiptr
>(buffer.
size), data, usage);
218 if(context->uploadStatisticsEnabled) context->uploadStatisticsBufferUpload(buffer.
size);
221 RegisterGPUResource(glBufferFakeAddress(buffer.
bufferId), buffer.
size, MemBlockType::GPUVertexBuffer);
224 RegisterGPUResource(glBufferFakeAddress(buffer.
bufferId), buffer.
size, MemBlockType::GPUIndexBuffer);
227 RegisterGPUResource(glBufferFakeAddress(buffer.
bufferId), buffer.
size, MemBlockType::GPUConstantBuffer);
230 RegisterGPUResource(glBufferFakeAddress(buffer.
bufferId), buffer.
size, MemBlockType::GPUBuffer);
233 const size_t roundedSize = buffer.
size;
234 BufferHandle handle = buffers.addResource(std::move(buffer));
241 if (!bufferHandle)
return;
246 context->unbindBuffer(bufferId);
250 UnregisterGPUResource(glBufferFakeAddress(bufferId));
252 glDeleteBuffers(1, &bufferId);
254 buffers.removeResource(bufferHandle);
260 std::vector<BufferHandle> handles;
261 for (
auto& resource : buffers) {
262 handles.push_back(buffers.getHandle(resource));
264 for (
auto& handle : handles) {
265 releaseBuffer(handle);
269 std::vector<InputLayoutHandle> handles;
270 for (
auto& resource : inputLayouts) {
271 handles.push_back(inputLayouts.getHandle(resource));
273 for (
auto& handle : handles) {
274 releaseInputLayout(handle);
278 std::vector<VertexArrayObjectHandle> handles;
279 for (
auto& resource : vertexArrayObjects) {
280 handles.push_back(vertexArrayObjects.getHandle(resource));
282 for (
auto& handle : handles) {
283 releaseVertexArrayObject(handle);
290 LOG_ERROR_ONCE(logger,
"retrieveSubBuffer: not implemented");
296 const VertexFormat*
const* vertexFormats,
const uint32_t* vertexStrides,
const uint32_t* vertexOffsets,
299 if (!HandleIsValid(effectHandle)) {
300 LOG_ERROR_ONCE(logger,
"loadVertexArrayObject: needs valid effect");
303 const EffectGLES30& effect = effects->effects[effectHandle];
305 for (
size_t i = 0; i < vertexBufferCount; i++) {
306 if (!HandleIsValid(vertexBufferHandles[i])) {
307 LOG_ERROR_ONCE(logger,
"loadVertexArrayObject: vertex buffer handle %zu (of %zu) is invalid", i, vertexBufferCount);
313 GLenum indexType = GL_INVALID_ENUM;
314 if (HandleIsValid(indexBufferHandle)) {
317 LOG_ERROR_ONCE(logger,
"loadVertexArrayObject: Cannot bind non-index buffer as index buffer");
321 switch (indexStride) {
324 assert((indexType == GL_UNSIGNED_SHORT) || (indexType == GL_UNSIGNED_INT));
327 indexType = GL_UNSIGNED_SHORT;
330 indexType = GL_UNSIGNED_INT;
333 LOG_ERROR_ONCE(logger,
"loadVertexArrayObject: invalid index stride %u", indexStride);
340 glGenVertexArrays(1, &vao.glName);
341 glBindVertexArray(vao.glName);
343 for (
size_t b = 0; b < vertexBufferCount; b++) {
347 if (vertexFormats && vertexFormats[b]) {
348 vertexFormat = vertexFormats[b];
350 const GLsizei stride = vertexStrides && vertexStrides[b] ? vertexStrides[b] :
static_cast<GLsizei
>(getSize(*vertexFormat));
351 const GLsizei bufferOffset = vertexOffsets ? vertexOffsets[b] : 0;
354 glBindBuffer(GL_ARRAY_BUFFER, buffer.
bufferId);
359 GLint attributeLocation = -1;
360 for (
size_t i = 0; i < effect.activeAttributes; i++) {
361 if (effect.attributeSemantic[i].semantic == uint32_t(element.
semantic) &&
364 attributeLocation = effect.attributeLocation[i];
368 if (attributeLocation == -1) {
continue; }
371 if (format.isVertexFormat == 0) {
372 LOG_WARNING_ONCE(logger,
"Encountered unsupported vertex format");
376 const GLvoid* attribOffset =
reinterpret_cast<const GLvoid*
>((size_t)element.
offset + bufferOffset);
378 if (format.type == GL_FLOAT && format.components == 4 && format.columns == 4) {
379 for (GLuint a = 0; a < 4; a++) {
380 GLuint ix = attributeLocation + a;
381 glVertexAttribPointer(ix, 4, format.type, GL_TRUE, stride,
reinterpret_cast<const GLvoid*
>(
sizeof(GLfloat) * a * 4));
382 glEnableVertexAttribArray(ix);
388 if (format.columns == 1) {
389 if (format.isInteger) {
390 glVertexAttribIPointer(attributeLocation, format.components, format.type, stride, attribOffset);
393 glVertexAttribPointer(attributeLocation, format.components, format.type, format.isNormalized ? GL_TRUE : GL_FALSE, stride, attribOffset);
395 glEnableVertexAttribArray(attributeLocation);
396 glVertexAttribDivisor(attributeLocation, element.
instanceStep);
402 if (HandleIsValid(indexBufferHandle)) {
406 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.
bufferId);
408 vao.indexType = indexType;
409 switch (vao.indexType) {
410 case GL_UNSIGNED_SHORT:
411 vao.indexCount = GLsizei(buffer.
size / 2);
412 vao.indexStride = indexStride;
414 case GL_UNSIGNED_INT:
415 vao.indexCount = GLsizei(buffer.
size / 4);
416 vao.indexStride = indexStride;
419 assert(
false &&
"Illegal index type");
424 glBindVertexArray(0);
427 context->vertexArrayObject.indexType = GL_INVALID_ENUM;
428 context->vertexArrayObject.indexCount = 0;
429 context->vertexArrayObject.indexStride = 0;
430 return vertexArrayObjects.addResource(std::move(vao));
436 glDeleteVertexArrays(1, &vao.glName);
437 vertexArrayObjects.removeResource(vertexArrayObjectHandle);
Log implementation class.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ InstanceMatrix
Instance matrix semantic.
@ Write
The buffer can be mapped and written to by the CPU after creation.
@ None
The buffer can not be either read from or written to by the CPU after creation.
EBindFlags
Bind flags enumeration.
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
@ StructuredBufferWithCounter
The buffer can be bound as a structured buffer and read or written from shaders, with an additional a...
@ StreamOutBuffer
The buffer can be bound as stream output to receive transform feedback results.
@ VertexBuffer
The buffer can be bound as input to the vertex shader stage as a vertex buffer.
@ RawBuffer
The buffer can be bound as a byte address buffer and read or written from shaders.
@ IndexBuffer
The buffer can be bound as input to the vertex shader stage as an index buffer.
@ ShaderResource
The buffer can be bound as a shader resource and read from shaders.
@ StructuredBuffer
The buffer can be bound as a structured buffer and read or written from shaders.
GLuint bufferId
OpenGL buffer name.
unsigned short isMapped
Buffer is currently mapped.
OpenGLES30::BufferTarget target
OpenGL bind target.
uint32_t bindFlags
Original Cogs::BindFlags bitmask used to create the buffer.
uint32_t size
Buffer size..
GLenum indexType
OpenGL index type if buffer is an index buffer.
unsigned short isIndexBuffer
Buffer is an index buffer.
const VertexFormat * vertexFormat
Vertex format if buffer is a vertex buffer.
unsigned short keepMapBacking
Do not release memory mapping backing store after unmap, set to 1 for repeatedly mapped buffers.
unsigned short writeBackMap
Set by map, if one, write back results to GL after unmap (i.e. map with write flags).
VertexBufferHandle loadVertexBuffer(const void *vertexData, const size_t count, const VertexFormat &vertexFormat) override
Loads a new vertex buffer and populates it with the given data.
void releaseVertexBuffer(VertexBufferHandle vertexBufferHandle) override
Release the vertex buffer with the given handle.
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...
IndexBufferHandle loadIndexBuffer(const void *indexData, const size_t count, const size_t indexSize)
Loads a new index buffer and populates it with the given indexData.
void releaseResources()
Releases all allocated buffer resources.
VertexArrayObjectHandle loadVertexArrayObject(const EffectHandle effectHandle, const VertexBufferHandle *vertexBufferHandles, const size_t count, const VertexFormat *const *vertexFormats=nullptr, const uint32_t *strides=nullptr, const uint32_t *offsets=nullptr, const IndexBufferHandle indexBufferHandle=IndexBufferHandle::NoHandle, uint32_t stride=4) override
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.
void releaseBuffer(BufferHandle bufferHandle)
Releases the buffer with the given bufferHandle.
void releaseInputLayout(InputLayoutHandle vertexFormatHandle)
Releases the input layout with the given inputLayoutHandle.
void releaseIndexBuffer(IndexBufferHandle indexBufferHandle)
Releases the index buffer with the given handle.
virtual void retrieveSubBuffer(void *data, BufferHandle source, const size_t offset, const size_t size) override
Retrieves the contents of a buffer.
void releaseVertexArrayObject(VertexArrayObjectHandle vertexArrayObjectHandle)
static const Handle_t NoHandle
Represents a handle to nothing.
static const Handle_t InvalidHandle
Represents an invalid handle.
virtual void annotate(BufferHandle handle, const StringView &name)
Associate a name with an object for use in graphics debugging.
@ Static
Buffer will be loaded once and used to render many subsequent frames without any updates.
@ Dynamic
Buffer will be loaded and modified with some frequency.
Vertex element structure used to describe a single data element in a vertex for the input assembler.
DataFormat format
Format of the element.
uint16_t offset
Offset in bytes from the vertex position in memory.
uint16_t semanticIndex
Index for the semantic mapping.
ElementSemantic semantic
Semantic mapping of the element (position, normal, etc...).
uint16_t instanceStep
Instance step factor.