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 #ifndef TENSORFLOW_LITE_DELEGATES_GPU_CL_GL_INTEROP_H_ 17 #define TENSORFLOW_LITE_DELEGATES_GPU_CL_GL_INTEROP_H_ 18 19 #include <vector> 20 21 #include <EGL/egl.h> 22 #include <EGL/eglext.h> 23 #include "tensorflow/lite/delegates/gpu/cl/cl_context.h" 24 #include "tensorflow/lite/delegates/gpu/cl/cl_device.h" 25 #include "tensorflow/lite/delegates/gpu/cl/cl_event.h" 26 #include "tensorflow/lite/delegates/gpu/cl/cl_memory.h" 27 #include "tensorflow/lite/delegates/gpu/cl/egl_sync.h" 28 #include "tensorflow/lite/delegates/gpu/cl/environment.h" 29 #include "tensorflow/lite/delegates/gpu/cl/opencl_wrapper.h" 30 #include "tensorflow/lite/delegates/gpu/common/access_type.h" 31 #include "tensorflow/lite/delegates/gpu/common/status.h" 32 #include "tensorflow/lite/delegates/gpu/gl/portable_gl31.h" 33 34 namespace tflite { 35 namespace gpu { 36 namespace cl { 37 38 // Creates an EglSync from OpenCL event. Source event does not need to outlive 39 // returned sync and could be safely destroyed. 40 // 41 // Depends on EGL 1.5. 42 Status CreateEglSyncFromClEvent(cl_event event, EGLDisplay display, 43 EglSync* sync); 44 45 // Returns true if 'CreateEglSyncFromClEvent' is supported. 46 bool IsEglSyncFromClEventSupported(); 47 48 // Creates CL event from EGL sync. 49 // Created event could only be comsumed by AcquiredGlObject::Acquire call as 50 // a 'wait_event'. 51 Status CreateClEventFromEglSync(cl_context context, const EglSync& egl_sync, 52 CLEvent* event); 53 54 // Returns true if 'CreateClEventFromEglSync' is supported. 55 bool IsClEventFromEglSyncSupported(const CLDevice& device); 56 57 // Creates new CL memory object from OpenGL buffer. 58 Status CreateClMemoryFromGlBuffer(GLuint gl_ssbo_id, AccessType access_type, 59 CLContext* context, CLMemory* memory); 60 61 // Creates new CL memory object from OpenGL texture. 62 Status CreateClMemoryFromGlTexture(GLenum texture_target, GLuint texture_id, 63 AccessType access_type, CLContext* context, 64 CLMemory* memory); 65 66 // Returns true if GL objects could be shared with OpenCL context. 67 bool IsGlSharingSupported(const CLDevice& device); 68 69 // RAII-wrapper for GL objects acquired into CL context. 70 class AcquiredGlObjects { 71 public: 72 static bool IsSupported(const CLDevice& device); 73 AcquiredGlObjects()74 AcquiredGlObjects() : AcquiredGlObjects({}, nullptr) {} 75 76 // Quitely releases OpenGL objects. It is recommended to call Release() 77 // explicitly to properly handle potential errors. 78 ~AcquiredGlObjects(); 79 80 // Acquires memory from the OpenGL context. Memory must be created by either 81 // CreateClMemoryFromGlBuffer or CreateClMemoryFromGlTexture calls. 82 // If 'acquire_event' is not nullptr, it will be signared once acquisition is 83 // complete. 84 static Status Acquire(const std::vector<cl_mem>& memory, 85 cl_command_queue queue, 86 const std::vector<cl_event>& wait_events, 87 CLEvent* acquire_event /* optional */, 88 AcquiredGlObjects* objects); 89 90 // Releases OpenCL memory back to OpenGL context. If 'release_event' is not 91 // nullptr, it will be signalled once release is complete. 92 Status Release(const std::vector<cl_event>& wait_events, 93 CLEvent* release_event /* optional */); 94 95 private: AcquiredGlObjects(const std::vector<cl_mem> & memory,cl_command_queue queue)96 AcquiredGlObjects(const std::vector<cl_mem>& memory, cl_command_queue queue) 97 : memory_(memory), queue_(queue) {} 98 99 std::vector<cl_mem> memory_; 100 cl_command_queue queue_; 101 }; 102 103 // Incapsulates all complicated GL-CL synchronization. It manages life time of 104 // all appropriate events to ensure fast synchronization whenever possible. 105 class GlInteropFabric { 106 public: 107 GlInteropFabric(EGLDisplay egl_display, Environment* environment); 108 109 // Ensures proper GL->CL synchronization is in place before 110 // GL objects that are mapped to CL objects are used. 111 Status Start(); 112 113 // Puts appropriate CL->GL synchronization after all work is complete. 114 Status Finish(); 115 116 // Registers memory to be used from GL context. Such CL memory object must 117 // be created with CreateClMemoryFromGlBuffer or CreateClMemoryFromGlTexture 118 // call. 119 void RegisterMemory(cl_mem memory); 120 121 // Unregisters memory registered with RegisterMemory call. 122 void UnregisterMemory(cl_mem memory); 123 124 private: is_enabled()125 bool is_enabled() const { return egl_display_ && !memory_.empty(); } 126 127 bool is_egl_sync_supported_; 128 bool is_egl_to_cl_mapping_supported_; 129 bool is_cl_to_egl_mapping_supported_; 130 131 const EGLDisplay egl_display_; 132 cl_context context_; 133 cl_command_queue queue_; 134 CLEvent inbound_event_; 135 CLEvent outbound_event_; 136 std::vector<cl_mem> memory_; 137 AcquiredGlObjects gl_objects_; // transient during Start/Finish calls. 138 }; 139 140 } // namespace cl 141 } // namespace gpu 142 } // namespace tflite 143 144 #endif // TENSORFLOW_LITE_DELEGATES_GPU_CL_GL_INTEROP_H_ 145