Please note that SwapBuffers hasn’t neccessarily “finished” all it should, as we may be led to believe.
I have a performance testing piece that has displayed a professional vendors implementation (one of the big two, with probably quite common h/w) sucking over ten million CPU cycles (whether due to spinning on a spinlock or actually doing work I don’t know, and it really was closer to 13e6 IIRC, which @2.4GHz clock was over 5ms!) worth of time for glClear(color|z) after a successful swap unless I added a Sleep() for a while after swapping (artificial test, only to test the speed and overheads of the implementation). If the code did Sleep() between swap and glClear, the clear call “only” took ~13k CPU cycles IIRC (at least it wasn’t anywhere close to even 1e6 CPU clock cycles).
I wrote this to display that what I have previously believed (and likely most of you) that calling glFinish or swapping has measured all of the time - it may not be true. In the case I observed, the time is somehow “amortized” until after the following glClear is completed.
(should there be interest in trying this code locally, if for nothing else to gloat “Haaa haaa, you made an error here!” :-), I could probably boil the source down)