I'm having a performance issue regarding Apple Spritekit Framework.
I use the method preloadTextureAtlases:withCompletionHandler: of SKTextureAtlas to make sure all my textures are loaded before the game really starts.
Yet when the first texture of this atlas (whatever it is) is added to the scene as a child I got a small lag, like if the texture wasn't loaded. It only happens the first time.
I tried real hard to debug this and to find the reason but I couldn't find it. Looking with Instrument and the Time Profiler I got this
Which seems strange since my texture atlas contains all the allocated textures (and they are still allocated). Why does it call a load method ? Maybe it's something related to OpenGL like the texture binding.
I'm sure this correspond to the frame where my object is allocated (see the spike on the right). Nothing else is allocated or in motion here.
I'm really stuck on this and any help would be deeply appreciated.
Thanks for your time.
Related
I've been trying to find out for the last 2 days why even after I tell cocos2d to remove textureatlas
it keeps holding memory.
I have no leeks on intruments, I'm debbuging inside CCTextureCache class and it removes just time
I've tried all the obvious ways to remove texture atlas from cache ex: [[CCDirector sharedDirector] purgeCachedData]; with no success
I'm very hopeless, any help?
Edit:
I'm having the same problem than this guy LINK , my game has 1 texture atlas for each level and I repeat the player sprites each image texture atlas files which works great.
my idea was having about up to 30 levels in the game, where it would cost disk space and Assuming I was able to free the memory from the previous texture atlas belonging to the previous level, it would work just fine.
but because I can't find a way to free the memory, the game consumes lots of memory in the 5th level.... it is very frustrating.
any tips are appreciated, thanks
Edit:
I found out what is going on, I have some animations that executed a selector at the end of it. I can't remove those selectors, or if I do, I will have to work a lot. I'm pretty upset because the removeallselectors method just doesnt work
For memory reasons I decided to not use texture atlas anymore, I want to load few sprites from file when I use them.
using batchnode, there was a very handy method which is reorderChild that automatically set sprites to front or back depending the axis they are
Is there any feature like that for free sprites? I'm not asking for the algorithm to do that.. just confirming if there is nothing similar to reorderChild out there before get my hands dirty.
Yes, I searched a lot before coming here,
thanks all
I need a help or an advice with SprikeKit. My app/game passed Apple review, but later I got some complaints regarding graphics (big red X). I am using spriteNodeWithImageNamed for loading pictures. Is it any way to find out if the picture was loaded? I'm sure that the picture does exist. Probably, the problem is related to a memory or something else. If I put the wrong picture name in Xcode I see error output and red x but how can I catch the error - #try/#catch does not help in this case. Any inputs, hints are very appreciated.
xcode 5, iPad air
Are you trying to load any very large textures? The max texture size for different models of iDevices vary - perhaps that's what you're running into. If you try to load a texture that's too large for a particular device, it might fall back to that X graphic.
As far as detecting whether the texture didn't load, I don't know a way to do that, but you might be able to ensure that it loads by using SKTexture's preloadWithCompletionHandler: method to make sure it's loaded.
Also, Apple recommends not loading textures on the fly, especially if you're loading many of them in a short time span, and carefully managing texture memory by discarding SKTextures that you no longer need. Do some preloading, and check that you're not keeping textures around that you don't need, and see if the X icons go away.
To clarify, I know that a texture atlas improves performance when using multiple distinct images. But I'm interested in how things are done when you are not doing this.
I tried doing some frame-by-frame animation manually in custom OpenGL where each frame I bind a new texture and draw it on the same point sprite. It works, but it is very slow compared to the UIImageView ability to abstract the same. I load all the textures up front, but the rebinding is done each frame. By comparison, UIImageView accepts the individual images, not a texture atlas, so I'd imagine it is doing similarly.
These are 76 images loaded individually, not as a texture atlas, and each is about 200px square. In OpenGL, I suspect the bottleneck is the requirement to rebind a texture at every frame. But how is UIImageView doing this as I'd expect a similar bottleneck?? Is UIImageView somehow creating an atlas behind the scenes so no rebinding of textures is necessary? Since UIKit ultimately has OpenGL running beneath it, I'm curious how this must be working.
If there is a more efficient means to animate multiple textures, rather than swapping out different bound textures each frame in OpenGL, I'd like to know, as it might hint at what Apple is doing in their framework.
If I did in fact get a new frame for each of 60 frames in a second, then it would take about 1.25 seconds to animate through my 76 frames. Indeed I get that with UIImageView, but the OpenGL is taking about 3 - 4 seconds.
I would say your bottleneck is somewhere else. The openGL is more then capable doing an animation the way you are doing. Since all the textures are loaded and you just bind another one each frame there is no loading time or anything else. Consider for a comparison I have an application that can in runtime generate or delete textures and can at some point have a great amount of textures loaded on the GPU, I have to bind all those textures every frame (not 1 every frame), using all from depth buffer, stencil, multiple FBOs, heavy user input, about 5 threads bottlenecked into 1 to process all the GL code and I have no trouble with the FPS at all.
Since you are working with the iOS I suggest you run some profilers to see what code is responsible for the overhead. And if for some reason your time profiler will tell you that the line with glBindTexture is taking too long I would still say that the problem is somewhere else.
So to answer your question, it is normal and great that UIImageView does its work so smoothly and there should be no problem achieving same performance with openGL. THOUGH, there are a few things to consider at this point. How can you say that image view does not skip images, you might be setting a pointer to a different image 60 times per second but the image view might just ask itself 30 times per second to redraw and when it does just uses a current image assigned to it. On the other hand with your GL code you are forcing the application to do the redraw 60FPS regardless to if it is capable of doing so.
Taking all into consideration, there is a thing called display link that apple developers created for you. I believe it is meant for exactly what you want to do. The display link will tell you how much time has elapsed between frames and by that key you should ask yourself what texture to bind rather then trying to force them all in a time frame that might be too short.
And another thing, I have seen that if you try to present render buffer at 100 FPS on most iOS devices (might be all), you will only get 60 FPS as the method to present render buffer will pause your thread if it has been called in less then 1/60s. That being said it is rather impossible do display anything at all at 60 FPS on iOS devices and everything running 30+ FPS is considered good.
"not as a texture atlas" is the sentence that is a red flag for me.
USing a texture atlas is a good thing....the texture is loaded into memory once and then you just move the rectangle position to play the animation. It's fast because its already all in memory. Any operation which involves constantly loading and reloading new image frames is going to be slower than that.
You'd have to post source code to get any more exact an answer than that.
I'm developing an iPad app that uses large textures in OpenGL ES. When the scene first loads I get a large black artifact on the ceiling for a few frames, as seen in the picture below. It's as if higher levels of the mipmap have not yet been filled in. On subsequent frames, the ceiling displays correctly.
This problem only began showing up when I started using mipmapping. One possible explanation is that the glGenerateMipmap() call does its work asynchronously, spawning some mipmap creation worker (in a separate process, or perhaps in the GPU) and returning.
Is this possible, or am I barking up the wrong tree?
Within a single context, all operations will appear to execute strictly in order. However, in your most recent reply, you mentioned using a second thread. To do that, you must have created a second shared context: it is always illegal to re-enter an OpenGL context. If already using a shared context, there are still some synchronization rules you must follow, documented at http://developer.apple.com/library/ios/ipad/#DOCUMENTATION/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithOpenGLESContexts/WorkingwithOpenGLESContexts.html
It should be synchronous; OpenGL does not in itself have any real concept of threading (excepting the implicit asynchronous dialogue between CPU and GPU).
A good way to diagnose would be to switch to GL_LINEAR_MIPMAP_LINEAR. If it's genuinely a problem with lower resolution mip maps not arriving until later then you'll see the troublesome areas on the ceiling blend into one another rather than the current black-or-correct effect.
A second guess, based on the output, would be some sort of depth buffer clearing issue.
I followed #Tommy's suggestion and switched to GL_LINEAR_MIPMAP_LINEAR. Now the black-or-correct effect changed to a fade between correct and black.
I guess that although we all know that OpenGL is a pipeline (and therefore asynchronous unless you are retrieving state or explicity synchronizing), we tend to forget it. I certainly did in this case, where I was not drawing, but loading and setting up textures.
Once I confirmed the nature of the problem, I added a glFinish() after loading all my textures, and the problem went away. (Btw, my draw loop is in the foreground and my texture loading loop - because it is so time consuming and would impair interactivity - is in the background. Also, since this may vary between platforms, I'm using iOS5 on an iPad 2)