[visionegg] Re: optimizing my code since timing is a catastrophe
- From: Andrew Straw <andrew.straw@xxxxxxxxxxxxxxx>
- To: visionegg@xxxxxxxxxxxxx
- Date: Fri, 9 May 2003 08:49:59 -0400
Hi Christoph,
Here's your code shortened to relevant bits:
preloaded_texture_list = [] # empty list
for stim_index in range(num_images):
texture = Texture(photoX[stim_index])
preloaded_texture_list.append( texture )
stimulus = TextureStimulus(on = 1,
texture = preloaded_texture_list[0],
size = preloaded_texture_list[0].size,
lowerleft=(x,y))
viewport = Viewport( screen=screen, stimuli=[stimulus] )
# draw the stimulus (during first loop: fixation)
stimulus.parameters.texture = preloaded_texture_list[stim_index]
screen.clear()
viewport.draw()
swap_buffers()
What your code does:
A) create an instance of the Texture class for each image you want to
use. The Texture class merely gets the data ready to be sent to
OpenGL, but does not actually send it unless the load() method is
called. (If I remember correctly, you wrote this part of your code
before I had re-written much of the Textures module to allow for the
speedups detailed below.)
B) create a single TextureStimulus class called "stimulus". This
method does call the load() method of the Texture you assign it and
therefore actually sends the data to OpenGL. This loading is
accomplished by creating a "texture object" (OpenGL terminology
referring to an allocation of resources used to cache texture data).
Creating a texture object can take some time.
C) when passing later images, they become the TextureSimulus's new
texture parameter, and each one will have its load() call used, thus
resulting in the problem when OpenGL needs a lot of time to (deallocate
old resources and) allocate new resources for the new texture object.
I'm 99% sure that this is your problem.
You have three options:
1) Use only one texture object. See the demo image_sequence_fast.py
for an example. This uses the put_sub_image() method to avoid creating
new texture objects. It recycles the old texture object instead.
2) Pre-allocate a texture object for each texture before you enter
time-critical code. Create a list of TextureStimulus instances, one
with each of your texture images. Change the
viewport.parameters.stimuli list to include only the TextureStimulus
you want to display on a particular frame. Note that you may have to
draw each of the textures once to really convince OpenGL to cache it.
(But you don't have to swap buffers, which means no one has to see that
you drew those textures.) This will only help up to the number of
textures you can put in video memory.
3) Wait for me to optimize Screen.put_pixels(), which is otherwise
done. Screen.put_pixels() is called with the image data you want and
will perform something very similar to #1 above. (Right now,
put_pixels() goes the slow route and does what you're doing.) The
advantage of using put_pixels() would be that you don't need to worry
about the details of OpenGL texture memory management. (BTW, the
approach is already described in the comments of put_pixels(), but just
not implemented yet. Feel free to have a go. :)
I recommend #1 for now, although #2 is also easy to try.
Cheers!
Andrew
======================================
The Vision Egg mailing list
Archives: //www.freelists.org/archives/visionegg
Website: http://www.visionegg.org/mailinglist.html
Other related posts: