1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2018 Intel Corporation
#ifndef OPENCV_GAPI_GARRAY_HPP
#define OPENCV_GAPI_GARRAY_HPP
#include <functional>
#include <ostream>
#include <vector>
#include <memory>
#include <opencv2/gapi/own/exports.hpp>
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/util/variant.hpp>
#include <opencv2/gapi/util/throw.hpp>
#include <opencv2/gapi/own/assert.hpp>
namespace cv
{
// Forward declaration; GNode and GOrigin are an internal
// (user-inaccessible) classes.
class GNode;
struct GOrigin;
template<typename T> class GArray;
/**
* \addtogroup gapi_meta_args
* @{
*/
struct GArrayDesc
{
// FIXME: Body
// FIXME: Also implement proper operator== then
bool operator== (const GArrayDesc&) const { return true; }
};
template<typename U> GArrayDesc descr_of(const std::vector<U> &) { return {};}
static inline GArrayDesc empty_array_desc() {return {}; }
/** @} */
std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &desc);
namespace detail
{
// ConstructVec is a callback which stores information about T and is used by
// G-API runtime to construct arrays in host memory (T remains opaque for G-API).
// ConstructVec is carried into G-API internals by GArrayU.
// Currently it is suitable for Host (CPU) plugins only, real offload may require
// more information for manual memory allocation on-device.
class VectorRef;
using ConstructVec = std::function<void(VectorRef&)>;
// This is the base struct for GArrayU type holder
struct TypeHintBase{virtual ~TypeHintBase() = default;};
// This class holds type of initial GArray to be checked from GArrayU
template <typename T>
struct TypeHint final : public TypeHintBase{};
// This class strips type information from GArray<T> and makes it usable
// in the G-API graph compiler (expression unrolling, graph generation, etc).
// Part of GProtoArg.
class GAPI_EXPORTS GArrayU
{
public:
GArrayU(const GNode &n, std::size_t out); // Operation result constructor
template <typename T>
bool holds() const; // Check if was created from GArray<T>
GOrigin& priv(); // Internal use only
const GOrigin& priv() const; // Internal use only
protected:
GArrayU(); // Default constructor
template<class> friend class cv::GArray; // (avialable to GArray<T> only)
void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor
template <typename T>
void specifyType(); // Store type of initial GArray<T>
std::shared_ptr<GOrigin> m_priv;
std::shared_ptr<TypeHintBase> m_hint;
};
template <typename T>
bool GArrayU::holds() const{
GAPI_Assert(m_hint != nullptr);
using U = typename std::decay<T>::type;
return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
};
template <typename T>
void GArrayU::specifyType(){
m_hint.reset(new TypeHint<typename std::decay<T>::type>);
};
// This class represents a typed STL vector reference.
// Depending on origins, this reference may be either "just a" reference to
// an object created externally, OR actually own the underlying object
// (be value holder).
class BasicVectorRef
{
public:
std::size_t m_elemSize = 0ul;
cv::GArrayDesc m_desc;
virtual ~BasicVectorRef() {}
};
template<typename T> class VectorRefT: public BasicVectorRef
{
using empty_t = util::monostate;
using ro_ext_t = const std::vector<T> *;
using rw_ext_t = std::vector<T> *;
using rw_own_t = std::vector<T> ;
util::variant<empty_t, ro_ext_t, rw_ext_t, rw_own_t> m_ref;
inline bool isEmpty() const { return util::holds_alternative<empty_t>(m_ref); }
inline bool isROExt() const { return util::holds_alternative<ro_ext_t>(m_ref); }
inline bool isRWExt() const { return util::holds_alternative<rw_ext_t>(m_ref); }
inline bool isRWOwn() const { return util::holds_alternative<rw_own_t>(m_ref); }
void init(const std::vector<T>* vec = nullptr)
{
m_elemSize = sizeof(T);
if (vec) m_desc = cv::descr_of(*vec);
}
public:
VectorRefT() { init(); }
virtual ~VectorRefT() {}
explicit VectorRefT(const std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
explicit VectorRefT(std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
explicit VectorRefT(std::vector<T>&& vec) : m_ref(std::move(vec)) { init(&vec); }
// Reset a VectorRefT. Called only for objects instantiated
// internally in G-API (e.g. temporary GArray<T>'s within a
// computation). Reset here means both initialization
// (creating an object) and reset (discarding its existing
// content before the next execution). Must never be called
// for external VectorRefTs.
void reset()
{
if (isEmpty())
{
std::vector<T> empty_vector;
m_desc = cv::descr_of(empty_vector);
m_ref = std::move(empty_vector);
GAPI_Assert(isRWOwn());
}
else if (isRWOwn())
{
util::get<rw_own_t>(m_ref).clear();
}
else GAPI_Assert(false); // shouldn't be called in *EXT modes
}
// Obtain a WRITE reference to underlying object
// Used by CPU kernel API wrappers when a kernel execution frame
// is created
std::vector<T>& wref()
{
GAPI_Assert(isRWExt() || isRWOwn());
if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
if (isRWOwn()) return util::get<rw_own_t>(m_ref);
util::throw_error(std::logic_error("Impossible happened"));
}
// Obtain a READ reference to underlying object
// Used by CPU kernel API wrappers when a kernel execution frame
// is created
const std::vector<T>& rref() const
{
// ANY vector can be accessed for reading, even if it declared for
// output. Example -- a GComputation from [in] to [out1,out2]
// where [out2] is a result of operation applied to [out1]:
//
// GComputation boundary
// . . . . . . .
// . .
// [in] ----> foo() ----> [out1]
// . . :
// . . . .:. . .
// . V .
// . bar() ---> [out2]
// . . . . . . . . . . . .
//
if (isROExt()) return *util::get<ro_ext_t>(m_ref);
if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
if (isRWOwn()) return util::get<rw_own_t>(m_ref);
util::throw_error(std::logic_error("Impossible happened"));
}
};
// This class strips type information from VectorRefT<> and makes it usable
// in the G-API executables (carrying run-time data/information to kernels).
// Part of GRunArg.
// Its methods are typed proxies to VectorRefT<T>.
// VectorRef maintains "reference" semantics so two copies of VectoRef refer
// to the same underlying object.
// FIXME: Put a good explanation on why cv::OutputArray doesn't fit this role
class VectorRef
{
std::shared_ptr<BasicVectorRef> m_ref;
template<typename T> inline void check() const
{
GAPI_DbgAssert(dynamic_cast<VectorRefT<T>*>(m_ref.get()) != nullptr);
GAPI_Assert(sizeof(T) == m_ref->m_elemSize);
}
public:
VectorRef() = default;
template<typename T> explicit VectorRef(const std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
template<typename T> explicit VectorRef(std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
template<typename T> explicit VectorRef(std::vector<T>&& vec) : m_ref(new VectorRefT<T>(vec)) {}
template<typename T> void reset()
{
if (!m_ref) m_ref.reset(new VectorRefT<T>());
check<T>();
static_cast<VectorRefT<T>&>(*m_ref).reset();
}
template<typename T> std::vector<T>& wref()
{
check<T>();
return static_cast<VectorRefT<T>&>(*m_ref).wref();
}
template<typename T> const std::vector<T>& rref() const
{
check<T>();
return static_cast<VectorRefT<T>&>(*m_ref).rref();
}
cv::GArrayDesc descr_of() const
{
return m_ref->m_desc;
}
};
} // namespace detail
/** \addtogroup gapi_data_objects
* @{
*/
template<typename T> class GArray
{
public:
GArray() { putDetails(); } // Empty constructor
explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
detail::GArrayU strip() const { return m_ref; }
private:
static void VCTor(detail::VectorRef& vref) { vref.reset<T>(); }
void putDetails() {
m_ref.setConstructFcn(&VCTor);
m_ref.specifyType<T>();
}
detail::GArrayU m_ref;
};
/** @} */
} // namespace cv
#endif // OPENCV_GAPI_GARRAY_HPP