• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/lite/delegates/gpu/cl/egl_sync.h"
17 
18 #include "tensorflow/lite/delegates/gpu/gl/gl_call.h"
19 
20 namespace tflite {
21 namespace gpu {
22 namespace cl {
23 
24 namespace {
25 
HasExtension(EGLDisplay display,const char * extension)26 bool HasExtension(EGLDisplay display, const char* extension) {
27   const char* extensions = eglQueryString(display, EGL_EXTENSIONS);
28   return extensions && std::strstr(extensions, extension);
29 }
30 
IsEglFenceSyncSupported(EGLDisplay display)31 absl::Status IsEglFenceSyncSupported(EGLDisplay display) {
32   static bool supported = HasExtension(display, "EGL_KHR_fence_sync");
33   if (supported) {
34     return absl::OkStatus();
35   }
36   return absl::InternalError("Not supported: EGL_KHR_fence_sync");
37 }
38 
IsEglWaitSyncSupported(EGLDisplay display)39 absl::Status IsEglWaitSyncSupported(EGLDisplay display) {
40   static bool supported = HasExtension(display, "EGL_KHR_wait_sync");
41   if (supported) {
42     return absl::OkStatus();
43   }
44   return absl::InternalError("Not supported: EGL_KHR_wait_sync");
45 }
46 
47 }  // anonymous namespace
48 
NewFence(EGLDisplay display,EglSync * sync)49 absl::Status EglSync::NewFence(EGLDisplay display, EglSync* sync) {
50   RETURN_IF_ERROR(IsEglFenceSyncSupported(display));
51   static auto* egl_create_sync_khr =
52       reinterpret_cast<decltype(&eglCreateSyncKHR)>(
53           eglGetProcAddress("eglCreateSyncKHR"));
54   if (egl_create_sync_khr == nullptr) {
55     // Needs extension: EGL_KHR_fence_sync (EGL) / GL_OES_EGL_sync (OpenGL ES).
56     return absl::InternalError(
57         "Not supported / bad EGL implementation: eglCreateSyncKHR.");
58   }
59   EGLSyncKHR egl_sync;
60   RETURN_IF_ERROR(TFLITE_GPU_CALL_EGL(*egl_create_sync_khr, &egl_sync, display,
61                                       EGL_SYNC_FENCE_KHR, nullptr));
62   if (egl_sync == EGL_NO_SYNC_KHR) {
63     return absl::InternalError("Returned empty KHR EGL sync");
64   }
65   *sync = EglSync(display, egl_sync);
66   return absl::OkStatus();
67 }
68 
operator =(EglSync && sync)69 EglSync& EglSync::operator=(EglSync&& sync) {
70   if (this != &sync) {
71     Invalidate();
72     std::swap(sync_, sync.sync_);
73     display_ = sync.display_;
74   }
75   return *this;
76 }
77 
Invalidate()78 void EglSync::Invalidate() {
79   if (sync_ != EGL_NO_SYNC_KHR) {
80     static auto* egl_destroy_sync_khr =
81         reinterpret_cast<decltype(&eglDestroySyncKHR)>(
82             eglGetProcAddress("eglDestroySyncKHR"));
83     // Needs extension: EGL_KHR_fence_sync (EGL) / GL_OES_EGL_sync (OpenGL ES).
84     if (IsEglFenceSyncSupported(display_).ok() && egl_destroy_sync_khr) {
85       // Note: we're doing nothing when the function pointer is nullptr, or the
86       // call returns EGL_FALSE.
87       (*egl_destroy_sync_khr)(display_, sync_);
88     }
89     sync_ = EGL_NO_SYNC_KHR;
90   }
91 }
92 
ServerWait()93 absl::Status EglSync::ServerWait() {
94   RETURN_IF_ERROR(IsEglWaitSyncSupported(display_));
95   static auto* egl_wait_sync_khr = reinterpret_cast<decltype(&eglWaitSyncKHR)>(
96       eglGetProcAddress("eglWaitSyncKHR"));
97   if (egl_wait_sync_khr == nullptr) {
98     // Needs extension: EGL_KHR_wait_sync
99     return absl::InternalError("Not supported: eglWaitSyncKHR.");
100   }
101   EGLint result;
102   RETURN_IF_ERROR(
103       TFLITE_GPU_CALL_EGL(*egl_wait_sync_khr, &result, display_, sync_, 0));
104   return result == EGL_TRUE ? absl::OkStatus()
105                             : absl::InternalError("eglWaitSync failed");
106 }
107 
ClientWait()108 absl::Status EglSync::ClientWait() {
109   RETURN_IF_ERROR(IsEglFenceSyncSupported(display_));
110   static auto* egl_client_wait_sync_khr =
111       reinterpret_cast<decltype(&eglClientWaitSyncKHR)>(
112           eglGetProcAddress("eglClientWaitSyncKHR"));
113   if (egl_client_wait_sync_khr == nullptr) {
114     // Needs extension: EGL_KHR_fence_sync (EGL) / GL_OES_EGL_sync (OpenGL ES).
115     return absl::InternalError("Not supported: eglClientWaitSyncKHR.");
116   }
117   EGLint result;
118   // TODO(akulik): make it active wait for better performance
119   RETURN_IF_ERROR(
120       TFLITE_GPU_CALL_EGL(*egl_client_wait_sync_khr, &result, display_, sync_,
121                           EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR));
122   return result == EGL_CONDITION_SATISFIED_KHR
123              ? absl::OkStatus()
124              : absl::InternalError("eglClientWaitSync failed");
125 }
126 
127 }  // namespace cl
128 }  // namespace gpu
129 }  // namespace tflite
130