gl_engine: pack all data into one gpu buffer

Pack all data into one gpu buffer to avoid memory fragmentation
This commit is contained in:
RuiwenTang 2023-08-29 23:30:26 +08:00 committed by Hermet Park
parent e0d1c947e6
commit b6e168b315
6 changed files with 98 additions and 46 deletions

View file

@ -32,12 +32,9 @@
GlGeometry::~GlGeometry() GlGeometry::~GlGeometry()
{ {
if (mVao) {
glDeleteVertexArrays(1, &mVao);
}
} }
bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag) bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag, GlStageBuffer* gpuBuffer)
{ {
mFillVertexOffset = 0; mFillVertexOffset = 0;
mStrokeVertexOffset = 0; mStrokeVertexOffset = 0;
@ -46,13 +43,7 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
mFillCount = 0; mFillCount = 0;
mStrokeCount = 0; mStrokeCount = 0;
mStaveVertex.clear();
mStageIndex.clear();
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
mFillVertexOffset = mStaveVertex.count * sizeof(float);
mFillIndexOffset = mStageIndex.count * sizeof(uint32_t);
Array<float> vertex; Array<float> vertex;
Array<uint32_t> index; Array<uint32_t> index;
@ -61,14 +52,11 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
mFillCount = index.count; mFillCount = index.count;
mStaveVertex.push(vertex); mFillVertexOffset = gpuBuffer->push(vertex.data, vertex.count * sizeof(float));
mStageIndex.push(index); mFillIndexOffset = gpuBuffer->push(index.data, index.count * sizeof(uint32_t));
} }
if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
mStrokeVertexOffset = mStaveVertex.count * sizeof(float);
mStrokeIndexOffset = mStageIndex.count * sizeof(uint32_t);
Array<float> vertex; Array<float> vertex;
Array<uint32_t> index; Array<uint32_t> index;
@ -77,8 +65,8 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
mStrokeCount = index.count; mStrokeCount = index.count;
mStaveVertex.push(vertex); mStrokeVertexOffset = gpuBuffer->push(vertex.data, vertex.count * sizeof(float));
mStageIndex.push(index); mStrokeIndexOffset = gpuBuffer->push(index.data, index.count * sizeof(uint32_t));
} }
return true; return true;
@ -88,8 +76,6 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
void GlGeometry::disableVertex(uint32_t location) void GlGeometry::disableVertex(uint32_t location)
{ {
GL_CHECK(glDisableVertexAttribArray(location)); GL_CHECK(glDisableVertexAttribArray(location));
mVertexBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
mIndexBuffer->unbind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
} }
@ -100,10 +86,6 @@ void GlGeometry::draw(const uint32_t location, RenderUpdateFlag flag)
return; return;
} }
if (mVao == 0) glGenVertexArrays(1, &mVao);
glBindVertexArray(mVao);
updateBuffer(location);
uint32_t vertexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeVertexOffset : mFillVertexOffset; uint32_t vertexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeVertexOffset : mFillVertexOffset;
uint32_t indexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeIndexOffset : mFillIndexOffset; uint32_t indexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeIndexOffset : mFillIndexOffset;
@ -116,16 +98,6 @@ void GlGeometry::draw(const uint32_t location, RenderUpdateFlag flag)
} }
void GlGeometry::updateBuffer(uint32_t location)
{
if (mVertexBuffer == nullptr) mVertexBuffer = std::make_unique<GlGpuBuffer>();
if (mIndexBuffer == nullptr) mIndexBuffer = std::make_unique<GlGpuBuffer>();
mVertexBuffer->updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, mStaveVertex.count * sizeof(float), mStaveVertex.data);
mIndexBuffer->updateBufferData(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER, mStageIndex.count * sizeof(uint32_t), mStageIndex.data);
}
void GlGeometry::updateTransform(const RenderTransform* transform, float w, float h) void GlGeometry::updateTransform(const RenderTransform* transform, float w, float h)
{ {
float modelMatrix[16]; float modelMatrix[16];

View file

@ -181,7 +181,7 @@ public:
} }
}; };
class GlGpuBuffer; class GlStageBuffer;
class GlGeometry class GlGeometry
{ {
@ -189,26 +189,19 @@ public:
~GlGeometry(); ~GlGeometry();
bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag); bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag, GlStageBuffer* gpuBuffer);
void disableVertex(uint32_t location); void disableVertex(uint32_t location);
void draw(const uint32_t location, RenderUpdateFlag flag); void draw(const uint32_t location, RenderUpdateFlag flag);
void updateTransform(const RenderTransform* transform, float w, float h); void updateTransform(const RenderTransform* transform, float w, float h);
float* getTransforMatrix(); float* getTransforMatrix();
private: private:
void updateBuffer(const uint32_t location);
Array<float> mStaveVertex;
Array<uint32_t> mStageIndex;
uint32_t mFillVertexOffset; uint32_t mFillVertexOffset;
uint32_t mFillIndexOffset; uint32_t mFillIndexOffset;
uint32_t mFillCount; uint32_t mFillCount;
uint32_t mStrokeVertexOffset; uint32_t mStrokeVertexOffset;
uint32_t mStrokeIndexOffset; uint32_t mStrokeIndexOffset;
uint32_t mStrokeCount; uint32_t mStrokeCount;
GLuint mVao = 0;
std::unique_ptr<GlGpuBuffer> mVertexBuffer;
std::unique_ptr<GlGpuBuffer> mIndexBuffer;
float mTransform[16]; float mTransform[16];
}; };

View file

@ -22,6 +22,9 @@
#include "tvgGlGpuBuffer.h" #include "tvgGlGpuBuffer.h"
#include <math.h>
#include <string.h>
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */
/************************************************************************/ /************************************************************************/
@ -44,12 +47,66 @@ GlGpuBuffer::~GlGpuBuffer()
void GlGpuBuffer::updateBufferData(Target target, uint32_t size, const void* data) void GlGpuBuffer::updateBufferData(Target target, uint32_t size, const void* data)
{ {
GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), mGlBufferId));
GL_CHECK(glBufferData(static_cast<uint32_t>(target), size, data, GL_STATIC_DRAW)); GL_CHECK(glBufferData(static_cast<uint32_t>(target), size, data, GL_STATIC_DRAW));
} }
void GlGpuBuffer::bind(Target target)
{
GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), mGlBufferId));
}
void GlGpuBuffer::unbind(Target target) void GlGpuBuffer::unbind(Target target)
{ {
GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), 0)); GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), 0));
} }
GlStageBuffer::~GlStageBuffer()
{
if (mVao) {
glDeleteVertexArrays(1, &mVao);
mVao = 0;
}
}
uint32_t GlStageBuffer::push(void *data, uint32_t size)
{
uint32_t offset = mStageBuffer.count;
if (this->mStageBuffer.reserved - this->mStageBuffer.count < size) {
this->mStageBuffer.grow(max(size, this->mStageBuffer.reserved));
}
memcpy(this->mStageBuffer.data + offset, data, size);
this->mStageBuffer.count += size;
return offset;
}
void GlStageBuffer::flushToGPU()
{
if (mStageBuffer.empty()) return;
if (!mGpuBuffer) {
mGpuBuffer.reset(new GlGpuBuffer);
GL_CHECK(glGenVertexArrays(1, &mVao));
}
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer->updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, mStageBuffer.count, mStageBuffer.data);
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
}
void GlStageBuffer::bind()
{
glBindVertexArray(mVao);
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer->bind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
}
void GlStageBuffer::unbind()
{
glBindVertexArray(0);
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
mGpuBuffer->unbind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
}

View file

@ -23,6 +23,9 @@
#ifndef _TVG_GL_GPU_BUFFER_H_ #ifndef _TVG_GL_GPU_BUFFER_H_
#define _TVG_GL_GPU_BUFFER_H_ #define _TVG_GL_GPU_BUFFER_H_
#include <memory>
#include "tvgArray.h"
#include "tvgGlCommon.h" #include "tvgGlCommon.h"
class GlGpuBuffer class GlGpuBuffer
@ -37,11 +40,31 @@ public:
GlGpuBuffer(); GlGpuBuffer();
~GlGpuBuffer(); ~GlGpuBuffer();
void updateBufferData(Target target, uint32_t size, const void* data); void updateBufferData(Target target, uint32_t size, const void* data);
void bind(Target target);
void unbind(Target target); void unbind(Target target);
private: private:
uint32_t mGlBufferId = 0; uint32_t mGlBufferId = 0;
}; };
class GlStageBuffer {
public:
GlStageBuffer() = default;
~GlStageBuffer();
uint32_t push(void* data, uint32_t size);
void flushToGPU();
void bind();
void unbind();
private:
GLuint mVao = 0;
unique_ptr<GlGpuBuffer> mGpuBuffer = {};
Array<uint8_t> mStageBuffer = {};
};
#endif /* _TVG_GL_GPU_BUFFER_H_ */ #endif /* _TVG_GL_GPU_BUFFER_H_ */

View file

@ -87,16 +87,21 @@ bool GlRenderer::preRender()
} }
GlRenderTask::unload(); GlRenderTask::unload();
mGpuBuffer->flushToGPU();
// Blend function for straight alpha // Blend function for straight alpha
GL_CHECK(glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GL_CHECK(glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
GL_CHECK(glEnable(GL_BLEND)); GL_CHECK(glEnable(GL_BLEND));
mGpuBuffer->bind();
return true; return true;
} }
bool GlRenderer::postRender() bool GlRenderer::postRender()
{ {
//TODO: called just after render() mGpuBuffer->unbind();
return true; return true;
} }
@ -238,7 +243,7 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const
if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform) ) if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform) )
{ {
if (!sdata->geometry->tesselate(rshape, sdata->updateFlag)) return sdata; if (!sdata->geometry->tesselate(rshape, sdata->updateFlag, mGpuBuffer.get())) return sdata;
} }
return sdata; return sdata;
} }

View file

@ -24,6 +24,7 @@
#define _TVG_GL_RENDERER_H_ #define _TVG_GL_RENDERER_H_
#include "tvgGlRenderTask.h" #include "tvgGlRenderTask.h"
#include "tvgGlGpuBuffer.h"
class GlRenderer : public RenderMethod class GlRenderer : public RenderMethod
{ {
@ -58,7 +59,7 @@ public:
static int term(); static int term();
private: private:
GlRenderer(){}; GlRenderer(): mGpuBuffer(new GlStageBuffer) {};
~GlRenderer(); ~GlRenderer();
void initShaders(); void initShaders();
@ -66,6 +67,7 @@ private:
void drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag); void drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag);
vector<shared_ptr<GlRenderTask>> mRenderTasks; vector<shared_ptr<GlRenderTask>> mRenderTasks;
std::unique_ptr<GlStageBuffer> mGpuBuffer;
}; };
#endif /* _TVG_GL_RENDERER_H_ */ #endif /* _TVG_GL_RENDERER_H_ */