Line data Source code
1 :
2 : /* Copyright (c) 2008-2015, Stefan Eilemann <eile@equalizergraphics.com>
3 : * Cedric Stalder <cedric.stalder@gmail.com>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #ifndef EQS_LOADEQUALIZER_H
20 : #define EQS_LOADEQUALIZER_H
21 :
22 : #include "../channelListener.h" // base class
23 : #include "equalizer.h" // base class
24 :
25 : #include <eq/fabric/range.h> // member
26 : #include <eq/fabric/viewport.h> // member
27 :
28 : #include <deque>
29 : #include <vector>
30 :
31 : namespace eq
32 : {
33 : namespace server
34 : {
35 : std::ostream& operator<<(std::ostream& os, const LoadEqualizer*);
36 :
37 : /** Adapts the 2D tiling or DB range of the attached compound's children. */
38 : class LoadEqualizer : public Equalizer, protected ChannelListener
39 : {
40 : public:
41 : EQSERVER_API LoadEqualizer();
42 : explicit LoadEqualizer(const fabric::Equalizer& from);
43 : virtual ~LoadEqualizer();
44 130 : void toStream(std::ostream& os) const final { os << this; }
45 : /** @sa CompoundListener::notifyUpdatePre */
46 : void notifyUpdatePre(Compound* compound, const uint32_t frameNumber) final;
47 :
48 : /** @sa ChannelListener::notifyLoadData */
49 : void notifyLoadData(Channel* channel, uint32_t frameNumber,
50 : const Statistics& statistics,
51 : const Viewport& region) final;
52 :
53 0 : uint32_t getType() const final { return fabric::LOAD_EQUALIZER; }
54 : protected:
55 732 : void notifyChildAdded(Compound*, Compound*) override { LBASSERT(!_tree); }
56 0 : void notifyChildRemove(Compound*, Compound*) override { LBASSERT(!_tree); }
57 : private:
58 : struct Node
59 : {
60 6 : Node()
61 6 : : left(0)
62 : , right(0)
63 : , compound(0)
64 : , mode(MODE_VERTICAL)
65 : , resources(0.0f)
66 : , split(0.5f)
67 : , boundaryf(0.0f)
68 6 : , resistancef(0.0f)
69 : {
70 6 : }
71 6 : ~Node()
72 6 : {
73 6 : delete left;
74 6 : delete right;
75 6 : }
76 :
77 : Node* left; //<! Left child (only on non-leafs)
78 : Node* right; //<! Right child (only on non-leafs)
79 : Compound* compound; //<! The corresponding child (only on leafs)
80 : LoadEqualizer::Mode mode; //<! What to adapt
81 : float resources; //<! total amount of resources of subtree
82 : float split; //<! 0..1 global (vp, range) split
83 : float boundaryf;
84 : Vector2i boundary2i;
85 : float resistancef;
86 : Vector2i resistance2i;
87 : Vector2i maxSize;
88 : };
89 : friend std::ostream& operator<<(std::ostream& os, const Node* node);
90 : typedef std::vector<Node*> LBNodes;
91 :
92 : Node* _tree; // <! The binary split tree of all children
93 :
94 : struct Data
95 : {
96 26 : Data()
97 26 : : channel(0)
98 : , taskID(0)
99 : , destTaskID(0)
100 : , time(-1)
101 26 : , assembleTime(0)
102 : {
103 26 : }
104 : Channel* channel;
105 : uint32_t taskID;
106 : uint32_t destTaskID;
107 : Viewport vp;
108 : Range range;
109 : int64_t time;
110 : int64_t assembleTime;
111 : };
112 :
113 : typedef std::vector<Data> LBDatas;
114 : typedef std::pair<uint32_t, LBDatas> LBFrameData;
115 :
116 : std::deque<LBFrameData> _history;
117 :
118 : //-------------------- Methods --------------------
119 : /** @return true if we have a valid LB tree */
120 : Node* _buildTree(const Compounds& children);
121 :
122 : /** Setup assembly with the compound dest value */
123 : void _updateAssembleTime(Data& data, const Statistic& stat);
124 :
125 : /** Clear the tree, does not delete the nodes. */
126 : void _clearTree(Node* node);
127 :
128 : /** get the total time used by the rendering. */
129 : int64_t _getTotalTime();
130 :
131 : /** get the assembly time used by the compound which use
132 : the destination Channel. */
133 : int64_t _getAssembleTime();
134 :
135 : /** Obsolete _history so that front-most item is youngest available. */
136 : void _checkHistory();
137 :
138 : /** Update all node fields influencing the split */
139 : void _update(Node* node, const Viewport& vp, const Range& range);
140 : void _updateLeaf(Node* node);
141 : void _updateNode(Node* node, const Viewport& vp, const Range& range);
142 :
143 : /** Adjust the split of each node based on the front-most _history. */
144 : void _computeSplit();
145 : void _removeEmpty(LBDatas& items);
146 :
147 : void _computeSplit(Node* node, const float time, LBDatas* sortedData,
148 : const Viewport& vp, const Range& range);
149 : void _assign(Compound* compound, const Viewport& vp, const Range& range);
150 :
151 : /** Get the resource for all children compound. */
152 : float _getTotalResources() const;
153 :
154 0 : static bool _compareX(const Data& data1, const Data& data2)
155 : {
156 0 : return data1.vp.x < data2.vp.x;
157 : }
158 0 : static bool _compareY(const Data& data1, const Data& data2)
159 : {
160 0 : return data1.vp.y < data2.vp.y;
161 : }
162 0 : static bool _compareRange(const Data& data1, const Data& data2)
163 : {
164 0 : return data1.range.start < data2.range.start;
165 : }
166 : };
167 : }
168 : }
169 :
170 : #endif // EQS_LOADEQUALIZER_H
|