I have been using OpenGL and Directx11 extensively for my engine. The thing is, when I wanted to support DX12 or Vulkan, I realized that they collect all the state data in one place, removing the update of different states altogether.

This causes a problem. Let's say I have 5 different mesh layouts, 300 different materials and 5 different framebuffers with different formats. So as far as I understand, I should create a 5x300x5 different pipelines in order to support the drawing of all the permutations.

This bugs me. It forces you to create all of your data statically in the editor time.

Let's consider if I created a different lighting method, and I wanted to spawn my light at runtime. My light uses a different format from the existing lights in the scene. So what happens? I froze the game for 0-x milliseconds to compile all of the permutations just for my newly instantiated light?

I hope I'm missing something out here. Because I don't like the idea of forcing me to create all the permutation of the possible pipelines before building the game into a separate executable.

Although this does not end with the game runtime. Whenever I create a different mesh layout or import different mesh layout from .obj/.fbx file, I should create all the necessary pipelines for these mesh layouts.

Which begs further questions, questions like should I manage my existing mesh layout-material-framebuffer registry every time I begin to render.

I feel like it will demand a high level maintenance for creating the required pipelines and accessing the existing pipelines.

Before it was like

Iterate each camera
Iterate each mesh renderer
Get mesh and material data and render

and now how should I manage the rendering?

Iterate each camera
Iterate each mesh renderer
Get the pipeline using the mesh renderer's material and mesh ID combinations?
Use pipeline and render

What happens when mesh renderer's material and mesh fields changes? Should I detect and switch pipelines for that renderer?

I feel like Vulkan and Directx12 is a let down in this regard. I understand that they offer an extensive control over the device, unlike OpenGL, but it feels like it's restricting me.

I'm curious about what your inputs will be. Please feel free to give any type of feedback.


2 Answers 2


This is a known problem with the new APIs: https://forum.beyond3d.com/threads/shader-complilation-on-pc-about-to-become-a-bigger-bottleneck.61929/

Vulkan is evolving solutions for it via extensions, such as VK_EXT_graphics_pipeline_library, which contains a statement and acknowledgement of the problem:

The original promise of monolithic pipelines in Vulkan was to enable developers to construct all their state up front, avoiding the driver doing dynamic compilation and patching shaders implicitly when recording draw calls, resulting in unexpected hitches.

The reality however is that for many game engines, requiring most of this state up front either fails to eliminate hitching, or requires precompiling so many state combinations that the size of the pipeline cache is nearly unmanageable.

Games engines are typically still managing enormous sets of state and shader combinations, and this is not a purely technical problem. It is still expected and encouraged that developers will limit the number of these, but it doesn’t change the fact that at least in the short-to-mid-term, developers are having real problems that can’t be solved by telling them to reduce the number of pipelines.

Until these solutions become commonplace, you're mostly stuck with workarounds for the problem, such as:

  • Consider if you actually need all of the permutations; there are probably permutations that it doesn't make sense to use together, and you surely don't need all 300 materials for each mesh you create.

  • Use shader uniform values of 0 or 1, or 1x1 black or white textures, to allow you to combine permutations and reduce the number that way.

  • Only create each permutation as it's needed, the first time it's used, at a cost of some runtime hitching and stalling.

  • Decide that Vulkan or DX12 don't meet the requirements of your program and continue using the old APIs.

  • Anything else that makes sense in the context of your program.

  • \$\begingroup\$ How long do you think OpenGL and Directx11 will be considered as ABSOLUTE obsolete? \$\endgroup\$
    – Roveldo
    Commented Jul 21, 2022 at 11:30
  • \$\begingroup\$ @Roveldo - I don't understand what you mean by "ABSOLUTE obsolete", but I will observe that Vulkan was never intended as a one-size-fits-all replacement for OpenGL. They're two different solutions for two different problem spaces, and there's a huge amount of legacy OpenGL code that guarantees OpenGL will still be around and supported for a long time. As for DX11, Microsoft tend to evolve their APIs differently, but it's worth noting that even old D3D8 or 9 programs will still work today. \$\endgroup\$ Commented Jul 21, 2022 at 11:37
  • \$\begingroup\$ That's exactly what I meant from "ABSOLUTE obselete". Apple moving towards Metal which is by definition similiar to Mantle thus similiar to Vulkan. I dont know if Metal too uses this restricting pipeline objects. It seems future belongs to these pipeline objects. \$\endgroup\$
    – Roveldo
    Commented Jul 21, 2022 at 11:58
  • \$\begingroup\$ I don't know that it's fair to call the PSO model restricting; it might be fair to observe that people did want it, but maybe didn't fully understand the implications of using it on PC hardware, and as a result it's a mismatch for the way people actually work. As I said, the ARB are already taking steps to address this via Vulkan extensions, and the drawbacks of it are generally recognized. \$\endgroup\$ Commented Jul 21, 2022 at 14:16

It may feel inconvenient, but precompiling all pipeline permutations ahead of time is how Vulkan was designed to be used. Compiling pipelines is expensive, and if you are able to do it all up-front it's worth doing so. If you still want to do JIT compilation, Vulkan offers "pipeline cache" objects that can let you serialize your shader permutations so that the majority of your permutations will be loaded, and only permutations that weren't captured by the cache are JIT-compiled.

Arseny Kapoulkine (Zeux) wrote a good article about this problem and the various solutions to it here (scroll down to "Pipeline Objects").


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .