Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / fluid / modules / gapi / src / api / gbackend.cpp
1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 //
5 // Copyright (C) 2018-2019 Intel Corporation
6
7
8 #include "precomp.hpp"
9 #include <memory> // unique_ptr
10
11 #include "opencv2/gapi/gkernel.hpp"
12 #include "opencv2/gapi/own/convert.hpp"
13
14 #include "api/gbackend_priv.hpp"
15 #include "backends/common/gbackend.hpp"
16 #include "compiler/gobjref.hpp"
17 #include "compiler/gislandmodel.hpp"
18
19 // GBackend private implementation /////////////////////////////////////////////
20 void cv::gapi::GBackend::Priv::unpackKernel(ade::Graph             & /*graph  */ ,
21                                             const ade::NodeHandle  & /*op_node*/ ,
22                                             const GKernelImpl      & /*impl   */ )
23 {
24     // Default implementation is still there as Priv
25     // is instantiated by some tests.
26     // Priv is even instantiated as a mock object in a number of tests
27     // as a backend and this method is called for mock objects (doing nothing).
28     // FIXME: add a warning message here
29     // FIXME: Do something with this! Ideally this function should be "=0";
30 }
31
32 std::unique_ptr<cv::gimpl::GIslandExecutable>
33 cv::gapi::GBackend::Priv::compile(const ade::Graph&,
34                                   const GCompileArgs&,
35                                   const std::vector<ade::NodeHandle> &) const
36 {
37     // ...and this method is here for the same reason!
38     GAPI_Assert(false);
39     return {};
40 }
41
42 void cv::gapi::GBackend::Priv::addBackendPasses(ade::ExecutionEngineSetupContext &)
43 {
44     // Do nothing by default, plugins may override this to
45     // add custom (backend-specific) graph transformations
46 }
47
48 // GBackend public implementation //////////////////////////////////////////////
49 cv::gapi::GBackend::GBackend()
50 {
51 }
52
53 cv::gapi::GBackend::GBackend(std::shared_ptr<cv::gapi::GBackend::Priv> &&p)
54     : m_priv(std::move(p))
55 {
56 }
57
58 cv::gapi::GBackend::Priv& cv::gapi::GBackend::priv()
59 {
60     return *m_priv;
61 }
62
63 const cv::gapi::GBackend::Priv& cv::gapi::GBackend::priv() const
64 {
65     return *m_priv;
66 }
67
68 std::size_t cv::gapi::GBackend::hash() const
69 {
70     return std::hash<const cv::gapi::GBackend::Priv*>{}(m_priv.get());
71 }
72
73 bool cv::gapi::GBackend::operator== (const cv::gapi::GBackend &rhs) const
74 {
75     return m_priv == rhs.m_priv;
76 }
77
78 // Abstract Host-side data manipulation ////////////////////////////////////////
79 // Reused between CPU backend and more generic GExecutor
80 namespace cv {
81 namespace gimpl {
82 namespace magazine {
83
84 // FIXME implement the below functions with visit()?
85
86 void bindInArg(Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat)
87 {
88     switch (rc.shape)
89     {
90     case GShape::GMAT:
91     {
92         switch (arg.index())
93         {
94         case GRunArg::index_of<cv::gapi::own::Mat>() :
95             if (is_umat)
96             {
97 #if !defined(GAPI_STANDALONE)
98                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
99                 mag_umat = to_ocv(util::get<cv::gapi::own::Mat>(arg)).getUMat(ACCESS_READ);
100 #else
101                 util::throw_error(std::logic_error("UMat is not supported in stadnalone build"));
102 #endif // !defined(GAPI_STANDALONE)
103             }
104             else
105             {
106                 auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
107                 mag_mat = util::get<cv::gapi::own::Mat>(arg);
108             }
109             break;
110 #if !defined(GAPI_STANDALONE)
111         case GRunArg::index_of<cv::Mat>() :
112             if (is_umat)
113             {
114                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
115                 mag_umat = (util::get<cv::UMat>(arg));
116             }
117             else
118             {
119                 auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
120                 mag_mat = to_own(util::get<cv::Mat>(arg));
121             }
122             break;
123 #endif //  !defined(GAPI_STANDALONE)
124         default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
125         }
126         break;
127     }
128
129
130     case GShape::GSCALAR:
131     {
132         auto& mag_scalar = mag.template slot<cv::gapi::own::Scalar>()[rc.id];
133         switch (arg.index())
134         {
135             case GRunArg::index_of<cv::gapi::own::Scalar>() : mag_scalar = util::get<cv::gapi::own::Scalar>(arg); break;
136 #if !defined(GAPI_STANDALONE)
137             case GRunArg::index_of<cv::Scalar>()            : mag_scalar = to_own(util::get<cv::Scalar>(arg));    break;
138 #endif //  !defined(GAPI_STANDALONE)
139             default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
140         }
141         break;
142     }
143
144     case GShape::GARRAY:
145         mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
146         break;
147
148     default:
149         util::throw_error(std::logic_error("Unsupported GShape type"));
150     }
151 }
152
153 void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat)
154 {
155     switch (rc.shape)
156     {
157     case GShape::GMAT:
158     {
159         switch (arg.index())
160         {
161         case GRunArgP::index_of<cv::gapi::own::Mat*>() :
162             if (is_umat)
163             {
164 #if !defined(GAPI_STANDALONE)
165                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
166                 mag_umat = to_ocv(*(util::get<cv::gapi::own::Mat*>(arg))).getUMat(ACCESS_RW);
167 #else
168                 util::throw_error(std::logic_error("UMat is not supported in standalone build"));
169 #endif // !defined(GAPI_STANDALONE)
170             }
171             else
172             {
173                 auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
174                 mag_mat = *util::get<cv::gapi::own::Mat*>(arg);
175             }
176             break;
177 #if !defined(GAPI_STANDALONE)
178         case GRunArgP::index_of<cv::Mat*>() :
179             if (is_umat)
180             {
181                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
182                 mag_umat = (*util::get<cv::UMat*>(arg));
183             }
184             else
185             {
186                 auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
187                 mag_mat = to_own(*util::get<cv::Mat*>(arg));
188             }
189             break;
190 #endif //  !defined(GAPI_STANDALONE)
191         default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
192         }
193         break;
194     }
195
196     case GShape::GSCALAR:
197     {
198         auto& mag_scalar = mag.template slot<cv::gapi::own::Scalar>()[rc.id];
199         switch (arg.index())
200         {
201             case GRunArgP::index_of<cv::gapi::own::Scalar*>() : mag_scalar = *util::get<cv::gapi::own::Scalar*>(arg); break;
202 #if !defined(GAPI_STANDALONE)
203             case GRunArgP::index_of<cv::Scalar*>()            : mag_scalar = to_own(*util::get<cv::Scalar*>(arg)); break;
204 #endif //  !defined(GAPI_STANDALONE)
205             default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
206         }
207         break;
208     }
209     case GShape::GARRAY:
210         mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
211         break;
212
213     default:
214         util::throw_error(std::logic_error("Unsupported GShape type"));
215         break;
216     }
217 }
218
219 void resetInternalData(Mag& mag, const Data &d)
220 {
221     if (d.storage != Data::Storage::INTERNAL)
222         return;
223
224     switch (d.shape)
225     {
226     case GShape::GARRAY:
227         util::get<cv::detail::ConstructVec>(d.ctor)
228             (mag.template slot<cv::detail::VectorRef>()[d.rc]);
229         break;
230
231     case GShape::GSCALAR:
232         mag.template slot<cv::gapi::own::Scalar>()[d.rc] = cv::gapi::own::Scalar();
233         break;
234
235     case GShape::GMAT:
236         // Do nothign here - FIXME unify with initInternalData?
237         break;
238
239     default:
240         util::throw_error(std::logic_error("Unsupported GShape type"));
241         break;
242     }
243 }
244
245 cv::GRunArg getArg(const Mag& mag, const RcDesc &ref)
246 {
247     // Wrap associated CPU object (either host or an internal one)
248     switch (ref.shape)
249     {
250     case GShape::GMAT:    return GRunArg(mag.template slot<cv::gapi::own::Mat>().at(ref.id));
251     case GShape::GSCALAR: return GRunArg(mag.template slot<cv::gapi::own::Scalar>().at(ref.id));
252     // Note: .at() is intentional for GArray as object MUST be already there
253     //   (and constructed by either bindIn/Out or resetInternal)
254     case GShape::GARRAY:  return GRunArg(mag.template slot<cv::detail::VectorRef>().at(ref.id));
255     default:
256         util::throw_error(std::logic_error("Unsupported GShape type"));
257         break;
258     }
259 }
260
261 cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat)
262 {
263     switch (rc.shape)
264     {
265     case GShape::GMAT:
266         if (is_umat)
267         {
268 #if !defined(GAPI_STANDALONE)
269             return GRunArgP(&mag.template slot<cv::UMat>()[rc.id]);
270 #else
271             util::throw_error(std::logic_error("UMat is not supported in standalone build"));
272 #endif //  !defined(GAPI_STANDALONE)
273         }
274         else
275             return GRunArgP(&mag.template slot<cv::gapi::own::Mat>()[rc.id]);
276     case GShape::GSCALAR: return GRunArgP(&mag.template slot<cv::gapi::own::Scalar>()[rc.id]);
277     // Note: .at() is intentional for GArray as object MUST be already there
278     //   (and constructer by either bindIn/Out or resetInternal)
279     case GShape::GARRAY:
280         // FIXME(DM): For some absolutely unknown to me reason, move
281         // semantics is involved here without const_cast to const (and
282         // value from map is moved into return value GRunArgP, leaving
283         // map with broken value I've spent few late Friday hours
284         // debugging this!!!1
285         return GRunArgP(const_cast<const Mag&>(mag)
286                         .template slot<cv::detail::VectorRef>().at(rc.id));
287     default:
288         util::throw_error(std::logic_error("Unsupported GShape type"));
289         break;
290     }
291 }
292
293 void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
294 {
295     switch (rc.shape)
296     {
297     case GShape::GARRAY:
298         // Do nothing - should we really do anything here?
299         break;
300
301     case GShape::GMAT:
302     {
303         //simply check that memory was not reallocated, i.e.
304         //both instances of Mat pointing to the same memory
305         uchar* out_arg_data = nullptr;
306         switch (g_arg.index())
307         {
308             case GRunArgP::index_of<cv::gapi::own::Mat*>() : out_arg_data = util::get<cv::gapi::own::Mat*>(g_arg)->data; break;
309 #if !defined(GAPI_STANDALONE)
310             case GRunArgP::index_of<cv::Mat*>()            : out_arg_data = util::get<cv::Mat*>(g_arg)->data; break;
311             case GRunArgP::index_of<cv::UMat*>()           : out_arg_data = (util::get<cv::UMat*>(g_arg))->getMat(ACCESS_RW).data; break;
312 #endif //  !defined(GAPI_STANDALONE)
313             default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
314         }
315         if (is_umat)
316         {
317 #if !defined(GAPI_STANDALONE)
318             auto& in_mag = mag.template slot<cv::UMat>().at(rc.id);
319             GAPI_Assert((out_arg_data == (in_mag.getMat(ACCESS_RW).data)) && " data for output parameters was reallocated ?");
320 #else
321             util::throw_error(std::logic_error("UMat is not supported in standalone build"));
322 #endif // !defined(GAPI_STANDALONE)
323         }
324         else
325         {
326             auto& in_mag = mag.template slot<cv::gapi::own::Mat>().at(rc.id);
327             GAPI_Assert((out_arg_data == in_mag.data) && " data for output parameters was reallocated ?");
328         }
329         break;
330     }
331
332     case GShape::GSCALAR:
333     {
334         switch (g_arg.index())
335         {
336             case GRunArgP::index_of<cv::gapi::own::Scalar*>() : *util::get<cv::gapi::own::Scalar*>(g_arg) = mag.template slot<cv::gapi::own::Scalar>().at(rc.id); break;
337 #if !defined(GAPI_STANDALONE)
338             case GRunArgP::index_of<cv::Scalar*>()            : *util::get<cv::Scalar*>(g_arg) = cv::gapi::own::to_ocv(mag.template slot<cv::gapi::own::Scalar>().at(rc.id)); break;
339 #endif //  !defined(GAPI_STANDALONE)
340             default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
341         }
342         break;
343     }
344
345     default:
346         util::throw_error(std::logic_error("Unsupported GShape type"));
347         break;
348     }
349 }
350
351 } // namespace magazine
352 } // namespace gimpl
353 } // namespace cv