Batch Rendering

Hi All,

Im considering using Corona for my next project but wanted to check something first, I couldn't find a good sub-forum to put this in so I thought id turn it into a feature request of sorts.. ;)

Is there any form of batch rendering in Corona? For example if I have 50 sprites on screen all using the same texture/spritesheet is that 1 draw call or 50?

If there isn't, are there any plans to add it? Would it fall under the "Improve Sprite API" on the roadmap?

Thanks

Dell

For the less technically inclined here, he is referring to the low-level calls made to OpenGL. How exactly Corona makes draw calls to OpenGL can have a massive effect on performance.

I sure hope that is what Corona does, maybe an engineer from Ansca can tell us for sure. In the meantime, your question really just boils down to "can corona draw 50 identical sprites really fast?" In which case, you should do some performance tests. Downloading the free trial and then learning how to display a bunch of sprites is something you would want to do anyway in evaluating a game engine.

Also, take a look at this thread for a method to have huge tile maps:
http://developer.anscamobile.com/forum/2011/01/29/object-culling-render-process-when-not-content-area#comment-26658

Thanks for the reply jhocking, ive just done some quick tests but im not sure of the results so far..

For ease I modified the Fishies sample, got rid of the background and replaced the image with a 16x16 png to try and rule out fill rate.

On an iPod Touch 2G I get a fairly steady 30fps with 75 sprites, which is more than I would expect a 2G to be able to handle if that was 75 draw calls.

However if I for example up it to 300 sprites and test on a 3GS it manages <20fps, now 300 sprites is quite a lot, but if they were all drawn in 1 call I would expect a 3GS to be able to handle that quite comfortably..

EDIT:

Ive just setup a similar scene using cocos2d's batch node, im getting 60fps with 500 sprites on the 3GS, so perhaps they are individual calls in Corona? Or could the bottleneck be iterating through an lua array with that many objects?

just to check.. you are actually using the sprite.newSpriteSheet etc? commands?
http://developer.anscamobile.com/reference/index/sprite

i only ask because people might refer to a normal bitmap image loaded with display.newImage as a "sprite"

j

Ive tried both methods and see little if any difference between them, that would lead me to believe they are being treated the same, other than the fact that the spritesheet shares memory..

Those testing results you had seem to suggest that Corona does batch the draw calls but that there is some other bottleneck from how Corona is handling the instances. Would be helpful for an Ansca engineer to pipe up at this point.

Or could the bottleneck be iterating through an lua array with that many objects?

Wait, what is your code doing that you need to loop through an array? For a draw calls test I would expect that your code doesn't actually do anything with the objects other than just place them on the screen at startup. If the code is doing anything more (eg. moving the objects around) then you would expect that to be slower because Lua is slower than C, and that has nothing to do with draw calls. Please post your code.

My code is essentially the Fishies sample that comes with corona, perhaps the problem then is my understanding..which we may be getting to the edge of ;-) I assumed that the buffer would not be cleared if nothing on screen changed.. if it is the case that the the sprites are re-drawn every frame regardless of whether they move then there must be some batching after all, as I can get a fairly steady 30fps with 300 static sprites on the 2G Touch..

On the down side, if that is the case, does that mean Lua is not fast enough to handle an array of that size on a 3GS? Admittedly there are few if statements etc as well in that sample but nothing major..

I have the same question and am hoping someone from Ansca can chime in.

would the following = 1 draw call or 3?

1
2
3
local but1 = display.newImageRect( "sprites/buttonAclosed.png", 32, 32 )
local but2 = display.newImageRect( "sprites/buttonAclosed.png", 32, 32 )
local but3 = display.newImageRect( "sprites/buttonAclosed.png", 32, 32 )

Based on an old podcast I listened to that was a conversation with Carlos and Walter, they explicitly stated that calling an image multiple times, that reference the same image file, Corona will reuse the image bits and only load the image into memory once.

Info on the podcast here: http://mobileorchard.com/corona-easy-to-implement-high-performance-native-iphone-apps-written-in-lua/

Direct download here: http://podcast.mobileorchard.com/podcast/019-Corona.mp3

Earlier today I was playing with Fishies iPad and put 2000 fish swimming back and forth on the screen. On an iPad 2 I got 8 FPS. :) Cut the number of fish in half and I got about 16 FPS, cut it in half again --500 swimming fish -- and got 30 FPS.

I was hoping for more, but there may be many places where that code can be optimized -- it was probably written for clarity more than speed.

And just for the fun of it I "unrolled the loop" -- instead of doing the same chunk of code 500 times I put in 500 chunks of code. Each fish had it's own code. No speed up, but I didn't really expect any with that few iterations. :)

Jay

PS - You young whippersnappers have it easy. Back in the day we put graphics on the screen a pixel at a time, and while unrolling the loops expanded the size of your code, we could get noticeable speed increases from doing that.

