映射PBO cudaGraphicsResource时出错

时间:2013-06-27 15:25:45

标签: c++ visual-studio-2010 opengl cuda

我有一个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);
}

1 个答案:

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

如果你拥有一大堆资源,这个数字是没有预先确定的,那么这很有用。在通常情况下,您不需要动态分配。