New InstanceManager: Instancing done the right way

Discussion area about developing or extending OGRE, adding plugins for it or building applications on it. No newbie questions please, use the Help forum for that.
User avatar
spacegaier
OGRE Team Member
OGRE Team Member
Posts: 4304
Joined: Mon Feb 04, 2008 2:02 pm
Location: Germany
x 136

Re: New InstanceManager: Instancing done the right way

Post by spacegaier »

I am pretty sure that it is already in the trunk (1.8). The commit messages seem to back that up.
Ogre Admin [Admin, Dev, PR, Finance, Wiki, etc.] | BasicOgreFramework | AdvancedOgreFramework
Don't know what to do in your spare time? Help the Ogre wiki grow! Or squash a bug...
Syphorlate
Gnoblar
Posts: 6
Joined: Wed Aug 31, 2011 7:26 pm

Re: New InstanceManager: Instancing done the right way

Post by Syphorlate »

I'll look into it. THX
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179

Re: New InstanceManager: Instancing done the right way

Post by jacmoe »

They are indeed pushing to the default branch (upcoming Ogre 1.8 )
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5433
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1341

Re: New InstanceManager: Instancing done the right way

Post by dark_sylinc »

New Instancing has been pushed into trunk since a long time by now.

What Mattan hasn't pushed yet are a few of his changes. One of his latest changes introduced a severe performance bug, and we have the fix already but hasn't been pushed yet.

I'm using Revision 2898 and that one doesn't have this performance bug.
Arkiruthis
Gremlin
Posts: 178
Joined: Fri Dec 24, 2010 7:55 pm
x 10

Re: New InstanceManager: Instancing done the right way

Post by Arkiruthis »

dark_sylinc: Firstly, thank you for your work on the new InstanceManager, I'm working with 1.8 and looking forward to implementing it (having built the new Instancing Sample).

A quick question:
In my game, all characters use the same mesh, but there are 4 different materials depending on allegiance. Am I best to have 4 InstanceManagers and update them (remove from one, add to another) whenever a character changes allegiance (i.e., needs a different material)?

I guess setMaterial() is out of the question per instance? (which is understandable)
User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
x 56

Re: New InstanceManager: Instancing done the right way

Post by Klaim »

CaptainFlaps> Check this post's picture in this same thread : http://www.ogre3d.org/forums/viewtopic. ... 86#p433386
Arkiruthis
Gremlin
Posts: 178
Joined: Fri Dec 24, 2010 7:55 pm
x 10

Re: New InstanceManager: Instancing done the right way

Post by Arkiruthis »

Oh! Interesting, thank you Klaim. I'll keep an eye on that. :) (in the meantime, I think I'll stick to regular entities and see how things pan out)

[edit - oh, haha, it was the same thread. That was embarrassing... :oops: ]
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5433
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1341

Re: New InstanceManager: Instancing done the right way

Post by dark_sylinc »

CaptainFlaps wrote:In my game, all characters use the same mesh, but there are 4 different materials depending on allegiance. Am I best to have 4 InstanceManagers and update them (remove from one, add to another) whenever a character changes allegiance (i.e., needs a different material)?
Yes. You nailed it. At least for now that's the only way.
So prepare your to code be ready to be able to swap the InstancedEntity pointers. Note that adding->removing->adding should be a very fast operation, since the InstancedEntities are already preallocated when a new batch is created, and then they're put to sleep when removed. It will be slightly slower if you just maxed out all batches, and a new batch needs to be created.

Furthermore, I don't think your units will be changing allegiance that often (i.e. once per frame). But rather once in a few minutes in worst case scenario.

