Publishing 2019 R3 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 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 cv::gapi::GKernelPackage cv::gapi::GBackend::Priv::auxiliaryKernels() const
49 {
50     return {};
51 }
52
53 // GBackend public implementation //////////////////////////////////////////////
54 cv::gapi::GBackend::GBackend()
55 {
56 }
57
58 cv::gapi::GBackend::GBackend(std::shared_ptr<cv::gapi::GBackend::Priv> &&p)
59     : m_priv(std::move(p))
60 {
61 }
62
63 cv::gapi::GBackend::Priv& cv::gapi::GBackend::priv()
64 {
65     return *m_priv;
66 }
67
68 const cv::gapi::GBackend::Priv& cv::gapi::GBackend::priv() const
69 {
70     return *m_priv;
71 }
72
73 std::size_t cv::gapi::GBackend::hash() const
74 {
75     return std::hash<const cv::gapi::GBackend::Priv*>{}(m_priv.get());
76 }
77
78 bool cv::gapi::GBackend::operator== (const cv::gapi::GBackend &rhs) const
79 {
80     return m_priv == rhs.m_priv;
81 }
82
83 // Abstract Host-side data manipulation ////////////////////////////////////////
84 // Reused between CPU backend and more generic GExecutor
85 namespace cv {
86 namespace gimpl {
87 namespace magazine {
88
89 // FIXME implement the below functions with visit()?
90
91 void bindInArg(Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat)
92 {
93     switch (rc.shape)
94     {
95     case GShape::GMAT:
96     {
97         switch (arg.index())
98         {
99         case GRunArg::index_of<cv::gapi::own::Mat>() :
100             if (is_umat)
101             {
102 #if !defined(GAPI_STANDALONE)
103                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
104                 mag_umat = to_ocv(util::get<cv::gapi::own::Mat>(arg)).getUMat(ACCESS_READ);
105 #else
106                 util::throw_error(std::logic_error("UMat is not supported in standalone build"));
107 #endif // !defined(GAPI_STANDALONE)
108             }
109             else
110             {
111                 auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
112                 mag_mat = util::get<cv::gapi::own::Mat>(arg);
113             }
114             break;
115 #if !defined(GAPI_STANDALONE)
116         case GRunArg::index_of<cv::Mat>() :
117             if (is_umat)
118             {
119                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
120                 mag_umat = (util::get<cv::UMat>(arg));
121             }
122             else
123             {
124                 auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
125                 mag_mat = to_own(util::get<cv::Mat>(arg));
126             }
127             break;
128 #endif //  !defined(GAPI_STANDALONE)
129         default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
130         }
131         break;
132     }
133
134
135     case GShape::GSCALAR:
136     {
137         auto& mag_scalar = mag.template slot<cv::gapi::own::Scalar>()[rc.id];
138         switch (arg.index())
139         {
140             case GRunArg::index_of<cv::gapi::own::Scalar>() : mag_scalar = util::get<cv::gapi::own::Scalar>(arg); break;
141 #if !defined(GAPI_STANDALONE)
142             case GRunArg::index_of<cv::Scalar>()            : mag_scalar = to_own(util::get<cv::Scalar>(arg));    break;
143 #endif //  !defined(GAPI_STANDALONE)
144             default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
145         }
146         break;
147     }
148
149     case GShape::GARRAY:
150         mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
151         break;
152
153     default:
154         util::throw_error(std::logic_error("Unsupported GShape type"));
155     }
156 }
157
158 void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat)
159 {
160     switch (rc.shape)
161     {
162     case GShape::GMAT:
163     {
164         switch (arg.index())
165         {
166         case GRunArgP::index_of<cv::gapi::own::Mat*>() :
167             if (is_umat)
168             {
169 #if !defined(GAPI_STANDALONE)
170                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
171                 mag_umat = to_ocv(*(util::get<cv::gapi::own::Mat*>(arg))).getUMat(ACCESS_RW);
172 #else
173                 util::throw_error(std::logic_error("UMat is not supported in standalone build"));
174 #endif // !defined(GAPI_STANDALONE)
175             }
176             else
177             {
178                 auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
179                 mag_mat = *util::get<cv::gapi::own::Mat*>(arg);
180             }
181             break;
182 #if !defined(GAPI_STANDALONE)
183         case GRunArgP::index_of<cv::Mat*>() :
184             if (is_umat)
185             {
186                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
187                 mag_umat = (*util::get<cv::UMat*>(arg));
188             }
189             else
190             {
191                 auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
192                 mag_mat = to_own(*util::get<cv::Mat*>(arg));
193             }
194             break;
195 #endif //  !defined(GAPI_STANDALONE)
196         default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
197         }
198         break;
199     }
200
201     case GShape::GSCALAR:
202     {
203         auto& mag_scalar = mag.template slot<cv::gapi::own::Scalar>()[rc.id];
204         switch (arg.index())
205         {
206             case GRunArgP::index_of<cv::gapi::own::Scalar*>() : mag_scalar = *util::get<cv::gapi::own::Scalar*>(arg); break;
207 #if !defined(GAPI_STANDALONE)
208             case GRunArgP::index_of<cv::Scalar*>()            : mag_scalar = to_own(*util::get<cv::Scalar*>(arg)); break;
209 #endif //  !defined(GAPI_STANDALONE)
210             default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
211         }
212         break;
213     }
214     case GShape::GARRAY:
215         mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
216         break;
217
218     default:
219         util::throw_error(std::logic_error("Unsupported GShape type"));
220         break;
221     }
222 }
223
224 void resetInternalData(Mag& mag, const Data &d)
225 {
226     if (d.storage != Data::Storage::INTERNAL)
227         return;
228
229     switch (d.shape)
230     {
231     case GShape::GARRAY:
232         util::get<cv::detail::ConstructVec>(d.ctor)
233             (mag.template slot<cv::detail::VectorRef>()[d.rc]);
234         break;
235
236     case GShape::GSCALAR:
237         mag.template slot<cv::gapi::own::Scalar>()[d.rc] = cv::gapi::own::Scalar();
238         break;
239
240     case GShape::GMAT:
241         // Do nothign here - FIXME unify with initInternalData?
242         break;
243
244     default:
245         util::throw_error(std::logic_error("Unsupported GShape type"));
246         break;
247     }
248 }
249
250 cv::GRunArg getArg(const Mag& mag, const RcDesc &ref)
251 {
252     // Wrap associated CPU object (either host or an internal one)
253     switch (ref.shape)
254     {
255     case GShape::GMAT:    return GRunArg(mag.template slot<cv::gapi::own::Mat>().at(ref.id));
256     case GShape::GSCALAR: return GRunArg(mag.template slot<cv::gapi::own::Scalar>().at(ref.id));
257     // Note: .at() is intentional for GArray as object MUST be already there
258     //   (and constructed by either bindIn/Out or resetInternal)
259     case GShape::GARRAY:  return GRunArg(mag.template slot<cv::detail::VectorRef>().at(ref.id));
260     default:
261         util::throw_error(std::logic_error("Unsupported GShape type"));
262         break;
263     }
264 }
265
266 cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat)
267 {
268     switch (rc.shape)
269     {
270     case GShape::GMAT:
271         if (is_umat)
272         {
273 #if !defined(GAPI_STANDALONE)
274             return GRunArgP(&mag.template slot<cv::UMat>()[rc.id]);
275 #else
276             util::throw_error(std::logic_error("UMat is not supported in standalone build"));
277 #endif //  !defined(GAPI_STANDALONE)
278         }
279         else
280             return GRunArgP(&mag.template slot<cv::gapi::own::Mat>()[rc.id]);
281     case GShape::GSCALAR: return GRunArgP(&mag.template slot<cv::gapi::own::Scalar>()[rc.id]);
282     // Note: .at() is intentional for GArray as object MUST be already there
283     //   (and constructer by either bindIn/Out or resetInternal)
284     case GShape::GARRAY:
285         // FIXME(DM): For some absolutely unknown to me reason, move
286         // semantics is involved here without const_cast to const (and
287         // value from map is moved into return value GRunArgP, leaving
288         // map with broken value I've spent few late Friday hours
289         // debugging this!!!1
290         return GRunArgP(const_cast<const Mag&>(mag)
291                         .template slot<cv::detail::VectorRef>().at(rc.id));
292     default:
293         util::throw_error(std::logic_error("Unsupported GShape type"));
294         break;
295     }
296 }
297
298 void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
299 {
300     switch (rc.shape)
301     {
302     case GShape::GARRAY:
303         // Do nothing - should we really do anything here?
304         break;
305
306     case GShape::GMAT:
307     {
308         //simply check that memory was not reallocated, i.e.
309         //both instances of Mat pointing to the same memory
310         uchar* out_arg_data = nullptr;
311         switch (g_arg.index())
312         {
313             case GRunArgP::index_of<cv::gapi::own::Mat*>() : out_arg_data = util::get<cv::gapi::own::Mat*>(g_arg)->data; break;
314 #if !defined(GAPI_STANDALONE)
315             case GRunArgP::index_of<cv::Mat*>()            : out_arg_data = util::get<cv::Mat*>(g_arg)->data; break;
316             case GRunArgP::index_of<cv::UMat*>()           : out_arg_data = (util::get<cv::UMat*>(g_arg))->getMat(ACCESS_RW).data; break;
317 #endif //  !defined(GAPI_STANDALONE)
318             default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
319         }
320         if (is_umat)
321         {
322 #if !defined(GAPI_STANDALONE)
323             auto& in_mag = mag.template slot<cv::UMat>().at(rc.id);
324             GAPI_Assert((out_arg_data == (in_mag.getMat(ACCESS_RW).data)) && " data for output parameters was reallocated ?");
325 #else
326             util::throw_error(std::logic_error("UMat is not supported in standalone build"));
327 #endif // !defined(GAPI_STANDALONE)
328         }
329         else
330         {
331             auto& in_mag = mag.template slot<cv::gapi::own::Mat>().at(rc.id);
332             GAPI_Assert((out_arg_data == in_mag.data) && " data for output parameters was reallocated ?");
333         }
334         break;
335     }
336
337     case GShape::GSCALAR:
338     {
339         switch (g_arg.index())
340         {
341             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;
342 #if !defined(GAPI_STANDALONE)
343             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;
344 #endif //  !defined(GAPI_STANDALONE)
345             default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
346         }
347         break;
348     }
349
350     default:
351         util::throw_error(std::logic_error("Unsupported GShape type"));
352         break;
353     }
354 }
355
356 } // namespace magazine
357
358 void createMat(const cv::GMatDesc desc, cv::gapi::own::Mat& mat)
359 {
360     const auto type = desc.planar ? desc.depth : CV_MAKETYPE(desc.depth, desc.chan);
361     const auto size = desc.planar ? cv::gapi::own::Size{desc.size.width, desc.size.height*desc.chan}
362                                   : desc.size;
363     mat.create(size, type);
364 }
365
366 #if !defined(GAPI_STANDALONE)
367 void createMat(const cv::GMatDesc desc, cv::Mat& mat)
368 {
369     const auto type = desc.planar ? desc.depth : CV_MAKETYPE(desc.depth, desc.chan);
370     const auto size = desc.planar ? cv::Size{desc.size.width, desc.size.height*desc.chan}
371                                   : cv::gapi::own::to_ocv(desc.size);
372     mat.create(size, type);
373 }
374 #endif
375
376 } // namespace gimpl
377 } // namespace cv