Draw calls triple? Why?

Discussion and feedback on Construct 2

Post » Fri Feb 21, 2014 8:11 am

Having a strange thing happen, and have tested it in both chrome and firefox.

If I spawn, say, 1000 moving objects of one type, I can see in the debugger that my draw calls are using about 4.5 percent of my cpu.

However, if I clone that object so I have three identical copies, place them in a family, and spawn a 1000 of them, my draw calls go up to 15-17 percent (almost 3 times more...suspicious number...) :?

I'll post a capx if no one can explain this, because everything I've read so far on the forum and in the manual suggests this shouldn't be happening. For example, this thread:

viewtopic.php?t=71373&start=0

Salient extract from the man himself:

Ashley wrote:As far as C2 draw calls are concerned (when it asks a plugin to draw itself), it makes a single draw call for every single visible object on-screen, and that's it. Offscreen objects are not drawn, and objects set invisible are not drawn (although objects with opacity 0 are still drawn). It doesn't matter if objects use different or the same frames, are from different or the same object types, there is one draw call per visible instance.


??? :(
B
44
S
10
G
10
Posts: 1,106
Reputation: 9,187

Post » Fri Feb 21, 2014 1:43 pm

Clones are separate textures as far as C2 runtime is concerned, so it draws each of the three in their own context. Just my guess.
B
62
S
21
G
12
Posts: 1,910
Reputation: 13,170

Post » Fri Feb 21, 2014 5:38 pm

Mipey is right. A cloned object is treated as it's own image. It's unfortunate, but C2 handles image in regards to sprite associations poorly. So when you clone a Sprite it also clones the existence of the image.

Instead of clone it's best to use instances of a sprite like you had above.

As a design for C2 use your sprites as image objects and Families as your entity. That way you can use a sprite for more than thing...

Though i wish c2 was designed around image ctx and plugins/sprites... then use a reference to an image.

Oh well it's still a great tool over all.
B
90
S
18
G
9
Posts: 2,455
Reputation: 15,013

Post » Fri Feb 21, 2014 9:01 pm

@Mipey @jayderyu

I gathered that it's not reusing the images, but I don't understand why that triples the draw call. The total number of objects is the same, there are just three object types versus one. Not trying to argue, just understand. See again what Ashley says (relevant parts bolded):

Ashley wrote:As far as C2 draw calls are concerned (when it asks a plugin to draw itself), it makes a single draw call for every single visible object on-screen, and that's it. Offscreen objects are not drawn, and objects set invisible are not drawn (although objects with opacity 0 are still drawn). It doesn't matter if objects use different or the same frames, are from different or the same object types, there is one draw call per visible instance.


The reason I'm doing this is to try and divide up collision testing loads across multiple ticks. And it works -- for the collision testing logic. The extra draw call overhead just about cancels it out though. Very frustrating. Basically, with col checks having to be top level now, I can't figure out any other way of pre-filtering objects to test.

Essentially, there little advantage anymore to testing collisions less often than every tick, unless you have many different object types...in which case your draw calls go way up...
B
44
S
10
G
10
Posts: 1,106
Reputation: 9,187

Post » Fri Feb 21, 2014 9:11 pm

Because rendering performance cost isn't linear. Once you hit a certain point it's a sliding exponential.
B
90
S
18
G
9
Posts: 2,455
Reputation: 15,013

Post » Mon Feb 24, 2014 12:46 pm

Objects of different object types use different textures, even if they are identical. (Note image deduplication on export might actually make them use the same image, so this may only apply to preview mode).

If you have 1000 of one object type, the draw calls look like this:

1. Set texture
2. Draw 1000 objects

If you have 1000 of mixed object types using different textures, the draw calls look like this:

1. Set texture to object A
2. Draw 1 object
3. Set texture to object B
4. Draw 1 object
5. Set texture to object C
6. Draw 1 object
7. Set texture to object A
8. Draw 1 object... ad nauseum.

Just keep them all in one object type. There is no need to clone to improve performance, you can always identify separate sets of instances using instance variables instead.
Scirra Founder
B
387
S
229
G
87
Posts: 24,245
Reputation: 192,160

Post » Tue Feb 25, 2014 3:15 am

@Ashley

Thanks for the explanation; now it begins to make sense to me. :) Also explains why my performance seemed better on export. :?

I've already decided against the duplication approach; too awkward, too prone to errors. However, to clarify, using instance variables to identify a set of objects does not work for collision testing...at least, not in my tests (and not according to what I've read on collision cells). That's why I was attempting the duplication approach, ugly as it appeared.

However, I still managed to gain an appreciable improvment in performance by implenting a scheduling system. So now I have a global var that cycles thru three steps, and I distribute my operations amongst them to balance things out. Like:

step 1. check bullet cols

step 2. spawn bullets

step 3. check for offscreen bullets, destroy them.

1...2...3...1...2...3...etc... :arrow:

It's not a massive optimization, but it does seem to reduce jank when everything is running full tilt (intermittent demanding operations don't end up aligning on the same tick).

Cheers, T
B
44
S
10
G
10
Posts: 1,106
Reputation: 9,187

Post » Tue Feb 25, 2014 12:35 pm

Why doesn't using instance variables to identify sets of objects work? It ought to do the job just fine.
Scirra Founder
B
387
S
229
G
87
Posts: 24,245
Reputation: 192,160

Post » Wed Feb 26, 2014 1:18 am

@Ashley

It works fine...except for collisions. I was trying to break up my collisions over multiple ticks. At first I just assumed it wouldn't work, given what I read here (specifically, "Caveat 2: picking in events"):

https://www.scirra.com/blog/ashley/6/co ... on-in-r155

But I did end up trying it anyway...and it doesn't work. I have the capx somewhere, I'll post it when I find it.

Anyway, for what I'm working on now, I've come up with an alternate solution that's working fine.

Cheers, T
B
44
S
10
G
10
Posts: 1,106
Reputation: 9,187

Post » Wed Feb 26, 2014 1:42 am

@TiAm - here's an example of how to cycle through instances for reduced collision checks: http://www.amirai.net/forums/filtered_collisions.zip
Moderator
B
93
S
33
G
33
Posts: 3,006
Reputation: 27,719

Next

Return to Construct 2 General

Who is online

Users browsing this forum: No registered users and 2 guests