Haven't checked DX12 yet, but both D3D11 and Metal have a small number of "tiers" with guaranteed feature sets, which basically correspond to GPU generations. Usually you pick the lowest tier you can afford and write your code against that feature set.
In D3D11, the "tier" is basically the minor version number (D3D11.1, .2, etc...), while in Metal you have this handy reference:
https://developer.apple.com/metal/Metal-Feature-Set-Tables.p...
Both solutions prevent the "combinatorial explosion" of OpenGL or Vulkan extensions.