VSync making performance worse on build (even disabled)

Hello,
I’m trying some optimisation on my game and encounter this on a build when I attach it to a profiler :

My FPS are lower on the build that on the editor. I never go higher than 15 fps in my build even with :

1- VSync set to "Don’t sync’ in every quality of project settings
9412637--1318298--upload_2023-10-16_19-47-34.png

2- using the code :

    private void Start()
    {
        QualitySettings.vSyncCount = 0;
        Application.targetFrameRate = 50;
    }

3- Disabling Vsyinc on my NVidia Panel > Handle 3D Parameters > Vertical Synchronisation = Disabled + reboot.

I’m using 2021.3.18f1 and have a GTX1070. I can have steady 30FPS on my editor but build is always 50% slower and 15FPS is kind of low. This “Vsync” doesn’t appear at all on the profiler on editor but I read somewhere that it’s not a good label and can reveal that a GPU is in a bottleneck. Any ideas ?

I’d take a GPU capture with RenderDoc (more for debugging but can do a little bit of profiling), NSight Graphics or PIX (DX12 only). If nothing shows up in NSight Graphics, you can also take a look at the entire system with NSight Systems.

Maybe also log the value of QualitySettings.vSyncCount in regular intervals just in case that there is some other script that sets it later in time.

By the way, a target frame rate of 50 is a bit of an odd choice. I would 60 on PC or 30 on mobile.

Thanks for the advice.

A capture with RenderDoc :
9413768--1318544--upload_2023-10-17_10-45-2.png
It made like 10 seconds to take the picture and the game was freezing.
Is the “MainLightShadow” that from EID 265 to 7525 expensive ? And DrawOpaqueObjects from 7565-13350?
Here a PIX capure :
9413768--1318547--upload_2023-10-17_10-50-18.png

In the first capture above you can see a huge “UniversalRenderPipeline.RenderSingleCamera:Camera_Fog_Gestion” and Camera_Fog_Gestion is a gameobject for my camera. I remove everything heavy for this gameobject (the fog), change my URP pipeline, and it’s increasing the “VSync” performance so I’m still capped at 15-18fps

9413768--1318541--upload_2023-10-17_10-40-26.png

Hit the timing button in RenderDoc to get draw call timings
9414224--1318706--upload_2023-10-17_7-52-31.png

Your PIX capture is missing timings too (EOP to EOP duration column). You many need to hit the “Start Analysis” button at the top right. After that click “Collect Timing Data” on the Overview tab.
I’m surprised you managed to make a PIX capture for a DX11 game, though. That has never worked for me. But that’s great, because PIX is a great tool for GPU debugging and profiling.
9414224--1318712--upload_2023-10-17_8-5-37.png 9414224--1318715--upload_2023-10-17_8-9-22.png

1 Like

Thanks again for your help. Didn’t find the same button as you said but here we are with PIX :

9414695--1318811--upload_2023-10-17_18-26-16.png

There is HUGE budget on the URP :

9414695--1318817--upload_2023-10-17_18-30-6.png

Here an extracted file for RenderDoc (CaptureFrameUnity.txt)

9414695–1318814–CaptureFrameUnity.txt (371 KB)

I can’t do the profiling for you. But, I’d start with draw call 12355, for example which takes a very long time.

All the draw calls with 6912 indices add up as well

By the way, even though RenderDoc can do some profiling, the timings are usually much higher than they would be in real-time. So you can’t really tell if you are within 16 ms or not with RenderDoc.

The PIX screenshot looks as if you didn’t even start a capture. The present() information on the right is interesting, but doesn’t really say what the issue is.

Thank you for the insights; I can identify some resource-intensive elements now. However, I depend on specific weather effects that I haven’t personally created, so optimizing them might be time-consuming. Even if I manage to optimize and possibly gain a 50% performance boost, I’m still perplexed about the significant FPS difference between the build and the editor. Ultimately, my goal is to achieve a consistent 60 FPS.

It’s worth noting that my GPU usage spikes to 100% when playing the game, yet it only renders at 15 FPS.

9416405--1319111--upload_2023-10-18_14-32-45.png

The following code doesn’t seem to have any impact:

        QualitySettings.vSyncCount = 0;
        Application.targetFrameRate = 50;

Interestingly, the FPS drop is predominantly associated with the game’s main scene. I say this because I get about 300 FPS in the menu when it’s built.

What baffles me the most is how the editor runs at double the speed compared to the build. The Unity profiler doesn’t offer much clarity either; most of the processes are lumped under the “Zsync” category.

