Advertisement
Guest User

Untitled

a guest
Mar 26th, 2011
387
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.17 KB | None | 0 0
  1. // includes
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #include <time.h>
  7. #include <GL/glew.h>
  8. #include <GL/glut.h>
  9.  
  10.  
  11. // error codes
  12. #define  ERROR_GLSL        -1
  13. #define  ERROR_GLEW        -2
  14. #define  ERROR_TEXTURE     -3
  15. #define  ERROR_BINDFBO     -4
  16. #define  ERROR_FBOTEXTURE  -5
  17. #define  ERROR_PARAMS      -6
  18.  
  19. // prototypes
  20. bool checkFramebufferStatus(void);
  21. void checkGLErrors(const char *label);
  22. void printResults(void);
  23. void createTextures(void);
  24. void createAllTextureParameters(void);
  25. void initGLSL(void);
  26. void initFBO(void);
  27. void initGLEW(void);
  28. void initGLUT(int argc, char** argv);
  29. void performComputation(void);
  30. void printProgramInfoLog(GLuint obj);
  31. void printShaderInfoLog(GLuint obj);
  32. void printVector(const float *p, const int N);
  33. void setupTexture(const GLuint texID);
  34. void swap(void);
  35. void transferFromTexture(float* data);
  36. void transferToTexture(float* data, GLuint texID);
  37.  
  38. // problem size, texture size, number of iterations (set from command line)
  39. int N;
  40. int texSize;
  41.  
  42. // texture identifiers
  43. GLuint yTexID[2];
  44. GLuint xTexID;
  45. GLuint aTexID;
  46.  
  47. // ping pong management vars
  48. int writeTex = 0;
  49. int readTex = 1;
  50. GLenum attachmentpoints[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
  51.  
  52. // GLSL vars
  53. GLuint glslProgram;
  54. GLuint fragmentShader;
  55. GLint yParam, xParam, alphaParam;
  56.  
  57. // FBO identifier
  58. GLuint fb;
  59.  
  60. // timing vars
  61. double start, end;
  62.  
  63. // handle to offscreen "window", only used to properly shut down the app
  64. GLuint glutWindowHandle;
  65.  
  66. // struct for variable parts of GL calls (texture format, float format etc)
  67. struct struct_textureParameters {
  68.     char* name;
  69.     GLenum texTarget;
  70.     GLenum texInternalFormat;
  71.     GLenum texFormat;
  72.     char* shader_source;
  73. }   rect_arb_rgba_32,   // texture rectangles, texture_float_ARB, RGBA, 32 bits
  74.     twod_arb_rgba_32;   // texture 2ds, texture_float_ARB, RGBA, 32 bits
  75.  
  76. // struct actually being used (set from command line)
  77. struct_textureParameters textureParameters;
  78.  
  79. // actual data
  80. float* dataX;
  81. float* dataY;
  82.  
  83.  
  84. /**
  85.  * main, just calls things in the appropriate order
  86.  */
  87. int main(int argc, char **argv)
  88. {
  89.     if(argc < 2)
  90.     {
  91.         printf("USAGE: glsl <NUM OF ELEMENTS>\n");
  92.     }
  93.     else
  94.     {
  95.         N = atoi (argv[1]);
  96.  
  97.         // create variables for GL
  98.         createAllTextureParameters();
  99.  
  100.         textureParameters = rect_arb_rgba_32;
  101.  
  102.         // calc texture dimensions
  103.         if (textureParameters.texFormat == GL_RGBA)
  104.         texSize = (int)sqrt(N/4.0);
  105.         else
  106.         texSize = (int)sqrt((double)N);
  107.         // create data vectors
  108.         dataX = (float*)malloc(N*sizeof(float));
  109.         dataY = (float*)malloc(N*sizeof(float));
  110.         // and fill with some arbitrary values
  111.         for (int i=0; i<N; i++)
  112.         {
  113.             dataX[i] = 10;
  114.             dataY[i] = 20;
  115.         }
  116.  
  117.         // init glut and glew
  118.         initGLUT(argc, argv);
  119.         initGLEW();
  120.         // init offscreen framebuffer
  121.         initFBO();
  122.         // create textures for vectors
  123.         createTextures();
  124.         // init shader runtime
  125.         initGLSL();
  126.         // and start computation
  127.  
  128.  
  129.         performComputation();
  130.         // print results
  131.         printResults();
  132.         // and clean up
  133.         glDetachShader(glslProgram, fragmentShader);
  134.         glDeleteShader(fragmentShader);
  135.         glDeleteProgram(glslProgram);
  136.         glDeleteFramebuffersEXT(1,&fb);
  137.         free(dataX);
  138.         free(dataY);
  139.         glDeleteTextures(2,yTexID);
  140.         glDeleteTextures (1,&xTexID);
  141.         glutDestroyWindow (glutWindowHandle);
  142.     }
  143.     // exit
  144.     return 0;
  145. }
  146.  
  147.  
  148. /**
  149.  * Sets up a floating point texture with NEAREST filtering.
  150.  * (mipmaps etc. are unsupported for floating point textures)
  151.  */
  152. void setupTexture (const GLuint texID) {
  153.     // make active and bind
  154.     glBindTexture(textureParameters.texTarget,texID);
  155.     // turn off filtering and wrap modes
  156.     glTexParameteri(textureParameters.texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  157.     glTexParameteri(textureParameters.texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  158.     glTexParameteri(textureParameters.texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
  159.     glTexParameteri(textureParameters.texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);
  160.     // define texture with floating point format
  161.     glTexImage2D(textureParameters.texTarget,0,textureParameters.texInternalFormat,texSize,texSize,0,textureParameters.texFormat,GL_FLOAT,0);
  162.     // check if that worked
  163.     if (glGetError() != GL_NO_ERROR) {
  164.     printf("glTexImage2D():\t\t\t [FAIL]\n");
  165.     exit (ERROR_TEXTURE);
  166.     }
  167. }
  168.  
  169. /**
  170.  * Transfers data from currently texture, and stores it in given array.
  171.  */
  172. void transferFromTexture(float* data)
  173. {
  174.     glReadBuffer(attachmentpoints[readTex]);
  175.     glReadPixels(0, 0, texSize, texSize,textureParameters.texFormat,GL_FLOAT,data);
  176. }
  177.  
  178. /**
  179.  * Transfers data to texture.
  180.  * Check web page for detailed explanation on the difference between ATI and NVIDIA.
  181.  */
  182. void transferToTexture (float* data, GLuint texID)
  183. {
  184.     glBindTexture(textureParameters.texTarget, texID);
  185.     glTexSubImage2D(textureParameters.texTarget,0,0,0,texSize,texSize,textureParameters.texFormat,GL_FLOAT,data);
  186. }
  187.  
  188. /**
  189.  * creates textures, sets proper viewport etc.
  190.  */
  191. void createTextures (void) {
  192.     // create textures
  193.     // y gets two textures, alternatingly read-only and write-only,
  194.     // x is just read-only
  195.     glGenTextures (2, yTexID);
  196.     glGenTextures (1, &xTexID);
  197.     // set up textures
  198.     setupTexture (yTexID[readTex]);
  199.     transferToTexture(dataY,yTexID[readTex]);
  200.     setupTexture (yTexID[writeTex]);
  201.     transferToTexture(dataY,yTexID[writeTex]);
  202.     setupTexture (xTexID);
  203.     transferToTexture(dataX,xTexID);
  204.     // set texenv mode from modulate (the default) to replace
  205.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  206.     // check if something went completely wrong
  207.     checkGLErrors ("createFBOandTextures()");
  208. }
  209.  
  210. /**
  211.  * Sets up GLUT, creates "window" (better put: valid GL context, since the window is never displayed)
  212.  */
  213. void initGLUT(int argc, char **argv) {
  214.     glutInit ( &argc, argv );
  215.     glutWindowHandle = glutCreateWindow("GLSL");
  216. }
  217.  
  218. /**
  219.  * Sets up GLEW to initialise OpenGL extensions
  220.  */
  221. void initGLEW (void) {
  222.     int err = glewInit();
  223.     // sanity check
  224.     if (GLEW_OK != err) {
  225.     printf((char*)glewGetErrorString(err));
  226.     exit(ERROR_GLEW);
  227.     }
  228. }
  229.  
  230. /**
  231.  * Creates framebuffer object, binds it to reroute rendering operations
  232.  * from the traditional framebuffer to the offscreen buffer
  233.  */
  234. void initFBO(void) {
  235.     // create FBO (off-screen framebuffer)
  236.     glGenFramebuffersEXT(1, &fb);
  237.     // bind offscreen framebuffer (that is, skip the window-specific render target)
  238.     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  239.     // viewport for 1:1 pixel=texture mapping
  240.     glMatrixMode(GL_PROJECTION);
  241.     glLoadIdentity();
  242.     gluOrtho2D(0.0, texSize, 0.0, texSize);
  243.     glMatrixMode(GL_MODELVIEW);
  244.     glLoadIdentity();
  245.     glViewport(0, 0, texSize, texSize);
  246. }
  247.  
  248. /**
  249.  * Sets up the GLSL runtime and creates shader.
  250.  */
  251. void initGLSL(void) {
  252.     // create program object
  253.     glslProgram = glCreateProgram();
  254.     // create shader object (fragment shader)
  255.     fragmentShader = glCreateShader(GL_FRAGMENT_SHADER_ARB);
  256.     // set source for shader
  257.     const GLchar* source = textureParameters.shader_source;
  258.     glShaderSource(fragmentShader, 1, &source, NULL);
  259.     // compile shader
  260.     glCompileShader(fragmentShader);
  261.     // check for errors
  262.     printShaderInfoLog(fragmentShader);
  263.     // attach shader to program
  264.     glAttachShader (glslProgram, fragmentShader);
  265.     // link into full program, use fixed function vertex pipeline
  266.     glLinkProgram(glslProgram);
  267.     // check for errors
  268.     printProgramInfoLog(glslProgram);
  269.     checkGLErrors("render(2)");
  270.     // Get location of the texture samplers for future use
  271.     yParam = glGetUniformLocation(glslProgram, "textureY");
  272.     xParam = glGetUniformLocation(glslProgram, "textureX");
  273. }
  274.  
  275.  
  276. /**
  277.  * Prints results
  278.  */
  279. void printResults () {
  280.     // get GPU results
  281.     float* data = new float[N];
  282.     transferFromTexture (data);
  283.  
  284.     printf("GPU RESULTS:\n");
  285.     printVector (data,N);
  286.  
  287.     delete [] data;
  288. }
  289.  
  290.  
  291. /**
  292.  * Performs the actual calculation.
  293.  */
  294. void performComputation(void)
  295. {
  296.     // attach two textures to FBO
  297.     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachmentpoints[writeTex], textureParameters.texTarget, yTexID[writeTex], 0);
  298.     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachmentpoints[readTex], textureParameters.texTarget, yTexID[readTex], 0);
  299.  
  300.     // enable GLSL program
  301.     glUseProgram(glslProgram);
  302.     // enable texture x (read-only, not changed in the computation loop)
  303.     glActiveTexture(GL_TEXTURE1);
  304.     glBindTexture(textureParameters.texTarget,xTexID);
  305.     glUniform1i(xParam, 1); // texunit 1
  306.  
  307.     // set render destination
  308.     glDrawBuffer (attachmentpoints[writeTex]);
  309.     // enable texture y_old (read-only)
  310.     glActiveTexture(GL_TEXTURE0);
  311.     glBindTexture(textureParameters.texTarget,yTexID[readTex]);
  312.     glUniform1i(yParam,0); // texunit 0
  313.     // and render multitextured viewport-sized quad
  314.     // depending on the texture target, switch between
  315.     // normalised ([0,1]^2) and unnormalised ([0,w]x[0,h])
  316.     // texture coordinates
  317.  
  318.  
  319.     // make quad filled to hit every pixel/texel
  320.     // (should be default but we never know)
  321.     glPolygonMode(GL_FRONT,GL_FILL);
  322.  
  323.     // and render the quad
  324.     if (textureParameters.texTarget == GL_TEXTURE_2D) {
  325.         // render with normalized texcoords
  326.         glBegin(GL_QUADS);
  327.         glTexCoord2f(0.0, 0.0);
  328.         glVertex2f(0.0, 0.0);
  329.         glTexCoord2f(1.0, 0.0);
  330.         glVertex2f(texSize, 0.0);
  331.         glTexCoord2f(1.0, 1.0);
  332.         glVertex2f(texSize, texSize);
  333.         glTexCoord2f(0.0, 1.0);
  334.         glVertex2f(0.0, texSize);
  335.         glEnd();
  336.     } else {
  337.         // render with unnormalized texcoords
  338.         glBegin(GL_QUADS);
  339.         glTexCoord2f(0.0, 0.0);
  340.         glVertex2f(0.0, 0.0);
  341.         glTexCoord2f(texSize, 0.0);
  342.         glVertex2f(texSize, 0.0);
  343.         glTexCoord2f(texSize, texSize);
  344.         glVertex2f(texSize, texSize);
  345.         glTexCoord2f(0.0, texSize);
  346.         glVertex2f(0.0, texSize);
  347.         glEnd();
  348.     }
  349.     // swap role of the two textures (read-only source becomes
  350.     // write-only target and the other way round):
  351.     swap();
  352.  
  353.  
  354.     // done, just do some checks if everything went smoothly.
  355.     checkFramebufferStatus();
  356.     checkGLErrors("render()");
  357. }
  358.  
  359. /**
  360.  * Sets up the various structs used to handle texture targets, texture formats etc.
  361.  */
  362. void createAllTextureParameters(void) {
  363.     rect_arb_rgba_32.name               = "TEXRECT - float_ARB - RGBA - 32";
  364.     rect_arb_rgba_32.texTarget      = GL_TEXTURE_RECTANGLE_ARB;
  365.     rect_arb_rgba_32.texInternalFormat  = GL_RGBA32F_ARB;
  366.     rect_arb_rgba_32.texFormat      = GL_RGBA;
  367.     rect_arb_rgba_32.shader_source  = \
  368.     "#extension GL_ARB_texture_rectangle : enable\n" \
  369.     "uniform sampler2DRect textureY;" \
  370.     "uniform sampler2DRect textureX;" \
  371.     "void main(void) { " \
  372.     "  vec4 y = texture2DRect(textureY, gl_TexCoord[0].st);" \
  373.     "  vec4 x = texture2DRect(textureX, gl_TexCoord[0].st);" \
  374.     "  gl_FragColor = y*x;"\
  375.     "}";
  376.  
  377.     twod_arb_rgba_32.name       = "tex2D - float_ARB - RGBA - 32";
  378.     twod_arb_rgba_32.texTarget      = GL_TEXTURE_2D;
  379.     twod_arb_rgba_32.texInternalFormat  = GL_RGBA32F_ARB;
  380.     twod_arb_rgba_32.texFormat      = GL_RGBA;
  381.     twod_arb_rgba_32.shader_source  = \
  382.     "uniform sampler2D textureY;" \
  383.     "uniform sampler2D textureX;" \
  384.     "void main(void) { " \
  385.     "  vec4 y = texture2D(textureY, gl_TexCoord[0].st);" \
  386.     "  vec4 x = texture2D(textureX, gl_TexCoord[0].st);" \
  387.     "  gl_FragColor = y*x;"\
  388.     "}";
  389. }
  390.  
  391. /**
  392.  * Checks for OpenGL errors.
  393.  * Extremely useful debugging function: When developing,
  394.  * make sure to call this after almost every GL call.
  395.  */
  396. void checkGLErrors (const char *label) {
  397.     GLenum errCode;
  398.     const GLubyte *errStr;
  399.  
  400.     if ((errCode = glGetError()) != GL_NO_ERROR) {
  401.     errStr = gluErrorString(errCode);
  402.     printf("OpenGL ERROR: ");
  403.     printf((char*)errStr);
  404.     printf("(Label: ");
  405.     printf(label);
  406.     printf(")\n.");
  407.     }
  408. }
  409.  
  410. /**
  411.  * Checks framebuffer status.
  412.  * Copied directly out of the spec, modified to deliver a return value.
  413.  */
  414. bool checkFramebufferStatus() {
  415.     GLenum status;
  416.     status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  417.     switch(status) {
  418.         case GL_FRAMEBUFFER_COMPLETE_EXT:
  419.             return true;
  420.         case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
  421.         printf("Framebuffer incomplete, incomplete attachment\n");
  422.             return false;
  423.         case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
  424.         printf("Unsupported framebuffer format\n");
  425.             return false;
  426.         case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
  427.         printf("Framebuffer incomplete, missing attachment\n");
  428.             return false;
  429.         case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
  430.         printf("Framebuffer incomplete, attached images must have same dimensions\n");
  431.             return false;
  432.         case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
  433.         printf("Framebuffer incomplete, attached images must have same format\n");
  434.             return false;
  435.         case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
  436.         printf("Framebuffer incomplete, missing draw buffer\n");
  437.             return false;
  438.         case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
  439.         printf("Framebuffer incomplete, missing read buffer\n");
  440.             return false;
  441.     }
  442.     return false;
  443. }
  444.  
  445. /**
  446.  * error checking for GLSL
  447.  */
  448. void printProgramInfoLog(GLuint obj) {
  449.     int infologLength = 0;
  450.     int charsWritten  = 0;
  451.     char *infoLog;
  452.     glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
  453.     if (infologLength > 1) {
  454.         infoLog = (char *)malloc(infologLength);
  455.         glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
  456.         printf(infoLog);
  457.         printf("\n");
  458.         free(infoLog);
  459.     }
  460. }
  461. void printShaderInfoLog(GLuint obj) {
  462.     int infologLength = 0;
  463.     int charsWritten  = 0;
  464.     char *infoLog;
  465.     glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
  466.     if (infologLength > 1) {
  467.         infoLog = (char *)malloc(infologLength);
  468.         glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
  469.         printf(infoLog);
  470.         printf("\n");
  471.         free(infoLog);
  472.     }
  473. }
  474.  
  475.  
  476. /**
  477.  * Prints out given vector for debugging purposes.
  478.  */
  479. void printVector (const float *p, const int N) {
  480.     for (int i=0; i<N; i++)
  481.     printf("%f\n",p[i]);
  482. }
  483.  
  484.  
  485.  
  486. /**
  487.  * swaps the role of the two y-textures (read-only and write-only)
  488.  * Can be done in a smarter way :-)
  489.  */
  490. void swap(void) {
  491.     if (writeTex == 0) {
  492.     writeTex = 1;
  493.     readTex = 0;
  494.     } else {
  495.     writeTex = 0;
  496.     readTex = 1;
  497.     }
  498. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement