glBindTexture(),glBegin()中的OpenGL / OpenCL互操作性能

时间:2014-10-02 20:35:08

标签: macos opengl opencl nsopenglview

我在多GPU设置(2013年末的Mac Pro)上使用OpenCL(在辅助GPU上)生成OS X应用程序以生成纹理,然后使用OpenGL将其绘制到屏幕上(在主GPU上)。由于调用glBindTexture()和glBegin(),应用程序受CPU限制,两者都花费了大部分时间:

_platform_memmove$VARIANT$Ivybridge

是视频驱动程序的一部分:

AMDRadeonX4000GLDriver

设置:创建OpenGL纹理( glPixelBuffer ),然后创建OpenCL对应物( clPixelBuffer )。

cl_int clerror = 0;
GLuint glPixelBuffer = 0;
cl_mem clPixelBuffer = 0;

glGenTextures(1, &glPixelBuffer);
glBindTexture(GL_TEXTURE_2D, glPixelBuffer);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2048, 2048, 0, GL_RGBA, GL_FLOAT, NULL);
glBindTexture(GL_TEXTURE_2D, 0);

clPixelBuffer = clCreateFromGLTexture(_clShareGroupContext, CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0, glPixelBuffer, &clerror);

绘图代码:将OpenGL纹理映射到视口。整个NSOpenGLView就是这一个纹理。

glClear(GL_COLOR_BUFFER_BIT);

glBindTexture(GL_TEXTURE_2D, _glPixelBuffer);  // <- spends cpu time here,
glBegin(GL_QUADS);                             // <- and here
glTexCoord2f(0., 0.); glVertex3f(-1.f,  1.f, 0.f);
glTexCoord2f(0., hr); glVertex3f(-1.f, -1.f, 0.f);
glTexCoord2f(wr, hr); glVertex3f( 1.f, -1.f, 0.f);
glTexCoord2f(wr, 0.); glVertex3f( 1.f,  1.f, 0.f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);

glFlush();

在获得纹理内存的控制权之后(通过 clEnqueueAcquireGLObjects()),OpenCL内核将数据写入纹理,然后释放对它的控制(通过 clEnqueueReleaseGLObjects() )。纹理数据永远不应该存在于主存储器中(如果我理解了所有这些)。

我的问题是:是否需要在memmove()中花费如此多的CPU时间?它是否表示我的代码存在问题?或许是驱动程序中的错误?我(毫无根据)怀疑纹理数据是通过以下方式移动的:GPUx - &gt; CPU / RAM - &gt; GPUy,我想避免。

1 个答案:

答案 0 :(得分:2)

在我触摸内存传输之前,我的第一个观察是你正在使用clBegin(),这不会是你最好的朋友,因为

1)此直接绘图与驱动程序不兼容。请改用VBO等,以便这些数据可以存储在GPU上。

2)在OS X上,它意味着您处于旧的兼容性上下文而不是新的核心上下文。正如(据我所知),新的上下文是一个完整的重写,这是未来的优化将会结束,而你正在使用的上下文(可能)只是被维护。

那么对于内存传输....在GL方面你是否在那上面放了glCreateSyncFromCLeventARB()和glWaitSync()?我不应该在你的代码中看到glFlush()。一旦你摆脱了立即模式绘图(如上所述)并在两个API之间使用同步对象,你的主机代码应该什么都不做(除了要求驱动程序告诉GPU做某事)。这将为您提供快速缓冲区复制的最佳机会....

是的,副本:(因为你的CL纹理物理上存在于GL纹理的不同GPU内存上,所以必须通过PCIe总线进行复制,这将很慢(呃)。这就是你所看到的在你的分析中。实际发生的是CPU将GPU内存A和GPU内存B映射到固定主机内存,然后用DMA重复它们(希望)。我怀疑数据实际上是否触及系统内存,所以移动是GPUx - &gt; GPUy。

尝试将CL和GL上下文放在同一GPU上,我认为您的传输时间会消失。

最后的想法:如果您的CL计算与传输时间相形见绌,那么最好将上下文粘贴在同一个CPU上。你有经典的CPU / GPU任务分割问题。