gfluidkernel.hpp 9.0 KB

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