A quick note on shader compilers

This morning I was wrestling with  a particularly complicated compute shader, which was taking just shy of 10 minutes to compile using D3DCompiler_43 from the June 2010 DirectX SDK. After a few failed attempts to speed it up by rearranging the code, I figured I’d try it out with the new version of the compiler that comes with the Windows 8 SDK. I wasn’t expecting any miracles, but to my surprise it compiled my shader in about 45 seconds! I figured I would pass along the knowledge, in case anyone else is dealing with a similar problem.

About these ads

15 comments

  1. I’ve found that with compute shaders in particular, if you drop down to O1 instead of the default O3 optimization level you will get the same instruction count with 2-10x faster compiles.

  2. @zproxy

    I don’t think I can say, although I’ll tell you that it involved a few instances of an unrolled loop that executed for 49 iterations.

    @talden

    I was actually already compiling the shaders at O1, and it was still that slow! But thanks for the tip.

  3. Using the Feb 2010 SDK, I’ve found that array size directly impacts shader compile time: We had an array for bones with 1K elements, and our compile times for vertex shaders were about 30-45 seconds depending on the shader; after changing that to a one element array (to test this theory), our compile times went down to 0.2, 0.3 secs.

  4. R Caloca, you should change the array count to 2. If it’s 1, compiler always selects the first bone so the generated assembly is incorrect; if it’s 2, it does the proper index-based lookup, and you can upload more than 2 bones – assuming that the array is at the end of the constant buffer, of course. This does not generate any D3D Debug warnings and, as far as I’m aware, is safe wrt different HW/drivers.

  5. Could you use the win8 sdk compiler with your win7 application? If so, can you give more details about how you manage to do that? Did you have to compile shader using fxc.exe or compiling from code also worked?
    thanks!

  6. Yes, it’s possible. You can build Win7 applications using the Win8 SDK, in which case you just include D3DCompiler.h and link to d3dcompiler.lib and you’ll use the new compiler. Just make sure that you copy d3dcompiler_46.dll from the Bin folder of your SDK install directory and put it next to your executable, because it won’t be present on Win7 machines.

    If you want to keep using the headers and libs from DirectX SDK and use the compiler from the Win8 SDK, it’s a little more tricky. You can’t just add both Include paths to your VC++ directories, otherwise VC++ won’t know which version of the file you want to include. An alternative would be to just use LoadLibrary and GetProcAddress to call the compile functions in d3dcompiler_46.dll without using the headers or linking to it. Or if you’re compiling your shaders ahead of time, using fxc.exe is a simple way to do it.

  7. Greate new and thanks for your answer, I’m fed up with slow shader compilation. I did not know that win8 is not needed to build apps using the win7 SDK. If I understand what you say all I have to do is to install the Win8SDK and include/link against the Directx11 (11.1?) that comes with it instead of DirectX SDK? And I won’t have to change anything else in my app to make it run with the win8SDK (as I can’t actually run a win8 on win7 anyway)?

  8. Greate news and thanks for your answer, I’m fed up with slow shader compilation. I did not know that win8 is not needed to build apps using the win8SDK. If I understand what you say all I have to do is to install the Win8SDK and include/link against the Directx11 (11.1?) that comes with it instead of DirectX SDK? And I won’t have to change anything else in my app to make it run with the win8SDK (as I can’t actually run a win8 on win7 anyway)?

  9. Thanks you for your help! I finally did it the “GetProcAddress” way because I was too lazy to change the vcproj. The shader now compile ~40% faster than before. Some shaders even compile twice faster (compute shaders and pixel shaders with lots of branch and nested loopts). Trivial shaders (like ZPass opaque PS) are a bit slower to compile.

  10. MJP, is it legal to ship the d3dcompiler.dll with your game or does Microsoft forbid that. If it is forbidden, then how can you ship your game when it pops a missing .dll error if you don’t include it? I am compiling ahead of time using VS2012 and so don’t see any reason why the executable would require me to dynamically link with the d3dcomipler anyway. For now I’ll just include the .dll in my .exe directory, but I feel that this is a hack. Thanks in advance.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s