For an in-depth study of latency in games, Mick West is the undisputed master. Read these two articles first, and it will make everything else make so much more sense.
There are two aspects to this. The first, which you've picked up on, is the latency between an instantaneous control input (e.g. a button press), and the time at which the user perceives the effects of that action. The firing of a gun is usually the best example of this as it's easy to measure. There are many contributing factors to this, most of which are completely out of your control. Worse, it's a cumulative effect, so if each stage is introducing a bit of latency, it can all mount up to lead to severe overall latency. Different types of latency you'll see:
- display latency (how long between a frame being presented at the input and the pixels on the screen changing to reflect that frame)
- GPU /sync latency (how long between you calling Present and the input being presented to the display, usually tied to framerate, e.g. at 30fps there may be anywhere from 0-32ms between calling Present and the next VSync where the GPU output would change)
- buffering latency (you've pointed this one out - frames prepared based on the world state from previous frames because rendering takes so long it's more efficient to have the rendering being done while the next frame is being prepared)
- processing latency (time between input being sampled, usually at the start of an update cycle, and the results of that input being reflected in the world state used by the rendering)
- input latency (if your input devices don't immediately reflect the live state, it's possible your input sampling is actually based on the state some time ago. That's pretty rare nowadays, but depends on what input devices you're talking about)
Sadly, there aren't many good answers as to how to minimise display latency. The most obvious answer to display latency is don't buffer frames. The rest of the chain of latency is out of your control, but this one isn't. You can choose to render less, and forego maximising your GPU/CPU parallelism, in favour of reduced latency. The next obvious answer is: render at 60Hz instead of 30Hz. That will cut your sync latency to 16ms. Again, to achieve that, you'll either have to render less, or render smarter. If you are running at just over 60Hz most of the time, but occasionally drop down, then rather than live with the massive hit of dropping to 30Hz, you can turn off lock-to-VSync, and live with those horrible screen tearing artifacts when you do take too long to render. However none of those options are great if you also want to make best use of your rendering power, which is why pretty much every modern game engine you see will buffer frames, and most of which run at 30Hz.
The second aspect relates to latency as a result of your simulation. Imagine a character jump. The user presses the jump button at time 0. If the visual feedback for jumping was just that the entire screen flashed yellow, then the latency would be purely based on your display chain (input -> processing -> rendering -> presenting -> displaying). With minimal processing, at 60Hz, on a CRT with minimal display lag, you could in theory see the yellow screen in about 30-40ms after your button press (less than one 16ms frame for input -> processing -> render, present on the first VSync at 16ms sharp, then the CRT displays some time after that).
Now imagine more typical visual feedback: the character animates - winds up and jumps. How many frames of animation does the character go through before they are obviously jumping? If it's more than 2 or 3, the simulation will feel 'laggy', not because the input isn't being processed immediately, but because the results of the input take some time to become obvious in the visual feedback.
This leads us to one of the better ways to make your game feel more responsive: run your simulation at 60Hz (or higher if you can). Even if you can't simulate and render at 60Hz, simulate (and sample input) at 60Hz anyway, and render based on the interpolated game state at any given point. You cannot avoid display latency, it will always be there, even if you try to minimise it. By decoupling your input / simulation loop from the rendering, you can sample input more frequently, and get more responsiveness in your physics, etc. As to why this is better? Read Mick's final paragraph in the original article on responsiveness: it's not so much about the player's reaction to what they see, as it is the games speed of reaction to what the player is doing. At a higher simulation speed, the game will react to the player more quickly. But there are other reasons to like a higher frequency simulation as well. Physics especially likes a smaller time-step, because there are fewer collisions and other discrete events per time-step that need resolved.
One of the nice things about that is if you do have a render-heavy system, you can actually drop the render rate to 20Hz and make use of that time, without the simulation part having problems because of the long slow time-steps. Of course, a 20Hz rendering will only make the display latency problem worse, I just throw it out there as a possibility once you've shifted to a decoupled simulation/render system.