2D Toolkit Forum

2D Toolkit => Support => Topic started by: n0mad on March 20, 2012, 06:37:54 pm

Title: 3.5, and the drawcall inflation effect.
Post by: n0mad on March 20, 2012, 06:37:54 pm
I already had some drawcall rising problems with 3D objects, as mentionned in this thread (http://forum.unity3d.com/threads/123664-Lightmap-Directional-Light-Drawcalls-went-up-SOLVED).

But Joachim said it was because of projectors, and lighmapping now being taken by dynamic lights.
Except .... I'm now experiencing this filthly famous drawcall rising with .... my HUD.
I'm counting a difference of 9 drawcalls instead of 3 in the Editor (HUD + 2 fonts), whenever I activate/deactivate the HUD.

This HUD is entirely managed by 2DToolkit, and is using 1 Atlas + the builtin PremulVertexShader, so it should really be only 3 drawcalls.

I'd like to know if anyone is experiencing the same, or if the problem is reproduced at Unikron Software.

Thanks.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: unikronsoftware on March 20, 2012, 09:15:32 pm
A couple things to test to isolate the problem.

1. Turn off everything else apart from the HUD and get the draw call count then. Make sure you don't select anything, as selecting things changes the draw call count. Also make sure you turn off lights, projectors, etc (ideally just multiselect everything apart form the HUD and delete them)

2. Make sure you don't use the scale parameter, but rather use the 2D Toolkit sprite/textmesh scale parameter.

3. How many polys does Unity report you are drawing here?

4. Keep in mind sandwiching fonts & sprites in Z will increase drawcalls, eg.
HUD - TEXT - HUD transparent on top of it could increase draw calls

If none of that helps, if you can send me a repro case I should be able to work this out for you really really quickly. support at unikronsoftware dot com. If its some confidential project, you could simply blank out the textures or whatnot - I just need a tiny bit of info to work out whats going on.

unikron
Title: Re: 3.5, and the drawcall inflation effect.
Post by: n0mad on March 21, 2012, 10:29:29 am
Ok, here we go :

1. 7 drawcalls on one level, 5 on another (sampled at the exact same time, so nothing changed in the HUD)

2. only Vector3.one scaling (but I got some scripts which use such scaling on one gameObject hosting several sprites, is it ok ?)

3. tris : 174, verts : 348

4. oh crap, that's what I'm doing in 4 places .... how can this increase DCs ? isn't dynamic batching supposed to pack everything from one atlas, whatever Z overlap it has ?

edit : ok I checked this out, disabled all overlapping text, and drawcalls are displaying the expected number (3). So how are we supposed to use HUD text ? :/

edit 2 : correction, I'm not doing HUD - TEXT - HUD, but just HUD - TEXT, at 4 places.
Why does it happens with text, not with sprites ? (I have a lot of overlapping sprites btw).

edit 3 : something's really strange ... I made the same test again, under the exact same conditions (disabling everything but the hud), and now it displays 10 drawcalls... and on another run 12 drawcalls ... the only thing I changed was turning a static textSprite into a sprite (baked the text).
Title: Re: 3.5, and the drawcall inflation effect.
Post by: n0mad on March 21, 2012, 11:05:49 am
Another interesting test :

I have 2 x 2 overlapping sprites on a given place. If I put sprite1A and sprite 1B on the same Z, but sprite2A and sprite2B on another different same Z (0.1 instead of 0), it displays an overall 10 drawcalls.
Now from that situation, if I put sprite2A (or 2B) on the exact same Z than sprite1A (or 1B), and leave the other one on a 0.1 Z, it gives 11 drawcalls.

wtf ? There's clearly an internal problem on Unity's part here, isn't it ?
(reminder : all 4 sprites are belonging to the same atlas)

edit : made another very simple to repro case :
1) create 4 tk2dSprites, and 2 textMeshes
2) put 2 sprites (overlapping themselves) on the left of the screen, 2 on the right
3) put spriteLeft1 on Z = 0, spriteLeft2 on Z = -0.1. Same for spriteRight1 & 2
4) now put one textMesh on the left sprite pack, at Z = -0.1, same for the right
- it displays 2 drawcalls, as expected.

