【问题标题】:How to Access data on cuda by openGL?如何通过openGL访问cuda上的数据?
【发布时间】:2014-06-01 02:40:35
【问题描述】:

我一般都学过 OpenGL 与 CUDA 的互操作性,但是我的问题是这样的:

我有很多数组,一些用于顶点,一些用于规范,一些用于单独的 alpha 值,还有一些指向设备内存上这些数组的指针(例如 dev_ver,dev_norm),它们在内核中使用。我已经映射了资源,现在我想在着色器中使用这些数据来制作一些效果。我的渲染代码是这样的:

glUseProgram                (programID);

glBindBuffer                (GL_ARRAY_BUFFER, vertexBuffer_0);
glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_0, GL_DYNAMIC_DRAW);
glVertexAttribPointer       (0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

glBindBuffer                (GL_ARRAY_BUFFER, vertexBuffer_1);
glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_1, GL_DYNAMIC_DRAW);
glVertexAttribPointer       (1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

glBindBuffer                (GL_ARRAY_BUFFER, vertexBuffer_2);
glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_2, GL_DYNAMIC_DRAW);
glVertexAttribPointer       (2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

glEnableVertexAttribArray   (0);
glEnableVertexAttribArray   (1);
glEnableVertexAttribArray   (2);

glDrawArrays                (GL_TRIANGLES, 0, _max_);

glDisableVertexAttribArray  (0);
glDisableVertexAttribArray  (1);
glDisableVertexAttribArray  (2);

但是,现在我没有_data_on_cpu_,还可以做同样的事情吗? cuda 6.0 中的示例是这样的:

glBindBuffer(GL_ARRAY_BUFFER, posVbo);
glVertexPointer(4, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);

glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalVbo);
glNormalPointer(GL_FLOAT, sizeof(float)*4, 0);
glEnableClientState(GL_NORMAL_ARRAY);

glColor3f(1.0, 0.0, 0.0);
glDrawArrays(GL_TRIANGLES, 0, totalVerts);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

我不完全了解这如何工作以及在我的情况下该怎么做。

顺便说一句,我使用的方法是 cudaMemcpy 将 dev_ 托管并像往常一样进行渲染,但这显然效率不高,因为当我进行渲染时,我再次通过 OpenGL 将数据发送回 GPU(如果我是正确的)。

【问题讨论】:

    标签: c++ opengl cuda


    【解决方案1】:

    不清楚您的要求是什么,您提到了 CUDA,但您发布的代码都不是 CUDA 特定的。我猜vertexbuffer_2 包含您想在着色器中访问的额外每个顶点信息?

    OpenGL 调用与您将获得的一样高效,它们实际上并没有将任何数据从设备复制回主机。他们只是将地址发送到设备,告诉它从哪里获取数据以及要使用多少数据来渲染。

    您只需要在程序开始时填写顶点和法线信息,在执行期间没有太多理由更改这些信息。然后,您可以更改存储在纹理缓冲区中的数据,以将附加的每个实体数据传递给着色器,以更改模型位置、旋转、颜色等。


    当您编写着色器时,您必须将其包含在内; attribute in vec3 v_data;(或类似)

    当你初始化你的着色器时,你必须这样做;

    GLuint vs_v_data = glGetAttribLocation(p_shaderProgram, "v_data"); 
    

    然后代替你的;

    glBindBuffer                (GL_ARRAY_BUFFER, vertexBuffer_2);
    glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_2, GL_DYNAMIC_DRAW);
    glVertexAttribPointer       (2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    

    你使用;

    glEnableVertexAttribArray   (vs_v_data);
    glBindBuffer                (GL_ARRAY_BUFFER, vertexBuffer_2);
    glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_2, GL_DYNAMIC_DRAW);
    glVertexAttribPointer       (vs_v_data, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    

    这应该让您可以访问名为v_data 的vshader 中的float3,其中存储了vertexBuffer_2 中的任何内容,大概是辅助顶点信息,以便在动画之间进行处理。


    一个简单的着色器,它可以根据输入的刻度简单地重新定位顶点

    #version 120
    attribute in float tick;
    attribute in vec3 v_data;
    void main()
    {
        gl_Vertex.xyz = mix(gl_Vertex.xyz, v_data, tick);
    }
    

    如果您想要每个实体数据而不是/除了每个顶点数据,您应该通过纹理缓冲区来实现。


    如果您尝试访问内核中的顶点缓冲区 obj 数据,则需要使用一堆函数;

    cudaGraphicsGLRegisterBuffer() 这将为您提供一个指向缓冲区的资源指针,在您最初设置 vbo 后执行一次。

    cudaGraphicsMapResources() 这将映射缓冲区(您可以在 CUDA 中使用它,但不能在 gl 中使用)

    cudaGraphicsResourceGetMappedPointer()这会给你一个指向缓冲区的设备指针,把它传递给内核。

    cudaGraphicsUnmapResources()这将取消映射缓冲区(您可以在gl中使用它,但不能在CUDA中使用)

    【讨论】:

    • Robadob,谢谢您的回答。注册和映射数据到 cuda 的部分在另一个地方,我只是省略了它。我理解你的代码,我一开始也是这样做的(我使用的是 OpenGL 3.3),但正如我所问的,现在数据在设备上,所以我没有 _data_on_cpu_2手。当然,如果我愿意,我可以将它从设备发送到主机,但这需要时间。我在主机上只有一个像 **dev_data_on_gpu_2**(启动内核)这样的指针。
    • 您想在内核中访问您的 vbo 数据?我已在我的答案中添加了有关此的信息。
    • 我不是在访问内核内部的 vbo 数据,而是反过来。数据总是在我的 gpu 中,我很少将它从 gpu 发送到 cpu。我只需要可视化它,所以我想做的是通过 OpenGL 访问 gpu 内的数据(如果可能的话)。还是我误解了一些重要的概念?
    • 你到底想做什么?使用 cuda/graphics,也许知道在更高的层次上会帮助我理解你的追求。
    • 我正在使用cuda做一些流体模拟,所以我首先在CPU上初始化数据,然后将数据发送到GPU。在 gpu 方面,在模拟的每一步之后,我都有每个节点的新位置和状态。然后我使用新状态来计算正常的东西(例如使用行进立方体),这也是由 cuda 完成的。到目前为止,没有数据从 GPU 发送到 CPU,但我接下来要做的是使用 OpenGL 可视化流体。我已经成功将数据从gpu发送到cpu并照常使用openGL,但我想知道是否可以直接使用gpu中的数据。
    猜你喜欢
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多