Add a global VAO manager
This commit is contained in:
parent
0a7e1312b5
commit
afd97345f7
@ -508,6 +508,235 @@ void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum
|
||||
glGetError();
|
||||
}
|
||||
|
||||
class VBOGatherer
|
||||
{
|
||||
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
|
||||
GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT];
|
||||
std::vector<scene::IMeshBuffer *> storedCPUBuffer[VTXTYPE_COUNT];
|
||||
void *vtx_mirror[VTXTYPE_COUNT], *idx_mirror[VTXTYPE_COUNT];
|
||||
size_t vtx_cnt[VTXTYPE_COUNT], idx_cnt[VTXTYPE_COUNT];
|
||||
std::map<scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
|
||||
|
||||
void regenerateBuffer(enum VTXTYPE);
|
||||
void regenerateVAO(enum VTXTYPE);
|
||||
size_t getVertexPitch(enum VTXTYPE) const;
|
||||
VTXTYPE getVTXTYPE(video::E_VERTEX_TYPE type);
|
||||
void append(scene::IMeshBuffer *, VBOGatherer::VTXTYPE tp);
|
||||
public:
|
||||
VBOGatherer();
|
||||
std::pair<unsigned, unsigned> getBase(scene::IMeshBuffer *);
|
||||
unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; }
|
||||
unsigned getVAO(video::E_VERTEX_TYPE type) { return vao[getVTXTYPE(type)]; }
|
||||
~VBOGatherer()
|
||||
{
|
||||
for (unsigned i = 0; i < VTXTYPE_COUNT; i++)
|
||||
{
|
||||
if (vbo[i])
|
||||
glDeleteBuffers(1, &vbo[i]);
|
||||
if (ibo[i])
|
||||
glDeleteBuffers(1, &ibo[i]);
|
||||
if (vao[i])
|
||||
glDeleteVertexArrays(1, &vao[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VBOGatherer::VBOGatherer()
|
||||
{
|
||||
vao[0] = vao[1] = vao[2] = 0;
|
||||
vbo[0] = vbo[1] = vbo[2] = 0;
|
||||
ibo[0] = ibo[1] = ibo[2] = 0;
|
||||
vtx_cnt[0] = vtx_cnt[1] = vtx_cnt[2] = 0;
|
||||
idx_cnt[0] = idx_cnt[1] = idx_cnt[2] = 0;
|
||||
vtx_mirror[0] = vtx_mirror[1] = vtx_mirror[2] = NULL;
|
||||
idx_mirror[0] = idx_mirror[1] = idx_mirror[2] = NULL;
|
||||
}
|
||||
|
||||
void VBOGatherer::regenerateBuffer(enum VTXTYPE tp)
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
if (vbo[tp])
|
||||
glDeleteBuffers(1, &vbo[tp]);
|
||||
glGenBuffers(1, &vbo[tp]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
glBufferData(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_STATIC_DRAW);
|
||||
|
||||
if (ibo[tp])
|
||||
glDeleteBuffers(1, &ibo[tp]);
|
||||
glGenBuffers(1, &ibo[tp]);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(u16)* idx_cnt[tp], idx_mirror[tp], GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void VBOGatherer::regenerateVAO(enum VTXTYPE tp)
|
||||
{
|
||||
if (vao[tp])
|
||||
glDeleteVertexArrays(1, &vao[tp]);
|
||||
glGenVertexArrays(1, &vao[tp]);
|
||||
glBindVertexArray(vao[tp]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
|
||||
switch (tp)
|
||||
{
|
||||
case VTXTYPE_STANDARD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
break;
|
||||
case VTXTYPE_TCOORD:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// SecondTexcoord
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
break;
|
||||
case VTXTYPE_TANGENT:
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
|
||||
// Texcoord
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
|
||||
// Tangent
|
||||
glEnableVertexAttribArray(5);
|
||||
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
|
||||
// Bitangent
|
||||
glEnableVertexAttribArray(6);
|
||||
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48);
|
||||
break;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
size_t VBOGatherer::getVertexPitch(enum VTXTYPE tp) const
|
||||
{
|
||||
switch (tp)
|
||||
{
|
||||
case VTXTYPE_STANDARD:
|
||||
return getVertexPitchFromType(video::EVT_STANDARD);
|
||||
case VTXTYPE_TCOORD:
|
||||
return getVertexPitchFromType(video::EVT_2TCOORDS);
|
||||
case VTXTYPE_TANGENT:
|
||||
return getVertexPitchFromType(video::EVT_TANGENTS);
|
||||
default:
|
||||
assert(0 && "Wrong vtxtype");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
VBOGatherer::VTXTYPE VBOGatherer::getVTXTYPE(video::E_VERTEX_TYPE type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
return VTXTYPE_STANDARD;
|
||||
case video::EVT_2TCOORDS:
|
||||
return VTXTYPE_TCOORD;
|
||||
case video::EVT_TANGENTS:
|
||||
return VTXTYPE_TANGENT;
|
||||
default:
|
||||
assert(0 && "Wrong vtxtype");
|
||||
}
|
||||
};
|
||||
|
||||
void VBOGatherer::append(scene::IMeshBuffer *mb, VBOGatherer::VTXTYPE tp)
|
||||
{
|
||||
size_t old_vtx_cnt = vtx_cnt[tp];
|
||||
vtx_cnt[tp] += mb->getVertexCount();
|
||||
vtx_mirror[tp] = realloc(vtx_mirror[tp], vtx_cnt[tp] * getVertexPitch(tp));
|
||||
intptr_t dstptr = (intptr_t)vtx_mirror[tp] + (old_vtx_cnt * getVertexPitch(tp));
|
||||
memcpy((void *)dstptr, mb->getVertices(), mb->getVertexCount() * getVertexPitch(tp));
|
||||
mappedBaseVertex[tp][mb] = old_vtx_cnt;
|
||||
|
||||
size_t old_idx_cnt = idx_cnt[tp];
|
||||
idx_cnt[tp] += mb->getIndexCount();
|
||||
idx_mirror[tp] = realloc(idx_mirror[tp], idx_cnt[tp] * sizeof(u16));
|
||||
|
||||
dstptr = (intptr_t)idx_mirror[tp] + (old_idx_cnt * sizeof(u16));
|
||||
memcpy((void *)dstptr, mb->getIndices(), mb->getIndexCount() * sizeof(u16));
|
||||
mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16);
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> VBOGatherer::getBase(scene::IMeshBuffer *mb)
|
||||
{
|
||||
VTXTYPE tp = getVTXTYPE(mb->getVertexType());
|
||||
if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end())
|
||||
{
|
||||
assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end());
|
||||
storedCPUBuffer[tp].push_back(mb);
|
||||
append(mb, tp);
|
||||
regenerateBuffer(tp);
|
||||
regenerateVAO(tp);
|
||||
}
|
||||
|
||||
std::map<scene::IMeshBuffer*, unsigned>::iterator It;
|
||||
It = mappedBaseVertex[tp].find(mb);
|
||||
assert(It != mappedBaseVertex[tp].end());
|
||||
unsigned vtx = It->second;
|
||||
It = mappedBaseIndex[tp].find(mb);
|
||||
assert(It != mappedBaseIndex[tp].end());
|
||||
return std::pair<unsigned, unsigned>(vtx, It->second);
|
||||
}
|
||||
|
||||
static VBOGatherer *gatherersingleton = 0;
|
||||
|
||||
std::pair<unsigned, unsigned> getVAOOffsetAndBase(scene::IMeshBuffer *mb)
|
||||
{
|
||||
if (!gatherersingleton)
|
||||
gatherersingleton = new VBOGatherer();
|
||||
return gatherersingleton->getBase(mb);
|
||||
}
|
||||
|
||||
unsigned getVBO(video::E_VERTEX_TYPE type)
|
||||
{
|
||||
if (gatherersingleton)
|
||||
return gatherersingleton->getVBO(type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned getVAO(video::E_VERTEX_TYPE type)
|
||||
{
|
||||
if (gatherersingleton)
|
||||
return gatherersingleton->getVAO(type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resetVAO()
|
||||
{
|
||||
if (gatherersingleton)
|
||||
delete gatherersingleton;
|
||||
gatherersingleton = 0;
|
||||
}
|
||||
|
||||
ScopedGPUTimer::ScopedGPUTimer(GPUTimer &timer)
|
||||
{
|
||||
if (!UserConfigParams::m_profiler_enabled) return;
|
||||
|
@ -236,6 +236,11 @@ void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = f
|
||||
bool loadCompressedTexture(const std::string& compressed_tex);
|
||||
void saveCompressedTexture(const std::string& compressed_tex);
|
||||
|
||||
std::pair<unsigned, unsigned> getVAOOffsetAndBase(scene::IMeshBuffer *mb);
|
||||
unsigned getVAO(video::E_VERTEX_TYPE type);
|
||||
unsigned getVBO(video::E_VERTEX_TYPE type);
|
||||
void resetVAO();
|
||||
|
||||
void draw3DLine(const core::vector3df& start,
|
||||
const core::vector3df& end, irr::video::SColor color);
|
||||
|
||||
|
@ -267,6 +267,7 @@ void Track::cleanup()
|
||||
{
|
||||
QuadGraph::destroy();
|
||||
ItemManager::destroy();
|
||||
resetVAO();
|
||||
|
||||
ParticleKindManager::get()->cleanUpTrackSpecificGfx();
|
||||
// Clear reminder of transformed textures
|
||||
|
Loading…
x
Reference in New Issue
Block a user