// 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 #include "precomp.hpp" #include // unique_ptr #include // multiplies #include #include #include "api/gbackend_priv.hpp" #include "backends/common/gbackend.hpp" #include "compiler/gobjref.hpp" #include "compiler/gislandmodel.hpp" // GBackend private implementation ///////////////////////////////////////////// void cv::gapi::GBackend::Priv::unpackKernel(ade::Graph & /*graph */ , const ade::NodeHandle & /*op_node*/ , const GKernelImpl & /*impl */ ) { // Default implementation is still there as Priv // is instantiated by some tests. // Priv is even instantiated as a mock object in a number of tests // as a backend and this method is called for mock objects (doing nothing). // FIXME: add a warning message here // FIXME: Do something with this! Ideally this function should be "=0"; } std::unique_ptr cv::gapi::GBackend::Priv::compile(const ade::Graph&, const GCompileArgs&, const std::vector &) const { // ...and this method is here for the same reason! GAPI_Assert(false); return {}; } std::unique_ptr cv::gapi::GBackend::Priv::compile(const ade::Graph& graph, const GCompileArgs& args, const std::vector& nodes, const std::vector&, const std::vector&) const { return compile(graph, args, nodes); } void cv::gapi::GBackend::Priv::addBackendPasses(ade::ExecutionEngineSetupContext &) { // Do nothing by default, plugins may override this to // add custom (backend-specific) graph transformations } void cv::gapi::GBackend::Priv::addMetaSensitiveBackendPasses(ade::ExecutionEngineSetupContext &) { // Do nothing by default, plugins may override this to // add custom (backend-specific) graph transformations // which are sensitive to metadata } cv::gapi::GKernelPackage cv::gapi::GBackend::Priv::auxiliaryKernels() const { return {}; } // GBackend public implementation ////////////////////////////////////////////// cv::gapi::GBackend::GBackend() { } cv::gapi::GBackend::GBackend(std::shared_ptr &&p) : m_priv(std::move(p)) { } cv::gapi::GBackend::Priv& cv::gapi::GBackend::priv() { return *m_priv; } const cv::gapi::GBackend::Priv& cv::gapi::GBackend::priv() const { return *m_priv; } std::size_t cv::gapi::GBackend::hash() const { return std::hash{}(m_priv.get()); } bool cv::gapi::GBackend::operator== (const cv::gapi::GBackend &rhs) const { return m_priv == rhs.m_priv; } // Abstract Host-side data manipulation //////////////////////////////////////// // Reused between CPU backend and more generic GExecutor namespace cv { namespace gimpl { namespace magazine { // FIXME implement the below functions with visit()? void bindInArg(Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat) { switch (rc.shape) { case GShape::GMAT: { switch (arg.index()) { case GRunArg::index_of() : if (is_umat) { #if !defined(GAPI_STANDALONE) auto& mag_umat = mag.template slot()[rc.id]; mag_umat = to_ocv(util::get(arg)).getUMat(ACCESS_READ); #else util::throw_error(std::logic_error("UMat is not supported in standalone build")); #endif // !defined(GAPI_STANDALONE) } else { auto& mag_mat = mag.template slot()[rc.id]; mag_mat = util::get(arg); } break; #if !defined(GAPI_STANDALONE) case GRunArg::index_of() : if (is_umat) { auto& mag_umat = mag.template slot()[rc.id]; mag_umat = util::get(arg).getUMat(ACCESS_READ); } else { auto& mag_mat = mag.template slot()[rc.id]; mag_mat = to_own(util::get(arg)); } break; #endif // !defined(GAPI_STANDALONE) default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?")); } break; } case GShape::GSCALAR: { auto& mag_scalar = mag.template slot()[rc.id]; switch (arg.index()) { case GRunArg::index_of() : mag_scalar = util::get(arg); break; #if !defined(GAPI_STANDALONE) case GRunArg::index_of() : mag_scalar = to_own(util::get(arg)); break; #endif // !defined(GAPI_STANDALONE) default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?")); } break; } case GShape::GARRAY: mag.template slot()[rc.id] = util::get(arg); break; case GShape::GOPAQUE: mag.template slot()[rc.id] = util::get(arg); break; default: util::throw_error(std::logic_error("Unsupported GShape type")); } } void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat) { switch (rc.shape) { case GShape::GMAT: { switch (arg.index()) { case GRunArgP::index_of() : if (is_umat) { #if !defined(GAPI_STANDALONE) auto& mag_umat = mag.template slot()[rc.id]; mag_umat = to_ocv(*(util::get(arg))).getUMat(ACCESS_RW); #else util::throw_error(std::logic_error("UMat is not supported in standalone build")); #endif // !defined(GAPI_STANDALONE) } else { auto& mag_mat = mag.template slot()[rc.id]; mag_mat = *util::get(arg); } break; #if !defined(GAPI_STANDALONE) case GRunArgP::index_of() : if (is_umat) { auto& mag_umat = mag.template slot()[rc.id]; mag_umat = util::get(arg)->getUMat(ACCESS_RW); } else { auto& mag_mat = mag.template slot()[rc.id]; mag_mat = to_own(*util::get(arg)); } break; #endif // !defined(GAPI_STANDALONE) default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?")); } break; } case GShape::GSCALAR: { auto& mag_scalar = mag.template slot()[rc.id]; switch (arg.index()) { case GRunArgP::index_of() : mag_scalar = *util::get(arg); break; #if !defined(GAPI_STANDALONE) case GRunArgP::index_of() : mag_scalar = to_own(*util::get(arg)); break; #endif // !defined(GAPI_STANDALONE) default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?")); } break; } case GShape::GARRAY: mag.template slot()[rc.id] = util::get(arg); break; case GShape::GOPAQUE: mag.template slot()[rc.id] = util::get(arg); break; default: util::throw_error(std::logic_error("Unsupported GShape type")); break; } } void resetInternalData(Mag& mag, const Data &d) { if (d.storage != Data::Storage::INTERNAL) return; switch (d.shape) { case GShape::GARRAY: util::get(d.ctor) (mag.template slot()[d.rc]); break; case GShape::GOPAQUE: util::get(d.ctor) (mag.template slot()[d.rc]); break; case GShape::GSCALAR: mag.template slot()[d.rc] = cv::gapi::own::Scalar(); break; case GShape::GMAT: // Do nothing here - FIXME unify with initInternalData? break; default: util::throw_error(std::logic_error("Unsupported GShape type")); break; } } cv::GRunArg getArg(const Mag& mag, const RcDesc &ref) { // Wrap associated CPU object (either host or an internal one) switch (ref.shape) { case GShape::GMAT: return GRunArg(mag.template slot().at(ref.id)); case GShape::GSCALAR: return GRunArg(mag.template slot().at(ref.id)); // Note: .at() is intentional for GArray and GOpaque as objects MUST be already there // (and constructed by either bindIn/Out or resetInternal) case GShape::GARRAY: return GRunArg(mag.template slot().at(ref.id)); case GShape::GOPAQUE: return GRunArg(mag.template slot().at(ref.id)); default: util::throw_error(std::logic_error("Unsupported GShape type")); break; } } cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat) { switch (rc.shape) { case GShape::GMAT: if (is_umat) { #if !defined(GAPI_STANDALONE) return GRunArgP(&mag.template slot()[rc.id]); #else util::throw_error(std::logic_error("UMat is not supported in standalone build")); #endif // !defined(GAPI_STANDALONE) } else return GRunArgP(&mag.template slot()[rc.id]); case GShape::GSCALAR: return GRunArgP(&mag.template slot()[rc.id]); // Note: .at() is intentional for GArray and GOpaque as objects MUST be already there // (and constructor by either bindIn/Out or resetInternal) case GShape::GARRAY: // FIXME(DM): For some absolutely unknown to me reason, move // semantics is involved here without const_cast to const (and // value from map is moved into return value GRunArgP, leaving // map with broken value I've spent few late Friday hours // debugging this!!!1 return GRunArgP(const_cast(mag) .template slot().at(rc.id)); case GShape::GOPAQUE: // FIXME(DM): For some absolutely unknown to me reason, move // semantics is involved here without const_cast to const (and // value from map is moved into return value GRunArgP, leaving // map with broken value I've spent few late Friday hours // debugging this!!!1 return GRunArgP(const_cast(mag) .template slot().at(rc.id)); default: util::throw_error(std::logic_error("Unsupported GShape type")); break; } } void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat) { switch (rc.shape) { case GShape::GARRAY: // Do nothing - should we really do anything here? break; case GShape::GOPAQUE: // Do nothing - should we really do anything here? break; case GShape::GMAT: { //simply check that memory was not reallocated, i.e. //both instances of Mat pointing to the same memory uchar* out_arg_data = nullptr; switch (g_arg.index()) { case GRunArgP::index_of() : out_arg_data = util::get(g_arg)->data; break; #if !defined(GAPI_STANDALONE) case GRunArgP::index_of() : out_arg_data = util::get(g_arg)->data; break; case GRunArgP::index_of() : out_arg_data = (util::get(g_arg))->getMat(ACCESS_RW).data; break; #endif // !defined(GAPI_STANDALONE) default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?")); } if (is_umat) { #if !defined(GAPI_STANDALONE) auto& in_mag = mag.template slot().at(rc.id); GAPI_Assert((out_arg_data == (in_mag.getMat(ACCESS_RW).data)) && " data for output parameters was reallocated ?"); #else util::throw_error(std::logic_error("UMat is not supported in standalone build")); #endif // !defined(GAPI_STANDALONE) } else { auto& in_mag = mag.template slot().at(rc.id); GAPI_Assert((out_arg_data == in_mag.data) && " data for output parameters was reallocated ?"); } break; } case GShape::GSCALAR: { switch (g_arg.index()) { case GRunArgP::index_of() : *util::get(g_arg) = mag.template slot().at(rc.id); break; #if !defined(GAPI_STANDALONE) case GRunArgP::index_of() : *util::get(g_arg) = cv::gapi::own::to_ocv(mag.template slot().at(rc.id)); break; #endif // !defined(GAPI_STANDALONE) default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?")); } break; } default: util::throw_error(std::logic_error("Unsupported GShape type")); break; } } } // namespace magazine void createMat(const cv::GMatDesc &desc, cv::gapi::own::Mat& mat) { // FIXME: Refactor (probably start supporting N-Dimensional blobs natively if (desc.dims.empty()) { const auto type = desc.planar ? desc.depth : CV_MAKETYPE(desc.depth, desc.chan); const auto size = desc.planar ? cv::gapi::own::Size{desc.size.width, desc.size.height*desc.chan} : desc.size; mat.create(size, type); } else { GAPI_Assert(!desc.planar); mat.create(desc.dims, desc.depth); } } #if !defined(GAPI_STANDALONE) void createMat(const cv::GMatDesc &desc, cv::Mat& mat) { // FIXME: Refactor (probably start supporting N-Dimensional blobs natively if (desc.dims.empty()) { const auto type = desc.planar ? desc.depth : CV_MAKETYPE(desc.depth, desc.chan); const auto size = desc.planar ? cv::Size{desc.size.width, desc.size.height*desc.chan} : cv::gapi::own::to_ocv(desc.size); mat.create(size, type); } else { GAPI_Assert(!desc.planar); mat.create(desc.dims, desc.depth); } } #endif } // namespace gimpl } // namespace cv