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.
5 // Copyright (C) 2018-2019 Intel Corporation
8 #ifndef OPENCV_GAPI_FLUID_KERNEL_HPP
9 #define OPENCV_GAPI_FLUID_KERNEL_HPP
14 #include <unordered_map>
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>
22 #include <opencv2/gapi/fluid/gfluidbuffer.hpp>
24 // FIXME: namespace scheme for backends?
32 * \addtogroup gapi_std_backends G-API Standard backends
36 * @brief Get a reference to Fluid backend.
38 * @sa gapi_std_backends
40 GAPI_EXPORTS cv::gapi::GBackend backend();
46 class GAPI_EXPORTS GFluidKernel
55 // This function is a generic "doWork" callback
56 using F = std::function<void(const cv::GArgs&, const std::vector<gapi::fluid::Buffer*> &)>;
58 // This function is a generic "initScratch" callback
59 using IS = std::function<void(const cv::GMetaArgs &, const cv::GArgs&, gapi::fluid::Buffer &)>;
61 // This function is a generic "resetScratch" callback
62 using RS = std::function<void(gapi::fluid::Buffer &)>;
64 // This function describes kernel metadata inference rule.
65 using M = std::function<GMetaArgs(const GMetaArgs &, const GArgs &)>;
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&)>;
70 // FIXME: move implementations out of header file
72 GFluidKernel(int w, Kind k, int l, bool scratch, const F& f, const IS &is, const RS &rs, const B& b)
85 const bool m_scratch = false;
94 // This is the temporary and experimental API
95 // which should be replaced by runtime roi-based scheduling
96 struct GFluidOutputRois
98 std::vector<cv::gapi::own::Rect> rois;
103 template<> struct CompileArgTag<GFluidOutputRois>
105 static const char* tag() { return "gapi.fluid.outputRois"; }
107 } // namespace detail
111 template<class T> struct fluid_get_in;
112 template<> struct fluid_get_in<cv::GMat>
114 static const cv::gapi::fluid::View& get(const cv::GArgs &in_args, int idx)
116 return in_args[idx].unsafe_get<cv::gapi::fluid::View>();
120 template<> struct fluid_get_in<cv::GScalar>
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)
126 return cv::gapi::own::to_ocv(in_args[idx].unsafe_get<cv::gapi::own::Scalar>());
129 static const cv::gapi::own::Scalar get(const cv::GArgs &in_args, int idx)
131 return in_args[idx].get<cv::gapi::own::Scalar>();
133 #endif // !defined(GAPI_STANDALONE)
135 template<class T> struct fluid_get_in
137 static const T& get(const cv::GArgs &in_args, int idx)
139 return in_args[idx].unsafe_get<T>();
143 template<bool, typename Impl, typename... Ins>
144 struct scratch_helper;
146 template<typename Impl, typename... Ins>
147 struct scratch_helper<true, Impl, Ins...>
151 static void help_init_impl(const cv::GMetaArgs &metas,
152 const cv::GArgs &in_args,
153 gapi::fluid::Buffer &scratch_buf,
156 Impl::initScratch(get_in_meta<Ins>(metas, in_args, IIs)..., scratch_buf);
159 static void help_init(const cv::GMetaArgs &metas,
160 const cv::GArgs &in_args,
161 gapi::fluid::Buffer &b)
163 help_init_impl(metas, in_args, b, typename detail::MkSeq<sizeof...(Ins)>::type());
167 static void help_reset(gapi::fluid::Buffer &b)
169 Impl::resetScratch(b);
173 template<typename Impl, typename... Ins>
174 struct scratch_helper<false, Impl, Ins...>
176 static void help_init(const cv::GMetaArgs &,
178 gapi::fluid::Buffer &)
182 static void help_reset(gapi::fluid::Buffer &)
188 template<typename T> struct is_gmat_type
190 static const constexpr bool value = std::is_same<cv::GMat, T>::value;
193 template<bool CallCustomGetBorder, typename Impl, typename... Ins>
194 struct get_border_helper;
196 template<typename Impl, typename... Ins>
197 struct get_border_helper<true, Impl, Ins...>
200 static gapi::fluid::BorderOpt get_border_impl(const GMetaArgs &metas,
201 const cv::GArgs &in_args,
202 cv::detail::Seq<IIs...>)
204 return util::make_optional(Impl::getBorder(cv::detail::get_in_meta<Ins>(metas, in_args, IIs)...));
207 static gapi::fluid::BorderOpt help(const GMetaArgs &metas,
208 const cv::GArgs &in_args)
210 return get_border_impl(metas, in_args, typename detail::MkSeq<sizeof...(Ins)>::type());
214 template<typename Impl, typename... Ins>
215 struct get_border_helper<false, Impl, Ins...>
217 static gapi::fluid::BorderOpt help(const cv::GMetaArgs &,
224 template<typename, typename, typename, bool UseScratch>
225 struct FluidCallHelper;
227 template<typename Impl, typename... Ins, typename... Outs, bool UseScratch>
228 struct FluidCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>, UseScratch>
230 static_assert(all_satisfy<is_gmat_type, Outs...>::value, "return type must be GMat");
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,
239 Impl::run(fluid_get_in<Ins>::get(in_args, IIs)..., *out_bufs[OIs]...);
242 static void call(const cv::GArgs &in_args,
243 const std::vector<gapi::fluid::Buffer*> &out_bufs)
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());
251 // Scratch buffer initialization dispatcher ////////////////////////////////
252 static void init_scratch(const GMetaArgs &metas,
253 const cv::GArgs &in_args,
254 gapi::fluid::Buffer &b)
256 scratch_helper<UseScratch, Impl, Ins...>::help_init(metas, in_args, b);
259 // Scratch buffer reset dispatcher /////////////////////////////////////////
260 static void reset_scratch(gapi::fluid::Buffer &scratch_buf)
262 scratch_helper<UseScratch, Impl, Ins...>::help_reset(scratch_buf);
265 static gapi::fluid::BorderOpt getBorder(const GMetaArgs &metas, const cv::GArgs &in_args)
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);
273 } // namespace detail
276 template<class Impl, class K, bool UseScratch>
277 class GFluidKernelImpl
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>;
286 static GFluidKernel kernel()
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,
292 &P::call, &P::init_scratch, &P::reset_scratch, &P::getBorder);
295 static cv::gapi::GBackend backend() { return cv::gapi::fluid::backend(); }
298 #define GAPI_FLUID_KERNEL(Name, API, Scratch) struct Name: public cv::GFluidKernelImpl<Name, API, Scratch>
302 #endif // OPENCV_GAPI_GCPUKERNEL_HPP