EEVEE shader compilation process information needed

Sorry if my question is too silly, I don’t have any technical knowledge.
Could that cache data permanently saved in the .blend file for the shaders that exist there? Or better yet, that cache data saved for all the shaders that you have added to your Asset manager in Asset manager data folder?
Or that could make .blend files size and disk space too big?

That OpenGL driver cache is outside of Blender’s control, and it can take up significant disk space. It’s also specific to the hardware and driver version, for example upgrading the graphics driver may clear the cache for things to work correctly.

2 Likes

Sounds like I need to head over to Khronos and beg for smarter glsl re-use.

Acording to 3di it seems they are encountering the long compile time the first time they load up blender. It seems like it is not getting saved for them.

Ah, Would make sense if they are just plugging the same group node into the output of both materials. I just figured that certain vendors might have done some more fine grained optimizations.

Khronos just writes the specification. It’s up to the manufacturer’s drivers to implement it.

That’s right, it’s recompiling every time you paste an object into an empty scene. Opening an existing file doesn’t recompile on open though. Suggesting either blender is storing the required info and not opengl, or opengl is only using cached glsl if it’s associated to the same .blend file.

It wouldn’t be associated with any blend file or anything in blender. The cache would be a global thing associated with an application.

I wonder why opengl only uses cached version in existing blend file and not new .blend file.

There is clearly something else going on there. Are you closing blender every time you create a new blend file?

I’m opening a new instance of blender, ctrl c from the existing file in which the material has already compiled, than ctrl v the object into the new instance. It results in recompile of the shader, suggesting it’s nothing to do with opengl, and more to do with Blender?

Wait, I think I misread what you are doing. So it seems you have two instances of blender open, and are trying to copy and paste between sessions, correct? Those sessions are probably not going to be sharing the same running cache and one of them might not even have permission to open the saved cache (if there is any) at all. Try to limit it to a single instance.

I think Brecht was saying that because it’s openGL that’s responsible for the re-use of cache of group, that the cache is available for days at a time, completely unrelated to the session of Blender.

If I close all sessions of Blender, then start a new session and open a file which has materials in it that have already compiled, then it doesn’t recompile. So it looks like it’s not related to the session, and because it’s still recompiling in a new file, that suggests it’s not related to OpenGL, looks like the cache is existing within the .blend file…

The cache is not in the blend file.

If I close all sessions of Blender, then start a new session and open a file which has materials in it that have already compiled, then it doesn’t recompile.

That suggests that it is trying to save/load the shader cache to and from a file on disk. Those multiple sessions appear to be going without any previous cache due to file permissions with multiple instances trying to access the same file.

not the opengl cache, but some other cache which blender is able to use to speed up the shader compilation.

There are two parts to the compilation. The shader graph to GLSL code that Blender does, and GLSL code to hardware instructions that the OpenGL driver does. Both have a performance impact.

The existence and implementation of caching at the OpenGL driver depends on the driver. I’m saying it may cache to disk, but I don’t know if it does for your particular GPU / driver / shader code.

1 Like

when blender shows compiling shaders, is that the part which is converting shader graph to GLSL? Or does that encompass both shader graph to glsl and glsl to hardware instructions?

I’m just thinking if that 26 seconds of compiling shaders is predominantly used for converting the shader graph to glsl, then perhaps it might be possible to save and reuse a groups glsl rather than recompiling it if it hasn’t change (during the first stage of compilation at Blender’s side)

1 Like

It’s only the GLSL code to hardware instructions as far as I know, that tends to be the slowest part.

1 Like

Another question.
I understand that both GPU and CPU are involved in the process of shader compilation. When I monitor use of them, it is clear that a single thread of the CPU is involved at 100%, but GPU utilization varies only from 5% to 50%. If it weren’t because with the same CPU I noticed that shader compilation takes much longer with intel iGPU than with nvidia GTX 960, I would have said that GPU use is not intensive for this, but GPU has influence apparently.

