| 186 | } |
| 187 | |
| 188 | Status GlInteropFabric::Start() { |
| 189 | if (!is_enabled()) { |
| 190 | return OkStatus(); |
| 191 | } |
| 192 | |
| 193 | // In GL-CL interoperability, we need to make sure GL finished processing of |
| 194 | // all commands that might affect GL objects. There are a few ways: |
| 195 | // a) glFinish |
| 196 | // slow, but portable |
| 197 | // b) EglSync + ClientWait |
| 198 | // faster alternative for glFinish, but still slow as it stalls GPU |
| 199 | // pipeline. |
| 200 | // c) EglSync->CLEvent or GlSync->CLEvent mapping |
| 201 | // Fast, as it allows to map sync to CL event and use it as a dependency |
| 202 | // later without stalling GPU pipeline. |
| 203 | if (is_egl_sync_supported_) { |
| 204 | EglSync sync; |
| 205 | RETURN_IF_ERROR(EglSync::NewFence(egl_display_, &sync)); |
| 206 | if (is_egl_to_cl_mapping_supported_) { |
| 207 | // (c) EglSync->CLEvent or GlSync->CLEvent mapping |
| 208 | glFlush(); |
| 209 | RETURN_IF_ERROR( |
| 210 | CreateClEventFromEglSync(context_, sync, &inbound_event_)); |
| 211 | } else { |
| 212 | // (b) EglSync + ClientWait |
| 213 | RETURN_IF_ERROR(sync.ClientWait()); |
| 214 | } |
| 215 | } else { |
| 216 | // (a) glFinish / GL fence sync |
| 217 | RETURN_IF_ERROR(gl::GlActiveSyncWait()); |
| 218 | } |
| 219 | |
| 220 | // Acquire all GL objects needed while processing. |
| 221 | auto make_acquire_wait = [&]() -> std::vector<cl_event> { |
| 222 | if (inbound_event_.is_valid()) { |
| 223 | return {inbound_event_.event()}; |
| 224 | } |
| 225 | return {}; |
| 226 | }; |
| 227 | return AcquiredGlObjects::Acquire(memory_, queue_, make_acquire_wait(), |
| 228 | nullptr, &gl_objects_); |
| 229 | } |
| 230 | |
| 231 | Status GlInteropFabric::Finish() { |
| 232 | if (!is_enabled()) { |