I wrote InstanceManager with RTS games in mind. As for performance considerations, watch out for fragmentation (i.e. having instances from the same batch very separate apart) which is solved by periodically calling defragmentBatches() (it's slow, so be sure to not do it often; RTS users will be forgiving if the game stalls a few seconds every 15 minutes or so, don't push it; action gamers just won't forgive you) and of course the more different units the are, the more different InstanceManagers you'll need which will start negating the gains from Instancing.

All in all is just about trying what works best in your case, and do your best to design your game to take maximum advantage of your technical strongpoints, minimizing the weaknesses.

Cheers
Dark Sylinc
Arkiruthis
Gremlin
Posts: 178
Joined: Fri Dec 24, 2010 7:55 pm
x 10

Re: New InstanceManager: Instancing done the right way

Post by Arkiruthis »

dark_sylinc: Awesome, thanks for that! I'll also figure in a periodic defragmentation (I have a routine that does 'housecleaning' every so often and can slot it in there). Early results from the New Instancing are most promising on my setup. :)
Arkiruthis
Gremlin
Posts: 178
Joined: Fri Dec 24, 2010 7:55 pm
x 10

Re: New InstanceManager: Instancing done the right way

Post by Arkiruthis »

On the latest 1.8 mercurial sources, I had to add "OgreNode.h" to the top of "OgreInstancedEntity.h" in order to build 1.8 successfully on MinGW. Don't think this happened with Visual Studio 2010 though.

Seems to be because on line 252 in _getParentNodeFullTransform(), there is a call for _getFullTransform() (part of OgreNode class) and possibly MinGW needs to see the full OgreNode.h definition to compile it inline in a header file (VS2010 perhaps does things in a different order):

As I say, I just added "OgreNode.h" and the build went fine but didn't want to submit a patch because it might just be something on my setup or something specific to MinGW builds.
User avatar
mkultra333
Gold Sponsor
Gold Sponsor
Posts: 1894
Joined: Sun Mar 08, 2009 5:25 am
x 116

Re: New InstanceManager: Instancing done the right way

Post by mkultra333 »

I have not been following this thread, and haven't been interested in instancing before, but now it's caught my eye. But I can't really tell what it can and can't do from this thread, when you should use it and when you shouldn't, what the downside is. I've looked up "instancing" and "instancemanager" in the wiki and nothing comes up, apart from some stuff from 2006 GSOC which I don't think is relevant anymore.

From what I gather, instancing allows you to have thousands of animated meshes at the cost of just a single batch, plus the CPU overhead for each of their nodes. If this is the case, why would anyone not use instancing? In a typical game where you're being attacked by 10 monsters, wouldn't you always chose instancing?

It seems as if it's just like hardware skinning only with unlimited bones. Not really any downside. All the instanced models can have their own animations, you can even move the bones manually. So for instance, I could explode one mesh manually, spreading it's bones over the map, while the other meshes ran about fighting.

Is that correct?
"In theory there is no difference between practice and theory. In practice, there is." - Psychology Textbook.
User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
x 56

Re: New InstanceManager: Instancing done the right way

Post by Klaim »

In a typical game where you're being attacked by 10 monsters, wouldn't you always chose instancing?
If the 10 monsters are all different in meshes and animation, you just can't use intancing. Also I background wouldn't benefit from it.

But obviously, if you want to display tons of same pair and animation objects, it's clearly only benefits.

At least that's what I understand.
User avatar
mkultra333
Gold Sponsor
Gold Sponsor
Posts: 1894
Joined: Sun Mar 08, 2009 5:25 am
x 116

Re: New InstanceManager: Instancing done the right way

Post by mkultra333 »

When you say "same animation," does that mean all the monsters have to be using the walk animation at the same time? So you can't have one monster dancing, one monster shooting a gun, and one monster running? I noticed something in the thread saying they don't have to be playing the same animation frame, so for instance if they're walking they won't all walk in lock-step. But do they all need to be playing the same animation track?

What about if you are manually controlling bones? Can you set each instanced monster to have a different manually controlled pose?
"In theory there is no difference between practice and theory. In practice, there is." - Psychology Textbook.
User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
x 56

Re: New InstanceManager: Instancing done the right way

Post by Klaim »

Correct me if I'm wrong but from what I understand from this thread, they have to have the same animation "set". As I didn't use this feature yet, I'm not sure what it means in code, but I one of the improvements done recently is to allow different states of the same or different animations for the same mesh/skeleton. That means the position and animation informations are together in the instantiation data and rely on a set of animations available to those instantiation data.

Confirmation from the devs is very welcome :mrgreen:
dermont
Bugbear
Posts: 812
Joined: Thu Dec 09, 2004 2:51 am
x 42

Re: New InstanceManager: Instancing done the right way

Post by dermont »

CaptainFlaps wrote:On the latest 1.8 mercurial sources, I had to add "OgreNode.h" to the top of "OgreInstancedEntity.h" in order to build 1.8 successfully on MinGW. Don't think this happened with Visual Studio 2010 though.

Seems to be because on line 252 in _getParentNodeFullTransform(), there is a call for _getFullTransform() (part of OgreNode class) and possibly MinGW needs to see the full OgreNode.h definition to compile it inline in a header file (VS2010 perhaps does things in a different order):

As I say, I just added "OgreNode.h" and the build went fine but didn't want to submit a patch because it might just be something on my setup or something specific to MinGW builds.
You should submit your patch, it appears to be gcc related since the same problem occurs here on Linux.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5433
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1341

Re: New InstanceManager: Instancing done the right way

Post by dark_sylinc »

Yes, documentation is lacking and should be a greater priority. Sorry :oops:

The advantages and drawbacks can be found in many papers though.
You may find usefull the code documentation which is generated from the comments in files OgreInstanceManager.h OgreInstanceBatch.h OgreInstancedEntity.h

As for your questions:
The first requisit to get a perf. boost from instancing is to be CPU overhead. If you're GPU bound there's no benefit at all.
mkultra333 wrote:IFrom what I gather, instancing allows you to have thousands of animated meshes at the cost of just a single batch
Having a single batch is not a cost, it's a benefit. However, this lowers chances of doing CPU scene graph culling; which if there's a lot of geometry you're not looking at with the camera and you're almost GPU bound, it will affect performance.
In a typical game where you're being attacked by 10 monsters, wouldn't you always chose instancing?
Because the 10 monsters must have the same mesh, and same material. They can have any animation you want playing at any rate.
There's one instancing technique recently made by Mattan which imposes a limit on animations and then starts repeating it in exchange for massive performance improvements. You're not forced to use that technique, but it's very handy for i.e. crowds in an arena or stadium, or random people walking in streets.

Advantage:
  • Major performance improvement (tipically ranging from 0.5x to 15x)
Drawbacks:
  • Generally: loss of flexibility
  • The more different materials you use, the lower the benefit.
  • Not possible to switch materials to an instanced entity (there are workarounds, check a few posts before this one)
  • Needs repetetive objects (i.e. rocks, particles, trees, leaves, grass, units in an RTS game)
  • Not suited to all kinds of scenes. Best case scenario when everything is viewed by the camera, worst case scenario when only one instance is in the camera everything else is behind it.
  • The render order is per batch, not per entity, therefore getting correct transparency (draw back to front) can be tricky.
  • May actually hurt performance if GPU bound
Hope this answers your questions
Cheers
Dark Sylinc
User avatar
mkultra333
Gold Sponsor
Gold Sponsor
Posts: 1894
Joined: Sun Mar 08, 2009 5:25 am
x 116

Re: New InstanceManager: Instancing done the right way

Post by mkultra333 »

Thanks dark_sylinc, that clears up a lot. I can't check the docs since I use 1.7.3. I was just wondering if I should update or not.

It doesn't sound like instancing would be a huge benefit to my project, the graphics part is mainly bound by lighting and shadows fragment shaders, and when I am cpu bound it's due to physics rather than graphics. Still, instancing does sound very interesting, and I might do something to try and take advantage of it in the future. The idea of 1000 robots running about on screen is just too tempting, and the implementation sounds very clever.

Oh, and when I said at the "cost of one batch", I meant that as a good thing, for instance as opposed to the cost of 1000 batches. :)

