sodium-fabric
sodium-fabric copied to clipboard
Frame presentation should be performed asynchronously
Problem
Minecraft currently blocks the main render thread when waiting on a V-blanking interval (when V-Sync is enabled) or when waiting for the next frame permit to be generated (when the Frame Limiter is enabled.) This is rather unfortunate, because there are a lot of things the renderer could be doing instead of sitting around (such as loading chunks or processing packets.) But, due to memory safety issues, we can't reliably touch those systems from other threads.
In practice, this makes Minecraft's frame pacing quite terrible (especially with V-Sync), since incoming work gets backlogged until the start of next frame, where it competes with rendering tasks for CPU time. It also means that things like chunk loading are effectively dependent on the frame rate, since kicking off new tasks can only be done from the main thread.
Solution
Rather than doing these tasks on other threads, we should instead just kick glfwSwapBuffers
to another thread. The main thread should then check periodically if the buffer swap has completed, and if not, try to find some other work to do in the mean while.
Concerns
On Linux, it is not possible to access the OpenGL context on the main render thread while the presentation thread is executing work. This means that we cannot touch any graphics state waiting on presentation, and that we cannot do things like setting up memory transfers for the next frame (i.e. for buffer compaction or pending chunk uploads.)
Additionally, we need to be careful not to do too much work while waiting on frame presentation, especially in regards to generating chunk meshes. This can result in large amounts of memory being allocated to chunks which are backlogged and waiting to be uploaded to the GPU, which is just going to make frame pacing worse.