in the framegen/ subproject, there's two files called context.cpp which have a method called "Context::present".
the comment indicating step 3, calls wait on a fence object. you need to move that entire section to the end of the method, just before frameIdx is increased.
that way, before returning, this code will WAIT until the frames are generated.
then, back where this is being called in the other context.cpp in the main project, you can get the system time via c++ high_resolution_clock before and after calling LSFG_3_1::presentContext. calculate the difference (just ask chatgpt if you don't know how any of this works lol), then see how much longer you need to wait according to whatever time the user selected. so for example if the user selected 25ms and generating took 5ms, then 20ms is what's left over.
then a bit lower in the for loop, right before the call to Layer::ovkQueuePresentKHR you sleep for those 20ms on the first iteration, and the usual 25ms for all following iterations. then you wait 25 ms again after the loop is done so it schedules the real frame properly as well.
that'll give basically perfect frame pacing, but has the chance to massively slow down the game. also change the present mode to immediate/mailbox, there's no need for fifo anymore