Error: Synchronization Failure

One thing to watch out for with WinTel setups is triple-buffering. Triple-buffering might be active even though it is neither advertised nor can it be disabled. In such a case, I found the following workaround useful:

kPsychBusyWaitForVBLBeforeBufferSwapRequest = 2^15;  
Screen('Preference', 'ConserveVRAM', kPsychBusyWaitForVBLBeforeBufferSwapRequest);

However, this workaround adds a consistent one-frame delay at the output, which is and cannot be detected by PTB, and it burns CPU time. But otherwise, the PTB flip timing is reliable and timestamps are consistent - well, at least with the single-screen setup I have tested. Note that programs that rely on swapping between only 2 buffers on a higher level, e.g. when preserving the information in the buffers for reusing it in subsequent frames, might need further tweaking for making them triple-buffer safe.

Here is a program that makes triple-buffering visible:

function TripleBufferCheck
% Check for triple buffering. 
% First, the program draws a patch in 3 consecutive frames at 3 positions on the screen - 1:left, 2:mid, 3:right.
% Then the program just flips between the buffers for a few seconds, without clearing the buffers in between.
% If there are only 2 buffers (aka double-buffering), we will see the patches flickering between 2 positions. 
% Otherwise, if we have triple-buffering, we will see patches flickering between all 3 positions. 
% There is also a small square at the top left that changes color while flipping.

    SCREEN_NO = 0;
    clear Screen
    Screen('Preference', 'VBLTimestampingMode', -1);    
    Screen('Preference', 'Verbosity', 3);
    Screen('Preference', 'VisualDebugLevel', 0);
    Screen('Preference', 'SkipSyncTests', 1); 
    try
        wnd = Screen('OpenWindow',SCREEN_NO,0);
        [w,h] = Screen('WindowSize', wnd);
        %--- Hide the mouse cursor, just in case there is some interference  
        %    between cursor drawing and buffering.
        HideCursor();
        for x=-1:1
            %--- Be sure that there are no pending flips anymore (at a very low 
            %    level). Don't rely on what PTB thinks is going on, because this 
            %    might be wrong due to triple-buffering.
            WaitSecs(50e-3,'YieldSecs');
            Screen('FillRect', wnd, 0);
            Screen('FillRect', wnd, 255, repmat([w/2+w/3*x,h/2],1,2) + w/16*[-1,-1,1,1]);
            Screen('Flip', wnd, 0, 2);
        end
        %--- Cycle through the buffers for a while in a consistent way, i.e. without 
        %    flipping potentially too fast for making every buffer show (with 
        %    triple-buffering, flip synchronization won't work correctly).
        alarm = GetSecs() + 4;
        while GetSecs()<alarm
            WaitSecs(50e-3,'YieldSecs');
            Screen('FillRect',wnd, round(rand(3,1)*255), [0,0,20,20]);
            Screen('Flip', wnd, 0, 2);            
        end
        ShowCursor();
        sca();
    catch e
        ShowCursor();
        sca();
        rethrow(e);
    end
end