blob: da4436ebdfb40ae558ecb2a2de4b07548ba2fcc7 [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>
gman@chromium.org8d804792012-10-17 21:33:48 +00009
10namespace {
Jamie Madillce505552014-06-26 14:56:33 -040011int GetSortOrder(ShDataType type)
gman@chromium.org8d804792012-10-17 21:33:48 +000012{
13 switch (type) {
Jamie Madillce505552014-06-26 14:56:33 -040014 case SH_FLOAT_MAT4:
15 case SH_FLOAT_MAT2x4:
16 case SH_FLOAT_MAT3x4:
17 case SH_FLOAT_MAT4x2:
18 case SH_FLOAT_MAT4x3:
gman@chromium.org8d804792012-10-17 21:33:48 +000019 return 0;
Jamie Madillce505552014-06-26 14:56:33 -040020 case SH_FLOAT_MAT2:
gman@chromium.org8d804792012-10-17 21:33:48 +000021 return 1;
Jamie Madillce505552014-06-26 14:56:33 -040022 case SH_FLOAT_VEC4:
23 case SH_INT_VEC4:
24 case SH_BOOL_VEC4:
gman@chromium.org8d804792012-10-17 21:33:48 +000025 return 2;
Jamie Madillce505552014-06-26 14:56:33 -040026 case SH_FLOAT_MAT3:
27 case SH_FLOAT_MAT2x3:
28 case SH_FLOAT_MAT3x2:
gman@chromium.org8d804792012-10-17 21:33:48 +000029 return 3;
Jamie Madillce505552014-06-26 14:56:33 -040030 case SH_FLOAT_VEC3:
31 case SH_INT_VEC3:
32 case SH_BOOL_VEC3:
gman@chromium.org8d804792012-10-17 21:33:48 +000033 return 4;
Jamie Madillce505552014-06-26 14:56:33 -040034 case SH_FLOAT_VEC2:
35 case SH_INT_VEC2:
36 case SH_BOOL_VEC2:
gman@chromium.org8d804792012-10-17 21:33:48 +000037 return 5;
Jamie Madillce505552014-06-26 14:56:33 -040038 case SH_FLOAT:
39 case SH_INT:
40 case SH_BOOL:
41 case SH_SAMPLER_2D:
42 case SH_SAMPLER_CUBE:
43 case SH_SAMPLER_EXTERNAL_OES:
44 case SH_SAMPLER_2D_RECT_ARB:
gman@chromium.org8d804792012-10-17 21:33:48 +000045 return 6;
46 default:
47 ASSERT(false);
48 return 7;
49 }
50}
51} // namespace
52
Jamie Madillce505552014-06-26 14:56:33 -040053int VariablePacker::GetNumComponentsPerRow(ShDataType type)
gman@chromium.org8d804792012-10-17 21:33:48 +000054{
55 switch (type) {
Jamie Madillce505552014-06-26 14:56:33 -040056 case SH_FLOAT_MAT4:
57 case SH_FLOAT_MAT2:
58 case SH_FLOAT_MAT2x4:
59 case SH_FLOAT_MAT3x4:
60 case SH_FLOAT_MAT4x2:
61 case SH_FLOAT_MAT4x3:
62 case SH_FLOAT_VEC4:
63 case SH_INT_VEC4:
64 case SH_BOOL_VEC4:
gman@chromium.org8d804792012-10-17 21:33:48 +000065 return 4;
Jamie Madillce505552014-06-26 14:56:33 -040066 case SH_FLOAT_MAT3:
67 case SH_FLOAT_MAT2x3:
68 case SH_FLOAT_MAT3x2:
69 case SH_FLOAT_VEC3:
70 case SH_INT_VEC3:
71 case SH_BOOL_VEC3:
gman@chromium.org8d804792012-10-17 21:33:48 +000072 return 3;
Jamie Madillce505552014-06-26 14:56:33 -040073 case SH_FLOAT_VEC2:
74 case SH_INT_VEC2:
75 case SH_BOOL_VEC2:
gman@chromium.org8d804792012-10-17 21:33:48 +000076 return 2;
Jamie Madillce505552014-06-26 14:56:33 -040077 case SH_FLOAT:
78 case SH_INT:
79 case SH_BOOL:
80 case SH_SAMPLER_2D:
81 case SH_SAMPLER_CUBE:
82 case SH_SAMPLER_EXTERNAL_OES:
83 case SH_SAMPLER_2D_RECT_ARB:
gman@chromium.org8d804792012-10-17 21:33:48 +000084 return 1;
85 default:
86 ASSERT(false);
87 return 5;
88 }
89}
90
Jamie Madillce505552014-06-26 14:56:33 -040091int VariablePacker::GetNumRows(ShDataType type)
gman@chromium.org8d804792012-10-17 21:33:48 +000092{
93 switch (type) {
Jamie Madillce505552014-06-26 14:56:33 -040094 case SH_FLOAT_MAT4:
95 case SH_FLOAT_MAT2x4:
96 case SH_FLOAT_MAT3x4:
97 case SH_FLOAT_MAT4x3:
98 case SH_FLOAT_MAT4x2:
gman@chromium.org8d804792012-10-17 21:33:48 +000099 return 4;
Jamie Madillce505552014-06-26 14:56:33 -0400100 case SH_FLOAT_MAT3:
101 case SH_FLOAT_MAT2x3:
102 case SH_FLOAT_MAT3x2:
gman@chromium.org8d804792012-10-17 21:33:48 +0000103 return 3;
Jamie Madillce505552014-06-26 14:56:33 -0400104 case SH_FLOAT_MAT2:
daniel@transgaming.comd5903ca2013-02-01 03:20:31 +0000105 return 2;
Jamie Madillce505552014-06-26 14:56:33 -0400106 case SH_FLOAT_VEC4:
107 case SH_INT_VEC4:
108 case SH_BOOL_VEC4:
109 case SH_FLOAT_VEC3:
110 case SH_INT_VEC3:
111 case SH_BOOL_VEC3:
112 case SH_FLOAT_VEC2:
113 case SH_INT_VEC2:
114 case SH_BOOL_VEC2:
115 case SH_FLOAT:
116 case SH_INT:
117 case SH_BOOL:
118 case SH_SAMPLER_2D:
119 case SH_SAMPLER_CUBE:
120 case SH_SAMPLER_EXTERNAL_OES:
121 case SH_SAMPLER_2D_RECT_ARB:
gman@chromium.org8d804792012-10-17 21:33:48 +0000122 return 1;
123 default:
124 ASSERT(false);
125 return 100000;
126 }
127}
128
129struct TVariableInfoComparer {
130 bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const
131 {
132 int lhsSortOrder = GetSortOrder(lhs.type);
133 int rhsSortOrder = GetSortOrder(rhs.type);
134 if (lhsSortOrder != rhsSortOrder) {
135 return lhsSortOrder < rhsSortOrder;
136 }
137 // Sort by largest first.
138 return lhs.size > rhs.size;
139 }
140};
141
142unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
143{
144 return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
145 kColumnMask) >> column;
146}
147
148void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
149{
150 unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
151 for (int r = 0; r < numRows; ++r) {
152 int row = topRow + r;
153 ASSERT((rows_[row] & columnFlags) == 0);
154 rows_[row] |= columnFlags;
155 }
156}
157
158bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
159{
160 ASSERT(destRow);
161
162 for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
163 ++topNonFullRow_) {
164 }
165
166 for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
167 --bottomNonFullRow_) {
168 }
169
170 if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
171 return false;
172 }
173
174 unsigned columnFlags = makeColumnFlags(column, 1);
175 int topGoodRow = 0;
176 int smallestGoodTop = -1;
177 int smallestGoodSize = maxRows_ + 1;
178 int bottomRow = bottomNonFullRow_ + 1;
179 bool found = false;
180 for (int row = topNonFullRow_; row <= bottomRow; ++row) {
181 bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
182 if (rowEmpty) {
183 if (!found) {
184 topGoodRow = row;
185 found = true;
186 }
187 } else {
188 if (found) {
189 int size = row - topGoodRow;
190 if (size >= numRows && size < smallestGoodSize) {
191 smallestGoodSize = size;
192 smallestGoodTop = topGoodRow;
193 }
194 }
195 found = false;
196 }
197 }
198 if (smallestGoodTop < 0) {
199 return false;
200 }
201
202 *destRow = smallestGoodTop;
203 if (destSize) {
204 *destSize = smallestGoodSize;
205 }
206 return true;
207}
208
209bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables)
210{
211 ASSERT(maxVectors > 0);
212 maxRows_ = maxVectors;
213 topNonFullRow_ = 0;
214 bottomNonFullRow_ = maxRows_ - 1;
215 TVariableInfoList variables(in_variables);
216
Nicolas Capens1d1c1152014-02-26 11:00:28 -0500217 // Check whether each variable fits in the available vectors.
218 for (size_t i = 0; i < variables.size(); i++) {
219 const TVariableInfo& variable = variables[i];
220 if (variable.size > maxVectors / GetNumRows(variable.type)) {
221 return false;
222 }
223 }
224
gman@chromium.org8d804792012-10-17 21:33:48 +0000225 // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
226 // order by type, then by size of array, largest first.
227 std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
228 rows_.clear();
229 rows_.resize(maxVectors, 0);
230
231 // Packs the 4 column variables.
232 size_t ii = 0;
233 for (; ii < variables.size(); ++ii) {
234 const TVariableInfo& variable = variables[ii];
235 if (GetNumComponentsPerRow(variable.type) != 4) {
236 break;
237 }
238 topNonFullRow_ += GetNumRows(variable.type) * variable.size;
239 }
240
241 if (topNonFullRow_ > maxRows_) {
242 return false;
243 }
244
245 // Packs the 3 column variables.
246 int num3ColumnRows = 0;
247 for (; ii < variables.size(); ++ii) {
248 const TVariableInfo& variable = variables[ii];
249 if (GetNumComponentsPerRow(variable.type) != 3) {
250 break;
251 }
252 num3ColumnRows += GetNumRows(variable.type) * variable.size;
253 }
254
255 if (topNonFullRow_ + num3ColumnRows > maxRows_) {
256 return false;
257 }
258
259 fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
260
261 // Packs the 2 column variables.
262 int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
263 int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
264 int rowsAvailableInColumns01 = twoColumnRowsAvailable;
265 int rowsAvailableInColumns23 = twoColumnRowsAvailable;
266 for (; ii < variables.size(); ++ii) {
267 const TVariableInfo& variable = variables[ii];
268 if (GetNumComponentsPerRow(variable.type) != 2) {
269 break;
270 }
271 int numRows = GetNumRows(variable.type) * variable.size;
272 if (numRows <= rowsAvailableInColumns01) {
273 rowsAvailableInColumns01 -= numRows;
274 } else if (numRows <= rowsAvailableInColumns23) {
275 rowsAvailableInColumns23 -= numRows;
276 } else {
277 return false;
278 }
279 }
280
281 int numRowsUsedInColumns01 =
282 twoColumnRowsAvailable - rowsAvailableInColumns01;
283 int numRowsUsedInColumns23 =
284 twoColumnRowsAvailable - rowsAvailableInColumns23;
285 fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
286 fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
287 2, 2);
288
289 // Packs the 1 column variables.
290 for (; ii < variables.size(); ++ii) {
291 const TVariableInfo& variable = variables[ii];
292 ASSERT(1 == GetNumComponentsPerRow(variable.type));
293 int numRows = GetNumRows(variable.type) * variable.size;
294 int smallestColumn = -1;
295 int smallestSize = maxRows_ + 1;
296 int topRow = -1;
297 for (int column = 0; column < kNumColumns; ++column) {
298 int row = 0;
299 int size = 0;
300 if (searchColumn(column, numRows, &row, &size)) {
301 if (size < smallestSize) {
302 smallestSize = size;
303 smallestColumn = column;
304 topRow = row;
305 }
306 }
307 }
308
309 if (smallestColumn < 0) {
310 return false;
311 }
312
313 fillColumns(topRow, numRows, smallestColumn, 1);
314 }
315
316 ASSERT(variables.size() == ii);
317
318 return true;
319}
320
321
322