How can I save CPU effort in SceneKit rendering delegates? - macos

SceneKit calls its rendering delegates sixty times a second to allow a host application to adjust parameters in the contained scene to provide animation, physics, etc.
My scene is large (360,000 vertices). Almost all (~95%) of the scene is rotated slightly every minute (every 3,600 delegate calls). A very small remainder of the scene (about 300 nodes ~ 15,000 vertices) is moved once a second (every 60 delegate calls); all the nodes are created and their properties set before the application 'starts' (in viewDidLoad) and then only their positions are changed, as described above, in the delegate calls.
My frame refresh rate only just keeps at 60 fps and CPU usage is about 30% according to Xcode. All that effort is being expended in the rendering loop (there's no interaction; no other work) so I have two questions:
1) does 30% CPU seems reasonable, given this general description of my app? More specifically, since my delegate code seems simple and invoked from <2% of the rendering loops, could I really be driving SceneKit to its limits?
2) if so, are there any SceneKit tricks to clawing back some CPU? Can the delegate call rate be slowed, for example?
This is with macOS 10.12.3 and Xcode 8 (Swift 3) on a 2.8GHz/i7 2015 MacBook Pro

How about trying to flatten the nodes and it's children using flattenedClone.

Creating SCNLevelOfDetail objects for your geometries is worth a try.
Is anything else moving? Can you reduce your view's preferredFramesPerSecond?

Related

Performance issues when rendering first frame of ThreeJS app

I currently have a big impact on the performances of my ThreeJS app when I render the very first frame. It causes the Edge and IE 11 browsers to freeze for 5 seconds with a pop-up indicating "This window does not respond", which may scare my users.
Using the Performance profiler of Chrome, it seems the problem come from several ThreeJS functions you can clearly identify in the screenshot below.
WebGLUniforms.upload : 425ms (50.7% frame rendering time)
WebGLProgram.constructor : 327ms (38.9% frame rendering time)
How can I minimize the duration of the functions call ?
Can I create the program over multiple frames? Or upload the uniforms?
Does the number of materials on my 3D models impact these functions ?
I've tried to hide all the models in the scene and show them one at a time, it seems to prevent the freeze, but each model takes 500ms to show, which is not perfect for user experience. Maybe, it's the only way to go.
Thanks for your time
EDIT : The number of materials or their nature (WebGLStandardMaterial?) seems to affect the performances
Put add a few objects to the scene per frame over time. Three.js inits WebGL resources on first use so if there's 100 objects on your scene all 100 objects get initialized the first time you call renderer.render.
So, just put N objects to the scene, call renderer.render, then next frame add N more to the scene, etc until all the objects have been added.
It's probably most important to do it by material and geometry. In other words if you have 10 different materials and 10 different geometries and you're rendering 100 different models (a model takes one material and one geometry), then you want to make sure the first N models you add don't use all the materials and all the models because those are the things that need to get initialized.
Post processing passes also need initialization so if you're using any of those maybe the first frame just init those, then start adding objects.

Qt QGraphicsView application is always using 15% CPU.

I have a Qt application that is built around a QGraphicsView/Scene. The graphical performance is fine, animations are extremely smooth and a simple high res timer says the frames are drawing as fast as 400 fps. However, the application is always using 15% cpu according to task manager. I have run performance analysis on it in Visual Studio 2012 and it is showing that most of the samples are being taken in the QApplication::notify function.
I have set the viewport to render with a QGLWidget in hopes that offloading the drawing functions to the GPU would help, but that had no impact at all on CPU usage.
Is this normal? Is there something I can do to reduce CPU usage?
Well, there you have it - 400 FPS framerates. That loads one of your cores at 100%. There is a reason people usually cap framerates. The high framerates are putting a strain on the Qt event system which is driving the graphics.
Limit your frame rate to 60 FPS and problem solved.
I'm not updating the view unless an event occurs that updates an
individual graphicswidget
Do not update the scene for each and every scene element change. This is likely the cause of the overhead. You can make multiple scene item changes, but render the scene at a fixed rate.
Also, I notice you said graphicswidget - which I assume is QGraphicsWidget - this might be problematic too. QObject derived classes are a little on the heavy side, and the Qt event system comes with overheads too, which is the reason the regular QGraphicsItem is not QObject derived. If you use graphics widgets excessively, that might be a source of overhead, so see if you can get away with using the lighter QGraphicsItem class and some lighter mechanism to drive your scene.

glBufferData very slow with big textures (sprites sheets) in Cocos2d-x 3.3