Edit: One more question. I use manually controlled bones a lot. You mention "They can have any animation you want playing at any rate." Can I also manually control all the bones if I want?
"In theory there is no difference between practice and theory. In practice, there is." - Psychology Textbook.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5433
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1341

Re: New InstanceManager: Instancing done the right way

Post by dark_sylinc »

mkultra333 wrote:Edit: One more question. I use manually controlled bones a lot. You mention "They can have any animation you want playing at any rate." Can I also manually control all the bones if I want?
Yes. If it's not working, then it's a bug and post it here we'll fix it.
11011001
Gnoblar
Posts: 12
Joined: Thu May 21, 2009 12:40 pm

Re: New InstanceManager: Instancing done the right way

Post by 11011001 »

Has anyone got this working on OS X Lion?
manituan
Gnoblar
Posts: 13
Joined: Sat Jul 02, 2011 2:30 am

Re: New InstanceManager: Instancing done the right way

Post by manituan »

Hi. I really appreciate your work.
I´m implementing your sample in my Ogre 1.8 project and I only see one mesh, but in the triangle count appears 9 million of them. The engine doesn´t show me them.
Do you know what it´s going on? Thanks.
jonim8or
Goblin
Posts: 287
Joined: Mon Dec 08, 2008 4:49 pm
x 10

