Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / fluid / modules / gapi / test / internal / gapi_int_island_fusion_tests.cpp
1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 //
5 // Copyright (C) 2018-2019 Intel Corporation
6
7
8 #include "test_precomp.hpp"
9 #include "compiler/transactions.hpp"
10
11 #include "gapi_mock_kernels.hpp"
12
13 #include "compiler/gmodel.hpp"
14 #include "compiler/gislandmodel.hpp"
15 #include "compiler/gcompiler.hpp"
16
17 namespace opencv_test
18 {
19
20 TEST(IslandFusion, TwoOps_OneIsland)
21 {
22     namespace J = Jupiter; // see mock_kernels.cpp
23
24     // Define a computation:
25     //
26     //    (in) -> J::Foo1 -> (tmp0) -> J::Foo2 -> (out)
27     //          :                               :
28     //          :          "island0"            :
29     //          :<----------------------------->:
30
31     cv::GMat in;
32     cv::GMat tmp0 = I::Foo::on(in);
33     cv::GMat out  = I::Foo::on(tmp0);
34     cv::GComputation cc(in, out);
35
36     // Prepare compilation parameters manually
37     const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
38     const auto pkg     = cv::gapi::kernels<J::Foo>();
39
40     // Directly instantiate G-API graph compiler and run partial compilation
41     cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
42     cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
43     compiler.runPasses(*graph);
44
45     // Inspect the graph and verify the islands configuration
46     cv::gimpl::GModel::ConstGraph gm(*graph);
47
48     auto in_nh  = cv::gimpl::GModel::dataNodeOf(gm, in);
49     auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
50     auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
51
52     // in/out mats shouldn't be assigned to any Island
53     EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
54     EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
55
56     // Since tmp is surrounded by two J kernels, tmp should be assigned
57     // to island J
58     EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
59 }
60
61 TEST(IslandFusion, TwoOps_TwoIslands)
62 {
63     namespace J = Jupiter; // see mock_kernels.cpp
64     namespace S = Saturn;  // see mock_kernels.cpp
65
66     // Define a computation:
67     //
68     //    (in) -> J::Foo --> (tmp0) -> S::Bar --> (out)
69     //          :          :        ->          :
70     //          :          :         :          :
71     //          :<-------->:         :<-------->:
72
73     cv::GMat in;
74     cv::GMat tmp0 = I::Foo::on(in);
75     cv::GMat out  = I::Bar::on(tmp0, tmp0);
76     cv::GComputation cc(in, out);
77
78     // Prepare compilation parameters manually
79     const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
80     const auto pkg     = cv::gapi::kernels<J::Foo, S::Bar>();
81
82     // Directly instantiate G-API graph compiler and run partial compilation
83     cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
84     cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
85     compiler.runPasses(*graph);
86
87     // Inspect the graph and verify the islands configuration
88     cv::gimpl::GModel::ConstGraph gm(*graph);
89
90     auto in_nh  = cv::gimpl::GModel::dataNodeOf(gm, in);
91     auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
92     auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
93
94     // in/tmp/out mats shouldn't be assigned to any Island
95     EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
96     EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
97     EXPECT_FALSE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
98
99     auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
100     cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
101
102     // There should be two islands in the GIslandModel
103     const auto is_island = [&](ade::NodeHandle nh) {
104         return (cv::gimpl::NodeKind::ISLAND
105                 == gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
106     };
107     const std::size_t num_isl = std::count_if(gim.nodes().begin(),
108                                               gim.nodes().end(),
109                                               is_island);
110     EXPECT_EQ(2u, num_isl);
111
112     auto isl_foo_nh  = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
113     auto isl_bar_nh  = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
114     ASSERT_NE(nullptr, isl_foo_nh);
115     ASSERT_NE(nullptr, isl_bar_nh);
116
117     // Islands should be different
118     auto isl_foo_obj = gim.metadata(isl_foo_nh).get<cv::gimpl::FusedIsland>().object;
119     auto isl_bar_obj = gim.metadata(isl_bar_nh).get<cv::gimpl::FusedIsland>().object;
120     EXPECT_FALSE(isl_foo_obj == isl_bar_obj);
121 }
122
123 TEST(IslandFusion, ConsumerHasTwoInputs)
124 {
125     namespace J = Jupiter; // see mock_kernels.cpp
126
127     // Define a computation:     island
128     //            ............................
129     //    (in0) ->:J::Foo -> (tmp) -> S::Bar :--> (out)
130     //            :....................^.....:
131     //                                 |
132     //    (in1) -----------------------`
133     //
134
135     // Check that island is build correctly, when consumer has two inputs
136
137     GMat in[2];
138     GMat tmp = I::Foo::on(in[0]);
139     GMat out = I::Bar::on(tmp, in[1]);
140
141     cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
142
143     // Prepare compilation parameters manually
144     cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)}),
145                               GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)})};
146     const auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
147
148     // Directly instantiate G-API graph compiler and run partial compilation
149     cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
150     cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
151     compiler.runPasses(*graph);
152
153     cv::gimpl::GModel::ConstGraph gm(*graph);
154
155     auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
156     auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
157     auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
158     auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
159
160     EXPECT_FALSE(gm.metadata(in0_nh ).contains<cv::gimpl::Island>());
161     EXPECT_FALSE(gm.metadata(in1_nh ).contains<cv::gimpl::Island>());
162     EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
163     EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
164
165     auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
166     cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
167
168     const auto is_island = [&](ade::NodeHandle nh) {
169         return (cv::gimpl::NodeKind::ISLAND
170                 == gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
171     };
172     const std::size_t num_isl = std::count_if(gim.nodes().begin(),
173                                               gim.nodes().end(),
174                                               is_island);
175     EXPECT_EQ(1u, num_isl);
176
177     auto isl_nh  = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
178     auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
179
180     EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp_nh));
181
182     EXPECT_EQ(2u, static_cast<std::size_t>(isl_nh->inNodes().size()));
183     EXPECT_EQ(1u, static_cast<std::size_t>(isl_nh->outNodes().size()));
184 }
185
186 TEST(IslandFusion, DataNodeUsedDifferentBackend)
187 {
188     // Define a computation:
189     //
190     //           internal isl            isl0
191     //             ...........................
192     //    (in1) -> :J::Foo--> (tmp) -> J::Foo: --> (out0)
193     //             :............|............:
194     //                          |     ........
195     //                          `---->:S::Baz: --> (out1)
196     //                                :......:
197
198     // Check that the node was not dropped out of the island
199     // because it is used by the kernel from another backend
200
201     namespace J = Jupiter;
202     namespace S = Saturn;
203
204     cv::GMat in, tmp, out0;
205     cv::GScalar out1;
206     tmp  = I::Foo::on(in);
207     out0 = I::Foo::on(tmp);
208     out1 = I::Baz::on(tmp);
209
210     cv::GComputation cc(cv::GIn(in), cv::GOut(out0, out1));
211
212     // Prepare compilation parameters manually
213     const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
214     const auto pkg     = cv::gapi::kernels<J::Foo, S::Baz>();
215
216     // Directly instantiate G-API graph compiler and run partial compilation
217     cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
218     cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
219     compiler.runPasses(*graph);
220
221     // Inspect the graph and verify the islands configuration
222     cv::gimpl::GModel::ConstGraph gm(*graph);
223
224     auto in_nh   = cv::gimpl::GModel::dataNodeOf(gm, in);
225     auto tmp_nh  = cv::gimpl::GModel::dataNodeOf(gm, tmp);
226     auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out0);
227     auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out1);
228
229     EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
230
231     auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
232     cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
233
234     auto isl_nh  = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
235     auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
236
237     EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp_nh));
238
239     EXPECT_EQ(2u, static_cast<std::size_t>(isl_nh->outNodes().size()));
240     EXPECT_EQ(7u, static_cast<std::size_t>(gm.nodes().size()));
241     EXPECT_EQ(6u, static_cast<std::size_t>(gim.nodes().size()));
242 }
243
244 TEST(IslandFusion, LoopBetweenDifferentBackends)
245 {
246     // Define a computation:
247     //
248     //
249     //            .............................
250     //    (in) -> :J::Baz -> (tmp0) -> J::Quux: -> (out0)
251     //      |     :............|..........^....
252     //      |     ........     |          |         ........
253     //      `---->:S::Foo:     `----------|-------->:S::Qux:-> (out1)
254     //            :....|.:                |         :....^.:
255     //                 |                  |              |
256     //                 `-------------- (tmp1) -----------`
257
258     // Kernels S::Foo and S::Qux cannot merge, because there will be a cycle between islands
259
260     namespace J = Jupiter;
261     namespace S = Saturn;
262
263     cv::GScalar tmp0;
264     cv::GMat in, tmp1, out0, out1;
265
266     tmp0 = I::Baz::on(in);
267     tmp1 = I::Foo::on(in);
268     out1 = I::Qux::on(tmp1, tmp0);
269     out0 = I::Quux::on(tmp0, tmp1);
270
271     cv::GComputation cc(cv::GIn(in), cv::GOut(out1, out0));
272
273     // Prepare compilation parameters manually
274     const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
275     const auto pkg     = cv::gapi::kernels<J::Baz, J::Quux, S::Foo, S::Qux>();
276
277     // Directly instantiate G-API graph compiler and run partial compilation
278     cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
279     cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
280     compiler.runPasses(*graph);
281
282     cv::gimpl::GModel::ConstGraph gm(*graph);
283     auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
284     cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
285
286     auto in_nh   = cv::gimpl::GModel::dataNodeOf(gm, in);
287     auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
288     auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp1);
289     auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out0);
290     auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out1);
291
292     EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
293     EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
294     EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
295     // The node does not belong to the island so as not to form a cycle
296     EXPECT_FALSE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
297
298     EXPECT_TRUE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
299
300     // There should be three islands in the GIslandModel
301     const auto is_island = [&](ade::NodeHandle nh) {
302         return (cv::gimpl::NodeKind::ISLAND
303                 == gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
304     };
305     const std::size_t num_isl = std::count_if(gim.nodes().begin(),
306                                               gim.nodes().end(),
307                                               is_island);
308     EXPECT_EQ(3u, num_isl);
309 }
310
311 TEST(IslandsFusion, PartionOverlapUserIsland)
312 {
313     // Define a computation:
314     //
315     //           internal isl            isl0
316     //             ........            ........
317     //    (in0) -> :J::Foo:--> (tmp) ->:S::Bar: --> (out)
318     //             :......:            :......:
319     //                                    ^
320     //                                    |
321     //    (in1) --------------------------`
322
323     // Check that internal islands does't overlap user island
324
325     namespace J = Jupiter;
326     namespace S = Saturn;
327
328     GMat in[2];
329     GMat tmp = I::Foo::on(in[0]);
330     GMat out = I::Bar::on(tmp, in[1]);
331
332     cv::gapi::island("isl0", cv::GIn(tmp, in[1]), cv::GOut(out));
333     cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
334
335     // Prepare compilation parameters manually
336     cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)}),
337                               GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)})};
338     const auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
339
340     // Directly instantiate G-API graph compiler and run partial compilation
341     cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
342     cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
343     compiler.runPasses(*graph);
344
345     cv::gimpl::GModel::ConstGraph gm(*graph);
346     auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
347     cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
348
349     auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
350     auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
351     auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
352     auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
353
354     auto foo_nh  = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
355     auto foo_obj = gim.metadata(foo_nh).get<cv::gimpl::FusedIsland>().object;
356
357     auto bar_nh  = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
358     auto bar_obj = gim.metadata(bar_nh).get<cv::gimpl::FusedIsland>().object;
359
360     EXPECT_FALSE(gm.metadata(in0_nh ).contains<cv::gimpl::Island>());
361     EXPECT_FALSE(gm.metadata(in1_nh ).contains<cv::gimpl::Island>());
362     EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
363     EXPECT_FALSE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
364     EXPECT_FALSE(foo_obj->is_user_specified());
365     EXPECT_TRUE(bar_obj->is_user_specified());
366 }
367
368 TEST(IslandsFusion, DISABLED_IslandContainsDifferentBackends)
369 {
370     // Define a computation:
371     //
372     //                       isl0
373     //             ............................
374     //    (in0) -> :J::Foo:--> (tmp) -> S::Bar: --> (out)
375     //             :..........................:
376     //                                    ^
377     //                                    |
378     //    (in1) --------------------------`
379
380     // Try create island contains different backends
381
382     namespace J = Jupiter;
383     namespace S = Saturn;
384
385     GMat in[2];
386     GMat tmp = I::Foo::on(in[0]);
387     GMat out = I::Bar::on(tmp, in[1]);
388
389     cv::gapi::island("isl0", cv::GIn(in[0], in[1]), cv::GOut(out));
390     cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
391
392     // Prepare compilation parameters manually
393     cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)}),
394                               GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)})};
395     const auto pkg = cv::gapi::kernels<J::Foo, S::Bar>();
396
397     // Directly instantiate G-API graph compiler and run partial compilation
398     cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
399     cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
400     EXPECT_ANY_THROW(compiler.runPasses(*graph));
401 }
402
403 TEST(IslandFusion, WithLoop)
404 {
405     namespace J = Jupiter; // see mock_kernels.cpp
406
407     // Define a computation:
408     //
409     //    (in) -> J::Foo --> (tmp0) -> J::Foo --> (tmp1) -> J::Qux -> (out)
410     //                            :                        ^
411     //                            '--> J::Baz --> (scl0) --'
412     //
413     // The whole thing should be merged to a single island
414     // There's a cycle warning if Foo/Foo/Qux are merged first
415     // Then this island both produces data for Baz and consumes data
416     // from Baz. This is a cycle and it should be avoided by the merging code.
417     //
418     cv::GMat    in;
419     cv::GMat    tmp0 = I::Foo::on(in);
420     cv::GMat    tmp1 = I::Foo::on(tmp0);
421     cv::GScalar scl0 = I::Baz::on(tmp0);
422     cv::GMat    out  = I::Qux::on(tmp1, scl0);
423     cv::GComputation cc(in, out);
424
425     // Prepare compilation parameters manually
426     const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
427     const auto pkg     = cv::gapi::kernels<J::Foo, J::Baz, J::Qux>();
428
429     // Directly instantiate G-API graph compiler and run partial compilation
430     cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
431     cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
432     compiler.runPasses(*graph);
433
434     // Inspect the graph and verify the islands configuration
435     cv::gimpl::GModel::ConstGraph gm(*graph);
436
437     auto in_nh   = cv::gimpl::GModel::dataNodeOf(gm, in);
438     auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
439     auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp1);
440     auto scl0_nh = cv::gimpl::GModel::dataNodeOf(gm, scl0);
441     auto out_nh  = cv::gimpl::GModel::dataNodeOf(gm, out);
442
443     // in/out mats shouldn't be assigned to any Island
444     EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
445     EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
446
447     // tmp0/tmp1/scl should be assigned to island
448     EXPECT_TRUE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
449     EXPECT_TRUE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
450     EXPECT_TRUE(gm.metadata(scl0_nh).contains<cv::gimpl::Island>());
451
452     // Check that there's a single island object and it contains all
453     // that data object handles
454
455     cv::gimpl::GModel::ConstGraph cg(*graph);
456     auto isl_model = cg.metadata().get<cv::gimpl::IslandModel>().model;
457     cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
458
459     const auto is_island = [&](ade::NodeHandle nh) {
460         return (cv::gimpl::NodeKind::ISLAND
461                 == gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
462     };
463     const std::size_t num_isl = std::count_if(gim.nodes().begin(),
464                                               gim.nodes().end(),
465                                               is_island);
466     EXPECT_EQ(1u, num_isl);
467
468     auto isl_nh  = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
469     auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
470     EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp0_nh));
471     EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp1_nh));
472     EXPECT_TRUE(ade::util::contains(isl_obj->contents(), scl0_nh));
473 }
474
475 TEST(IslandFusion, Regression_ShouldFuseAll)
476 {
477     // Initially the merge procedure didn't work as expected and
478     // stopped fusion even if it could be continued (e.g. full
479     // GModel graph could be fused into a single GIsland node).
480     // Example of this is custom RGB 2 YUV pipeline as shown below:
481
482     cv::GMat r, g, b;
483     cv::GMat y = 0.299f*r + 0.587f*g + 0.114f*b;
484     cv::GMat u = 0.492f*(b - y);
485     cv::GMat v = 0.877f*(r - y);
486
487     cv::GComputation customCvt({r, g, b}, {y, u, v});
488
489     const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
490
491     // Directly instantiate G-API graph compiler and run partial compilation
492     cv::gimpl::GCompiler compiler(customCvt, {in_meta,in_meta,in_meta}, cv::compile_args());
493     cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
494     compiler.runPasses(*graph);
495
496     cv::gimpl::GModel::ConstGraph cg(*graph);
497     auto isl_model = cg.metadata().get<cv::gimpl::IslandModel>().model;
498     cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
499
500     std::vector<ade::NodeHandle> data_nhs;
501     std::vector<ade::NodeHandle> isl_nhs;
502     for (auto &&nh : gim.nodes())
503     {
504         if (gim.metadata(nh).contains<cv::gimpl::FusedIsland>())
505             isl_nhs.push_back(std::move(nh));
506         else if (gim.metadata(nh).contains<cv::gimpl::DataSlot>())
507             data_nhs.push_back(std::move(nh));
508         else FAIL() << "GIslandModel node with unexpected metadata type";
509     }
510
511     EXPECT_EQ(6u, data_nhs.size()); // 3 input nodes + 3 output nodes
512     EXPECT_EQ(1u, isl_nhs.size());  // 1 island
513 }
514
515 // FIXME: add more tests on mixed (hetero) graphs
516 // ADE-222, ADE-223
517
518 // FIXME: add test on combination of user-specified island
519 // which should be heterogeneous (based on kernel availability)
520 // but as we don't support this, compilation should fail
521
522 // FIXME: add tests on automatic inferred islands which are
523 // connected via 1) gmat 2) gscalar 3) garray,
524 // check the case with executor
525 // check the case when this 1/2/3 interim object is also gcomputation output
526
527 } // namespace opencv_test