Author Topic: performance of material drawing in SkinModifier  (Read 593 times)

Josh Brown   «   on: May 26, 2016, 04:27:36 PM »
We have an issue in our app.  After we finish loading everything and the user makes several selections we start playing animations on about a 20 character meshes.  Everything works great except during the first 30 frames after we start animating the meshes.  We get 3 or 4 frames that take 10x the normal frame time.  Looking in scout, all the time on these few frames is coming from the skinmodifier.draw function.  Inside that call it makes a call to Material3D.draw which is doing a Material3D.upload and a FLSLMaterial.draw call.  And these two calls are taking a ton of time (200ms+) on a few random frames shortly after we start animating.  It's always within 30 frames and it's not always the same frames. 

Once the 3-4 frames of hitching are complete we never see this behavior again.  Is there some sort of delayed material setup or shader compilation on skinned meshes?  I'm sort of lost on this one so any ideas on something to try or more information I can gather that might reveal the problem would be great!

Josh Brown   «   Reply #1 on: May 27, 2016, 01:42:56 PM »
Well, I figured out that this appears to happen when the animated meshes move onto the screen, so my working theory right now is that the skinning shader is not applied until the object is being rendered - if it's culled then it doesn't get compiled and uploaded until it comes into view.  Which then causes a huge hitch during gameplay for us.  I'm not sure what happens if we start the animations on screen and then move them off screen and back on, but maybe that'll help.

Ariel Nehmad   «   Reply #2 on: May 29, 2016, 02:23:06 PM »
Hi Josh, you can try calling mesh.upload() after the model is loaded, that way you can force it to upload all the necessary resources to the GPU before start rendering.

Josh Brown   «   Reply #3 on: June 01, 2016, 12:44:20 AM »
Thanks Ariel,

I actually was able to move some stuff around in our loading order that got all our animated meshes to load and animated before we needed to show them to the user so that worked around my issue - but if I have to revisit this I'll give the mesh.upload a try.

I'm still working on performance optimizations for low end iOS devices.  I'm running scout and looking at where our most of our frame is going.  Scout isn't the greatest profiler and sometimes gives bad data but two things I noticed:

1) About 20%-30% of our frame is going to Mesh3D.get inView.  Is there any way to not compute this on a scene?  In our game, we know what's on/off screen at all times with the way we have structured the game so it would be nice to just set a visibility flag and not spend any time computing it.  Obviously that puts the onus on the user code to handle visibility correctly so we're not wasting rendering time on off-screen meshes, but if it's going to chew up so much frame time computing visibility then this seems like a reasonable place to gain some milliseconds back for us.  Do you have any suggestions on how to accomplish that or to reduce this time?

2) About 50% of our frame is going to the SkinModifier.draw call so that is where I'd like to focus my optimization efforts but I'm not sure what all to do here without knowing how the skinning is implemented.  In other engines I've worked with, reducing bones would have a near-linear reduction in the animation skinning time, but that doesn't seem to have much effect in our Flare.  Also, we essentially animate between a set of poses.  There seems to be a pretty high fixed cost for having a mesh animated even if it's not updated in a frame.  Is there a way to indicate to the skinning shader to not re-compute every frame when there isn't an animation actually affecting the mesh - or once we start animating do we pay the cost of the animation shader regardless?

 I've searched around and didn't find much in docs/google for optimizing flare3d animated meshes, but maybe you have a doc on this already I missed - please direct me to any docs you have too and sorry if I missed them :)  And if you could shed a little light on the top things to look at for optimizing animated meshes or any tricks I could try to speed up animations that would be really helpful.


Ariel Nehmad   «   Reply #4 on: June 02, 2016, 10:39:38 AM »
About the first one, just setting the mesh.bounds = null; will disable any flare3d visibility computations, but as you said, after that, is up to you to define what's visible and what's the engine will have no clue ;)

About the second one...keep in mind that inside the skin draw there is also the cost of the actual draw call and sending the buffers to the GPU.
If you're drawing many skinned meshes, makes sense that it takes some considerable time, otherwise, it shouldn't take that much of a CPU time the heavy part of the skinning is mostly done in the GPU.

Josh Brown   «   Reply #5 on: June 03, 2016, 11:17:30 AM »
Thanks Ariel,

That's exactly what I was looking for on the visibility.  After looking at that a little closer, it looks like we only see time spent in the inView method in debug builds.  In our release builds we don't seem to see any time there so not sure if we need this afterall :)

And thanks for the info on the skinning.  It looks like we're just not going to be able to implement our plan for low end devices, there just isn't enough juice on them to handle several animated characters.  We're only getting 12fps now and even if I could cut the animation time in half we'd be around 18, so we'll have to come up with a compromise in our game design.  Thanks for your help on this!