Line data Source code
1 : //
2 : // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
3 : // Use of this source code is governed by a BSD-style license that can be
4 : // found in the LICENSE file.
5 : //
6 :
7 : #include <algorithm>
8 :
9 : #include "angle_gl.h"
10 :
11 : #include "compiler/translator/VariablePacker.h"
12 : #include "common/utilities.h"
13 :
14 0 : int VariablePacker::GetNumComponentsPerRow(sh::GLenum type)
15 : {
16 0 : switch (type)
17 : {
18 : case GL_FLOAT_MAT4:
19 : case GL_FLOAT_MAT2:
20 : case GL_FLOAT_MAT2x4:
21 : case GL_FLOAT_MAT3x4:
22 : case GL_FLOAT_MAT4x2:
23 : case GL_FLOAT_MAT4x3:
24 : case GL_FLOAT_VEC4:
25 : case GL_INT_VEC4:
26 : case GL_BOOL_VEC4:
27 : case GL_UNSIGNED_INT_VEC4:
28 0 : return 4;
29 : case GL_FLOAT_MAT3:
30 : case GL_FLOAT_MAT2x3:
31 : case GL_FLOAT_MAT3x2:
32 : case GL_FLOAT_VEC3:
33 : case GL_INT_VEC3:
34 : case GL_BOOL_VEC3:
35 : case GL_UNSIGNED_INT_VEC3:
36 0 : return 3;
37 : case GL_FLOAT_VEC2:
38 : case GL_INT_VEC2:
39 : case GL_BOOL_VEC2:
40 : case GL_UNSIGNED_INT_VEC2:
41 0 : return 2;
42 : default:
43 0 : ASSERT(gl::VariableComponentCount(type) == 1);
44 0 : return 1;
45 : }
46 : }
47 :
48 0 : int VariablePacker::GetNumRows(sh::GLenum type)
49 : {
50 0 : switch (type)
51 : {
52 : case GL_FLOAT_MAT4:
53 : case GL_FLOAT_MAT2x4:
54 : case GL_FLOAT_MAT3x4:
55 : case GL_FLOAT_MAT4x3:
56 : case GL_FLOAT_MAT4x2:
57 0 : return 4;
58 : case GL_FLOAT_MAT3:
59 : case GL_FLOAT_MAT2x3:
60 : case GL_FLOAT_MAT3x2:
61 0 : return 3;
62 : case GL_FLOAT_MAT2:
63 0 : return 2;
64 : default:
65 0 : ASSERT(gl::VariableRowCount(type) == 1);
66 0 : return 1;
67 : }
68 : }
69 :
70 : struct TVariableInfoComparer
71 : {
72 0 : bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const
73 : {
74 0 : int lhsSortOrder = gl::VariableSortOrder(lhs.type);
75 0 : int rhsSortOrder = gl::VariableSortOrder(rhs.type);
76 0 : if (lhsSortOrder != rhsSortOrder) {
77 0 : return lhsSortOrder < rhsSortOrder;
78 : }
79 : // Sort by largest first.
80 0 : return lhs.arraySize > rhs.arraySize;
81 : }
82 : };
83 :
84 0 : unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
85 : {
86 0 : return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
87 0 : kColumnMask) >> column;
88 : }
89 :
90 0 : void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
91 : {
92 0 : unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
93 0 : for (int r = 0; r < numRows; ++r) {
94 0 : int row = topRow + r;
95 0 : ASSERT((rows_[row] & columnFlags) == 0);
96 0 : rows_[row] |= columnFlags;
97 : }
98 0 : }
99 :
100 0 : bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
101 : {
102 0 : ASSERT(destRow);
103 :
104 0 : for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
105 0 : ++topNonFullRow_) {
106 : }
107 :
108 0 : for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
109 0 : --bottomNonFullRow_) {
110 : }
111 :
112 0 : if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
113 0 : return false;
114 : }
115 :
116 0 : unsigned columnFlags = makeColumnFlags(column, 1);
117 0 : int topGoodRow = 0;
118 0 : int smallestGoodTop = -1;
119 0 : int smallestGoodSize = maxRows_ + 1;
120 0 : int bottomRow = bottomNonFullRow_ + 1;
121 0 : bool found = false;
122 0 : for (int row = topNonFullRow_; row <= bottomRow; ++row) {
123 0 : bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
124 0 : if (rowEmpty) {
125 0 : if (!found) {
126 0 : topGoodRow = row;
127 0 : found = true;
128 : }
129 : } else {
130 0 : if (found) {
131 0 : int size = row - topGoodRow;
132 0 : if (size >= numRows && size < smallestGoodSize) {
133 0 : smallestGoodSize = size;
134 0 : smallestGoodTop = topGoodRow;
135 : }
136 : }
137 0 : found = false;
138 : }
139 : }
140 0 : if (smallestGoodTop < 0) {
141 0 : return false;
142 : }
143 :
144 0 : *destRow = smallestGoodTop;
145 0 : if (destSize) {
146 0 : *destSize = smallestGoodSize;
147 : }
148 0 : return true;
149 : }
150 :
151 0 : bool VariablePacker::CheckVariablesWithinPackingLimits(
152 : unsigned int maxVectors,
153 : const std::vector<sh::ShaderVariable> &in_variables)
154 : {
155 0 : ASSERT(maxVectors > 0);
156 0 : maxRows_ = maxVectors;
157 0 : topNonFullRow_ = 0;
158 0 : bottomNonFullRow_ = maxRows_ - 1;
159 0 : std::vector<sh::ShaderVariable> variables;
160 :
161 0 : for (const auto &variable : in_variables)
162 : {
163 0 : ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse,
164 0 : &variables);
165 : }
166 :
167 : // Check whether each variable fits in the available vectors.
168 0 : for (size_t i = 0; i < variables.size(); i++) {
169 0 : const sh::ShaderVariable &variable = variables[i];
170 0 : if (variable.elementCount() > maxVectors / GetNumRows(variable.type)) {
171 0 : return false;
172 : }
173 : }
174 :
175 : // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
176 : // order by type, then by size of array, largest first.
177 0 : std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
178 0 : rows_.clear();
179 0 : rows_.resize(maxVectors, 0);
180 :
181 : // Packs the 4 column variables.
182 0 : size_t ii = 0;
183 0 : for (; ii < variables.size(); ++ii) {
184 0 : const sh::ShaderVariable &variable = variables[ii];
185 0 : if (GetNumComponentsPerRow(variable.type) != 4) {
186 0 : break;
187 : }
188 0 : topNonFullRow_ += GetNumRows(variable.type) * variable.elementCount();
189 : }
190 :
191 0 : if (topNonFullRow_ > maxRows_) {
192 0 : return false;
193 : }
194 :
195 : // Packs the 3 column variables.
196 0 : int num3ColumnRows = 0;
197 0 : for (; ii < variables.size(); ++ii) {
198 0 : const sh::ShaderVariable &variable = variables[ii];
199 0 : if (GetNumComponentsPerRow(variable.type) != 3) {
200 0 : break;
201 : }
202 0 : num3ColumnRows += GetNumRows(variable.type) * variable.elementCount();
203 : }
204 :
205 0 : if (topNonFullRow_ + num3ColumnRows > maxRows_) {
206 0 : return false;
207 : }
208 :
209 0 : fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
210 :
211 : // Packs the 2 column variables.
212 0 : int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
213 0 : int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
214 0 : int rowsAvailableInColumns01 = twoColumnRowsAvailable;
215 0 : int rowsAvailableInColumns23 = twoColumnRowsAvailable;
216 0 : for (; ii < variables.size(); ++ii) {
217 0 : const sh::ShaderVariable &variable = variables[ii];
218 0 : if (GetNumComponentsPerRow(variable.type) != 2) {
219 0 : break;
220 : }
221 0 : int numRows = GetNumRows(variable.type) * variable.elementCount();
222 0 : if (numRows <= rowsAvailableInColumns01) {
223 0 : rowsAvailableInColumns01 -= numRows;
224 0 : } else if (numRows <= rowsAvailableInColumns23) {
225 0 : rowsAvailableInColumns23 -= numRows;
226 : } else {
227 0 : return false;
228 : }
229 : }
230 :
231 : int numRowsUsedInColumns01 =
232 0 : twoColumnRowsAvailable - rowsAvailableInColumns01;
233 : int numRowsUsedInColumns23 =
234 0 : twoColumnRowsAvailable - rowsAvailableInColumns23;
235 0 : fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
236 0 : fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
237 0 : 2, 2);
238 :
239 : // Packs the 1 column variables.
240 0 : for (; ii < variables.size(); ++ii) {
241 0 : const sh::ShaderVariable &variable = variables[ii];
242 0 : ASSERT(1 == GetNumComponentsPerRow(variable.type));
243 0 : int numRows = GetNumRows(variable.type) * variable.elementCount();
244 0 : int smallestColumn = -1;
245 0 : int smallestSize = maxRows_ + 1;
246 0 : int topRow = -1;
247 0 : for (int column = 0; column < kNumColumns; ++column) {
248 0 : int row = 0;
249 0 : int size = 0;
250 0 : if (searchColumn(column, numRows, &row, &size)) {
251 0 : if (size < smallestSize) {
252 0 : smallestSize = size;
253 0 : smallestColumn = column;
254 0 : topRow = row;
255 : }
256 : }
257 : }
258 :
259 0 : if (smallestColumn < 0) {
260 0 : return false;
261 : }
262 :
263 0 : fillColumns(topRow, numRows, smallestColumn, 1);
264 : }
265 :
266 0 : ASSERT(variables.size() == ii);
267 :
268 0 : return true;
269 : }
|