You really just need to dump textures and set up a matching context, which at worst should require an indirection shim to translate handles if they are stored by the application but generated by the driver with no way to force custom values during object creation (like how Linux allows custom PIDs for checkpoint/restore and other replay tech like rr).
Even if have a perfect wrapper that achieves all that you now have to save all application-supplied texture and shader data in the original form even where that memory could normally be freed after translating it to GPU-specific formats.
But "restricting yourself to a shared subset of OpenGL" alone already makes this unviable for anything demanding as it also means restricting yourself to the lowest common denominator for all limits including VRAM size, maximum texture sizes, essentially guaranteeing your solution to run worse on both systems.
The texture size issue I don't see as a problem (I thought we grew out of that being an issue years ago?), and the VRAM issue shouldn't be that hard, as games tend to not use spare VRAM for dynamic time-memory tradeoffs (unlike OS kernels with their pagecache).
On top of that, it's not like you need this functionality to deliver top performance from games that don't want to play their part to make this efficient. Working seamlessly at "just" 30% less FPS should already be very useful.