Re: New InstanceManager: Instancing done the right way

Post by jonim8or »

does the triangle count also drop to almost zero when you rotate the camera so you don't see that one mesh?
Then I guess for some reason all the meshes are drawn at the same position.

Are you using one of the meshes+materials from the demo, or your own? The demo has special materials to do the techniques with.

For me some of the techniques are working, others are not. so you might need to experimetn with the different techniques.
11011001
Gnoblar
Posts: 12
Joined: Thu May 21, 2009 12:40 pm

Re: New InstanceManager: Instancing done the right way

Post by 11011001 »

11011001 wrote:Has anyone got this working on OS X Lion?
Has anyone else failed to get this working on OS X?
User avatar
m2codeGEN
Halfling
Posts: 52
Joined: Tue Apr 26, 2011 9:13 am
Location: Russia, Tver
x 2

Re: New InstanceManager: Instancing done the right way

Post by m2codeGEN »

HI dears Ogre Contributors :D
Let me throw my 50 cents in the total sum. I use Ogre 1.8 RC1

1) Possible memory leak SceneManager::createInstanceManager.

Code: Select all

InstanceManager* SceneManager::createInstanceManager( const String &customName, const String &meshName,  const String &groupName, InstanceManager::InstancingTechnique technique, size_t numInstancesPerBatch, uint16 flags, unsigned short subMeshIdx )
{
   // m2codeGEN warning!!! first check for name unique, then create new instance
   InstanceManager *retVal = new InstanceManager( customName, this, meshName, groupName, technique, flags, numInstancesPerBatch, subMeshIdx );
   if (mInstanceManagerMap.find(customName) != mInstanceManagerMap.end())
  {
		OGRE_EXCEPT( Exception::ERR_DUPLICATE_ITEM, 
			"InstancedManager with name '" + customName + "' already exists!", 
			"SceneManager::createInstanceManager");
   }
   
   mInstanceManagerMap[customName] = retVal;
   return retVal;
}
2) Maybe it's worth to think about how to delete the old implementation of the InstancedGeometry. SceneManager and OgreMain have a lot of code.
3) Add a method SceneManager* InstanceManager::getSceneManager() const { return mSceneManager; }
4) I suggest to change the interface/or overload the interface InstanceManager::createInstancedEntity, InstanceManager::getFreeBatch, InstanceManager::buildNewBatch and send the material as a Pointer instead name, and do not perform a search in the resource group.
5) You can also change the storage method InstanceBatchMap with map<String, InstanceBatchVec> map<MaterialPtr, InstanceBatchVec>,
map<String, BatchSettings>::type BatchSettingsMap too. For a comparison of pointers is much faster strings.
6) void InstanceBatchShader::setupVertices you can use the overloaded constructor VertexData(VertexDeclaration* dcl, VertexBufferBinding* bind) and manually suspended flag VertexData::mDeleteDclBinding, and may in other types of batches too.
7) Add the call to the method MovableObject::_notifyManager in the constructor InstanceBatch we have InstanceManager *creator and we can call InstanceManager::getSceneManager()
8) It seems there is support for the relative rendering InstanceBatch::makeMatrixCameraRelative3x4, at the time when the method InstanceBatchHW::_updateRenderQueue throws an exception.

Regards,
Vadim
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5433
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1341

Re: New InstanceManager: Instancing done the right way

Post by dark_sylinc »