I’ve experimented with multiple builds, toggling Zsync on and off… Even when I strip down the scene completely, the FPS remains disappointingly low.

Do you think upgrading to Unity 2022 might help? Or perhaps starting with a fresh scene and reimporting assets ? Is it common to have a worsen build that editor ?

Usually the editor runs worse than the build but are you using the same quality level in both?

Are you running the player as a full-screen application at native resolution?

Yes, I only have 1 quality parameter for my project now “Low”. In editor, 35FPS and in build no more than 15-18 event deleting everything. However, it’s only on the “main scene” of my game with 3D scene, when I’m in the menu I have 300 FPS.

Same resolution 1920x1080 tested for build and editor. In editor when I “Play Focused” or “Play Maximised” no difference.

9421952--1320317--upload_2023-10-20_20-55-14.png

9421952--1320320--upload_2023-10-20_20-57-5.png

Today, I revisited the issue and tested two scenarios: one with FOG and another WITHOUT it. While the performance isn’t as severely impacted as before, the FPS improvement from removing the fog is more pronounced in the editor than in the build.

9421952--1320329--upload_2023-10-20_21-46-30.png

BUT my GPU is still at 100% on the build…
9421952--1320332--upload_2023-10-20_21-48-56.png

9421952--1320329--upload_2023-10-20_21-46-30.png

The screenshot says that you have scale set to 0.51in the Editor.

having Scale 1f or 0.51f doesn’t change performance in editor

I identify two problems.

I have a frame that take up to 217,000 µs to be made (0.217 seconds => 5FPS).
I have 133,000 from a pluggin to make a volumetric fog :

13942 | - DrawIndexed(6)                                                                                                    | 3476   | 133291.744
13943 | - OMSetRenderTargets({ Render Target View 6929 }, No Resource)                                                      |        |
13944 | - RSSetViewports({ { 0.00, 0.00, 5120.00, 2160.00 } })                                                              |        |
13945 | - ResolveSubresource(RenderTexture-2D-5120x2160, TempBuffer 59 5120x2160)                                           | 3477   | 405.504
13946 | - OMSetRenderTargets({ Render Target View 6929 }, No Resource)                                                      |        |
13947 | - RSSetViewports({ { 0.00, 0.00, 5120.00, 2160.00 } })                                                              |        |
13948 | - Map(Buffer-1-1048576, 0)                                                                                          |        |
13949 | - Map(Buffer-2-131072, 0)                                                                                           |        |
13950 | - Unmap(Buffer-1-1048576, 0, (68 bytes))                                                                            |        |
13951 | - Unmap(Buffer-2-131072, 0, (11 bytes))                                                                             |        |
13952 | - PSSetShaderResources(0, { RenderTexture-SRV-1515-color-5120x2160 })                                               |        |
13953 | - PSSetSamplers(0, { SamplerState-1-111-1 })                                                                        |        |
13954 | - PSSetShaderResources(1, { RenderTexture-SRV-1521-color-5120x2160 })                                               |        |
13955 | - PSSetShaderResources(2, { RenderTexture-SRV-1529-depth-5120x2160 })                                               |        |
13956 | - PSSetSamplers(2, { SamplerState-0-111-0 })                                                                        |        |
13957 | - OMSetBlendState(BlendState-2-1, {})                                                                               |        |
13958 | - IASetVertexBuffers(0, ID3D11Buffer *[8])                                                                          |        |
13959 | - IASetInputLayout(InputLayout-14)                                                                                  |        |
13960 | - IASetIndexBuffer(Buffer-2-131072)                                                                                 |        |
13961 | - VSSetShader(Unlit/FullVolumeCloudsURP LAYERS Fog of War)                                                          |        |
13962 | - PSSetShader(Unlit/FullVolumeCloudsURP LAYERS Fog of War)                                                          |        |
13963 | - Map(ConstantBuffer-171-656, 0)                                                                                    |        |
13964 | - Unmap(ConstantBuffer-171-656, 0, (656 bytes))                                                                     |        |
13965 | - VSSetConstantBuffers(1, { ConstantBuffer-171-656 })                                                               |        |

I will see with the author of the asset for this part.

And then I have this line that repeat 1,700 times, and if I add all times it takes up to 60,000µs :

