iPhone and Vertex Buffer Objects - iphone

I've just started playing around with opengl es on the iphone the past couple of weeks and i'm looking at refactoring some of my code to use Vertex Buffer Objects(VBO). Before I do though I would like to make sure it'll be worth it. The problem is that afaik the only reason you create VBO's is to shift a chunk of data onto the graphics card so that it doesn't need to be retrieved from system ram when it's used. The iPhone however does not have any dedicated ram that I'm aware of so i'm struggling to see why I would benefit at all from using VBO's. I have seen talk around the internet with conflicting opinions and apple certainly want dev's to use it so there's probably still a reason to use them but just wanted to see if anyone on SO had an opinion to add.

I saw no performance improvement on an iPhone 3G. I moved a bunch of stuff to VBOs, but eventually backed it out as it made it more difficult for me to pursue other performance gains. It's not the quick 25% performance increase that I was hoping for.
I've read somewhere that it can make a difference on the newer hardware (3GS), but I don't have references to back that up.

It depends. (sorry).
Rob didn't see an improvement for his setup, but here is an interesting post that did see a large improvement.

The main reason to existence of VBO's is the presence of static data on 3D models. The first bottleneck you encounter is the slowness of copying data to video memory (by using the unavailable glBegin/glEnd block or glVertexPointer, glBufferData and friends).
Let's imagine the old "flying toaster" screensaver. All toasts are static (changing only the position) - why waste resources copying them every frame from CPU's memory to GPU's? Copy it once with buffers and draw it with a single command. And, depending on how you do animations, even the animated toasters can be described in a static fashion.
My first 2D game I started without VBOs. When I changed to VBOs, no difference (like Rob). But, when I refactored to use more static buffers, FPS gone from 20 to 40. Since my goal was to reach 30, I was satisfied. I had some ideas to refactor even more, leaving everything static, but I don't have time now (game is on review, next one to come).

Related

I think I abuse of Ressources.load

Ok so I'm a bit confused about Ressources.Load. I actually use it quite a lot and everyone seems to see this feature as pure evilness. In this documentation, it's even written "Don't use it". I searched a lot about this and found this post. It mostly says to use Ressources.Load only for rare assets, otherwise, performance could/will be harmed.
I can see why this could be a "bad" thing to use, but honestly, I don't know how not to use this in my situation.
Lets say I have a game with ~10 different races with couples of units per race. The user chose it's race and start the game. At this point, it seems normal to me to Ressource.Load only the assets related to this specific race, and not the other ones...
Also, let's say you have a combat scene, with many possible environments (ie: winter, forest, desert, etc.). Again, I wouldn't want to load anything else than the one I'm fighting on. So using Ressources.Load seems the perfect tool. No? Am I missing something important about Unity or what?
Thanks a lot
It's true that Unity loads everything it see that is connected to things in the inspector in the scene. You have no way to stop Unity's loading once you are in the scene. (You can unload later, but it already took the toll of loading them all) The performance harmed in Unity's term seems to mean while playing, because if you connect them to the scene it loads everything from start and plays smooth from then but if you do a dynamic load you risk in lagging while playing.
Don't use it.
This strong recommendation is made for several reasons:
Use of the Resources folder makes fine-grained memory management more
difficult.
It's difficult but not impossible. If you are careful on your own, then you can reap the reward that is lower memory consumption.
Improper use of Resources folders will increase application
startup time and the length of builds. As the number of Resources
folders increases, management of the Assets within those folders
becomes very difficult.
It can't be help because offsetting with the load time you can save at scene start, the increased startup time is probably worth it. Most player won't mind the startup time in my opinion.
The Resources system degrades a project's
ability to deliver custom content to specific platforms and eliminates
the possibility of incremental content upgrades. AssetBundle Variants
are Unity's primary tool for adjusting content on a per-device basis.
Then you only put things that works universally in the Resources folder.
A modern alternate way is to compose your game in scene and use LoadSceneMode.Additive to get what you want one by one. It is suitable for big chunks like combat scene, but for lazy loading of something small in concept (but potentially contains large data like textures) like characters I would still use Resources.Load. The only thing that has delayed load build in is AudioClip which you can deselect preload audio data.
I wrote a detailed load process and its memory consumption here if you are interested in reading.
https://gametorrahod.com/unity-texture-memory-loading-unloading-7054819e4ae8

Is there a way to get a heapshot from Unity3d?

