blob: c68767769045a16e066f426a1729a66d2a9180f1 [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 Madill183bde52014-07-02 15:31:19 -040012int VariablePacker::GetNumComponentsPerRow(sh::GLenum type)
gman@chromium.org8d804792012-10-17 21:33:48 +000013{
Jamie Madillaa72d782014-07-02 15:31:19 -040014 switch (type)
15 {
16 case GL_FLOAT_MAT4:
17 case GL_FLOAT_MAT2:
18 case GL_FLOAT_MAT2x4:
19 case GL_FLOAT_MAT3x4:
20 case GL_FLOAT_MAT4x2:
21 case GL_FLOAT_MAT4x3:
22 case GL_FLOAT_VEC4:
23 case GL_INT_VEC4:
24 case GL_BOOL_VEC4:
25 case GL_UNSIGNED_INT_VEC4:
26 return 4;
27 case GL_FLOAT_MAT3:
28 case GL_FLOAT_MAT2x3:
29 case GL_FLOAT_MAT3x2:
30 case GL_FLOAT_VEC3:
31 case GL_INT_VEC3:
32 case GL_BOOL_VEC3:
33 case GL_UNSIGNED_INT_VEC3:
34 return 3;
35 case GL_FLOAT_VEC2:
36 case GL_INT_VEC2:
37 case GL_BOOL_VEC2:
38 case GL_UNSIGNED_INT_VEC2:
39 return 2;
40 default:
41 ASSERT(gl::VariableComponentCount(type) == 1);
42 return 1;
gman@chromium.org8d804792012-10-17 21:33:48 +000043 }
44}
45
Jamie Madill183bde52014-07-02 15:31:19 -040046int VariablePacker::GetNumRows(sh::GLenum type)
gman@chromium.org8d804792012-10-17 21:33:48 +000047{
Jamie Madillaa72d782014-07-02 15:31:19 -040048 switch (type)
49 {
50 case GL_FLOAT_MAT4:
51 case GL_FLOAT_MAT2x4:
52 case GL_FLOAT_MAT3x4:
53 case GL_FLOAT_MAT4x3:
54 case GL_FLOAT_MAT4x2:
55 return 4;
56 case GL_FLOAT_MAT3:
57 case GL_FLOAT_MAT2x3:
58 case GL_FLOAT_MAT3x2:
59 return 3;
60 case GL_FLOAT_MAT2:
61 return 2;
62 default:
63 ASSERT(gl::VariableRowCount(type) == 1);
64 return 1;
gman@chromium.org8d804792012-10-17 21:33:48 +000065 }
66}
67
Jamie Madill865d1452014-07-02 15:31:20 -040068struct TVariableInfoComparer
69{
gman@chromium.org8d804792012-10-17 21:33:48 +000070 bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const
71 {
Jamie Madill865d1452014-07-02 15:31:20 -040072 int lhsSortOrder = gl::VariableSortOrder(lhs.type);
73 int rhsSortOrder = gl::VariableSortOrder(rhs.type);
gman@chromium.org8d804792012-10-17 21:33:48 +000074 if (lhsSortOrder != rhsSortOrder) {
75 return lhsSortOrder < rhsSortOrder;
76 }
77 // Sort by largest first.
78 return lhs.size > rhs.size;
79 }
80};
81
82unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
83{
84 return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
85 kColumnMask) >> column;
86}
87
88void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
89{
90 unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
91 for (int r = 0; r < numRows; ++r) {
92 int row = topRow + r;
93 ASSERT((rows_[row] & columnFlags) == 0);
94 rows_[row] |= columnFlags;
95 }
96}
97
98bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
99{
100 ASSERT(destRow);
101
102 for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
103 ++topNonFullRow_) {
104 }
105
106 for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
107 --bottomNonFullRow_) {
108 }
109
110 if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
111 return false;
112 }
113
114 unsigned columnFlags = makeColumnFlags(column, 1);
115 int topGoodRow = 0;
116 int smallestGoodTop = -1;
117 int smallestGoodSize = maxRows_ + 1;
118 int bottomRow = bottomNonFullRow_ + 1;
119 bool found = false;
120 for (int row = topNonFullRow_; row <= bottomRow; ++row) {
121 bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
122 if (rowEmpty) {
123 if (!found) {
124 topGoodRow = row;
125 found = true;
126 }
127 } else {
128 if (found) {
129 int size = row - topGoodRow;
130 if (size >= numRows && size < smallestGoodSize) {
131 smallestGoodSize = size;
132 smallestGoodTop = topGoodRow;
133 }
134 }
135 found = false;
136 }
137 }
138 if (smallestGoodTop < 0) {
139 return false;
140 }
141
142 *destRow = smallestGoodTop;
143 if (destSize) {
144 *destSize = smallestGoodSize;
145 }
146 return true;
147}
148
149bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables)
150{
151 ASSERT(maxVectors > 0);
152 maxRows_ = maxVectors;
153 topNonFullRow_ = 0;
154 bottomNonFullRow_ = maxRows_ - 1;
155 TVariableInfoList variables(in_variables);
156
Nicolas Capens1d1c1152014-02-26 11:00:28 -0500157 // Check whether each variable fits in the available vectors.
158 for (size_t i = 0; i < variables.size(); i++) {
159 const TVariableInfo& variable = variables[i];
160 if (variable.size > maxVectors / GetNumRows(variable.type)) {
161 return false;
162 }
163 }
164
gman@chromium.org8d804792012-10-17 21:33:48 +0000165 // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
166 // order by type, then by size of array, largest first.
167 std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
168 rows_.clear();
169 rows_.resize(maxVectors, 0);
170
171 // Packs the 4 column variables.
172 size_t ii = 0;
173 for (; ii < variables.size(); ++ii) {
174 const TVariableInfo& variable = variables[ii];
175 if (GetNumComponentsPerRow(variable.type) != 4) {
176 break;
177 }
178 topNonFullRow_ += GetNumRows(variable.type) * variable.size;
179 }
180
181 if (topNonFullRow_ > maxRows_) {
182 return false;
183 }
184
185 // Packs the 3 column variables.
186 int num3ColumnRows = 0;
187 for (; ii < variables.size(); ++ii) {
188 const TVariableInfo& variable = variables[ii];
189 if (GetNumComponentsPerRow(variable.type) != 3) {
190 break;
191 }
192 num3ColumnRows += GetNumRows(variable.type) * variable.size;
193 }
194
195 if (topNonFullRow_ + num3ColumnRows > maxRows_) {
196 return false;
197 }
198
199 fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
200
201 // Packs the 2 column variables.
202 int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
203 int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
204 int rowsAvailableInColumns01 = twoColumnRowsAvailable;
205 int rowsAvailableInColumns23 = twoColumnRowsAvailable;
206 for (; ii < variables.size(); ++ii) {
207 const TVariableInfo& variable = variables[ii];
208 if (GetNumComponentsPerRow(variable.type) != 2) {
209 break;
210 }
211 int numRows = GetNumRows(variable.type) * variable.size;
212 if (numRows <= rowsAvailableInColumns01) {
213 rowsAvailableInColumns01 -= numRows;
214 } else if (numRows <= rowsAvailableInColumns23) {
215 rowsAvailableInColumns23 -= numRows;
216 } else {
217 return false;
218 }
219 }
220
221 int numRowsUsedInColumns01 =
222 twoColumnRowsAvailable - rowsAvailableInColumns01;
223 int numRowsUsedInColumns23 =
224 twoColumnRowsAvailable - rowsAvailableInColumns23;
225 fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
226 fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
227 2, 2);
228
229 // Packs the 1 column variables.
230 for (; ii < variables.size(); ++ii) {
231 const TVariableInfo& variable = variables[ii];
232 ASSERT(1 == GetNumComponentsPerRow(variable.type));
233 int numRows = GetNumRows(variable.type) * variable.size;
234 int smallestColumn = -1;
235 int smallestSize = maxRows_ + 1;
236 int topRow = -1;
237 for (int column = 0; column < kNumColumns; ++column) {
238 int row = 0;
239 int size = 0;
240 if (searchColumn(column, numRows, &row, &size)) {
241 if (size < smallestSize) {
242 smallestSize = size;
243 smallestColumn = column;
244 topRow = row;
245 }
246 }
247 }
248
249 if (smallestColumn < 0) {
250 return false;
251 }
252
253 fillColumns(topRow, numRows, smallestColumn, 1);
254 }
255
256 ASSERT(variables.size() == ii);
257
258 return true;
259}
260
261
262