Make animated mesh render separately in instanced rendering

Try to introduce mesh + render info hash in vao manager, without
copying the mesh
This commit is contained in:
Benau 2016-10-26 14:25:48 +08:00
parent 9bd4c87b9c
commit e93e8b7708
5 changed files with 61 additions and 63 deletions

View File

@ -99,6 +99,16 @@ void STKAnimatedMesh::updateNoGL()
if (!isMaterialInitialized)
{
// Use a default render info to distinguish same mesh buffer created by
// different animated mesh node in vao manager when using instanced
// rendering
RenderInfo* default_ri = NULL;
if (CVS->isARBBaseInstanceUsable())
{
default_ri = new RenderInfo();
m_static_render_info.push_back(default_ri);
}
video::IVideoDriver* driver = SceneManager->getVideoDriver();
const u32 mb_count = m->getMeshBufferCount();
for (u32 i = 0; i < mb_count; ++i)
@ -121,7 +131,7 @@ void STKAnimatedMesh::updateNoGL()
}
else
{
cur_ri = NULL;
cur_ri = default_ri;
}
}
else
@ -137,7 +147,7 @@ void STKAnimatedMesh::updateNoGL()
assert(cur_ri ? cur_ri->isStatic() : true);
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name,
affected || m_all_parts_colorized || (cur_ri
&& cur_ri->isTransparent()) ? cur_ri : NULL));
&& cur_ri->isTransparent()) ? cur_ri : default_ri));
}
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
@ -221,7 +231,7 @@ void STKAnimatedMesh::updateGL()
if (CVS->isARBBaseInstanceUsable())
{
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb);
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb, GLmeshes[i].m_render_info);
mesh.vaoBaseVertex = p.first;
mesh.vaoOffset = p.second;
}

View File

@ -41,7 +41,6 @@
#include <unordered_map>
#include <SViewFrustum.h>
#include <functional>
template<typename T>
struct InstanceFiller
@ -156,28 +155,6 @@ FillInstances_impl(std::vector<std::pair<GLMesh *, scene::ISceneNode *> > Instan
PolyCount += (InstanceBufferOffset - InitialOffset) * mesh->IndexCount / 3;
}
class MeshRenderInfoHash
{
public:
size_t operator() (const std::pair<scene::IMeshBuffer*, RenderInfo*> &p) const
{
return (std::hash<scene::IMeshBuffer*>()(p.first) ^
(std::hash<RenderInfo*>()(p.second) << 1));
}
};
struct MeshRenderInfoEquals : std::binary_function
<const std::pair<scene::IMeshBuffer*, RenderInfo*>&,
const std::pair<scene::IMeshBuffer*, RenderInfo*>&, bool>
{
result_type operator() (first_argument_type lhs,
second_argument_type rhs) const
{
return (lhs.first == rhs.first) &&
(lhs.second == rhs.second);
}
};
template<typename T>
static
void FillInstances(const std::unordered_map<std::pair<scene::IMeshBuffer*, RenderInfo*>, std::vector<std::pair<GLMesh *, scene::ISceneNode*> >, MeshRenderInfoHash, MeshRenderInfoEquals> &GatheredGLMesh, std::vector<GLMesh *> &InstancedList,

View File

@ -287,7 +287,7 @@ irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp)
}
}
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp, RenderInfo* ri)
{
size_t old_vtx_cnt = last_vertex[tp];
size_t old_idx_cnt = last_index[tp];
@ -318,26 +318,28 @@ void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, old_idx_cnt * sizeof(u16), mb->getIndexCount() * sizeof(u16), mb->getIndices());
}
mappedBaseVertex[tp][mb] = old_vtx_cnt;
mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16);
std::pair<scene::IMeshBuffer*, RenderInfo*> key(mb, ri);
mappedBaseVertex[tp][key] = old_vtx_cnt;
mappedBaseIndex[tp][key] = old_idx_cnt * sizeof(u16);
}
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb, RenderInfo* ri)
{
VTXTYPE tp = getVTXTYPE(mb->getVertexType());
if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end())
std::pair<scene::IMeshBuffer*, RenderInfo*> key(mb, ri);
if (mappedBaseVertex[tp].find(key) == mappedBaseVertex[tp].end())
{
assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end());
append(mb, tp);
assert(mappedBaseIndex[tp].find(key) == mappedBaseIndex[tp].end());
append(mb, tp, ri);
regenerateVAO(tp);
regenerateInstancedVAO();
}
std::unordered_map<scene::IMeshBuffer*, unsigned>::iterator It;
It = mappedBaseVertex[tp].find(mb);
std::unordered_map<std::pair<scene::IMeshBuffer*, RenderInfo*>, unsigned, MeshRenderInfoHash, MeshRenderInfoEquals>::iterator It;
It = mappedBaseVertex[tp].find(key);
assert(It != mappedBaseVertex[tp].end());
unsigned vtx = It->second;
It = mappedBaseIndex[tp].find(mb);
It = mappedBaseIndex[tp].find(key);
assert(It != mappedBaseIndex[tp].end());
return std::pair<unsigned, unsigned>(vtx, It->second);
}

View File

