Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // includes
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <time.h>
- #include <GL/glew.h>
- #include <GL/glut.h>
- // 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 printResults(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 printProgramInfoLog(GLuint obj);
- void printShaderInfoLog(GLuint 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);
- // problem size, texture size, number of iterations (set from command line)
- int N;
- int texSize;
- // 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
- GLuint glslProgram;
- GLuint fragmentShader;
- 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
- twod_arb_rgba_32; // texture 2ds, texture_float_ARB, RGBA, 32 bits
- // struct actually being used (set from command line)
- struct_textureParameters textureParameters;
- // actual data
- float* dataX;
- float* dataY;
- /**
- * main, just calls things in the appropriate order
- */
- int main(int argc, char **argv)
- {
- if(argc < 2)
- {
- printf("USAGE: glsl <NUM OF ELEMENTS>\n");
- }
- else
- {
- N = atoi (argv[1]);
- // create variables for GL
- createAllTextureParameters();
- textureParameters = rect_arb_rgba_32;
- // 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<N; i++)
- {
- dataX[i] = 10;
- dataY[i] = 20;
- }
- // init glut and glew
- initGLUT(argc, argv);
- initGLEW();
- // init offscreen framebuffer
- initFBO();
- // create textures for vectors
- createTextures();
- // init shader runtime
- initGLSL();
- // and start computation
- performComputation();
- // print results
- printResults();
- // and clean up
- glDetachShader(glslProgram, fragmentShader);
- glDeleteShader(fragmentShader);
- glDeleteProgram(glslProgram);
- glDeleteFramebuffersEXT(1,&fb);
- free(dataX);
- free(dataY);
- glDeleteTextures(2,yTexID);
- glDeleteTextures (1,&xTexID);
- glutDestroyWindow (glutWindowHandle);
- }
- // exit
- return 0;
- }
- /**
- * Sets up a floating point texture with NEAREST filtering.
- * (mipmaps etc. are unsupported for floating point textures)
- */
- void setupTexture (const GLuint texID) {
- // make active and bind
- glBindTexture(textureParameters.texTarget,texID);
- // turn off filtering and wrap modes
- glTexParameteri(textureParameters.texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(textureParameters.texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(textureParameters.texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(textureParameters.texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);
- // define texture with floating point format
- glTexImage2D(textureParameters.texTarget,0,textureParameters.texInternalFormat,texSize,texSize,0,textureParameters.texFormat,GL_FLOAT,0);
- // check if that worked
- if (glGetError() != GL_NO_ERROR) {
- printf("glTexImage2D():\t\t\t [FAIL]\n");
- exit (ERROR_TEXTURE);
- }
- }
- /**
- * Transfers data from currently texture, and stores it in given array.
- */
- void transferFromTexture(float* data)
- {
- glReadBuffer(attachmentpoints[readTex]);
- glReadPixels(0, 0, texSize, texSize,textureParameters.texFormat,GL_FLOAT,data);
- }
- /**
- * Transfers data to texture.
- * Check web page for detailed explanation on the difference between ATI and NVIDIA.
- */
- void transferToTexture (float* data, GLuint texID)
- {
- glBindTexture(textureParameters.texTarget, texID);
- glTexSubImage2D(textureParameters.texTarget,0,0,0,texSize,texSize,textureParameters.texFormat,GL_FLOAT,data);
- }
- /**
- * creates textures, sets proper viewport etc.
- */
- void createTextures (void) {
- // create textures
- // y gets two textures, alternatingly read-only and write-only,
- // x is just read-only
- glGenTextures (2, yTexID);
- glGenTextures (1, &xTexID);
- // set up textures
- setupTexture (yTexID[readTex]);
- transferToTexture(dataY,yTexID[readTex]);
- setupTexture (yTexID[writeTex]);
- transferToTexture(dataY,yTexID[writeTex]);
- setupTexture (xTexID);
- transferToTexture(dataX,xTexID);
- // set texenv mode from modulate (the default) to replace
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- // check if something went completely wrong
- checkGLErrors ("createFBOandTextures()");
- }
- /**
- * Sets up GLUT, creates "window" (better put: valid GL context, since the window is never displayed)
- */
- void initGLUT(int argc, char **argv) {
- glutInit ( &argc, argv );
- glutWindowHandle = glutCreateWindow("GLSL");
- }
- /**
- * Sets up GLEW to initialise OpenGL extensions
- */
- void initGLEW (void) {
- int err = glewInit();
- // sanity check
- if (GLEW_OK != err) {
- printf((char*)glewGetErrorString(err));
- exit(ERROR_GLEW);
- }
- }
- /**
- * Creates framebuffer object, binds it to reroute rendering operations
- * from the traditional framebuffer to the offscreen buffer
- */
- void initFBO(void) {
- // create FBO (off-screen framebuffer)
- glGenFramebuffersEXT(1, &fb);
- // bind offscreen framebuffer (that is, skip the window-specific render target)
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
- // viewport for 1:1 pixel=texture mapping
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(0.0, texSize, 0.0, texSize);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glViewport(0, 0, texSize, texSize);
- }
- /**
- * Sets up the GLSL runtime and creates shader.
- */
- void initGLSL(void) {
- // create program object
- glslProgram = glCreateProgram();
- // create shader object (fragment shader)
- fragmentShader = glCreateShader(GL_FRAGMENT_SHADER_ARB);
- // set source for shader
- const GLchar* source = textureParameters.shader_source;
- glShaderSource(fragmentShader, 1, &source, NULL);
- // compile shader
- glCompileShader(fragmentShader);
- // check for errors
- printShaderInfoLog(fragmentShader);
- // attach shader to program
- glAttachShader (glslProgram, fragmentShader);
- // link into full program, use fixed function vertex pipeline
- glLinkProgram(glslProgram);
- // check for errors
- printProgramInfoLog(glslProgram);
- checkGLErrors("render(2)");
- // Get location of the texture samplers for future use
- yParam = glGetUniformLocation(glslProgram, "textureY");
- xParam = glGetUniformLocation(glslProgram, "textureX");
- }
- /**
- * Prints results
- */
- void printResults () {
- // get GPU results
- float* data = new float[N];
- transferFromTexture (data);
- 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);
- // enable GLSL program
- glUseProgram(glslProgram);
- // enable texture x (read-only, not changed in the computation loop)
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(textureParameters.texTarget,xTexID);
- glUniform1i(xParam, 1); // texunit 1
- // set render destination
- glDrawBuffer (attachmentpoints[writeTex]);
- // enable texture y_old (read-only)
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(textureParameters.texTarget,yTexID[readTex]);
- glUniform1i(yParam,0); // texunit 0
- // and render multitextured viewport-sized quad
- // depending on the texture target, switch between
- // normalised ([0,1]^2) and unnormalised ([0,w]x[0,h])
- // texture coordinates
- // make quad filled to hit every pixel/texel
- // (should be default but we never know)
- glPolygonMode(GL_FRONT,GL_FILL);
- // and render the quad
- if (textureParameters.texTarget == GL_TEXTURE_2D) {
- // render with normalized texcoords
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0);
- glVertex2f(0.0, 0.0);
- glTexCoord2f(1.0, 0.0);
- glVertex2f(texSize, 0.0);
- glTexCoord2f(1.0, 1.0);
- glVertex2f(texSize, texSize);
- glTexCoord2f(0.0, 1.0);
- glVertex2f(0.0, texSize);
- glEnd();
- } else {
- // render with unnormalized texcoords
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0);
- glVertex2f(0.0, 0.0);
- glTexCoord2f(texSize, 0.0);
- glVertex2f(texSize, 0.0);
- glTexCoord2f(texSize, texSize);
- glVertex2f(texSize, texSize);
- glTexCoord2f(0.0, texSize);
- glVertex2f(0.0, texSize);
- glEnd();
- }
- // swap role of the two textures (read-only source becomes
- // write-only target and the other way round):
- swap();
- // done, just do some checks if everything went smoothly.
- checkFramebufferStatus();
- checkGLErrors("render()");
- }
- /**
- * Sets up the various structs used to handle texture targets, texture formats etc.
- */
- void createAllTextureParameters(void) {
- rect_arb_rgba_32.name = "TEXRECT - float_ARB - RGBA - 32";
- rect_arb_rgba_32.texTarget = GL_TEXTURE_RECTANGLE_ARB;
- rect_arb_rgba_32.texInternalFormat = GL_RGBA32F_ARB;
- rect_arb_rgba_32.texFormat = GL_RGBA;
- rect_arb_rgba_32.shader_source = \
- "#extension GL_ARB_texture_rectangle : enable\n" \
- "uniform sampler2DRect textureY;" \
- "uniform sampler2DRect textureX;" \
- "void main(void) { " \
- " vec4 y = texture2DRect(textureY, gl_TexCoord[0].st);" \
- " vec4 x = texture2DRect(textureX, gl_TexCoord[0].st);" \
- " gl_FragColor = y*x;"\
- "}";
- twod_arb_rgba_32.name = "tex2D - float_ARB - RGBA - 32";
- twod_arb_rgba_32.texTarget = GL_TEXTURE_2D;
- twod_arb_rgba_32.texInternalFormat = GL_RGBA32F_ARB;
- twod_arb_rgba_32.texFormat = GL_RGBA;
- twod_arb_rgba_32.shader_source = \
- "uniform sampler2D textureY;" \
- "uniform sampler2D textureX;" \
- "void main(void) { " \
- " vec4 y = texture2D(textureY, gl_TexCoord[0].st);" \
- " vec4 x = texture2D(textureX, gl_TexCoord[0].st);" \
- " gl_FragColor = y*x;"\
- "}";
- }
- /**
- * Checks for OpenGL errors.
- * Extremely useful debugging function: When developing,
- * make sure to call this after almost every GL call.
- */
- void checkGLErrors (const char *label) {
- GLenum errCode;
- const GLubyte *errStr;
- if ((errCode = glGetError()) != GL_NO_ERROR) {
- errStr = gluErrorString(errCode);
- printf("OpenGL ERROR: ");
- printf((char*)errStr);
- printf("(Label: ");
- printf(label);
- printf(")\n.");
- }
- }
- /**
- * Checks framebuffer status.
- * Copied directly out of the spec, modified to deliver a return value.
- */
- bool checkFramebufferStatus() {
- GLenum status;
- status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- switch(status) {
- case GL_FRAMEBUFFER_COMPLETE_EXT:
- return true;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- printf("Framebuffer incomplete, incomplete attachment\n");
- return false;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- printf("Unsupported framebuffer format\n");
- return false;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- printf("Framebuffer incomplete, missing attachment\n");
- return false;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- printf("Framebuffer incomplete, attached images must have same dimensions\n");
- return false;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- printf("Framebuffer incomplete, attached images must have same format\n");
- return false;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- printf("Framebuffer incomplete, missing draw buffer\n");
- return false;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- printf("Framebuffer incomplete, missing read buffer\n");
- return false;
- }
- return false;
- }
- /**
- * error checking for GLSL
- */
- void printProgramInfoLog(GLuint obj) {
- int infologLength = 0;
- int charsWritten = 0;
- char *infoLog;
- glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
- if (infologLength > 1) {
- infoLog = (char *)malloc(infologLength);
- glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
- printf(infoLog);
- printf("\n");
- free(infoLog);
- }
- }
- void printShaderInfoLog(GLuint obj) {
- int infologLength = 0;
- int charsWritten = 0;
- char *infoLog;
- glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
- if (infologLength > 1) {
- infoLog = (char *)malloc(infologLength);
- glGetShaderInfoLog(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<N; i++)
- printf("%f\n",p[i]);
- }
- /**
- * swaps the role of the two y-textures (read-only and write-only)
- * Can be done in a smarter way :-)
- */
- void swap(void) {
- if (writeTex == 0) {
- writeTex = 1;
- readTex = 0;
- } else {
- writeTex = 0;
- readTex = 1;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement