mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
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:
parent
e0d1c947e6
commit
b6e168b315
6 changed files with 98 additions and 46 deletions
|
@ -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];
|
||||||
|
|
|
@ -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];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
Loading…
Add table
Reference in a new issue