I am trying to understand how the the recently announced "GPU over draw" feature works. Why are certain parts of the screen drawn twice or thrice? How does this really work? Does this have anything to do with nesting of layouts? How to minimize this over draw. In windows phone we have an option like Bitmapcachemode which will cache the redraw and prevent re drawing over and over again. Is there anything similar to this in Android? (The snippet below is from official Google docs)
With the latest version of glass, developers have an option of
turning on GPU over draw.When you turn this setting on, the system
will color in each pixel on the screen depending on how many times it
was drawn in the last paint cycle. This setting helps you debug
performance issues with deeply nested layouts or complex paint logic.
Pixels drawn in their original color were only drawn once.
Pixels shaded in blue were drawn twice.
Pixels shaded in green were drawn three times.
Pixels shaded in light red were drawn four times.
Pixels shaded in dark red were drawn five or more times.
Source - Google official docs.
The GPU overdraw feature is simply a debugging tool for visualizing overdraw. Excessive overdraw can cause poor drawing/animation performance as it eats up time on the UI thread.
This feature has been present in Android for some time, Glass simply exposed a menu option to turn it on. See the "Visualizing overdraw" section of http://www.curious-creature.org/docs/android-performance-case-study-1.html for more information.
Overdraw is not necessarily caused by nested layouts. Overdraw occurs when you have views over other views that draw to the same region of the screen. For instance, it is common to set a background on your activity, but then have a full screen view that also has a background. In this instance, you are drawing every pixel on the screen at least 2 times. To fix this specific issue, you can remove the background on the activity since it is never visible due to the child view.
Currently Android does not have the ability to automatically detect and prevent overdraw, so it is on the developer to account for this in their implementation.
Related
I am developing an image viewer where graphics are rendered with antialiased mode. Images can be first edited using Autocad that generates DXF files.
The application is written by using Visual C++ and Direct2D.
Although I am able to load the image quite quickly, zoom and especially pan remain a problem for me if compared with the performance of Autocad for the same image (same number of shapes).
Following is the piece of code aimed to render graphics:
auto shapes = quadTree.get_visible_shapes();
shapes.sort_by_Zorder();
for each shape in shapes:
shape.draw();
After profiling I can say that more than the 90% of the computational time is spent in the loop aimed to draw the shapes.
Drawing only the visible shapes, thanks to the implementation of the Quadtree, has been a huge performance improvement; I also render the graphics in aliased mode while panning, but there is still a big difference with Autocad.
I am wondering if Autocad draws a bitmap representation of the image, even if I didn't try this approach yet so I cannot tell if there could be an effective improvement in speed.
Considering these hypothesis are there any ways to improve the action of pan and zoom?
In AutoCAD, there is a mechanism called Adaptive degradation which abort rendering when the FPS falls below a predefined value:
And there is also a lot of optimization. You can not compete with a big program like this.
There are few considerations when doing pan on 2D/3D scene, especially when redraw-world is expensive.
Off-screen canvas
Render your screen onto an off screen bitmap with slightly larger canvas (e.g. w+N * h+N), upon PAN you instantly put up the screen, and update the off-screen one in background. There are also many ways to further optimize on this direction.
EDIT: More details:
For example, the screen of your scene is 640x480, the scene itself is 1000x1000, you want to show the region (301, 301) ~ (940, 780). You would instead create an off-screen buffer with, say, 740x580 (ie. N=50) from (251,251) ~ (990, 830). so, if the PAN operation move less than 50 pixel, (e.g. PAN left 5 pixels) you already have such content to instantly render to screen.
Also, after PAN you may want to prepare the new off-screen buffer in background (or when idle) so that subsequent PAN can be performed instantly.
In case of PAN too far, you still have to wait for it, or reduce the quality of rendering for intermediate screens, and render full details only when PAN stopped - user won't notice details when moving anyway.
Limit update frequency
PAN operation is usually triggered by mouse (or gesture touch) which may comes at high volume of events. Instead of queue all the 20 mouse move events within that one second and spend 3 seconds redraw the world 20 times, you should limit the update frequency.
I'm trying to do a little game in 2D to learn how to do it and improve my programming skills. I programme the game using C++/C and OpenGL 3.0 with GLUT.
I so confused with some important concepts about animations and scenario refresh.
It's a good practice load all the textures only when the level begins ?
I choose a fps rate to 40 fps, should i redraw all the scenario and the agents in every frame or only the modifications ?
In an agent animation should i redraw all the entire agent or only the parts which changes from the past ?
If some part of the scene changes (one wall or something similar is destroyed) should i need to redraw all the entire scene or only the part which changes ?
Now my "game" works with a framerate of 40fps but the game has a flickering effect that looks really weird.
Yes, creating and deleting textures/buffers every frame is a huge waste.
It's almost always cheaper to just redraw the entire scene. GPUs are built to do this, it's very fast.
Reading the framebuffer from VRAM back to regular RAM and calculating the difference is going to be much slower, especially since OpenGL doesn't keep track of your "objects", it just takes a triangle at a time, rasterizes it, then forgets about it.
Depends on how you define the animation. If you're talking about sprite-like animation, where each frame is a separate image, then it's cheapest to just refer to the new texture and redraw.
If you've got a texture atlas, update the texture coordinates and redraw, and if you're using shaders (you pretty much have to if you want to be OpenGL 3.0), you might be able to get away with a uniform that offsets texture coordinates.
Yeah, as I said before, the hardware is built to clear the screen and redraw everything.
And for a framerate, you should be using the monitor's refresh rate to avoid vertical tearing. Pretty much all monitors now are 60Hz, so 60fps is the most common "target" framerate.
Choose either 30 or 60 fps as most modern monitors refresh in 60 Hz rate. So you have either 2 or 1 rendered frame per "monitor frame". This should reduce flickering effects. (I'm not 100% sure if you mean this with "flash effect".)
Regarding all other questions (which sound pretty much the same): In OpenGL rendering, redrawing everything is pretty common, as in most games almost the entire screen changes in every frame, for example if you're moving around. You could do a partial screen update, but it's very uncommon and more expensive on the CPU side, as you have to compute which parts to draw instead of just "draw everything".
Yes
2-4. Yes - Hopefully this help you understand why you must...
Imagine you have 2 pieces of paper. The first paper you draw a stick man standing still, and show that to somebody.
The second paper while the user is looking at that paper you draw the same thing again but this time you move the arm a little bit.
Now you show them the second paper, as they look at the second paper you clear the first paper and draw the man moving his arm a little bit more.
This is pretty much how it works and is the reason you must always render the whole image regardless if nothing has changed.
I'm building a cocos2d game where I use two background sprites, actually one is a sprite, the other one is a CCMask that is used to make holes into the other background, but the performance problem is the same even when using 2 regular background sprites on top of each other.
When I use one background sprite, my FPS is around 60 all the time, when I use two background sprites the FPS drops to 30 every time. I've googled around, tried different solutions including reading sprites from a sprite frame cash instead of from a file, unfortunately the result is the same.
I just can't figure out why this is happening. Does any one here have any idea why this is happening and how to get around it?
On older devices (1st & 2nd generation, ie iPhone 3G) this can easily happen since they have terrible fillrates.
If possible try to SpriteBatch the two background images. You need to add both to a texture atlas, for example with TexturePacker. Sprite batching is particularly effective if the sprites are large.
Also, just in case: don't test performance in the Simulator. Simulator performance has no relation to actual device performance whatsoever.
Is there anyone who can explain how hardware cursor works precisely? How does it relate to the graphics I'm drawing on the screen? I'm using OpenGL to draw, how does hardware cursor relate to OpenGL graphics?
EDIT: For those who may be interested in this in the future I just implemented what is needed to show the cursor with the hardware. The implementation was in the kernel and to use it simple ioctl's were sufficient. Works perfectly.
Hardware Cursor means, that the GPU provides to draw a (small) overlay picture over the screen framebuffer, which position can be changed by two registers (or so) on the GPU. So moving around the pointer doesn't require to redraw the portions of the framebuffer that were previously obstructed.
Relation to OpenGL: None!
The hardware cursor is not rendered or supported by OpenGL. Some small piece of hardware overlays it on whatever image is going out the display connector - it's inserted directly into the bitstream at scan-out of each frame. Because of that, it can be moved around by changing a pair of hardware registers containing its coordinates. In the old days, these were called sprites and various numbers of them were supported on different systems.
Hardware cursors have less latency, and thus provide a better experience, because they are not tied to your game or engine frame rate but to the screen refresh rate.
Software cursors, rendered by you as a screen-space sprite during your render loop, however, must run at the rate of your game engine. Thus, if your game experiences lag or otherwise drops below target fps, the cursor latency will get worse. A minor drop in game fps is usually acceptable, but a minor drop in cursor latency is very noticeable as a "sluggish cursor".
You can test this easily by rendering a software cursor while leaving the hardware cursor on. (FYI, in Windows API the hw cursor function is ShowCursor). You'll find that the software cursor trails behind the hardware cursor.
I plan on making a game (in SDL) where, if one character moves, the part of the image it was on turns alpha, thus allowing me to place a scrolling image underneath the original scene.
1) Is this possible?
2) If yes to #1, how can I go about implementing this (not to give me code, but to guide me in the right direction).
It sounds like you want to learn about image compositing.
A typical game these days will have a redraw function somewhere to redraw the entire screen. The entire scene is always redrawn each frame.
void redraw()
{
drawBackground();
drawCharacters();
drawHUD();
swapBuffers();
}
This is as simple as it gets: by using the right blending modes, each time you draw something it appears on top of what was drawn before. Older games are much more complicated because they don't redraw the entire screen at a time (or don't use a framebuffer), and newer games are much more complicated because they draw the world front-to-back and back-to-front in multiple passes for different types of objects.
SDL has software image compositing functions which you can use, or you can use OpenGL (which may use a combination of software and hardware). I personally use OpenGL because it is more powerful (lets you draw more complicated scenes), but the SDL compositing functions are easier to use. There are many excellent tutorials and many more mediocre or terrible tutorials online.
I'm not sure what you mean when you say "the part of the image it was on turns alpha". The alpha channel does not appear on screen, you cannot see it, it just affects how two images are composited.