GPUs suck at things like e.g. data driven branches. What looks like one shader at a high level ends up creating many separate compiled blobs, because you really want some of the parameters baked in at compile time to avoid the performance tanking, and this means you need to compile a version of the shader for every combination of values those parameters can take.