1
function VBLSyncTest(n, numifis, loadjitter, clearmode, stereo, flushpipe, synchronous)
2
% VBLSyncTest(n, numifis, loadjitter, clearmode, stereo, flushpipe, synchronous)
1
function VBLSyncTest(n, numifis, loadjitter, clearmode, stereo, flushpipe, synchronous, usedpixx)
2
% VBLSyncTest(n, numifis, loadjitter, clearmode, stereo, flushpipe, synchronous, usedpixx)
4
4
% Tests syncing of PTB-OSX to the vertical retrace (VBL) and demonstrates
5
5
% how to implement the old Screen('WaitBlanking') behaviour with
90
90
% compatible stereo display hardware, e.g., CrystalEyes shutter glasses.
94
93
% flushpipe = Mark end of drawing commands to improve presentation timing.
95
94
% PTB knows a new command Screen('DrawingFinished') which, when properly used,
96
95
% will give PTB hints on how to optimize drawing of stimuli: This allows to draw
106
105
% but degrades performance significantly in real experiments.
108
% usedpixx = 1 Use a DataPixx/ViewPixx/ProPixx device for external
109
% timestamping of stimulus onset, as a correctness test for Screen('Flip')
110
% timestamping. Disabled (0) by default.
111
115
% VBLSyncTest(1000, 0, 0.6, 0, 0, 1, 0) -- Render 1000 consecutive frames,
200
204
%%% VBLSyncTest(1000, 0, 0.6, 0, 0, 1, 0)
206
if nargin < 1 || isempty(n)
210
if nargin < 2 || isempty(numifis)
214
if nargin < 3 || isempty(loadjitter)
218
if nargin < 4 || isempty(clearmode)
222
if nargin < 5 || isempty(stereo)
226
if nargin < 6 || isempty(flushpipe)
230
if nargin < 7 || isempty(synchronous)
234
if nargin < 8 || isempty(usedpixx)
231
239
% This script calls Psychtoolbox commands available only in OpenGL-based
232
240
% versions of the Psychtoolbox. (So far, the OS X Psychtoolbox is the
234
242
% an error message if someone tries to execute this script on a computer without
235
243
% an OpenGL Psychtoolbox
247
% Enforce use of DWM on Windows-Vista and later: This simulates the
248
% situation of Windows-8 or later on Windows-Vista and Windows-7:
249
Screen('Preference','ConserveVRAM', 16384); % Force use of DWM.
238
252
% Get the list of Screens and choose the one with the highest screen number.
239
253
% Screen 0 is, by definition, the display with the menu bar. Often when
240
254
% two monitors are connected the one without the menu bar is used as
241
% the stimulus display. Chosing the display with the highest dislay number is
255
% the stimulus display. Chosing the display with the highest display number is
242
256
% a best guess about where you want the stimulus displayed.
243
257
screens=Screen('Screens');
244
258
screenNumber=max(screens);
250
264
% Open double-buffered window: Optionally enable stereo output if
252
w=Screen('OpenWindow',screenNumber, 0,[],32,2, stereo);
266
PsychImaging('PrepareConfiguration')
268
% Use DataPixx for external timestamping for quick basic correctness
270
PsychImaging('AddTask', 'General', 'UseDataPixx');
272
w=PsychImaging('OpenWindow',screenNumber, 0,[],[],[], stereo);
254
274
% Query effective stereo mode, as Screen() could have changed it behind our
255
275
% back, e.g., if we asked for mode 1 but Screen() had to fallback to
371
% Ask for a Datapixx onset timestamp for next 'Flip':
372
PsychDataPixx('LogOnsetTimestamps', 1);
349
375
% Flip: The clearmode argument specifies if flip should clear the
350
376
% drawing buffer after flip (=0 - default), keep it "as is"
351
377
% for incremental drawing/updating of stims (=1) or don't do
363
389
% beampos > screen height means that flip returned during the VBL
364
390
% interval. Small values << screen height are also ok,
365
391
% they just indicate either a slower machine or some types of flat-panels...
366
[ tvbl so(i) flipfin(i) missest(i) beampos(i)]=Screen('Flip', w, tdeadline, clearmode);
392
if usedpixx && IsOctave
393
% Workaround for Datapixx + Octave bug in January 2013 ptb:
394
tvbl = Screen('Flip', w, tdeadline, clearmode);
397
[ tvbl so(i) flipfin(i) missest(i) beampos(i)]=Screen('Flip', w, tdeadline, clearmode);
368
% Special code for debugging: Disabled by default - Not for pure
401
% Ask for a Datapixx onset timestamp from last 'Flip':
402
[boxTime, sodpixx(i)] = PsychDataPixx('GetLastOnsetTimestamp'); %#ok<ASGLU>
405
% Special code for DWM debugging: Disabled by default - Not for pure
370
if IsWin & 0 %#ok<AND2>
372
winfo = Screen('GetWindowInfo', w); %#ok<NASGU>
373
% fprintf('QUERY %i : t = %0.10f : LastVBL = %0.10f : VBLCount = %i\n', i, GetSecs, winfo.LastVBLTime, winfo.VBLCount);
374
wdminfo = Screen('GetWindowInfo', w, 2) %#ok<NOPRT>
410
WaitSecs('YieldSecs', 0.001);
411
wdminfo = Screen('GetWindowInfo', w, 2);
378
if (i > 1) && (tSecondary(i-1) == wdminfo.OnsetVBLTime)
379
% fprintf('DELAYED: %i %0.10f \n', i, wdminfo.OnsetVBLTime);
383
%fprintf('---> tnew - told = %0.10f \n', wdminfo.OnsetVBLTime - tSecondary(i-1));
386
tSecondary(i) = wdminfo.OnsetVBLTime;
413
if ~isstruct(wdminfo)
417
if wdminfo.cDXPresentConfirmed == wdminfo.cDXPresentSubmitted
418
tSecondary(i) = wdminfo.qpcVBlank - ((wdminfo.cDXRefresh - wdminfo.cDXRefreshConfirmed) * wdminfo.qpcRefreshPeriod);
419
tvbl = tSecondary(i);
420
so(i) = tSecondary(i);
397
426
% Record timestamp for later use:
510
539
fprintf('Average discrepancy between DWM and beamposition timestamping is %f msecs, stddev = %f msecs.\n', mean((tSecondary - so) * 1000), std((tSecondary - so) * 1000));
544
plot((so - sodpixx) * 1000);
545
title('Time delta in msecs onset according to Flip - onset according to DataPixx:');
546
fprintf('Average discrepancy between Flip timestamping and DataPixx is %f msecs, stddev = %f msecs.\n', mean((so - sodpixx) * 1000), std((so - sodpixx) * 1000));
513
549
% Count and output number of missed flip on VBL deadlines:
516
554
if (stereo == 11) && (numifis == 1)
517
555
% Special case: Stereomode 11 can't do better than one swap
523
561
if (ts(i)-ts(i-1) > ifi*(numifis+0.5))
524
562
numbermisses=numbermisses+1;
565
if (ts(i)-ts(i-1) < ifi*(numifis-0.5))
566
numberearly=numberearly+1;
529
571
% Special case: Stereomode 11 can't do better than one swap
535
577
if (ts(i)-ts(i-1) > ifi*1.5)
536
578
numbermisses=numbermisses+1;
581
if (ts(i)-ts(i-1) < ifi*(numifis-0.5))
582
numberearly=numberearly+1;
541
587
% Output some summary and say goodbye...
542
588
fprintf('PTB missed %i out of %i stimulus presentation deadlines.\n', numbermisses, n);
543
589
fprintf('One missed deadline is ok and an artifact of the measurement.\n');
591
fprintf('PTB completed %i stimulus presentations before the requested target time.\n', numberearly);
593
fprintf('CAUTION: Completing flips too early should *never ever happen*! Your system has\n');
594
fprintf('CAUTION: a serious bug or misconfiguration in its graphics driver!!!\n');
544
596
fprintf('Have a look at the plots for more details...\n');
548
600
% This "catch" section executes in case of an error in the "try" section
549
601
% above. Importantly, it closes the onscreen window if its open and
550
602
% shuts down realtime-scheduling of Matlab:
552
605
% Disable realtime-priority in case of errors.
554
607
psychrethrow(psychlasterror);