The latest hints from Vulkan and D3D12 developments (VK_EXT_Shader_object[0], D3D12 Work Graphs[1]) suggest there might be an industry move away from pipelines and towards alternative solutions.
Good info, interesting. It does add a layer of complexity that takes a bit more to handle. The point of moving away from stateful/naming was to prevent global state and bugs but you can also run into those in other ways as it is somewhat like going from keyed data to offsets/positions binary data. Rebuilding pipelines also seems heavy.
Maybe the solution is a lower level API (current) and a higher level API (somewhat stateful/named but not so global). That does add extra weight though.
D3D10/11 is the sweet spot IMHO. It splits render pipeline state into a small number of immutable state group objects instead of granular render state toggles (like OpenGL or that new Vulkan extension), or an all-in-one rigid pipeline state object (like WebGPU or Vulkan).
Those D3D11 state objects are roughly: rasterizer-state, blend-state, depth-stencil-state, (vertex-)input-layout, and one shader object per shader stage.
> They used to be all "stateful" global state like OpenGL/OpenGL ES
Not at all.
Glide and others before IrisGL became OpenGL and Doom helped miniGL get widespread adoption weren't.
Most game console 3D APIs never were, DirectX also never was.
WebGL and WebGPU also show some of the difference in how rendering libraries have evolved. They used to be all "stateful" global state like OpenGL/OpenGL ES. WebGL followed that model as it was simple and needed for the time, but could have bugs if correct flags weren't set.
WebGPU and other newer rendering libraries (Vulkan, Metal, and Direct3D 12) are more "modern" in that they have almost no global state. They are also more raw and lower level and take a bit more to grok.
This is one of the best overviews of the differences between WebGL/WebGPU but also is similar to how OpenGL to Vulkan, Metal, and Direct3D 12 evolved.
https://webgpufundamentals.org/webgpu/lessons/webgpu-from-we...
> The biggest difference is WebGL is a stateful API and WebGPU is not. By that I mean in WebGL there is a bunch of global state. Which textures are currently bound, which buffers are currently bound, what the current program is, what the blending, depth, and stencil settings are. You set those states by calling various API functions like gl.bindBuffer, gl.enable, gl.blendFunc, etc…, and they stay what you set them globally until you change them to something else.
> By contrast, In WebGPU there is almost no global state. Instead, there are the concepts of a pipeline or render pipeline and a render pass which together effectively contain most of the state that was global in WebGL. Which textures, which attributes, which buffers, and all the various other settings. Any settings you don’t set have default values. You can’t modify a pipeline. Instead, you create them and after that they are immutable. If you want different settings you need to create another pipeline. render passes do have some state, but that state is local to the render pass.
> The second-biggest difference is that WebGPU is lower level than WebGL. In WebGL many things connect by names. For example, you declare a uniform in GLSL and you look up its location
> `loc = gl.getUniformLocation(program, 'nameOfUniform')`;
> Another example is varyings, in a vertex shader you use `varying vec2 v_texcoord` or `out vec2 v_texcoord` and in the fragment shader you declare the corresponding varying naming it `v_texcoord`. The good part of this is if you mistype the name you’ll get an error.
> WebGPU, on the other hand, everything is entirely connected by index or byte offset. You don’t create individual uniforms like WebGL, instead you declare uniform blocks (a structure that declares your uniforms). It’s then up to you to make sure you manually organize the data you pass to the shader to match that structure.
> Note: WebGL2 has the same concept, known as Uniform Blocks, but WebGL2 also had the concept of uniforms by name. And, even though individual fields in a WebGL2 Uniform Block needed to be set via byte offsets, (a) you could query WebGL2 for those offsets and (b) you could still look up the block locations themselves by name.
For a time, supporting four rendering engines did cause lots of work for game engines, much more integration and abstraction. As OpenGL support fades at least one will drop off. I will miss it as I do still love OpenGL/WebGL and in many cases the global state is more simple, but to take advantage of GPUs and rendering lower level the innovations were needed. The naming to index/position based for instance is lower level and can also end up in bugs just as the global state in GL could. The benefit is performance and cleaner global state.