我有一个关于CUDA缓冲区访问的问题:我注册了一个OpenGL缓冲区来使用CUDA,cudaGraphicsGLRegisterBuffer()没有返回错误(即成功),但是当我想用cudaGraphicsMapResources()映射我的PBO时,我得到"cudaErrorMapBufferObjectFailed“。
以下是我的代码(经过简化,但包含了相关部分):
在.h文件中
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..我在一台装有Windows7的x64电脑上,在一台GTX580上运行CUDA4.2。
编辑:以下是修改后的代码
在.h文件中
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);
}发布于 2013-06-28 00:25:14
cudaGraphisMapResources接受一个指针作为第二个参数。不是指向指针的指针。您的PBO_CUDA_Widget变量已经是一个指针。调用应该是(不带地址,即省略'&'):
cudaError_t error_test = cudaGraphicsMapResources(1, PBO_CUDA_Widget, 0);请记住,在启动访问资源的OpenGL内核之前,要解除PBO与CUDA的绑定。
顺便说一句:从OpenGL1.5开始,OpenGL Buffer对象就一直是核心OpenGL的一部分。任何支持CUDA的图形处理器也支持比OpenGL-2更好的=>不要使用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成为一个指针是什么意思呢?好吧,这样的话:
cudaGraphicsResource_t *p_cuda_gr_resources =
malloc(count * sizeof cudaGraphicsResource_t);
/* do some stuff */
free(p_cuda_gr_resources);如果你有一大堆资源,这是很有用的,这个数字不是预先确定的。不过,在通常情况下,您不需要动态分配。
https://stackoverflow.com/questions/17347193
复制相似问题