Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / fluid / modules / gapi / include / opencv2 / gapi / fluid / gfluidkernel.hpp
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 #ifndef OPENCV_GAPI_FLUID_KERNEL_HPP
9 #define OPENCV_GAPI_FLUID_KERNEL_HPP
10
11 #include <vector>
12 #include <functional>
13 #include <map>
14 #include <unordered_map>
15
16 #include <opencv2/gapi/opencv_includes.hpp>
17 #include <opencv2/gapi/gcommon.hpp>
18 #include <opencv2/gapi/gkernel.hpp>
19 #include <opencv2/gapi/garg.hpp>
20 #include <opencv2/gapi/own/types.hpp>
21
22 #include <opencv2/gapi/fluid/gfluidbuffer.hpp>
23
24 // FIXME: namespace scheme for backends?
25 namespace cv {
26
27 namespace gapi
28 {
29 namespace fluid
30 {
31     /**
32      * \addtogroup gapi_std_backends G-API Standard backends
33      * @{
34      */
35     /**
36      * @brief Get a reference to Fluid backend.
37      *
38      * @sa gapi_std_backends
39      */
40     GAPI_EXPORTS cv::gapi::GBackend backend();
41     /** @} */
42 } // namespace flud
43 } // namespace gapi
44
45
46 class GAPI_EXPORTS GFluidKernel
47 {
48 public:
49     enum class Kind
50     {
51         Filter,
52         Resize
53     };
54
55     // This function is a generic "doWork" callback
56     using F = std::function<void(const cv::GArgs&, const std::vector<gapi::fluid::Buffer*> &)>;
57
58     // This function is a generic "initScratch" callback
59     using IS = std::function<void(const cv::GMetaArgs &, const cv::GArgs&, gapi::fluid::Buffer &)>;
60
61     // This function is a generic "resetScratch" callback
62     using RS = std::function<void(gapi::fluid::Buffer &)>;
63
64     // This function describes kernel metadata inference rule.
65     using M = std::function<GMetaArgs(const GMetaArgs &, const GArgs &)>;
66
67     // This function is a generic "getBorder" callback (extracts border-related data from kernel's input parameters)
68     using B = std::function<gapi::fluid::BorderOpt(const GMetaArgs&, const GArgs&)>;
69
70     // FIXME: move implementations out of header file
71     GFluidKernel() {}
72     GFluidKernel(int w, Kind k, int l, bool scratch, const F& f, const IS &is, const RS &rs, const B& b)
73         : m_window(w)
74         , m_kind(k)
75         , m_lpi(l)
76         , m_scratch(scratch)
77         , m_f(f)
78         , m_is(is)
79         , m_rs(rs)
80         , m_b(b) {}
81
82     int m_window = -1;
83     Kind m_kind;
84     const int  m_lpi     = -1;
85     const bool m_scratch = false;
86
87     const F    m_f;
88     const IS   m_is;
89     const RS   m_rs;
90     const B    m_b;
91 };
92
93 // FIXME!!!
94 // This is the temporary and experimental API
95 // which should be replaced by runtime roi-based scheduling
96 struct GFluidOutputRois
97 {
98     std::vector<cv::gapi::own::Rect> rois;
99 };
100
101 namespace detail
102 {
103 template<> struct CompileArgTag<GFluidOutputRois>
104 {
105     static const char* tag() { return "gapi.fluid.outputRois"; }
106 };
107 } // namespace detail
108
109 namespace detail
110 {
111 template<class T> struct fluid_get_in;
112 template<> struct fluid_get_in<cv::GMat>
113 {
114     static const cv::gapi::fluid::View& get(const cv::GArgs &in_args, int idx)
115     {
116         return in_args[idx].unsafe_get<cv::gapi::fluid::View>();
117     }
118 };
119
120 template<> struct fluid_get_in<cv::GScalar>
121 {
122     // FIXME: change to return by reference when moved to own::Scalar
123 #if !defined(GAPI_STANDALONE)
124     static const cv::Scalar get(const cv::GArgs &in_args, int idx)
125     {
126         return cv::gapi::own::to_ocv(in_args[idx].unsafe_get<cv::gapi::own::Scalar>());
127     }
128 #else
129     static const cv::gapi::own::Scalar get(const cv::GArgs &in_args, int idx)
130     {
131         return in_args[idx].get<cv::gapi::own::Scalar>();
132     }
133 #endif // !defined(GAPI_STANDALONE)
134 };
135 template<class T> struct fluid_get_in
136 {
137     static const T& get(const cv::GArgs &in_args, int idx)
138     {
139         return in_args[idx].unsafe_get<T>();
140     }
141 };
142
143 template<bool, typename Impl, typename... Ins>
144 struct scratch_helper;
145
146 template<typename Impl, typename... Ins>
147 struct scratch_helper<true, Impl, Ins...>
148 {
149     // Init
150     template<int... IIs>
151     static void help_init_impl(const cv::GMetaArgs &metas,
152                                const cv::GArgs     &in_args,
153                                gapi::fluid::Buffer &scratch_buf,
154                                detail::Seq<IIs...>)
155     {
156         Impl::initScratch(get_in_meta<Ins>(metas, in_args, IIs)..., scratch_buf);
157     }
158
159     static void help_init(const cv::GMetaArgs &metas,
160                           const cv::GArgs     &in_args,
161                           gapi::fluid::Buffer &b)
162     {
163         help_init_impl(metas, in_args, b, typename detail::MkSeq<sizeof...(Ins)>::type());
164     }
165
166     // Reset
167     static void help_reset(gapi::fluid::Buffer &b)
168     {
169         Impl::resetScratch(b);
170     }
171 };
172
173 template<typename Impl, typename... Ins>
174 struct scratch_helper<false, Impl, Ins...>
175 {
176     static void help_init(const cv::GMetaArgs &,
177                           const cv::GArgs     &,
178                           gapi::fluid::Buffer &)
179     {
180         GAPI_Assert(false);
181     }
182     static void help_reset(gapi::fluid::Buffer &)
183     {
184         GAPI_Assert(false);
185     }
186 };
187
188 template<typename T> struct is_gmat_type
189 {
190     static const constexpr bool value = std::is_same<cv::GMat, T>::value;
191 };
192
193 template<bool CallCustomGetBorder, typename Impl, typename... Ins>
194 struct get_border_helper;
195
196 template<typename Impl, typename... Ins>
197 struct get_border_helper<true, Impl, Ins...>
198 {
199     template<int... IIs>
200     static gapi::fluid::BorderOpt get_border_impl(const GMetaArgs &metas,
201                                                   const cv::GArgs &in_args,
202                                                   cv::detail::Seq<IIs...>)
203     {
204         return util::make_optional(Impl::getBorder(cv::detail::get_in_meta<Ins>(metas, in_args, IIs)...));
205     }
206
207     static gapi::fluid::BorderOpt help(const GMetaArgs &metas,
208                                        const cv::GArgs &in_args)
209     {
210         return get_border_impl(metas, in_args, typename detail::MkSeq<sizeof...(Ins)>::type());
211     }
212 };
213
214 template<typename Impl, typename... Ins>
215 struct get_border_helper<false, Impl, Ins...>
216 {
217     static gapi::fluid::BorderOpt help(const cv::GMetaArgs &,
218                                        const cv::GArgs     &)
219     {
220         return {};
221     }
222 };
223
224 template<typename, typename, typename, bool UseScratch>
225 struct FluidCallHelper;
226
227 template<typename Impl, typename... Ins, typename... Outs, bool UseScratch>
228 struct FluidCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>, UseScratch>
229 {
230     static_assert(all_satisfy<is_gmat_type, Outs...>::value, "return type must be GMat");
231
232     // Execution dispatcher ////////////////////////////////////////////////////
233     template<int... IIs, int... OIs>
234     static void call_impl(const cv::GArgs &in_args,
235                           const std::vector<gapi::fluid::Buffer*> &out_bufs,
236                           detail::Seq<IIs...>,
237                           detail::Seq<OIs...>)
238     {
239         Impl::run(fluid_get_in<Ins>::get(in_args, IIs)..., *out_bufs[OIs]...);
240     }
241
242     static void call(const cv::GArgs &in_args,
243                      const std::vector<gapi::fluid::Buffer*> &out_bufs)
244     {
245         constexpr int numOuts = (sizeof...(Outs)) + (UseScratch ? 1 : 0);
246         call_impl(in_args, out_bufs,
247                   typename detail::MkSeq<sizeof...(Ins)>::type(),
248                   typename detail::MkSeq<numOuts>::type());
249     }
250
251     // Scratch buffer initialization dispatcher ////////////////////////////////
252     static void init_scratch(const GMetaArgs &metas,
253                              const cv::GArgs &in_args,
254                              gapi::fluid::Buffer &b)
255     {
256         scratch_helper<UseScratch, Impl, Ins...>::help_init(metas, in_args, b);
257     }
258
259     // Scratch buffer reset dispatcher /////////////////////////////////////////
260     static void reset_scratch(gapi::fluid::Buffer &scratch_buf)
261     {
262         scratch_helper<UseScratch, Impl, Ins...>::help_reset(scratch_buf);
263     }
264
265     static gapi::fluid::BorderOpt getBorder(const GMetaArgs &metas, const cv::GArgs &in_args)
266     {
267         // User must provide "init" callback if Window != 1
268         // TODO: move to constexpr if when we enable C++17
269         constexpr bool callCustomGetBorder = (Impl::Window != 1);
270         return get_border_helper<callCustomGetBorder, Impl, Ins...>::help(metas, in_args);
271     }
272 };
273 } // namespace detail
274
275
276 template<class Impl, class K, bool UseScratch>
277 class GFluidKernelImpl
278 {
279     static const int LPI = 1;
280     static const auto Kind = GFluidKernel::Kind::Filter;
281     using P = detail::FluidCallHelper<Impl, typename K::InArgs, typename K::OutArgs, UseScratch>;
282
283 public:
284     using API = K;
285
286     static GFluidKernel kernel()
287     {
288         // FIXME: call() and getOutMeta() needs to be renamed so it is clear these
289         // functions are internal wrappers, not user API
290         return GFluidKernel(Impl::Window, Impl::Kind, Impl::LPI,
291                             UseScratch,
292                             &P::call, &P::init_scratch, &P::reset_scratch, &P::getBorder);
293     }
294
295     static cv::gapi::GBackend backend() { return cv::gapi::fluid::backend(); }
296 };
297
298 #define GAPI_FLUID_KERNEL(Name, API, Scratch) struct Name: public cv::GFluidKernelImpl<Name, API, Scratch>
299
300 } // namespace cv
301
302 #endif // OPENCV_GAPI_GCPUKERNEL_HPP