Advertisement
Guest User

Untitled

a guest
Aug 5th, 2009
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.71 KB | None | 0 0
  1. # This is a partially finished attempt at a GL interop demo,
  2. # submitted by Peter Berrington.
  3.  
  4. from OpenGL.GL import *
  5. from OpenGL.GLUT import *
  6. from OpenGL.GLU import *
  7. from OpenGL.GL.ARB.vertex_buffer_object import *
  8. import numpy, sys, time
  9. import pycuda.driver as cuda_driver
  10. import pycuda.gl as cuda_gl
  11. from pycuda.compiler import SourceModule
  12.  
  13. #this is all munged together from the CUDA SDK postprocessGL example.
  14.  
  15. initial_size = 512,512
  16. current_size = initial_size
  17. animate = True
  18. enable_cuda = True
  19. window = None     # Number of the glut window.
  20. time_of_last_draw = 0.0
  21. time_of_last_titleupdate = 0.0
  22. frames_per_second = 0.0
  23. frame_counter = 0
  24. output_texture = None # pointer to offscreen render target
  25. (source_pbo, dest_pbo, cuda_module, invert,
  26.  pycuda_source_pbo, pycuda_dest_pbo) = [None]*6
  27. heading,pitch,bank = [0.0]*3
  28.  
  29. def create_PBOs(w,h):
  30.     global source_pbo, dest_pbo, pycuda_source_pbo, pycuda_dest_pbo
  31.     num_texels = w*h
  32.     data = numpy.zeros((num_texels,4),numpy.uint8)
  33.     source_pbo = glGenBuffers(1)
  34.     glBindBuffer(GL_ARRAY_BUFFER, source_pbo)
  35.     glBufferData(GL_ARRAY_BUFFER, data, GL_DYNAMIC_DRAW)
  36.     glBindBuffer(GL_ARRAY_BUFFER, 0)
  37.     pycuda_source_pbo = cuda_gl.BufferObject(long(source_pbo))
  38.     dest_pbo = glGenBuffers(1)
  39.     glBindBuffer(GL_ARRAY_BUFFER, dest_pbo)
  40.     glBufferData(GL_ARRAY_BUFFER, data, GL_DYNAMIC_DRAW)
  41.     glBindBuffer(GL_ARRAY_BUFFER, 0)
  42.     pycuda_dest_pbo = cuda_gl.BufferObject(long(dest_pbo))
  43.  
  44. def destroy_PBOs():
  45.     global source_pbo, dest_pbo, pycuda_source_pbo, pycuda_dest_pbo
  46.     for pbo in [source_pbo, dest_pbo]:
  47.         glBindBuffer(GL_ARRAY_BUFFER, long(pbo))
  48.         glDeleteBuffers(1, long(pbo));
  49.         glBindBuffer(GL_ARRAY_BUFFER, 0)
  50.     source_pbo,dest_pbo,pycuda_source_pbo,pycuda_dest_pbo = [None]*4
  51.  
  52. def create_texture(w,h):
  53.     global output_texture
  54.     output_texture = glGenTextures(1)
  55.     glBindTexture(GL_TEXTURE_2D, output_texture)
  56.     # set basic parameters
  57.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
  58.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
  59.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
  60.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
  61.     # buffer data
  62.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
  63.                  w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)
  64.  
  65. def destroy_texture():
  66.     global output_texture
  67.     glDeleteTextures(output_texture);
  68.     output_texture = None
  69.  
  70. def init_gl():
  71.     Width, Height = current_size
  72.     glClearColor(0.1, 0.1, 0.5, 1.0)
  73.     glDisable(GL_DEPTH_TEST)
  74.     glViewport(0, 0, Width, Height)
  75.     glMatrixMode(GL_PROJECTION);
  76.     glLoadIdentity();
  77.     gluPerspective(60.0, Width/float(Height), 0.1, 10.0)
  78.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
  79.     glEnable(GL_LIGHT0)
  80.     red   = ( 1.0, 0.1, 0.1, 1.0 )
  81.     white = ( 1.0, 1.0, 1.0, 1.0 )
  82.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,  red  )
  83.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white)
  84.     glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 60.0)
  85.  
  86. def resize(Width, Height):
  87.     global current_size
  88.     current_size = Width, Height
  89.     glViewport(0, 0, Width, Height)        # Reset The Current Viewport And Perspective Transformation
  90.     glMatrixMode(GL_PROJECTION)
  91.     glLoadIdentity()
  92.     gluPerspective(60.0, Width/float(Height), 0.1, 10.0)
  93.  
  94. def do_tick():
  95.     global time_of_last_titleupdate, frame_counter, frames_per_second
  96.     if ((time.clock () * 1000.0) - time_of_last_titleupdate >= 1000.):
  97.         frames_per_second = frame_counter                   # Save The FPS
  98.         frame_counter = 0  # Reset The FPS Counter
  99.         szTitle = "%d FPS" % (frames_per_second )
  100.         glutSetWindowTitle ( szTitle )
  101.         time_of_last_titleupdate = time.clock () * 1000.0
  102.     frame_counter += 1
  103.  
  104. # The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)
  105. def keyPressed(*args):
  106.     global animate, enable_cuda
  107.     # If escape is pressed, kill everything.
  108.     if args[0] == '\033':
  109.         print 'Closing..'
  110.         destroy_PBOs()
  111.         destroy_texture()
  112.         exit()
  113.     elif args[0] == 'a':
  114.         print 'toggling animation'
  115.         animate = not animate
  116.     elif args[0] == 'e':
  117.         print 'toggling cuda'
  118.         enable_cuda = not enable_cuda
  119.  
  120. def idle():
  121.     global heading, pitch, bank
  122.     if animate:
  123.         heading += 0.2
  124.         pitch   += 0.6
  125.         bank    += 1.0
  126.  
  127.     glutPostRedisplay()
  128.  
  129. def display():
  130.     try:
  131.         render_scene()
  132.         if enable_cuda:
  133.             process_image()
  134.             display_image()
  135.         glutSwapBuffers()
  136.     except:
  137.         from traceback import print_exc
  138.         print_exc()
  139.         from os import _exit
  140.         _exit(0)
  141.  
  142. def process(width, height):
  143.     """ Use PyCuda """
  144.     grid_dimensions   = (width//16,height//16)
  145.  
  146.     source_mapping = pycuda_source_pbo.map()
  147.     dest_mapping   = pycuda_dest_pbo.map()
  148.  
  149.     invert.prepared_call(grid_dimensions,
  150.             source_mapping.device_ptr(),
  151.             dest_mapping.device_ptr())
  152.  
  153.     cuda_driver.Context.synchronize()
  154.  
  155.     source_mapping.unmap()
  156.     dest_mapping.unmap()
  157.  
  158. def process_image():
  159.     """ copy image and process using CUDA """
  160.     global pycuda_source_pbo,source_pbo,current_size, dest_pbo
  161.     image_width, image_height = current_size
  162.     assert source_pbo is not None
  163.  
  164.     # tell cuda we are going to get into these buffers
  165.     pycuda_source_pbo.unregister()
  166.  
  167.     # activate destination buffer
  168.     glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, long(source_pbo))
  169.  
  170.     # read data into pbo. note: use BGRA format for optimal performance
  171.     import OpenGL.raw.GL as rawgl
  172.  
  173.     rawgl.glReadPixels(
  174.              0,                  #start x
  175.              0,                  #start y
  176.              image_width,        #end   x
  177.              image_height,       #end   y
  178.              GL_BGRA,            #format
  179.              GL_UNSIGNED_BYTE,   #output type
  180.              ctypes.c_void_p(0))
  181.  
  182.     pycuda_source_pbo = cuda_gl.BufferObject(long(source_pbo))
  183.    
  184.     # run the Cuda kernel
  185.     process(image_width, image_height)
  186.     # blit convolved texture onto the screen
  187.     # download texture from PBO
  188.     glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, long(dest_pbo))
  189.     glBindTexture(GL_TEXTURE_2D, output_texture)
  190.  
  191.     rawgl.glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
  192.                     image_width, image_height,
  193.                     GL_BGRA, GL_UNSIGNED_BYTE, ctypes.c_void_p(0))
  194.  
  195. def display_image():
  196.     """ render a screen sized quad """
  197.     glDisable(GL_DEPTH_TEST)
  198.     glDisable(GL_LIGHTING)
  199.     glEnable(GL_TEXTURE_2D)
  200.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
  201.     glMatrixMode(GL_PROJECTION)
  202.     glPushMatrix()
  203.     glLoadIdentity()
  204.     glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0)
  205.     glMatrixMode( GL_MODELVIEW)
  206.     glLoadIdentity()
  207.     glViewport(0, 0, current_size[0], current_size[1])
  208.     glBegin(GL_QUADS)
  209.     glTexCoord2f(0.0, 0.0)
  210.     glVertex3f(-1.0, -1.0, 0.5)
  211.     glTexCoord2f(1.0, 0.0)
  212.     glVertex3f(1.0, -1.0, 0.5)
  213.     glTexCoord2f(1.0, 1.0)
  214.     glVertex3f(1.0, 1.0, 0.5)
  215.     glTexCoord2f(0.0, 1.0)
  216.     glVertex3f(-1.0, 1.0, 0.5)
  217.     glEnd()
  218.     glMatrixMode(GL_PROJECTION)
  219.     glPopMatrix()
  220.     glDisable(GL_TEXTURE_2D)
  221.     glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0)
  222.     glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0)
  223.  
  224.  
  225. def render_scene():
  226.     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)# Clear Screen And Depth Buffer    
  227.     glMatrixMode(GL_MODELVIEW)
  228.     glLoadIdentity ()      # Reset The Modelview Matrix
  229.     glTranslatef(0.0, 0.0, -3.0);
  230.     glRotatef(heading, 1.0, 0.0, 0.0)
  231.     glRotatef(pitch  , 0.0, 1.0, 0.0)
  232.     glRotatef(bank   , 0.0, 0.0, 1.0)
  233.     glViewport(0, 0, current_size[0],current_size[1])
  234.     glEnable(GL_LIGHTING)
  235.     glEnable(GL_DEPTH_TEST)
  236.     glDepthFunc(GL_LESS)
  237.     glutSolidTeapot(1.0)
  238.     do_tick()#just for fps display..
  239.     return True
  240.  
  241. def main():
  242.     global window, cuda_module, cuda_gl, cuda_driver, invert
  243.     glutInit(sys.argv)
  244.     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
  245.     glutInitWindowSize(*initial_size)
  246.     glutInitWindowPosition(0, 0)
  247.     window = glutCreateWindow("PyCuda GL Interop Example")
  248.     glutDisplayFunc(display)
  249.     glutIdleFunc(idle)
  250.     glutReshapeFunc(resize)
  251.     glutKeyboardFunc(keyPressed)
  252.     glutSpecialFunc(keyPressed)
  253.     init_gl()
  254.  
  255.     # create texture for blitting to screen
  256.     create_texture(*initial_size)
  257.  
  258.     #setup pycuda gl interop
  259.     import pycuda.gl.autoinit
  260.     import pycuda.gl
  261.     cuda_gl = pycuda.gl
  262.     cuda_driver = pycuda.driver
  263.  
  264.     cuda_module = SourceModule("""
  265.    __global__ void invert(unsigned char *source, unsigned char *dest)
  266.    {
  267.      int block_num        = blockIdx.x + blockIdx.y * gridDim.x;
  268.      int thread_num       = threadIdx.y * blockDim.x + threadIdx.x;
  269.      int threads_in_block = blockDim.x * blockDim.y;
  270.      //Since the image is RGBA we multiply the index 4.
  271.      //We'll only use the first 3 (RGB) channels though
  272.      int idx              = 4 * (threads_in_block * block_num + thread_num);
  273.      dest[idx  ] = 255 - source[idx  ];
  274.      dest[idx+1] = 255 - source[idx+1];
  275.      dest[idx+2] = 255 - source[idx+2];
  276.    }
  277.    """)
  278.     invert = cuda_module.get_function("invert")
  279.     # The argument "PP" indicates that the invert function will take two PBOs as arguments
  280.     invert.prepare("PP", (16, 16, 1))
  281.  
  282.     # create source and destination pixel buffer objects for processing
  283.     create_PBOs(*initial_size)
  284.  
  285.     glutMainLoop()
  286.  
  287. # Print message to console, and kick off the main to get it rolling.
  288. if __name__ == "__main__":
  289.     print "Hit ESC key to quit, 'a' to toggle animation, and 'e' to toggle cuda"
  290.     main()
  291.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement