Also, in general you don't have such a close binding between assets in the simulation and assets in the hardware.
Generally systems will build an abstraction. Shaders are typically abstracted by a material. The material is used in the simulation's realm. The material may or may not have the shaders actually loaded from disk, and the shaders may or may not be loaded in the card, but the simulation can use the material immediately.
It is similar for all other assets. A mesh is useful on the simulation side, but the actual mesh model may or may not be loaded from the disk, and the mesh model may or may not be loaded in any particular LOD into rendering hardware. A texture on the simulation may have a variety of graphics data loaded, the files may or may not be loaded, the files may or may not be on the graphics card. An audio clip similarly, the actual data may or may not be loaded, and may or may not be streaming.
One conceptual pattern is a store, proxy, cache, and loader, although engines call them by various names. The store, the world, the simulation, basically it's the collection of all the things that exist. When you tell the store to create a new resource object it can immediately return a proxy object for the resource. Telling it to create a material can instantly return an object that serves as a proxy to the underlying shaders even though they haven't been loaded from disk yet. Telling the store to create a mesh can instantly return a mesh proxy before the data file is loaded. Repeat for any other resource, you don't need to actually load the final resource, just have enough metadata to describe what that data file would have when it eventually loads. When the game engine decides you're close enough to actually need the resources, near enough to a graphical thing, near enough to an audio source, or if they're otherwise flagged as important or about to be used, the store uses the cache. First the store can check to see if an instance of the resource is already loaded into the cache, and if not, the resource can be loaded using the loader to open of the data files (locally, across the Internet, from a shared network data store, whatever) and pull them into the cache of loaded resources. It will also likely have different caches for different resources as they'll probably be treated differently, audio is likely to be different from physics data, which is likely different from graphics data. At some point later when you're far enough away, or when all the things are gone from memory, the cache can unload the actual resources from the hardware even though the store still says the proxy objects exist.