Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / fluid / modules / gapi / src / compiler / gmodel.cpp
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-2019 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