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:
parent
9bd4c87b9c
commit
e93e8b7708
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)]; }
|
||||
|
@ -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++)
|
||||
|
Loading…
x
Reference in New Issue
Block a user