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);
153 buffer.
target = OpenGLES30::BufferTarget::ArrayBuffer;
157 LOG_ERROR_ONCE(logger,
"loadBuffer: Buffer with mixed vertex and index data is explicitly not supported by WebGL");
160 LOG_WARNING_ONCE(logger,
"loadBuffer: Buffer with mixed vertex and index data is explicitly not supported by WebGL");
166 buffer.
target = OpenGLES30::BufferTarget::ElementArrayBuffer;
177 LOG_ERROR_ONCE(logger,
"loadBuffer: IndexBuffer with unsupported stride %u", stride);
183 buffer.
target = OpenGLES30::BufferTarget::UniformBuffer;
186 buffer.
size = (buffer.
size + 15) & ~15;
190 buffer.
target = OpenGLES30::BufferTarget::TransformFeedbackBuffer;
193 buffer.
target = OpenGLES30::BufferTarget::CopyReadBuffer;
196 GLenum usage = GL_STATIC_DRAW;
200 usage = GL_STATIC_DRAW;
203 usage = GL_DYNAMIC_DRAW;
207 usage = GL_STREAM_READ;
211 assert(
false &&
"Illegal usage mode");
215 GLenum glTarget = context->bindBufferCopy(OpenGLES30::BufferTarget::CopyWriteBuffer, buffer);
216 glBufferData(glTarget,
static_cast<GLsizeiptr
>(buffer.
size), data, usage);
217 if(context->uploadStatisticsEnabled) context->uploadStatisticsBufferUpload(buffer.
size);
219 bufferMemoryConsumption += buffer.
size;
222 RegisterGPUResource(glBufferFakeAddress(buffer.
bufferId), buffer.
size, MemBlockType::GPUVertexBuffer);
225 RegisterGPUResource(glBufferFakeAddress(buffer.
bufferId), buffer.
size, MemBlockType::GPUIndexBuffer);
228 RegisterGPUResource(glBufferFakeAddress(buffer.
bufferId), buffer.
size, MemBlockType::GPUConstantBuffer);
231 RegisterGPUResource(glBufferFakeAddress(buffer.
bufferId), buffer.
size, MemBlockType::GPUBuffer);
234 return buffers.addResource(std::move(buffer));
239 if (!bufferHandle)
return;
244 context->unbindBuffer(bufferId);
246 bufferMemoryConsumption -= buffer.
size;
248 UnregisterGPUResource(glBufferFakeAddress(bufferId));
250 glDeleteBuffers(1, &bufferId);
252 buffers.removeResource(bufferHandle);
258 std::vector<BufferHandle> handles;
259 for (
auto& resource : buffers) {
260 handles.push_back(buffers.getHandle(resource));
262 for (
auto& handle : handles) {
263 releaseBuffer(handle);
267 std::vector<InputLayoutHandle> handles;
268 for (
auto& resource : inputLayouts) {
269 handles.push_back(inputLayouts.getHandle(resource));
271 for (
auto& handle : handles) {
272 releaseInputLayout(handle);
276 std::vector<VertexArrayObjectHandle> handles;
277 for (
auto& resource : vertexArrayObjects) {
278 handles.push_back(vertexArrayObjects.getHandle(resource));
280 for (
auto& handle : handles) {
281 releaseVertexArrayObject(handle);
288 LOG_ERROR_ONCE(logger,
"retrieveSubBuffer: not implemented");
294 const VertexFormat*
const* vertexFormats,
const uint32_t* vertexStrides,
const uint32_t* vertexOffsets,
297 if (!HandleIsValid(effectHandle)) {
298 LOG_ERROR_ONCE(logger,
"loadVertexArrayObject: needs valid effect");
301 const EffectGLES30& effect = effects->effects[effectHandle];
303 for (
size_t i = 0; i < vertexBufferCount; i++) {
304 if (!HandleIsValid(vertexBufferHandles[i])) {
305 LOG_ERROR_ONCE(logger,
"loadVertexArrayObject: vertex buffer handle %zu (of %zu) is invalid", i, vertexBufferCount);
311 GLenum indexType = GL_INVALID_ENUM;
312 if (HandleIsValid(indexBufferHandle)) {
315 LOG_ERROR_ONCE(logger,
"loadVertexArrayObject: Cannot bind non-index buffer as index buffer");
319 switch (indexStride) {
322 assert((indexType == GL_UNSIGNED_SHORT) || (indexType == GL_UNSIGNED_INT));
325 indexType = GL_UNSIGNED_SHORT;
328 indexType = GL_UNSIGNED_INT;
331 LOG_ERROR_ONCE(logger,
"loadVertexArrayObject: invalid index stride %u", indexStride);
338 glGenVertexArrays(1, &vao.glName);
339 glBindVertexArray(vao.glName);
341 for (
size_t b = 0; b < vertexBufferCount; b++) {
345 if (vertexFormats && vertexFormats[b]) {
346 vertexFormat = vertexFormats[b];
348 const GLsizei stride = vertexStrides && vertexStrides[b] ? vertexStrides[b] :
static_cast<GLsizei
>(getSize(*vertexFormat));
349 const GLsizei bufferOffset = vertexOffsets ? vertexOffsets[b] : 0;
352 glBindBuffer(GL_ARRAY_BUFFER, buffer.
bufferId);
357 GLint attributeLocation = -1;
358 for (
size_t i = 0; i < effect.activeAttributes; i++) {
359 if (effect.attributeSemantic[i].semantic == uint32_t(element.
semantic) &&
362 attributeLocation = effect.attributeLocation[i];
366 if (attributeLocation == -1) {
continue; }
369 if (format.isVertexFormat == 0) {
370 LOG_WARNING_ONCE(logger,
"Encountered unsupported vertex format");
374 const GLvoid* attribOffset =
reinterpret_cast<const GLvoid*
>((size_t)element.
offset + bufferOffset);
376 if (format.type == GL_FLOAT && format.components == 4 && format.columns == 4) {
377 for (GLuint a = 0; a < 4; a++) {
378 GLuint ix = attributeLocation + a;
379 glVertexAttribPointer(ix, 4, format.type, GL_TRUE, stride,
reinterpret_cast<const GLvoid*
>(
sizeof(GLfloat) * a * 4));
380 glEnableVertexAttribArray(ix);
386 if (format.columns == 1) {
387 if (format.isInteger) {
388 glVertexAttribIPointer(attributeLocation, format.components, format.type, stride, attribOffset);
391 glVertexAttribPointer(attributeLocation, format.components, format.type, format.isNormalized ? GL_TRUE : GL_FALSE, stride, attribOffset);
393 glEnableVertexAttribArray(attributeLocation);
394 glVertexAttribDivisor(attributeLocation, element.
instanceStep);
400 if (HandleIsValid(indexBufferHandle)) {
404 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.
bufferId);
406 vao.indexType = indexType;
407 switch (vao.indexType) {
408 case GL_UNSIGNED_SHORT:
409 vao.indexCount = GLsizei(buffer.
size / 2);
410 vao.indexStride = indexStride;
412 case GL_UNSIGNED_INT:
413 vao.indexCount = GLsizei(buffer.
size / 4);
414 vao.indexStride = indexStride;
417 assert(
false &&
"Illegal index type");
422 glBindVertexArray(0);
425 context->vertexArrayObject.indexType = GL_INVALID_ENUM;
426 context->vertexArrayObject.indexCount = 0;
427 context->vertexArrayObject.indexStride = 0;
428 return vertexArrayObjects.addResource(std::move(vao));
434 glDeleteVertexArrays(1, &vao.glName);
435 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.
@ 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 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.