5) then put the left testMesh at Z = 0 (same Z as the underneath spriteLeft1, in fact).

- it displays 4 drawcalls.

edit 2 : I tried to reproduce the same scenario with FBX imported textured quads (same shader). Exact same scenario, exact same Z position tests, except here it's 2 different FBX with 2 different atlases (to emulate the tk2d sprite + textMesh different atlas).

Guess what ? I have the same drawcall rising in the exact same conditions. As long as I separate each sprite from a different Z pos, it batches correctly. But as soon as I put a sprite on the same Z level as another, drawcalls rise up.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: unikronsoftware on March 21, 2012, 11:46:11 am
Can you send me a test case to look at?
Title: Re: 3.5, and the drawcall inflation effect.
Post by: n0mad on March 21, 2012, 11:49:31 am
Ah, unfortunately I'm using FBX that contains a ton of NDA elements :/

But you can 100% reproduce that with the scenario above, may it be with tk2dSprites or just FBX imported textured quads.
edit : sorry, I forgot one precision in the repro case. I'm writing a clean one for the FBX method in 5 minutes.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: unikronsoftware on March 21, 2012, 11:59:38 am
I'll be looking at these over the weekend if thats OK with your timescale? I can shuffle things about if you need it looked at sooner.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: n0mad on March 21, 2012, 12:47:57 pm
Ok I wrote a very detailed repro case, with FBX this time (to highlight the fact that it's not tied to 2DToolkit).

Here it is : http://forum.unity3d.com/threads/123664-Lightmap-Directional-Light-Drawcalls-went-up-SOLVED?p=869108#post869108

I'll be looking at these over the weekend if thats OK with your timescale? I can shuffle things about if you need it looked at sooner.

Thank you for your dedication, really. But here I feel it's a Unity bug. The only tie with TK2D I can think of is that I'm using tk2dCamera, which is multiplying all corrdinates to huge numbers, and could cause the batching to fail (as it's mentionned that objects need to be "close", but close how ? visually close ? or coord ?).

I'm a bit upset by Unity huge lack of feedback on this drawcall 3.5 problem, I admit. The only move they made was to put a [SOLVED] in my thread title and link it to a problem with lights hitting lightmaps in 3.5 but not in 3.4. Or a bug with projectors in 3.5. But there were some other threads where the case was not involving projectors at all, or not having lightmaps at all, but still having higher drawcalls than in 3.4 ....

So well, I'll just try to wave hands and make some noise in the Unity forums, so that maybe we would at last have a glimpse of a bone from the staff.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: n0mad on March 21, 2012, 03:49:36 pm
Tried to add another TextMesh -> getting another additional drawcall  :'(

I'd like to know, what are the expected results with multiple text meshes (from the same font) ? When you tested tk2d, or even the games you're in which using it, are you following some particular guiderules to prevent from such random drawcall inflation ?
Title: Re: 3.5, and the drawcall inflation effect.
Post by: unikronsoftware on March 22, 2012, 10:47:58 am
Hi,

Sorry I missed your question earlier. With text meshes, they're a slightly special case, as the number of polygons in them determines if they can be merged at runtime or not. Each character in a text mesh draws 2 triangles, that multiplied by max chars determines how many polys are constantly drawn.

The unity draw call batching doc goes into detail of how many polys get batched. A quick test shows a textmesh will batch up to about 75 characters.

The main thing that breaks batching is overlap between text meshes and sprites or different fonts & textmeshes, etc. eg. If a textmesh is sandwiched between 2 sprites, and another one further away, that breaks batching. I've attached a screenshot illustrating this. What we usually do is keep all sprites in one layer of z, and all text meshes in another. This helps keep the drawcalls much more consistent.

This can be partly worked around by merging the font atlas with the sprite collection, and could potentially help reduce draw calls quite a bit, but only in this kind of special case, and when the sprites & font will actually fit on one texture.

One more thing you could do to help with this (and avoid accidental overlap), is to create a new camera specially for the HUDs and keep it isolated from the main scene. Use the depth parameter to get it to draw later. We tend to do this most of the time, as it helps organizing things - also you can turn different HUDs on and off by simply enabling and disabling cameras.

Hope that info helps, and let me know if that merging atlas thing would be useful - I'm happy to implement it but only if there is demand for it. We don't need it.

Cheers,
unikron
Title: Re: 3.5, and the drawcall inflation effect.
Post by: n0mad on March 22, 2012, 11:24:19 am
Hi,

great feedback as always.

Ok, after applying your advices, here are my scene analysis :
- no textmesh goes above 20 chars. Most are 4 chars max.
- no textmesh is sandwiched between 2 sprites. the only overlap is texmeshes over some sprites (inevitable background frame).
- I'm already creating a separate HUD camera of course :-) I'm also disabling several groups of HUD as long as they're not used. I'm also keeping things organized by using the Anchor system (very neat feature btw, I tried every possible resolution, it always fits, great job).

Actually, I would take anything that could reduce the drawcalls, as the HUD cannot be tweaked like a background complex gameObject, or a shader. Even on a 3G, the HUD is vital.
I made my font atlas to fit inside 256x26, so they could totally fit inside my HUD atlas. If you're 100% sure that merging text atlases inside sprite atlas can drastically reduce drawcalls, I'm totally in for such a solution :-)

p.s : the attached png is 0 kb.

p.s 2 : I attached a screenshot of the HUD
Title: Re: 3.5, and the drawcall inflation effect.
Post by: unikronsoftware on March 22, 2012, 11:45:09 am
I'll put that in the TODO for after the tilemap editor. I don't believe its that big a job.

ps. I dont know how I managed to delete the image before I clicked submit :(
Title: Re: 3.5, and the drawcall inflation effect.
Post by: n0mad on March 22, 2012, 11:47:48 am
I'll put that in the TODO for after the tilemap editor. I don't believe its that big a job.

ps. I dont know how I managed to delete the image before I clicked submit :(

Thanks, that's great news :)

Also,  I made another experience, disabling everything ingame except tk2dSprites. Drawcalls skyrocketted to 18 :o
Then I disabled and re-enabled some of these sprites, and drawcalls went to 4. As weird as it is, it would seem like overlapping causes total random batching results, but I made another test in this situation : still having nothing but tk2dSprites, except I separated all of them in order for not having a single overlap. Drawcalls stayed at 7. I don't understand ...
Title: Re: 3.5, and the drawcall inflation effect.
Post by: unikronsoftware on March 22, 2012, 12:09:40 pm
That is actually an issue specific to 3.5. It does weird stuff depending on selection in the editor, etc. Once its showing some ridiculous number, try saving and reloading.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: n0mad on March 22, 2012, 12:18:44 pm
Ok, so the whole drawcall behaviour is confirmed to be a Unity bug. Thanks.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: KyleStaves on April 06, 2012, 03:46:43 pm
Quote
The unity draw call batching doc goes into detail of how many polys get batched. A quick test shows a textmesh will batch up to about 75 characters.

This was massively helpful, thank you. I was running into a draw call nightmare (not really causing performance issues since I was only hovering about 14 - but it should have been closer to 3 so it was bothering me). My strings were all set with a max length well over the batchable limit - didn't realize the polycount was important there.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: fsadeq on August 02, 2012, 02:22:28 pm
Was this problem ever resolved? I too am having nightmare draw call inflations and I have no idea why. I'm abiding by all of the batching rules, so I can't understand why i have 2 materials and 30 draw calls (not even using any textmesh). All I have are several layers in the tilemap editor and that is it. Any reason why my draw call count would be so high? The only shaders I'm using are the built in 2D Toolkit ones SolidVertexColor and BlendVertexColor.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: Tochas on January 13, 2013, 11:23:34 pm
Hi,

I am not sure if the effect I am experiencing has something to do with this but here it goes

I have a prefab consisting on an Empty Game Object that has one AnimatedSprite and one Sprite as child
The animated sprite is my character with the set of animations and the "static" sprite is just a circular shadow therefore there is a overlap of the two.

The character has its own spriteCollection while the shadow is on another spriteCollection

the funny thing:
If I drag the prefab into the editor as many times as I want the drawcalls will remain steady about 8
If I create instances of the prefab by an ObjectPool object/script as soon as a character appears on the screen it adds 2 drawcalls giving an ever increasing number of drawcalls as long as the spawner stay active
If I remove the shadow sprite from my prefab and retry both previous test the drawcalls remain steady about 8

as far as this goes I can get to the conclusion to ask to my graphic artist to include the shadow with the character animations but I really want to understand why is this happening so I can design my prefabs in a more drawcall safe manner.

Thanks
Title: Re: 3.5, and the drawcall inflation effect.
Post by: unikronsoftware on January 14, 2013, 09:05:21 am
Was this problem ever resolved? I too am having nightmare draw call inflations and I have no idea why. I'm abiding by all of the batching rules, so I can't understand why i have 2 materials and 30 draw calls (not even using any textmesh). All I have are several layers in the tilemap editor and that is it. Any reason why my draw call count would be so high? The only shaders I'm using are the built in 2D Toolkit ones SolidVertexColor and BlendVertexColor.

Dunno how I missed this, but now that its been bumped I might as well answer.

Each layer in your tilemap is likely to end up as a drawcall, depending on the number of tiles used. Batching stops applying after a certain number of polygons, so if your tilemap partition mesh is over a certain size it isn't going to be batched, and there isn't any way around it apart from increasing partition size.

And talking about partition sizes - each partition is a set of draw calls, and when you're at a boundary, you are likely to see 4 of them at the same time. Say you have 5 layers which cant be batched - at a partition boundary, you could in theory go up to 20 draw calls if they don't batch.

This is quite inevitable, and the only way around it is to dynamically generate geometry every frame, but then that is likely to end up slower than the batch overhead. Also, draw call overhead isn't as bad as it used to be a couple generations ago on iOS devices...
Title: Re: 3.5, and the drawcall inflation effect.
Post by: unikronsoftware on January 14, 2013, 09:07:41 am
Hi,

I am not sure if the effect I am experiencing has something to do with this but here it goes

I have a prefab consisting on an Empty Game Object that has one AnimatedSprite and one Sprite as child
The animated sprite is my character with the set of animations and the "static" sprite is just a circular shadow therefore there is a overlap of the two.

The character has its own spriteCollection while the shadow is on another spriteCollection

the funny thing:
If I drag the prefab into the editor as many times as I want the drawcalls will remain steady about 8
If I create instances of the prefab by an ObjectPool object/script as soon as a character appears on the screen it adds 2 drawcalls giving an ever increasing number of drawcalls as long as the spawner stay active
If I remove the shadow sprite from my prefab and retry both previous test the drawcalls remain steady about 8

as far as this goes I can get to the conclusion to ask to my graphic artist to include the shadow with the character animations but I really want to understand why is this happening so I can design my prefabs in a more drawcall safe manner.

Thanks

It likely isn't the same issue at all. What happens in your ObjectPool script? I'd step through / look into the instances to make sure the material instances aren't being duplicated for whatever reason.
Title: Re: 3.5, and the drawcall inflation effect.
Post by: Tochas on January 15, 2013, 03:36:51 am
Hi Unikron,

I am using the GameObject.Instantiate() method, passing a stored prefab instance as argument. similar to http://forum.unity3d.com/threads/76851-Simple-Reusable-Object-Pool-Help-limit-your-instantiations! (http://forum.unity3d.com/threads/76851-Simple-Reusable-Object-Pool-Help-limit-your-instantiations!)

I will debug to check the reference value between the prefab and instantiated object materials.

On a previous post you mentioned that now draw calls are not a big concern on iOs development, do you have an estimate of how many drawcalls can be considered "ok"?

Thanks
Title: Re: 3.5, and the drawcall inflation effect.
Post by: unikronsoftware on January 15, 2013, 11:14:38 am
Its not that they aren't a big concern any more, but with increasing CPU speeds, they are not as bad as they used to be. There isn't a magic number you should be aiming for - you're balancing CPU utilization with the rest of your game, sound, etc. The acceptable draw call count depends very much on what else you're doing. I suggest profiling your app to see what the current utilization is like.