Jump to content
  • Advertisement
Sign in to follow this  
CodeBoyCjy

OpenGL OpenGL Shader cache

This topic is 1427 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all

 

I'm trying to design a policy for my shader cache in my rendering engine.

There is little to say about D3D11, let's talk about opengl.

 

As we know that there is no IL in opengl, any binary shader format is hardware and driver dependent. So it is mandatory to pack the GLSL source in the final release application. And as far as I know, UE3 uses GLSL as the format of shader cache.

 

For shader cache format, there are several options:

  1. GLSL shader source files. ( No cache at all. Slowest. )
  2. GLSL shader cache. ( UE3 way of doing it. Maybe a little faster due to efficient way of file loading. )
  3. GLSL shader binary cache. ( There is no guarantee that it is supported on all hardware. And it still needs link. Should be faster in creating shaders.)
  4. GLSL program binary cache. ( A better way of doing it. No need to compile or link. Should be quite fast. However it may suffer from shader explosion issues.)
  5. GLSL seperate program binary cache. ( No shader explosion issue. And fast to initialize. )

In terms of loading speed and shader cache size, I think the last one is the best. However it may need run-time shader link before every draw call, does it affect perf a lot?

 

Or any better idea in GL shader cache?

 

Thanks

Share this post


Link to post
Share on other sites
Advertisement

wrt to GLSL and not standard binary format, what exactly would you be caching ? The said GLSL source ? If so, then what is the benefit of this caching scheme ?.

imo, if you are not caching some for of binary( shader or program ), then a shader cache makes no sense. If you cache the source, then compilation and linking still have to be done each time the application is started.

Share this post


Link to post
Share on other sites

Have a way setup to detect GPU and driver version.

 

First time the program is launched, pop in a "compiling shaders" screen (much like Battlefield 2 did), and compile all your shaders saving the binary to disk. Or you could pop in a separate context that compiles and saves the shaders in the background, then make the main context load the binaries.

 

If you don't have that many shaders, you could try to compile them in all their configurations, otherwise just save the ones needed for the current graphics configuration.

 

If user changes drivers/GPU (as I said, you need a reliable way to do this, or have a way open for the user to force recompiling, or both), recompile and save all the shaders to disk again.

 


wrt to GLSL and not standard binary format, what exactly would you be caching ? The said GLSL source ? If so, then what is the benefit of this caching scheme ?.

Yeah, this bit has me confused too.

Share this post


Link to post
Share on other sites

 

Have a way setup to detect GPU and driver version.

 

First time the program is launched, pop in a "compiling shaders" screen (much like Battlefield 2 did), and compile all your shaders saving the binary to disk. Or you could pop in a separate context that compiles and saves the shaders in the background, then make the main context load the binaries.

 

If you don't have that many shaders, you could try to compile them in all their configurations, otherwise just save the ones needed for the current graphics configuration.

 

If user changes drivers/GPU (as I said, you need a reliable way to do this, or have a way open for the user to force recompiling, or both), recompile and save all the shaders to disk again.

 

 


wrt to GLSL and not standard binary format, what exactly would you be caching ? The said GLSL source ? If so, then what is the benefit of this caching scheme ?.

Yeah, this bit has me confused too.

 

 

So which option is preferred? 4 or 5?

Share this post


Link to post
Share on other sites

I'm a big fan of option 4, however, the biggest downside is that the binary will be highly platform specific( even with the same GPU vendor, since difference driver version may tweak the shader compiler/linker which may in turn affect the generated binary. )

Share this post


Link to post
Share on other sites

The problem about option 4 is that it is more vulnerable to uber shader explosion.

 

You might have to cache a same shader for multiple times just because it is involved in multiple programs.

 

SSO shader cache will reduce the size. And I'm not sure if it affects perf,  because we'll have to link during rendering.

Share this post


Link to post
Share on other sites

I'm personally not a great fan of separable programs. Yes, the official IHV point of view is "GPUs have worked that way for years anyway" (quoted from some old nVidia presentation), but linking a program gives the optimizer the opportunity to optimize across stages, say what you will.

Insofar, for me it's between #3 and #4 (using #4 but I'm sure #3 would work just fine anyway).

 

 

Have a way setup to detect GPU and driver version.
That isn't even necessary, luckily it just works (and since it's a lot of trouble and error-prone, I would like to avoid it).

 

The command void ProgramBinary( ... ); loads a program object
[...]
Loading a program binary may also fail if the implementation determines that
there has been a change in hardware or software configuration
[...]
LinkProgram and ProgramBinary both set the program object’s LINK_STATUS to TRUE or FALSE, as queried with GetProgramiv, to reflect success or failure

(Section 7.5 of the OpenGL 4.5 specification)

 

Also, calling glUseProgram will generate INVALID_OPERATION if loading the binary has failed (section 7.3). Thus, there is no reason to query some obscure non-standardized values from the operating system and try to figure out a particular model and driver combination from these. Luckily  smile.png

Share this post


Link to post
Share on other sites


Also, calling glUseProgram will generate INVALID_OPERATION if loading the binary has failed (section 7.3). Thus, there is no reason to query some obscure non-standardized values from the operating system and try to figure out a particular model and driver combination from these. Luckily 
Of cooourse! Checking for GL_INVALID_OPERATION. Why I never thought of it, I'm so silly. Thanks a lot for the info :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!