如何使用openGL访问cuda上的数据

How to Access data on cuda by openGL?

本文关键字:数据 cuda 访问 何使用 openGL      更新时间:2023-10-16

我通常已经学习了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_主机和做渲染像往常一样,但这显然是不有效的,因为当我做渲染我再次发送数据回GPU通过OpenGL(如果我是对的)。

这不是很清楚你的要求是什么,你提到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);

这应该让你访问一个float3在你的vshaders称为v_data,有任何存储在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中使用)