arly said:
So the key point here is to get more optimal shader out of the user's computer? Also I heard about this SPIR-V, but only to get pre-compiled shaders though (for example, glslc to SPIR-V bytecode binary file), but I barely understand the potential usage outside of it. Like, if you say “it's not available everywhere”, do you mean it's not available on users' computers, and if they do have it, we can let the SPIR-V in their device to compile it?
SPIR-V is not machine code any GPU could execute. Similar to DXIL for DirectX, it is just another ‘programming language’ (actually ‘byte code’) the GPU driver needs to compile to the final machine instructions on the client.
So the pipeline actually goes like: Transpile GLSL high level language to SPIR-V byte code (lower level, hardly readable by humans), then - by the GPU driver - eventually transpile the byte code to some other, proprietary byte code GPU IHVs use internally, then finally compile the machine code from that.
Notice there are about two transpiling steps involved, which means to translate from one language to another, but not the machine language the hardware could actually run.
On PC there is no way to avoid this. For example, NVidia does not even specify their machine code instructions. So the only way to execute anything on a NV GPU is to use their compiler coming with their (black boxed) drivers and software.
That's a very different situation from what we have on CPU, where the instruction set is public and standardized, and we have many compilers available to choose from.
We currently have a similar case with the BVH used for ray tracing, but here it gives a real problem: The BVH data structures are black boxed and not specified. So we can not access and change the data, nor can we precompute BVH and stream it from disk.
We must generate the BVH at runtime, which has a high cost. And because we can't change the BVH data, we can not have any fine grained LOD solution with ray tracing.
Any time a small patch of surface for our model changes detail, we need to regenerate the BVH for the whole model, since there is no option for local BVH updates given by APIs. Because it's likely that all models change some of their detail as we move through the scene, so we have to rebuild the BVH for the entire scene each frame, which is not possible in realtime. In other words: Raytracing API design was a total failure. It's actually preventing any progress on the still open LOD problem, which isn't less important than lighting.
That's why UE5 Nanite geometry can't be traced, and Epic has to use low poly proxies without LOD instead. That's likely also why we still see no competitor to Nanite from other engine makers - they better wait until the amateurs at MS and NV fix their broken API design or lift black boxes.
That just said to illustrate that shader compile times are not that much of a problem. There are much bigger and similar problems, but people don't notice them since they don't know what they miss.
arly said:
Speaking of shader cache and shader configuration, in context of Vulkan for example, is this what the VkPipelineCache is all about? Creating Pipeline State Objects (PSOs?) can be cached and, if found, reused when needed? Also, this happens after we compile the shaders first, right? What I'm saying is, correct me if I'm wrong, there are two things that can happen during runtime (though probably not in order), which is compiling the shader modules, and creating the pipelines IF they aren't cached or aren't created the first time, is that it? So we got 1) shaders to compile and save and 2) pipelines to cache, whenever they are needed?
Yeah that's right. Maybe worth to mention that you likely need to recompile shaders if users update their graphics driver.
arly said:
So I assume to balance this, it's in between of either trying to get the best looking game where the dev needs to throw in all possible shader permutations to get the look that the artists want in any possible device at any possible moment in the game, or to limit the shader capability to reduce the amount of the combinations significantly, say creating 2D game where it's all sprites, as an extreme example. Hmm…
One cause of the problem is that shaders (source code) is currently treated like content. Shaders are basically assets. Artists generate them like textures on the fly, so their number tends to become large.
That's maybe not how it should be. Alternatively we could setup a limited number of material options the artists can choose from. And then they have to work with that, without an option to create new materials on demand, needed just for a single model.
However, that's what people often try to do already. We try to find good compromises, but still compile times became a problem.
Personally i look at it this way: We got rid of loading times, but now we have traversal and compiler shutters. Nothing comes for free, and we have to live with that.