/* * License (based on zlib/libpng): * * Copyright (c) 2005-2007 Dominik Göddeke, University of Dortmund, Germany. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely. * */ /* * GPGPU Reduction Tutorial: Computes maximum of a vector on the GPU. * * Limitation: vector length must be 2^k by 2^k. * * This version: texture rectangles, precomputed texcoords * * More details: www.mathematik.uni-dortmund.de/~goeddeke/gpgpu * * Please drop me a note if you encounter any bugs, or if you have suggestions * on how to improve this tutorial: dominik.goeddeke@math.uni-dortmund.de * */ // includes #include #include #include #include #include #include #include #include // error codes static int ERROR_CG = -1; static int ERROR_GLEW = -2; static int ERROR_TEXTURE = -3; static int ERROR_BINDFBO = -4; static int ERROR_FBOTEXTURE = -5; static int ERROR_PARAMS = -6; // prototypes void cgErrorCallback(void); bool checkFramebufferStatus(void); void checkGLErrors(const char *label); void compareResults(void); void createTextures(void); void drawQuad(int w, int h); void initCG(void); void initFBOandViewport(void); void initGLEW(void); void initGLUT(int argc, char** argv); void performComputation(void); void setupTexture(const GLuint texID); void swap(void); // problem size (must be power of 2 by power of 2) int N = 1024*1024; int texSize = 1024; // texture identifiers GLuint pingpongTexID[2]; GLuint inputTexID; // ping pong management vars int writeTex = 0; int readTex = 1; GLenum attachmentpoints[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }; // Cg vars CGcontext cgContext; CGprofile fragmentProfile; CGprogram fragmentProgram; CGparameter textureParam; // FBO identifier GLuint fb; // handle to offscreen "window", only used to properly shut down the app GLuint glutWindowHandle; // shortcuts for texture internals GLenum texTarget = GL_TEXTURE_RECTANGLE_ARB; GLenum texInternalFormat = GL_FLOAT_R32_NV; GLenum texFormat = GL_LUMINANCE; // see course web page for details on this shader char* shader = \ "float maximum( " \ " float2 left: TEXCOORD0,"\ " float2 right: TEXCOORD1,"\ " float2 top: TEXCOORD2,"\ " float2 bottom: TEXCOORD3,"\ " uniform samplerRECT texture) : COLOR { "\ "float val1 = texRECT(texture, left);"\ "float val2 = texRECT(texture, right);"\ "float val3 = texRECT(texture, top);"\ "float val4 = texRECT(texture, bottom);"\ "return max(val1,max(val2,max(val3,val4)));}"; // actual data float* data; /** * main, just calls things in the appropriate order */ int main(int argc, char **argv) { printf("--------------------------------------------------------------\n"); printf("Parallel reduction example\n\n"); printf("see www.mathematik.uni-dortmund.de/~goeddeke/gpgpu for details\n"); printf("--------------------------------------------------------------\n"); // // create data vector // srand(time(NULL)); data = (float*)malloc(N*sizeof(float)); for (int i=0; i cpuResult) cpuResult = data[i]; // and print out results printf("--------------------------------------------------------------\n"); printf("GPU result:\t%f\n",gpuResult); printf("CPU result:\t%f\n",cpuResult); printf("--------------------------------------------------------------\n"); } /** * Performs the actual calculation. */ void performComputation(void) { printf("--------------------------------------------------------------\n"); // enable fragment profile cgGLEnableProfile(fragmentProfile); // bind "maximum" program cgGLBindProgram(fragmentProgram); // // pass 1: read from inputTexture, first reduction step // idea: do not overwrite input during pingpong // // enable input texture cgGLSetTextureParameter(textureParam, inputTexID); cgGLEnableTextureParameter(textureParam); // set render destination glDrawBuffer (attachmentpoints[writeTex]); // calculate output region width and height int outputWidth = texSize / 2; printf("Input size :\t%dx%d\n",texSize,texSize); printf("Reduction step:\t%dx%d to %dx%d.\n",texSize, texSize, outputWidth, outputWidth); // perform computation and ping-pong output textures drawQuad(outputWidth,outputWidth); /* float* result = (float*)malloc(outputWidth*outputWidth*sizeof(float)); glReadBuffer(attachmentpoints[writeTex]); glReadPixels(0, 0, outputWidth, outputWidth,texFormat,GL_FLOAT,result); for (int i=0; i