blob: 9c4c9376b542c3cff4904d97ea46accc617edf98 [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//
gman@chromium.org8d804792012-10-17 21:33:48 +00006
7#include <algorithm>
gman@chromium.org8d804792012-10-17 21:33:48 +00008
Jamie Madille294bb82014-07-17 14:16:26 -04009#include "angle_gl.h"
10
11#include "compiler/translator/VariablePacker.h"
12#include "common/utilities.h"
13
Jamie Madill183bde52014-07-02 15:31:19 -040014int VariablePacker::GetNumComponentsPerRow(sh::GLenum type)
gman@chromium.org8d804792012-10-17 21:33:48 +000015{
Jamie Madillaa72d782014-07-02 15:31:19 -040016 switch (type)
17 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -050018 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 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 return 3;
37 case GL_FLOAT_VEC2:
38 case GL_INT_VEC2:
39 case GL_BOOL_VEC2:
40 case GL_UNSIGNED_INT_VEC2:
41 return 2;
42 default:
43 ASSERT(gl::VariableComponentCount(type) == 1);
44 return 1;
gman@chromium.org8d804792012-10-17 21:33:48 +000045 }
46}
47
Jamie Madill183bde52014-07-02 15:31:19 -040048int VariablePacker::GetNumRows(sh::GLenum type)
gman@chromium.org8d804792012-10-17 21:33:48 +000049{
Jamie Madillaa72d782014-07-02 15:31:19 -040050 switch (type)
51 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -050052 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 return 4;
58 case GL_FLOAT_MAT3:
59 case GL_FLOAT_MAT2x3:
60 case GL_FLOAT_MAT3x2:
61 return 3;
62 case GL_FLOAT_MAT2:
63 return 2;
64 default:
65 ASSERT(gl::VariableRowCount(type) == 1);
66 return 1;
gman@chromium.org8d804792012-10-17 21:33:48 +000067 }
68}
69
Jamie Madill865d1452014-07-02 15:31:20 -040070struct TVariableInfoComparer
71{
Jamie Madilla718c1e2014-07-02 15:31:22 -040072 bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const
gman@chromium.org8d804792012-10-17 21:33:48 +000073 {
Jamie Madill865d1452014-07-02 15:31:20 -040074 int lhsSortOrder = gl::VariableSortOrder(lhs.type);
75 int rhsSortOrder = gl::VariableSortOrder(rhs.type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -050076 if (lhsSortOrder != rhsSortOrder)
77 {
gman@chromium.org8d804792012-10-17 21:33:48 +000078 return lhsSortOrder < rhsSortOrder;
79 }
80 // Sort by largest first.
Jamie Madilla718c1e2014-07-02 15:31:22 -040081 return lhs.arraySize > rhs.arraySize;
gman@chromium.org8d804792012-10-17 21:33:48 +000082 }
83};
84
85unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
86{
Jamie Madilld7b1ab52016-12-12 14:42:19 -050087 return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & kColumnMask) >> column;
gman@chromium.org8d804792012-10-17 21:33:48 +000088}
89
90void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
91{
92 unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
Jamie Madilld7b1ab52016-12-12 14:42:19 -050093 for (int r = 0; r < numRows; ++r)
94 {
gman@chromium.org8d804792012-10-17 21:33:48 +000095 int row = topRow + r;
96 ASSERT((rows_[row] & columnFlags) == 0);
97 rows_[row] |= columnFlags;
98 }
99}
100
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500101bool VariablePacker::searchColumn(int column, int numRows, int *destRow, int *destSize)
gman@chromium.org8d804792012-10-17 21:33:48 +0000102{
103 ASSERT(destRow);
104
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500105 for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; ++topNonFullRow_)
106 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000107 }
108
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500109 for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; --bottomNonFullRow_)
110 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000111 }
112
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500113 if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows)
114 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000115 return false;
116 }
117
118 unsigned columnFlags = makeColumnFlags(column, 1);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500119 int topGoodRow = 0;
120 int smallestGoodTop = -1;
gman@chromium.org8d804792012-10-17 21:33:48 +0000121 int smallestGoodSize = maxRows_ + 1;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500122 int bottomRow = bottomNonFullRow_ + 1;
123 bool found = false;
124 for (int row = topNonFullRow_; row <= bottomRow; ++row)
125 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000126 bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500127 if (rowEmpty)
128 {
129 if (!found)
130 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000131 topGoodRow = row;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500132 found = true;
gman@chromium.org8d804792012-10-17 21:33:48 +0000133 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500134 }
135 else
136 {
137 if (found)
138 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000139 int size = row - topGoodRow;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500140 if (size >= numRows && size < smallestGoodSize)
141 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000142 smallestGoodSize = size;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500143 smallestGoodTop = topGoodRow;
gman@chromium.org8d804792012-10-17 21:33:48 +0000144 }
145 }
146 found = false;
147 }
148 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500149 if (smallestGoodTop < 0)
150 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000151 return false;
152 }
153
154 *destRow = smallestGoodTop;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500155 if (destSize)
156 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000157 *destSize = smallestGoodSize;
158 }
159 return true;
160}
161
Corentin Walleze58e1412016-07-18 16:40:46 -0400162bool VariablePacker::CheckVariablesWithinPackingLimits(
163 unsigned int maxVectors,
164 const std::vector<sh::ShaderVariable> &in_variables)
gman@chromium.org8d804792012-10-17 21:33:48 +0000165{
166 ASSERT(maxVectors > 0);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500167 maxRows_ = maxVectors;
168 topNonFullRow_ = 0;
gman@chromium.org8d804792012-10-17 21:33:48 +0000169 bottomNonFullRow_ = maxRows_ - 1;
Corentin Walleze58e1412016-07-18 16:40:46 -0400170 std::vector<sh::ShaderVariable> variables;
171
172 for (const auto &variable : in_variables)
173 {
174 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse,
175 &variables);
176 }
gman@chromium.org8d804792012-10-17 21:33:48 +0000177
Nicolas Capens1d1c1152014-02-26 11:00:28 -0500178 // Check whether each variable fits in the available vectors.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500179 for (size_t i = 0; i < variables.size(); i++)
180 {
Jamie Madilla718c1e2014-07-02 15:31:22 -0400181 const sh::ShaderVariable &variable = variables[i];
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500182 if (variable.elementCount() > maxVectors / GetNumRows(variable.type))
183 {
Nicolas Capens1d1c1152014-02-26 11:00:28 -0500184 return false;
185 }
186 }
187
gman@chromium.org8d804792012-10-17 21:33:48 +0000188 // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
189 // order by type, then by size of array, largest first.
190 std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
191 rows_.clear();
192 rows_.resize(maxVectors, 0);
193
194 // Packs the 4 column variables.
195 size_t ii = 0;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500196 for (; ii < variables.size(); ++ii)
197 {
Jamie Madilla718c1e2014-07-02 15:31:22 -0400198 const sh::ShaderVariable &variable = variables[ii];
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500199 if (GetNumComponentsPerRow(variable.type) != 4)
200 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000201 break;
202 }
Jamie Madilla718c1e2014-07-02 15:31:22 -0400203 topNonFullRow_ += GetNumRows(variable.type) * variable.elementCount();
gman@chromium.org8d804792012-10-17 21:33:48 +0000204 }
205
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500206 if (topNonFullRow_ > maxRows_)
207 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000208 return false;
209 }
210
211 // Packs the 3 column variables.
212 int num3ColumnRows = 0;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500213 for (; ii < variables.size(); ++ii)
214 {
Jamie Madilla718c1e2014-07-02 15:31:22 -0400215 const sh::ShaderVariable &variable = variables[ii];
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500216 if (GetNumComponentsPerRow(variable.type) != 3)
217 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000218 break;
219 }
Jamie Madilla718c1e2014-07-02 15:31:22 -0400220 num3ColumnRows += GetNumRows(variable.type) * variable.elementCount();
gman@chromium.org8d804792012-10-17 21:33:48 +0000221 }
222
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500223 if (topNonFullRow_ + num3ColumnRows > maxRows_)
224 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000225 return false;
226 }
227
228 fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
229
230 // Packs the 2 column variables.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500231 int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
232 int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
gman@chromium.org8d804792012-10-17 21:33:48 +0000233 int rowsAvailableInColumns01 = twoColumnRowsAvailable;
234 int rowsAvailableInColumns23 = twoColumnRowsAvailable;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500235 for (; ii < variables.size(); ++ii)
236 {
Jamie Madilla718c1e2014-07-02 15:31:22 -0400237 const sh::ShaderVariable &variable = variables[ii];
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500238 if (GetNumComponentsPerRow(variable.type) != 2)
239 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000240 break;
241 }
Jamie Madilla718c1e2014-07-02 15:31:22 -0400242 int numRows = GetNumRows(variable.type) * variable.elementCount();
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500243 if (numRows <= rowsAvailableInColumns01)
244 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000245 rowsAvailableInColumns01 -= numRows;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500246 }
247 else if (numRows <= rowsAvailableInColumns23)
248 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000249 rowsAvailableInColumns23 -= numRows;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500250 }
251 else
252 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000253 return false;
254 }
255 }
256
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500257 int numRowsUsedInColumns01 = twoColumnRowsAvailable - rowsAvailableInColumns01;
258 int numRowsUsedInColumns23 = twoColumnRowsAvailable - rowsAvailableInColumns23;
gman@chromium.org8d804792012-10-17 21:33:48 +0000259 fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500260 fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, 2, 2);
gman@chromium.org8d804792012-10-17 21:33:48 +0000261
262 // Packs the 1 column variables.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500263 for (; ii < variables.size(); ++ii)
264 {
Jamie Madilla718c1e2014-07-02 15:31:22 -0400265 const sh::ShaderVariable &variable = variables[ii];
gman@chromium.org8d804792012-10-17 21:33:48 +0000266 ASSERT(1 == GetNumComponentsPerRow(variable.type));
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500267 int numRows = GetNumRows(variable.type) * variable.elementCount();
gman@chromium.org8d804792012-10-17 21:33:48 +0000268 int smallestColumn = -1;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500269 int smallestSize = maxRows_ + 1;
270 int topRow = -1;
271 for (int column = 0; column < kNumColumns; ++column)
272 {
273 int row = 0;
gman@chromium.org8d804792012-10-17 21:33:48 +0000274 int size = 0;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500275 if (searchColumn(column, numRows, &row, &size))
276 {
277 if (size < smallestSize)
278 {
279 smallestSize = size;
gman@chromium.org8d804792012-10-17 21:33:48 +0000280 smallestColumn = column;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500281 topRow = row;
gman@chromium.org8d804792012-10-17 21:33:48 +0000282 }
283 }
284 }
285
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500286 if (smallestColumn < 0)
287 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000288 return false;
289 }
290
291 fillColumns(topRow, numRows, smallestColumn, 1);
292 }
293
294 ASSERT(variables.size() == ii);
295
296 return true;
297}