AMD Tahiti 上的 OpenCL / OpenGL 隐式同步

问题描述 投票:0回答:1

我在 AMD Tahiti(AMD Radeon HD 7900 系列)设备上遇到 OpenCL 和 OpenGL 的“隐式同步”问题。该设备具有 cl/gl 扩展名、

cl_khr_gl_sharing
cl_khr_gl_event

当我运行这个只是一个简单的 vbo 更新内核的程序,并用简单的着色器将其绘制为一条白线时,它会疯狂地打嗝,每次更新都会停滞 2-4 帧。我可以确认我用来更新和绘制缓冲区的不是 cl 内核或 gl 着色器,因为如果我在获取和释放 cl 的 gl 对象之前和之后放置

glFinish
commandQueue.finish()
更新,一切正常。

所以,我认为我需要“启用”事件扩展......

#pragma OPENCL EXTENSION cl_khr_gl_event : enable

...在 cl 程序中,但这会引发错误。我认为这个扩展不是面向客户端的扩展,应该只是按“预期”工作,这就是为什么我无法启用它。

我注意到的第三个行为是,如果我取出

glFinish()
commandQueue.finish()
,并在 CodeXL 调试中运行它,隐式同步就会起作用。例如,无需对代码库进行任何更改(例如强制完成同步),CodeXL 允许隐式同步。因此,隐式同步显然有效,但我无法通过 Visual Studio 定期运行应用程序并强制同步来使其工作。

显然我错过了一些东西,但老实说我看不到它。任何想法或解释将不胜感激,因为我很乐意保持同步隐式。

c++ opengl opencl amd-gpu
1个回答
1
投票

我猜您没有使用 GLsync-cl_event 同步(

GL_ARB_cl_event
cl_khr_gl_event
扩展),这就是为什么添加 cl/glFinish 和 CodeXL 的开销会有所帮助。

我的猜测是你的代码看起来像:

A1. clEnqueueNDRangeKernel
A2. clEnqueueReleaseObjects
[here is where you inserted clFinish]
B1. glDraw*
B2. wgl/glXSwapBuffers
[here is where you inserted glFinish]
C1. clEnqueueAcquireObjects
[repeat from A1]

相反,你应该:

  1. CL->GL 同步:让

    clEnqueueReleaseObjects
    创建要传递给
    glCreateSyncFromCLeventARB
    的(输出)事件,然后使用
    glWaitSync
    (不是
    glClientWaitSync
    - 在这种情况下与
    clFinish
    相同) .

  2. GL->CL 同步:让

    clEnqueueAcquireObjects
    获取一个(输入)事件,该事件将使用
    clCreateFromGLsync
    创建,从
    glFenceSync

  3. 获取同步对象

总体来说应该是:

A1. `clEnqueueNDRangeKernel`

[Option 1.1:]
A2. `clEnqueueReleaseObjects`( ..., 0, NULL, &eve1)

[Option 1.2:]
A2. `clEnqueueReleaseObjects`( ..., 0, NULL, NULL)
A2'. `clEnqueueMarker`(&eve1)

A3. sync1 = glCreateSyncFromCLeventARB(eve1)
* clReleaseEvent(eve1)
A4. glWaitSync(sync1)
* glDeleteSync(sync1)
B1. glDraw*
B2. wgl/glXSwapBuffers
B3. sync2 = glFenceSync
B4. eve2 = clCreateFromGLSync(sync2)
* glDeleteSync(sync2)

[Option 2.1:]
C1. clEnqueueAcquireObjects(, ..., 1, &eve2, NULL)
* clReleaseEvent(eve2)

[Option 2.2:]
B5. clEnqueueWaitForEvents(1, &eve2)
* clReleaseEvent(eve2)
C1. clEnqueueAcquireObjects(, ..., 0, NULL, NULL)

[Repeat from A1]

(如果您在将控制权移交给其他 API 之前事先不确切知道最后一个队列是什么,那么选项 1.2 / 2.2 会更好)

顺便说一句,我假设您没有为 OpenCL 使用无序队列(在这种情况下确实不需要) - 如果您这样做了,您当然还必须同步

 clEnqueueAcquire
->
clEnqueueNDRange
->
clEnqueueRelease

© www.soinside.com 2019 - 2024. All rights reserved.