Skip to main content
GameDev.net gamedev.net
🔒 Locked

Shader cache

Started by Volgut Jul 12, 2010 at 10:48 AM 13 replies 8.6k views
Original Post
Volgut
Volgut
Hello,

I would like to implement a shader cache which will store all compiled shaders in a file. Shader will be re-compiled if source file has been changed - otherwise compiled shader will be used directly from the cache file.

I am not very familiar with OpenGL and I am looking for a function which will return compiled shader and another function which I could use to set compiled shader which was loaded from the cache.

Best regards,
Tomasz
Danny02
Danny02
just one question why?
Volgut
Volgut
My application uses many variations of several shaders and I need to access them at any time. For example - if I enable a point light, then several shaders need to be re-compiled to include point light computations. Currently it stops the whole application for a short while, because OpenGL driver needs to re-compile these shaders. Instead of re-compiling shaders, I would like to directly use them from a cache in a binary (compiled) format.
Yann L
Yann L
This is not possible under OpenGL.
Volgut
Volgut
I am a bit surprised that it's not possible to load a shader in a binary format, because as I know it's not a problem under DirectX.

Anyway, thanks for the answer.
Yann L
Yann L
Quote:
Original post by Volgut
I am a bit surprised that it's not possible to load a shader in a binary format, because as I know it's not a problem under DirectX.

Well, tell that the ARB. People have been bitching for years to finally get binary blobs, and the ARB keeps coming up with idiotic "reasons" why we still don't have them.

OpenGL ES has them, although in somewhat limited way and on a purely optional basis.
AndyEsser
AndyEsser
Can you not do this with CG? I thought with CG you could get the compiled code back and reload it straight as the binary? I may be talking out my arse though, so probably best to ignore me.
Eric Lengyel
Eric Lengyel
This is not possible under any graphics library, including both OpenGL and DirectX. Different GPUs have completely different native instruction sets, and they change every few generations. You can't compile straight to binary and expect the code to work on more than one generation of GPUs from one vendor. The best you can do is compile to some generic intermediate format, and this is what DirectX provides. This saves the compiler from having to parse the input program, run syntactic analysis, and perform high-level optimizations (like inlining and dead code elimination), but the it will always still have to generate the final native code and perform low-level optimizations (like instruction scheduling and register allocation).
phresnel
phresnel
Quote:
Original post by Yann L
Quote:
Original post by Volgut
I am a bit surprised that it's not possible to load a shader in a binary format, because as I know it's not a problem under DirectX.

Well, tell that the ARB. People have been bitching for years to finally get binary blobs, and the ARB keeps coming up with idiotic "reasons" why we still don't have them.

OpenGL ES has them, although in somewhat limited way and on a purely optional basis.


Without being too much into the topic, I guess ppl cried for it because they hoped for protection. But then, OpenGL seems to be a non-proprietary standard: How should their content be more safe in a binary blob if that binary blobs codec's open? Thus I'd conclude that OpenGL is simply not for them.

If blobbing was more about performance, i.e. about readily tokenized but non-compiled code, then ignore my post.

And in case of a compiled blob: I think that would be in the way of future compatibility and code-scalability w.r.t. improving hardware, as compilation in this case would also be information loss.
Yann L
Yann L
Quote:
Original post by Eric Lengyel
This is not possible under any graphics library, including both OpenGL and DirectX. Different GPUs have completely different native instruction sets, and they change every few generations.

Well, a popular idea is a local binary shader cache. You ship your product with uncompiled high level shaders. On the first run, these shaders are compiled to a native binary, which are put into a cache tied to the GPU ID. On subsequent runs, the time intensive compilation can be skipped. If the GPU is swapped, the cache is rebuilt.

Quote:
Original post by phresnel
Without being too much into the topic, I guess ppl cried for it because they hoped for protection. But then, OpenGL seems to be a non-proprietary standard: How should their content be more safe in a binary blob if that binary blobs codec's open? Thus I'd conclude that OpenGL is simply not for them.

Yes, IP protection is a part of the issue. Performance is the other. OpenGL is not open. It is however standarized, just as D3D is. Even a standarized intermediate language can improve IP protection by a lot, compared to shipping uncompiled GLSL. At least it's much harder to reverse engineer than being presented plain source.

I for myself would go a lot further, advocating asymmetric on-die decryption and DRM. I firmly believe that more and more IP lies in the shaders, and that IP needs to be protected. But an IL would already be a first step. At this point, obfuscating GLSL (where you replace all variable/attribute/uniform/etc names with GUIDs) is the only, highly unsatisfactory way.

About OpenGL not being for them. I'd like to remind you for whom OpenGL was originally designed for and still is: the CAD/CAM and defense industries.

Quote:
Original post by phresnel
If blobbing was more about performance, i.e. about readily tokenized but non-compiled code, then ignore my post.

Of course it's also about performance. The idea of a native binary blob is exclusively about performance, since shader source is still initially required.
Hodgman
Hodgman
Quote:
Original post by Danny02
just one question why?
Loading times is a big reason - and not just in the final/shipping version of the game --

Some companies go further than a local shader cache during development, and use a networked shader cache. Whenever a shader is compiled, the binary version is uploaded to a central server so other people on the team don't also have to compile it.

On some games, with hundreds of shader permutations, changing a shader source file can add a few minutes to your next loading screen - multiply the number of shader changes by the number of people on the team and it can be a non-trivial amount of wasted development time ;)
Danny02
Danny02
I can see that u don't want your App to freez for a short amount of time when it needs to recompile shaders, but why don't u compiel all shaders at programm start?

What questions me is, I felt that the compile time of a shader was always quite quick and when having a lot shaders this shouldn't matter that much when all are compiled at startup rigth?
Hodgman
Hodgman
Quote:
Original post by Danny02
why don't u compiel all shaders at programm start?
Being able to reload shaders while the game is running is very useful for fast iteration, but that's another topic ;)
Quote:
What questions me is, I felt that the compile time of a shader was always quite quick and when having a lot shaders this shouldn't matter that much when all are compiled at startup rigth?
I've got one shader at work that has about 70 permutations (different versions of the same shader with #ifdefs). Some of the individual permutations take ~10 seconds to compile :( In total, the whole shader takes a few minutes.
Volgut
Volgut
The only reason why I was thinking about shader cache is to avoid run-time stalls.

And no, I can't compile all shaders at a start up of my app, because as Hodgman said, that would take too much time. I have around 5 "super shaders" and every one of them uses around 10-30 #ifdefs.

[Edited by - Volgut on July 13, 2010 9:22:24 AM]
Prune
Prune
Is not an additional motivation on the vendors' side optimizations that come with new drivers? I bet non-trivial shaders compiled under an old and a new driver on the same hardware have a good chance of producing nonidentical binary.

By the way, is it possible to transfer an OpenGL context from one process to another? If so, it would be possible to use a Windows service or Linux daemon to hold your context with its compiled shaders until your application needs it, thus providing a semi-persistent OpenGL context (within a system restart). Catching a fatal exception in your application, or a quit message etc., would then trigger the transferring back to the service.

I might actually try something like this since I'm already using a system service as a watchdog.
"But who prays for Satan? Who, in eighteen centuries, has had the common humanity to pray for the one sinner that needed it most?" --Mark Twain

~~~~~~~~~~~~~~~Looking for a high-performance, easy to use, and lightweight math library? http://www.cmldev.net/ (note: I'm not associated with that project; just a user)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.