Frame Rate issue Apple SpriteKit - ios

I'm currently making an app for an assessment which generates a maze using Recursive Backtracking. It's a 25x25 grid maze, with each wall being a separate SKSpriteNode (I read up that using SKShapeNodes was not efficient).
However, there are about 1300 nodes in the scene, which is causing some frame rate issues, even on my iPhone X. It's currently idling at about 15-30 fps, which really isn't ideal.
Are there any ideas on how to either cache SKSpriteNodes to produce better performance? I'm probably overlooking many things, and not creating walls in the most efficient way but the frames seem way too low to be correct?
If anyone would be able to suggest or nudge me in the right location that would be a huge help.

I highly recommend using SKTextures for repeated, identical images. See Creating a Textured Sprite Node.
For optimal performance, create sprites before compile time and put them in a texture atlas in your asset catalog. For creating texture atlases, see the documentation for SKTextureAtlas.

Related

SpriteKit - minimize quadcount

I've been trying to teach myself SpriteKit and jumped into Raywenderlich's tutorials which said that QuadCount should be minimized for a better performance. I turned on showQuadCount, showDrawCount, showNodeCount for debugging. However, I saw quadcount is always equals to node count. Anyone can help me explain in a simple way what quadcount really is and give me an example on that quadcount is different from nodecount. (I did search google but I can not understand, so please do not give me a link without explaination). Thanks so much.
Every node that draws something draws a quad (two triangles).
So only SKNode nodes which don't draw anything will not increase the quad count.
Also, quad count nearly isn't everything. It's more important to support Sprite Kit's internal batching by using texture atlases, and avoiding child nodes that use different texture atlas than their parent, otherwise this would interrupt batching.

cocos2d flicker

I have a pool of CCSprites numbering 1200 in each of two arrays, displayGrid1 and displayGrid2. I turn them visible or invisible when showing walls or floors. Floors have a number of different textures and are not z-order dependent. Walls also have several textures and are z-order dependent.
I am getting about 6-7 frames when moving which is okay because its a turn based isometric rogue-like. However, I am also getting a small amount of flicker, which I think is performance related, because there is no flicker on the simulator.
I would like to improve performance. I am considering using an array CCSpriteBatchNodes for the floor which is not z-order dependent but am concerned with the cost of adding and removing sprites frequently between the elements of this array, which would be necessary I think.
Can anyone please advise as to how I can improve performance?
As mentioned in the comments, you're using multiple small sprite files loaded individually which can cause performance issues as there is wasted memory being used to store excess pixel data around each of the individual sprites. Each row of pixel data in an OpenGL texture must have a number of bytes totaling a power of 2 for performance reasons. Although I believe OpenGL ES under iOS does this automatically, it can come with a big performance hit. Grouping sprites together into a single texture that is correctly sized can be a tremendous boon to rendering performance.
You can use an App like Zwoptex to group all these smaller sprite files into a larger, more manageable sprite sheets/texture atlas and utilize one CCSpriteBatchNode for each sprite sheet/texture atlas.
Cocos2D has pretty good support for utilizing sprite sheets with texture atlases and converting your code to using these instead of individual files can be done with little effort. Creating individual sprites from a texture atlas is easy, you just call the sprite by name instead of from the file.
CCSpriteBatchNodes group OpenGL calls for their sprites together, a process known as batching, which causes the operating system and OpenGL to have to make less round trips to the GPU which greatly improves performance. Unfortunately, CCSpriteBatchNodes are limited to only being able to draw sprites for the texture that backs them (enter sprite sheets/texture atlases).

Is Direct3D feasible for zoom and pan of large images?

I want to make an image viewer for large images (up to 2000 x 8000 pixels) with very responsive zooming and panning, say 30 FPS or more. One option I came up with is to create a 3D scene with the image as a sort of fixed billboard, then move the camera forward/back to zoom and up/down/left/right to pan.
That basic idea seems reasonable to me, but I don't have experience with 3D graphics. Is there some fundamental thing I'm missing that will make my idea difficult or impossible? What might cause problems or be challenging to implement well? What part of this design will limit the maximum image size? Any guesses as to what framerate I might achieve?
I also welcome any guidance or suggestions on how to approach this task for someone brand new to Direct3D.
That seems pretty doable to me, 30 fps even seems quite low, you can certainly achieve a solid 60 (minimum)
One image at 8k*2k resolution is about 100 megs of VRAM (with mipmaps), so with today's graphics cards it's not much of an issue, you'll of course face challenges if you need to load several at the same time.
DirectX 11 supports 16k*16k size textures, so for maximum size you should be sorted.
If you want to just show your image flat your should not even need any 3d transformations, 2d scaling/translations will do just fine.

