CUDA 与 OpenGL 的互操作

2019-09-17 09:56:39来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

CUDA 与 OpenGL 的互操作

 

  CUDA 与 OpenGL 的互操作一般是使用CUDA生成数据,然后在OpenGL中渲染数据对应的图形。这两者的结合有两种方式:

    1、使用OpenGL中的PBO(像素缓冲区对象)。CUDA生成像素数据,OpenGL直接渲染即可。

    2、使用OpenGL中的FBO(顶点缓冲区对象)。CUDA生成顶点数据,OpenGL渲染。

  这两种方法的核心都是将OpenGL中的缓冲区对象映射到CUDA内存空间中(让CUDA的内存指针指向OpenGL的缓冲区),这样就不需要将缓冲区中的数据传输至CUDA内存中,然后利用CUDA的高并行计算性能加速计算,最后直接使用OpenGL渲染。

  

  一个例子,使用CUDA根据时间动态生成16个点,在屏幕上显示。

  步骤:

  1、设置与OpenGL互操作的设备

status=cudaGLSetGLDevice(0);

  2、在CUDA中注册缓冲区对象

status = cudaGLRegisterBufferObject(this->VBO);

  3、映射缓冲区对象:让CUDA内存指针指向缓冲区对象对应的空间

// 映射缓冲对象
    float4* position;
    status=cudaGLMapBufferObject((void**)&position, this->VBO);

  4、运行核函数

// 运行核函数
    dim3 dimBlock(4, 4, 1);
    dim3 dimGrid(1);
    KernelFunc<<<dimGrid, dimBlock>>>(position, clock(), 4, 4);
    cudaThreadSynchronize(); //同步线程

  5、取消映射

status=cudaGLUnmapBufferObject(this->VBO);

 效果图:

  

  注意:当CUDA的kernel函数修改CUDA指针指向的空间超出OpenGL缓冲对象大小时,会导致后面出现取消映射失败。(这里所说的CUDA指针是映射到OpenGL缓冲对象的)

  完整代码如下:

  

#include "GenVertex.cuh"
#include <time.h>


__global__ void KernelFunc(float4* position, float time, unsigned int width, unsigned int height)
{
    unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
    unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
    float u = x / (float)width;
    float v = y / (float)height;
    u = u*2.0f - 1.0f;
    v = v*2.0f - 1.0f;
    float freq = 4.0f;
    float w = sinf(u*freq + time*0.001f)*cosf(v*freq + time*0.001f)*0.5f;
    position[y*width + x] = make_float4(u*10, w*10, v*10, 1.0f);
}

GenVertex::GenVertex()
{
    this->setup();
}

GenVertex::~GenVertex()
{
}

void GenVertex::setup() {
    cudaError_t status;
    //设备设置
    status=cudaGLSetGLDevice(0);
    if (status != cudaSuccess) {
        puts("setup Device failed!");
    }
}

void GenVertex::setVBO(unsigned int vbo) {
    this->VBO = vbo;
    cudaError_t status;
    status = cudaGLRegisterBufferObject(this->VBO);
    if (status != cudaSuccess) {
        puts("Register buffer object failed!");
    }
}


void GenVertex::createVtxWithCuda()
{
    cudaError_t status;
    // 映射缓冲对象
    float4* position;
    status=cudaGLMapBufferObject((void**)&position, this->VBO);
    if (status != cudaSuccess) {
        puts("map buffer object failed!");
    }
    // 运行核函数
    dim3 dimBlock(4, 4, 1);
    dim3 dimGrid(1);
    KernelFunc<<<dimGrid, dimBlock>>>(position, clock(), 4, 4);
    cudaThreadSynchronize(); //同步线程
    status=cudaGLUnmapBufferObject(this->VBO);
    if (status != cudaSuccess) {
        puts("unmap buffer object failed!");
    }
}

 


原文链接:https://www.cnblogs.com/chen9510/p/11530567.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:对象的构造与析构(一)

下一篇:C++ --const修饰指针