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 Intel Corporation
6 
7 #ifndef OPENCV_GAPI_FLUID_BACKEND_HPP
8 #define OPENCV_GAPI_FLUID_BACKEND_HPP
9 
10 // FIXME? Actually gfluidbackend.hpp is not included anywhere
11 // and can be placed in gfluidbackend.cpp
12 
13 #include <opencv2/gapi/garg.hpp>
14 #include <opencv2/gapi/gproto.hpp>
15 #include <opencv2/gapi/fluid/gfluidkernel.hpp>
16 #include <opencv2/gapi/fluid/gfluidbuffer.hpp>
17 
18 // PRIVATE STUFF!
19 #include "backends/common/gbackend.hpp"
20 #include "compiler/gislandmodel.hpp"
21 
22 namespace cv { namespace gimpl {
23 
24 struct FluidUnit
25 {
namecv::gimpl::FluidUnit26     static const char *name() { return "FluidUnit"; }
27     GFluidKernel k;
28     gapi::fluid::BorderOpt border;
29     int border_size;
30     int window;
31     std::vector<int> line_consumption;
32     double ratio;
33 };
34 
35 struct FluidUseOwnBorderBuffer
36 {
namecv::gimpl::FluidUseOwnBorderBuffer37     static const char *name() { return "FluidUseOwnBorderBuffer"; }
38     bool use;
39 };
40 
41 struct FluidData
42 {
namecv::gimpl::FluidData43     static const char *name() { return "FluidData"; }
44 
45     // FIXME: This structure starts looking like "FluidBuffer" meta
46     int  latency         = 0;
47     int  skew            = 0;
48     int  max_consumption = 1;
49     int  border_size     = 0;
50     int  lpi_write       = 1;
51     bool internal        = false; // is node internal to any fluid island
52     gapi::fluid::BorderOpt border;
53 };
54 
55 struct agent_data_t {
56      GFluidKernel::Kind  kind;
57      ade::NodeHandle     nh;
58      std::vector<int>    in_buffer_ids;
59      std::vector<int>    out_buffer_ids;
60  };
61 
62 struct FluidAgent
63 {
64 public:
65     virtual ~FluidAgent() = default;
66     FluidAgent(const ade::Graph &g, ade::NodeHandle nh);
67 
68     GFluidKernel k;
69     ade::NodeHandle op_handle; // FIXME: why it is here??//
70     std::string op_name;
71 
72     // <  0 - not a buffer
73     // >= 0 - a buffer with RcID
74     std::vector<int> in_buffer_ids;
75     std::vector<int> out_buffer_ids;
76 
77     cv::GArgs in_args;
78     std::vector<cv::gapi::fluid::View>   in_views; // sparce list of IN views
79     std::vector<cv::gapi::fluid::Buffer*> out_buffers;
80 
81     // FIXME Current assumption is that outputs have EQUAL SIZES
82     int m_outputLines = 0;
83     int m_producedLines = 0;
84 
85     // Execution methods
86     void reset();
87     bool canWork() const;
88     bool canRead() const;
89     bool canWrite() const;
90     void doWork();
91     bool done() const;
92 
93     void debug(std::ostream& os);
94 
95     // FIXME:
96     // refactor (implement a more solid replacement or
97     // drop this method completely)
98     virtual void setRatio(double ratio) = 0;
99 
100 private:
101     // FIXME!!!
102     // move to another class
103     virtual int firstWindow(std::size_t inPort) const = 0;
104     virtual std::pair<int,int> linesReadAndnextWindow(std::size_t inPort) const = 0;
105 };
106 
107 //helper data structure for accumulating graph traversal/analysis data
108 struct FluidGraphInputData {
109 
110     std::vector<agent_data_t>               m_agents_data;
111     std::vector<std::size_t>                m_scratch_users;
112     std::unordered_map<int, std::size_t>    m_id_map;           // GMat id -> buffer idx map
113     std::map<std::size_t, ade::NodeHandle>  m_all_gmat_ids;
114 
115     std::size_t                             m_mat_count;
116 };
117 //local helper function to traverse the graph once and pass the results to multiple instances of GFluidExecutable
118 FluidGraphInputData fluidExtractInputDataFromGraph(const ade::Graph &m_g, const std::vector<ade::NodeHandle> &nodes);
119 
120 class GFluidExecutable final: public GIslandExecutable
121 {
122     GFluidExecutable(const GFluidExecutable&) = delete;  // due std::unique_ptr in members list
123 
124     const ade::Graph &m_g;
125     GModel::ConstGraph m_gm;
126 
127     std::vector<std::unique_ptr<FluidAgent>> m_agents;
128 
129     std::vector<FluidAgent*> m_script;
130 
131     cv::gimpl::Mag m_res;
132 
133     std::size_t m_num_int_buffers; // internal buffers counter (m_buffers - num_scratch)
134     std::vector<std::size_t> m_scratch_users;
135 
136     std::unordered_map<int, std::size_t> m_id_map; // GMat id -> buffer idx map
137     std::map<std::size_t, ade::NodeHandle> m_all_gmat_ids;
138 
139     std::vector<cv::gapi::fluid::Buffer> m_buffers;
140 
141     void bindInArg (const RcDesc &rc, const GRunArg &arg);
142     void bindOutArg(const RcDesc &rc, const GRunArgP &arg);
143     void packArg   (GArg &in_arg, const GArg &op_arg);
144 
145     void initBufferRois(std::vector<int>& readStarts, std::vector<cv::Rect>& rois, const std::vector<cv::Rect> &out_rois);
146     void makeReshape(const std::vector<cv::Rect>& out_rois);
147     std::size_t total_buffers_size() const;
148 
149 public:
canReshape() const150     virtual inline bool canReshape() const override { return true; }
151     virtual void reshape(ade::Graph& g, const GCompileArgs& args) override;
152 
153     virtual void run(std::vector<InObj>  &&input_objs,
154                      std::vector<OutObj> &&output_objs) override;
155 
156     using GIslandExecutable::run; // (IInput&, IOutput&) version
157 
158     void run(std::vector<InObj>  &input_objs,
159              std::vector<OutObj> &output_objs);
160 
161 
162      GFluidExecutable(const ade::Graph                          &g,
163                       const FluidGraphInputData                 &graph_data,
164                       const std::vector<cv::Rect>               &outputRois);
165 };
166 
167 
168 class GParallelFluidExecutable final: public GIslandExecutable {
169     GParallelFluidExecutable(const GParallelFluidExecutable&) = delete;  // due std::unique_ptr in members list
170 
171     std::vector<std::unique_ptr<GFluidExecutable>> tiles;
172     decltype(GFluidParallelFor::parallel_for) parallel_for;
173 public:
174     GParallelFluidExecutable(const ade::Graph                       &g,
175                              const FluidGraphInputData              &graph_data,
176                              const std::vector<GFluidOutputRois>    &parallelOutputRois,
177                              const decltype(parallel_for)           &pfor);
178 
179 
canReshape() const180     virtual inline bool canReshape() const override { return false; }
181     virtual void reshape(ade::Graph& g, const GCompileArgs& args) override;
182 
183     virtual void run(std::vector<InObj>  &&input_objs,
184                      std::vector<OutObj> &&output_objs) override;
185 };
186 }} // cv::gimpl
187 
188 
189 #endif // OPENCV_GAPI_FLUID_BACKEND_HPP
190