Cocos2d: GPU having to process the non visible CCSprite quads

Given one texture sheet is it better to have one or multiple CCSpriteBatchNodes? Or does this not affect at all the GPU computational cost in processing the non visible CCSprite quads?
I am thinking about performance and referring to this question and answer I got. Basically it suggests that I should use more than one CCSpriteBatchNode even if I have only one file. I don't understand if the sentence "Too many batched sprites still affects performance negatively even if they are not visible or outside the screen" is applicable also having two CCSpriteBatchNode instead of one. In other words, does the sentence refer to this "The GPU is responsible for cancelling draws of quads that are not visible due to being entirely outside the screen. It still needs to process those quads."? And if so it should meant that it doesn't really matter how may CCSpriteBatchNode instances I have using the same texture sheet, right?
How can I optimize this? I mean, how can I avoid the GPU having to process the non visible quads?
Would you be able to answer to at least the questions in bold?
First case: Too many nodes (or sprites) in the scene and many of them are out of screen/visible area. In this case for each sprite, GPU has to check if its outside the visible area or not. Too many sprite-nodes means too much load on GPU.
Adding more CCSpriteBatchNode should not effect the performance. Because the sprite-sheet bitmap is loaded to the GPU memory, and an array of coordinates is kept by the application for drawing individual sprites. So if you put 2 images in 2 different CCSpriteBatchNodes or 2 images in 1, it will be same for both CPU and GPU.
How to optimize?
The best way would be to remove the invisible nodes/sprites from the parent. But it depends on your application.
FPS drops certainly because of two reasons:
fillrate - when a lot of sprites overlap each others (and additionally if we render high-res texture into small sprite)
redundant state changes - in this case the heaviest are shader and texture switches
You can render sprites outside of screen in single batch and this doesn't drop performance singnificantly. Pay attention that rendering sprite with zero opacity (or transparent texture) takes the same time as non-transparent sprite.
First of all, this really sounds like a case of premature optimization. Do a test with the number of sprites you expect to be on screen, and some added, others removed. Do you get 60 fps on the oldest supported device? If yes, good, no need to optimize. If no, tweak the code design to see what actually makes a difference.
I mean, how can I avoid the GPU having to process the non visible quads?
You can't, unless you're going to rewrite how cocos2d handles drawing of sprites/batched sprites.
it doesn't really matter how may CCSpriteBatchNode instances I have using the same texture sheet, right?
Each additional sprite batch node adds a draw call. Given how many sprites they can batch into a single draw call, the benefit far outweighs the drawbacks. Whether you have one, two or three sprite batch nodes makes absolutely no difference.

What is the fastest drawing method on iOS?

I'm developing a 2D game on iOS, but I'm finding it difficult getting drawing to run fast (60 FPS on Retina display).
I've first used UIKit for drawing, which is of course not suitable for a game. I coulnd't draw a couple of sprites without slowdown.
Then I moved on to OpenGL, because I read it's the closest I can get to the GPU (which I think it means it's the fastest possible). I was using glDrawArrays(). When I ran it on the Simulator, FPS dropped when I was reaching over 200 triangles. People said it was because the Simulator or the computer are not optimized to run iOS OpenGL. Then I tested it on a real device, and to my surprise, the performance difference was really small. It still couldn't run that few triangles smoothly - and I know other games on iOS use a lot more polygons, shaders, 3D graphics, etc.
When I ran it through Instruments to check OpenGL performance, it told me I could speed it up by using VBOs. So I rewrote my code to use VBO instead, updating all vertices each frame. Performance increased very little, and I still can't surpass 200 triangles at consistent 60 FPS. And that is 2D drawing alone without context changes/transformations. I also didn't write the game yet - there are no objects making no CPU-intensive tasks.
Everyone I ask says OpenGL is top performance. What could I possibly be doing wrong? I am assuming OpenGL can handle LOTS of polygons that are updated each frame - is that right? Which method other games use that I see they run fine, like Infinity Blade which is 3D, or even Angry Birds which has lots of ever-updating sprites? What is recommended when making a game?
OpenGL is definitely going to be your fastest option. Even on the oldest iOS devices you can run about 20,000 polygons at 30+ fps.
Sounds like you must be doing something wrong or extra. It is impossible to try to guess what that might be without seeing your source code.
Generally speaking though, you want to make sure you create your VBO and all your loading outside of your drawing pipeline.

Resources