Data resource issues
The CPU controls the rendering process. It provides new data, such as transforms and light positions for every frame. GPU processing is asynchronous. This means data resources may be referenced by a queued command, and sit in the command stream for some time. OpenGL ES needs rendering to reflect the state of the resources at the time the draw call was made, so resources can’t be modified until the GPU workload referencing them completes.
Attempting to modify a resource that’s still referenced will usually trigger the creation of a new copy of that resource. This will avoid stalling the pipeline, but it creates significant CPU overhead. In effect, we need to make a new memory allocation, then copy data to populate the parts which were not replaced. This is often referred to as resource ghosting.
Streamline lets you pinpoint instances of high CPU load. Where this is being caused by resource ghost creation, you might see high-time inside the graphics driver
libGLES_Mali.so, in the Call Paths or Functions views.
There are two ways to resolve this problem:
- The application creates multiple buffers (or textures) and uses them in a round-robin fashion. The aim here is to have enough buffers in the rotation that all pending references have dropped by the time they are reused in a later frame.
GL_MAP_UNSYNCHRONIZED. You can then build the rotation using subregions inside a single buffer. This avoids the need for multiple buffers, however, you will need to manage the subregion dependencies in application logic. Avoid specifying the
MAP_INVALIDATEflag. Arm is a unified memory architecture, so the flag can be safely omitted. In fact on some older Mali driver releases, specifying
INVALIDATEwould override the unsynchronized behavior and re-trigger ghosting.