xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/delegates/external/external_delegate.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2020 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 #include "tensorflow/lite/delegates/external/external_delegate.h"
16 
17 #include <locale>
18 #include <string>
19 #include <vector>
20 
21 #include "tensorflow/lite/minimal_logging.h"
22 #include "tensorflow/lite/shared_library.h"
23 
24 namespace tflite {
25 namespace {
26 
27 // External delegate library construct
28 struct ExternalLib {
29   using CreateDelegatePtr = std::add_pointer<TfLiteDelegate*(
30       const char**, const char**, size_t,
31       void (*report_error)(const char*))>::type;
32   using DestroyDelegatePtr = std::add_pointer<void(TfLiteDelegate*)>::type;
33   struct wchar_codecvt : public std::codecvt<wchar_t, char, std::mbstate_t> {};
34 
35   // Open a given delegate library and load the create/destroy symbols
loadtflite::__anon7d121f280111::ExternalLib36   bool load(const std::string library) {
37 #if defined(_WIN32)
38     std::wstring_convert<wchar_codecvt> converter;
39     void* handle = SharedLibrary::LoadLibrary(
40         converter.from_bytes(library.c_str()).c_str());
41 #else
42     void* handle = SharedLibrary::LoadLibrary(library.c_str());
43 #endif  // defined(_WIN32)
44     if (handle == nullptr) {
45       TFLITE_LOG(TFLITE_LOG_INFO, "Unable to load external delegate from : %s",
46                  library.c_str());
47     } else {
48       create =
49           reinterpret_cast<decltype(create)>(SharedLibrary::GetLibrarySymbol(
50               handle, "tflite_plugin_create_delegate"));
51       destroy =
52           reinterpret_cast<decltype(destroy)>(SharedLibrary::GetLibrarySymbol(
53               handle, "tflite_plugin_destroy_delegate"));
54       return create && destroy;
55     }
56     return false;
57   }
58 
59   CreateDelegatePtr create{nullptr};
60   DestroyDelegatePtr destroy{nullptr};
61 };
62 
63 // An ExternalDelegateWrapper is responsibile to manage a TFLite delegate
64 // initialized from a shared library. It creates a delegate from the given
65 // option and storages it to external_delegate_ member variable. On the
66 // destruction, it conducts necessary clean up process.
67 class ExternalDelegateWrapper {
68  public:
69   explicit ExternalDelegateWrapper(
70       const TfLiteExternalDelegateOptions* options);
71   ~ExternalDelegateWrapper();
72 
73   // Return a TfLiteDelegate which is created from
74   // tflite_plugin_create_delegate() of an external delegate logic.
tflite_external_delegate()75   TfLiteDelegate* tflite_external_delegate() { return external_delegate_; }
76 
77   // Return a TfLiteDelegate which is convertibile to this class.
tflite_wrapper_delegate()78   TfLiteDelegate* tflite_wrapper_delegate() { return &wrapper_delegate_; }
79 
80  private:
81   ExternalLib external_lib_;
82 
83   // external delegate instance owned by external delegate logic.
84   // It's created by "tflite_plugin_destroy_delegate()" function in the external
85   // delegate logic And it should be released by
86   // "tflite_plugin_destroy_delegate()" function.
87   TfLiteDelegate* external_delegate_;
88 
89   // TfLiteDelegate representation of this ExternalDelegateWrapper object.
90   TfLiteDelegate wrapper_delegate_;
91 };
92 
93 // Converts the given TfLiteDelegate to an ExternalDelegateWrapper instance.
GetExternalDelegateWrapper(TfLiteDelegate * delegate)94 inline ExternalDelegateWrapper* GetExternalDelegateWrapper(
95     TfLiteDelegate* delegate) {
96   return reinterpret_cast<ExternalDelegateWrapper*>(delegate->data_);
97 }
98 
99 // Relay Prepare() call to the associated external TfLiteDelegate object.
DelegatePrepare(TfLiteContext * context,TfLiteDelegate * delegate)100 TfLiteStatus DelegatePrepare(TfLiteContext* context, TfLiteDelegate* delegate) {
101   auto external_delegate_wrapper = GetExternalDelegateWrapper(delegate);
102   TfLiteDelegate* external_delegate =
103       external_delegate_wrapper->tflite_external_delegate();
104   return external_delegate->Prepare(context, external_delegate);
105 }
106 
107 // Relay CopyFromBufferHandle() call to the associated external TfLiteDelegate
108 // object.
DelegateCopyFromBufferHandle(TfLiteContext * context,struct TfLiteDelegate * delegate,TfLiteBufferHandle buffer_handle,TfLiteTensor * tensor)109 TfLiteStatus DelegateCopyFromBufferHandle(TfLiteContext* context,
110                                           struct TfLiteDelegate* delegate,
111                                           TfLiteBufferHandle buffer_handle,
112                                           TfLiteTensor* tensor) {
113   auto external_delegate_wrapper = GetExternalDelegateWrapper(delegate);
114   TfLiteDelegate* external_delegate =
115       external_delegate_wrapper->tflite_external_delegate();
116   return external_delegate->CopyFromBufferHandle(context, delegate,
117                                                  buffer_handle, tensor);
118 }
119 
120 // Relay CopyToBufferHandle() call to the associated external TfLiteDelegate
121 // object.
DelegateCopyToBufferHandle(TfLiteContext * context,struct TfLiteDelegate * delegate,TfLiteBufferHandle buffer_handle,TfLiteTensor * tensor)122 TfLiteStatus DelegateCopyToBufferHandle(TfLiteContext* context,
123                                         struct TfLiteDelegate* delegate,
124                                         TfLiteBufferHandle buffer_handle,
125                                         TfLiteTensor* tensor) {
126   auto external_delegate_wrapper = GetExternalDelegateWrapper(delegate);
127   TfLiteDelegate* external_delegate =
128       external_delegate_wrapper->tflite_external_delegate();
129   return external_delegate->CopyToBufferHandle(context, delegate, buffer_handle,
130                                                tensor);
131 }
132 
133 // Relay FreeBufferHandle() call to the associated external TfLiteDelegate
134 // object.
DelegateFreeBufferHandle(TfLiteContext * context,struct TfLiteDelegate * delegate,TfLiteBufferHandle * handle)135 void DelegateFreeBufferHandle(TfLiteContext* context,
136                               struct TfLiteDelegate* delegate,
137                               TfLiteBufferHandle* handle) {
138   auto external_delegate_wrapper = GetExternalDelegateWrapper(delegate);
139   TfLiteDelegate* external_delegate =
140       external_delegate_wrapper->tflite_external_delegate();
141   return external_delegate->FreeBufferHandle(context, delegate, handle);
142 }
143 
ExternalDelegateWrapper(const TfLiteExternalDelegateOptions * options)144 ExternalDelegateWrapper::ExternalDelegateWrapper(
145     const TfLiteExternalDelegateOptions* options) {
146   external_delegate_ = nullptr;
147   if (external_lib_.load(options->lib_path)) {
148     std::vector<const char*> ckeys, cvalues;
149     for (int i = 0; i < options->count; i++) {
150       ckeys.push_back(options->keys[i]);
151       cvalues.push_back(options->values[i]);
152     }
153 
154     external_delegate_ = external_lib_.create(ckeys.data(), cvalues.data(),
155                                               ckeys.size(), nullptr);
156     if (external_delegate_) {
157       wrapper_delegate_ = {
158           reinterpret_cast<void*>(this),  // .data =
159           DelegatePrepare,                // .Prepare =
160           nullptr,                        // .CopyFromBufferHandle =
161           nullptr,                        // .CopyToBufferHandle =
162           nullptr,                        // .FreeBufferHandle =
163           external_delegate_->flags,      // .flags =
164       };
165       if (external_delegate_->CopyFromBufferHandle) {
166         wrapper_delegate_.CopyFromBufferHandle = DelegateCopyFromBufferHandle;
167       }
168       if (external_delegate_->CopyToBufferHandle) {
169         wrapper_delegate_.CopyToBufferHandle = DelegateCopyToBufferHandle;
170       }
171       if (external_delegate_->FreeBufferHandle) {
172         wrapper_delegate_.FreeBufferHandle = DelegateFreeBufferHandle;
173       }
174     }
175   }
176 }
177 
~ExternalDelegateWrapper()178 ExternalDelegateWrapper::~ExternalDelegateWrapper() {
179   if (external_delegate_ != nullptr) {
180     external_lib_.destroy(external_delegate_);
181   }
182 }
183 
184 }  // namespace
185 }  // namespace tflite
186 
187 // TfLiteExternalDelegateOptionsInsert adds key/value to the given
188 // TfLiteExternalDelegateOptions instance.
TfLiteExternalDelegateOptionsInsert(TfLiteExternalDelegateOptions * options,const char * key,const char * value)189 TfLiteStatus TfLiteExternalDelegateOptionsInsert(
190     TfLiteExternalDelegateOptions* options, const char* key,
191     const char* value) {
192   if (options->count >= kExternalDelegateMaxOptions) {
193     return kTfLiteError;
194   }
195   options->keys[options->count] = key;
196   options->values[options->count] = value;
197   options->count++;
198   return kTfLiteOk;
199 }
200 
TfLiteExternalDelegateOptionsDefault(const char * lib_path)201 TfLiteExternalDelegateOptions TfLiteExternalDelegateOptionsDefault(
202     const char* lib_path) {
203   // As 'keys' and 'values' don't need to be set here, using designated
204   // initializers may cause a compiling error as "non-trivial designated
205   // initializers not supported" by some compiler.
206   TfLiteExternalDelegateOptions options;
207   options.lib_path = lib_path;
208   options.count = 0;
209   options.insert = TfLiteExternalDelegateOptionsInsert;
210   return options;
211 }
212 
TfLiteExternalDelegateCreate(const TfLiteExternalDelegateOptions * options)213 TfLiteDelegate* TfLiteExternalDelegateCreate(
214     const TfLiteExternalDelegateOptions* options) {
215   auto* external_delegate_wrapper =
216       new tflite::ExternalDelegateWrapper(options);
217   if (external_delegate_wrapper) {
218     return external_delegate_wrapper->tflite_wrapper_delegate();
219   }
220   return nullptr;
221 }
222 
TfLiteExternalDelegateDelete(TfLiteDelegate * delegate)223 void TfLiteExternalDelegateDelete(TfLiteDelegate* delegate) {
224   delete tflite::GetExternalDelegateWrapper(delegate);
225 }
226