mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
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
This commit is contained in:
parent
de977cc9c8
commit
935c02c0a3
@ -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"
|
Kernel packages are combinable -- in the above example, we take "Core"
|
||||||
and "ImgProc" Fluid kernel packages and combine it into a single
|
and "ImgProc" Fluid kernel packages and combine it into a single
|
||||||
one. See documentation reference on cv::gapi::combine and
|
one. See documentation reference on cv::gapi::combine.
|
||||||
cv::unite_policy on package combination options.
|
|
||||||
|
|
||||||
If no kernel packages are specified in options, G-API is using
|
If no kernel packages are specified in options, G-API is using
|
||||||
_default_ package which consists of default OpenCV implementations and
|
_default_ package which consists of default OpenCV implementations and
|
||||||
thus G-API graphs are executed via OpenCV functions by default. OpenCV
|
thus G-API graphs are executed via OpenCV functions by default. OpenCV
|
||||||
backend provides broader functional coverage than any other
|
backend provides broader functional coverage than any other
|
||||||
backend. If a kernel package is specified, like in this example, then
|
backend. If a kernel package is specified, like in this example, then
|
||||||
it is being combined with the _default_ one with
|
it is being combined with the _default_.
|
||||||
cv::unite_policy::REPLACE. It means that user-specified
|
It means that user-specified implementations will replace default implementations in case of
|
||||||
implementations will replace default implementations in case of
|
|
||||||
conflict.
|
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.
|
|
||||||
|
|
||||||
<!-- FIXME Document this process better as a part of regular -->
|
<!-- FIXME Document this process better as a part of regular -->
|
||||||
<!-- documentation, not a tutorial kind of thing -->
|
<!-- documentation, not a tutorial kind of thing -->
|
||||||
|
|
||||||
|
@ -43,13 +43,12 @@ namespace cpu
|
|||||||
* stack. Every backend is hardware-oriented and thus can run its
|
* stack. Every backend is hardware-oriented and thus can run its
|
||||||
* kernels efficiently on the target platform.
|
* 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
|
* side, all backends are represented as different objects of the
|
||||||
* same class cv::gapi::GBackend. User can manipulate with backends
|
* same class cv::gapi::GBackend.
|
||||||
* mainly by specifying which kernels to use or where to look up
|
* User can manipulate with backends by specifying which kernels to use.
|
||||||
* for kernels first.
|
|
||||||
*
|
*
|
||||||
* @sa @ref gapi_hld, cv::gapi::lookup_order()
|
* @sa @ref gapi_hld
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include <type_traits> // false_type, true_type
|
#include <type_traits> // false_type, true_type
|
||||||
#include <unordered_map> // map (for GKernelPackage)
|
#include <unordered_map> // map (for GKernelPackage)
|
||||||
#include <utility> // tuple
|
#include <utility> // tuple
|
||||||
#include <vector> // lookup order
|
|
||||||
|
|
||||||
#include <opencv2/gapi/gcommon.hpp> // CompileArgTag
|
#include <opencv2/gapi/gcommon.hpp> // CompileArgTag
|
||||||
#include <opencv2/gapi/util/util.hpp> // Seq
|
#include <opencv2/gapi/util/util.hpp> // Seq
|
||||||
@ -24,7 +23,6 @@
|
|||||||
#include <opencv2/gapi/gtype_traits.hpp> // GTypeTraits
|
#include <opencv2/gapi/gtype_traits.hpp> // GTypeTraits
|
||||||
#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
|
#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
|
||||||
|
|
||||||
|
|
||||||
namespace cv {
|
namespace cv {
|
||||||
|
|
||||||
using GShapes = std::vector<GShape>;
|
using GShapes = std::vector<GShape>;
|
||||||
@ -57,7 +55,6 @@ namespace detail
|
|||||||
//
|
//
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T> struct Yield;
|
template<typename T> struct Yield;
|
||||||
template<> struct Yield<cv::GMat>
|
template<> struct Yield<cv::GMat>
|
||||||
{
|
{
|
||||||
@ -248,13 +245,6 @@ public:
|
|||||||
|
|
||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
// Declare <unite> in cv:: namespace
|
|
||||||
enum class unite_policy
|
|
||||||
{
|
|
||||||
REPLACE,
|
|
||||||
KEEP
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace gapi
|
namespace gapi
|
||||||
{
|
{
|
||||||
// Prework: model "Device" API before it gets to G-API headers.
|
// 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<GBackend>;
|
|
||||||
/**
|
|
||||||
* @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<GBackend> &&list)
|
|
||||||
{
|
|
||||||
return GLookupOrder(std::move(list));
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Hide implementation
|
// FIXME: Hide implementation
|
||||||
/**
|
/**
|
||||||
* @brief A container class for heterogeneous kernel
|
* @brief A container class for heterogeneous kernel
|
||||||
@ -353,20 +316,16 @@ namespace gapi {
|
|||||||
* one since G-API kernel implementations are _types_, not objects.
|
* one since G-API kernel implementations are _types_, not objects.
|
||||||
*
|
*
|
||||||
* Finally, two kernel packages can be combined into a new one
|
* Finally, two kernel packages can be combined into a new one
|
||||||
* with function cv::gapi::combine(). There are different rules
|
* with function cv::gapi::combine().
|
||||||
* apply to this process, see also cv::gapi::unite_policy for
|
|
||||||
* details.
|
|
||||||
*/
|
*/
|
||||||
class GAPI_EXPORTS GKernelPackage
|
class GAPI_EXPORTS GKernelPackage
|
||||||
{
|
{
|
||||||
/// @private
|
|
||||||
using S = std::unordered_map<std::string, GKernelImpl>;
|
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
using M = std::unordered_map<GBackend, S>;
|
using M = std::unordered_map<std::string, std::pair<GBackend, GKernelImpl>>;
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
M m_backend_kernels;
|
M m_id_kernels;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// @private
|
/// @private
|
||||||
@ -398,10 +357,9 @@ namespace gapi {
|
|||||||
template<typename KImpl>
|
template<typename KImpl>
|
||||||
bool includes() const
|
bool includes() const
|
||||||
{
|
{
|
||||||
const auto set_iter = m_backend_kernels.find(KImpl::backend());
|
auto kernel_it = m_id_kernels.find(KImpl::API::id());
|
||||||
return (set_iter != m_backend_kernels.end())
|
return kernel_it != m_id_kernels.end() &&
|
||||||
? (set_iter->second.count(KImpl::API::id()) > 0)
|
kernel_it->second.first == KImpl::backend();
|
||||||
: false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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.
|
* Throws if nothing found.
|
||||||
*
|
*
|
||||||
* @return Backend which hosts matching kernel implementation.
|
* @return Backend which hosts matching kernel implementation.
|
||||||
*
|
*
|
||||||
* @sa cv::gapi::lookup_order
|
|
||||||
*/
|
*/
|
||||||
template<typename KAPI>
|
template<typename KAPI>
|
||||||
GBackend lookup(const GLookupOrder &order = {}) const
|
GBackend lookup() const
|
||||||
{
|
{
|
||||||
return lookup(KAPI::id(), order).first;
|
return lookup(KAPI::id()).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
std::pair<cv::gapi::GBackend, cv::GKernelImpl>
|
std::pair<cv::gapi::GBackend, cv::GKernelImpl>
|
||||||
lookup(const std::string &id, const GLookupOrder &order = {}) const;
|
lookup(const std::string &id) const;
|
||||||
|
|
||||||
// FIXME: No overwrites allowed?
|
// FIXME: No overwrites allowed?
|
||||||
/**
|
/**
|
||||||
* @brief Put a new kernel implementation KImpl into package.
|
* @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<typename KImpl>
|
template<typename KImpl>
|
||||||
void include(const cv::unite_policy up = cv::unite_policy::KEEP)
|
void include()
|
||||||
{
|
{
|
||||||
auto backend = KImpl::backend();
|
auto backend = KImpl::backend();
|
||||||
auto kernel_id = KImpl::API::id();
|
auto kernel_id = KImpl::API::id();
|
||||||
auto kernel_impl = GKernelImpl{KImpl::kernel()};
|
auto kernel_impl = GKernelImpl{KImpl::kernel()};
|
||||||
if (up == cv::unite_policy::REPLACE) removeAPI(kernel_id);
|
removeAPI(kernel_id);
|
||||||
else GAPI_Assert(up == cv::unite_policy::KEEP);
|
|
||||||
|
|
||||||
// Regardless of the policy, store new impl in its storage slot.
|
m_id_kernels[kernel_id] = std::make_pair(backend, kernel_impl);
|
||||||
m_backend_kernels[backend][kernel_id] = std::move(kernel_impl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -492,23 +440,14 @@ namespace gapi {
|
|||||||
// TODO: Doxygen bug -- it wants me to place this comment
|
// TODO: Doxygen bug -- it wants me to place this comment
|
||||||
// here, not below.
|
// here, not below.
|
||||||
/**
|
/**
|
||||||
* @brief Create a new package based on `lhs` and `rhs`,
|
* @brief Create a new package based on `lhs` and `rhs`.
|
||||||
* with unity policy defined by `policy`.
|
|
||||||
*
|
*
|
||||||
* @param lhs "Left-hand-side" package in the process
|
* @param lhs "Left-hand-side" package in the process
|
||||||
* @param rhs "Right-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.
|
* @return a new kernel package.
|
||||||
*/
|
*/
|
||||||
friend GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &lhs,
|
friend GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &lhs,
|
||||||
const GKernelPackage &rhs,
|
const GKernelPackage &rhs);
|
||||||
const cv::unite_policy policy);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -540,6 +479,7 @@ namespace gapi {
|
|||||||
// and parentheses are used to hide function call in the expanded sequence.
|
// 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<>()).
|
// Leading 0 helps to handle case when KK is an empty list (kernels<>()).
|
||||||
|
|
||||||
|
static_assert(detail::all_unique<typename KK::API...>::value, "Kernels API must be unique");
|
||||||
int unused[] = { 0, (pkg.include<KK>(), 0)... };
|
int unused[] = { 0, (pkg.include<KK>(), 0)... };
|
||||||
cv::util::suppress_unused_warning(unused);
|
cv::util::suppress_unused_warning(unused);
|
||||||
return pkg;
|
return pkg;
|
||||||
@ -548,8 +488,17 @@ namespace gapi {
|
|||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &lhs,
|
GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &lhs,
|
||||||
const GKernelPackage &rhs,
|
const GKernelPackage &rhs);
|
||||||
const cv::unite_policy policy);
|
/**
|
||||||
|
* @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 gapi
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -558,9 +507,10 @@ namespace detail
|
|||||||
{
|
{
|
||||||
static const char* tag() { return "gapi.kernel_package"; }
|
static const char* tag() { return "gapi.kernel_package"; }
|
||||||
};
|
};
|
||||||
template<> struct CompileArgTag<cv::gapi::GLookupOrder>
|
|
||||||
|
template<> struct CompileArgTag<cv::gapi::use_only>
|
||||||
{
|
{
|
||||||
static const char* tag() { return "gapi.lookup_order"; }
|
static const char* tag() { return "gapi.use_only"; }
|
||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
@ -84,6 +84,19 @@ namespace detail
|
|||||||
{
|
{
|
||||||
static constexpr const std::size_t value = S;
|
static constexpr const std::size_t value = S;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename...>
|
||||||
|
struct contains : std::false_type{};
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename... Ts>
|
||||||
|
struct contains<T1, T2, Ts...> : std::integral_constant<bool, std::is_same<T1, T2>::value ||
|
||||||
|
contains<T1, Ts...>::value> {};
|
||||||
|
template <typename...>
|
||||||
|
struct all_unique : std::true_type{};
|
||||||
|
|
||||||
|
template <typename T1, typename... Ts>
|
||||||
|
struct all_unique<T1, Ts...> : std::integral_constant<bool, !contains<T1, Ts...>::value &&
|
||||||
|
all_unique<Ts...>::value> {};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
|
||||||
|
@ -49,8 +49,7 @@ int main(int argc, char *argv[])
|
|||||||
//! [apply_with_param]
|
//! [apply_with_param]
|
||||||
cv::gapi::GKernelPackage kernels = cv::gapi::combine
|
cv::gapi::GKernelPackage kernels = cv::gapi::combine
|
||||||
(cv::gapi::core::fluid::kernels(),
|
(cv::gapi::core::fluid::kernels(),
|
||||||
cv::gapi::imgproc::fluid::kernels(),
|
cv::gapi::imgproc::fluid::kernels());
|
||||||
cv::unite_policy::KEEP);
|
|
||||||
sobelEdge.apply(input, output, cv::compile_args(kernels));
|
sobelEdge.apply(input, output, cv::compile_args(kernels));
|
||||||
//! [apply_with_param]
|
//! [apply_with_param]
|
||||||
|
|
||||||
|
@ -20,128 +20,73 @@
|
|||||||
// GKernelPackage public implementation ////////////////////////////////////////
|
// GKernelPackage public implementation ////////////////////////////////////////
|
||||||
void cv::gapi::GKernelPackage::remove(const cv::gapi::GBackend& backend)
|
void cv::gapi::GKernelPackage::remove(const cv::gapi::GBackend& backend)
|
||||||
{
|
{
|
||||||
m_backend_kernels.erase(backend);
|
std::vector<std::string> 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
|
bool cv::gapi::GKernelPackage::includesAPI(const std::string &id) const
|
||||||
{
|
{
|
||||||
// In current form not very efficient (n * log n)
|
return ade::util::contains(m_id_kernels, id);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cv::gapi::GKernelPackage::removeAPI(const std::string &id)
|
void cv::gapi::GKernelPackage::removeAPI(const std::string &id)
|
||||||
{
|
{
|
||||||
for (auto &bk : m_backend_kernels)
|
m_id_kernels.erase(id);
|
||||||
bk.second.erase(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t cv::gapi::GKernelPackage::size() const
|
std::size_t cv::gapi::GKernelPackage::size() const
|
||||||
{
|
{
|
||||||
return std::accumulate(m_backend_kernels.begin(),
|
return m_id_kernels.size();
|
||||||
m_backend_kernels.end(),
|
|
||||||
static_cast<std::size_t>(0u),
|
|
||||||
[](std::size_t acc, const M::value_type& v) {
|
|
||||||
return acc + v.second.size();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage &lhs,
|
cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage &lhs,
|
||||||
const GKernelPackage &rhs,
|
const GKernelPackage &rhs)
|
||||||
const cv::unite_policy policy)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (policy == cv::unite_policy::REPLACE)
|
// If there is a collision, prefer RHS to LHS
|
||||||
{
|
|
||||||
// REPLACE policy: if there is a collision, prefer RHS
|
|
||||||
// to LHS
|
|
||||||
// since RHS package has a precedense, start with its copy
|
// since RHS package has a precedense, start with its copy
|
||||||
GKernelPackage result(rhs);
|
GKernelPackage result(rhs);
|
||||||
// now iterate over LHS package and put kernel if and only
|
// now iterate over LHS package and put kernel if and only
|
||||||
// if there's no such one
|
// 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_id_kernels.emplace(kernel.first, kernel.second);
|
||||||
result.m_backend_kernels[backend.first].insert(kimpl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
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::GBackend, cv::GKernelImpl>
|
std::pair<cv::gapi::GBackend, cv::GKernelImpl>
|
||||||
cv::gapi::GKernelPackage::lookup(const std::string &id,
|
cv::gapi::GKernelPackage::lookup(const std::string &id) const
|
||||||
const GLookupOrder &order) 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
|
return kernel_it->second;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
// If reached here, kernel was not found.
|
||||||
{
|
|
||||||
// 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.
|
|
||||||
util::throw_error(std::logic_error("Kernel " + id + " was not found"));
|
util::throw_error(std::logic_error("Kernel " + id + " was not found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<cv::gapi::GBackend> cv::gapi::GKernelPackage::backends() const
|
std::vector<cv::gapi::GBackend> cv::gapi::GKernelPackage::backends() const
|
||||||
{
|
{
|
||||||
std::vector<cv::gapi::GBackend> result;
|
using kernel_type = std::pair<std::string, std::pair<cv::gapi::GBackend, cv::GKernelImpl>>;
|
||||||
for (const auto &p : m_backend_kernels) result.emplace_back(p.first);
|
std::unordered_set<cv::gapi::GBackend> unique_set;
|
||||||
return result;
|
ade::util::transform(m_id_kernels, std::inserter(unique_set, unique_set.end()),
|
||||||
|
[](const kernel_type& k) { return k.second.first; });
|
||||||
|
|
||||||
|
return std::vector<cv::gapi::GBackend>(unique_set.begin(), unique_set.end());
|
||||||
}
|
}
|
||||||
|
@ -48,16 +48,19 @@ namespace
|
|||||||
{
|
{
|
||||||
cv::gapi::GKernelPackage getKernelPackage(cv::GCompileArgs &args)
|
cv::gapi::GKernelPackage getKernelPackage(cv::GCompileArgs &args)
|
||||||
{
|
{
|
||||||
|
auto has_use_only = cv::gimpl::getCompileArg<cv::gapi::use_only>(args);
|
||||||
|
if (has_use_only)
|
||||||
|
return has_use_only.value().pkg;
|
||||||
|
|
||||||
static auto ocv_pkg =
|
static auto ocv_pkg =
|
||||||
#if !defined(GAPI_STANDALONE)
|
#if !defined(GAPI_STANDALONE)
|
||||||
combine(cv::gapi::core::cpu::kernels(),
|
combine(cv::gapi::core::cpu::kernels(),
|
||||||
cv::gapi::imgproc::cpu::kernels(),
|
cv::gapi::imgproc::cpu::kernels());
|
||||||
cv::unite_policy::KEEP);
|
|
||||||
#else
|
#else
|
||||||
cv::gapi::GKernelPackage();
|
cv::gapi::GKernelPackage();
|
||||||
#endif // !defined(GAPI_STANDALONE)
|
#endif // !defined(GAPI_STANDALONE)
|
||||||
auto user_pkg = cv::gimpl::getCompileArg<cv::gapi::GKernelPackage>(args);
|
auto user_pkg = cv::gimpl::getCompileArg<cv::gapi::GKernelPackage>(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<std::string> getGraphDumpDirectory(cv::GCompileArgs& args)
|
cv::util::optional<std::string> getGraphDumpDirectory(cv::GCompileArgs& args)
|
||||||
@ -87,7 +90,6 @@ cv::gimpl::GCompiler::GCompiler(const cv::GComputation &c,
|
|||||||
{
|
{
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
m_all_kernels = getKernelPackage(m_args);
|
m_all_kernels = getKernelPackage(m_args);
|
||||||
auto lookup_order = getCompileArg<gapi::GLookupOrder>(m_args).value_or(gapi::GLookupOrder());
|
|
||||||
auto dump_path = getGraphDumpDirectory(m_args);
|
auto dump_path = getGraphDumpDirectory(m_args);
|
||||||
|
|
||||||
m_e.addPassStage("init");
|
m_e.addPassStage("init");
|
||||||
@ -107,8 +109,7 @@ cv::gimpl::GCompiler::GCompiler(const cv::GComputation &c,
|
|||||||
|
|
||||||
m_e.addPassStage("kernels");
|
m_e.addPassStage("kernels");
|
||||||
m_e.addPass("kernels", "resolve_kernels", std::bind(passes::resolveKernels, _1,
|
m_e.addPass("kernels", "resolve_kernels", std::bind(passes::resolveKernels, _1,
|
||||||
std::ref(m_all_kernels), // NB: and not copied here
|
std::ref(m_all_kernels))); // NB: and not copied here
|
||||||
lookup_order));
|
|
||||||
m_e.addPass("kernels", "check_islands_content", passes::checkIslandsContent);
|
m_e.addPass("kernels", "check_islands_content", passes::checkIslandsContent);
|
||||||
|
|
||||||
m_e.addPassStage("meta");
|
m_e.addPassStage("meta");
|
||||||
|
@ -101,8 +101,7 @@ namespace
|
|||||||
// This pass, given the kernel package, selects a kernel implementation
|
// This pass, given the kernel package, selects a kernel implementation
|
||||||
// for every operation in the graph
|
// for every operation in the graph
|
||||||
void cv::gimpl::passes::resolveKernels(ade::passes::PassContext &ctx,
|
void cv::gimpl::passes::resolveKernels(ade::passes::PassContext &ctx,
|
||||||
const gapi::GKernelPackage &kernels,
|
const gapi::GKernelPackage &kernels)
|
||||||
const gapi::GLookupOrder &order)
|
|
||||||
{
|
{
|
||||||
std::unordered_set<cv::gapi::GBackend> active_backends;
|
std::unordered_set<cv::gapi::GBackend> active_backends;
|
||||||
|
|
||||||
@ -114,8 +113,7 @@ void cv::gimpl::passes::resolveKernels(ade::passes::PassContext &ctx,
|
|||||||
auto &op = gr.metadata(nh).get<Op>();
|
auto &op = gr.metadata(nh).get<Op>();
|
||||||
cv::gapi::GBackend selected_backend;
|
cv::gapi::GBackend selected_backend;
|
||||||
cv::GKernelImpl selected_impl;
|
cv::GKernelImpl selected_impl;
|
||||||
std::tie(selected_backend, selected_impl)
|
std::tie(selected_backend, selected_impl) = kernels.lookup(op.k.name);
|
||||||
= kernels.lookup(op.k.name, order);
|
|
||||||
|
|
||||||
selected_backend.priv().unpackKernel(ctx.graph, nh, selected_impl);
|
selected_backend.priv().unpackKernel(ctx.graph, nh, selected_impl);
|
||||||
op.backend = selected_backend;
|
op.backend = selected_backend;
|
||||||
|
@ -44,9 +44,8 @@ void storeResultingMeta(ade::passes::PassContext &ctx);
|
|||||||
void expandKernels(ade::passes::PassContext &ctx,
|
void expandKernels(ade::passes::PassContext &ctx,
|
||||||
const gapi::GKernelPackage& kernels);
|
const gapi::GKernelPackage& kernels);
|
||||||
|
|
||||||
void resolveKernels(ade::passes::PassContext &ctx,
|
void resolveKernels(ade::passes::PassContext &ctx,
|
||||||
const gapi::GKernelPackage &kernels,
|
const gapi::GKernelPackage &kernels);
|
||||||
const gapi::GLookupOrder &order);
|
|
||||||
|
|
||||||
void fuseIslands(ade::passes::PassContext &ctx);
|
void fuseIslands(ade::passes::PassContext &ctx);
|
||||||
void syncIslandTags(ade::passes::PassContext &ctx);
|
void syncIslandTags(ade::passes::PassContext &ctx);
|
||||||
|
@ -235,7 +235,7 @@ TEST(GCompoundKernel, ReplaceDefaultKernel)
|
|||||||
cv::GMat in1, in2;
|
cv::GMat in1, in2;
|
||||||
auto out = cv::gapi::add(in1, in2);
|
auto out = cv::gapi::add(in1, in2);
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundAddImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundAddImpl>();
|
||||||
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::GComputation comp(cv::GIn(in1, in2), cv::GOut(out));
|
||||||
cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
|
cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
|
||||||
in_mat2 = 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);
|
auto out = cv::gapi::addC(super, s);
|
||||||
|
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundDoubleAddCImpl>();
|
const auto custom_pkg = cv::gapi::kernels<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::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
|
||||||
|
|
||||||
cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
|
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);
|
auto out = cv::gapi::addC(super, s);
|
||||||
|
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundAddCImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundAddCImpl>();
|
||||||
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::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
|
||||||
|
|
||||||
cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
|
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);
|
auto out = cv::gapi::merge3(a2, b2, c2);
|
||||||
|
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundMergeWithSplitImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundMergeWithSplitImpl>();
|
||||||
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::GComputation comp(cv::GIn(in), cv::GOut(out));
|
||||||
|
|
||||||
cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC3), out_mat, ref_mat;
|
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);
|
auto out = GCompoundAddWithAddC::on(in1, in2, s);
|
||||||
|
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundAddWithAddCImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundAddWithAddCImpl>();
|
||||||
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::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
|
||||||
|
|
||||||
cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
|
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);
|
std::tie(out1, out2) = GCompoundSplitWithAdd::on(in);
|
||||||
|
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundSplitWithAddImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundSplitWithAddImpl>();
|
||||||
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::GComputation comp(cv::GIn(in), cv::GOut(out1, out2));
|
||||||
|
|
||||||
cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC3),
|
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);
|
std::tie(out1, out2) = GCompoundParallelAddC::on(in1, in2);
|
||||||
|
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundParallelAddCImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundParallelAddCImpl>();
|
||||||
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::GComputation comp(cv::GIn(in1, in2), cv::GOut(out1, out2));
|
||||||
|
|
||||||
cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1),
|
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));
|
auto out = cv::gapi::add(GCompoundAddWithAddC::on(in1, in2, s), cv::gapi::addC(in2, s));
|
||||||
|
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundAddWithAddCImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundAddWithAddCImpl>();
|
||||||
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::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
|
||||||
|
|
||||||
cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
|
cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
|
||||||
@ -428,7 +428,7 @@ TEST(GCompoundKernel, CompoundExpandedToCompound)
|
|||||||
GCompoundAddWithAddCImpl,
|
GCompoundAddWithAddCImpl,
|
||||||
GCompoundDoubleAddCImpl>();
|
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::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
|
||||||
|
|
||||||
cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
|
cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
|
||||||
@ -449,7 +449,7 @@ TEST(GCompoundKernel, MaxInArray)
|
|||||||
GDoubleArray in;
|
GDoubleArray in;
|
||||||
auto out = GCompoundMaxInArray::on(in);
|
auto out = GCompoundMaxInArray::on(in);
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundMaxInArrayImpl, GMaxInArrayImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundMaxInArrayImpl, GMaxInArrayImpl>();
|
||||||
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::GComputation comp(cv::GIn(in), cv::GOut(out));
|
||||||
std::vector<double> v = { 1, 5, -2, 3, 10, 2};
|
std::vector<double> v = { 1, 5, -2, 3, 10, 2};
|
||||||
cv::Scalar out_scl;
|
cv::Scalar out_scl;
|
||||||
@ -465,7 +465,7 @@ TEST(GCompoundKernel, NegateArray)
|
|||||||
GDoubleArray in;
|
GDoubleArray in;
|
||||||
GDoubleArray out = GCompoundNegateArray::on(in);
|
GDoubleArray out = GCompoundNegateArray::on(in);
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundNegateArrayImpl, GNegateArrayImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundNegateArrayImpl, GNegateArrayImpl>();
|
||||||
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::GComputation comp(cv::GIn(in), cv::GOut(out));
|
||||||
std::vector<double> in_v = {1, 5, -2, -10, 3};
|
std::vector<double> in_v = {1, 5, -2, -10, 3};
|
||||||
std::vector<double> out_v;
|
std::vector<double> out_v;
|
||||||
@ -483,7 +483,7 @@ TEST(GCompoundKernel, RightGArrayHandle)
|
|||||||
GDoubleArray a;
|
GDoubleArray a;
|
||||||
cv::GMat out = GCompoundGMatGArrayGMat::on(in[0], a, in[1]);
|
cv::GMat out = GCompoundGMatGArrayGMat::on(in[0], a, in[1]);
|
||||||
const auto custom_pkg = cv::gapi::kernels<GCompoundGMatGArrayGMatImpl, SetDiagKernelImpl>();
|
const auto custom_pkg = cv::gapi::kernels<GCompoundGMatGArrayGMatImpl, SetDiagKernelImpl>();
|
||||||
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));
|
cv::GComputation comp(cv::GIn(in[0], a, in[1]), cv::GOut(out));
|
||||||
std::vector<double> in_v(3, 1.0);
|
std::vector<double> in_v(3, 1.0);
|
||||||
cv::Mat in_mat1 = cv::Mat::eye(cv::Size(3, 3), CV_8UC1),
|
cv::Mat in_mat1 = cv::Mat::eye(cv::Size(3, 3), CV_8UC1),
|
||||||
|
@ -381,7 +381,7 @@ static auto fluidResizeTestPackage = [](int interpolation, cv::Size szIn, cv::Si
|
|||||||
}break;
|
}break;
|
||||||
default: CV_Assert(false);
|
default: CV_Assert(false);
|
||||||
}
|
}
|
||||||
return combine(pkg, fluidTestPackage, unite_policy::KEEP);
|
return combine(pkg, fluidTestPackage);
|
||||||
|
|
||||||
#undef RESIZE_SWITCH
|
#undef RESIZE_SWITCH
|
||||||
#undef RESIZE_CASE
|
#undef RESIZE_CASE
|
||||||
@ -743,7 +743,7 @@ TEST_P(NV12PlusResizeTest, Test)
|
|||||||
auto out = cv::gapi::resize(rgb, out_sz, 0, 0, interp);
|
auto out = cv::gapi::resize(rgb, out_sz, 0, 0, interp);
|
||||||
cv::GComputation c(cv::GIn(y, uv), cv::GOut(out));
|
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)
|
c.apply(cv::gin(y_mat, uv_mat), cv::gout(out_mat)
|
||||||
,cv::compile_args(pkg, cv::GFluidOutputRois{{to_own(roi)}}));
|
,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));
|
cv::GComputation c(cv::GIn(y, uv), cv::GOut(out));
|
||||||
|
|
||||||
auto pkg = cv::gapi::combine(cv::gapi::core::fluid::kernels(),
|
auto pkg = cv::gapi::combine(cv::gapi::core::fluid::kernels(),
|
||||||
fluidResizeTestPackage(interp, in_sz, out_sz, 4),
|
fluidResizeTestPackage(interp, in_sz, out_sz, 4));
|
||||||
cv::unite_policy::REPLACE);
|
|
||||||
|
|
||||||
c.apply(cv::gin(y_mat, uv_mat), cv::gout(out_mat)
|
c.apply(cv::gin(y_mat, uv_mat), cv::gout(out_mat)
|
||||||
,cv::compile_args(pkg, cv::GFluidOutputRois{{to_own(roi)}}));
|
,cv::compile_args(pkg, cv::GFluidOutputRois{{to_own(roi)}}));
|
||||||
|
@ -9,25 +9,126 @@
|
|||||||
#include "opencv2/gapi/cpu/gcpukernel.hpp"
|
#include "opencv2/gapi/cpu/gcpukernel.hpp"
|
||||||
#include "gapi_mock_kernels.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 opencv_test
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
G_TYPED_KERNEL(GClone, <GMat(GMat)>, "org.opencv.test.clone")
|
namespace I
|
||||||
{
|
{
|
||||||
static GMatDesc outMeta(GMatDesc in) { return in; }
|
G_TYPED_KERNEL(GClone, <GMat(GMat)>, "org.opencv.test.clone")
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
GAPI_OCV_KERNEL(GCloneImpl, GClone)
|
|
||||||
{
|
|
||||||
static void run(const cv::Mat& in, cv::Mat &out)
|
|
||||||
{
|
{
|
||||||
out = in.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
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
class HeteroGraph: public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HeteroGraph()
|
||||||
|
{
|
||||||
|
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<KernelTags> 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<KernelTags> HeteroGraph::kernel_calls;
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
TEST(KernelPackage, Create)
|
TEST(KernelPackage, Create)
|
||||||
{
|
{
|
||||||
@ -57,17 +158,6 @@ TEST(KernelPackage, IncludesAPI)
|
|||||||
EXPECT_FALSE(pkg.includesAPI<I::Qux>());
|
EXPECT_FALSE(pkg.includesAPI<I::Qux>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(KernelPackage, IncludesAPI_Overlapping)
|
|
||||||
{
|
|
||||||
namespace J = Jupiter;
|
|
||||||
namespace S = Saturn;
|
|
||||||
auto pkg = cv::gapi::kernels<J::Foo, J::Bar, S::Foo, S::Bar>();
|
|
||||||
EXPECT_TRUE (pkg.includesAPI<I::Foo>());
|
|
||||||
EXPECT_TRUE (pkg.includesAPI<I::Bar>());
|
|
||||||
EXPECT_FALSE(pkg.includesAPI<I::Baz>());
|
|
||||||
EXPECT_FALSE(pkg.includesAPI<I::Qux>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(KernelPackage, Include_Add)
|
TEST(KernelPackage, Include_Add)
|
||||||
{
|
{
|
||||||
namespace J = Jupiter;
|
namespace J = Jupiter;
|
||||||
@ -78,23 +168,6 @@ TEST(KernelPackage, Include_Add)
|
|||||||
EXPECT_TRUE(pkg.includes<J::Qux>());
|
EXPECT_TRUE(pkg.includes<J::Qux>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(KernelPackage, Include_KEEP)
|
|
||||||
{
|
|
||||||
namespace J = Jupiter;
|
|
||||||
namespace S = Saturn;
|
|
||||||
auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
|
||||||
EXPECT_FALSE(pkg.includes<S::Foo>());
|
|
||||||
EXPECT_FALSE(pkg.includes<S::Bar>());
|
|
||||||
|
|
||||||
pkg.include<S::Bar>(); // default (KEEP)
|
|
||||||
EXPECT_TRUE(pkg.includes<J::Bar>());
|
|
||||||
EXPECT_TRUE(pkg.includes<S::Bar>());
|
|
||||||
|
|
||||||
pkg.include<S::Foo>(cv::unite_policy::KEEP); // explicit (KEEP)
|
|
||||||
EXPECT_TRUE(pkg.includes<J::Foo>());
|
|
||||||
EXPECT_TRUE(pkg.includes<S::Foo>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(KernelPackage, Include_REPLACE)
|
TEST(KernelPackage, Include_REPLACE)
|
||||||
{
|
{
|
||||||
namespace J = Jupiter;
|
namespace J = Jupiter;
|
||||||
@ -102,7 +175,7 @@ TEST(KernelPackage, Include_REPLACE)
|
|||||||
auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
||||||
EXPECT_FALSE(pkg.includes<S::Bar>());
|
EXPECT_FALSE(pkg.includes<S::Bar>());
|
||||||
|
|
||||||
pkg.include<S::Bar>(cv::unite_policy::REPLACE);
|
pkg.include<S::Bar>();
|
||||||
EXPECT_FALSE(pkg.includes<J::Bar>());
|
EXPECT_FALSE(pkg.includes<J::Bar>());
|
||||||
EXPECT_TRUE(pkg.includes<S::Bar>());
|
EXPECT_TRUE(pkg.includes<S::Bar>());
|
||||||
}
|
}
|
||||||
@ -111,31 +184,27 @@ TEST(KernelPackage, RemoveBackend)
|
|||||||
{
|
{
|
||||||
namespace J = Jupiter;
|
namespace J = Jupiter;
|
||||||
namespace S = Saturn;
|
namespace S = Saturn;
|
||||||
auto pkg = cv::gapi::kernels<J::Foo, J::Bar, S::Foo>();
|
auto pkg = cv::gapi::kernels<J::Foo, J::Bar, S::Baz>();
|
||||||
EXPECT_TRUE(pkg.includes<J::Foo>());
|
EXPECT_TRUE(pkg.includes<J::Foo>());
|
||||||
EXPECT_TRUE(pkg.includes<J::Bar>());
|
EXPECT_TRUE(pkg.includes<J::Bar>());
|
||||||
EXPECT_TRUE(pkg.includes<S::Foo>());
|
|
||||||
|
|
||||||
pkg.remove(J::backend());
|
pkg.remove(J::backend());
|
||||||
EXPECT_FALSE(pkg.includes<J::Foo>());
|
EXPECT_FALSE(pkg.includes<J::Foo>());
|
||||||
EXPECT_FALSE(pkg.includes<J::Bar>());
|
EXPECT_FALSE(pkg.includes<J::Bar>());
|
||||||
EXPECT_TRUE(pkg.includes<S::Foo>());
|
EXPECT_TRUE(pkg.includes<S::Baz>());
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(KernelPackage, RemoveAPI)
|
TEST(KernelPackage, RemoveAPI)
|
||||||
{
|
{
|
||||||
namespace J = Jupiter;
|
namespace J = Jupiter;
|
||||||
namespace S = Saturn;
|
namespace S = Saturn;
|
||||||
auto pkg = cv::gapi::kernels<J::Foo, J::Bar, S::Foo, S::Bar>();
|
auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
||||||
EXPECT_TRUE(pkg.includes<J::Foo>());
|
EXPECT_TRUE(pkg.includes<J::Foo>());
|
||||||
EXPECT_TRUE(pkg.includes<J::Bar>());
|
EXPECT_TRUE(pkg.includes<J::Bar>());
|
||||||
EXPECT_TRUE(pkg.includes<S::Foo>());
|
|
||||||
|
|
||||||
pkg.remove<I::Foo>();
|
pkg.remove<I::Foo>();
|
||||||
EXPECT_TRUE(pkg.includes<J::Bar>());
|
EXPECT_TRUE(pkg.includes<J::Bar>());
|
||||||
EXPECT_TRUE(pkg.includes<S::Bar>());
|
|
||||||
EXPECT_FALSE(pkg.includes<J::Foo>());
|
EXPECT_FALSE(pkg.includes<J::Foo>());
|
||||||
EXPECT_FALSE(pkg.includes<S::Foo>());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(KernelPackage, CreateHetero)
|
TEST(KernelPackage, CreateHetero)
|
||||||
@ -177,7 +246,7 @@ TEST(KernelPackage, Combine_REPLACE_Full)
|
|||||||
namespace S = Saturn;
|
namespace S = Saturn;
|
||||||
auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
|
auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
|
||||||
auto s_pkg = cv::gapi::kernels<S::Foo, S::Bar, S::Baz>();
|
auto s_pkg = cv::gapi::kernels<S::Foo, S::Bar, S::Baz>();
|
||||||
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_EQ(3u, u_pkg.size());
|
||||||
EXPECT_FALSE(u_pkg.includes<J::Foo>());
|
EXPECT_FALSE(u_pkg.includes<J::Foo>());
|
||||||
@ -194,7 +263,7 @@ TEST(KernelPackage, Combine_REPLACE_Partial)
|
|||||||
namespace S = Saturn;
|
namespace S = Saturn;
|
||||||
auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
||||||
auto s_pkg = cv::gapi::kernels<S::Bar>();
|
auto s_pkg = cv::gapi::kernels<S::Bar>();
|
||||||
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_EQ(2u, u_pkg.size());
|
||||||
EXPECT_TRUE (u_pkg.includes<J::Foo>());
|
EXPECT_TRUE (u_pkg.includes<J::Foo>());
|
||||||
@ -208,38 +277,7 @@ TEST(KernelPackage, Combine_REPLACE_Append)
|
|||||||
namespace S = Saturn;
|
namespace S = Saturn;
|
||||||
auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
||||||
auto s_pkg = cv::gapi::kernels<S::Qux>();
|
auto s_pkg = cv::gapi::kernels<S::Qux>();
|
||||||
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_TRUE(u_pkg.includes<J::Foo>());
|
|
||||||
EXPECT_TRUE(u_pkg.includes<J::Bar>());
|
|
||||||
EXPECT_TRUE(u_pkg.includes<S::Qux>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(KernelPackage, Combine_KEEP_AllDups)
|
|
||||||
{
|
|
||||||
namespace J = Jupiter;
|
|
||||||
namespace S = Saturn;
|
|
||||||
auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
|
|
||||||
auto s_pkg = cv::gapi::kernels<S::Foo, S::Bar, S::Baz>();
|
|
||||||
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<J::Foo>());
|
|
||||||
EXPECT_TRUE(u_pkg.includes<J::Bar>());
|
|
||||||
EXPECT_TRUE(u_pkg.includes<J::Baz>());
|
|
||||||
EXPECT_TRUE(u_pkg.includes<S::Foo>());
|
|
||||||
EXPECT_TRUE(u_pkg.includes<S::Bar>());
|
|
||||||
EXPECT_TRUE(u_pkg.includes<S::Baz>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(KernelPackage, Combine_KEEP_Append_NoDups)
|
|
||||||
{
|
|
||||||
namespace J = Jupiter;
|
|
||||||
namespace S = Saturn;
|
|
||||||
auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
|
||||||
auto s_pkg = cv::gapi::kernels<S::Qux>();
|
|
||||||
auto u_pkg = cv::gapi::combine(j_pkg, s_pkg, cv::unite_policy::KEEP);
|
|
||||||
|
|
||||||
EXPECT_EQ(3u, u_pkg.size());
|
EXPECT_EQ(3u, u_pkg.size());
|
||||||
EXPECT_TRUE(u_pkg.includes<J::Foo>());
|
EXPECT_TRUE(u_pkg.includes<J::Foo>());
|
||||||
@ -252,7 +290,7 @@ TEST(KernelPackage, TestWithEmptyLHS)
|
|||||||
namespace J = Jupiter;
|
namespace J = Jupiter;
|
||||||
auto lhs = cv::gapi::kernels<>();
|
auto lhs = cv::gapi::kernels<>();
|
||||||
auto rhs = cv::gapi::kernels<J::Foo>();
|
auto rhs = cv::gapi::kernels<J::Foo>();
|
||||||
auto pkg = cv::gapi::combine(lhs, rhs, cv::unite_policy::KEEP);
|
auto pkg = cv::gapi::combine(lhs, rhs);
|
||||||
|
|
||||||
EXPECT_EQ(1u, pkg.size());
|
EXPECT_EQ(1u, pkg.size());
|
||||||
EXPECT_TRUE(pkg.includes<J::Foo>());
|
EXPECT_TRUE(pkg.includes<J::Foo>());
|
||||||
@ -263,22 +301,211 @@ TEST(KernelPackage, TestWithEmptyRHS)
|
|||||||
namespace J = Jupiter;
|
namespace J = Jupiter;
|
||||||
auto lhs = cv::gapi::kernels<J::Foo>();
|
auto lhs = cv::gapi::kernels<J::Foo>();
|
||||||
auto rhs = 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_EQ(1u, pkg.size());
|
||||||
EXPECT_TRUE(pkg.includes<J::Foo>());
|
EXPECT_TRUE(pkg.includes<J::Foo>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(KernelPackage, Return_Unique_Backends)
|
||||||
|
{
|
||||||
|
auto pkg = cv::gapi::kernels<cpu::GClone, fluid::BGR2Gray, fluid::GAdd>();
|
||||||
|
EXPECT_EQ(2u, pkg.backends().size());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(KernelPackage, Can_Use_Custom_Kernel)
|
TEST(KernelPackage, Can_Use_Custom_Kernel)
|
||||||
{
|
{
|
||||||
cv::GMat in[2];
|
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)});
|
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
|
||||||
|
|
||||||
auto pkg = cv::gapi::kernels<GCloneImpl>();
|
auto pkg = cv::gapi::kernels<cpu::GClone>();
|
||||||
|
|
||||||
EXPECT_NO_THROW(cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)).
|
EXPECT_NO_THROW(cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)).
|
||||||
compile({in_meta, in_meta}, cv::compile_args(pkg)));
|
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<cpu::GClone>();
|
||||||
|
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<fluid::GClone>();
|
||||||
|
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<cpu::GClone, cpu::BGR2Gray>();
|
||||||
|
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<cpu::GClone, fluid::BGR2Gray>();
|
||||||
|
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<cpu::GAdd, cpu::GClone, cpu::BGR2Gray>();
|
||||||
|
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<fluid::GAdd, fluid::GClone, fluid::BGR2Gray>();
|
||||||
|
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<cpu::GAdd, fluid::GClone, fluid::BGR2Gray>();
|
||||||
|
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<fluid::GClone, fluid::BGR2Gray>();
|
||||||
|
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<cpu::GAdd, fluid::BGR2Gray>();
|
||||||
|
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<cpu::GAdd, fluid::BGR2Gray>();
|
||||||
|
auto clone_pkg = cv::gapi::kernels<cpu::GClone>();
|
||||||
|
|
||||||
|
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
|
} // namespace opencv_test
|
||||||
|
@ -197,8 +197,7 @@ TEST(GComputationCompile, ReshapeRois)
|
|||||||
cv::randn(first_in_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));
|
cv::randn(first_in_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));
|
||||||
cv::Mat first_out_mat;
|
cv::Mat first_out_mat;
|
||||||
auto fluidKernels = cv::gapi::combine(gapi::imgproc::fluid::kernels(),
|
auto fluidKernels = cv::gapi::combine(gapi::imgproc::fluid::kernels(),
|
||||||
gapi::core::fluid::kernels(),
|
gapi::core::fluid::kernels());
|
||||||
cv::unite_policy::REPLACE);
|
|
||||||
cc.apply(first_in_mat, first_out_mat, cv::compile_args(fluidKernels));
|
cc.apply(first_in_mat, first_out_mat, cv::compile_args(fluidKernels));
|
||||||
auto first_comp = cc.priv().m_lastCompiled;
|
auto first_comp = cc.priv().m_lastCompiled;
|
||||||
|
|
||||||
|
@ -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<J::Foo, J::Bar, J::Baz,
|
|
||||||
S::Foo, S::Bar, S::Baz>();
|
|
||||||
|
|
||||||
EXPECT_NO_THROW (pkg.lookup<I::Foo>());
|
|
||||||
EXPECT_NO_THROW (pkg.lookup<I::Bar>());
|
|
||||||
EXPECT_NO_THROW (pkg.lookup<I::Baz>());
|
|
||||||
EXPECT_ANY_THROW(pkg.lookup<I::Qux>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Lookup, Only_Jupiter)
|
|
||||||
{
|
|
||||||
namespace J = Jupiter;
|
|
||||||
namespace S = Saturn;
|
|
||||||
const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz,
|
|
||||||
S::Foo, S::Bar, S::Baz>();
|
|
||||||
|
|
||||||
auto order = cv::gapi::lookup_order({J::backend()});
|
|
||||||
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Foo>(order));
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Bar>(order));
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Baz>(order));
|
|
||||||
EXPECT_ANY_THROW(pkg.lookup<I::Qux>(order));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Lookup, Only_Saturn)
|
|
||||||
{
|
|
||||||
namespace J = Jupiter;
|
|
||||||
namespace S = Saturn;
|
|
||||||
const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz,
|
|
||||||
S::Foo, S::Bar, S::Baz>();
|
|
||||||
|
|
||||||
auto order = cv::gapi::lookup_order({S::backend()});
|
|
||||||
|
|
||||||
EXPECT_EQ(S::backend(), pkg.lookup<I::Foo>(order));
|
|
||||||
EXPECT_EQ(S::backend(), pkg.lookup<I::Bar>(order));
|
|
||||||
EXPECT_EQ(S::backend(), pkg.lookup<I::Baz>(order));
|
|
||||||
EXPECT_ANY_THROW(pkg.lookup<I::Qux>(order));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Lookup, With_Order)
|
|
||||||
{
|
|
||||||
namespace J = Jupiter;
|
|
||||||
namespace S = Saturn;
|
|
||||||
const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz,
|
|
||||||
S::Foo, S::Bar, S::Baz>();
|
|
||||||
|
|
||||||
auto prefer_j = cv::gapi::lookup_order({J::backend(), S::backend()});
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Foo>(prefer_j));
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Bar>(prefer_j));
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Baz>(prefer_j));
|
|
||||||
EXPECT_ANY_THROW(pkg.lookup<I::Qux>(prefer_j));
|
|
||||||
|
|
||||||
auto prefer_s = cv::gapi::lookup_order({S::backend(), J::backend()});
|
|
||||||
EXPECT_EQ(S::backend(), pkg.lookup<I::Foo>(prefer_s));
|
|
||||||
EXPECT_EQ(S::backend(), pkg.lookup<I::Bar>(prefer_s));
|
|
||||||
EXPECT_EQ(S::backend(), pkg.lookup<I::Baz>(prefer_s));
|
|
||||||
EXPECT_ANY_THROW(pkg.lookup<I::Qux>(prefer_s));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Lookup, NoOverlap)
|
|
||||||
{
|
|
||||||
namespace J = Jupiter;
|
|
||||||
namespace S = Saturn;
|
|
||||||
const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, S::Baz, S::Qux>();
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Foo>());
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Bar>());
|
|
||||||
EXPECT_EQ(S::backend(), pkg.lookup<I::Baz>());
|
|
||||||
EXPECT_EQ(S::backend(), pkg.lookup<I::Qux>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Lookup, ExtraBackend)
|
|
||||||
{
|
|
||||||
namespace J = Jupiter;
|
|
||||||
namespace S = Saturn;
|
|
||||||
const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
|
|
||||||
|
|
||||||
// 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<I::Foo>(prefer_sj));
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Bar>(prefer_sj));
|
|
||||||
EXPECT_EQ(J::backend(), pkg.lookup<I::Baz>(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<I::Foo>(only_s));
|
|
||||||
EXPECT_ANY_THROW(pkg.lookup<I::Bar>(only_s));
|
|
||||||
EXPECT_ANY_THROW(pkg.lookup<I::Baz>(only_s));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace opencv_test
|
|
@ -65,8 +65,7 @@ int main()
|
|||||||
// Prepare the kernel package and run the graph
|
// Prepare the kernel package and run the graph
|
||||||
cv::gapi::GKernelPackage fluid_kernels = cv::gapi::combine // Define a custom kernel package:
|
cv::gapi::GKernelPackage fluid_kernels = cv::gapi::combine // Define a custom kernel package:
|
||||||
(cv::gapi::core::fluid::kernels(), // ...with Fluid Core kernels
|
(cv::gapi::core::fluid::kernels(), // ...with Fluid Core kernels
|
||||||
cv::gapi::imgproc::fluid::kernels(), // ...and Fluid ImgProc kernels
|
cv::gapi::imgproc::fluid::kernels()); // ...and Fluid ImgProc kernels
|
||||||
cv::unite_policy::KEEP);
|
|
||||||
//! [kernel_pkg]
|
//! [kernel_pkg]
|
||||||
//! [kernel_hotfix]
|
//! [kernel_hotfix]
|
||||||
fluid_kernels.remove<cv::gapi::imgproc::GBoxFilter>(); // Remove Fluid Box filter as unsuitable,
|
fluid_kernels.remove<cv::gapi::imgproc::GBoxFilter>(); // Remove Fluid Box filter as unsuitable,
|
||||||
|
Loading…
Reference in New Issue
Block a user