blob: ec57bc48d81343d44383f0224c6533756cefd140 [file] [log] [blame]
gman@chromium.org8d804792012-10-17 21:33:48 +00001//
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//
Geoff Lang17732822013-08-29 13:46:49 -04006#include "compiler/translator/VariablePacker.h"
gman@chromium.org8d804792012-10-17 21:33:48 +00007
8#include <algorithm>
Geoff Lang17732822013-08-29 13:46:49 -04009#include "compiler/translator/ShHandle.h"
gman@chromium.org8d804792012-10-17 21:33:48 +000010
11namespace {
12int GetSortOrder(ShDataType type)
13{
14 switch (type) {
15 case SH_FLOAT_MAT4:
shannonwoods@chromium.org8da034c2013-05-30 00:19:15 +000016 case SH_FLOAT_MAT2x4:
17 case SH_FLOAT_MAT3x4:
18 case SH_FLOAT_MAT4x2:
19 case SH_FLOAT_MAT4x3:
gman@chromium.org8d804792012-10-17 21:33:48 +000020 return 0;
21 case SH_FLOAT_MAT2:
22 return 1;
23 case SH_FLOAT_VEC4:
24 case SH_INT_VEC4:
25 case SH_BOOL_VEC4:
26 return 2;
27 case SH_FLOAT_MAT3:
shannonwoods@chromium.org8da034c2013-05-30 00:19:15 +000028 case SH_FLOAT_MAT2x3:
29 case SH_FLOAT_MAT3x2:
gman@chromium.org8d804792012-10-17 21:33:48 +000030 return 3;
31 case SH_FLOAT_VEC3:
32 case SH_INT_VEC3:
33 case SH_BOOL_VEC3:
34 return 4;
35 case SH_FLOAT_VEC2:
36 case SH_INT_VEC2:
37 case SH_BOOL_VEC2:
38 return 5;
39 case SH_FLOAT:
40 case SH_INT:
41 case SH_BOOL:
42 case SH_SAMPLER_2D:
43 case SH_SAMPLER_CUBE:
44 case SH_SAMPLER_EXTERNAL_OES:
45 case SH_SAMPLER_2D_RECT_ARB:
46 return 6;
47 default:
48 ASSERT(false);
49 return 7;
50 }
51}
52} // namespace
53
54int VariablePacker::GetNumComponentsPerRow(ShDataType type)
55{
56 switch (type) {
57 case SH_FLOAT_MAT4:
58 case SH_FLOAT_MAT2:
shannonwoods@chromium.org8da034c2013-05-30 00:19:15 +000059 case SH_FLOAT_MAT2x4:
60 case SH_FLOAT_MAT3x4:
61 case SH_FLOAT_MAT4x2:
62 case SH_FLOAT_MAT4x3:
gman@chromium.org8d804792012-10-17 21:33:48 +000063 case SH_FLOAT_VEC4:
64 case SH_INT_VEC4:
65 case SH_BOOL_VEC4:
66 return 4;
67 case SH_FLOAT_MAT3:
shannonwoods@chromium.org8da034c2013-05-30 00:19:15 +000068 case SH_FLOAT_MAT2x3:
69 case SH_FLOAT_MAT3x2:
gman@chromium.org8d804792012-10-17 21:33:48 +000070 case SH_FLOAT_VEC3:
71 case SH_INT_VEC3:
72 case SH_BOOL_VEC3:
73 return 3;
74 case SH_FLOAT_VEC2:
75 case SH_INT_VEC2:
76 case SH_BOOL_VEC2:
77 return 2;
78 case SH_FLOAT:
79 case SH_INT:
80 case SH_BOOL:
81 case SH_SAMPLER_2D:
82 case SH_SAMPLER_CUBE:
83 case SH_SAMPLER_EXTERNAL_OES:
84 case SH_SAMPLER_2D_RECT_ARB:
85 return 1;
86 default:
87 ASSERT(false);
88 return 5;
89 }
90}
91
92int VariablePacker::GetNumRows(ShDataType type)
93{
94 switch (type) {
95 case SH_FLOAT_MAT4:
shannonwoods@chromium.org8da034c2013-05-30 00:19:15 +000096 case SH_FLOAT_MAT2x4:
97 case SH_FLOAT_MAT3x4:
98 case SH_FLOAT_MAT4x3:
99 case SH_FLOAT_MAT4x2:
gman@chromium.org8d804792012-10-17 21:33:48 +0000100 return 4;
101 case SH_FLOAT_MAT3:
shannonwoods@chromium.org8da034c2013-05-30 00:19:15 +0000102 case SH_FLOAT_MAT2x3:
103 case SH_FLOAT_MAT3x2:
gman@chromium.org8d804792012-10-17 21:33:48 +0000104 return 3;
105 case SH_FLOAT_MAT2:
daniel@transgaming.comd5903ca2013-02-01 03:20:31 +0000106 return 2;
gman@chromium.org8d804792012-10-17 21:33:48 +0000107 case SH_FLOAT_VEC4:
108 case SH_INT_VEC4:
109 case SH_BOOL_VEC4:
110 case SH_FLOAT_VEC3:
111 case SH_INT_VEC3:
112 case SH_BOOL_VEC3:
113 case SH_FLOAT_VEC2:
114 case SH_INT_VEC2:
115 case SH_BOOL_VEC2:
116 case SH_FLOAT:
117 case SH_INT:
118 case SH_BOOL:
119 case SH_SAMPLER_2D:
120 case SH_SAMPLER_CUBE:
121 case SH_SAMPLER_EXTERNAL_OES:
122 case SH_SAMPLER_2D_RECT_ARB:
123 return 1;
124 default:
125 ASSERT(false);
126 return 100000;
127 }
128}
129
130struct TVariableInfoComparer {
131 bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const
132 {
133 int lhsSortOrder = GetSortOrder(lhs.type);
134 int rhsSortOrder = GetSortOrder(rhs.type);
135 if (lhsSortOrder != rhsSortOrder) {
136 return lhsSortOrder < rhsSortOrder;
137 }
138 // Sort by largest first.
139 return lhs.size > rhs.size;
140 }
141};
142
143unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
144{
145 return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
146 kColumnMask) >> column;
147}
148
149void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
150{
151 unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
152 for (int r = 0; r < numRows; ++r) {
153 int row = topRow + r;
154 ASSERT((rows_[row] & columnFlags) == 0);
155 rows_[row] |= columnFlags;
156 }
157}
158
159bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
160{
161 ASSERT(destRow);
162
163 for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
164 ++topNonFullRow_) {
165 }
166
167 for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
168 --bottomNonFullRow_) {
169 }
170
171 if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
172 return false;
173 }
174
175 unsigned columnFlags = makeColumnFlags(column, 1);
176 int topGoodRow = 0;
177 int smallestGoodTop = -1;
178 int smallestGoodSize = maxRows_ + 1;
179 int bottomRow = bottomNonFullRow_ + 1;
180 bool found = false;
181 for (int row = topNonFullRow_; row <= bottomRow; ++row) {
182 bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
183 if (rowEmpty) {
184 if (!found) {
185 topGoodRow = row;
186 found = true;
187 }
188 } else {
189 if (found) {
190 int size = row - topGoodRow;
191 if (size >= numRows && size < smallestGoodSize) {
192 smallestGoodSize = size;
193 smallestGoodTop = topGoodRow;
194 }
195 }
196 found = false;
197 }
198 }
199 if (smallestGoodTop < 0) {
200 return false;
201 }
202
203 *destRow = smallestGoodTop;
204 if (destSize) {
205 *destSize = smallestGoodSize;
206 }
207 return true;
208}
209
210bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables)
211{
212 ASSERT(maxVectors > 0);
213 maxRows_ = maxVectors;
214 topNonFullRow_ = 0;
215 bottomNonFullRow_ = maxRows_ - 1;
216 TVariableInfoList variables(in_variables);
217
218 // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
219 // order by type, then by size of array, largest first.
220 std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
221 rows_.clear();
222 rows_.resize(maxVectors, 0);
223
224 // Packs the 4 column variables.
225 size_t ii = 0;
226 for (; ii < variables.size(); ++ii) {
227 const TVariableInfo& variable = variables[ii];
228 if (GetNumComponentsPerRow(variable.type) != 4) {
229 break;
230 }
231 topNonFullRow_ += GetNumRows(variable.type) * variable.size;
232 }
233
234 if (topNonFullRow_ > maxRows_) {
235 return false;
236 }
237
238 // Packs the 3 column variables.
239 int num3ColumnRows = 0;
240 for (; ii < variables.size(); ++ii) {
241 const TVariableInfo& variable = variables[ii];
242 if (GetNumComponentsPerRow(variable.type) != 3) {
243 break;
244 }
245 num3ColumnRows += GetNumRows(variable.type) * variable.size;
246 }
247
248 if (topNonFullRow_ + num3ColumnRows > maxRows_) {
249 return false;
250 }
251
252 fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
253
254 // Packs the 2 column variables.
255 int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
256 int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
257 int rowsAvailableInColumns01 = twoColumnRowsAvailable;
258 int rowsAvailableInColumns23 = twoColumnRowsAvailable;
259 for (; ii < variables.size(); ++ii) {
260 const TVariableInfo& variable = variables[ii];
261 if (GetNumComponentsPerRow(variable.type) != 2) {
262 break;
263 }
264 int numRows = GetNumRows(variable.type) * variable.size;
265 if (numRows <= rowsAvailableInColumns01) {
266 rowsAvailableInColumns01 -= numRows;
267 } else if (numRows <= rowsAvailableInColumns23) {
268 rowsAvailableInColumns23 -= numRows;
269 } else {
270 return false;
271 }
272 }
273
274 int numRowsUsedInColumns01 =
275 twoColumnRowsAvailable - rowsAvailableInColumns01;
276 int numRowsUsedInColumns23 =
277 twoColumnRowsAvailable - rowsAvailableInColumns23;
278 fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
279 fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
280 2, 2);
281
282 // Packs the 1 column variables.
283 for (; ii < variables.size(); ++ii) {
284 const TVariableInfo& variable = variables[ii];
285 ASSERT(1 == GetNumComponentsPerRow(variable.type));
286 int numRows = GetNumRows(variable.type) * variable.size;
287 int smallestColumn = -1;
288 int smallestSize = maxRows_ + 1;
289 int topRow = -1;
290 for (int column = 0; column < kNumColumns; ++column) {
291 int row = 0;
292 int size = 0;
293 if (searchColumn(column, numRows, &row, &size)) {
294 if (size < smallestSize) {
295 smallestSize = size;
296 smallestColumn = column;
297 topRow = row;
298 }
299 }
300 }
301
302 if (smallestColumn < 0) {
303 return false;
304 }
305
306 fillColumns(topRow, numRows, smallestColumn, 1);
307 }
308
309 ASSERT(variables.size() == ii);
310
311 return true;
312}
313
314
315