/* * Copyright 1993-2007 NVIDIA Corporation. All rights reserved. * * NOTICE TO USER: * * This source code is subject to NVIDIA ownership rights under U.S. and * international Copyright laws. Users and possessors of this source code * are hereby granted a nonexclusive, royalty-free license to use this code * in individual and commercial software. * * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE * OR PERFORMANCE OF THIS SOURCE CODE. * * U.S. Government End Users. This source code is a "commercial item" as * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of * "commercial computer software" and "commercial computer software * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) * and is provided to the U.S. Government only as a commercial end item. * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the * source code with only those rights set forth herein. * * Any use of this source code in individual and commercial software must * include, in the user documentation and internal comments to the code, * the above Disclaimer and U.S. Government End Users Notice. */ /* This example demonstrates how to use the Cuda OpenGL bindings to dynamically modify a vertex buffer using a Cuda kernel. The steps are: 1. Create an empty vertex buffer object (VBO) 2. Register the VBO with Cuda 3. Map the VBO for writing from Cuda 4. Run Cuda kernel to modify the vertex positions 5. Unmap the VBO 6. Render the results using OpenGL Host code */ #ifdef _WIN32 # define WINDOWS_LEAN_AND_MEAN # define NOMINMAX # include #endif // includes, system #include #include #include #include // includes, GL #include #include // includes #include #include #include //////////////////////////////////////////////////////////////////////////////// // constants const unsigned int window_width = 512; const unsigned int window_height = 512; const unsigned int mesh_width = 256; const unsigned int mesh_height = 256; // vbo variables GLuint vbo; float anim = 0.0; // mouse controls int mouse_old_x, mouse_old_y; int mouse_buttons = 0; float rotate_x = 0.0, rotate_y = 0.0; float translate_z = -3.0; //////////////////////////////////////////////////////////////////////////////// // kernels #include //////////////////////////////////////////////////////////////////////////////// // declaration, forward void runTest( int argc, char** argv); // GL functionality CUTBoolean initGL(); void createVBO( GLuint* vbo); void deleteVBO( GLuint* vbo); // rendering callbacks void display(); void keyboard( unsigned char key, int x, int y); void mouse(int button, int state, int x, int y); void motion(int x, int y); // Cuda functionality void runCuda( GLuint vbo); void checkResultCuda( int argc, char** argv, const GLuint& vbo); //////////////////////////////////////////////////////////////////////////////// // Program main //////////////////////////////////////////////////////////////////////////////// int main( int argc, char** argv) { runTest( argc, argv); CUT_EXIT(argc, argv); } //////////////////////////////////////////////////////////////////////////////// //! Run a simple test for CUDA //////////////////////////////////////////////////////////////////////////////// void runTest( int argc, char** argv) { CUT_DEVICE_INIT(); // Create GL context glutInit( &argc, argv); glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE); glutInitWindowSize( window_width, window_height); glutCreateWindow( "Cuda GL interop"); // initialize GL if( CUTFalse == initGL()) { return; } // register callbacks glutDisplayFunc( display); glutKeyboardFunc( keyboard); glutMouseFunc( mouse); glutMotionFunc( motion); // create VBO createVBO( &vbo); // run the cuda part runCuda( vbo); // check result of Cuda step checkResultCuda( argc, argv, vbo); // start rendering mainloop glutMainLoop(); } //////////////////////////////////////////////////////////////////////////////// //! Run the Cuda part of the computation //////////////////////////////////////////////////////////////////////////////// void runCuda( GLuint vbo) { // map OpenGL buffer object for writing from CUDA float4 *dptr; CUDA_SAFE_CALL(cudaGLMapBufferObject( (void**)&dptr, vbo)); // execute the kernel dim3 block(8, 8, 1); dim3 grid(mesh_width / block.x, mesh_height / block.y, 1); kernel<<< grid, block>>>(dptr, mesh_width, mesh_height, anim); // unmap buffer object CUDA_SAFE_CALL(cudaGLUnmapBufferObject( vbo)); } //////////////////////////////////////////////////////////////////////////////// //! Initialize GL //////////////////////////////////////////////////////////////////////////////// CUTBoolean initGL() { // initialize necessary OpenGL extensions glewInit(); if (! glewIsSupported( "GL_VERSION_2_0 " "GL_ARB_pixel_buffer_object" )) { fprintf( stderr, "ERROR: Support for necessary OpenGL extensions missing."); fflush( stderr); return CUTFalse; } // default initialization glClearColor( 0.0, 0.0, 0.0, 1.0); glDisable( GL_DEPTH_TEST); // viewport glViewport( 0, 0, window_width, window_height); // projection glMatrixMode( GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat)window_width / (GLfloat) window_height, 0.1, 10.0); CUT_CHECK_ERROR_GL(); return CUTTrue; } //////////////////////////////////////////////////////////////////////////////// //! Create VBO //////////////////////////////////////////////////////////////////////////////// void createVBO(GLuint* vbo) { // create buffer object glGenBuffers( 1, vbo); glBindBuffer( GL_ARRAY_BUFFER, *vbo); // initialize buffer object unsigned int size = mesh_width * mesh_height * 4 * sizeof( float); glBufferData( GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW); glBindBuffer( GL_ARRAY_BUFFER, 0); // register buffer object with CUDA CUDA_SAFE_CALL(cudaGLRegisterBufferObject(*vbo)); CUT_CHECK_ERROR_GL(); } //////////////////////////////////////////////////////////////////////////////// //! Delete VBO //////////////////////////////////////////////////////////////////////////////// void deleteVBO( GLuint* vbo) { glBindBuffer( 1, *vbo); glDeleteBuffers( 1, vbo); CUDA_SAFE_CALL(cudaGLUnregisterBufferObject(*vbo)); *vbo = 0; } //////////////////////////////////////////////////////////////////////////////// //! Display callback //////////////////////////////////////////////////////////////////////////////// void display() { // run CUDA kernel to generate vertex positions runCuda(vbo); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // set view matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, translate_z); glRotatef(rotate_x, 1.0, 0.0, 0.0); glRotatef(rotate_y, 0.0, 1.0, 0.0); // render from the vbo glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexPointer(4, GL_FLOAT, 0, 0); glEnableClientState(GL_VERTEX_ARRAY); glColor3f(1.0, 0.0, 0.0); glDrawArrays(GL_POINTS, 0, mesh_width * mesh_height); glDisableClientState(GL_VERTEX_ARRAY); glutSwapBuffers(); glutPostRedisplay(); anim += 0.01; } //////////////////////////////////////////////////////////////////////////////// //! Keyboard events handler //////////////////////////////////////////////////////////////////////////////// void keyboard( unsigned char key, int /*x*/, int /*y*/) { switch( key) { case( 27) : deleteVBO( &vbo); exit( 0); } } //////////////////////////////////////////////////////////////////////////////// //! Mouse event handlers //////////////////////////////////////////////////////////////////////////////// void mouse(int button, int state, int x, int y) { if (state == GLUT_DOWN) { mouse_buttons |= 1<