opengl - Cuda 和 OpenGL 互操作

标签 opengl cuda

我一直在阅读 CUDA 文档,在我看来,每个需要与 OpenGL 接口(interface)的缓冲区都需要在 glBuffer 中创建。

根据 nvidia 编程指南,必须这样做:

GLuint positionsVBO;
struct cudaGraphicsResource* positionsVBO_CUDA;

int main() {

    // Explicitly set device
    cudaGLSetGLDevice(0);
    // Initialize OpenGL and GLUT
    ...
    glutDisplayFunc(display);
    // Create buffer object and register it with CUDA
    glGenBuffers(1, positionsVBO);
    glBindBuffer(GL_ARRAY_BUFFER, &vbo);
    unsigned int size = width * height * 4 * sizeof(float);
    glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    cudaGraphicsGLRegisterBuffer(&positionsVBO_CUDA, positionsVBO, cudaGraphicsMapFlagsWriteDiscard);

    // Launch rendering loop
    glutMainLoop();
}
void display() {
    // Map buffer object for writing from CUDA
    float4* positions;
    cudaGraphicsMapResources(1, &positionsVBO_CUDA, 0);
    size_t num_bytes;
    cudaGraphicsResourceGetMappedPointer((void**)&positions, &num_bytes, positionsVBO_CUDA));
    // Execute kernel
    dim3 dimBlock(16, 16, 1);
    dim3 dimGrid(width / dimBlock.x, height / dimBlock.y, 1);
    createVertices<<<dimGrid, dimBlock>>>(positions, time, width, height);
    // Unmap buffer object
    cudaGraphicsUnmapResources(1, &positionsVBO_CUDA, 0);
    // Render from buffer object
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBindBuffer(GL_ARRAY_BUFFER, positionsVBO);
    glVertexPointer(4, GL_FLOAT, 0, 0);
    glEnableClientState(GL_VERTEX_ARRAY);
    glDrawArrays(GL_POINTS, 0, width * height);
    glDisableClientState(GL_VERTEX_ARRAY);
    // Swap buffers
    glutSwapBuffers();
    glutPostRedisplay();
}
void deleteVBO() {
    cudaGraphicsUnregisterResource(positionsVBO_CUDA);
    glDeleteBuffers(1, &positionsVBO);
}

__global__ void createVertices(float4* positions, float time, unsigned int width, unsigned int height) { 
    // [....]
}

有没有办法将 cudaMalloc 创建的内存空间直接提供给 OpenGL?我已经在 cuda 上编写了工作代码,我想将我的 float4 数组直接放入 OpenGL。

说如果已经有这样的代码:
float4 *cd = (float4*) cudaMalloc(elements*sizeof(float4)). 
do_something<<<16,1>>>(cd);

我想通过OpenGL显示do_something的输出。

旁注:为什么 cudaGraphicsResourceGetMappedPointer 函数在每个时间步上运行?

最佳答案

从 CUDA 4.0 开始,OpenGL 互操作是单向的。这意味着要做你想做的事情(运行一个将数据写入 GL 缓冲区或纹理图像的 CUDA 内核),你必须将缓冲区映射到一个设备指针,并将该指针传递给你的内核,如你的示例所示。

至于您的旁注:每次调用 display() 时都会调用 cudaGraphicsResourceGetMappedPointer ,因为每帧都会调用 cudaGraphicsMapResource 。任何时候你重新映射一个资源,你都应该重新获取映射的指针,因为它可能已经改变了。为什么要重新映射每一帧?好吧,出于性能原因(尤其是在内存密集型 GL 应用程序中),OpenGL 有时会在内存中移动缓冲区对象。如果您始终保持资源映射,则它无法做到这一点,并且性能可能会受到影响。我相信 GL 虚拟化内存对象的能力和需要也是当前 GL 互操作 API 是单向的原因之一(不允许 GL 移动 CUDA 分配,因此您无法映射 CUDA 分配的设备指针到 GL 缓冲区对象中)。

关于opengl - Cuda 和 OpenGL 互操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6481123/

相关文章:

crash - CUDA - nvidia 驱动程序在运行时崩溃

java - OpenGL 1.1 和当前 4.3 之间的主要区别是什么?

c++ - opengl 3.3 中的黑屏输出

opengl - 如何使用 OpenGL 阵列纹理?

cuda - 指定结束位时 cub::DeviceRadixSort 失败

git - 在 Git 扩展中添加 .cu 和 .cuh 作为 'c' 代码

c++ - 计算角度/曲率?

opengl - WebKit 是否使用 OpenGL 来呈现 CSS 过渡?

c++ - 如何在设备内存中有效地随机播放数据?

c++ - Cuda cudaGetTextureReference 返回 "invalid texture reference"