CUDA & OpenGL FrameBuffer Object.

Hello everyone.

I am making a CUDA/OpenGL project. And since I am a newbie to both technologies, I have run into a point where I am not sure what is right and what is wrong. Any help would be appreciated.

Well my project has particles (in a VBO) flying around (thanx to fluidsGL example from the SDK). Now I wanted to render the particles into a texture and operate on it before rendering it on my screen. So I used a FBO and I did it. My problem now was to map the FBO data into a CUDA pointer. So I searched it a bit, and my first attempt was to register my FBO when I was creating it. Here is my function ::

GLuint  fbo,

	texImageID,

	depthBuffer;

void prepareTheFBO()

{

  cout << "prepareTheFBO();" << endl;

  glGenFramebuffersEXT(1, &fbo);

  glGenTextures(1, &texImageID);

  glGenRenderbuffersEXT(1, &depthBuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

	glBindTexture(GL_TEXTURE_2D, texImageID);

	  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

	  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DIM, DIM, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

	  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texImageID, 0);

	glBindTexture(GL_TEXTURE_2D, 0);

	

//	 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);

//	   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, DIM, DIM);

//	   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer);

//	 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

//   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	cutilSafeCall(cudaGraphicsGLRegisterBuffer(&cuda_fbo_resource, fbo, cudaGraphicsMapFlagsNone));

	cutilCheckMsg("cudaGraphicsGLRegisterBuffer FBO failed");

	

//   cutilSafeCall(cudaGraphicsGLRegisterImage(&cuda_fbo_resource, texImageID, GL_TEXTURE_2D, cudaGraphicsMapFlagsNone));

//   cutilCheckMsg("cudaGraphicsGLRegisterBufferImage failed");

}

Then in my display function I use this code ::

GLubyte *offScreenTexture;

size_t offScreenTextureByteSize; 

void display(void) 

{

  glClearColor(0.0, 0.0, 0.0, 1.0);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

	  renderTheParticles();

  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

// Over here I should bind the fbo texture.

  // 	Map it somewhere and pass it on to a cuda function.

  // 	Process it with the cuda function.

  // 	return the results.

  // 	unmap them

  // 	Render them on the screen.

cutilSafeCall(cudaGraphicsMapResources(1, &cuda_fbo_resource, 0));

  cutilCheckMsg(">> cudaGraphicsMapResources fbo failed");

cutilSafeCall(cudaGraphicsResourceGetMappedPointer((void **) &offScreenTexture, &offScreenTextureByteSize, cuda_fbo_resource));

  cutilCheckMsg(">> cudaGraphicsResourceGetMappedPointer fbo failed");

  cout << "offScreenTextureByteSize :: " << offScreenTextureByteSize << endl;

callTestKernel();

cutilSafeCall(cudaGraphicsUnmapResources(1, &cuda_fbo_resource, 0));

  cutilCheckMsg(">> cudaGraphicsUnmapResources fbo failed");

glEnable(GL_TEXTURE_2D);

  glBindTexture(GL_TEXTURE_2D, texImageID);

glGenerateMipmapEXT(GL_TEXTURE_2D);

  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DIM, DIM, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

glPushMatrix();

  glBegin(GL_QUADS);

	glColor3f(1.0f, 1.0f, 1.0f);

	glTexCoord2d(0.0, 0.0); glVertex2d(0.0, 0.0);

	glTexCoord2d(1.0, 0.0); glVertex2d(1.0, 0.0);

	glTexCoord2d(1.0, 1.0); glVertex2d(1.0, 1.0);

	glTexCoord2d(0.0, 1.0); glVertex2d(0.0, 1.0);

  glEnd();

  glPopMatrix();

glBindTexture(GL_TEXTURE_2D, 0);

  glDisable(GL_TEXTURE_2D);

countTheFPS(true);

   glutSwapBuffers();

   glutPostRedisplay();

}

It works as expected (but if you see something wrong, please let me know). But now I have 2 questions.

Q1. The texture I have bounded on my FBO is of size_t DIMDIM4 where DIM is my texture and window dimensions and 4 because of RGBA values. I expected the offScreenTextureByteSize to be of that size but it is 2 times that. I am asking about this, because I want to pass the offScreenTexture into a CUDA kernel and operate on it, but now I don’t know which element refers to which pixel.

Q2. Am I perceiving this whole issue about mapping the FBO to the CUDA memory in some wrong way? Should I not map the buffer, but the texture itself that is bounded on the FBO and then operate on the returned cudaArray pointer?

Thank you in advance for any kind of help.

Hello everyone.

I am making a CUDA/OpenGL project. And since I am a newbie to both technologies, I have run into a point where I am not sure what is right and what is wrong. Any help would be appreciated.

