/* * 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 Basic Math Tutorial * * * 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 // error codes #define ERROR_GLSL -1 #define ERROR_GLEW -2 #define ERROR_TEXTURE -3 #define ERROR_BINDFBO -4 #define ERROR_FBOTEXTURE -5 #define ERROR_PARAMS -6 // prototypes bool checkFramebufferStatus(void); void checkGLErrors(const char *label); void compareResults(void); void createTextures(void); void createAllTextureParameters(void); void initGLSL(void); void initFBO(void); void initGLEW(void); void initGLUT(int argc, char** argv); void performComputation(void); void printInfoLog(GLhandleARB obj); void printVector(const float *p, const int N); void setupTexture(const GLuint texID); void swap(void); void transferFromTexture(float* data); void transferToTexture(float* data, GLuint texID); // mode: 0=test (POT), 1=bench (set from command line) int mode; // problem size, texture size, number of iterations (set from command line) int N; int texSize; int numIterations; // flags to fine-tune application and to ease debugging bool mode_showResults = true; bool mode_compareResults = true; // texture identifiers GLuint yTexID[2]; GLuint xTexID; GLuint aTexID; // ping pong management vars int writeTex = 0; int readTex = 1; GLenum attachmentpoints[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }; // GLSL vars GLhandleARB programObject; GLhandleARB shaderObject; GLint yParam, xParam, alphaParam; // FBO identifier GLuint fb; // timing vars double start, end; // handle to offscreen "window", only used to properly shut down the app GLuint glutWindowHandle; // struct for variable parts of GL calls (texture format, float format etc) struct struct_textureParameters { char* name; GLenum texTarget; GLenum texInternalFormat; GLenum texFormat; char* shader_source; } rect_arb_rgba_32, // texture rectangles, texture_float_ARB, RGBA, 32 bits rect_arb_rgba_16, // texture rectangles, texture_float_ARB, RGBA, 16 bits rect_arb_r_32, // texture rectangles, texture_float_ARB, R, 32 bits rect_ati_rgba_32, // texture rectangles, ATI_texture_float, RGBA, 32 bits rect_ati_rgba_16, // texture rectangles, ATI_texture_float, RGBA, 16 bits rect_ati_r_32, // texture rectangles, ATI_texture_float, R, 32 bits rect_nv_rgba_32, // texture rectangles, NV_float_buffer, RGBA, 32 bits rect_nv_rgba_16, // texture rectangles, NV_float_buffer, RGBA, 16 bits rect_nv_r_32, // texture rectangles, NV_float_buffer, R, 32 bits twod_arb_rgba_32, // texture 2ds, texture_float_ARB, RGBA, 32 bits twod_arb_rgba_16, // texture 2ds, texture_float_ARB, RGBA, 16 bits twod_arb_r_32, // texture 2ds, texture_float_ARB, R, 32 bits twod_ati_rgba_32, // texture 2ds, ATI_texture_float, RGBA, 32 bits twod_ati_rgba_16, // texture 2ds, ATI_texture_float, RGBA, 16 bits twod_ati_r_32, // texture 2ds, NV_float_buffer, R, 32 bits twod_nv_rgba_32, // texture 2ds, NV_float_buffer, RGBA, 32 bits twod_nv_rgba_16, // texture 2ds, NV_float_buffer, RGBA, 16 bits twod_nv_r_32; // texture 2ds, NV_float_buffer, R, 32 bits // struct actually being used (set from command line) struct_textureParameters textureParameters; // actual data float* dataX; float* dataY; float alpha; /** * main, just calls things in the appropriate order */ int main(int argc, char **argv) { // create variables for GL createAllTextureParameters(); // parse command line if (argc < 6) { printf("Command line parameters:\n"); printf("Param 1: 0 = check if given format is supported\n"); printf(" 1 = do some benchmarking \n"); printf("Param 2: one of the test formats\n"); printf(" rect_arb_rgba_32, // texture rectangles, texture_float_ARB, RGBA, 32 bits\n"); printf(" rect_arb_rgba_16, // texture rectangles, texture_float_ARB, RGBA, 16 bits\n"); printf(" rect_arb_r_32, // texture rectangles, texture_float_ARB, R, 32 bits\n"); printf(" rect_ati_rgba_32, // texture rectangles, ATI_texture_float, RGBA, 32 bits\n"); printf(" rect_ati_rgba_16, // texture rectangles, ATI_texture_float, RGBA, 16 bits\n"); printf(" rect_ati_r_32, // texture rectangles, ATI_texture_float, R, 32 bits\n"); printf(" rect_nv_rgba_32, // texture rectangles, NV_float_buffer, RGBA, 32 bits\n"); printf(" rect_nv_rgba_16, // texture rectangles, NV_float_buffer, RGBA, 16 bits\n"); printf(" rect_nv_r_32, // texture rectangles, NV_float_buffer, R, 32 bits\n"); printf(" twod_arb_rgba_32, // texture 2ds, texture_float_ARB, RGBA, 32 bits\n"); printf(" twod_arb_rgba_16, // texture 2ds, texture_float_ARB, RGBA, 16 bits\n"); printf(" twod_arb_r_32, // texture 2ds, texture_float_ARB, R, 32 bits\n"); printf(" twod_ati_rgba_32, // texture 2ds, ATI_texture_float, RGBA, 32 bits\n"); printf(" twod_ati_rgba_16, // texture 2ds, ATI_texture_float, RGBA, 16 bits\n"); printf(" twod_ati_r_32, // texture 2ds, ATI_texture_float, R, 32 bits\n"); printf(" twod_nv_rgba_32, // texture 2ds, NV_float_buffer, RGBA, 32 bits\n"); printf(" twod_nv_rgba_16, // texture 2ds, NV_float_buffer, RGBA, 16 bits\n"); printf(" twod_nv_r_32, // texture 2ds, NV_float_buffer, R, 32 bits\n"); printf("Param 3: 0 = no comparison of results\n"); printf(" 1 = compare and only print out max errors\n"); printf(" 2 = compare and print out full result vectors (use with care for large N)\n"); printf("Param 4: problem size N \n"); printf("Param 5: number of iterations \n"); exit(0); } else { mode = atoi(argv[1]); if (strcmp(argv[2],"rect_arb_rgba_32")==0) textureParameters = rect_arb_rgba_32; else if (strcmp(argv[2],"rect_arb_rgba_16")==0) textureParameters = rect_arb_rgba_16; else if (strcmp(argv[2],"rect_arb_r_32")==0) textureParameters = rect_arb_r_32; else if (strcmp(argv[2],"rect_ati_rgba_32")==0) textureParameters = rect_ati_rgba_32; else if (strcmp(argv[2],"rect_ati_rgba_16")==0) textureParameters = rect_ati_rgba_16; else if (strcmp(argv[2],"rect_ati_r_32")==0) textureParameters = rect_ati_r_32; else if (strcmp(argv[2],"rect_nv_rgba_32")==0) textureParameters = rect_nv_rgba_32; else if (strcmp(argv[2],"rect_nv_rgba_16")==0) textureParameters = rect_nv_rgba_16; else if (strcmp(argv[2],"rect_nv_r_32")==0) textureParameters = rect_nv_r_32; else if (strcmp(argv[2],"twod_arb_rgba_32")==0) textureParameters = twod_arb_rgba_32; else if (strcmp(argv[2],"twod_arb_rgba_16")==0) textureParameters = twod_arb_rgba_16; else if (strcmp(argv[2],"twod_arb_r_32")==0) textureParameters = twod_arb_r_32; else if (strcmp(argv[2],"twod_ati_rgba_32")==0) textureParameters = twod_ati_rgba_32; else if (strcmp(argv[2],"twod_ati_rgba_16")==0) textureParameters = twod_ati_rgba_16; else if (strcmp(argv[2],"twod_ati_r_32")==0) textureParameters = twod_ati_r_32; else if (strcmp(argv[2],"twod_nv_rgba_32")==0) textureParameters = twod_nv_rgba_32; else if (strcmp(argv[2],"twod_nv_rgba_16")==0) textureParameters = twod_nv_rgba_16; else if (strcmp(argv[2],"twod_nv_r_32")==0) textureParameters = twod_nv_r_32; else { printf("unknown parameter, exit\n"); exit(ERROR_PARAMS); } int i = atoi(argv[3]); switch (i) { case 0: mode_showResults = false; mode_compareResults = false; break; case 1: mode_showResults = false; mode_compareResults = true; break; case 2: mode_showResults = true; mode_compareResults = true; break; default: printf("unknown parameter, exit\n"); exit(ERROR_PARAMS); } N = atoi (argv[4]); numIterations = atoi (argv[5]); printf(textureParameters.name); printf(", N=%d, numIter=%d\n",N,numIterations); } // calc texture dimensions if (textureParameters.texFormat == GL_RGBA) texSize = (int)sqrt(N/4.0); else texSize = (int)sqrt((double)N); // create data vectors dataX = (float*)malloc(N*sizeof(float)); dataY = (float*)malloc(N*sizeof(float)); // and fill with some arbitrary values for (int i=0; i maxError) maxError = diff; avgError += diff; } avgError /= (double)N; printf("Max Error: \t\t\t%e\n",maxError); printf("Avg Error: \t\t\t%e\n",avgError); if (mode_showResults) { printf("CPU RESULTS:\n"); printVector(dataY,N); } } if (mode_showResults) { // print out results printf("GPU RESULTS:\n"); printVector (data,N); } delete [] data; } /** * Performs the actual calculation. */ void performComputation(void) { // attach two textures to FBO glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachmentpoints[writeTex], textureParameters.texTarget, yTexID[writeTex], 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachmentpoints[readTex], textureParameters.texTarget, yTexID[readTex], 0); // check if that worked if (!checkFramebufferStatus()) { printf("glFramebufferTexture2DEXT():\t [FAIL]\n"); exit (ERROR_FBOTEXTURE); } else if (mode == 0) { printf("glFramebufferTexture2DEXT():\t [PASS]\n"); } // enable GLSL program glUseProgramObjectARB(programObject); // enable texture x (read-only, not changed in the computation loop) glActiveTexture(GL_TEXTURE1); glBindTexture(textureParameters.texTarget,xTexID); glUniform1iARB(xParam, 1); // texunit 1 // enable scalar alpha (same) glUniform1fARB(alphaParam,alpha); // Calling glFinish() is only neccessary to get accurate timings, // and we need a high number of iterations to avoid timing noise. glFinish(); start = clock(); for (int i=0; i 1) { infoLog = (char *)malloc(infologLength); glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog); printf(infoLog); printf("\n"); free(infoLog); } } /** * Prints out given vector for debugging purposes. */ void printVector (const float *p, const int N) { for (int i=0; i