It is very unnecessary. And the offscreen window approach would be one way to prerender and show very demanding stimuli if everything else fails.
Your approach 1 with async flips also works, iff you enable the imaging pipeline a la…
PsychImaging('PrepareConfiguration');
PsychImaging('AddTask', 'General', 'UseVirtualFramebuffer');
w = PsychImaging('OpenWindow', screenid, 0);
→ The use of the virtual framebuffer gives you that 3rd buffer that you can draw into the next stimulus image while Asyncflip keeps the regular framebuffer busy.
AsyncFlipTest.m demonstrates all kinds of such async flips and approach 1.
If you don’t need your code to run on non-Linux system and use a graphics card with the open-source drivers (== not NVidia with proprietary driver), then PerceptualVBLSyncTestFlipInfo2.m shows how one can draw and flip frames as fast as possible, not waiting for flips to complete, and collect all stimulus onset timestamps later, e.g., at the end of a trial. This allows to pre-queue potentially multiple frames depending on gpu.
But in practice almost certainly none of this matters for your circles, and simple is simpler.
-mario