Handmade Hero » Forums » Code » [Day 235] Opengl's pixel format takes a long time
DanZaidan
Daniel Zaidan
12 posts
#12607 [Day 235] Opengl's pixel format takes a long time
3 weeks, 4 days ago

Hi folks!

I'm trying to work with Opengl and even though I got it to work (I can set a screen color) successfully, it takes a long time (something like 3 seconds) for opengl to init.

I stepped through the code and found that the bottle neck was in ChoosePixelFormat:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
PIXELFORMATDESCRIPTOR desired_pixel_format = {};
    desired_pixel_format.nSize = sizeof(desired_pixel_format);
    desired_pixel_format.nVersion = 1;
    desired_pixel_format.dwFlags = PFD_SUPPORT_OPENGL|PFD_DRAW_TO_WINDOW|PFD_DOUBLEBUFFER;
    desired_pixel_format.cColorBits = 32;
    desired_pixel_format.cAlphaBits = 8;
    desired_pixel_format.iLayerType = PFD_MAIN_PLANE;
    
    int suggested_pixel_format_index = ChoosePixelFormat(window_dc, &desired_pixel_format);
    PIXELFORMATDESCRIPTOR suggested_pixel_format;
    DescribePixelFormat(window_dc, suggested_pixel_format_index, sizeof(suggested_pixel_format), &suggested_pixel_format);
    SetPixelFormat(window_dc, suggested_pixel_format_index, &suggested_pixel_format);


So I copied the values from the pixel format windows gave me and hardcoded it into a new code that doesn't use ChoosePixelFormat.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PIXELFORMATDESCRIPTOR pixel_format = {};
    pixel_format.nSize = sizeof(pixel_format);
    pixel_format.nVersion = 1;
    pixel_format.dwFlags = 33317;
    pixel_format.cColorBits = 32;
    pixel_format.cRedBits = 8;
    pixel_format.cRedShift = 16;
    pixel_format.cGreenBits = 8;
    pixel_format.cGreenShift = 8;
    pixel_format.cBlueBits = 8;
    pixel_format.cBlueShift = 0;
    pixel_format.cAlphaBits = 8;
    pixel_format.cAlphaShift = 24;
    pixel_format.cAccumBits = 64;
    pixel_format.cAccumRedBits = 16;
    pixel_format.cAccumGreenBits = 16;
    pixel_format.cAccumBlueBits = 16;
    pixel_format.cAccumAlphaBits = 16;
    pixel_format.cDepthBits = 24;
    pixel_format.cStencilBits = 0;
    pixel_format.cAuxBuffers = 4;
    
    BOOL result = SetPixelFormat(window_dc, 8, &pixel_format);


However this time, the bottleneck happened in SetPixelFormat.

I found it quite weird that it launched 4 threads and specially weird that it changed places (ChoosePixelFormat and SetPixelFormat) based on what code I called, and that the output log looked the same on them both:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\nvoglv64.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\shell32.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\windows.storage.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\shlwapi.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\powrprof.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\profapi.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\setupapi.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\wtsapi32.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\version.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\devobj.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\wintrust.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\msasn1.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\crypt32.dll'. Cannot find or open the PDB file.
The thread 0x2ce8 has exited with code 0 (0x0).
The thread 0x2dd8 has exited with code 0 (0x0).
The thread 0xb20 has exited with code 0 (0x0).
The thread 0x2e64 has exited with code 0 (0x0).
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\nvspcap64.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\ole32.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\psapi.dll'. Cannot find or open the PDB file.
'win32_main.exe' (Win32): Loaded 'C:\Windows\System32\winhttp.dll'. Cannot find or open the PDB file.


Last week, I tried messing around with SDL and found that whenever I changed the window to use Opengl, it took the same 3 seconds to start. I tested that .exe in 4 different PCs. Two of them opened instantaneously, and two (the better two) took a long time.

I have a 64-bit Windows 10, running on an i7-5820K @3.30GHz and two GTX 780.

What could possibly be causing this?

Thanks,
Dan Zaidan
mmozeiko
Mārtiņš Možeiko
1437 posts
1 project
#12611 [Day 235] Opengl's pixel format takes a long time
3 weeks, 3 days ago Edited by Mārtiņš Možeiko on July 24, 2017, 7:40 p.m.

Bad driver. Bad anti-virus software. Some other running service/utility/software. But most likely just a drivers issue. Not much you can do...
Nytheris
1 posts

None

#12621 [Day 235] Opengl's pixel format takes a long time
3 weeks, 3 days ago

I'm getting the same thing. On my PC with a GTX 750Ti it takes 3 seconds, yet on my laptop with just the integrated intel graphics, it only takes about 100 milliseconds.

None
musicaljelly
Lewis
2 posts
#12623 [Day 235] Opengl's pixel format takes a long time
3 weeks, 2 days ago

I'm running into the same problem, about 1.2 seconds for me. Some web searching digs up a number of posts about this issue, but no actual solutions. It does reek of a driver issue, but the issue seems widespread enough that finding a workaround would be highly desirable.
DanZaidan
Daniel Zaidan
12 posts
#12632 [Day 235] Opengl's pixel format takes a long time
3 weeks, 2 days ago