Anyway, can this be even better optimized? Could this task be a multi-threaded CPU process one day and will it improve shader compilation times?

1 Like

The CPU runs the compiler, the GPU just gets fed the finished machine instructions. There are likely other factors why certain GPUs and drivers might be slower during this process that does not necessarily equate to overall performance. OpenGL is a heavily single threaded API from before multi-threading was really a thing and has aged quite a bit, hence why Vulkan exists. So yes, when blender moves to Vulkan, multi-threaded shader compilation and pipeline creation is very much a recommended and doable optimization for compiling more pipelines and shaders at a single time. Not sure if there are any viable fixes over GL in the meantime.

1 Like

@brecht I’ve posted on the Khronos forum, and one of the senior members is asking the below. Are you able to answer any of these questions?

I’ve seen very large GLSL shader programs (all stages) with a lot of unused bloat in them that take ~300-500 ms to compile+link. But 30 seconds is outrageous,

You should dig into this and see what Blender’s doing for all that time.

  1. How long is its shader graph -to- GLSL conversion taking?
  2. How long is it taking to compile the GLSL source code for the shader stages in a single program?
  3. How long is it taking to link the compiled shader objects into that single shader program?
  4. Is it generating+compiling+linking a bunch of shader programs rather than just one? How many?
  5. Is it sending a lot of unused bloat in the GLSL source code (**)?
  6. What CPU and GL driver is this on?

If I were you, I’d want to know.

** Re bloat. I’m talking about lots of comments and uncalled/unexecuted code in the GLSL which adds needless content that the GLSL compiler has to wade through, parse, and ultimately just chuck into the bitbucket.

If you can, get a hold of the GLSL source for the shader stages in that program (prob just vertex and fragment) and post it if you can. I’d like to see this.

More correctly, adding a single node results in Blender demanding that OpenGL recompile the entire GLSL shader to machine code again, from scratch.

Is Blender using separate shader objects? Or shader subroutines? Or assembly shaders (including SPIR-V)?

Or is it re-providing new GLSL source code for the entire shader program to OpenGL to compile and link at runtime, where the graphics driver has no choice but to do exactly what the application demands.

Also re the comments in that Blender thread you linked to about a “shader cache”… Blender could read back compiled+linked shader binaries and save them off, forming its own cache, stored someplace such as in the .blend file or associated file (e.g. see ARB_get_program_binary). But if I infer correctly from that thread, they’re implicitly saying Blender does not do this but instead hopes/expects that the OpenGL driver implements some kind of compiled GLSL shader program cache like this. Some do.

It’s premature at this point to jump to this as a potential solution (because we don’t really know what the problem is yet). But just FYI…

The GPU vendors stopped supporting ARB assembly shaders years ago. NVIDIA held out until just a few years back with their vendor-specific (NV) assembly shaders, but recent GPU features are no longer supportable through that assembly language; they’ve switched to SPIR-V. So you won’t be patching those assembly shaders anymore if you want cross-GPU support or support for the latest features.

SPIR-V assembly is another possible option GL supports for loading shaders (bypassing the need to compile GLSL in the GL driver). But it doesn’t support some important GL features like bindless texture, so that makes it a non-option for some GL users.

Without re-generating shaders at the assembly level, you make the most of the support you’ve got through the GLSL high-level shading language. Let’s see how effective Blender’s use of it is

2 Likes

Remember to make sure you have your graphics drivers up to date before chasing any rabbits here. If that is the issue it can be frustrating to people trying to debug your issue.

26 seconds is EXTREMELY BAD for shader compilation times in most development environments, but I know I have waited longer on UE3/4 to compile a single shader than 500ms (could be mostly overhead though). Blender materials in particular can get absurdity taxing on fragment shader instruction count when the artist makes ample use of procedural noise/bump mapping, Blender can kind of go off the deep-end past any reasonable shader for games/visualization there. It’s not out of the question that the shader is just that ridiculous enough to cause those compile times on your machine.

Maybe you could share a .blend/screenshot of the node graph which is causing this slowdown?