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:
    17
    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?
     
  2. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    479
    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.
     
    futurlab_xbox likes this.
  3. a-dolbilov

    a-dolbilov

    Joined:
    Jun 4, 2013
    Posts:
    17
    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...
     
  4. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    479
    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:
    479
    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:
    479
    Fix for this will be in Unity 2019.3.0a7
     
    senkal_, Prodigga, JesOb and 2 others like this.
  7. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    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?
     
    JesOb likes this.
  8. a-dolbilov

    a-dolbilov

    Joined:
    Jun 4, 2013
    Posts:
    17
    Hi @Prodigga, sorry for huge delay. I confirm that Vulkan+Multithreaded Rendering+Graphics Jobs works as expected in Unity 2019.3.0b4.
     
    CubeGameStudio and Prodigga like this.
  9. Masahiro_Kono

    Masahiro_Kono

    Joined:
    Apr 12, 2019
    Posts:
    1
    From which version is the modification applied in Unity 2018?
     
  10. Kobald-Klaus

    Kobald-Klaus

    Joined:
    Jun 20, 2014
    Posts:
    127
    is there a way to switch to vulkan or opengl after a query to a server has been made? my problem is, that only a few devices seem to have problems with vulkan. but vulkan renders more beautiful. so I want to turn vulkan off only for some devices on request.
     
  11. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    479
    We don't support switching Graphics APIs at runtime.
    You add a non-Unity Activity and handle the server communication there.
    Another option could be to default to OpenGL ES 3.x, download something from Unity C# and then only apply the new settings on next launch.
     
    bartkoko likes this.
  12. Kobald-Klaus

    Kobald-Klaus

    Joined:
    Jun 20, 2014
    Posts:
    127
    I thought about that, but how can I patch the apk or change the "activity"? I have no real idea how android is working.
    Anyhow: I will post more details in a new post on this vkCreateImageView exception. I am currently testing on all available firebase > testlab devices and there seems to be consistent errors on the same devices all the time.
    I don´t think that my code is causing that problem since it is happening before anything is loaded.
     
  13. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    479
    You can have multiple activities in your AndroidManifest.xml and also specify which one runs on startup.
    The Java code for that additional activity can also be in your Unity project (https://docs.unity3d.com/Manual/AndroidJavaSourcePlugins.html).
    Your custom startup activity would then download your device specific config and switch to the main Unity activity to apply the config and start the game.
     
  14. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Could Unity with all its resources compile a list of devices that perform better with one than the other ? In our tests the difference is stark. Either Vulkan is a little better or same as OpenGL, OR it is incredibly worse. I would love to be able to select a "pick best for device" option.

    As a simple example: OnePlus 5 vs OnePlus 6T.

    https://m.gsmarena.com/compare.php3?idPhone1=8647&idPhone2=9350

    My friends OnePlus 5 performs decently with OpenGL but sees improvement with Vulkan. The improvement was significant enough that I would pick it over OpenGL. (I can't recall exact numbers but do remember it was a noticeable difference)

    Then on my OnePlus6T, great performance in OpenGL compared to One Plus 5. Expected. 6T is newer and it's hardware is more powerful compared to OP5. Then we tried Vulkan and it ran worse than OP5. No improvement. A complete degradation in performance. A newer device running slower than its predecessor.

    So what do we do? Stick with OpenGL, miss out on performance boost for OP5. There are hundreds of devices out there, who knows which device performance better/worse with one or the other?

    Recently ran some tests on Firebase TestLabs. All tests in OpenGL because we've since abandoned Vulkan. On a whim I tried Vulkan and some xiaomi devices which were struggling were able to hit 30fps every now and then. Big improvement.

    You can't win. You need to profile a bunch of devices to see which graphics API it responds better to, then you need to ship this preference list with the build, write a custom Unity activity to lookup this list and pick the appropriate API on startup.

    This really feels like the kind of problem the engine should solve. It would benefit everyone, collectively save so many developers so much time and improve performance across hundreds of Unity Android applications "for free".
     
    Starburst999 and Starsmiao like this.
  15. Kobald-Klaus

    Kobald-Klaus

    Joined:
    Jun 20, 2014
    Posts:
    127
    thanks for the android hints.

    Maybe it´s to early to party, but I found the following:
    I made tests with 67 google testlab devices and 3 of them had problems terminating with that vkCreateImageView Exception.
    After changing these settings:
    - vulkanNumSwapchainBuffers: 3
    - vulkanEnableSetSRGBWrite: 1
    + vulkanNumSwapchainBuffers: 2
    + vulkanEnableSetSRGBWrite: 0
    (swapchain image was off all times)
    Only one device had a problem. (Asus ZenFone 4, API level 28)

    Since deployment I do not see any crashes in the google play console. So let´s see....
     
  16. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    479
    @Kobald-Klaus vulkanNumSwapchainBuffers=2 may cause performance issues, especially for GPU bound games.
    I suspect your crash is caused by the SRGB write-control setting. Most likely you won‘t need that anyway (not supported my many GLES drivers). I can check next week if we can reproduce the problem.
     
    yuliyF and Kobald-Klaus like this.
  17. florianpenzkofer

    florianpenzkofer

    Unity Technologies

    Joined:
    Sep 2, 2014
    Posts:
    479
    @Prodigga Thanks for the feedback.

    We are working on improving the defaults when Vulkan is used instead of OpenGL ES.

    The goal is to only use Vulkan on devices where it’s stable and performs well. The problem is that in many cases this depends on the content (CPU-bound vs GPU-bound, which features does it use etc).

    But I don’t know if this will solve your problem with the OnePlus6T anyway, at least I have not seen issues like that on other devices with Snapdragon 845.
     
    Kobald-Klaus likes this.
  18. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,741
    It does, but you've been around long enough that to know that Unity doesn't like to solve these and prefers to let the users solve them themselves.

    As for Vulkan, just give up on it, it was much more solid when it was first introduced (was faster on all devices I tested and there weren't many issues), then at some point it took a nose dive.
     
    Starsmiao and Kobald-Klaus like this.
  19. Kobald-Klaus

    Kobald-Klaus

    Joined:
    Jun 20, 2014
    Posts:
    127
    @florianpenzkofer, fyi, according to google report, I have no vulkan related crashes since I changed the parameters mentioned above.
     
    florianpenzkofer likes this.
  20. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    @florianpenzkofer Hi. Customizing Activity (https://docs.unity3d.com/2020.1/Documentation/Manual/AndroidUnityPlayerActivity.html) works well, but how to get GPU information before calling
    updateUnityCommandLineArguments()? I can get device name or id by using android.os.Build, but can't get GPU information (GLES20.glGetString(GLES20.GL_RENDERER) throws error) because GPU is not initialized at startup.

    Some GPU has problem in Vulkan mode, so I want to use opengles on specific GPU-devices. Is there any solution for getting gpu information?
     
    buFFalo94 likes this.
  21. Ikaro88

    Ikaro88

    Joined:
    Jun 6, 2016
    Posts:
    300
    I can do that on IOS?