@mmozeiko I only use Windows Defender in this PC, it turned it off and added it to the exceptions list but there was no difference. I ended all the processes I could and no difference, so yeah, it's probably a driver problem.

It's somewhat reassuring that Nytheris and musicaljelly also have the problem. :P

Just to add some info, I tested on the drivers GeForce 382.05, 384.76 and 384.94.
mmozeiko
Mārtiņš Možeiko
1437 posts
1 project
#12672 [Day 235] Opengl's pixel format takes a long time
2 weeks, 5 days ago Edited by Mārtiņš Možeiko on July 30, 2017, 7:47 a.m.

I did a little debugging and disassembling of Nvidia OpenGL driver (user-space part of it) to look what it is doing.

First I wrote this test code: https://gist.github.com/mmozeiko/9b661cf8f48b56945984d518a9cd6310

On my desktop PC (i7-6700K, GTX 970, Windows 10 x64, Nvidia 384.94 driver) it gives me 0.668 seconds for Choose + Set pixel format functions.

After profiling, disassembling and debugging the driver, I found that most of the time it is processing huge list application & executable names. Not sure exactly what it is doing but its a lot of code+time. I think it tries to mach profile for custom 3D settings. In your Nvidia Control Panel go to "Manage 3D Settings" -> Program Settings -> uncheck "Show only programs found on this computer" and check how big is the list in combobox. It is huge.

Unfortunately there is no good way to officially delete contents of this list. I started to look where this list is stored and found three locations:
  1. C:\ProgramData\NVIDIA Corporation\Drs\nvdrsdb0.bin
  2. C:\ProgramData\NVIDIA Corporation\Drs\nvdrsdb1.bin
  3. C:\Program Files\NVIDIA Corporation\Drs\nvdrsdb.bin
First two you can safely remove - but just in case DO NOT DELETE these files. Rename to something like nvdrsdb0.bin.old. It looks that these files store customized settings and are recreated from third location if they don't exist.

After removing first two files, the test program from my gist now prints 0.456 seconds. That is 32% improvement. Pretty nice.

Unfortunately we cannot remove or replace with empty file the third location. By doing that the Nvidia opengl driver will simply crash and none of your applications will work. What I did instead - I went to Nvidia site and took this file from old 280.26 driver version from 2011. There this file is only 305KB big compared to 1.4MB - so it stores less information about application settings. You can get this file here: nvdrsdb.zip You'll need to replace this file every time you upgrade Nvidia driver.

After replacing nvdrsdb.bin file my test program prints out 0.306 seconds which is ~54% - two times faster than initially. Even better!

Now it looks that Nvidia opengl code now is spending most of the time in different place, some initialization code with loading library (LoadLibrary function). Processing that big list is not a bottleneck anymore. Ideally I would want to reduce this list to 0 items, but that would require more time on reverse engineering format of nvdrsdb.bin file. I tried some quick'n'dirty experiments - replaced few numbers with value 0 in header, but all I got was crash. So more debugging is needed. But it should be possible.

I think Nvidia is just adding more and more predefined application profiles to this file, it gets bigger and bigger, so the linear scan through list gets slower and slower. Not 100% sure about this, that's just my guess.

I do not know if this breaks anything. Maybe your SLI configuration will stop working. Maybe there will be some glitches with older OpenGL applications/games - this file might contain some workarounds, not only 3D setting customizations. But try it, maybe it gets faster also for you. This is not a real fix, but for dev machine this could be acceptable workaround.

DanZaidan
Daniel Zaidan
12 posts
#12681 [Day 235] Opengl's pixel format takes a long time
2 weeks, 4 days ago

Wow, thanks so much for digging into this!

I ran your code and it printed 1.081.
So I went to the C:\Program Files\NVIDIA Corporation\Drs directory and there was no nvdrsdb0.bin or nvdrsdb0.bin!

Only nvdrsdb.bin and dbInstaller.exe.
After changing the nvdrsdb.bin file to the one you linked, I got a small performance increase to 1.077. :(

Over in the SDL thread, Daniel_Gibson linked to this tweet from Sean Barret: https://twitter.com/nothings/status/891335303130005504
Based on his tweet: "If NVIDIA folks following me want more info" I suppose Nvidia is already aware of the driver issue, and that it is actually pretty widespread (with different results, apparently). :P
mmozeiko
Mārtiņš Možeiko
1437 posts
1 project
#12684 [Day 235] Opengl's pixel format takes a long time
2 weeks, 4 days ago Edited by Mārtiņš Možeiko on July 30, 2017, 7:13 p.m.

nvdrsdb0.bin and nvdrsdb1.bin files are in "C:\ProgramData\NVIDIA Corporation\Drs" folder. Not "Program Files".
DanZaidan
Daniel Zaidan
12 posts
#12695 [Day 235] Opengl's pixel format takes a long time
2 weeks, 3 days ago

Oh yeah! (I can't believe I overlooked that... :( )

Now it's waay faster! 0.478!

Thanks so much! :)