2
\$\begingroup\$

Generally, video games and other graphical software that use vertex and fragment shaders will have said shaders in the form of actual shader source code (typically in glsl or hlsl), and will compile them for use with the display hardware at runtime. (It is my understanding that shaders cannot really be precompiled into the game binary because the actual shader machine code that the display hardware uses depends on the graphics card brand and even its model/generation, and they may well be incompatible with each other.)

Even though I do myself work on the game programming field and use shaders, I actually don't know exactly which part of the graphics pipeline actually compiles the shaders into the machine code that the graphics card uses. Compiling shaders is essentially a black box: Throw the shader source code into whatever library you are using, and it does its magic behind the scenes.

I would be interested in knowing exactly where this compiling process happens. Which exact part of the entire system takes the shader source code and produces shader machine code from it?

My (wild) guess is that this is done by the graphics card driver (because the driver knows what kind of machine code it should output, and how to optimize it, for the particular brand and model of graphics card).

(If this is indeed so, it would explain at least partially why the graphics driver is so crucial in how efficiently games run, as its optimization of the shader machine code would have great impact on rendering speed.)

Are there any resources out there were I could find more info, in general, about these things?

\$\endgroup\$
1
\$\begingroup\$

It is my understanding that shaders cannot really be precompiled into the game binary because the actual shader machine code that the display hardware uses depends on the graphics card brand and even its model/generation, and they may well be incompatible with each other.

This understanding is incorrect.

The model used by most games is that shaders are first compiled from text-based source code (HLSL, etc) to a hardware-independent binary intermediate language. This produces binary blobs which can be shipped with the game, whether baked into game binary as embedded resources, or in PAK files, or loose files, or howsoever. These binary blobs are then compiled during startup time (not at run time) to actual hardware-dependent shader objects.

So shader compilation is therefore a two-step process:

  1. Compilation from source code to hardware-independent binary intermediate language.
  2. Compilation from hardware-independent binary intermediate language to hardware-dependent shader object.

Step 1 is the slow step; the one that requires text-parsing, error checking, dead-code removal, validation against hardware profiles, etc.

Step 2 is fast.

Step 1 need not be performed by the driver; it can be performed by a standalone compiler on a command-line and it's not even necessary to initialize a graphics device or context to perform it.

Step 2 requires a graphics device or context to be initialized.


The important thing to understand is that the model I've described above is not the model that is used by OpenGL. If the only API you know is OpenGL, if you assume that other APIs work the same way as OpenGL, you may come to the conclusion that this model does not or cannot happen.

That, however, would be an incorrect conclusion.

Every other API uses the model I've described above; Metal, Direct3D, Vulkan; the two-step model is widely-used, well-understood, and works.


So, to answer your question, typically shader compilation is not done by the graphics card driver but rather by an offline tool, and compilation is done as part of the development process before the game is even shipped. The graphics card driver then takes the output of that offline tool and does a final pass to convert it to something usable on your specific hardware. This final pass is typically not done at runtime but rather while the program is first starting up, and drivers may even cache the result of that for faster startups in second and subsequent runs.

OpenGL, however, is the odd-one-out in that the full shader compiler is part of the driver and therefore steps 1 and 2 cannot be separated.

\$\endgroup\$
  • \$\begingroup\$ I'm aware that OpenGL extensions do exist that allow for program binaries. \$\endgroup\$ – Maximus Minimus May 29 '18 at 16:04
0
\$\begingroup\$

OpenGL and DirectX aren't libraries in the traditional sense (as in "library is a set of functions") , it's a definition. Instead of implementing the functions, they just declared what manufacturers need to implement to support them. That's, why graphics card support a certain version, and not the other way around.

So, with this it should be much clearer what they actually do. They just tells the GPU driver what to do, but not how exactly. Same with shader compilation, they send the source to the driver, which compiles it.

Technically, you could pre-compile every shader, but you would be trading a ton of storage space for little performance, especially since shaders get compiled before gameplay

\$\endgroup\$
  • 1
    \$\begingroup\$ My question was specifically exactly what compiles shaders into the machine code used by the graphics card. My question was in no way related to OpenGL or what it is. Is it indeed so that it's the display driver created by the graphics card manufacturer that performs the compilation? \$\endgroup\$ – Warp May 29 '18 at 12:00
  • \$\begingroup\$ @Warp extended answer to DirectX. The information about what actually compiles it is in it \$\endgroup\$ – Bálint May 29 '18 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.