8214  |   - DrawIndexedInstanced(6912, 1)                                                                                   | 2318   | 63.488
8215  |   - IASetVertexBuffers(0, ID3D11Buffer *[8])                                                                        |        |
8216  |   - IASetIndexBuffer(Hex_Mesh)                                                                                      |        |
8217  |   - VSSetConstantBuffers1(1, { Buffer 2154 })                                                                       |        |
8218  |   - PSSetConstantBuffers1(2, { Buffer 2154 })                                                                       |        |
8219  |   - DrawIndexedInstanced(6912, 1)                                                                                   | 2319   | 63.488
8220  |   - IASetVertexBuffers(0, ID3D11Buffer *[8])                                                                        |        |
8221  |   - IASetIndexBuffer(Hex_Mesh)                                                                                      |        |
8222  |   - VSSetConstantBuffers1(1, { Buffer 2154 })                                                                       |        |
8223  |   - PSSetConstantBuffers1(2, { Buffer 2154 })                                                                       |        |
8224  |   - DrawIndexedInstanced(6912, 1)                                                                                   | 2320   | 64.128
8225  |   - IASetVertexBuffers(0, ID3D11Buffer *[8])                                                                        |        |
8226  |   - IASetIndexBuffer(Hex_Mesh)                                                                                      |        |
8227  |   - VSSetConstantBuffers1(1, { Buffer 2154 })                                                                       |        |
8228  |   - PSSetConstantBuffers1(2, { Buffer 2154 })                                                                       |        |

in my game here a HexChunk that contain :

  • HexMesh
  • A canvas
  • HexFeature that contain all feature in the grid
  • 64 HexCell gameobject

9423827--1320821--upload_2023-10-22_10-58-7.png

Here HexMesh with the “Hex_Mesh” mesh that repeat in my log :

I try to make it static and adding “Enable GPU Instancing” in the Hex_Map_Triplanar_Infinite material but performance don’t change. Any idea ?

Check if instancing is actually working in RenderDoc and the frame debugger. If it isn’t, the built-in frame debugger might tell you why not.
You might need to remove SRP batcher compatibility to use instancing.

I believe instancing isn’t functioning correctly in RenderDoc. This is based on the numerous “DrawIndexedInstanced(xxxx, 1)” lines observed, where the second argument is ALWAYS at 1.
9425099--1321115--upload_2023-10-23_10-33-6.png

Made a frame debugger on my project for HexMesh :

9425099--1321097--upload_2023-10-23_9-42-32.png
9425099--1321100--upload_2023-10-23_9-43-7.png

SRP Why draw call can’t be batched with the previous one (I list the errors I have):

  • First call from ScriptableRenderLoopJob
  • Objects either have different shadow caster shaders, or have different shader properties / keywords that affect the output of the shadow caster pass.
  • Nodes have different shaders

So here my shader that is SRP compatible :
9425099--1321103--upload_2023-10-23_9-46-50.png

I tried to make the shader incompatible with SRP by following the instructions in the documentation. I copied the shader and pasted it into a new file named SRP_INCOMPATIBLE.shader. I then added only a material in the properties section

Shader "Hex_Map_Triplanar_infinite_SRP_incompatible"
{
    Properties
    {
        _SRPuncompatible("SRP uncompatible", Float) = 1.0
        _infinite_hex_size("infinite_hex_size", Float) = 0.84

However, the shader still shows as “SRB Batcher: compatible,” preventing me from testing GPU Instancing on this new shader.

It’s worth noting that the “Hex_Map_Triplanar_infinite” material is the same for all the Hex_Mesh chunks in my map. Each chunk has the exact same material without any instances. However, the meshes of these chunks vary due to differences in altitude or rotation. There is also a cookie light with moving cloud that go over the material.

9425099--1321103--upload_2023-10-23_9-46-50.png

Unfortunately, I don’t know why it doesn’t work. My experience with URP is limited. But I think, you are on the right track. You can try to make the renderer incompatible instead (see docs).

Different transforms won’t break instancing. Or do you mean you are actually using different meshes? You can only use instancing for objects that have identical mesh and materials - however, you can have different transforms and materialpropertyblocks.

Yes thanks for the info I didn’t know anthing about SRP batcher and GPU instancing I will dig it for the moment all infos !

Did you get anything out of your search ? I recently had my vsync meter go through the roof as well. It was seemlingly ok like just some times ago.

I greatly reduce triangle amount in mesh and it did the trick.

1 Like

Thanks. Yes after further research and profiling it appears that the CPU was simply waiting for the GPU (GPU profiling is turned off by default), so indeed culling/simplification/drawcall reduction todo, (and one fullscreen effect that was poorly optimized)