@ -26,6 +26,8 @@
#include <map>
#include <unordered_map>
class RenderInfo;
enum InstanceType
{
InstanceTypeDualTex,
@ -153,6 +155,30 @@ struct GlowInstanceData
#pragma pack(pop)
#endif
#include <functional>
class MeshRenderInfoHash
{
public:
size_t operator() (const std::pair<irr::scene::IMeshBuffer*, RenderInfo*> &p) const
{
return (std::hash<irr::scene::IMeshBuffer*>()(p.first) ^
(std::hash<RenderInfo*>()(p.second) << 1));
}
};
struct MeshRenderInfoEquals : std::binary_function
<const std::pair<irr::scene::IMeshBuffer*, RenderInfo*>&,
const std::pair<irr::scene::IMeshBuffer*, RenderInfo*>&, bool>
{
result_type operator() (first_argument_type lhs,
second_argument_type rhs) const
{
return (lhs.first == rhs.first) &&
(lhs.second == rhs.second);
}
};
class VAOManager : public Singleton<VAOManager>
{
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
@ -162,7 +188,7 @@ class VAOManager : public Singleton<VAOManager>
void *VBOPtr[VTXTYPE_COUNT], *IBOPtr[VTXTYPE_COUNT];
size_t RealVBOSize[VTXTYPE_COUNT], RealIBOSize[VTXTYPE_COUNT];
size_t last_vertex[VTXTYPE_COUNT], last_index[VTXTYPE_COUNT];
std::unordered_map<irr::scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
std::unordered_map <std::pair<irr::scene::IMeshBuffer*, RenderInfo*>, unsigned, MeshRenderInfoHash, MeshRenderInfoEquals> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
std::map<std::pair<irr::video::E_VERTEX_TYPE, InstanceType>, GLuint> InstanceVAO;
void cleanInstanceVAOs();
@ -172,10 +198,10 @@ class VAOManager : public Singleton<VAOManager>
size_t getVertexPitch(enum VTXTYPE) const;
VTXTYPE getVTXTYPE(irr::video::E_VERTEX_TYPE type);
irr::video::E_VERTEX_TYPE getVertexType(enum VTXTYPE tp);
void append(irr::scene::IMeshBuffer *, VTXTYPE tp);
void append(irr::scene::IMeshBuffer *, VTXTYPE tp, RenderInfo* ri = NULL);
public:
VAOManager();
std::pair<unsigned, unsigned> getBase(irr::scene::IMeshBuffer *);
std::pair<unsigned, unsigned> getBase(irr::scene::IMeshBuffer *, RenderInfo* ri = NULL);
GLuint getInstanceBuffer(InstanceType it) { return instance_vbo[it]; }
void *getInstanceBufferPtr(InstanceType it) { return Ptr[it]; }
unsigned getVBO(irr::video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; }

View File

@ -247,12 +247,6 @@ KartModel::~KartModel()
{
// Master KartModels should never have a speed weighted object attached.
assert(!m_is_master);
// Drop the cloned transparent model if created
if (m_krt == KRT_TRANSPARENT)
{
m_speed_weighted_objects[i].m_model->drop();
}
m_speed_weighted_objects[i].m_node->drop();
}
if(m_is_master && m_speed_weighted_objects[i].m_model)
@ -262,20 +256,15 @@ KartModel::~KartModel()
}
}
// In case of the master, the mesh must be dropped. A non-master KartModel
// has a copy of the master's mesh, so it needs to be dropped, too.
if (m_mesh)
if (m_is_master && m_mesh)
{
m_mesh->drop();
if (m_is_master)
// If there is only one copy left, it's the copy in irrlicht's
// mesh cache, so it can be removed.
if (m_mesh && m_mesh->getReferenceCount() == 1)
{
// If there is only one copy left, it's the copy in irrlicht's
// mesh cache, so it can be removed.
if (m_mesh && m_mesh->getReferenceCount() == 1)
{
irr_driver->dropAllTextures(m_mesh);
irr_driver->removeMeshFromCache(m_mesh);
}
irr_driver->dropAllTextures(m_mesh);
irr_driver->removeMeshFromCache(m_mesh);
}
}
@ -308,7 +297,7 @@ KartModel* KartModel::makeCopy(KartRenderType krt)
km->m_kart_height = m_kart_height;
km->m_kart_highest_point = m_kart_highest_point;
km->m_kart_lowest_point = m_kart_lowest_point;
km->m_mesh = irr_driver->copyAnimatedMesh(m_mesh);
km->m_mesh = m_mesh;
km->m_model_filename = m_model_filename;
km->m_animation_speed = m_animation_speed;
km->m_current_animation = AF_DEFAULT;
@ -343,12 +332,6 @@ KartModel* KartModel::makeCopy(KartRenderType krt)
// Master should not have any speed weighted nodes.
assert(!m_speed_weighted_objects[i].m_node);
km->m_speed_weighted_objects[i] = m_speed_weighted_objects[i];
if (krt == KRT_TRANSPARENT)
{
// Only clone the mesh if transparent type is used, see #2445
km->m_speed_weighted_objects[i].m_model = irr_driver
->copyAnimatedMesh(m_speed_weighted_objects[i].m_model);
}
}
for(unsigned int i=AF_BEGIN; i<=AF_END; i++)