My engine is data driven, and I'd expect the same from other big engines. In the game's data files, I declare "stream formats" (how vertex data is laid out on disk / in memory) and "vertex formats" (the input to vertex shaders) and then declare which ones are compatible with each other. Those declared compatible pairs describe the fixed-function config of the input-assembler stage -- a.k.a. vertex declaration / input layout / vertex attribute formats.
These input assembler layouts, and reflection data on the other structures, are compiled from human-readable text into an efficient binary format for the engine runtime.
How do you handle dynamic material assignment at run-time if the loaded stream format doesn't support the required vertex format?