I want to debug which part that consume most of mono memory in Unity because what I saw from profiler is only a chunk said "Mono" something like that and do not know what it is.
I have already done the texture observe in Unity profiler and I do not have a problem with it. (I stated that I used it and saw only mono chunk with high memory) The problem is there must be some kind of memory leak not memory spike because if I play the game long enough, my Galaxy Grand Duo will crash with black texture which is memory used too much. If I saw it in the profiler, it said ManagedHeap and Mono Domain only with large chunk of memory after play the game multiple times.
More information about which platform you are developing for, which tools you are already using, and the reason you are profiling your memory to begin with would be helpful. Without that information I can only suggest the following ...
1) Unity Memory Profiler
I would recommend starting with the memory profiling tools included with the Unity3D editor. You can find out more about these tools here: http://docs.unity3d.com/Manual/ProfilerMemory.html
It sounds like you are already doing this since you have narrowed it down the the "Mono" item from the profiler. This is good, you now know that it is one of your scripts that is consuming the memory.
Make sure you are using the Advanced View. The advanced view of the Unity Profiler will give you more information about which scripts are utilizing your memory.
2) Textures
When it comes to Unity and memory I always start with the textures. It seems like every time I do something with dynamic loading or modifying of textures I end up creating a memory leak. Take a look at your scripts, particularly any that load textures, and try temporarily disabling this logic. Does it help your memory issue?
3) Observe and Optimize
If you aren't able to locate any scripts that seem like they could be causing an issue, I would try observing your game and locating the point where you see your memory spike. Try to identify what logic is running at this point in time. Disable individual scripts and run your scene again. Did this reduce the memory usage? Repeat this process until you locate the script or scripts responsible for your spike. Once you find these scripts you can try re-factoring them until you get the results you are looking for.

Grabbing data from XML document on a fairly regular basis on mobile, is it ok for performance?

A game I"m working on has several XML files it uses to manage sprite animations. Currently when I create an instance of a sprite I load it up into an XDocument once and keep it in a cache so that if I need to load it again I can just grab what is arlready in memory.
I do this very often in-game as I create animated sprites and such, going through its definitions like so:
var definitions = doc.Document.Descendants(name);
foreach (var animationDefinition in definitions)
So my question is, is this acceptable on a mobile phone? Say iPhone 3GS/iPhone 4/Windows Phone 7/Android? I use MonoTouch in ANdroid and iPhone while WP7 has its own .Net running.
The reason I ask is currently I don't load that many animated sprites up but as I do more and more I'm worried it will start hurting performance. I figure it might be best to change my design ideas now than wait to suffer at a later date.
Thanks for any help!
I would simply test what's faster (reading it again an again using a SAXParser or storing it in Memory using DOM).
Maybe it also makes sense to save the read data from your XML-File in something like an Array/Vector/Class so you don't need to parse the XML File over and over again.
Well in essentially what you are trying to ask is how many is "too many". I would suggest to find a "practical" limit considering performance, you just need to recursively increase the number of sprites and notice when the application slows down. Keep a safety factor of say 1.5 to 3. And there you know. Again you need to consider how many sprites do you have in all to begin with. If all can possibly be kept in memory respect all other specifications, then go for it. Customer's won't mind a slightly longer loading time for games, as long as it is smooth inside. Else just test stuff out.

Advice on using sandbox vs. caching for UITableView async image download

