Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/gapi/src/compiler/gmodel.cpp
16337 views
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
7
8
#include "precomp.hpp"
9
10
#include <string>
11
#include <sstream> // used in GModel::log
12
13
14
#include <ade/util/zip_range.hpp> // util::indexed
15
#include <ade/util/checked_cast.hpp>
16
17
#include "opencv2/gapi/gproto.hpp"
18
#include "api/gnode_priv.hpp"
19
#include "compiler/gobjref.hpp"
20
#include "compiler/gmodel.hpp"
21
22
namespace cv { namespace gimpl {
23
24
ade::NodeHandle GModel::mkOpNode(GModel::Graph &g, const GKernel &k, const std::vector<GArg> &args, const std::string &island)
25
{
26
ade::NodeHandle op_h = g.createNode();
27
g.metadata(op_h).set(NodeType{NodeType::OP});
28
//These extra empty {} are to please GCC (-Wmissing-field-initializers)
29
g.metadata(op_h).set(Op{k, args, {}, {}, {}});
30
if (!island.empty())
31
g.metadata(op_h).set(Island{island});
32
return op_h;
33
}
34
35
ade::NodeHandle GModel::mkDataNode(GModel::Graph &g, const GOrigin& origin)
36
{
37
ade::NodeHandle op_h = g.createNode();
38
const auto id = g.metadata().get<DataObjectCounter>().GetNewId(origin.shape);
39
g.metadata(op_h).set(NodeType{NodeType::DATA});
40
41
GMetaArg meta;
42
Data::Storage storage = Data::Storage::INTERNAL; // By default, all objects are marked INTERNAL
43
44
if (origin.node.shape() == GNode::NodeShape::CONST_BOUNDED)
45
{
46
auto value = value_of(origin);
47
meta = descr_of(value);
48
storage = Data::Storage::CONST;
49
g.metadata(op_h).set(ConstValue{value});
50
}
51
g.metadata(op_h).set(Data{origin.shape, id, meta, origin.ctor, storage});
52
return op_h;
53
}
54
55
void GModel::linkIn(Graph &g, ade::NodeHandle opH, ade::NodeHandle objH, std::size_t in_port)
56
{
57
// Check if input is already connected
58
for (const auto& in_e : opH->inEdges())
59
{
60
GAPI_Assert(g.metadata(in_e).get<Input>().port != in_port);
61
}
62
63
auto &op = g.metadata(opH).get<Op>();
64
auto &gm = g.metadata(objH).get<Data>();
65
66
// FIXME: check validity using kernel prototype
67
GAPI_Assert(in_port < op.args.size());
68
69
ade::EdgeHandle eh = g.link(objH, opH);
70
g.metadata(eh).set(Input{in_port});
71
72
// Replace an API object with a REF (G* -> GOBJREF)
73
op.args[in_port] = cv::GArg(RcDesc{gm.rc, gm.shape, {}});
74
}
75
76
void GModel::linkOut(Graph &g, ade::NodeHandle opH, ade::NodeHandle objH, std::size_t out_port)
77
{
78
// FIXME: check validity using kernel prototype
79
80
// Check if output is already connected
81
for (const auto& out_e : opH->outEdges())
82
{
83
GAPI_Assert(g.metadata(out_e).get<Output>().port != out_port);
84
}
85
86
auto &op = g.metadata(opH).get<Op>();
87
auto &gm = g.metadata(objH).get<Data>();
88
89
GAPI_Assert(objH->inNodes().size() == 0u);
90
91
ade::EdgeHandle eh = g.link(opH, objH);
92
g.metadata(eh).set(Output{out_port});
93
94
// TODO: outs must be allocated according to kernel protocol!
95
const auto storage_with_port = ade::util::checked_cast<std::size_t>(out_port+1);
96
const auto min_out_size = std::max(op.outs.size(), storage_with_port);
97
op.outs.resize(min_out_size, RcDesc{-1,GShape::GMAT,{}}); // FIXME: Invalid shape instead?
98
op.outs[out_port] = RcDesc{gm.rc, gm.shape, {}};
99
}
100
101
std::vector<ade::NodeHandle> GModel::orderedInputs(Graph &g, ade::NodeHandle nh)
102
{
103
std::vector<ade::NodeHandle> sorted_in_nhs(nh->inEdges().size());
104
for (const auto& in_eh : nh->inEdges())
105
{
106
const auto port = g.metadata(in_eh).get<cv::gimpl::Input>().port;
107
GAPI_Assert(port < sorted_in_nhs.size());
108
sorted_in_nhs[port] = in_eh->srcNode();
109
}
110
return sorted_in_nhs;
111
}
112
113
std::vector<ade::NodeHandle> GModel::orderedOutputs(Graph &g, ade::NodeHandle nh)
114
{
115
std::vector<ade::NodeHandle> sorted_out_nhs(nh->outEdges().size());
116
for (const auto& out_eh : nh->outEdges())
117
{
118
const auto port = g.metadata(out_eh).get<cv::gimpl::Output>().port;
119
GAPI_Assert(port < sorted_out_nhs.size());
120
sorted_out_nhs[port] = out_eh->dstNode();
121
}
122
return sorted_out_nhs;
123
}
124
125
void GModel::init(Graph& g)
126
{
127
g.metadata().set(DataObjectCounter());
128
}
129
130
void GModel::log(Graph &g, ade::NodeHandle nh, std::string &&msg, ade::NodeHandle updater)
131
{
132
std::string s = std::move(msg);
133
if (updater != nullptr)
134
{
135
std::stringstream fmt;
136
fmt << " (via " << updater << ")";
137
s += fmt.str();
138
}
139
140
if (g.metadata(nh).contains<Journal>())
141
{
142
g.metadata(nh).get<Journal>().messages.push_back(s);
143
}
144
else
145
{
146
g.metadata(nh).set(Journal{{s}});
147
}
148
}
149
150
// FIXME:
151
// Unify with GModel::log(.. ade::NodeHandle ..)
152
void GModel::log(Graph &g, ade::EdgeHandle eh, std::string &&msg, ade::NodeHandle updater)
153
{
154
std::string s = std::move(msg);
155
if (updater != nullptr)
156
{
157
std::stringstream fmt;
158
fmt << " (via " << updater << ")";
159
s += fmt.str();
160
}
161
162
if (g.metadata(eh).contains<Journal>())
163
{
164
g.metadata(eh).get<Journal>().messages.push_back(s);
165
}
166
else
167
{
168
g.metadata(eh).set(Journal{{s}});
169
}
170
}
171
172
ade::NodeHandle GModel::detail::dataNodeOf(const ConstGraph &g, const GOrigin &origin)
173
{
174
// FIXME: Does it still work with graph transformations, e.g. redirectWriter()??
175
return g.metadata().get<Layout>().object_nodes.at(origin);
176
}
177
178
void GModel::redirectReaders(Graph &g, ade::NodeHandle from, ade::NodeHandle to)
179
{
180
std::vector<ade::EdgeHandle> ehh(from->outEdges().begin(), from->outEdges().end());
181
for (auto e : ehh)
182
{
183
auto dst = e->dstNode();
184
auto input = g.metadata(e).get<Input>();
185
g.erase(e);
186
linkIn(g, dst, to, input.port);
187
}
188
}
189
190
void GModel::redirectWriter(Graph &g, ade::NodeHandle from, ade::NodeHandle to)
191
{
192
GAPI_Assert(from->inEdges().size() == 1);
193
auto e = from->inEdges().front();
194
auto op = e->srcNode();
195
auto output = g.metadata(e).get<Output>();
196
g.erase(e);
197
linkOut(g, op, to, output.port);
198
}
199
200
GMetaArgs GModel::collectInputMeta(GModel::ConstGraph cg, ade::NodeHandle node)
201
{
202
GAPI_Assert(cg.metadata(node).get<NodeType>().t == NodeType::OP);
203
GMetaArgs in_meta_args(cg.metadata(node).get<Op>().args.size());
204
205
for (const auto &e : node->inEdges())
206
{
207
const auto& in_data = cg.metadata(e->srcNode()).get<Data>();
208
in_meta_args[cg.metadata(e).get<Input>().port] = in_data.meta;
209
}
210
211
return in_meta_args;
212
}
213
214
215
ade::EdgeHandle GModel::getInEdgeByPort(const GModel::ConstGraph& cg,
216
const ade::NodeHandle& nh,
217
std::size_t in_port)
218
{
219
auto inEdges = nh->inEdges();
220
const auto& edge = ade::util::find_if(inEdges, [&](ade::EdgeHandle eh) {
221
return cg.metadata(eh).get<Input>().port == in_port;
222
});
223
GAPI_Assert(edge != inEdges.end());
224
return *edge;
225
}
226
227
GMetaArgs GModel::collectOutputMeta(GModel::ConstGraph cg, ade::NodeHandle node)
228
{
229
GAPI_Assert(cg.metadata(node).get<NodeType>().t == NodeType::OP);
230
GMetaArgs out_meta_args(cg.metadata(node).get<Op>().outs.size());
231
232
for (const auto &e : node->outEdges())
233
{
234
const auto& out_data = cg.metadata(e->dstNode()).get<Data>();
235
out_meta_args[cg.metadata(e).get<Output>().port] = out_data.meta;
236
}
237
238
return out_meta_args;
239
}
240
241
bool GModel::isActive(const GModel::Graph &cg, const cv::gapi::GBackend &backend)
242
{
243
return ade::util::contains(cg.metadata().get<ActiveBackends>().backends,
244
backend);
245
}
246
247
}} // cv::gimpl
248
249