zoukankan      html  css  js  c++  java
  • 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缓冲对象的)

      完整代码如下:

    • .cuh文件
    #include "cuda_runtime.h" //CUDA运行时API
    #include "device_launch_parameters.h"
    #include <cuda.h>
    #include "GL/glew.h"
    #include <cuda_gl_interop.h>
    #include <iostream>
    #include <stdio.h>
    
    class GenVertex
    {
    public:
        GenVertex();
        ~GenVertex();
        void setVBO(unsigned int vbo);
        void createVtxWithCuda();
    
    private:
        unsigned int VBO;
    
    private:
        void setup();
    };
    • .cu文件
    #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!");
        }
    }
  • 相关阅读:
    重新定位Excel Addin插件的方法
    VBA调用DOS程序两种方法
    Simulink Memory vs Unit Delay
    C#对象序列化与反序列化zz
    [leetcode]Sqrt(x) @ Python
    [leetcode]Sort Colors @ Python
    [leetcode]Pow(x, n) @ Python
    [leetcode]Edit Distance @ Python
    [leetcode]Rotate Image @ Python
    [leetcode]Length of Last Word @ Python
  • 原文地址:https://www.cnblogs.com/chen9510/p/11530567.html
Copyright © 2011-2022 走看看