Apple just released some sample code on lazy loading images in a UITableView a week ago. I checked it out and implemented it into my own UITableView (which is a drawRect one for fast scrolling), to see if there was a difference from what I was already doing.
After implementing I am not sure what is best; the new code or what I already had. I am not seeing much of a speed improvement on my 3GS.
"Sandbox" method: Load images lazily, then save to local tmp folder in the sandbox. Each time the cell is displayed it looks for whether an image with that filename is already located in the sandbox folder. If it is, it retrieves the image and displays it, if not it continues with the download, saves it locally and then displays it. The benefit with this is that the images won't be blank the second time you open the app. They will already be downloaded and ready for displaying.
Caching method: This also loads the images lazily, however, now I include a UIImage on each object in the array that's displayed in the tableview. Instead of saving the image locally, I now download the image and put it into the array for the object. Now, instead of checking for the filename every single time, it jut check whether the UIImage != nil and uses the cached image (or downloads if nil).
A small difference is also that the caching code resizes the image before caching it to the exact size of what is displayed in the cell, whereas the image used in the sandbox code example is actually a bit larger than what it needs to display, which means it has to resize on the fly when scrolling as well. I read months ago that this could be a bit expensive to do, and I am also not sure whether it makes much of a difference in terms of then using a cached image instead of the sandbox-stored image and therefore more CPU intensive anyway (compared to what you save from caching with the caching code above).
I guess my question would be whether I should even bother with the caching code? Again, the new code won't immediately load images on a new launch, whereas the old code actually does because it's already in the sandbox. Since I am not reusing images, I have a lot of images to load (from the sandbox or cache) so I am not noticing a huge difference in speed. In fact, on my 3GS it's almost impossible to tell, in my opinion. The scrolling is not silky smooth, and I assume this is due to the large amount of images that I cannot reuse (different image for each cell). I am also wondering whether the sandbox method would get slower once there's 1000+ images in the folder, for example, eventually having it look through many more images than just 100 or so.
I hope I am making sense. I wanted to be pretty thorough with the details, and I am happy to give more details if needed.
Thanks!
If you have code that already works, and there's not a pressing problem, then don't change it.
If your scrolling actually is too slow, then perhaps you could use a mixture of ideas, and try to get the UIImage, and if it's not there, load it from the sandbox, and if it's not there, then download it.
The only good way to tell if there is any discernible difference in performance is to use profiling tools like Instruments (for measuring things like display framerate for the two techniques) or Shark (to determine hotspots in your code). There could be small differences in your exact implementation that could potentially cause significant differences between any general answer we could give and the actual performance you see in your application.
The thing that primarily concerns me with the "sandbox" method is not performance but disk space usage. Users won't appreciate you filling up their iPhone or iPod Touch with unnecessary files, especially if all the images aren't consistently used or if the set of used images changes often. Without knowing more about your application its impossible to guess how often these cached images would be loaded.
If you're testing locally on your own device, you might be on Wifi network. My recommendation would be to turn Wifi off for part of your testing to see how the two approaches perform when you have to fetch all the images over the cellular network. I would also recommend trying to find an older device (iPhone 3G or worse) because the 3GS does in fact hide potential performance issues that could be annoying for users on older devices.
I have personally used the LazyTableImages technique in my apps many times (provided it hasn't changed drastically between WWDC09 and the recent 'release') and find it to be just what I need. Caching images on disk wouldn't be an option in my case, however, and you shouldn't take my anecdote too strongly into account - profile your own code and use the results it shows.
Edit: The obvious answer is that accessing an in-memory cache is going to be faster than accessing the filesystem, but of course the final word on that is left up to profiling. If the images are already in memory, they don't need to be read from flash and parsed by UIImage. The traditional tradeoff comes into play here though - in-memory caching vs. disk space.
While it may be faster for you to store your images in-memory, you need to be very sure that you correctly handle memory warnings in your application (as you should be doing anyway!). Otherwise long period of use will lead to many, many images in your in-memory cache and trigger memory warnings and if your application is not built to handle these, at best your application will be killed by the OS due to lack of memory resources.
There are pros and cons in both approaches that you present - I suggest using elements of both in your app.
It's better to keep your images in memory and save them later (perhaps when your app quits). If you have a lot of images, it might be faster to use Core Data to save them, than as regular files.
It's also better to avoid doing any resizing on the fly, i.e. in your tableView:cellForRowAtIndexPath: or tableView:willDisplayCell:forRowAtIndexPath: methods or in any method that has to do with drawing your cells' content view. If you can, ask the image provider (content management?) to supply images at the size that your table view displays.

Best approach to debugging applicationDidReceiveMemoryWarning on iPhone?

Need advice on how to debug this. I'm new with limited environments and have no previous embedded or smart phone programming experience so I could use some clues.
Already aware of:
Instruments, Clanger Static Analysis, manual code review, etc. Instruments seems to be very helpful in general but quite time consuming and freezes up a lot of the time! Clanger has also helped me a lot as well. It seems like I'm just consuming too much memory in general and I'm wondering what a good strategy is. Do I release some top-level objects? Is there a 'preferred strategy'?
Just wondering if anyone has tackled this successfully and if they have any other suggestions? Thanks all.
There are a lot of good articles for memory management in an iPhone app. Here are some useful links.
http://iosdevelopertips.com/objective-c/memory-management.html
http://kosmaczewski.net/2009/01/28/10-iphone-memory-management-tips/
https://cocoa-touch.blogspot.com/2008/09/memory-management-on-iphone.html
Things you should in general take care of
Release any variables which you do not need
Always handle didReceiveMemoryWarning and release any variables not in use
Stop any memory-heavy processes in applicationDidReceiveMemoryWarning like audio/video playing, UIImagePickerController etc
EDIT
This does not apply any more. imageNamed: had caching issues prior to 3.x OS versions. The issue does not exist any more and you should use imageNamed: (makes implementing retina display easier)
Do NOT use imageNamed: to create UIImage objects.
Basically you're receiving this warning because (unsurprisingly) the iPhone is dangerously low on memory. This can generally be for one of two reasons;
You have a memory leak.
You are allocating far too many objects and need to revisit your design.
For the first one you should run instruments and examine your memory allocations. This can really slow down your app (and requires additional memory) so try testing areas of your app one at a time. E.g. if you have multiple views switch between them a couple of times.
For the second you will have to examine things you are doing that could result in large memory allocations. For example if you're writing a Flickr browser you might need to cut down the number of images you have loaded at anyone time, or free up some unused ones when you receive this warning.
These are about the only general rules I can suggest without knowing more about your app.
Unfortunately there's no real way (that I know of) to get figures for current memory allocation from the iPhone OS. This makes it really difficult to isolate the areas of your application that are inadvertently memory hungry.