Draw calls triple? Why?

  • 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:

    Salient extract from the man himself:

    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.

    ???

  • 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.

  • 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.

  • 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):

    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...

  • Because rendering performance cost isn't linear. Once you hit a certain point it's a sliding exponential.

  • 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.

  • Ashley

    Thanks for the explanation; now it begins to make sense to me.

    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...

    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

  • Why doesn't using instance variables to identify sets of objects work? It ought to do the job just fine.

  • 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

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • TiAm - here's an example of how to cycle through instances for reduced collision checks: http://www.amirai.net/forums/filtered_collisions.zip

  • Arima I thought we were meant to put the collision conditions at the top to ensure we take advantage of the new speed increases...

  • AnD4D , With Arima's .capx, the collision check is getting called every 1 second, so I think the "Put collisions at top" thing wouldn't apply there as it's doing a collision check for 1 tick every second (whilst if you wanted to constantly detect whether something is overlapping or not, then collision cells would lessen the load for having 60 collision checks per tick)

  • AnD4D - not all games and situations benefit from collision cells. For some situations this method is better.

    @Jase00 - it's checking once per second to make the effect obvious - I didn't mean that people should only check for collisions once per second.

  • Arima

    Thanks for the capx example. It's an approach I never thought of, and may come in handy in the future.

    However, in my case collision cell opts were working fine; I was simply attempting to gain an additional advantage by only testing cols ever 3-4 ticks.

    I was hoping to break the tests up by only testing 1/3 of the objects per tick, thus cutting the cpu load to third/quarter without cramming all the col testing on a single, intermittent tick (ie, every 0.1 seconds or the like).

    However, it seems that, at this point in time, there's no real way to do that and retain the advantage of collision cells. Perhaps it's not even possible.

    As I said before, I've moved past this for my game, but it would be nice to see this ability in the future.

  • TiAm - here's an example of how to cycle through instances for reduced collision checks: http://www.amirai.net/forums/filtered_collisions.zip

    Any chance this is still around somewhere? I'd like to have a look <img src="{SMILIES_PATH}/icon_e_biggrin.gif" alt=":D" title="Very Happy">

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)