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_RUNTIME_SHARED_BUFFER_H_ 17 #define TENSORFLOW_LITE_DELEGATES_GPU_GL_RUNTIME_SHARED_BUFFER_H_ 18 19 #include <algorithm> 20 #include <iterator> 21 #include <vector> 22 23 #include "tensorflow/lite/delegates/gpu/common/status.h" 24 #include "tensorflow/lite/delegates/gpu/common/util.h" 25 #include "tensorflow/lite/delegates/gpu/gl/gl_buffer.h" 26 #include "tensorflow/lite/delegates/gpu/gl/object.h" 27 #include "tensorflow/lite/delegates/gpu/gl/portable_gl31.h" 28 29 namespace tflite { 30 namespace gpu { 31 namespace gl { 32 33 // Class accumulates readonly data and creates a single buffer out of it. 34 // User should call Add one or more times and complete shared buffer creation 35 // with CreateSharedBuffer() call. 36 class SharedBufferData { 37 public: SharedBufferData()38 SharedBufferData() { 39 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment_); 40 } 41 42 // @return true if data was added to the shared buffer. Add(const ObjectData & data,GlBuffer * buffer)43 bool Add(const ObjectData& data, GlBuffer* buffer) { 44 // TODO(akulik): Does it make sense to bundle even big buffers > 1MB? 45 46 // align buffer's data. 47 shared_data_.resize(AlignByN(shared_data_.size(), alignment_), 0); 48 // Accumulate readonly data in a single shared buffer buffer. 49 *buffer = GlBuffer(GL_SHADER_STORAGE_BUFFER, buffer_id_.id(), data.size(), 50 shared_data_.size(), /*has_ownership=*/false); 51 std::copy(data.begin(), data.end(), std::back_inserter(shared_data_)); 52 return true; 53 } 54 empty()55 bool empty() const { return shared_data_.empty(); } 56 57 // Returns a single GlBuffer that owns entire shared data. CreateSharedGlBuffer(GlBuffer * gl_buffer)58 absl::Status CreateSharedGlBuffer(GlBuffer* gl_buffer) { 59 // Upload data to a buffer 60 gl_buffer_internal::BufferBinder binder(GL_SHADER_STORAGE_BUFFER, 61 buffer_id_.id()); 62 RETURN_IF_ERROR(TFLITE_GPU_CALL_GL(glBufferData, GL_SHADER_STORAGE_BUFFER, 63 shared_data_.size(), shared_data_.data(), 64 GL_STATIC_READ)); 65 *gl_buffer = GlBuffer(GL_SHADER_STORAGE_BUFFER, buffer_id_.Release(), 66 shared_data_.size(), 0, /*has_ownership=*/true); 67 return absl::OkStatus(); 68 } 69 70 private: 71 GLint alignment_ = 256; 72 gl_buffer_internal::BufferId buffer_id_; 73 ObjectData shared_data_; 74 }; 75 76 } // namespace gl 77 } // namespace gpu 78 } // namespace tflite 79 80 #endif // TENSORFLOW_LITE_DELEGATES_GPU_GL_RUNTIME_SHARED_BUFFER_H_ 81