From 935c02c0a37518aea49d48db6293c4693daa118f Mon Sep 17 00:00:00 2001 From: atalaman Date: Wed, 22 May 2019 14:53:44 +0300 Subject: [PATCH] Merge pull request #13851 from TolyaTalamanov:at/new-kernel-package-design G-API: Kernel package design (#13851) * Remove cv::unite_policy from API * Add check that all id in kernel package are unique * Refactor checker id procedure * Remove cv::gapi::GLookupOrder from API * Implement cv::gapi::use_only * Fix samples * Fix docs * Fix comments to review * Remove unite_policy * Fix GKernelPackage::backends() * Fix comments to review * Fix all_unique * Fix comments to review * Fix comments to review * Remove out of date tests --- .../porting_anisotropic_segmentation.markdown | 14 +- .../gapi/include/opencv2/gapi/cpu/gcpukernel.hpp | 9 +- modules/gapi/include/opencv2/gapi/gkernel.hpp | 112 ++---- modules/gapi/include/opencv2/gapi/util/util.hpp | 13 + modules/gapi/samples/api_ref_snippets.cpp | 3 +- modules/gapi/src/api/gkernel.cpp | 119 ++----- modules/gapi/src/compiler/gcompiler.cpp | 13 +- modules/gapi/src/compiler/passes/kernels.cpp | 6 +- modules/gapi/src/compiler/passes/passes.hpp | 5 +- .../gapi/test/common/gapi_compoundkernel_tests.cpp | 24 +- modules/gapi/test/gapi_fluid_resize_test.cpp | 7 +- modules/gapi/test/gapi_kernel_tests.cpp | 387 ++++++++++++++++----- .../test/internal/gapi_int_recompilation_test.cpp | 3 +- .../test/internal/gapi_int_resolve_kernel_test.cpp | 119 ------- ...g_anisotropic_image_segmentation_gapi_fluid.cpp | 3 +- 15 files changed, 419 insertions(+), 418 deletions(-) delete mode 100644 modules/gapi/test/internal/gapi_int_resolve_kernel_test.cpp diff --git a/doc/tutorials/gapi/anisotropic_segmentation/porting_anisotropic_segmentation.markdown b/doc/tutorials/gapi/anisotropic_segmentation/porting_anisotropic_segmentation.markdown index cf01903..f84b96e 100644 --- a/doc/tutorials/gapi/anisotropic_segmentation/porting_anisotropic_segmentation.markdown +++ b/doc/tutorials/gapi/anisotropic_segmentation/porting_anisotropic_segmentation.markdown @@ -306,25 +306,17 @@ G-API to utilize appropriate Fluid functions in our graph. Kernel packages are combinable -- in the above example, we take "Core" and "ImgProc" Fluid kernel packages and combine it into a single -one. See documentation reference on cv::gapi::combine and -cv::unite_policy on package combination options. +one. See documentation reference on cv::gapi::combine. If no kernel packages are specified in options, G-API is using _default_ package which consists of default OpenCV implementations and thus G-API graphs are executed via OpenCV functions by default. OpenCV backend provides broader functional coverage than any other backend. If a kernel package is specified, like in this example, then -it is being combined with the _default_ one with -cv::unite_policy::REPLACE. It means that user-specified -implementations will replace default implementations in case of +it is being combined with the _default_. +It means that user-specified implementations will replace default implementations in case of conflict. -Kernel packages may contain a mix of kernels, in particular, multiple -implementations of the same kernel. For example, a single kernel -package may contain both OpenCV and Fluid implementations of kernel -"Filter2D". In this case, the implementation selection preference can -be specified with a special compilation parameter cv::gapi::lookup_order. - diff --git a/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp b/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp index 80392fe..9597942 100644 --- a/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp +++ b/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp @@ -43,13 +43,12 @@ namespace cpu * stack. Every backend is hardware-oriented and thus can run its * kernels efficiently on the target platform. * - * Backends are usually "back boxes" for G-API users -- on the API + * Backends are usually "black boxes" for G-API users -- on the API * side, all backends are represented as different objects of the - * same class cv::gapi::GBackend. User can manipulate with backends - * mainly by specifying which kernels to use or where to look up - * for kernels first. + * same class cv::gapi::GBackend. + * User can manipulate with backends by specifying which kernels to use. * - * @sa @ref gapi_hld, cv::gapi::lookup_order() + * @sa @ref gapi_hld */ /** diff --git a/modules/gapi/include/opencv2/gapi/gkernel.hpp b/modules/gapi/include/opencv2/gapi/gkernel.hpp index af18424..db9ac76 100644 --- a/modules/gapi/include/opencv2/gapi/gkernel.hpp +++ b/modules/gapi/include/opencv2/gapi/gkernel.hpp @@ -14,7 +14,6 @@ #include // false_type, true_type #include // map (for GKernelPackage) #include // tuple -#include // lookup order #include // CompileArgTag #include // Seq @@ -24,7 +23,6 @@ #include // GTypeTraits #include //suppress_unused_warning - namespace cv { using GShapes = std::vector; @@ -57,7 +55,6 @@ namespace detail // namespace { - template struct Yield; template<> struct Yield { @@ -248,13 +245,6 @@ public: namespace cv { -// Declare in cv:: namespace -enum class unite_policy -{ - REPLACE, - KEEP -}; - namespace gapi { // Prework: model "Device" API before it gets to G-API headers. @@ -303,33 +293,6 @@ namespace gapi { * @{ */ - // Lookup order is in fact a vector of Backends to traverse during look-up - /** - * @brief Priority list of backends to use during kernel - * resolution process. - * - * Priority is descending -- the first backend in the list has the - * top priority, and the last one has the lowest priority. - * - * If there's multiple implementations available for a kernel at - * the moment of graph compilation, a kernel (and thus a backend) - * will be selected according to this order (if the parameter is passed). - * - * Default order is not specified (and by default, only - * CPU(OpenCV) backend is involved in graph compilation). - */ - using GLookupOrder = std::vector; - /** - * @brief Create a backend lookup order -- priority list of - * backends to use during graph compilation process. - * - * @sa GLookupOrder, @ref gapi_std_backends - */ - inline GLookupOrder lookup_order(std::initializer_list &&list) - { - return GLookupOrder(std::move(list)); - } - // FIXME: Hide implementation /** * @brief A container class for heterogeneous kernel @@ -353,20 +316,16 @@ namespace gapi { * one since G-API kernel implementations are _types_, not objects. * * Finally, two kernel packages can be combined into a new one - * with function cv::gapi::combine(). There are different rules - * apply to this process, see also cv::gapi::unite_policy for - * details. + * with function cv::gapi::combine(). */ class GAPI_EXPORTS GKernelPackage { - /// @private - using S = std::unordered_map; /// @private - using M = std::unordered_map; + using M = std::unordered_map>; /// @private - M m_backend_kernels; + M m_id_kernels; protected: /// @private @@ -398,10 +357,9 @@ namespace gapi { template bool includes() const { - const auto set_iter = m_backend_kernels.find(KImpl::backend()); - return (set_iter != m_backend_kernels.end()) - ? (set_iter->second.count(KImpl::API::id()) > 0) - : false; + auto kernel_it = m_id_kernels.find(KImpl::API::id()); + return kernel_it != m_id_kernels.end() && + kernel_it->second.first == KImpl::backend(); } /** @@ -439,47 +397,37 @@ namespace gapi { } /** - * @brief Find a kernel (by its API), given the look-up order. + * @brief Find a kernel (by its API) * - * If order is empty, returns first suitable implementation. + * Returns implementation corresponding id. * Throws if nothing found. * * @return Backend which hosts matching kernel implementation. * - * @sa cv::gapi::lookup_order */ template - GBackend lookup(const GLookupOrder &order = {}) const + GBackend lookup() const { - return lookup(KAPI::id(), order).first; + return lookup(KAPI::id()).first; } /// @private std::pair - lookup(const std::string &id, const GLookupOrder &order = {}) const; + lookup(const std::string &id) const; // FIXME: No overwrites allowed? /** * @brief Put a new kernel implementation KImpl into package. - * - * @param up unite policy to use. If the package has already - * implementation for this kernel (probably from another - * backend), and cv::unite_policy::KEEP is passed, the - * existing implementation remains in package; on - * cv::unite_policy::REPLACE all other existing - * implementations are first dropped from the package. */ template - void include(const cv::unite_policy up = cv::unite_policy::KEEP) + void include() { auto backend = KImpl::backend(); auto kernel_id = KImpl::API::id(); auto kernel_impl = GKernelImpl{KImpl::kernel()}; - if (up == cv::unite_policy::REPLACE) removeAPI(kernel_id); - else GAPI_Assert(up == cv::unite_policy::KEEP); + removeAPI(kernel_id); - // Regardless of the policy, store new impl in its storage slot. - m_backend_kernels[backend][kernel_id] = std::move(kernel_impl); + m_id_kernels[kernel_id] = std::make_pair(backend, kernel_impl); } /** @@ -492,23 +440,14 @@ namespace gapi { // TODO: Doxygen bug -- it wants me to place this comment // here, not below. /** - * @brief Create a new package based on `lhs` and `rhs`, - * with unity policy defined by `policy`. + * @brief Create a new package based on `lhs` and `rhs`. * * @param lhs "Left-hand-side" package in the process * @param rhs "Right-hand-side" package in the process - * @param policy Unite policy which is used in case of conflicts - * -- when the same kernel API is implemented in both packages by - * different backends; cv::unite_policy::KEEP keeps both - * implementation in the resulting package, while - * cv::unite_policy::REPLACE gives precedence two kernels from - * "Right-hand-side". - * * @return a new kernel package. */ friend GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &lhs, - const GKernelPackage &rhs, - const cv::unite_policy policy); + const GKernelPackage &rhs); }; /** @@ -540,6 +479,7 @@ namespace gapi { // and parentheses are used to hide function call in the expanded sequence. // Leading 0 helps to handle case when KK is an empty list (kernels<>()). + static_assert(detail::all_unique::value, "Kernels API must be unique"); int unused[] = { 0, (pkg.include(), 0)... }; cv::util::suppress_unused_warning(unused); return pkg; @@ -548,8 +488,17 @@ namespace gapi { /** @} */ GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &lhs, - const GKernelPackage &rhs, - const cv::unite_policy policy); + const GKernelPackage &rhs); + /** + * @brief cv::use_only() is a special combinator which hints G-API to use only + * kernels specified in cv::GComputation::compile() (and not to extend kernels available by + * default with that package). + */ + struct GAPI_EXPORTS use_only + { + GKernelPackage pkg; + }; + } // namespace gapi namespace detail @@ -558,9 +507,10 @@ namespace detail { static const char* tag() { return "gapi.kernel_package"; } }; - template<> struct CompileArgTag + + template<> struct CompileArgTag { - static const char* tag() { return "gapi.lookup_order"; } + static const char* tag() { return "gapi.use_only"; } }; } // namespace detail } // namespace cv diff --git a/modules/gapi/include/opencv2/gapi/util/util.hpp b/modules/gapi/include/opencv2/gapi/util/util.hpp index d0378e0..a62c0c5 100644 --- a/modules/gapi/include/opencv2/gapi/util/util.hpp +++ b/modules/gapi/include/opencv2/gapi/util/util.hpp @@ -84,6 +84,19 @@ namespace detail { static constexpr const std::size_t value = S; }; + + template + struct contains : std::false_type{}; + + template + struct contains : std::integral_constant::value || + contains::value> {}; + template + struct all_unique : std::true_type{}; + + template + struct all_unique : std::integral_constant::value && + all_unique::value> {}; } // namespace detail } // namespace cv diff --git a/modules/gapi/samples/api_ref_snippets.cpp b/modules/gapi/samples/api_ref_snippets.cpp index 5e8859d..2793aee 100644 --- a/modules/gapi/samples/api_ref_snippets.cpp +++ b/modules/gapi/samples/api_ref_snippets.cpp @@ -49,8 +49,7 @@ int main(int argc, char *argv[]) //! [apply_with_param] cv::gapi::GKernelPackage kernels = cv::gapi::combine (cv::gapi::core::fluid::kernels(), - cv::gapi::imgproc::fluid::kernels(), - cv::unite_policy::KEEP); + cv::gapi::imgproc::fluid::kernels()); sobelEdge.apply(input, output, cv::compile_args(kernels)); //! [apply_with_param] diff --git a/modules/gapi/src/api/gkernel.cpp b/modules/gapi/src/api/gkernel.cpp index f8c851a..fb5dd61 100644 --- a/modules/gapi/src/api/gkernel.cpp +++ b/modules/gapi/src/api/gkernel.cpp @@ -20,128 +20,73 @@ // GKernelPackage public implementation //////////////////////////////////////// void cv::gapi::GKernelPackage::remove(const cv::gapi::GBackend& backend) { - m_backend_kernels.erase(backend); + std::vector id_deleted_kernels; + for (const auto& p : m_id_kernels) + { + if (p.second.first == backend) + { + id_deleted_kernels.push_back(p.first); + } + } + + for (const auto& kernel_id : id_deleted_kernels) + { + m_id_kernels.erase(kernel_id); + } } bool cv::gapi::GKernelPackage::includesAPI(const std::string &id) const { - // In current form not very efficient (n * log n) - auto it = std::find_if(m_backend_kernels.begin(), - m_backend_kernels.end(), - [&id](const M::value_type &p) { - return ade::util::contains(p.second, id); - }); - return (it != m_backend_kernels.end()); + return ade::util::contains(m_id_kernels, id); } void cv::gapi::GKernelPackage::removeAPI(const std::string &id) { - for (auto &bk : m_backend_kernels) - bk.second.erase(id); + m_id_kernels.erase(id); } std::size_t cv::gapi::GKernelPackage::size() const { - return std::accumulate(m_backend_kernels.begin(), - m_backend_kernels.end(), - static_cast(0u), - [](std::size_t acc, const M::value_type& v) { - return acc + v.second.size(); - }); + return m_id_kernels.size(); } cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage &lhs, - const GKernelPackage &rhs, - const cv::unite_policy policy) + const GKernelPackage &rhs) { - if (policy == cv::unite_policy::REPLACE) - { - // REPLACE policy: if there is a collision, prefer RHS - // to LHS + // If there is a collision, prefer RHS to LHS // since RHS package has a precedense, start with its copy GKernelPackage result(rhs); // now iterate over LHS package and put kernel if and only // if there's no such one - for (const auto &backend : lhs.m_backend_kernels) + for (const auto& kernel : lhs.m_id_kernels) { - for (const auto &kimpl : backend.second) + if (!result.includesAPI(kernel.first)) { - if (!result.includesAPI(kimpl.first)) - result.m_backend_kernels[backend.first].insert(kimpl); + result.m_id_kernels.emplace(kernel.first, kernel.second); } } return result; - } - else if (policy == cv::unite_policy::KEEP) - { - // KEEP policy: if there is a collision, just keep two versions - // of a kernel - GKernelPackage result(lhs); - for (const auto &p : rhs.m_backend_kernels) - { - result.m_backend_kernels[p.first].insert(p.second.begin(), - p.second.end()); - } - return result; - } - else GAPI_Assert(false); - return GKernelPackage(); } std::pair -cv::gapi::GKernelPackage::lookup(const std::string &id, - const GLookupOrder &order) const +cv::gapi::GKernelPackage::lookup(const std::string &id) const { - if (order.empty()) + auto kernel_it = m_id_kernels.find(id); + if (kernel_it != m_id_kernels.end()) { - // If order is empty, return what comes first - auto it = std::find_if(m_backend_kernels.begin(), - m_backend_kernels.end(), - [&id](const M::value_type &p) { - return ade::util::contains(p.second, id); - }); - if (it != m_backend_kernels.end()) - { - // FIXME: Two lookups! - return std::make_pair(it->first, it->second.find(id)->second); - } + return kernel_it->second; } - else - { - // There is order, so: - // 1. Limit search scope only to specified backends - // FIXME: Currently it is not configurable if search can fall-back - // to other backends (not listed in order) if kernel hasn't been found - // in the look-up list - // 2. Query backends in the specified order - for (const auto &selected_backend : order) - { - const auto kernels_it = m_backend_kernels.find(selected_backend); - if (kernels_it == m_backend_kernels.end()) - { - GAPI_LOG_WARNING(NULL, - "Backend " - << &selected_backend.priv() // FIXME: name instead - << " was listed in lookup list but was not found " - "in the package"); - continue; - } - if (ade::util::contains(kernels_it->second, id)) - { - // FIXME: two lookups! - return std::make_pair(selected_backend, kernels_it->second.find(id)->second); - } - } - } - - // If reached here, kernel was not found among selected backends. + // If reached here, kernel was not found. util::throw_error(std::logic_error("Kernel " + id + " was not found")); } std::vector cv::gapi::GKernelPackage::backends() const { - std::vector result; - for (const auto &p : m_backend_kernels) result.emplace_back(p.first); - return result; + using kernel_type = std::pair>; + std::unordered_set unique_set; + ade::util::transform(m_id_kernels, std::inserter(unique_set, unique_set.end()), + [](const kernel_type& k) { return k.second.first; }); + + return std::vector(unique_set.begin(), unique_set.end()); } diff --git a/modules/gapi/src/compiler/gcompiler.cpp b/modules/gapi/src/compiler/gcompiler.cpp index 83d4da1..6677841 100644 --- a/modules/gapi/src/compiler/gcompiler.cpp +++ b/modules/gapi/src/compiler/gcompiler.cpp @@ -48,16 +48,19 @@ namespace { cv::gapi::GKernelPackage getKernelPackage(cv::GCompileArgs &args) { + auto has_use_only = cv::gimpl::getCompileArg(args); + if (has_use_only) + return has_use_only.value().pkg; + static auto ocv_pkg = #if !defined(GAPI_STANDALONE) combine(cv::gapi::core::cpu::kernels(), - cv::gapi::imgproc::cpu::kernels(), - cv::unite_policy::KEEP); + cv::gapi::imgproc::cpu::kernels()); #else cv::gapi::GKernelPackage(); #endif // !defined(GAPI_STANDALONE) auto user_pkg = cv::gimpl::getCompileArg(args); - return combine(ocv_pkg, user_pkg.value_or(cv::gapi::GKernelPackage{}), cv::unite_policy::REPLACE); + return combine(ocv_pkg, user_pkg.value_or(cv::gapi::GKernelPackage{})); } cv::util::optional getGraphDumpDirectory(cv::GCompileArgs& args) @@ -87,7 +90,6 @@ cv::gimpl::GCompiler::GCompiler(const cv::GComputation &c, { using namespace std::placeholders; m_all_kernels = getKernelPackage(m_args); - auto lookup_order = getCompileArg(m_args).value_or(gapi::GLookupOrder()); auto dump_path = getGraphDumpDirectory(m_args); m_e.addPassStage("init"); @@ -107,8 +109,7 @@ cv::gimpl::GCompiler::GCompiler(const cv::GComputation &c, m_e.addPassStage("kernels"); m_e.addPass("kernels", "resolve_kernels", std::bind(passes::resolveKernels, _1, - std::ref(m_all_kernels), // NB: and not copied here - lookup_order)); + std::ref(m_all_kernels))); // NB: and not copied here m_e.addPass("kernels", "check_islands_content", passes::checkIslandsContent); m_e.addPassStage("meta"); diff --git a/modules/gapi/src/compiler/passes/kernels.cpp b/modules/gapi/src/compiler/passes/kernels.cpp index 0feb7b1..1d9eac6 100644 --- a/modules/gapi/src/compiler/passes/kernels.cpp +++ b/modules/gapi/src/compiler/passes/kernels.cpp @@ -101,8 +101,7 @@ namespace // This pass, given the kernel package, selects a kernel implementation // for every operation in the graph void cv::gimpl::passes::resolveKernels(ade::passes::PassContext &ctx, - const gapi::GKernelPackage &kernels, - const gapi::GLookupOrder &order) + const gapi::GKernelPackage &kernels) { std::unordered_set active_backends; @@ -114,8 +113,7 @@ void cv::gimpl::passes::resolveKernels(ade::passes::PassContext &ctx, auto &op = gr.metadata(nh).get(); cv::gapi::GBackend selected_backend; cv::GKernelImpl selected_impl; - std::tie(selected_backend, selected_impl) - = kernels.lookup(op.k.name, order); + std::tie(selected_backend, selected_impl) = kernels.lookup(op.k.name); selected_backend.priv().unpackKernel(ctx.graph, nh, selected_impl); op.backend = selected_backend; diff --git a/modules/gapi/src/compiler/passes/passes.hpp b/modules/gapi/src/compiler/passes/passes.hpp index 14f6acd..4daddab 100644 --- a/modules/gapi/src/compiler/passes/passes.hpp +++ b/modules/gapi/src/compiler/passes/passes.hpp @@ -44,9 +44,8 @@ void storeResultingMeta(ade::passes::PassContext &ctx); void expandKernels(ade::passes::PassContext &ctx, const gapi::GKernelPackage& kernels); -void resolveKernels(ade::passes::PassContext &ctx, - const gapi::GKernelPackage &kernels, - const gapi::GLookupOrder &order); +void resolveKernels(ade::passes::PassContext &ctx, + const gapi::GKernelPackage &kernels); void fuseIslands(ade::passes::PassContext &ctx); void syncIslandTags(ade::passes::PassContext &ctx); diff --git a/modules/gapi/test/common/gapi_compoundkernel_tests.cpp b/modules/gapi/test/common/gapi_compoundkernel_tests.cpp index d1d8793..e2b56a7 100644 --- a/modules/gapi/test/common/gapi_compoundkernel_tests.cpp +++ b/modules/gapi/test/common/gapi_compoundkernel_tests.cpp @@ -235,7 +235,7 @@ TEST(GCompoundKernel, ReplaceDefaultKernel) cv::GMat in1, in2; auto out = cv::gapi::add(in1, in2); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(cv::gapi::core::cpu::kernels(), custom_pkg, cv::unite_policy::REPLACE); + const auto full_pkg = cv::gapi::combine(cv::gapi::core::cpu::kernels(), custom_pkg); cv::GComputation comp(cv::GIn(in1, in2), cv::GOut(out)); cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1), in_mat2 = cv::Mat::eye(3, 3, CV_8UC1), @@ -257,7 +257,7 @@ TEST(GCompoundKernel, DoubleAddC) auto out = cv::gapi::addC(super, s); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out)); cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1), @@ -282,7 +282,7 @@ TEST(GCompoundKernel, AddC) auto out = cv::gapi::addC(super, s); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out)); cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1), @@ -308,7 +308,7 @@ TEST(GCompoundKernel, MergeWithSplit) auto out = cv::gapi::merge3(a2, b2, c2); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in), cv::GOut(out)); cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC3), out_mat, ref_mat; @@ -325,7 +325,7 @@ TEST(GCompoundKernel, AddWithAddC) auto out = GCompoundAddWithAddC::on(in1, in2, s); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out)); cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1), @@ -347,7 +347,7 @@ TEST(GCompoundKernel, SplitWithAdd) std::tie(out1, out2) = GCompoundSplitWithAdd::on(in); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in), cv::GOut(out1, out2)); cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC3), @@ -375,7 +375,7 @@ TEST(GCompoundKernel, ParallelAddC) std::tie(out1, out2) = GCompoundParallelAddC::on(in1, in2); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in1, in2), cv::GOut(out1, out2)); cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1), @@ -402,7 +402,7 @@ TEST(GCompoundKernel, GCompundKernelAndDefaultUseOneData) auto out = cv::gapi::add(GCompoundAddWithAddC::on(in1, in2, s), cv::gapi::addC(in2, s)); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out)); cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1), @@ -428,7 +428,7 @@ TEST(GCompoundKernel, CompoundExpandedToCompound) GCompoundAddWithAddCImpl, GCompoundDoubleAddCImpl>(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out)); cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1), @@ -449,7 +449,7 @@ TEST(GCompoundKernel, MaxInArray) GDoubleArray in; auto out = GCompoundMaxInArray::on(in); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in), cv::GOut(out)); std::vector v = { 1, 5, -2, 3, 10, 2}; cv::Scalar out_scl; @@ -465,7 +465,7 @@ TEST(GCompoundKernel, NegateArray) GDoubleArray in; GDoubleArray out = GCompoundNegateArray::on(in); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in), cv::GOut(out)); std::vector in_v = {1, 5, -2, -10, 3}; std::vector out_v; @@ -483,7 +483,7 @@ TEST(GCompoundKernel, RightGArrayHandle) GDoubleArray a; cv::GMat out = GCompoundGMatGArrayGMat::on(in[0], a, in[1]); const auto custom_pkg = cv::gapi::kernels(); - const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP); + const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels()); cv::GComputation comp(cv::GIn(in[0], a, in[1]), cv::GOut(out)); std::vector in_v(3, 1.0); cv::Mat in_mat1 = cv::Mat::eye(cv::Size(3, 3), CV_8UC1), diff --git a/modules/gapi/test/gapi_fluid_resize_test.cpp b/modules/gapi/test/gapi_fluid_resize_test.cpp index cbe3237..2798b85 100644 --- a/modules/gapi/test/gapi_fluid_resize_test.cpp +++ b/modules/gapi/test/gapi_fluid_resize_test.cpp @@ -381,7 +381,7 @@ static auto fluidResizeTestPackage = [](int interpolation, cv::Size szIn, cv::Si }break; default: CV_Assert(false); } - return combine(pkg, fluidTestPackage, unite_policy::KEEP); + return combine(pkg, fluidTestPackage); #undef RESIZE_SWITCH #undef RESIZE_CASE @@ -743,7 +743,7 @@ TEST_P(NV12PlusResizeTest, Test) auto out = cv::gapi::resize(rgb, out_sz, 0, 0, interp); cv::GComputation c(cv::GIn(y, uv), cv::GOut(out)); - auto pkg = cv::gapi::combine(fluidTestPackage, cv::gapi::core::fluid::kernels(), cv::unite_policy::KEEP); + auto pkg = cv::gapi::combine(fluidTestPackage, cv::gapi::core::fluid::kernels()); c.apply(cv::gin(y_mat, uv_mat), cv::gout(out_mat) ,cv::compile_args(pkg, cv::GFluidOutputRois{{to_own(roi)}})); @@ -822,8 +822,7 @@ TEST_P(Preproc4lpiTest, Test) cv::GComputation c(cv::GIn(y, uv), cv::GOut(out)); auto pkg = cv::gapi::combine(cv::gapi::core::fluid::kernels(), - fluidResizeTestPackage(interp, in_sz, out_sz, 4), - cv::unite_policy::REPLACE); + fluidResizeTestPackage(interp, in_sz, out_sz, 4)); c.apply(cv::gin(y_mat, uv_mat), cv::gout(out_mat) ,cv::compile_args(pkg, cv::GFluidOutputRois{{to_own(roi)}})); diff --git a/modules/gapi/test/gapi_kernel_tests.cpp b/modules/gapi/test/gapi_kernel_tests.cpp index aeb4762..bece077 100644 --- a/modules/gapi/test/gapi_kernel_tests.cpp +++ b/modules/gapi/test/gapi_kernel_tests.cpp @@ -9,25 +9,126 @@ #include "opencv2/gapi/cpu/gcpukernel.hpp" #include "gapi_mock_kernels.hpp" +#include "opencv2/gapi/cpu/gcpukernel.hpp" // cpu::backend +#include "opencv2/gapi/fluid/gfluidkernel.hpp" // fluid::backend + namespace opencv_test { namespace { - G_TYPED_KERNEL(GClone, , "org.opencv.test.clone") + namespace I { - static GMatDesc outMeta(GMatDesc in) { return in; } + G_TYPED_KERNEL(GClone, , "org.opencv.test.clone") + { + static GMatDesc outMeta(GMatDesc in) { return in; } + }; + } + enum class KernelTags + { + CPU_CUSTOM_BGR2GRAY, + CPU_CUSTOM_CLONE, + CPU_CUSTOM_ADD, + FLUID_CUSTOM_BGR2GRAY, + FLUID_CUSTOM_CLONE, + FLUID_CUSTOM_ADD }; - GAPI_OCV_KERNEL(GCloneImpl, GClone) + class HeteroGraph: public ::testing::Test { - static void run(const cv::Mat& in, cv::Mat &out) + public: + HeteroGraph() { - out = in.clone(); + auto tmp = I::GClone::on(cv::gapi::add(in[0], in[1])); + out = cv::gapi::imgproc::GBGR2Gray::on(tmp); + } + + static void registerCallKernel(KernelTags kernel_tag) { + kernel_calls.insert(kernel_tag); + } + + bool checkCallKernel(KernelTags kernel_tag) { + return ade::util::contains(kernel_calls, kernel_tag); } + + protected: + void SetUp() override + { + if (!kernel_calls.empty()) + cv::util::throw_error(std::logic_error("Kernel call log has not been cleared!!!")); + } + + void TearDown() override + { + kernel_calls.clear(); + } + + protected: + cv::GMat in[2], out; + static std::set kernel_calls; }; -} + + namespace cpu + { + GAPI_OCV_KERNEL(GClone, I::GClone) + { + static void run(const cv::Mat&, cv::Mat) + { + HeteroGraph::registerCallKernel(KernelTags::CPU_CUSTOM_CLONE); + } + }; + + GAPI_OCV_KERNEL(BGR2Gray, cv::gapi::imgproc::GBGR2Gray) + { + static void run(const cv::Mat&, cv::Mat&) + { + HeteroGraph::registerCallKernel(KernelTags::CPU_CUSTOM_BGR2GRAY); + } + }; + + GAPI_OCV_KERNEL(GAdd, cv::gapi::core::GAdd) + { + static void run(const cv::Mat&, const cv::Mat&, int, cv::Mat&) + { + HeteroGraph::registerCallKernel(KernelTags::CPU_CUSTOM_ADD); + } + }; + } + + namespace fluid + { + GAPI_FLUID_KERNEL(GClone, I::GClone, false) + { + static const int Window = 1; + static void run(const cv::gapi::fluid::View&, cv::gapi::fluid::Buffer) + { + HeteroGraph::registerCallKernel(KernelTags::FLUID_CUSTOM_CLONE); + } + }; + + GAPI_FLUID_KERNEL(BGR2Gray, cv::gapi::imgproc::GBGR2Gray, false) + { + static const int Window = 1; + static void run(const cv::gapi::fluid::View&, cv::gapi::fluid::Buffer&) + { + HeteroGraph::registerCallKernel(KernelTags::FLUID_CUSTOM_BGR2GRAY); + } + }; + + GAPI_FLUID_KERNEL(GAdd, cv::gapi::core::GAdd, false) + { + static const int Window = 1; + static void run(const cv::gapi::fluid::View&, const cv::gapi::fluid::View&, + int, cv::gapi::fluid::Buffer&) + { + HeteroGraph::registerCallKernel(KernelTags::FLUID_CUSTOM_ADD); + } + }; + } + + std::set HeteroGraph::kernel_calls; +} // anonymous namespace TEST(KernelPackage, Create) { @@ -57,17 +158,6 @@ TEST(KernelPackage, IncludesAPI) EXPECT_FALSE(pkg.includesAPI()); } -TEST(KernelPackage, IncludesAPI_Overlapping) -{ - namespace J = Jupiter; - namespace S = Saturn; - auto pkg = cv::gapi::kernels(); - EXPECT_TRUE (pkg.includesAPI()); - EXPECT_TRUE (pkg.includesAPI()); - EXPECT_FALSE(pkg.includesAPI()); - EXPECT_FALSE(pkg.includesAPI()); -} - TEST(KernelPackage, Include_Add) { namespace J = Jupiter; @@ -78,23 +168,6 @@ TEST(KernelPackage, Include_Add) EXPECT_TRUE(pkg.includes()); } -TEST(KernelPackage, Include_KEEP) -{ - namespace J = Jupiter; - namespace S = Saturn; - auto pkg = cv::gapi::kernels(); - EXPECT_FALSE(pkg.includes()); - EXPECT_FALSE(pkg.includes()); - - pkg.include(); // default (KEEP) - EXPECT_TRUE(pkg.includes()); - EXPECT_TRUE(pkg.includes()); - - pkg.include(cv::unite_policy::KEEP); // explicit (KEEP) - EXPECT_TRUE(pkg.includes()); - EXPECT_TRUE(pkg.includes()); -} - TEST(KernelPackage, Include_REPLACE) { namespace J = Jupiter; @@ -102,7 +175,7 @@ TEST(KernelPackage, Include_REPLACE) auto pkg = cv::gapi::kernels(); EXPECT_FALSE(pkg.includes()); - pkg.include(cv::unite_policy::REPLACE); + pkg.include(); EXPECT_FALSE(pkg.includes()); EXPECT_TRUE(pkg.includes()); } @@ -111,31 +184,27 @@ TEST(KernelPackage, RemoveBackend) { namespace J = Jupiter; namespace S = Saturn; - auto pkg = cv::gapi::kernels(); + auto pkg = cv::gapi::kernels(); EXPECT_TRUE(pkg.includes()); EXPECT_TRUE(pkg.includes()); - EXPECT_TRUE(pkg.includes()); pkg.remove(J::backend()); EXPECT_FALSE(pkg.includes()); EXPECT_FALSE(pkg.includes()); - EXPECT_TRUE(pkg.includes()); + EXPECT_TRUE(pkg.includes()); }; TEST(KernelPackage, RemoveAPI) { namespace J = Jupiter; namespace S = Saturn; - auto pkg = cv::gapi::kernels(); + auto pkg = cv::gapi::kernels(); EXPECT_TRUE(pkg.includes()); EXPECT_TRUE(pkg.includes()); - EXPECT_TRUE(pkg.includes()); pkg.remove(); EXPECT_TRUE(pkg.includes()); - EXPECT_TRUE(pkg.includes()); EXPECT_FALSE(pkg.includes()); - EXPECT_FALSE(pkg.includes()); }; TEST(KernelPackage, CreateHetero) @@ -177,7 +246,7 @@ TEST(KernelPackage, Combine_REPLACE_Full) namespace S = Saturn; auto j_pkg = cv::gapi::kernels(); auto s_pkg = cv::gapi::kernels(); - auto u_pkg = cv::gapi::combine(j_pkg, s_pkg, cv::unite_policy::REPLACE); + auto u_pkg = cv::gapi::combine(j_pkg, s_pkg); EXPECT_EQ(3u, u_pkg.size()); EXPECT_FALSE(u_pkg.includes()); @@ -194,7 +263,7 @@ TEST(KernelPackage, Combine_REPLACE_Partial) namespace S = Saturn; auto j_pkg = cv::gapi::kernels(); auto s_pkg = cv::gapi::kernels(); - auto u_pkg = cv::gapi::combine(j_pkg, s_pkg, cv::unite_policy::REPLACE); + auto u_pkg = cv::gapi::combine(j_pkg, s_pkg); EXPECT_EQ(2u, u_pkg.size()); EXPECT_TRUE (u_pkg.includes()); @@ -208,38 +277,7 @@ TEST(KernelPackage, Combine_REPLACE_Append) namespace S = Saturn; auto j_pkg = cv::gapi::kernels(); auto s_pkg = cv::gapi::kernels(); - auto u_pkg = cv::gapi::combine(j_pkg, s_pkg, cv::unite_policy::REPLACE); - - EXPECT_EQ(3u, u_pkg.size()); - EXPECT_TRUE(u_pkg.includes()); - EXPECT_TRUE(u_pkg.includes()); - EXPECT_TRUE(u_pkg.includes()); -} - -TEST(KernelPackage, Combine_KEEP_AllDups) -{ - namespace J = Jupiter; - namespace S = Saturn; - auto j_pkg = cv::gapi::kernels(); - auto s_pkg = cv::gapi::kernels(); - auto u_pkg = cv::gapi::combine(j_pkg ,s_pkg, cv::unite_policy::KEEP); - - EXPECT_EQ(6u, u_pkg.size()); - EXPECT_TRUE(u_pkg.includes()); - EXPECT_TRUE(u_pkg.includes()); - EXPECT_TRUE(u_pkg.includes()); - EXPECT_TRUE(u_pkg.includes()); - EXPECT_TRUE(u_pkg.includes()); - EXPECT_TRUE(u_pkg.includes()); -} - -TEST(KernelPackage, Combine_KEEP_Append_NoDups) -{ - namespace J = Jupiter; - namespace S = Saturn; - auto j_pkg = cv::gapi::kernels(); - auto s_pkg = cv::gapi::kernels(); - auto u_pkg = cv::gapi::combine(j_pkg, s_pkg, cv::unite_policy::KEEP); + auto u_pkg = cv::gapi::combine(j_pkg, s_pkg); EXPECT_EQ(3u, u_pkg.size()); EXPECT_TRUE(u_pkg.includes()); @@ -252,7 +290,7 @@ TEST(KernelPackage, TestWithEmptyLHS) namespace J = Jupiter; auto lhs = cv::gapi::kernels<>(); auto rhs = cv::gapi::kernels(); - auto pkg = cv::gapi::combine(lhs, rhs, cv::unite_policy::KEEP); + auto pkg = cv::gapi::combine(lhs, rhs); EXPECT_EQ(1u, pkg.size()); EXPECT_TRUE(pkg.includes()); @@ -263,22 +301,211 @@ TEST(KernelPackage, TestWithEmptyRHS) namespace J = Jupiter; auto lhs = cv::gapi::kernels(); auto rhs = cv::gapi::kernels<>(); - auto pkg = cv::gapi::combine(lhs, rhs, cv::unite_policy::KEEP); + auto pkg = cv::gapi::combine(lhs, rhs); EXPECT_EQ(1u, pkg.size()); EXPECT_TRUE(pkg.includes()); } +TEST(KernelPackage, Return_Unique_Backends) +{ + auto pkg = cv::gapi::kernels(); + EXPECT_EQ(2u, pkg.backends().size()); +} + TEST(KernelPackage, Can_Use_Custom_Kernel) { cv::GMat in[2]; - auto out = GClone::on(cv::gapi::add(in[0], in[1])); + auto out = I::GClone::on(cv::gapi::add(in[0], in[1])); const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)}); - auto pkg = cv::gapi::kernels(); + auto pkg = cv::gapi::kernels(); EXPECT_NO_THROW(cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). compile({in_meta, in_meta}, cv::compile_args(pkg))); } +TEST_F(HeteroGraph, Call_Custom_Kernel_Default_Backend) +{ + // in0 -> GCPUAdd -> tmp -> cpu::GClone -> GCPUBGR2Gray -> out + // ^ + // | + // in1 -------` + + cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC3), + in_mat2 = cv::Mat::eye(3, 3, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(pkg)); + + EXPECT_TRUE(checkCallKernel(KernelTags::CPU_CUSTOM_CLONE)); +} + +TEST_F(HeteroGraph, Call_Custom_Kernel_Not_Default_Backend) +{ + // in0 -> GCPUAdd -> tmp -> fluid::GClone -> GCPUBGR2Gray -> out + // ^ + // | + // in1 -------` + + cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC3), + in_mat2 = cv::Mat::eye(3, 3, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(pkg)); + + EXPECT_TRUE(checkCallKernel(KernelTags::FLUID_CUSTOM_CLONE)); +} + +TEST_F(HeteroGraph, Replace_Default_To_Same_Backend) +{ + // in0 -> GCPUAdd -> tmp -> cpu::GClone -> cpu::BGR2Gray -> out + // ^ + // | + // in1 -------` + + cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC3), + in_mat2 = cv::Mat::eye(3, 3, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(pkg)); + + EXPECT_TRUE(checkCallKernel(KernelTags::CPU_CUSTOM_BGR2GRAY)); +} + +TEST_F(HeteroGraph, Replace_Default_To_Another_Backend) +{ + //in0 -> GCPUAdd -> tmp -> cpu::GClone -> fluid::BGR2Gray -> out + // ^ + // | + //in1 --------` + + cv::Mat in_mat1(300, 300, CV_8UC3), + in_mat2(300, 300, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(pkg)); + + EXPECT_TRUE(checkCallKernel(KernelTags::FLUID_CUSTOM_BGR2GRAY)); +} + +TEST_F(HeteroGraph, Use_Only_Same_Backend) +{ + //in0 -> cpu::GAdd -> tmp -> cpu::GClone -> cpu::BGR2Gray -> out + // ^ + // | + //in1 --------` + + cv::Mat in_mat1(300, 300, CV_8UC3), + in_mat2(300, 300, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(cv::gapi::use_only{pkg})); + + EXPECT_TRUE(checkCallKernel(KernelTags::CPU_CUSTOM_ADD)); + EXPECT_TRUE(checkCallKernel(KernelTags::CPU_CUSTOM_CLONE)); + EXPECT_TRUE(checkCallKernel(KernelTags::CPU_CUSTOM_BGR2GRAY)); +} + +TEST_F(HeteroGraph, Use_Only_Another_Backend) +{ + //in0 -> fluid::GAdd -> tmp -> fluid::GClone -> fluid::BGR2Gray -> out + // ^ + // | + //in1 --------` + + cv::Mat in_mat1(300, 300, CV_8UC3), + in_mat2(300, 300, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(cv::gapi::use_only{pkg})); + + EXPECT_TRUE(checkCallKernel(KernelTags::FLUID_CUSTOM_ADD)); + EXPECT_TRUE(checkCallKernel(KernelTags::FLUID_CUSTOM_CLONE)); + EXPECT_TRUE(checkCallKernel(KernelTags::FLUID_CUSTOM_BGR2GRAY)); +} + +TEST_F(HeteroGraph, Use_Only_Hetero_Backend) +{ + //in0 -> cpu::GAdd -> tmp -> fluid::GClone -> fluid::BGR2Gray -> out + // ^ + // | + //in1 --------` + + cv::Mat in_mat1(300, 300, CV_8UC3), + in_mat2(300, 300, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(cv::gapi::use_only{pkg})); + + EXPECT_TRUE(checkCallKernel(KernelTags::CPU_CUSTOM_ADD)); + EXPECT_TRUE(checkCallKernel(KernelTags::FLUID_CUSTOM_CLONE)); + EXPECT_TRUE(checkCallKernel(KernelTags::FLUID_CUSTOM_BGR2GRAY)); +} + +TEST_F(HeteroGraph, Use_Only_Not_Found_Default) +{ + //in0 -> GCPUAdd -> tmp -> fluid::GClone -> fluid::BGR2Gray -> out + // ^ + // | + //in1 --------` + + cv::Mat in_mat1(300, 300, CV_8UC3), + in_mat2(300, 300, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + EXPECT_ANY_THROW(cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(cv::gapi::use_only{pkg}))); +} + +TEST_F(HeteroGraph, Use_Only_Not_Found_Custom) +{ + //in0 -> cpu::GAdd -> tmp -> fluid::GClone -> fluid::BGR2Gray -> out + // ^ + // | + //in1 --------` + + cv::Mat in_mat1(300, 300, CV_8UC3), + in_mat2(300, 300, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + EXPECT_ANY_THROW(cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(cv::gapi::use_only{pkg}))); +} + +TEST_F(HeteroGraph, Use_Only_Other_Package_Ignored) +{ + //in0 -> cpu::GAdd -> tmp -> fluid::GClone -> fluid::BGR2Gray -> out + // ^ + // | + //in1 --------` + + cv::Mat in_mat1(300, 300, CV_8UC3), + in_mat2(300, 300, CV_8UC3), + out_mat; + + auto pkg = cv::gapi::kernels(); + auto clone_pkg = cv::gapi::kernels(); + + EXPECT_ANY_THROW(cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)). + apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), + cv::compile_args(clone_pkg, cv::gapi::use_only{pkg}))); +} + } // namespace opencv_test diff --git a/modules/gapi/test/internal/gapi_int_recompilation_test.cpp b/modules/gapi/test/internal/gapi_int_recompilation_test.cpp index 833ea17..25c8e3d 100644 --- a/modules/gapi/test/internal/gapi_int_recompilation_test.cpp +++ b/modules/gapi/test/internal/gapi_int_recompilation_test.cpp @@ -197,8 +197,7 @@ TEST(GComputationCompile, ReshapeRois) cv::randn(first_in_mat, cv::Scalar::all(127), cv::Scalar::all(40.f)); cv::Mat first_out_mat; auto fluidKernels = cv::gapi::combine(gapi::imgproc::fluid::kernels(), - gapi::core::fluid::kernels(), - cv::unite_policy::REPLACE); + gapi::core::fluid::kernels()); cc.apply(first_in_mat, first_out_mat, cv::compile_args(fluidKernels)); auto first_comp = cc.priv().m_lastCompiled; diff --git a/modules/gapi/test/internal/gapi_int_resolve_kernel_test.cpp b/modules/gapi/test/internal/gapi_int_resolve_kernel_test.cpp deleted file mode 100644 index c0411f4..0000000 --- a/modules/gapi/test/internal/gapi_int_resolve_kernel_test.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// 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 "../test_precomp.hpp" - -#include "../gapi_mock_kernels.hpp" - -namespace opencv_test -{ - -TEST(Lookup, CreateOrder) -{ - const auto order = cv::gapi::lookup_order({Jupiter::backend(), - Saturn::backend()}); - EXPECT_EQ(2u, order.size()); - EXPECT_EQ(Jupiter::backend(), order[0]); - EXPECT_EQ(Saturn ::backend(), order[1]); -} - -TEST(Lookup, NoOrder) -{ - namespace J = Jupiter; - namespace S = Saturn; - const auto pkg = cv::gapi::kernels(); - - EXPECT_NO_THROW (pkg.lookup()); - EXPECT_NO_THROW (pkg.lookup()); - EXPECT_NO_THROW (pkg.lookup()); - EXPECT_ANY_THROW(pkg.lookup()); -} - -TEST(Lookup, Only_Jupiter) -{ - namespace J = Jupiter; - namespace S = Saturn; - const auto pkg = cv::gapi::kernels(); - - auto order = cv::gapi::lookup_order({J::backend()}); - - EXPECT_EQ(J::backend(), pkg.lookup(order)); - EXPECT_EQ(J::backend(), pkg.lookup(order)); - EXPECT_EQ(J::backend(), pkg.lookup(order)); - EXPECT_ANY_THROW(pkg.lookup(order)); -} - -TEST(Lookup, Only_Saturn) -{ - namespace J = Jupiter; - namespace S = Saturn; - const auto pkg = cv::gapi::kernels(); - - auto order = cv::gapi::lookup_order({S::backend()}); - - EXPECT_EQ(S::backend(), pkg.lookup(order)); - EXPECT_EQ(S::backend(), pkg.lookup(order)); - EXPECT_EQ(S::backend(), pkg.lookup(order)); - EXPECT_ANY_THROW(pkg.lookup(order)); -} - -TEST(Lookup, With_Order) -{ - namespace J = Jupiter; - namespace S = Saturn; - const auto pkg = cv::gapi::kernels(); - - auto prefer_j = cv::gapi::lookup_order({J::backend(), S::backend()}); - EXPECT_EQ(J::backend(), pkg.lookup(prefer_j)); - EXPECT_EQ(J::backend(), pkg.lookup(prefer_j)); - EXPECT_EQ(J::backend(), pkg.lookup(prefer_j)); - EXPECT_ANY_THROW(pkg.lookup(prefer_j)); - - auto prefer_s = cv::gapi::lookup_order({S::backend(), J::backend()}); - EXPECT_EQ(S::backend(), pkg.lookup(prefer_s)); - EXPECT_EQ(S::backend(), pkg.lookup(prefer_s)); - EXPECT_EQ(S::backend(), pkg.lookup(prefer_s)); - EXPECT_ANY_THROW(pkg.lookup(prefer_s)); -} - -TEST(Lookup, NoOverlap) -{ - namespace J = Jupiter; - namespace S = Saturn; - const auto pkg = cv::gapi::kernels(); - EXPECT_EQ(J::backend(), pkg.lookup()); - EXPECT_EQ(J::backend(), pkg.lookup()); - EXPECT_EQ(S::backend(), pkg.lookup()); - EXPECT_EQ(S::backend(), pkg.lookup()); -} - -TEST(Lookup, ExtraBackend) -{ - namespace J = Jupiter; - namespace S = Saturn; - const auto pkg = cv::gapi::kernels(); - - // Even if pkg doesn't contain S kernels while S is preferable, - // it should work. - const auto prefer_sj = cv::gapi::lookup_order({S::backend(), J::backend()}); - EXPECT_EQ(J::backend(), pkg.lookup(prefer_sj)); - EXPECT_EQ(J::backend(), pkg.lookup(prefer_sj)); - EXPECT_EQ(J::backend(), pkg.lookup(prefer_sj)); - - // If search scope is limited to S only, neither J nor S kernels - // shouldn't be found - const auto only_s = cv::gapi::lookup_order({S::backend()}); - EXPECT_ANY_THROW(pkg.lookup(only_s)); - EXPECT_ANY_THROW(pkg.lookup(only_s)); - EXPECT_ANY_THROW(pkg.lookup(only_s)); -} - -} // namespace opencv_test diff --git a/samples/cpp/tutorial_code/gapi/porting_anisotropic_image_segmentation/porting_anisotropic_image_segmentation_gapi_fluid.cpp b/samples/cpp/tutorial_code/gapi/porting_anisotropic_image_segmentation/porting_anisotropic_image_segmentation_gapi_fluid.cpp index 71271c3..2d528aa 100644 --- a/samples/cpp/tutorial_code/gapi/porting_anisotropic_image_segmentation/porting_anisotropic_image_segmentation_gapi_fluid.cpp +++ b/samples/cpp/tutorial_code/gapi/porting_anisotropic_image_segmentation/porting_anisotropic_image_segmentation_gapi_fluid.cpp @@ -65,8 +65,7 @@ int main() // Prepare the kernel package and run the graph cv::gapi::GKernelPackage fluid_kernels = cv::gapi::combine // Define a custom kernel package: (cv::gapi::core::fluid::kernels(), // ...with Fluid Core kernels - cv::gapi::imgproc::fluid::kernels(), // ...and Fluid ImgProc kernels - cv::unite_policy::KEEP); + cv::gapi::imgproc::fluid::kernels()); // ...and Fluid ImgProc kernels //! [kernel_pkg] //! [kernel_hotfix] fluid_kernels.remove(); // Remove Fluid Box filter as unsuitable, -- 2.7.4