Hi! Thanks for the feedback.
m2codeGEN wrote: 1) Possible memory leak SceneManager::createInstanceManager.
3) Add a method SceneManager* InstanceManager::getSceneManager() const { return mSceneManager; }
Done. Don't know why would you need getSceneManager but I'm no one to judge. It doesn't hurt.
m2codeGEN wrote: 2) Maybe it's worth to think about how to delete the old implementation of the InstancedGeometry. SceneManager and OgreMain have a lot of code.
It's within my plans, but first it should be flagged as deprecated and leave it for a couple more versions before actually deleting it. I should start another thread with a poll & discussion.
m2codeGEN wrote: 4) I suggest to change the interface/or overload the interface InstanceManager::createInstancedEntity, InstanceManager::getFreeBatch, InstanceManager::buildNewBatch and send the material as a Pointer instead name, and do not perform a search in the resource group.
5) You can also change the storage method InstanceBatchMap with map<String, InstanceBatchVec> map<MaterialPtr, InstanceBatchVec>,
map<String, BatchSettings>::type BatchSettingsMap too. For a comparison of pointers is much faster strings.
You're right it would more efficient. Definately go with the overload, not the interface change option, since the whole idea is about the caller specifying the material he wants, rather than dealing with pointers. It's more "user friendly" (the user being the developer)
It's quite a significant change considering we're closening towards stable 1.8 release, so any changes regarding this should go to 1.9 default branch. Furthermore:
  • The performance impact isn't that big. New batches aren't created all the time, in fact it's possible there will be less than 5 usually. Anything more means you're probably negating any benefit from using instancing.
  • The actual places where look-ups are performed are in buildNewBatch & setSetting; due to the rarity in which they get called and the low number of different materials, the bottleneck is most likely somewhere else (ie. setting up new vertex buffers). Again, if buildNewBatch is called too often then you're doing something wrong or instancing isn't for you.
  • I'm really busy this month, the next one, and in February I'm foreseeing to be in crunch mode. So don't expect to see these changes happening until March at least. :?
Because of the reasons above, it will be a low priority for me. If someone wants to submit a patch (as long as there are two overloads like in most Ogre code using strings & pointers) then go ahead.
m2codeGEN wrote: 6) void InstanceBatchShader::setupVertices you can use the overloaded constructor VertexData(VertexDeclaration* dcl, VertexBufferBinding* bind) and manually suspended flag VertexData::mDeleteDclBinding, and may in other types of batches too.
7) Add the call to the method MovableObject::_notifyManager in the constructor InstanceBatch we have InstanceManager *creator and we can call InstanceManager::getSceneManager()
Could you elaborate on that? I didn't understand it.
m2codeGEN wrote: 8) It seems there is support for the relative rendering InstanceBatch::makeMatrixCameraRelative3x4, at the time when the method InstanceBatchHW::_updateRenderQueue throws an exception.
There's a technical limitation in which camera relative rendering can't be supported when using InstanceBatchHW and setStaticAndUpdate( true ) was called. If you want camera relative rendering, use a different instancing technique or set static batches to false (the default value)

Cheers & Thanks for the feedback
Dark Sylinc
User avatar
m2codeGEN
Halfling
Posts: 52
Joined: Tue Apr 26, 2011 9:13 am
Location: Russia, Tver
x 2

Re: New InstanceManager: Instancing done the right way

Post by m2codeGEN »

Thanks for the quick reply.
I planned upgrade PagedGeometry to use instancing without multi-threading. Therefore, the performance in render thread is expensive.
m2codeGEN wrote:
6) void InstanceBatchShader::setupVertices you can use the overloaded constructor VertexData(VertexDeclaration* dcl, VertexBufferBinding* bind) and manually suspended flag VertexData::mDeleteDclBinding, and may in other types of batches too.

Could you elaborate on that? I didn't understand it.
Lets see some code...

Code: Select all

mRenderOperation.vertexData = OGRE_NEW VertexData();
mRemoveOwnVertexData = true; //Raise flag to remove our own vertex data in the end (not always needed)

VertexData *thisVertexData = mRenderOperation.vertexData;
VertexData *baseVertexData = baseSubMesh->vertexData;

thisVertexData->vertexStart = 0;
thisVertexData->vertexCount = baseVertexData->vertexCount * mInstancesPerBatch;

HardwareBufferManager::getSingleton().destroyVertexDeclaration( thisVertexData->vertexDeclaration );
thisVertexData->vertexDeclaration = baseVertexData->vertexDeclaration->clone();
You destroy vertex declaration that was just created. mRenderOperation.vertexData = OGRE_NEW VertexData(); .... HardwareBufferManager::getSingleton().destroyVertexDeclaration( thisVertexData->vertexDeclaration );
Instead of this you can use the overloaded constructor VertexData(VertexDeclaration* dcl, VertexBufferBinding* bind) and manually suspended flag VertexData::mDeleteDclBinding.

Regards,
Vadim