Search Unity

Android Multithreaded Rendering and Graphics Jobs settings collision

Discussion in 'General Graphics' started by a-dolbilov, Jun 4, 2019.

  1. a-dolbilov

    a-dolbilov

    Joined:
    Jun 4, 2013
    Posts:
    6
    Hi everybody!

    We are trying to improve performance on our Android project and like many other developers have lots of CPU time spent in Camera.Render. To figure out how we can improve performance just with Player Settings we have created simple test which issues 1000 unbatched draw calls and track Camera.Render time in Main Thread using Unity Profiler->CPU Usage->Timeline. All tests are made on Samsung Galaxy S8. Unity version: 2019.1.4f.

    Settings we tested:
    - Graphics APIs: Vulkan, OpenGLES 3.0, OpenGLES 2.0
    - Target Architectures: ARMv7, ARM64
    - Multithreaded Rendering
    - Graphics Jobs

    Interesting facts:
    - OpenGLES 3.0 and OpenGLES 2.0 shows nearly equal results, so no need to provide separate info for them.
    - Vulkan is about 20% faster then OpenGLES.
    - Multithreaded rendering is about 1.5-2 times faster both for Vulkan and OpenGLES.
    - (!!!!!!!) ARM64 is about 2.5 times faster than ARMv7 but doesn't used by default (!!!!!!!!)

    The most interesting part of this test is Vulkan:
    - Multithreaded Rendering (true), Graphics Jobs (true): 20.1 ms
    - Multithreaded Rendering (true), Graphics Jobs (false): 20.1 ms
    - Multithreaded Rendering (false), Graphics Jobs (true): 2.7 ms (!!!!!!!!!)
    - Multithreaded Rendering (false), Graphics Jobs (false): 32.8 ms

    It looks like Graphics Jobs are working only in case of Multithreaded Rendering is disabled. And this is the point of Player Settings collision. For Vulkan we want to disable Multithreaded Rendering, but we want to enable Multithreaded Rendering for OpenGLES. Also, there is no ability to enable/disable Multithreaded Rendering in run-time. The only thing we can do is prepare separate apk's, but it's really inconvenient...

    My suggestion is to change Unity logic on selecting rendering path. The optimal way is to use Graphics Jobs even if Multithreaded Rendering is enabled. Other solution to this problem is to provide API which can change Multithreaded Rendering option during run-time.

    Do you have any ideas how to solve this problem now or in the near future?
     
    Peter77 likes this.
  2. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    191
    When using Vulkan these two modes should be different.
    You can verify by looking at what the Worker threads are doing in the profiler's timeline.
    When both Graphics Jobs and Multithreaded Rendering are enabled Vulkan API calls are made from Render Thread, Worker Threads and Vulkan Submission Thread.
    With just Multithreaded Rendering enabled there should be no Vulkan Submission Thread and Vulkan API calls should only happen from Render Thread.

    Unity 2019.3 introduces an Android specific solution that allows you to change Graphics APIs and threading modes very early during startup using standard Unity command line arguments. It's still not very convenient because you will have to write custom Java code to do that, but it's a solution.
     
  3. a-dolbilov

    a-dolbilov

    Joined:
    Jun 4, 2013
    Posts:
    6
    Thanks for reply Florian!

    I have found Vulkan Submission Thread in Graphics Jobs enabled version, but Camera.Render time is the same in the Main Thread for both cases (Graphics Jobs: true, false).

    My primary concern is Main Thread time. Of course we can try to move some heavy gameplay logic to Jobs, but that's not really easy task for such a huge project as ours. So we have selected the easiest possible way of optimization.

    This is the case Multithreaded Rendering (true), Graphics Jobs (true): 20.1 ms
    mt_true_gj_true.png


    This is the case Multithreaded Rendering (false), Graphics Jobs (true): 3.33 ms
    mt_false_gj_true.png

    As you can see in second case Main Thread have much less to do in Camera.Render. As far as I understand GfxDeviceVK.SyncSubmissions just waiting and doesn't affect the resulting performance. Also we can see a lot of activity in Job->Worker0-4, which means the rendering is really shifted to Graphics Jobs.

    But when Multithreaded Rendering is enabled things become much worse... That is why I am talking about incorrect implementation.

    BTW: Thanks for the hope about Unity 2019.3 solution, but we have only 3 months before worldwide release and Unity 2019.3 will not be stable enough to use it...
     
    Prodigga and Peter77 like this.
  4. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    191
    Your first screenshot looks like a bug in Unity for Android/Vulkan with GraphicsJobs + Multithreaded Rendering. I'll look into it.
     
    richardkettlewell and Peter77 like this.
  5. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    191
    GfxDeviceVK.SyncSubmissions does affect overall frame time. In GfxDeviceVK.SyncSubmissions we wait until previous frame's GraphicsJobs are done (i.e. submitted to the GPU).
    But you could use that time on the main thread for something else such as executing script code.
     
  6. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    191
    Fix for this will be in Unity 2019.3.0a7
     
  7. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    780
    Hi @a-dolbilov I was wondering if you ever ran your benchmarks again to test 2019.3.0a7 or greater now that the fixes are in?
     
    Jes28 likes this.
  8. a-dolbilov

    a-dolbilov

    Joined:
    Jun 4, 2013
    Posts:
    6
    Hi @Prodigga, sorry for huge delay. I confirm that Vulkan+Multithreaded Rendering+Graphics Jobs works as expected in Unity 2019.3.0b4.