我有一个CUDA缓冲区访问的问题:我注册一个OpenGL缓冲区以使用它与CUDA,cudaGraphicsGLRegisterBuffer()返回没有错误(即cudasucess),但当我想用cudaGraphicsMapResources()映射我的PBO时,我得到“ cudaErrorMapBufferObjectFailed”。
这是我的代码(简化但有相关部分):
<。>文件中的
GLuint bufferID;
struct cudaGraphicsResource* PBO_CUDA_Widget;
在.cpp文件中
void HDR_GLWidget::initializeGL()
{
cutilSafeCall(cudaGLSetGLDevice(cutGetMaxGflopsDeviceId()));
// create pixel buffer object
glGenBuffersARB(1, &bufferID);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufferID);
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * 4, NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
cudaError_t error_test = cudaGraphicsGLRegisterBuffer(&PBO_CUDA_Widget, bufferID, cudaGraphicsMapFlagsWriteDiscard); //no cuda error here
}
void HDR_GLWidget::uploadBuffer
{
cudaError_t error_test = cudaGraphicsMapResources(1, &PBO_CUDA_Widget, 0); //crash here
[...]
}
这是我得到的错误:
First-chance exception at 0x000007fefd47bccd in IHM_Qt_TM_cuda.exe: Microsoft C++ exception: cudaError_enum at memory location 0x073ff200..
我正在使用Windows 7的x64机器,GTX580上的CUDA 4.2。
编辑:这是修改后的代码
<。>文件中的
cudaGraphicsResource* PBO_CUDA_Widget;
GLuint bufferID;
在.cpp文件中
void HDR_GLWidget::initializeGL()
{
cutilSafeCall(cudaGLSetGLDevice(cutGetMaxGflopsDeviceId()));
GLenum err = glewInit();
glGenBuffers(1, &bufferID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferID);
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * 4, NULL, GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
cutilSafeCall(cudaMalloc((void**) PBO_CUDA_Widget, width * height * sizeof(uchar4)));
cudaError_t error_reg = cudaGraphicsGLRegisterBuffer((cudaGraphicsResource **)PBO_CUDA_Widget, bufferID, cudaGraphicsMapFlagsWriteDiscard);
}
void HDR_GLWidget::uploadBuffer()
{
cudaError_t error_map = cudaGraphicsMapResources(1, (cudaGraphicsResource_t*)PBO_CUDA_Widget, 0); //error here
[...]
cudaError_t flag_unmap = cudaGraphicsUnmapResources(1, (cudaGraphicsResource_t*)PBO_CUDA_Widget, 0);
}
答案 0 :(得分:3)
cudaGraphisMapResources将指针作为第二个参数。不是指向指针的指针。您的PBO_CUDA_Widget
变量已经是指针。呼叫应该是(不带地址,即省略'&amp;'):
cudaError_t error_test = cudaGraphicsMapResources(1, PBO_CUDA_Widget, 0);
在启动访问资源的CUDA内核之前,请记住从OpenGL中取消绑定PBO。
BTW:自OpenGL-1.5以来,OpenGL Buffer Objects已成为核心OpenGL的一部分。任何支持CUDA的GPU也支持比OpenGL-2 =&gt;更好的支持。请勿使用ARB
后缀。
这是我的一个项目的实际测试代码。从技术上讲,它分散在几个函数上,变量名称略有不同。但是将它合并为一个单独的函数它就是这样的。
void example(void)
{
GLuint pbo_ID;
size_t pbo_size = ...;
// note the type, there's no '*' and it's initialized to 0
cudaGraphicsResource_t cgr = 0;
glGenBuffers(1, &pbo_ID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_ID);
glBufferData(GL_PIXEL_UNPACK_BUFFER, pbo_size, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
cudaGraphicsGLRegisterBuffer(&cgr, pbo_ID, cudaGraphicsRegisterFlagsWriteDiscard);
cudaGraphicsMapResources(1, &cgr, 0);
void *ptr;
size_t mapped_size;
cudaGraphicsResourceGetMappedPointer(
&ptr, &mapped_size, cgr);
cudaArray_t array;
cudaGraphicsSubResourceGetMappedArray(
&array,
cgr,
0, 0 );
call_CUDA_kernel();
cudaGraphicsUnmapResources(1, &cgr, 0);
}
现在我的意思是让cudaGrapicsResource
成为你的malloc指针。那么这样:
cudaGraphicsResource_t *p_cuda_gr_resources =
malloc(count * sizeof cudaGraphicsResource_t);
/* do some stuff */
free(p_cuda_gr_resources);
如果你拥有一大堆资源,这个数字是没有预先确定的,那么这很有用。在通常情况下,您不需要动态分配。