A lot of times you simply don't understand what the program is even trying to implement, so you fail to understand the codebase. You have to understand what is being implemented: the inputs and outputs of the codebase. For example, if you want to tackle a graphics driver, you should probably learn the API that it's implementing (OpenGL, Vulkan, Direct X 12, etc.), which is the input to the system, and you should also learn the OS and Hardware interfaces, which are the output to the system.<p>Every time you need to learn a subsystem of the codebase, the same concept applies. Learning the shading language compiler? Well, learn the shading language itself and then learn the Hardware's programming interface for shaders. Learning memory management? Learn how programs manage their memory, learn how the hardware managers memory. And so on.<p>Want to dive into a library? Well, learn how to use the library. Then learn whatever interface the library is on top of. Then imagine how you would implement the library yourself, that should give you a gigantic idea of how the library works and you would probably start recognizing what each piece of the code does.<p>Also, ctags, cscope and Vim's ctrl+] are essential.