Corona will reuse the image bits and only load the image into memory once.

Loading the image isn't what we're talking about; we're talking about how the code renders the image after it's been loaded. It's a subtle technical point that only people with low-level experience in OpenGL will understand, but you can draw multiple instances of the same image with a single draw call. OpenGL is optimized to handle lots of data in a single draw call faster than the same amount of data spread out over multiple draw calls.

This is one of the myriad reasons spritesheets are more efficient than separate images; if you have multiple sprites sharing a spritesheet then OpenGL will allow you to render all of those sprites with a single draw call. The question here is, does Corona do that?

I am well aware of that. But the question of a single draw call versus multiples in this case (the fishies) is implicit in the example.

According to the podcast, they are only loading the image once into memory, and reusing the OpenGL id of the bits, with the slight overhead of redrawing the fish (position, rotation, scale), a single draw call is to be expected.

Now, I guess the real question is "is" it actually making a single draw call, or is there something else going on in the code that "breaks" the batch?

I know in all the other engines I have used over the years, batching is very dependent on the requirements, to ensure a batch. If one little thing is wrong, the batch breaks.

Has anyone tested changing the Fishies example to actually load in a sprite sheet instead of the current display.newImage?

According to the podcast, they are only loading the image once into memory, and reusing the OpenGL id of the bits, with the slight overhead of redrawing the fish (position, rotation, scale), a single draw call is to be expected.

I still don't think you're getting it. Have you ever wrote anything in OpenGL? Not used rendering engines based on OpenGL, but actually made calls to OpenGL in your own code.

It is perfectly possible to use the same OpenGL id over and over in multiple draw calls. The code would look something like (warning: massively simplified pseudo-code)

1
2
3
4
5
tex = opengl.load("fish.png")
opengl.draw(poly1, tex)
opengl.draw(poly2, tex)
opengl.draw(poly3, tex)
opengl.draw(poly4, tex)

While I haven't written any OpenGL code myself, I do understand how it works, and my assumptions of a single draw call are based entirely on Carlos and Walters statements. That assumption may be completely wrong, but it is based on what they have said.

Without actually either hearing from Carlos, Walter or another Ansca engineer, or a method in Corona to get the number of draw calls, we are just speculating, based on our tests.

I wanted to find out how many draw calls were going on in my app, to verify that the sprite sheets were actually working as I expected, and was told there is no method to get the number of draw calls from Corona.

Do you have a method of getting the draw calls? Because that would be a good number to have, or see.

No I don't have any way of knowing that. That's why in my very first post in this thread I said "I sure hope that is what Corona does, maybe an engineer from Ansca can tell us for sure."

As for our speculations, I was simply disagreeing with you that the statement you quoted from that podcast has any relevance to draw calls.

No worries! I like discussions like this, because I learn by having to solidify my knowledge into words. Sometimes it proves me wrong and I like that. After 15 years making games, there is always something, on a basic level, for me to learn.

I would like an Ansca person to chime in on this as well.

What I really want is a call to be able to see how many draw calls there actually are.

If we told you, we'd have to eliminate you.

Now that's just not funny.

Why do Ansca staff like to reply super-funny (not) answers when we're expecting them to give us a valuable one? Is that all we get for being subscribers beside the game engine, "jokes" on a forum?

"If we told you, we'd have to eliminate you."

Responses like that might eliminate me as a customer, is that what you meant?

Seriously Dell's question should already be covered in the docs, we shouldn't need to ask basic questions like this in the forums. And certainly we shouldn't have to wait over a month for a response.

I was hoping for more, but there may be many places where that code can be optimized -- it was probably written for clarity more than speed.

The above statement is true.

While we do incremental performance increases, if you guys read my blog from April 14th, 2011 http://blog.anscamobile.com/2011/04/whoa-is-right-our-corona-sdk-gets-major-update/

One of the items that we are focusing on the next release is The next area of focus is graphic enhancements. Do I need to say more? We will focus from increasing our graphic pipeline performance, to adding shaders, to hard-core graphic features such built in curve-fitting all the way to raster and imaging enhancements. Photoshop anyone? UGHGH I get carried away sometimes… Oh behave !

Hope that answers your questions.

And seriously, guys, the funny statements, try answering forums, and support emails for a living, and you will see how much fun they are. I am notorious for it. They don't mean anything. It is the staff trying to vent on their long days. And in a startup, the days are 24/7/365 non-stop. But guess what? What other company you know off that the co-founders roll up their sleeve and take time to answer your forum post and try to monitor it on a daily basis to get a temperature reading on whats going on with their product. :-) It's all good. (See am venting ;-) Means no harm.

Carlos << yes one of the co-founder dweebs

views:2389 update:2011/9/18 10:09:28
corona forums © 2003-2011