cudaGraphicsGLRegisterImage(..)返回CUDAErrorRunKnown;可能的错误源是什么?

cudaGraphicsGLRegisterImage(..)返回CUDAErrorRunKnown;可能的错误源是什么?,cuda,nvidia,gpu,Cuda,Nvidia,Gpu,我正在使用CUDA运行时API。在内核文件的主机代码中,我执行以下操作: 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, nDataFo

我正在使用CUDA运行时API。在内核文件的主机代码中,我执行以下操作:

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);
无论我对纹理的格式和/或数据类型做了什么或做了什么更改,我都会发现cudaerroruneError。我不能相信错误是因为选择了错误的格式,因为官方文档()说,所有这些格式都受支持

那么我要问你的问题是:cudaErrorUnknown在这种情况下还有什么其他原因?

顺便说一下:我以前没有使用过对cudaSetDevice或cudaGLSetGLDevice的调用。当我这样做时,我会遇到“运行时API错误:所有支持CUDA的设备都忙或不可用”的问题。但我已经证明,在调用前后,当前设备的索引是相同的和有效的(我的Quadro 600)

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

这里是我的一个函数,它准备一个纹理,然后向CUDA注册。也许它能帮助你

// 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));
}
在调用此函数之前,我调用:

InitGL(&argc, argv));
g_cuda_device = cutGetMaxGflopsDeviceId();
cudaSetDevice(g_cuda_device);
cudaGLSetGLDevice(g_cuda_device);
将设备更改为非默认设置时,我调用:

GLDeviceInit(g_cuda_device);
我认为问题(除了调用
new
后出现的奇怪的
()
——这到底是什么?)在于您正在将一个ID作为目标参数传递给
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);
任何
glTexImage*
调用的第一个参数都是target,它是
enum
值,而不是纹理ID。您应该具有如下内容:

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);

所以我认为这是一个OpenGL问题,而不是CUDA问题——如果检查GL错误,您可能会在调用
glTexImage3D
后看到无效值错误或其他东西。存在GL错误状态这一事实可能解释了为什么您得到
cudaErrorUnknown

有人敢问什么
unsigned char*pData=new unsigned char*[2*256*256]()
应该是?是的,即使最后没有奇怪的函数调用
()
,您也希望分配一个
字符数组,而不是
字符数组*
,对吗?另外,您是否调用过
glBindTexture()
?@Talonmes您是对的,这是一个键入错误。@harrism是的,我以前在创建纹理时调用过它。或者你的意思是在我调用cudaGraphicsGLRegisterImage之前必须再次绑定纹理?@harrism好的,这可能就是问题所在。我期望的正好相反,就像本教程中描述的那样。我将在星期一试一试。这是你的教程,不是吗?在源代码中,在cudaGraphicsGLRegisterImage调用之前取消绑定纹理,在上面的示例中,明确绑定纹理。你能解释一下吗?@morph:这不是我的教程。我不确定是否需要取消绑定自由绑定序列,但它确实有效。您确定同时调用
cudaSetDevice()
cudaGLSetGLDevice()
是个好主意吗?“注意,
cudaSetDevice()
cudaGLSetGLDevice()
是相互排斥的。”@shinjin:谢谢你提供的信息。我查看了一个旧版本的CUDA C编程指南,它没有关于两个调用互斥的语言。我将检查应用程序是否只与
cudaGLSetGLDevice()
一起工作,并更新example.OFFTOPIC:(除了调用new后的奇怪()之外--这到底是什么?-->不要问我从哪里得到的,但我刚刚在vs10的调试器中重新编程了这一点:()-运算符用0初始化数组。很抱歉,这个错误我认为是正确的,因为它是在我们庞大的框架中的其他地方完成的。我只是处理一个包含已经初始化的textureID的对象,因此我在上面绘制了这个glTexImage3D代码,以获得更全面的上下文和glBindTexture调用的提示?如我所述,
glTexImage3D
的第一个参数必须是
GL\u TEXTURE\u 3D
。如果
nTextureID
有其他值,那么它可能是错误的。正如我已经提到的,我的包含glTexImage3D的代码只是一些外部库内容的占位符。但是我可以证明库正确调用了glTexImage3D函数。在您的问题中,对于
glTexImage3D
的目标参数,您的代码仍然通过
nTextureID
。只要您的代码在这里这样做,我只能假设它在现实世界中这样做,这将是一个错误。如果这只是伪代码,那么任何人都很难提供帮助。