0
votes

I am using the CUDA runtime API. In my kernel file's host code I do the following:

unsigned char* pData = new unsigned char[2*256*256*256]();

glTexImage3D(
  nTextureID, // created before (glBindTexture etc.)
  0, 
  nInternalFormat, // GL_LUMINANCE_ALPHA
  256, 
  256, 
  256, 
  0, 
  nDataFormat, // GL_LUMINANCE8_ALPHA8
  nDataType, // GL_UNSIGNED_BYTE
  pData);

/* ... still in OpenGL context ... */

cudaGraphicsResource* pGraphicResource = 0;
cudaError_t eError = cudaGraphicsGLRegisterImage(
  &pGraphicResource, 
  nTextureID, 
  GL_TEXTURE_3D, 
  cudaGraphicsRegisterFlagsSurfaceLoadStore);

Whatever I do or change concerning the texture's format and/or data type I always get cudaErrorUnknown for eError. I can't believe that the error is because of chosing a wrong format, because the official documentation (external link) says, that all these formats are supported.

So my question to you: What other reasons may the cudaErrorUnknown have in this context?

By the way: I didn't use a call of cudaSetDevice or cudaGLSetGLDevice before. When I do so I get problems with "Runtime API error : all CUDA-capable devices are busy or unavailable". But I have proved that the index of the current device is the same and a valid one (my Quadro 600) before and after the call.

My GPU: NVIDIA Quadro 600 My SDK: NVIDIA CUDA Toolkit v4.1

2
Dare one ask what unsigned char* pData = new unsigned char*[2*256*256*256](); is supposed to be? - talonmies
Yeah, even without the bizarre function call () at the end, you want to allocate an array of char, not and array of char*, right? Also, do you ever call glBindTexture()? - harrism
@talonmies you're right, that was a typing error. - morph
@harrism yes, i call that before when I create my texture. Or do you mean that the texture has to be bind again before I call cudaGraphicsGLRegisterImage? - morph
@harrism OK, that might be the problem. I expected the opposite like it is described in this tutorial rauwendaal.net/2011/12/02/…. I will give it a try on monday. - morph

2 Answers

1
votes

Here is a function of mine that prepares a texture and then registers it with CUDA. Maybe it can help you.

// Create a texture and register it for sharing with CUDA.
void CreateAndRegisterTex(GLuint& tex, cudaGraphicsResource*& resource, u32 w, u32 h) {
  u32 i(0);
  uchar4* buf((uchar4*)malloc(w * h * sizeof(uchar4)));
  glGenTextures(1, &tex);
  glBindTexture(GL_TEXTURE_2D, tex);
  // glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // program works without this but maybe it should be in there?
  glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
  glBindTexture(GL_TEXTURE_2D, 0);
  free(buf);
  glBindTexture(GL_TEXTURE_2D, tex);
  // Register this image for sharing with CUDA. cudaGraphicsGLRegisterImage()
  // supports all texture formats with 1, 2, or 4 components and an internal
  // type of float (e.g. GL_RGBA_FLOAT32) and unnormalized integer (e.g.
  // GL_RGBA8UI). It does not currently support normalized integer formats (e.g.
  // GL_RGBA8). Please note that since GL_RGBA8UI is an OpenGL 3.0 texture
  // format, it can only be written by shaders, not the fixed function pipeline.
  cutilSafeCall(cudaGraphicsGLRegisterImage(&resource, tex, GL_TEXTURE_2D,
                                            cudaGraphicsMapFlagsWriteDiscard));
}

Before calling this function, I call:

InitGL(&argc, argv));
g_cuda_device = cutGetMaxGflopsDeviceId();
cudaSetDevice(g_cuda_device);
cudaGLSetGLDevice(g_cuda_device);

When changing the device to other than default, I call:

GLDeviceInit(g_cuda_device);
1
votes

I think the problem (other than the strange () after your call to new -- what the heck is that?) is that you are passing an ID as the target parameter to glTexImage3D:

unsigned char* pData = new unsigned char[2*256*256*256](); // note weird parens here

glTexImage3D(
  nTextureID, // created before (glBindTexture etc.)
  0, 
  nInternalFormat, // GL_LUMINANCE_ALPHA
  256, 
  256, 
  256, 
  0, 
  nDataFormat, // GL_LUMINANCE8_ALPHA8
  nDataType, // GL_UNSIGNED_BYTE
  pData);

The first argument of any glTexImage* call is the target, which is an enum value, not the texture ID. What you should have is something like this:

glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);

glTexImage3D(
  GL_TEXTURE_3D,
  0, 
  nInternalFormat, // GL_LUMINANCE_ALPHA
  256, 
  256, 
  256, 
  0, 
  nDataFormat, // GL_LUMINANCE8_ALPHA8
  nDataType, // GL_UNSIGNED_BYTE
  pData);

So I think this is an OpenGL problem, not a CUDA problem -- if you check for GL errors you will probably see an invalid value error or something after the glTexImage3D call. The fact that there is a GL error state probably explains why you get cudaErrorUnknown.