Take a look at these "pit-occupiers" in Profiler

Original link: http://blog.uwa4d.com/archives/presentandsync.html

WaitForTargetFPS, Gfx.WaitForPresent and Graphics.PresentAndSync are the parameters we are often asked about. Presumably you who are reading this article have often encountered these excessive CPU overheads in Profiler. In this regard, let's talk about the specific meanings and trigger rules of these parameters today.


WaitForTargetFPS

This parameter generally appears when the CPU overhead is too low and the target frame rate is set (Application.targetFrameRate) . When the previous frame is lower than the target frame rate, a WaitForTargetFPS idle waiting time will be generated in this frame to maintain the target frame rate.

Analysis : This item is actually executed first in the main loop of the Unity engine, that is, the engine actually maintains the running FPS to the target value by supplementing WaitForTargetFPS in the current frame based on the CPU time consumption of the previous frame. For example, if the target frame rate is 30 frames per second, and the last frame took 15ms, then the WaitForTargetFPS in the current frame will be 18 (33-15)ms, but the other time in this frame is 28ms, then in Profiler this The total time-consuming of one frame becomes 46 (18+28) ms.

Therefore, the phenomenon of high profiler overhead caused by this value is actually a time-consuming "illusion", and you can "turn a blind eye" to it during the optimization process.

Gfx.WaitForPresent && Graphics.PresentAndSync

These two parameters often have high CPU usage in Profiler, and can only be seen in the release version. The reason is actually caused by the vertical synchronization (VSync) between the CPU and GPU. The reason why there are two parameters is mainly related to whether the project enables multi-threaded rendering . When multi-threaded rendering is enabled for the project, what you see is Gfx.WaitForPresent ; when multi-threaded rendering is not enabled for the project, what you see is Graphics.PresentAndSync .

Graphics.PresentAndSync  refers to the waiting time for the main thread to present and the waiting time for vertical synchronization. The literal meaning of Gfx.WaitForPresent is also the waiting time for Present, but a lot of content is actually omitted here. Its real meaning should be the time that the current main thread (MainThread) needs to wait in order to present in the rendering thread (Rendering Thread) . It still sounds like a mouthful, so let's explain it in detail.

When the project starts multi-threaded rendering, the engine will put Present and other related work on the rendering thread as much as possible, that is, the main thread only needs to call the rendering thread through instructions and let it perform Present, thereby reducing the pressure on the main thread. However, when the CPU wants to perform a Present operation, it needs to wait for the GPU to complete the last rendering. If the GPU rendering overhead is high, the CPU's Present operation will always be in a waiting operation, and the waiting time is the Gfx.WaitForPresent time of the current frame, as shown in the figure below.

UWA Tech Doc

Similarly, when the project does not enable multi-threaded rendering, the engine will perform Present in the main thread (most mobile games currently use this operation). Of course, the Present operation also needs to wait for the GPU to complete the last rendering. If the GPU rendering overhead is high, the CPU's Present operation will always be in a waiting operation, and the waiting time is the Graphics.PresentAndSync time of the current frame, as shown in the figure below.

UWA Tech Doc

We made a more extreme example to show this situation. On the Unity 5.3.3 version, create 60 full-screen UIPanels, enable and disable multi-threaded rendering respectively, and do not set TargetFPS. Then, the CPU overhead of this parameter on the Samsung S6 device is as follows:

When multithreaded rendering is enabled:

UWA Tech Doc

When multithreaded rendering is turned off:

UWA Tech Doc

So, if the CPU time consumption of Gfx.WaitForPresent or Graphics.PresentAndSync is very high in your project, it is not that they do some mysterious operations themselves, but that your current rendering task is too heavy and the GPU load is too high. Sincerely .

At the same time, for projects that enable vertical synchronization, Gfx.WaitForPresent and Graphics.PresentAndSync will also have high CPU usage. Before explaining this kind of problem, let's take "everyone takes the subway" as an example. Generally speaking, the time for the subway to reach each station is average and certain, assuming that a group of passengers is picked up every 10 minutes. But hardly many passengers can arrive on time. If you arrive two minutes early, you only need to wait two minutes to get on the subway. Minutes to take the subway.

We often encounter the above situation. In the rendering pipeline of the GPU, the working principle of converting the front buffer and back buffer is actually the same as "taking the subway". You can simply imagine the GPU pipeline as a subway train. For mobile devices, the frame rate of the GPU is generally 30 frames per second or 60 frames per second, that is, VSync "arrives once" every 33ms or every 16.6ms, and the Present of the CPU is "passengers take the subway", and then go to respective destinations. Similar to the early arrival and late arrival of passengers, the CPU Present will also have similar situations, such as:

The CPU-side overhead is very small. Present is executed very early, but at this time VSync has not yet arrived, and there will be a high waiting time, that is, the CPU overhead of Gfx.WaitForPresent and Graphics.PresentAndSync seems to be high. The figure below shows the CPU usage of Graphics.PresentAndSync on a Samsung S6 device in Unity 5.3.3 version, when an empty scene does not enable multi-threaded rendering and does not set TargetFPS.

UWA Tech Doc

The CPU-side overhead is high, so that the Present misses the VSync operation during execution. In this way, the Present will have to wait for the next VSync to arrive, resulting in high CPU overhead of Gfx.WaitForPresent and Graphics.PresentAndSync. This situation is especially prone to occur when excessive resources are loaded on the CPU side, such as WWW loading a large AssetBundle, Resource.Load loading a large number of Textures, and so on.

Through the above explanation, we hope that you have a deep understanding of Gfx.WaitForPresent and Graphics.PresentAndSync at this moment. No matter how much CPU is occupied by these two parameters, it is actually not a problem of these two parameters themselves, but caused by other parts of the project. In this regard, we will make a summary to facilitate your further impression.

There are three main reasons for the high CPU usage of these two parameters:

The CPU overhead is very low, so the CPU is waiting for the GPU to complete the rendering work or the arrival of VSync; the CPU
overhead is high, so that the Present misses the VSync of the current frame, that is, it has to wait for the next VSync to arrive;
the GPU overhead is high, and the CPU's Present needs to wait for the completion of a frame of rendering work on the GPU.

Finally, how to optimize and reduce the CPU usage of these two parameters? That is, ignore the two parameters Gfx.WaitForPresent and Graphics.PresentAndSync, optimize everything else you can optimize !

Do you have a feeling that you have been deceived for a long time, but luckily Yuhu-kun saved you~

Guess you like

Origin blog.csdn.net/lips264/article/details/89377556