У меня проблема с «неявной синхронизацией» OpenCL и OpenGL на устройстве AMD Tahiti (AMD Radeon HD 7900 Series). Устройство имеет расширения cl / gl, cl_khr_gl_sharing и cl_khr_gl_event.
Когда я запускаю программу, которая представляет собой простое ядро с обновлением vbo, и рисую ее в виде белой линии с простым шейдером, она идиотит как сумасшедшая, останавливая то, что выглядит как 2-4 кадра при каждом обновлении. Я могу подтвердить, что это не ядро cl или шейдер gl, который я использую для обновления и отрисовки буфера, потому что если я добавлю glFinish и commandQueue.finish () до и после получения и выпуска объектов gl для cl обнови, все работает как надо.
Итак, я понял, что мне нужно «включить» расширение события …
#pragma OPENCL EXTENSION cl_khr_gl_event : enable
…в программе cl, но это выдает ошибки. Я предполагаю, что это расширение не относится к клиентскому расширению и должно работать как «ожидаемое», поэтому я не могу включить его.
Третье поведение, которое я заметил … если я возьму glFinish () и commandQueue.finish () и запустю его в отладке CodeXL, неявная синхронизация работает. Например, без каких-либо изменений в кодовой базе, таких как принудительная синхронизация с завершением, CodeXL допускает неявную синхронизацию. Итак, неявная синхронизация четко работает, но я не могу заставить ее работать, просто регулярно запуская приложение через Visual Studio и форсируя синхронизацию.
Я явно что-то упускаю, но, честно говоря, не вижу этого. Буду очень признателен за любые мысли или объяснения, так как я хотел бы сохранить синхронизацию неявной.
Я предполагаю, что вы не используете синхронизацию 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]
Вместо этого вы должны:
CL-> GL synchro: есть clEnqueueReleaseObjects
создать (выходное) событие для передачи glCreateSyncFromCLeventARB
затем используйте glWaitSync
(НЕ glClientWaitSync
— который в этом случае будет таким же, как clFinish
).
GL-> CL synchro: есть clEnqueueAcquireObjects
принять (входное) событие, которое будет создано с clCreateFromGLsync
, принимая объект синхронизации из glFenceSync
В целом, это должно быть:
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]
(Варианты 1.2 / 2.2 лучше, если вы точно не знаете заранее, какой будет последняя очередь перед передачей управления другому API)
В качестве примечания, я предположил, что вы не используете неупорядоченную очередь для OpenCL (в этом случае действительно не должно быть нужды) — если вы это сделали, вам, конечно же, придется синхронизировать clEnqueueAcquire
-> clEnqueueNDRange
-> clEnqueueRelease
,