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_GL_GL_SYNC_H_ 17 #define TENSORFLOW_LITE_DELEGATES_GPU_GL_GL_SYNC_H_ 18 19 #include "tensorflow/lite/delegates/gpu/common/status.h" 20 #include "tensorflow/lite/delegates/gpu/gl/gl_buffer.h" 21 #include "tensorflow/lite/delegates/gpu/gl/gl_call.h" 22 #include "tensorflow/lite/delegates/gpu/gl/gl_program.h" 23 #include "tensorflow/lite/delegates/gpu/gl/portable_gl31.h" 24 25 namespace tflite { 26 namespace gpu { 27 namespace gl { 28 29 // RAII wrapper for OpenGL GLsync object. 30 // See https://www.khronos.org/opengl/wiki/Sync_Object for more information. 31 // 32 // GlSync is moveable but not copyable. 33 class GlSync { 34 public: NewSync(GlSync * gl_sync)35 static Status NewSync(GlSync* gl_sync) { 36 GLsync sync; 37 RETURN_IF_ERROR(TFLITE_GPU_CALL_GL(glFenceSync, &sync, 38 GL_SYNC_GPU_COMMANDS_COMPLETE, 0)); 39 *gl_sync = GlSync(sync); 40 return OkStatus(); 41 } 42 43 // Creates invalid object. GlSync()44 GlSync() : GlSync(nullptr) {} 45 46 // Move-only GlSync(GlSync && sync)47 GlSync(GlSync&& sync) : sync_(sync.sync_) { sync.sync_ = nullptr; } 48 49 GlSync& operator=(GlSync&& sync) { 50 if (this != &sync) { 51 Invalidate(); 52 std::swap(sync_, sync.sync_); 53 } 54 return *this; 55 } 56 57 GlSync(const GlSync&) = delete; 58 GlSync& operator=(const GlSync&) = delete; 59 ~GlSync()60 ~GlSync() { Invalidate(); } 61 sync()62 const GLsync sync() const { return sync_; } 63 64 private: GlSync(GLsync sync)65 explicit GlSync(GLsync sync) : sync_(sync) {} 66 Invalidate()67 void Invalidate() { 68 if (sync_) { 69 glDeleteSync(sync_); 70 sync_ = nullptr; 71 } 72 } 73 74 GLsync sync_; 75 }; 76 77 // Waits until GPU is done with processing. 78 Status GlSyncWait(); 79 80 // Waits until all comands are flushed and then performs active waiting by 81 // spinning a thread and checking sync status. It leads to shorter wait time 82 // (up to tens of ms) but consumes more CPU. 83 Status GlActiveSyncWait(); 84 85 // CPU checks the value in the buffer that is going to be written by GPU. The 86 // persistent buffer is used for the simultaneous access to the buffer by GPU 87 // and CPU. The instance remains invalid if persistent buffer OpenGL extension 88 // is not supported by the device. 89 class GlShaderSync { 90 public: 91 static Status NewSync(GlShaderSync* gl_sync); GlShaderSync()92 GlShaderSync() {} 93 Status Wait(); 94 95 private: 96 GlProgram flag_program_; 97 GlPersistentBuffer flag_buffer_; 98 }; 99 100 } // namespace gl 101 } // namespace gpu 102 } // namespace tflite 103 104 #endif // TENSORFLOW_LITE_DELEGATES_GPU_GL_GL_SYNC_H_ 105