By Kshitiz Gupta
18 May 2012
In this article, I will gradually pen any interesting observations that I come across with stage3D which will help actionscript developers gauge a better insight as to what happens behind the scenes.
For the folks who are unaware of stage3d, Stage3D is a new model of rendering developed by Adobe which provides a set of low level GPU accelerated APIs advanced 2D and 3D capabilities across multiple screens and devices (desktop, mobile, and TV) through the runtimes. These APIs provide advanced 2D and 3D developers with the flexibility to leverage GPU hardware acceleration. Refer: http://www.adobe.com/devnet/flashplayer/stage3d.html for more details.
1) Calls synchronous or asynchronous
One question that would perplex stage3d code writers would be as to how do calls stack up. This may assist them in understanding why certain calls take longer than other. Almost all calls in Stage3D are asynchronous. Anything in stage3d is passed as a request to the gpu which gpu then takes up on its leisure and processes them as it feels like. Following are the exceptions and are calls that are synchronous in nature
i) present() or clear(): If gpu is not done with the previous batch of calls then either of these calls will wait synchronously for the gpu to finish what it was doing previously.
ii) Uploads done to gpu memory behave synchronously. CPU is a participant in the transfer and hence this call behaves synchronously. Minimizing uploads is a key thing in a memory constrained mobile environment. Avoid having a situation where you are uploading, drawing, uploading again and again. Upload everything to the gpu once at the beginning of the application and then draw.
iii) DrawtoBitmapData is again one call that requires a conversation between the cpu and gpu. This call again is synchronous.
As a general rule of thumb do not try to time gpu calls as the amount of data being drawn and time to draw that data is something that does not vary linearly. Some calls are blocking and the time that it takes for you to get the control back could actually be because of a host of earlier calls.
2) Multiple draw calls vs one draw call
Another simple query would be if one should draw everything in one drawTriangles call or use multiple drawTriangles call to draw the same content and the answer is what you would expect. Use one draw with large amount of content. GPUs love parallelism and providing more data allows them to work on a lot of data asynchronously.
3) Importance of enableErrorChecking
Context3D.enableErrorChecking is very important during your development cycles.
For example, something that may not happen regularly. Let say that your code set a texture at a certain register using the Context3D.setTexture call but you never sample it in your fragment shader. Such a texture, since it has been set, cannot be gc by the runtime even if there are no more references to it. If you would have set enableErrorChecking to true, you would get a runtime error and would have come to know about the issue. In case you have set enableErrorChecking to false the draw call would silently die.
If enableErrorChecking is true, then every stage3d call (on desktops) is synchronous. So definitely you would not want to publish content with this set to true.