mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Merge pull request #16213 from TolyaTalamanov:at/lambdas-for-kernels
G-API: Using functors as kernel implementation * Implement ability to create kernel impls from functors * Clean up * Replace make_ocv_functor to ocv_kernel * Clean up * Replace GCPUFunctor -> GOCVFunctor * Move GOCVFunctor to cv::gapi::cpu namespace * Implement override for rvalue and lvalue cases * Fix comments to review * Remove GAPI_EXPORT for template functions * Fix indentation
This commit is contained in:
committed by
GitHub
parent
f3237fdc6e
commit
a6ef9b4584
@@ -72,6 +72,17 @@ namespace cpu
|
||||
*/
|
||||
GAPI_EXPORTS cv::gapi::GBackend backend();
|
||||
/** @} */
|
||||
|
||||
class GOCVFunctor;
|
||||
|
||||
//! @cond IGNORED
|
||||
template<typename K, typename Callable>
|
||||
GOCVFunctor ocv_kernel(const Callable& c);
|
||||
|
||||
template<typename K, typename Callable>
|
||||
GOCVFunctor ocv_kernel(Callable& c);
|
||||
//! @endcond
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace gapi
|
||||
|
||||
@@ -279,6 +290,12 @@ struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
|
||||
Impl::run(std::forward<Inputs>(ins)..., outs...);
|
||||
postprocess(outs...);
|
||||
}
|
||||
|
||||
template<typename... Outputs>
|
||||
static void call(Impl& impl, Inputs&&... ins, Outputs&&... outs)
|
||||
{
|
||||
impl(std::forward<Inputs>(ins)..., outs...);
|
||||
}
|
||||
};
|
||||
|
||||
template<int... IIs, int... OIs>
|
||||
@@ -290,7 +307,17 @@ struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
|
||||
//them to parameters of ad-hoc function
|
||||
//Convert own::Scalar to cv::Scalar before call kernel and run kernel
|
||||
//convert cv::Scalar to own::Scalar after call kernel and write back results
|
||||
call_and_postprocess<decltype(get_in<Ins>::get(ctx, IIs))...>::call(get_in<Ins>::get(ctx, IIs)..., get_out<Outs>::get(ctx, OIs)...);
|
||||
call_and_postprocess<decltype(get_in<Ins>::get(ctx, IIs))...>
|
||||
::call(get_in<Ins>::get(ctx, IIs)...,
|
||||
get_out<Outs>::get(ctx, OIs)...);
|
||||
}
|
||||
|
||||
template<int... IIs, int... OIs>
|
||||
static void call_impl(cv::GCPUContext &ctx, Impl& impl, detail::Seq<IIs...>, detail::Seq<OIs...>)
|
||||
{
|
||||
call_and_postprocess<decltype(cv::detail::get_in<Ins>::get(ctx, IIs))...>
|
||||
::call(impl, cv::detail::get_in<Ins>::get(ctx, IIs)...,
|
||||
cv::detail::get_out<Outs>::get(ctx, OIs)...);
|
||||
}
|
||||
|
||||
static void call(GCPUContext &ctx)
|
||||
@@ -299,6 +326,16 @@ struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
|
||||
typename detail::MkSeq<sizeof...(Ins)>::type(),
|
||||
typename detail::MkSeq<sizeof...(Outs)>::type());
|
||||
}
|
||||
|
||||
// NB: Same as call but calling the object
|
||||
// This necessary for kernel implementations that have a state
|
||||
// and are represented as an object
|
||||
static void callFunctor(cv::GCPUContext &ctx, Impl& impl)
|
||||
{
|
||||
call_impl(ctx, impl,
|
||||
typename detail::MkSeq<sizeof...(Ins)>::type(),
|
||||
typename detail::MkSeq<sizeof...(Outs)>::type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@@ -318,6 +355,39 @@ public:
|
||||
|
||||
#define GAPI_OCV_KERNEL(Name, API) struct Name: public cv::GCPUKernelImpl<Name, API>
|
||||
|
||||
class gapi::cpu::GOCVFunctor : public gapi::GFunctor
|
||||
{
|
||||
public:
|
||||
using Impl = std::function<void(GCPUContext &)>;
|
||||
|
||||
GOCVFunctor(const char* id, const Impl& impl)
|
||||
: gapi::GFunctor(id), impl_{GCPUKernel(impl)}
|
||||
{
|
||||
}
|
||||
|
||||
GKernelImpl impl() const override { return impl_; }
|
||||
gapi::GBackend backend() const override { return gapi::cpu::backend(); }
|
||||
|
||||
private:
|
||||
GKernelImpl impl_;
|
||||
};
|
||||
|
||||
//! @cond IGNORED
|
||||
template<typename K, typename Callable>
|
||||
gapi::cpu::GOCVFunctor gapi::cpu::ocv_kernel(Callable& c)
|
||||
{
|
||||
using P = detail::OCVCallHelper<Callable, typename K::InArgs, typename K::OutArgs>;
|
||||
return GOCVFunctor(K::id(), std::bind(&P::callFunctor, std::placeholders::_1, std::ref(c)));
|
||||
}
|
||||
|
||||
template<typename K, typename Callable>
|
||||
gapi::cpu::GOCVFunctor gapi::cpu::ocv_kernel(const Callable& c)
|
||||
{
|
||||
using P = detail::OCVCallHelper<Callable, typename K::InArgs, typename K::OutArgs>;
|
||||
return GOCVFunctor(K::id(), std::bind(&P::callFunctor, std::placeholders::_1, c));
|
||||
}
|
||||
//! @endcond
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_GAPI_GCPUKERNEL_HPP
|
||||
|
||||
@@ -383,6 +383,20 @@ namespace std
|
||||
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
class GFunctor
|
||||
{
|
||||
public:
|
||||
virtual cv::GKernelImpl impl() const = 0;
|
||||
virtual cv::gapi::GBackend backend() const = 0;
|
||||
const char* id() const { return m_id; }
|
||||
|
||||
virtual ~GFunctor() = default;
|
||||
protected:
|
||||
GFunctor(const char* id) : m_id(id) { };
|
||||
private:
|
||||
const char* m_id;
|
||||
};
|
||||
|
||||
/** \addtogroup gapi_compile_args
|
||||
* @{
|
||||
*/
|
||||
@@ -460,6 +474,10 @@ namespace gapi {
|
||||
}
|
||||
|
||||
public:
|
||||
void include(const GFunctor& functor)
|
||||
{
|
||||
m_id_kernels[functor.id()] = std::make_pair(functor.backend(), functor.impl());
|
||||
}
|
||||
/**
|
||||
* @brief Returns total number of kernels
|
||||
* in the package (across all backends included)
|
||||
@@ -618,6 +636,15 @@ namespace gapi {
|
||||
return pkg;
|
||||
};
|
||||
|
||||
template<typename... FF>
|
||||
GKernelPackage kernels(FF&... functors)
|
||||
{
|
||||
GKernelPackage pkg;
|
||||
int unused[] = { 0, (pkg.include(functors), 0)... };
|
||||
cv::util::suppress_unused_warning(unused);
|
||||
return pkg;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
// FYI - this function is already commented above
|
||||
|
||||
Reference in New Issue
Block a user