gl_engine: seperate the index buffer from vertex buffer

WebGL has a strict rule that does not allow the same GLBuffer
to be bound to both ARRAY_BUFFER and ELEMENT_ARRAY_BUFFER at the same time.
(https://registry.khronos.org/webgl/specs/latest/1.0/#5.14.5)

To support WebGL in the future, a separate GLBuffer is used to store index data.
This commit is contained in:
RuiwenTang 2024-10-25 16:46:08 +08:00 committed by Hermet Park
parent e66f6853d9
commit 8b37ec5d9c
4 changed files with 38 additions and 17 deletions

View file

@ -142,7 +142,7 @@ bool GlGeometry::draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdate
if (indexBuffer->count == 0) return false;
uint32_t vertexOffset = gpuBuffer->push(vertexBuffer->data, vertexBuffer->count * sizeof(float));
uint32_t indexOffset = gpuBuffer->push(indexBuffer->data, indexBuffer->count * sizeof(uint32_t));
uint32_t indexOffset = gpuBuffer->pushIndex(indexBuffer->data, indexBuffer->count * sizeof(uint32_t));
// vertex layout
if (flag & RenderUpdateFlag::Image) {

View file

@ -72,7 +72,7 @@ void GlGpuBuffer::unbind(Target target)
GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), 0));
}
GlStageBuffer::GlStageBuffer() : mVao(0), mGpuBuffer(new GlGpuBuffer)
GlStageBuffer::GlStageBuffer() : mVao(0), mGpuBuffer(), mGpuIndexBuffer()
{
GL_CHECK(glGenVertexArrays(1, &mVao));
}
@ -102,14 +102,33 @@ uint32_t GlStageBuffer::push(void *data, uint32_t size, bool alignGpuOffset)
return offset;
}
uint32_t GlStageBuffer::pushIndex(void *data, uint32_t size)
{
uint32_t offset = mIndexBuffer.count;
if (this->mIndexBuffer.reserved - this->mIndexBuffer.count < size) {
this->mIndexBuffer.grow(max(size, this->mIndexBuffer.reserved));
}
memcpy(this->mIndexBuffer.data + offset, data, size);
this->mIndexBuffer.count += size;
return offset;
}
void GlStageBuffer::flushToGPU()
{
if (mStageBuffer.empty()) return;
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer->updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, mStageBuffer.count, mStageBuffer.data);
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer.bind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer.updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, mStageBuffer.count, mStageBuffer.data);
mGpuBuffer.unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuIndexBuffer.bind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
mGpuIndexBuffer.updateBufferData(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER, mIndexBuffer.count, mIndexBuffer.data);
mGpuIndexBuffer.unbind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
mStageBuffer.clear();
}
@ -117,22 +136,22 @@ void GlStageBuffer::flushToGPU()
void GlStageBuffer::bind()
{
glBindVertexArray(mVao);
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer->bind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
mGpuBuffer->bind(GlGpuBuffer::Target::UNIFORM_BUFFER);
mGpuBuffer.bind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer.bind(GlGpuBuffer::Target::UNIFORM_BUFFER);
mGpuIndexBuffer.bind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
}
void GlStageBuffer::unbind()
{
glBindVertexArray(0);
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer->unbind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
mGpuBuffer->unbind(GlGpuBuffer::Target::UNIFORM_BUFFER);
mGpuBuffer.unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer.unbind(GlGpuBuffer::Target::UNIFORM_BUFFER);
mGpuIndexBuffer.unbind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
}
GLuint GlStageBuffer::getBufferId()
{
return mGpuBuffer->getBufferId();
return mGpuBuffer.getBufferId();
}
void GlStageBuffer::alignOffset(uint32_t size)

View file

@ -23,8 +23,6 @@
#ifndef _TVG_GL_GPU_BUFFER_H_
#define _TVG_GL_GPU_BUFFER_H_
#include <memory>
#include "tvgGlCommon.h"
class GlGpuBuffer
@ -56,6 +54,8 @@ public:
uint32_t push(void* data, uint32_t size, bool alignGpuOffset = false);
uint32_t pushIndex(void* data, uint32_t size);
void flushToGPU();
void bind();
@ -67,8 +67,10 @@ private:
void alignOffset(uint32_t size);
private:
GLuint mVao = 0;
unique_ptr<GlGpuBuffer> mGpuBuffer = {};
GlGpuBuffer mGpuBuffer = {};
GlGpuBuffer mGpuIndexBuffer = {};
Array<uint8_t> mStageBuffer = {};
Array<uint8_t> mIndexBuffer = {};
};
#endif /* _TVG_GL_GPU_BUFFER_H_ */

View file

@ -478,7 +478,7 @@ void GlRenderer::drawClip(Array<RenderData>& clips)
mat4[15] = 1.f;
auto identityVertexOffset = mGpuBuffer->push(identityVertex.data, 8 * sizeof(float));
auto identityIndexOffset = mGpuBuffer->push(identityIndex.data, 6 * sizeof(uint32_t));
auto identityIndexOffset = mGpuBuffer->pushIndex(identityIndex.data, 6 * sizeof(uint32_t));
auto mat4Offset = mGpuBuffer->push(mat4, 16 * sizeof(float), true);
Array<int32_t> clipDepths(clips.count);
@ -744,7 +744,7 @@ void GlRenderer::prepareCmpTask(GlRenderTask* task, const RenderRegion& vp, uint
indices.push(3);
uint32_t vertexOffset = mGpuBuffer->push(vertices.data, vertices.count * sizeof(float));
uint32_t indexOffset = mGpuBuffer->push(indices.data, indices.count * sizeof(uint32_t));
uint32_t indexOffset = mGpuBuffer->pushIndex(indices.data, indices.count * sizeof(uint32_t));
task->addVertexLayout(GlVertexLayout{0, 2, 4 * sizeof(float), vertexOffset});
task->addVertexLayout(GlVertexLayout{1, 2, 4 * sizeof(float), vertexOffset + 2 * sizeof(float)});