Path: blob/master/modules/gapi/src/compiler/gmodel.cpp
16337 views
// This file is part of OpenCV project.1// It is subject to the license terms in the LICENSE file found in the top-level directory2// of this distribution and at http://opencv.org/license.html.3//4// Copyright (C) 2018 Intel Corporation567#include "precomp.hpp"89#include <string>10#include <sstream> // used in GModel::log111213#include <ade/util/zip_range.hpp> // util::indexed14#include <ade/util/checked_cast.hpp>1516#include "opencv2/gapi/gproto.hpp"17#include "api/gnode_priv.hpp"18#include "compiler/gobjref.hpp"19#include "compiler/gmodel.hpp"2021namespace cv { namespace gimpl {2223ade::NodeHandle GModel::mkOpNode(GModel::Graph &g, const GKernel &k, const std::vector<GArg> &args, const std::string &island)24{25ade::NodeHandle op_h = g.createNode();26g.metadata(op_h).set(NodeType{NodeType::OP});27//These extra empty {} are to please GCC (-Wmissing-field-initializers)28g.metadata(op_h).set(Op{k, args, {}, {}, {}});29if (!island.empty())30g.metadata(op_h).set(Island{island});31return op_h;32}3334ade::NodeHandle GModel::mkDataNode(GModel::Graph &g, const GOrigin& origin)35{36ade::NodeHandle op_h = g.createNode();37const auto id = g.metadata().get<DataObjectCounter>().GetNewId(origin.shape);38g.metadata(op_h).set(NodeType{NodeType::DATA});3940GMetaArg meta;41Data::Storage storage = Data::Storage::INTERNAL; // By default, all objects are marked INTERNAL4243if (origin.node.shape() == GNode::NodeShape::CONST_BOUNDED)44{45auto value = value_of(origin);46meta = descr_of(value);47storage = Data::Storage::CONST;48g.metadata(op_h).set(ConstValue{value});49}50g.metadata(op_h).set(Data{origin.shape, id, meta, origin.ctor, storage});51return op_h;52}5354void GModel::linkIn(Graph &g, ade::NodeHandle opH, ade::NodeHandle objH, std::size_t in_port)55{56// Check if input is already connected57for (const auto& in_e : opH->inEdges())58{59GAPI_Assert(g.metadata(in_e).get<Input>().port != in_port);60}6162auto &op = g.metadata(opH).get<Op>();63auto &gm = g.metadata(objH).get<Data>();6465// FIXME: check validity using kernel prototype66GAPI_Assert(in_port < op.args.size());6768ade::EdgeHandle eh = g.link(objH, opH);69g.metadata(eh).set(Input{in_port});7071// Replace an API object with a REF (G* -> GOBJREF)72op.args[in_port] = cv::GArg(RcDesc{gm.rc, gm.shape, {}});73}7475void GModel::linkOut(Graph &g, ade::NodeHandle opH, ade::NodeHandle objH, std::size_t out_port)76{77// FIXME: check validity using kernel prototype7879// Check if output is already connected80for (const auto& out_e : opH->outEdges())81{82GAPI_Assert(g.metadata(out_e).get<Output>().port != out_port);83}8485auto &op = g.metadata(opH).get<Op>();86auto &gm = g.metadata(objH).get<Data>();8788GAPI_Assert(objH->inNodes().size() == 0u);8990ade::EdgeHandle eh = g.link(opH, objH);91g.metadata(eh).set(Output{out_port});9293// TODO: outs must be allocated according to kernel protocol!94const auto storage_with_port = ade::util::checked_cast<std::size_t>(out_port+1);95const auto min_out_size = std::max(op.outs.size(), storage_with_port);96op.outs.resize(min_out_size, RcDesc{-1,GShape::GMAT,{}}); // FIXME: Invalid shape instead?97op.outs[out_port] = RcDesc{gm.rc, gm.shape, {}};98}99100std::vector<ade::NodeHandle> GModel::orderedInputs(Graph &g, ade::NodeHandle nh)101{102std::vector<ade::NodeHandle> sorted_in_nhs(nh->inEdges().size());103for (const auto& in_eh : nh->inEdges())104{105const auto port = g.metadata(in_eh).get<cv::gimpl::Input>().port;106GAPI_Assert(port < sorted_in_nhs.size());107sorted_in_nhs[port] = in_eh->srcNode();108}109return sorted_in_nhs;110}111112std::vector<ade::NodeHandle> GModel::orderedOutputs(Graph &g, ade::NodeHandle nh)113{114std::vector<ade::NodeHandle> sorted_out_nhs(nh->outEdges().size());115for (const auto& out_eh : nh->outEdges())116{117const auto port = g.metadata(out_eh).get<cv::gimpl::Output>().port;118GAPI_Assert(port < sorted_out_nhs.size());119sorted_out_nhs[port] = out_eh->dstNode();120}121return sorted_out_nhs;122}123124void GModel::init(Graph& g)125{126g.metadata().set(DataObjectCounter());127}128129void GModel::log(Graph &g, ade::NodeHandle nh, std::string &&msg, ade::NodeHandle updater)130{131std::string s = std::move(msg);132if (updater != nullptr)133{134std::stringstream fmt;135fmt << " (via " << updater << ")";136s += fmt.str();137}138139if (g.metadata(nh).contains<Journal>())140{141g.metadata(nh).get<Journal>().messages.push_back(s);142}143else144{145g.metadata(nh).set(Journal{{s}});146}147}148149// FIXME:150// Unify with GModel::log(.. ade::NodeHandle ..)151void GModel::log(Graph &g, ade::EdgeHandle eh, std::string &&msg, ade::NodeHandle updater)152{153std::string s = std::move(msg);154if (updater != nullptr)155{156std::stringstream fmt;157fmt << " (via " << updater << ")";158s += fmt.str();159}160161if (g.metadata(eh).contains<Journal>())162{163g.metadata(eh).get<Journal>().messages.push_back(s);164}165else166{167g.metadata(eh).set(Journal{{s}});168}169}170171ade::NodeHandle GModel::detail::dataNodeOf(const ConstGraph &g, const GOrigin &origin)172{173// FIXME: Does it still work with graph transformations, e.g. redirectWriter()??174return g.metadata().get<Layout>().object_nodes.at(origin);175}176177void GModel::redirectReaders(Graph &g, ade::NodeHandle from, ade::NodeHandle to)178{179std::vector<ade::EdgeHandle> ehh(from->outEdges().begin(), from->outEdges().end());180for (auto e : ehh)181{182auto dst = e->dstNode();183auto input = g.metadata(e).get<Input>();184g.erase(e);185linkIn(g, dst, to, input.port);186}187}188189void GModel::redirectWriter(Graph &g, ade::NodeHandle from, ade::NodeHandle to)190{191GAPI_Assert(from->inEdges().size() == 1);192auto e = from->inEdges().front();193auto op = e->srcNode();194auto output = g.metadata(e).get<Output>();195g.erase(e);196linkOut(g, op, to, output.port);197}198199GMetaArgs GModel::collectInputMeta(GModel::ConstGraph cg, ade::NodeHandle node)200{201GAPI_Assert(cg.metadata(node).get<NodeType>().t == NodeType::OP);202GMetaArgs in_meta_args(cg.metadata(node).get<Op>().args.size());203204for (const auto &e : node->inEdges())205{206const auto& in_data = cg.metadata(e->srcNode()).get<Data>();207in_meta_args[cg.metadata(e).get<Input>().port] = in_data.meta;208}209210return in_meta_args;211}212213214ade::EdgeHandle GModel::getInEdgeByPort(const GModel::ConstGraph& cg,215const ade::NodeHandle& nh,216std::size_t in_port)217{218auto inEdges = nh->inEdges();219const auto& edge = ade::util::find_if(inEdges, [&](ade::EdgeHandle eh) {220return cg.metadata(eh).get<Input>().port == in_port;221});222GAPI_Assert(edge != inEdges.end());223return *edge;224}225226GMetaArgs GModel::collectOutputMeta(GModel::ConstGraph cg, ade::NodeHandle node)227{228GAPI_Assert(cg.metadata(node).get<NodeType>().t == NodeType::OP);229GMetaArgs out_meta_args(cg.metadata(node).get<Op>().outs.size());230231for (const auto &e : node->outEdges())232{233const auto& out_data = cg.metadata(e->dstNode()).get<Data>();234out_meta_args[cg.metadata(e).get<Output>().port] = out_data.meta;235}236237return out_meta_args;238}239240bool GModel::isActive(const GModel::Graph &cg, const cv::gapi::GBackend &backend)241{242return ade::util::contains(cg.metadata().get<ActiveBackends>().backends,243backend);244}245246}} // cv::gimpl247248249