Ever since I upgraded my video card, launching anything built with Unity causes very strange behaviour: the first Unity window doesn’t appear until around 30 seconds after double-clicking the EXE, and during those 30 seconds, my entire computer—including cursor movement!—stalls to about 5 fps. It’s so slow during this delay that I can sometimes watch individual windows redrawing piece by piece; folder windows occasionally go into ‘stop responding’ mode. Then, once Unity’s first window appears, everything is instantly fine again.
I’m running Windows 7 64-bit, with 6 GB of RAM. The problem started when I upgraded from a Radeon 6850 to a Geforce 970. I’ve already uninstalled the Radeon drivers and installed the Geforce drivers. I have an Oculus Rift, but this occurs even in non-Rift games, and even with the Rift disconnected.
Has anyone else had this problem? Is there anything I can do to determine what on earth Windows is doing during those 30 seconds where it’s so pegged that the cursor judders?
So far it has only happened with Unity games—although since yesterday, I have found a couple of Unity games that it doesn’t happen with, so maybe it’s only games compiled by a certain version of Unity…?
I’ve been tempted to ask them for information about their projects to try and isolate a cause, but I’m not sure what criteria to ask for, does anyone have any suggestions?
(And does really no-one else experience this minute-long stall while launching any of those projects?)
Generally, support for games made in Unity needs to go via the developers of the games in question - we have no idea what crazy things they’ve done - but if you want, you could try profiling your system (using a tool like Very Sleepy) to try and capture some information about what your CPU is doing during that massive lag.
Your suggestions so far - D3D9 vs DX11 and Unity4 vs Unity5 - are good, so I’d look for the games’ output_log.txt files for more information (should be in the ‘Data’ folder alongside the game executable). Other possible culprits include virus scanners (especially if Unity is taking 30secs to even show you the launcher window) and disk access.
I can now confirm, that the lag ALWAYS happens in Unity DirectX11 projects, and NEVER happens in Unity DirectX9 projects!
Interestingly, I tried Saints Row 3 (a non-Unity game) in both its DX9 and its DX11 mode, and the hang didn’t happen in either case, so it DOES seem like this is Unity-specific.
I’ve made VerySleepy logs of launching a Unity DX9 game and a Unity DX11 game (each only getting as far as the ‘configuration’ screen), but I’m not sure how to interpret them; I’ve attached them here in case they can help you make any sense of this. (The DX11 version does seem to have a new entry that took up a huge chunk of time, but I don’t know what it is…)
Unfortunately the VerySleepy files don’t tell me much beyond the fact that most of the time was spent in a function at address [75507E6C], which belonged to wow64.dll (part of Windows involved in running 32-bit applications on 64-bit Windows). It looks like it happened during loading of data, but it’s hard to say for certain.
I’ve built a minimal 32-bit D3D11 app for you - download it and give it a try.
Yes, trying out a minimal 64-bit Unity D3D11 project is the next step here. I’ve not got around to building the project though, with all the GDC prep, sorry…
Now that GDC is safely behind us, I figure it’s safe to check back in here
With Unity 5 being free, I was able to make myself a couple of test projects, and confirmed that a bare room (with a single cube) causes the hang when I compile it with DX11, and doesn’t cause the hang when I compile it with DX9.
Now that you have Unity installed, could you try the VerySleepy capture again, on ‘Development Build’ versions of both 32-bit and 64-bit players? Development Build players should include symbols that ought to make the VerySleepy files a bit more intelligible.
You’re right! The function it’s spending a minute on is called “ChangeDisplaySettingsA”. It’s being called from “WinScreenSetup::InitializeResolutions”. Does that give you anything to go on? (Should I attach the log?)
So, ChangeDisplaySettings. We use it when we’re building the list of resolutions that your graphics card supports, for testing whether a given resolution is actually supported. In pseudocode, we do something like this:
for(each screen resolution returned by EnumDisplaySettings for the main display device)
{
if(resolution is below 512x384, or has fewer than 16bpp)
skip resolution;
if(ChangeDisplaySettings(resolution, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
skip resolution;
otherwise add it to the list of supported resolutions
}
We do something different in D3D9 mode - using the Direct3D9-specific API for retrieving the available resolutions - which is why you see this problem only with D3D11-based games and not D3D9-based games.
So, why would ChangeDisplaySettings - in ‘test’ mode, so not actually changing resolution - be taking upwards of a minute? The only explanation I have - assuming that you don’t have a gazillion resolutions and it’s actually genuinely taking upwards of a minute to loop through them all, which I doubt - is that Windows and/or the display driver are taking a really long time to complete the test. Why are they taking a really long time? God (or Microsoft, or the display driver manufacturers) only knows…
Trawling the web a bit, I see a couple of vague references to ChangeDisplaySettings having “a known compatibility issue” with Windows 7. I can’t find any explanation of what this issue actually is, or whether it would result in the behaviour we’re seeing here… but there is are notes on a workaround using a different API.
I think the best next step here is probably going to be for me to cook up a little test app for you which tries out both APIs, and then we can see both a) that the ChangeDisplaySettings calls are indeed still the problem even when isolated, and b) whether the workaround approach has the same slow behaviour…
Oh, yikes, something must have gone wrong with the notification emails, I never got notified that you’d replied! Sorry!
I have some more news, then—after your explanation about monitor resolutions, I’ve now confirmed that this bug ONLY happens while my Dell U3011 is connected! I use three monitors, but specifically unplugging the U3011 makes Unity launches go back to normal. (And despite what your pseudocode says about the main display device, setting a different monitor to be my primary isn’t enough to avoid the bug…)
Is there something I can run to get a list of all the reported resolutions for this monitor, so you can see if there’s anything fishy about it?