1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00

Merge pull request #18339 from rgarnov:rg/rmat_integration

[GAPI] RMat integration into the framework

* RMat integration

* Added initialization of input mat in GArray initialization tests

* Fixed klocwork warnings in RMat tests, changed argument order in EXPECT_EQ
This commit is contained in:
Ruslan Garnov
2020-10-04 21:57:41 +03:00
committed by GitHub
parent 199687a1c5
commit 5224d016e9
31 changed files with 659 additions and 229 deletions
+109 -15
View File
@@ -72,7 +72,7 @@ cv::gimpl::GExecutor::GExecutor(std::unique_ptr<ade::Graph> &&g_model)
const auto orig_data_nh
= m_gim.metadata(nh).get<DataSlot>().original_data_node;
// (1)
initResource(orig_data_nh);
initResource(nh, orig_data_nh);
m_slots.emplace_back(DataDesc{nh, orig_data_nh});
}
break;
@@ -84,7 +84,82 @@ cv::gimpl::GExecutor::GExecutor(std::unique_ptr<ade::Graph> &&g_model)
} // for(gim nodes)
}
void cv::gimpl::GExecutor::initResource(const ade::NodeHandle &orig_nh)
namespace cv {
namespace gimpl {
namespace magazine {
namespace {
void bindInArgExec(Mag& mag, const RcDesc &rc, const GRunArg &arg)
{
if (rc.shape != GShape::GMAT)
{
bindInArg(mag, rc, arg);
return;
}
auto& mag_rmat = mag.template slot<cv::RMat>()[rc.id];
switch (arg.index())
{
case GRunArg::index_of<Mat>() :
mag_rmat = make_rmat<RMatAdapter>(util::get<Mat>(arg)); break;
case GRunArg::index_of<cv::RMat>() :
mag_rmat = util::get<cv::RMat>(arg); break;
default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
}
}
void bindOutArgExec(Mag& mag, const RcDesc &rc, const GRunArgP &arg)
{
if (rc.shape != GShape::GMAT)
{
bindOutArg(mag, rc, arg);
return;
}
auto& mag_rmat = mag.template slot<cv::RMat>()[rc.id];
switch (arg.index())
{
case GRunArgP::index_of<Mat*>() :
mag_rmat = make_rmat<RMatAdapter>(*util::get<Mat*>(arg)); break;
case GRunArgP::index_of<cv::RMat*>() :
mag_rmat = *util::get<cv::RMat*>(arg); break;
default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
}
}
cv::GRunArgP getObjPtrExec(Mag& mag, const RcDesc &rc)
{
if (rc.shape != GShape::GMAT)
{
return getObjPtr(mag, rc);
}
return GRunArgP(&mag.template slot<cv::RMat>()[rc.id]);
}
void writeBackExec(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg)
{
if (rc.shape != GShape::GMAT)
{
writeBack(mag, rc, g_arg);
return;
}
auto checkOutArgData = [&](const uchar* out_arg_data) {
//simply check that memory was not reallocated, i.e.
//both Mat and View pointing to the same memory
auto mag_data = mag.template slot<cv::RMat>().at(rc.id).get<RMatAdapter>()->data();
GAPI_Assert((out_arg_data == mag_data) && " data for output parameters was reallocated ?");
};
switch (g_arg.index())
{
case GRunArgP::index_of<cv::Mat*>() : checkOutArgData(util::get<cv::Mat*>(g_arg)->data); break;
case GRunArgP::index_of<cv::RMat*>() : /* do nothing */ break;
default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
}
}
} // anonymous namespace
}}} // namespace cv::gimpl::magazine
void cv::gimpl::GExecutor::initResource(const ade::NodeHandle & nh, const ade::NodeHandle &orig_nh)
{
const Data &d = m_gm.metadata(orig_nh).get<Data>();
@@ -99,9 +174,19 @@ void cv::gimpl::GExecutor::initResource(const ade::NodeHandle &orig_nh)
{
case GShape::GMAT:
{
// Let island allocate it's outputs if it can,
// allocate cv::Mat and wrap it with RMat otherwise
GAPI_Assert(!nh->inNodes().empty());
const auto desc = util::get<cv::GMatDesc>(d.meta);
auto& mat = m_res.slot<cv::Mat>()[d.rc];
createMat(desc, mat);
auto& exec = m_gim.metadata(nh->inNodes().front()).get<IslandExec>().object;
auto& rmat = m_res.slot<cv::RMat>()[d.rc];
if (exec->allocatesOutputs()) {
rmat = exec->allocate(desc);
} else {
Mat mat;
createMat(desc, mat);
rmat = make_rmat<RMatAdapter>(mat);
}
}
break;
@@ -146,7 +231,7 @@ public:
class cv::gimpl::GExecutor::Output final: public cv::gimpl::GIslandExecutable::IOutput
{
cv::gimpl::Mag &mag;
virtual GRunArgP get(int idx) override { return magazine::getObjPtr(mag, desc()[idx]); }
virtual GRunArgP get(int idx) override { return magazine::getObjPtrExec(mag, desc()[idx]); }
virtual void post(GRunArgP&&) override { } // Do nothing here
virtual void post(EndOfStream&&) override {} // Do nothing here too
public:
@@ -186,11 +271,10 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
using cv::util::get;
const auto desc = get<cv::GMatDesc>(d.meta);
auto check_own_mat = [&desc, &args, &index]()
auto check_rmat = [&desc, &args, &index]()
{
auto& out_mat = *get<cv::Mat*>(args.outObjs.at(index));
GAPI_Assert(out_mat.data != nullptr &&
desc.canDescribe(out_mat));
auto& out_mat = *get<cv::RMat*>(args.outObjs.at(index));
GAPI_Assert(desc.canDescribe(out_mat));
};
#if !defined(GAPI_STANDALONE)
@@ -202,15 +286,25 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
auto& out_mat = *get<cv::Mat*>(args.outObjs.at(index));
createMat(desc, out_mat);
}
// In the case of own::Mat never reallocated, checked to perfectly fit required meta
// In the case of RMat check to fit required meta
else
{
check_own_mat();
check_rmat();
}
#else
// Building standalone - output buffer should always exist,
// and _exact_ match our inferred metadata
check_own_mat();
if (cv::util::holds_alternative<cv::Mat*>(args.outObjs.at(index)))
{
auto& out_mat = *get<cv::Mat*>(args.outObjs.at(index));
GAPI_Assert(out_mat.data != nullptr &&
desc.canDescribe(out_mat));
}
// In the case of RMat check to fit required meta
else
{
check_rmat();
}
#endif // !defined(GAPI_STANDALONE)
}
}
@@ -218,12 +312,12 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
for (auto it : ade::util::zip(ade::util::toRange(proto.inputs),
ade::util::toRange(args.inObjs)))
{
magazine::bindInArg(m_res, std::get<0>(it), std::get<1>(it));
magazine::bindInArgExec(m_res, std::get<0>(it), std::get<1>(it));
}
for (auto it : ade::util::zip(ade::util::toRange(proto.outputs),
ade::util::toRange(args.outObjs)))
{
magazine::bindOutArg(m_res, std::get<0>(it), std::get<1>(it));
magazine::bindOutArgExec(m_res, std::get<0>(it), std::get<1>(it));
}
// Reset internal data
@@ -246,7 +340,7 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
for (auto it : ade::util::zip(ade::util::toRange(proto.outputs),
ade::util::toRange(args.outObjs)))
{
magazine::writeBack(m_res, std::get<0>(it), std::get<1>(it));
magazine::writeBackExec(m_res, std::get<0>(it), std::get<1>(it));
}
}
+2 -3
View File
@@ -54,6 +54,7 @@ namespace gimpl {
class GExecutor
{
protected:
Mag m_res;
std::unique_ptr<ade::Graph> m_orig_graph;
std::shared_ptr<ade::Graph> m_island_graph;
@@ -80,9 +81,7 @@ protected:
class Input;
class Output;
Mag m_res;
void initResource(const ade::NodeHandle &orig_nh); // FIXME: shouldn't it be RcDesc?
void initResource(const ade::NodeHandle &nh, const ade::NodeHandle &orig_nh); // FIXME: shouldn't it be RcDesc?
public:
explicit GExecutor(std::unique_ptr<ade::Graph> &&g_model);
@@ -109,7 +109,13 @@ void sync_data(cv::GRunArgs &results, cv::GRunArgsP &outputs)
switch (out_obj.index())
{
case T::index_of<cv::Mat*>():
*cv::util::get<cv::Mat*>(out_obj) = std::move(cv::util::get<cv::Mat>(res_obj));
{
auto out_mat_p = cv::util::get<cv::Mat*>(out_obj);
auto view = cv::util::get<cv::RMat>(res_obj).access(cv::RMat::Access::R);
*out_mat_p = cv::gimpl::asMat(view).clone();
} break;
case T::index_of<cv::RMat*>():
*cv::util::get<cv::RMat*>(out_obj) = std::move(cv::util::get<cv::RMat>(res_obj));
break;
case T::index_of<cv::Scalar*>():
*cv::util::get<cv::Scalar*>(out_obj) = std::move(cv::util::get<cv::Scalar>(res_obj));
@@ -408,6 +414,7 @@ class StreamingOutput final: public cv::gimpl::GIslandExecutable::IOutput
// These objects are owned externally
const cv::GMetaArgs &m_metas;
std::vector< std::vector<Q*> > &m_out_queues;
std::shared_ptr<cv::gimpl::GIslandExecutable> m_island;
// Allocate a new data object for output under idx
// Prepare this object for posting
@@ -430,10 +437,19 @@ class StreamingOutput final: public cv::gimpl::GIslandExecutable::IOutput
// FIXME: This is absolutely ugly but seem to work perfectly for its purpose.
case cv::GShape::GMAT:
{
MatType newMat;
cv::gimpl::createMat(cv::util::get<cv::GMatDesc>(m_metas[idx]), newMat);
out_arg = cv::GRunArg(std::move(newMat));
ret_val = cv::GRunArgP(&cv::util::get<MatType>(out_arg));
auto desc = cv::util::get<cv::GMatDesc>(m_metas[idx]);
if (m_island->allocatesOutputs())
{
out_arg = cv::GRunArg(m_island->allocate(desc));
}
else
{
MatType newMat;
cv::gimpl::createMat(desc, newMat);
auto rmat = cv::make_rmat<cv::gimpl::RMatAdapter>(newMat);
out_arg = cv::GRunArg(std::move(rmat));
}
ret_val = cv::GRunArgP(&cv::util::get<cv::RMat>(out_arg));
}
break;
case cv::GShape::GSCALAR:
@@ -538,9 +554,11 @@ class StreamingOutput final: public cv::gimpl::GIslandExecutable::IOutput
public:
explicit StreamingOutput(const cv::GMetaArgs &metas,
std::vector< std::vector<Q*> > &out_queues,
const std::vector<cv::gimpl::RcDesc> &out_descs)
const std::vector<cv::gimpl::RcDesc> &out_descs,
std::shared_ptr<cv::gimpl::GIslandExecutable> island)
: m_metas(metas)
, m_out_queues(out_queues)
, m_island(island)
{
set(out_descs);
m_postings.resize(out_descs.size());
@@ -573,7 +591,7 @@ void islandActorThread(std::vector<cv::gimpl::RcDesc> in_rcs, //
GAPI_Assert(out_queues.size() == out_metas.size());
QueueReader qr;
StreamingInput input(qr, in_queues, in_constants, in_rcs);
StreamingOutput output(out_metas, out_queues, out_rcs);
StreamingOutput output(out_metas, out_queues, out_rcs, island);
while (!output.done())
{
island->run(input, output);