Unexpected vsync behaviour with waitBlanking=False

Hi everyone,

I’ve been trying to get an experiment to run without vertical sync (by setting waitBlanking=False during window creation). However, no matter what waitBlanking is set to the main loop is locked to a 60Hz frame rate. Here’s a reasonably minimal reproducible example:

from __future__ import absolute_import, division
from psychopy import gui, visual, core, data, event
import pyglet

# full_screen, backend and vsync are the 3 variables we're looking at
full_screen = True
backend = "pyglet" #'pyglet', # 'pygame', #'glfw',
vsync = True

win = visual.Window(fullscr=full_screen,
                    winType=backend,                     
                    waitBlanking=vsync,
                    monitor='testMonitor', color=[-1,0,-1], colorSpace='rgb', blendMode='avg', 
                    mouseVisible = True, allowGUI=False)
    
print ("Monitor refresh time is ", win.monitorFramePeriod)

stim = visual.ShapeStim(win, vertices=[(-2,2),  (2,2),  (2,-2),  (-2,-2)], fillColor='white', lineWidth=0, opacity=1, units='cm')

# ============================= START MAIN LOOP
stimClock=core.Clock()
start_time   = stimClock.getTime()
time_elapsed = stimClock.getTime() - start_time

trial_length = 1 # seconds

flip_time = 0
loop_count = 0
while time_elapsed < trial_length: 
    print("loop ", loop_count, ' with time elapsed:', time_elapsed, " and time flipped is ", flip_time) 

    stim.draw ()     # Draw _something_ just to try and make things as valid as possible..

    loop_count+=1
    time_elapsed = stimClock.getTime() - start_time

    flip_time = win.flip()
# ============================= END MAIN LOOP

print("Performed", loop_count, "loops. Last flip time recorded as ", flip_time) 

# Wait for button press
event.waitKeys()
core.quit()

Using the ‘pyglet’ back-end I’ve tested this on Windows 10 with an NVidia card, and on Mac OSX with an integrated Intel GPU (both with 60Hz monitors). Both exhibited the same behaviour. I’m also seeing different/conflicting results using other backends. Does anyone know why this would be happening?

Hi all,

Following on from this thread instead of making a new one as my problem is similar. The number of iterations of a while loop is limited by frame rate even when waitBlanking = False. I’ve made a small script to reproduce this issue:

from psychopy import visual, core # import modules

win = visual.Window(waitBlanking=False,fullscr=True) # set window
iterations = 5*[1] # repeat each loop 5 times
timer = core.CountdownTimer(1) # each loop lasts 1 second

# Loop w/ win.flip()
flip_counter = 0 # set counter to 0
for i in iterations: # loop over iterations
    timer.reset() # reset timer
    while timer.getTime() > 0: # while timer is > 0
        flip_counter = flip_counter + 1 # add 1 to the counter
        win.flip() # flip the window

# Loop w/o win.flip()
nonflip_counter = 0
for i in iterations:
    timer.reset()
    while timer.getTime() > 0:
        nonflip_counter = nonflip_counter + 1

ave_flip_counter = flip_counter/len(iterations) # calculate average number of loops w/ win.flip()
ave_nonflip_counter = nonflip_counter/len(iterations) # calculate average number of loops w/o win.flip()
print(ave_flip_counter) # print loops w/ win.flip()
print(ave_nonflip_counter) # print loops w/o win.flip()

On my 60 Hz monitor the results for the loop with win.flip() is 60.4 (60 Hz) and without win.flip is 586294. Thus, the script is still waiting for the blank when waitBlanking is set to false. This is an important issue as I am monitoring serial inputs during the presentation of a dynamic stimuli. I am essentially limited to 16 ms increments which is understandable for stimulus presentation, but limits the iterations within a while loop vastly (60.4 vs 586294). This would not be a problem if waitBlanking worked as described.

Has anyone got any advances on this?

Thanks,
Corey