blob: 7186cb9cd2960fdd578f51cfb64aa838b971e8ab [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"
Jamie Madill183bde52014-07-02 15:31:19 -04007#include "angle_gl.h"
Jamie Madillaa72d782014-07-02 15:31:19 -04008#include "common/utilities.h"
gman@chromium.org8d804792012-10-17 21:33:48 +00009
10#include <algorithm>
gman@chromium.org8d804792012-10-17 21:33:48 +000011
Jamie Madillaa72d782014-07-02 15:31:19 -040012namespace
13{
14
Jamie Madill183bde52014-07-02 15:31:19 -040015int GetSortOrder(sh::GLenum type)
gman@chromium.org8d804792012-10-17 21:33:48 +000016{
17 switch (type) {
Jamie Madill183bde52014-07-02 15:31:19 -040018 case GL_FLOAT_MAT4:
19 case GL_FLOAT_MAT2x4:
20 case GL_FLOAT_MAT3x4:
21 case GL_FLOAT_MAT4x2:
22 case GL_FLOAT_MAT4x3:
gman@chromium.org8d804792012-10-17 21:33:48 +000023 return 0;
Jamie Madill183bde52014-07-02 15:31:19 -040024 case GL_FLOAT_MAT2:
gman@chromium.org8d804792012-10-17 21:33:48 +000025 return 1;
Jamie Madill183bde52014-07-02 15:31:19 -040026 case GL_FLOAT_VEC4:
27 case GL_INT_VEC4:
28 case GL_BOOL_VEC4:
gman@chromium.org8d804792012-10-17 21:33:48 +000029 return 2;
Jamie Madill183bde52014-07-02 15:31:19 -040030 case GL_FLOAT_MAT3:
31 case GL_FLOAT_MAT2x3:
32 case GL_FLOAT_MAT3x2:
gman@chromium.org8d804792012-10-17 21:33:48 +000033 return 3;
Jamie Madill183bde52014-07-02 15:31:19 -040034 case GL_FLOAT_VEC3:
35 case GL_INT_VEC3:
36 case GL_BOOL_VEC3:
gman@chromium.org8d804792012-10-17 21:33:48 +000037 return 4;
Jamie Madill183bde52014-07-02 15:31:19 -040038 case GL_FLOAT_VEC2:
39 case GL_INT_VEC2:
40 case GL_BOOL_VEC2:
gman@chromium.org8d804792012-10-17 21:33:48 +000041 return 5;
Jamie Madill183bde52014-07-02 15:31:19 -040042 case GL_FLOAT:
43 case GL_INT:
44 case GL_BOOL:
45 case GL_SAMPLER_2D:
46 case GL_SAMPLER_CUBE:
47 case GL_SAMPLER_EXTERNAL_OES:
48 case GL_SAMPLER_2D_RECT_ARB:
gman@chromium.org8d804792012-10-17 21:33:48 +000049 return 6;
50 default:
51 ASSERT(false);
52 return 7;
53 }
54}
Jamie Madillaa72d782014-07-02 15:31:19 -040055
gman@chromium.org8d804792012-10-17 21:33:48 +000056} // namespace
57
Jamie Madill183bde52014-07-02 15:31:19 -040058int VariablePacker::GetNumComponentsPerRow(sh::GLenum type)
gman@chromium.org8d804792012-10-17 21:33:48 +000059{
Jamie Madillaa72d782014-07-02 15:31:19 -040060 switch (type)
61 {
62 case GL_FLOAT_MAT4:
63 case GL_FLOAT_MAT2:
64 case GL_FLOAT_MAT2x4:
65 case GL_FLOAT_MAT3x4:
66 case GL_FLOAT_MAT4x2:
67 case GL_FLOAT_MAT4x3:
68 case GL_FLOAT_VEC4:
69 case GL_INT_VEC4:
70 case GL_BOOL_VEC4:
71 case GL_UNSIGNED_INT_VEC4:
72 return 4;
73 case GL_FLOAT_MAT3:
74 case GL_FLOAT_MAT2x3:
75 case GL_FLOAT_MAT3x2:
76 case GL_FLOAT_VEC3:
77 case GL_INT_VEC3:
78 case GL_BOOL_VEC3:
79 case GL_UNSIGNED_INT_VEC3:
80 return 3;
81 case GL_FLOAT_VEC2:
82 case GL_INT_VEC2:
83 case GL_BOOL_VEC2:
84 case GL_UNSIGNED_INT_VEC2:
85 return 2;
86 default:
87 ASSERT(gl::VariableComponentCount(type) == 1);
88 return 1;
gman@chromium.org8d804792012-10-17 21:33:48 +000089 }
90}
91
Jamie Madill183bde52014-07-02 15:31:19 -040092int VariablePacker::GetNumRows(sh::GLenum type)
gman@chromium.org8d804792012-10-17 21:33:48 +000093{
Jamie Madillaa72d782014-07-02 15:31:19 -040094 switch (type)
95 {
96 case GL_FLOAT_MAT4:
97 case GL_FLOAT_MAT2x4:
98 case GL_FLOAT_MAT3x4:
99 case GL_FLOAT_MAT4x3:
100 case GL_FLOAT_MAT4x2:
101 return 4;
102 case GL_FLOAT_MAT3:
103 case GL_FLOAT_MAT2x3:
104 case GL_FLOAT_MAT3x2:
105 return 3;
106 case GL_FLOAT_MAT2:
107 return 2;
108 default:
109 ASSERT(gl::VariableRowCount(type) == 1);
110 return 1;
gman@chromium.org8d804792012-10-17 21:33:48 +0000111 }
112}
113
114struct TVariableInfoComparer {
115 bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const
116 {
117 int lhsSortOrder = GetSortOrder(lhs.type);
118 int rhsSortOrder = GetSortOrder(rhs.type);
119 if (lhsSortOrder != rhsSortOrder) {
120 return lhsSortOrder < rhsSortOrder;
121 }
122 // Sort by largest first.
123 return lhs.size > rhs.size;
124 }
125};
126
127unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
128{
129 return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
130 kColumnMask) >> column;
131}
132
133void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
134{
135 unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
136 for (int r = 0; r < numRows; ++r) {
137 int row = topRow + r;
138 ASSERT((rows_[row] & columnFlags) == 0);
139 rows_[row] |= columnFlags;
140 }
141}
142
143bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
144{
145 ASSERT(destRow);
146
147 for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
148 ++topNonFullRow_) {
149 }
150
151 for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
152 --bottomNonFullRow_) {
153 }
154
155 if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
156 return false;
157 }
158
159 unsigned columnFlags = makeColumnFlags(column, 1);
160 int topGoodRow = 0;
161 int smallestGoodTop = -1;
162 int smallestGoodSize = maxRows_ + 1;
163 int bottomRow = bottomNonFullRow_ + 1;
164 bool found = false;
165 for (int row = topNonFullRow_; row <= bottomRow; ++row) {
166 bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
167 if (rowEmpty) {
168 if (!found) {
169 topGoodRow = row;
170 found = true;
171 }
172 } else {
173 if (found) {
174 int size = row - topGoodRow;
175 if (size >= numRows && size < smallestGoodSize) {
176 smallestGoodSize = size;
177 smallestGoodTop = topGoodRow;
178 }
179 }
180 found = false;
181 }
182 }
183 if (smallestGoodTop < 0) {
184 return false;
185 }
186
187 *destRow = smallestGoodTop;
188 if (destSize) {
189 *destSize = smallestGoodSize;
190 }
191 return true;
192}
193
194bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables)
195{
196 ASSERT(maxVectors > 0);
197 maxRows_ = maxVectors;
198 topNonFullRow_ = 0;
199 bottomNonFullRow_ = maxRows_ - 1;
200 TVariableInfoList variables(in_variables);
201
Nicolas Capens1d1c1152014-02-26 11:00:28 -0500202 // Check whether each variable fits in the available vectors.
203 for (size_t i = 0; i < variables.size(); i++) {
204 const TVariableInfo& variable = variables[i];
205 if (variable.size > maxVectors / GetNumRows(variable.type)) {
206 return false;
207 }
208 }
209
gman@chromium.org8d804792012-10-17 21:33:48 +0000210 // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
211 // order by type, then by size of array, largest first.
212 std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
213 rows_.clear();
214 rows_.resize(maxVectors, 0);
215
216 // Packs the 4 column variables.
217 size_t ii = 0;
218 for (; ii < variables.size(); ++ii) {
219 const TVariableInfo& variable = variables[ii];
220 if (GetNumComponentsPerRow(variable.type) != 4) {
221 break;
222 }
223 topNonFullRow_ += GetNumRows(variable.type) * variable.size;
224 }
225
226 if (topNonFullRow_ > maxRows_) {
227 return false;
228 }
229
230 // Packs the 3 column variables.
231 int num3ColumnRows = 0;
232 for (; ii < variables.size(); ++ii) {
233 const TVariableInfo& variable = variables[ii];
234 if (GetNumComponentsPerRow(variable.type) != 3) {
235 break;
236 }
237 num3ColumnRows += GetNumRows(variable.type) * variable.size;
238 }
239
240 if (topNonFullRow_ + num3ColumnRows > maxRows_) {
241 return false;
242 }
243
244 fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
245
246 // Packs the 2 column variables.
247 int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
248 int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
249 int rowsAvailableInColumns01 = twoColumnRowsAvailable;
250 int rowsAvailableInColumns23 = twoColumnRowsAvailable;
251 for (; ii < variables.size(); ++ii) {
252 const TVariableInfo& variable = variables[ii];
253 if (GetNumComponentsPerRow(variable.type) != 2) {
254 break;
255 }
256 int numRows = GetNumRows(variable.type) * variable.size;
257 if (numRows <= rowsAvailableInColumns01) {
258 rowsAvailableInColumns01 -= numRows;
259 } else if (numRows <= rowsAvailableInColumns23) {
260 rowsAvailableInColumns23 -= numRows;
261 } else {
262 return false;
263 }
264 }
265
266 int numRowsUsedInColumns01 =
267 twoColumnRowsAvailable - rowsAvailableInColumns01;
268 int numRowsUsedInColumns23 =
269 twoColumnRowsAvailable - rowsAvailableInColumns23;
270 fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
271 fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
272 2, 2);
273
274 // Packs the 1 column variables.
275 for (; ii < variables.size(); ++ii) {
276 const TVariableInfo& variable = variables[ii];
277 ASSERT(1 == GetNumComponentsPerRow(variable.type));
278 int numRows = GetNumRows(variable.type) * variable.size;
279 int smallestColumn = -1;
280 int smallestSize = maxRows_ + 1;
281 int topRow = -1;
282 for (int column = 0; column < kNumColumns; ++column) {
283 int row = 0;
284 int size = 0;
285 if (searchColumn(column, numRows, &row, &size)) {
286 if (size < smallestSize) {
287 smallestSize = size;
288 smallestColumn = column;
289 topRow = row;
290 }
291 }
292 }
293
294 if (smallestColumn < 0) {
295 return false;
296 }
297
298 fillColumns(topRow, numRows, smallestColumn, 1);
299 }
300
301 ASSERT(variables.size() == ii);
302
303 return true;
304}
305
306
307