I'm working with Cocos2d-x to port my PC game to Android.
For the sprites part, I wanted to optimize the rendering process so I decided to dynamically create sprites sheets that contain the frames for all the sprites.
Unfortunately, this makes the rendering process about 10-15 times slower than using small textures containing only the frames for the current sprite (on mobile device, on Windows everything runs smoothly).
I initially thought it could be related to the switching between the sheets (big textures like 4096*4096) when the rendering process would display one sprite from one sheet, then another from another sheet and so on... making a lot of switches between huge textures.
So I sorted the sprites before "putting" their frames in the sprites sheets, and I can confirm that the switches are now non-existent.
After a long investigation, profiling, tests etc... I finally found that one Open GL function takes all the time:
glBufferData(GL_ARRAY_BUFFER, sizeof(_quadVerts[0]) * _numberQuads * 4, _quadVerts, GL_DYNAMIC_DRAW);
Calling this function takes a long time (profiler says more than 20 ms per call) if I use the big texture, quite fast if I use small ones (about 2 ms).
I don't really know Open GL, I'm using it because Cocos2d-x uses it, and I'm not at ease to try to debug/optimize the engine because I really think they are far better than me for that :)
I might be misunderstanding something and I'm stuck on this since several days and I have no idea of what I can do now.
Any clues ?
Note: I'm talking about glBufferData but I have the same issue with glBindFramebuffer, very slow with big textures. I assume this is all the same topic.
Thanks
It is normally a costly call to do as glBufferData involves CPU to GPU transfer.
But the logic behind Renderer::drawBatchedQuads is to flush the quads that have been buffered in a temporary array. The more quads you have to render, the more data have to be transferred.
Since the quads properties (positions, texture, colors) are likely to change each frame, a CPU to GPU transfer is required every frame as hinted by the flag GL_DYNAMIC_DRAW.
According to specs:
GL_DYNAMIC_DRAW: The data store contents will be modified repeatedly and used many times as the source for GL drawing command.
There are possible alternatives to glBufferData such as glMapBuffer or glBufferSubData that could be used for comparison.

Update NSView frame every millisecond

I'm trying to update an NSView's frame at every millisecond. It work for some frame but it blocks very quickly.
How should I do to make smooth updates ?
The WindowServer will only ever update the screen at a maximum of 60FPS (Unless you turn that off with Quartz Debug, but in general, it will be limited to 60FPS, and it will never be 1000FPS). Attempting to force redraw any more frequently than that is a waste of effort. I would expect, under normal circumstances, that calling -setFrame: on an NSView will cause -setNeedsDisplay: to be called, which means that your view will be redrawn the next time the WindowServer draws a frame, so even if you're calling -setFrame: 1000 times a second, it's not going to be drawing your view 1000 times per second. If you're seeing stuttering, I would bet that what's actually happening is that your view is taking more than 1/60th of a second to redraw. It's hard to do any non-trivial raster drawing (i.e. the kind you would be doing in -[NSView drawRect:]) in <1/60th of a second.
If you're trying to simply move the view (and you don't need to redraw it) you might try calling -setFrameOrigin and using Layer-backed views. I would expect AppKit/CoreAnimation to be able to re-position a layer-backed view (without re-rasterizing it) in <1/60th of a second (with ease).
If you want something more complex that simply re-positioning a view, and you want it to happen at the max frame rate (again, 60FPS) you are likely going to want to look into using OpenGL.
But really, the take home message here is "don't try to do stuff 1000 times per second." When the Leap Motion delegate method is called, update your view's position, and let the WindowServer do the rest at its own pace.

Is it better to count n ticks or run two seperate timers

I'm making a snake game and on every tick the snake moves. because the snake is moving a whole unit on each tick the animation is jumpy. The game is on an invisable grid so the snake can only change directions at specific points.
Would it be considered better practice to have a timer that will move the snake a pixels at a time counting it with a variable, and on every n tick run the code to change direction. Or is it better to have two separate timers; one for move the snake a pixel at a time and another for changing the snakes direction?
Essentially, you're creating a "game-loop" to update the displayList (in Actionscript) and re-draw your view. When the game gets complex, Timers and listening for ENTER_FRAME events will be constrained to the flashplayer settings for screen refresh (i.e. it's FPS) and the CPU's rendering based on what it is tasked to process.
For frame-rate independent animation, you should probably use a combination of ENTER_FRAME to track milliseconds and GetTimer() calls to more accurately (to the millisecond) call animations and normalize the experience across a variety of platforms.
Basically, listen for the ENTER_FRAME event, check the current milliseconds since the last update and if it exceeds your refresh-rate (in terms of milli's), fire off the animation/state update: check for snake collision detection with a "direction-block" - handle if true, then update the snake's movement / position / state.
Flash updates the Display List at whatever it's settings, and CPU / machine-dependent issues are. The key, I've found, is to make sure you're normalizing the speed of updates to make the experience consistent. Timer's have their usage, but can cause memory performance issues. ENTER_FRAME is synced to the main timeline / frame-rate settings.
For a dated, but interesting discussion 3 years ago, check out this post from actionscript.org.

Resources