Well my project has particles (in a VBO) flying around (thanx to fluidsGL example from the SDK). Now I wanted to render the particles into a texture and operate on it before rendering it on my screen. So I used a FBO and I did it. My problem now was to map the FBO data into a CUDA pointer. So I searched it a bit, and my first attempt was to register my FBO when I was creating it. Here is my function ::

GLuint  fbo,

	texImageID,

	depthBuffer;

void prepareTheFBO()

{

  cout << "prepareTheFBO();" << endl;

  glGenFramebuffersEXT(1, &fbo);

  glGenTextures(1, &texImageID);

  glGenRenderbuffersEXT(1, &depthBuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

	glBindTexture(GL_TEXTURE_2D, texImageID);

	  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

	  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DIM, DIM, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

	  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texImageID, 0);

	glBindTexture(GL_TEXTURE_2D, 0);

	

//	 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);

//	   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, DIM, DIM);

//	   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer);

//	 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

//   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	cutilSafeCall(cudaGraphicsGLRegisterBuffer(&cuda_fbo_resource, fbo, cudaGraphicsMapFlagsNone));

	cutilCheckMsg("cudaGraphicsGLRegisterBuffer FBO failed");

	

//   cutilSafeCall(cudaGraphicsGLRegisterImage(&cuda_fbo_resource, texImageID, GL_TEXTURE_2D, cudaGraphicsMapFlagsNone));

//   cutilCheckMsg("cudaGraphicsGLRegisterBufferImage failed");

}

Then in my display function I use this code ::

GLubyte *offScreenTexture;

size_t offScreenTextureByteSize; 

void display(void) 

{

  glClearColor(0.0, 0.0, 0.0, 1.0);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

	  renderTheParticles();

  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

// Over here I should bind the fbo texture.

  // 	Map it somewhere and pass it on to a cuda function.

  // 	Process it with the cuda function.

  // 	return the results.

  // 	unmap them

  // 	Render them on the screen.

cutilSafeCall(cudaGraphicsMapResources(1, &cuda_fbo_resource, 0));

  cutilCheckMsg(">> cudaGraphicsMapResources fbo failed");

cutilSafeCall(cudaGraphicsResourceGetMappedPointer((void **) &offScreenTexture, &offScreenTextureByteSize, cuda_fbo_resource));

  cutilCheckMsg(">> cudaGraphicsResourceGetMappedPointer fbo failed");

  cout << "offScreenTextureByteSize :: " << offScreenTextureByteSize << endl;

callTestKernel();

cutilSafeCall(cudaGraphicsUnmapResources(1, &cuda_fbo_resource, 0));

  cutilCheckMsg(">> cudaGraphicsUnmapResources fbo failed");

glEnable(GL_TEXTURE_2D);

  glBindTexture(GL_TEXTURE_2D, texImageID);

glGenerateMipmapEXT(GL_TEXTURE_2D);

  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DIM, DIM, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

glPushMatrix();

  glBegin(GL_QUADS);

	glColor3f(1.0f, 1.0f, 1.0f);

	glTexCoord2d(0.0, 0.0); glVertex2d(0.0, 0.0);

	glTexCoord2d(1.0, 0.0); glVertex2d(1.0, 0.0);

	glTexCoord2d(1.0, 1.0); glVertex2d(1.0, 1.0);

	glTexCoord2d(0.0, 1.0); glVertex2d(0.0, 1.0);

  glEnd();

  glPopMatrix();

glBindTexture(GL_TEXTURE_2D, 0);

  glDisable(GL_TEXTURE_2D);

countTheFPS(true);

   glutSwapBuffers();

   glutPostRedisplay();

}

It works as expected (but if you see something wrong, please let me know). But now I have 2 questions.

Q1. The texture I have bounded on my FBO is of size_t DIMDIM4 where DIM is my texture and window dimensions and 4 because of RGBA values. I expected the offScreenTextureByteSize to be of that size but it is 2 times that. I am asking about this, because I want to pass the offScreenTexture into a CUDA kernel and operate on it, but now I don’t know which element refers to which pixel.

Q2. Am I perceiving this whole issue about mapping the FBO to the CUDA memory in some wrong way? Should I not map the buffer, but the texture itself that is bounded on the FBO and then operate on the returned cudaArray pointer?

Thank you in advance for any kind of help.

I tried to run your code, but the program throws “invalid resource handle” upon executing
cutilSafeCall(cudaGraphicsGLRegisterBuffer(&cuda_fbo_resource,
fbo, cudaGraphicsMapFlagsNone));

How do you make it works? Thanks a lot!

Hi there.

Since then I have changed the code a bit. I don’t know why it does that. But I can help you solve it. You actually want to use the texture that is bind to the fbo right?