From 8b37ec5d9c1a0d5d080b44d486c9afab619d415d Mon Sep 17 00:00:00 2001 From: RuiwenTang Date: Fri, 25 Oct 2024 16:46:08 +0800 Subject: [PATCH] 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. --- src/renderer/gl_engine/tvgGlGeometry.cpp | 2 +- src/renderer/gl_engine/tvgGlGpuBuffer.cpp | 41 +++++++++++++++++------ src/renderer/gl_engine/tvgGlGpuBuffer.h | 8 +++-- src/renderer/gl_engine/tvgGlRenderer.cpp | 4 +-- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/renderer/gl_engine/tvgGlGeometry.cpp b/src/renderer/gl_engine/tvgGlGeometry.cpp index 8944d668..c3284f63 100644 --- a/src/renderer/gl_engine/tvgGlGeometry.cpp +++ b/src/renderer/gl_engine/tvgGlGeometry.cpp @@ -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) { diff --git a/src/renderer/gl_engine/tvgGlGpuBuffer.cpp b/src/renderer/gl_engine/tvgGlGpuBuffer.cpp index cc5a179a..9163de8b 100644 --- a/src/renderer/gl_engine/tvgGlGpuBuffer.cpp +++ b/src/renderer/gl_engine/tvgGlGpuBuffer.cpp @@ -72,7 +72,7 @@ void GlGpuBuffer::unbind(Target target) GL_CHECK(glBindBuffer(static_cast(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) diff --git a/src/renderer/gl_engine/tvgGlGpuBuffer.h b/src/renderer/gl_engine/tvgGlGpuBuffer.h index d1392e4e..fca0d3f8 100644 --- a/src/renderer/gl_engine/tvgGlGpuBuffer.h +++ b/src/renderer/gl_engine/tvgGlGpuBuffer.h @@ -23,8 +23,6 @@ #ifndef _TVG_GL_GPU_BUFFER_H_ #define _TVG_GL_GPU_BUFFER_H_ -#include - #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 mGpuBuffer = {}; + GlGpuBuffer mGpuBuffer = {}; + GlGpuBuffer mGpuIndexBuffer = {}; Array mStageBuffer = {}; + Array mIndexBuffer = {}; }; #endif /* _TVG_GL_GPU_BUFFER_H_ */ diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 66c438de..ad7a3480 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -478,7 +478,7 @@ void GlRenderer::drawClip(Array& 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 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)});