gopaque.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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) 2019-2020 Intel Corporation
  6. #ifndef OPENCV_GAPI_GOPAQUE_HPP
  7. #define OPENCV_GAPI_GOPAQUE_HPP
  8. #include <functional>
  9. #include <ostream>
  10. #include <memory>
  11. #include <opencv2/gapi/own/exports.hpp>
  12. #include <opencv2/gapi/opencv_includes.hpp>
  13. #include <opencv2/gapi/util/any.hpp>
  14. #include <opencv2/gapi/util/variant.hpp>
  15. #include <opencv2/gapi/util/throw.hpp>
  16. #include <opencv2/gapi/util/type_traits.hpp>
  17. #include <opencv2/gapi/own/assert.hpp>
  18. #include <opencv2/gapi/gcommon.hpp> // OpaqueKind
  19. #include <opencv2/gapi/garray.hpp> // TypeHintBase
  20. namespace cv
  21. {
  22. // Forward declaration; GNode and GOrigin are an internal
  23. // (user-inaccessible) classes.
  24. class GNode;
  25. struct GOrigin;
  26. template<typename T> class GOpaque;
  27. /**
  28. * \addtogroup gapi_meta_args
  29. * @{
  30. */
  31. struct GAPI_EXPORTS_W_SIMPLE GOpaqueDesc
  32. {
  33. // FIXME: Body
  34. // FIXME: Also implement proper operator== then
  35. bool operator== (const GOpaqueDesc&) const { return true; }
  36. };
  37. template<typename U> GOpaqueDesc descr_of(const U &) { return {};}
  38. GAPI_EXPORTS_W inline GOpaqueDesc empty_gopaque_desc() {return {}; }
  39. /** @} */
  40. std::ostream& operator<<(std::ostream& os, const cv::GOpaqueDesc &desc);
  41. namespace detail
  42. {
  43. // ConstructOpaque is a callback which stores information about T and is used by
  44. // G-API runtime to construct an object in host memory (T remains opaque for G-API).
  45. // ConstructOpaque is carried into G-API internals by GOpaqueU.
  46. // Currently it is suitable for Host (CPU) plugins only, real offload may require
  47. // more information for manual memory allocation on-device.
  48. class OpaqueRef;
  49. using ConstructOpaque = std::function<void(OpaqueRef&)>;
  50. // FIXME: garray.hpp already contains hint classes (for actual T type verification),
  51. // need to think where it can be moved (currently opaque uses it from garray)
  52. // This class strips type information from GOpaque<T> and makes it usable
  53. // in the G-API graph compiler (expression unrolling, graph generation, etc).
  54. // Part of GProtoArg.
  55. class GAPI_EXPORTS GOpaqueU
  56. {
  57. public:
  58. GOpaqueU(const GNode &n, std::size_t out); // Operation result constructor
  59. template <typename T>
  60. bool holds() const; // Check if was created from GOpaque<T>
  61. GOrigin& priv(); // Internal use only
  62. const GOrigin& priv() const; // Internal use only
  63. protected:
  64. GOpaqueU(); // Default constructor
  65. template<class> friend class cv::GOpaque; // (available for GOpaque<T> only)
  66. void setConstructFcn(ConstructOpaque &&cv); // Store T-aware constructor
  67. template <typename T>
  68. void specifyType(); // Store type of initial GOpaque<T>
  69. template <typename T>
  70. void storeKind();
  71. void setKind(cv::detail::OpaqueKind);
  72. std::shared_ptr<GOrigin> m_priv;
  73. std::shared_ptr<TypeHintBase> m_hint;
  74. };
  75. template <typename T>
  76. bool GOpaqueU::holds() const{
  77. GAPI_Assert(m_hint != nullptr);
  78. using U = util::decay_t<T>;
  79. return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
  80. };
  81. template <typename T>
  82. void GOpaqueU::specifyType(){
  83. m_hint.reset(new TypeHint<util::decay_t<T>>);
  84. };
  85. template <typename T>
  86. void GOpaqueU::storeKind(){
  87. // FIXME: Add assert here on cv::Mat and cv::Scalar?
  88. setKind(cv::detail::GOpaqueTraits<T>::kind);
  89. };
  90. // This class represents a typed object reference.
  91. // Depending on origins, this reference may be either "just a" reference to
  92. // an object created externally, OR actually own the underlying object
  93. // (be value holder).
  94. class BasicOpaqueRef
  95. {
  96. public:
  97. cv::GOpaqueDesc m_desc;
  98. virtual ~BasicOpaqueRef() {}
  99. virtual void mov(BasicOpaqueRef &ref) = 0;
  100. virtual const void* ptr() const = 0;
  101. virtual void set(const cv::util::any &a) = 0;
  102. };
  103. template<typename T> class OpaqueRefT final: public BasicOpaqueRef
  104. {
  105. using empty_t = util::monostate;
  106. using ro_ext_t = const T *;
  107. using rw_ext_t = T *;
  108. using rw_own_t = T ;
  109. util::variant<empty_t, ro_ext_t, rw_ext_t, rw_own_t> m_ref;
  110. inline bool isEmpty() const { return util::holds_alternative<empty_t>(m_ref); }
  111. inline bool isROExt() const { return util::holds_alternative<ro_ext_t>(m_ref); }
  112. inline bool isRWExt() const { return util::holds_alternative<rw_ext_t>(m_ref); }
  113. inline bool isRWOwn() const { return util::holds_alternative<rw_own_t>(m_ref); }
  114. void init(const T* obj = nullptr)
  115. {
  116. if (obj) m_desc = cv::descr_of(*obj);
  117. }
  118. public:
  119. OpaqueRefT() { init(); }
  120. virtual ~OpaqueRefT() {}
  121. explicit OpaqueRefT(const T& obj) : m_ref(&obj) { init(&obj); }
  122. explicit OpaqueRefT( T& obj) : m_ref(&obj) { init(&obj); }
  123. explicit OpaqueRefT( T&& obj) : m_ref(std::move(obj)) { init(&obj); }
  124. // Reset a OpaqueRefT. Called only for objects instantiated
  125. // internally in G-API (e.g. temporary GOpaque<T>'s within a
  126. // computation). Reset here means both initialization
  127. // (creating an object) and reset (discarding its existing
  128. // content before the next execution). Must never be called
  129. // for external OpaqueRefTs.
  130. void reset()
  131. {
  132. if (isEmpty())
  133. {
  134. T empty_obj{};
  135. m_desc = cv::descr_of(empty_obj);
  136. m_ref = std::move(empty_obj);
  137. GAPI_Assert(isRWOwn());
  138. }
  139. else if (isRWOwn())
  140. {
  141. util::get<rw_own_t>(m_ref) = {};
  142. }
  143. else GAPI_Assert(false); // shouldn't be called in *EXT modes
  144. }
  145. // Obtain a WRITE reference to underlying object
  146. // Used by CPU kernel API wrappers when a kernel execution frame
  147. // is created
  148. T& wref()
  149. {
  150. GAPI_Assert(isRWExt() || isRWOwn());
  151. if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
  152. if (isRWOwn()) return util::get<rw_own_t>(m_ref);
  153. util::throw_error(std::logic_error("Impossible happened"));
  154. }
  155. // Obtain a READ reference to underlying object
  156. // Used by CPU kernel API wrappers when a kernel execution frame
  157. // is created
  158. const T& rref() const
  159. {
  160. // ANY object can be accessed for reading, even if it declared for
  161. // output. Example -- a GComputation from [in] to [out1,out2]
  162. // where [out2] is a result of operation applied to [out1]:
  163. //
  164. // GComputation boundary
  165. // . . . . . . .
  166. // . .
  167. // [in] ----> foo() ----> [out1]
  168. // . . :
  169. // . . . .:. . .
  170. // . V .
  171. // . bar() ---> [out2]
  172. // . . . . . . . . . . . .
  173. //
  174. if (isROExt()) return *util::get<ro_ext_t>(m_ref);
  175. if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
  176. if (isRWOwn()) return util::get<rw_own_t>(m_ref);
  177. util::throw_error(std::logic_error("Impossible happened"));
  178. }
  179. virtual void mov(BasicOpaqueRef &v) override {
  180. OpaqueRefT<T> *tv = dynamic_cast<OpaqueRefT<T>*>(&v);
  181. GAPI_Assert(tv != nullptr);
  182. wref() = std::move(tv->wref());
  183. }
  184. virtual const void* ptr() const override { return &rref(); }
  185. virtual void set(const cv::util::any &a) override {
  186. wref() = util::any_cast<T>(a);
  187. }
  188. };
  189. // This class strips type information from OpaqueRefT<> and makes it usable
  190. // in the G-API executables (carrying run-time data/information to kernels).
  191. // Part of GRunArg.
  192. // Its methods are typed proxies to OpaqueRefT<T>.
  193. // OpaqueRef maintains "reference" semantics so two copies of OpaqueRef refer
  194. // to the same underlying object.
  195. class OpaqueRef
  196. {
  197. std::shared_ptr<BasicOpaqueRef> m_ref;
  198. cv::detail::OpaqueKind m_kind = cv::detail::OpaqueKind::CV_UNKNOWN;
  199. template<typename T> inline void check() const
  200. {
  201. GAPI_DbgAssert(dynamic_cast<OpaqueRefT<T>*>(m_ref.get()) != nullptr);
  202. }
  203. public:
  204. OpaqueRef() = default;
  205. template<
  206. typename T,
  207. typename = util::are_different_t<OpaqueRef, T>
  208. >
  209. // FIXME: probably won't work with const object
  210. explicit OpaqueRef(T&& obj) :
  211. m_ref(new OpaqueRefT<util::decay_t<T>>(std::forward<T>(obj))),
  212. m_kind(GOpaqueTraits<util::decay_t<T>>::kind) {}
  213. cv::detail::OpaqueKind getKind() const
  214. {
  215. return m_kind;
  216. }
  217. template<typename T> void reset()
  218. {
  219. if (!m_ref) m_ref.reset(new OpaqueRefT<T>());
  220. check<T>();
  221. storeKind<T>();
  222. static_cast<OpaqueRefT<T>&>(*m_ref).reset();
  223. }
  224. template <typename T>
  225. void storeKind()
  226. {
  227. m_kind = cv::detail::GOpaqueTraits<T>::kind;
  228. }
  229. template<typename T> T& wref()
  230. {
  231. check<T>();
  232. return static_cast<OpaqueRefT<T>&>(*m_ref).wref();
  233. }
  234. template<typename T> const T& rref() const
  235. {
  236. check<T>();
  237. return static_cast<OpaqueRefT<T>&>(*m_ref).rref();
  238. }
  239. void mov(OpaqueRef &v)
  240. {
  241. m_ref->mov(*v.m_ref);
  242. }
  243. cv::GOpaqueDesc descr_of() const
  244. {
  245. return m_ref->m_desc;
  246. }
  247. // May be used to uniquely identify this object internally
  248. const void *ptr() const { return m_ref->ptr(); }
  249. // Introduced for in-graph meta handling
  250. OpaqueRef& operator= (const cv::util::any &a)
  251. {
  252. m_ref->set(a);
  253. return *this;
  254. }
  255. };
  256. } // namespace detail
  257. /** \addtogroup gapi_data_objects
  258. * @{
  259. */
  260. /**
  261. * @brief `cv::GOpaque<T>` template class represents an object of
  262. * class `T` in the graph.
  263. *
  264. * `cv::GOpaque<T>` describes a functional relationship between operations
  265. * consuming and producing object of class `T`. `cv::GOpaque<T>` is
  266. * designed to extend G-API with user-defined data types, which are
  267. * often required with user-defined operations. G-API can't apply any
  268. * optimizations to user-defined types since these types are opaque to
  269. * the framework. However, there is a number of G-API operations
  270. * declared with `cv::GOpaque<T>` as a return type,
  271. * e.g. cv::gapi::streaming::timestamp() or cv::gapi::streaming::size().
  272. *
  273. * @sa `cv::GArray<T>`
  274. */
  275. template<typename T> class GOpaque
  276. {
  277. public:
  278. // Host type (or Flat type) - the type this GOpaque is actually
  279. // specified to.
  280. /// @private
  281. using HT = typename detail::flatten_g<util::decay_t<T>>::type;
  282. /**
  283. * @brief Constructs an empty `cv::GOpaque<T>`
  284. *
  285. * Normally, empty G-API data objects denote a starting point of
  286. * the graph. When an empty `cv::GOpaque<T>` is assigned to a result
  287. * of some operation, it obtains a functional link to this
  288. * operation (and is not empty anymore).
  289. */
  290. GOpaque() { putDetails(); } // Empty constructor
  291. /// @private
  292. explicit GOpaque(detail::GOpaqueU &&ref) // GOpaqueU-based constructor
  293. : m_ref(ref) { putDetails(); } // (used by GCall, not for users)
  294. /// @private
  295. detail::GOpaqueU strip() const {
  296. return m_ref;
  297. }
  298. /// @private
  299. static void Ctor(detail::OpaqueRef& ref) {
  300. ref.reset<HT>();
  301. }
  302. private:
  303. void putDetails() {
  304. m_ref.setConstructFcn(&Ctor);
  305. m_ref.specifyType<HT>();
  306. m_ref.storeKind<HT>();
  307. }
  308. detail::GOpaqueU m_ref;
  309. };
  310. /** @} */
  311. } // namespace cv
  312. #endif // OPENCV_GAPI_GOPAQUE_HPP