xref: /aosp_15_r20/external/angle/src/compiler/translator/VariablePacker.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // Check whether variables fit within packing limits according to the packing rules from the GLSL ES
7*8975f5c5SAndroid Build Coastguard Worker // 1.00.17 spec, Appendix A, section 7.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include <algorithm>
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "angle_gl.h"
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/VariablePacker.h"
15*8975f5c5SAndroid Build Coastguard Worker 
16*8975f5c5SAndroid Build Coastguard Worker namespace sh
17*8975f5c5SAndroid Build Coastguard Worker {
18*8975f5c5SAndroid Build Coastguard Worker 
19*8975f5c5SAndroid Build Coastguard Worker namespace
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker 
22*8975f5c5SAndroid Build Coastguard Worker // Expand the variable so that struct variables are split into their individual fields.
23*8975f5c5SAndroid Build Coastguard Worker // Will not set the mappedName or staticUse fields on the expanded variables.
24*8975f5c5SAndroid Build Coastguard Worker void ExpandVariable(const ShaderVariable &variable,
25*8975f5c5SAndroid Build Coastguard Worker                     const std::string &name,
26*8975f5c5SAndroid Build Coastguard Worker                     std::vector<ShaderVariable> *expanded);
27*8975f5c5SAndroid Build Coastguard Worker 
ExpandStructVariable(const ShaderVariable & variable,const std::string & name,std::vector<ShaderVariable> * expanded)28*8975f5c5SAndroid Build Coastguard Worker void ExpandStructVariable(const ShaderVariable &variable,
29*8975f5c5SAndroid Build Coastguard Worker                           const std::string &name,
30*8975f5c5SAndroid Build Coastguard Worker                           std::vector<ShaderVariable> *expanded)
31*8975f5c5SAndroid Build Coastguard Worker {
32*8975f5c5SAndroid Build Coastguard Worker     ASSERT(variable.isStruct());
33*8975f5c5SAndroid Build Coastguard Worker 
34*8975f5c5SAndroid Build Coastguard Worker     const std::vector<ShaderVariable> &fields = variable.fields;
35*8975f5c5SAndroid Build Coastguard Worker 
36*8975f5c5SAndroid Build Coastguard Worker     for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
37*8975f5c5SAndroid Build Coastguard Worker     {
38*8975f5c5SAndroid Build Coastguard Worker         const ShaderVariable &field = fields[fieldIndex];
39*8975f5c5SAndroid Build Coastguard Worker         ExpandVariable(field, name + "." + field.name, expanded);
40*8975f5c5SAndroid Build Coastguard Worker     }
41*8975f5c5SAndroid Build Coastguard Worker }
42*8975f5c5SAndroid Build Coastguard Worker 
ExpandStructArrayVariable(const ShaderVariable & variable,unsigned int arrayNestingIndex,const std::string & name,std::vector<ShaderVariable> * expanded)43*8975f5c5SAndroid Build Coastguard Worker void ExpandStructArrayVariable(const ShaderVariable &variable,
44*8975f5c5SAndroid Build Coastguard Worker                                unsigned int arrayNestingIndex,
45*8975f5c5SAndroid Build Coastguard Worker                                const std::string &name,
46*8975f5c5SAndroid Build Coastguard Worker                                std::vector<ShaderVariable> *expanded)
47*8975f5c5SAndroid Build Coastguard Worker {
48*8975f5c5SAndroid Build Coastguard Worker     // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
49*8975f5c5SAndroid Build Coastguard Worker     // innermost.
50*8975f5c5SAndroid Build Coastguard Worker     const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex);
51*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
52*8975f5c5SAndroid Build Coastguard Worker     {
53*8975f5c5SAndroid Build Coastguard Worker         const std::string elementName = name + ArrayString(arrayElement);
54*8975f5c5SAndroid Build Coastguard Worker         if (arrayNestingIndex + 1u < variable.arraySizes.size())
55*8975f5c5SAndroid Build Coastguard Worker         {
56*8975f5c5SAndroid Build Coastguard Worker             ExpandStructArrayVariable(variable, arrayNestingIndex + 1u, elementName, expanded);
57*8975f5c5SAndroid Build Coastguard Worker         }
58*8975f5c5SAndroid Build Coastguard Worker         else
59*8975f5c5SAndroid Build Coastguard Worker         {
60*8975f5c5SAndroid Build Coastguard Worker             ExpandStructVariable(variable, elementName, expanded);
61*8975f5c5SAndroid Build Coastguard Worker         }
62*8975f5c5SAndroid Build Coastguard Worker     }
63*8975f5c5SAndroid Build Coastguard Worker }
64*8975f5c5SAndroid Build Coastguard Worker 
ExpandVariable(const ShaderVariable & variable,const std::string & name,std::vector<ShaderVariable> * expanded)65*8975f5c5SAndroid Build Coastguard Worker void ExpandVariable(const ShaderVariable &variable,
66*8975f5c5SAndroid Build Coastguard Worker                     const std::string &name,
67*8975f5c5SAndroid Build Coastguard Worker                     std::vector<ShaderVariable> *expanded)
68*8975f5c5SAndroid Build Coastguard Worker {
69*8975f5c5SAndroid Build Coastguard Worker     if (variable.isStruct())
70*8975f5c5SAndroid Build Coastguard Worker     {
71*8975f5c5SAndroid Build Coastguard Worker         if (variable.isArray())
72*8975f5c5SAndroid Build Coastguard Worker         {
73*8975f5c5SAndroid Build Coastguard Worker             ExpandStructArrayVariable(variable, 0u, name, expanded);
74*8975f5c5SAndroid Build Coastguard Worker         }
75*8975f5c5SAndroid Build Coastguard Worker         else
76*8975f5c5SAndroid Build Coastguard Worker         {
77*8975f5c5SAndroid Build Coastguard Worker             ExpandStructVariable(variable, name, expanded);
78*8975f5c5SAndroid Build Coastguard Worker         }
79*8975f5c5SAndroid Build Coastguard Worker     }
80*8975f5c5SAndroid Build Coastguard Worker     else
81*8975f5c5SAndroid Build Coastguard Worker     {
82*8975f5c5SAndroid Build Coastguard Worker         ShaderVariable expandedVar = variable;
83*8975f5c5SAndroid Build Coastguard Worker         expandedVar.name           = name;
84*8975f5c5SAndroid Build Coastguard Worker 
85*8975f5c5SAndroid Build Coastguard Worker         expanded->push_back(expandedVar);
86*8975f5c5SAndroid Build Coastguard Worker     }
87*8975f5c5SAndroid Build Coastguard Worker }
88*8975f5c5SAndroid Build Coastguard Worker 
GetVariablePackingRows(const ShaderVariable & variable)89*8975f5c5SAndroid Build Coastguard Worker int GetVariablePackingRows(const ShaderVariable &variable)
90*8975f5c5SAndroid Build Coastguard Worker {
91*8975f5c5SAndroid Build Coastguard Worker     return GetTypePackingRows(variable.type) * variable.getArraySizeProduct();
92*8975f5c5SAndroid Build Coastguard Worker }
93*8975f5c5SAndroid Build Coastguard Worker 
94*8975f5c5SAndroid Build Coastguard Worker class VariablePacker
95*8975f5c5SAndroid Build Coastguard Worker {
96*8975f5c5SAndroid Build Coastguard Worker   public:
97*8975f5c5SAndroid Build Coastguard Worker     bool checkExpandedVariablesWithinPackingLimits(unsigned int maxVectors,
98*8975f5c5SAndroid Build Coastguard Worker                                                    std::vector<sh::ShaderVariable> *variables);
99*8975f5c5SAndroid Build Coastguard Worker 
100*8975f5c5SAndroid Build Coastguard Worker   private:
101*8975f5c5SAndroid Build Coastguard Worker     static const int kNumColumns      = 4;
102*8975f5c5SAndroid Build Coastguard Worker     static const unsigned kColumnMask = (1 << kNumColumns) - 1;
103*8975f5c5SAndroid Build Coastguard Worker 
104*8975f5c5SAndroid Build Coastguard Worker     unsigned makeColumnFlags(int column, int numComponentsPerRow);
105*8975f5c5SAndroid Build Coastguard Worker     void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
106*8975f5c5SAndroid Build Coastguard Worker     bool searchColumn(int column, int numRows, int *destRow, int *destSize);
107*8975f5c5SAndroid Build Coastguard Worker 
108*8975f5c5SAndroid Build Coastguard Worker     int topNonFullRow_;
109*8975f5c5SAndroid Build Coastguard Worker     int bottomNonFullRow_;
110*8975f5c5SAndroid Build Coastguard Worker     int maxRows_;
111*8975f5c5SAndroid Build Coastguard Worker     std::vector<unsigned> rows_;
112*8975f5c5SAndroid Build Coastguard Worker };
113*8975f5c5SAndroid Build Coastguard Worker 
114*8975f5c5SAndroid Build Coastguard Worker struct TVariableInfoComparer
115*8975f5c5SAndroid Build Coastguard Worker {
operator ()sh::__anone7e802c40111::TVariableInfoComparer116*8975f5c5SAndroid Build Coastguard Worker     bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const
117*8975f5c5SAndroid Build Coastguard Worker     {
118*8975f5c5SAndroid Build Coastguard Worker         int lhsSortOrder = gl::VariableSortOrder(lhs.type);
119*8975f5c5SAndroid Build Coastguard Worker         int rhsSortOrder = gl::VariableSortOrder(rhs.type);
120*8975f5c5SAndroid Build Coastguard Worker         if (lhsSortOrder != rhsSortOrder)
121*8975f5c5SAndroid Build Coastguard Worker         {
122*8975f5c5SAndroid Build Coastguard Worker             return lhsSortOrder < rhsSortOrder;
123*8975f5c5SAndroid Build Coastguard Worker         }
124*8975f5c5SAndroid Build Coastguard Worker         // Sort by largest first.
125*8975f5c5SAndroid Build Coastguard Worker         return lhs.getArraySizeProduct() > rhs.getArraySizeProduct();
126*8975f5c5SAndroid Build Coastguard Worker     }
127*8975f5c5SAndroid Build Coastguard Worker };
128*8975f5c5SAndroid Build Coastguard Worker 
makeColumnFlags(int column,int numComponentsPerRow)129*8975f5c5SAndroid Build Coastguard Worker unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
130*8975f5c5SAndroid Build Coastguard Worker {
131*8975f5c5SAndroid Build Coastguard Worker     return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & kColumnMask) >> column;
132*8975f5c5SAndroid Build Coastguard Worker }
133*8975f5c5SAndroid Build Coastguard Worker 
fillColumns(int topRow,int numRows,int column,int numComponentsPerRow)134*8975f5c5SAndroid Build Coastguard Worker void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
135*8975f5c5SAndroid Build Coastguard Worker {
136*8975f5c5SAndroid Build Coastguard Worker     unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
137*8975f5c5SAndroid Build Coastguard Worker     for (int r = 0; r < numRows; ++r)
138*8975f5c5SAndroid Build Coastguard Worker     {
139*8975f5c5SAndroid Build Coastguard Worker         int row = topRow + r;
140*8975f5c5SAndroid Build Coastguard Worker         ASSERT((rows_[row] & columnFlags) == 0);
141*8975f5c5SAndroid Build Coastguard Worker         rows_[row] |= columnFlags;
142*8975f5c5SAndroid Build Coastguard Worker     }
143*8975f5c5SAndroid Build Coastguard Worker }
144*8975f5c5SAndroid Build Coastguard Worker 
searchColumn(int column,int numRows,int * destRow,int * destSize)145*8975f5c5SAndroid Build Coastguard Worker bool VariablePacker::searchColumn(int column, int numRows, int *destRow, int *destSize)
146*8975f5c5SAndroid Build Coastguard Worker {
147*8975f5c5SAndroid Build Coastguard Worker     ASSERT(destRow);
148*8975f5c5SAndroid Build Coastguard Worker 
149*8975f5c5SAndroid Build Coastguard Worker     for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; ++topNonFullRow_)
150*8975f5c5SAndroid Build Coastguard Worker     {
151*8975f5c5SAndroid Build Coastguard Worker     }
152*8975f5c5SAndroid Build Coastguard Worker 
153*8975f5c5SAndroid Build Coastguard Worker     for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; --bottomNonFullRow_)
154*8975f5c5SAndroid Build Coastguard Worker     {
155*8975f5c5SAndroid Build Coastguard Worker     }
156*8975f5c5SAndroid Build Coastguard Worker 
157*8975f5c5SAndroid Build Coastguard Worker     if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows)
158*8975f5c5SAndroid Build Coastguard Worker     {
159*8975f5c5SAndroid Build Coastguard Worker         return false;
160*8975f5c5SAndroid Build Coastguard Worker     }
161*8975f5c5SAndroid Build Coastguard Worker 
162*8975f5c5SAndroid Build Coastguard Worker     unsigned columnFlags = makeColumnFlags(column, 1);
163*8975f5c5SAndroid Build Coastguard Worker     int topGoodRow       = 0;
164*8975f5c5SAndroid Build Coastguard Worker     int smallestGoodTop  = -1;
165*8975f5c5SAndroid Build Coastguard Worker     int smallestGoodSize = maxRows_ + 1;
166*8975f5c5SAndroid Build Coastguard Worker     int bottomRow        = bottomNonFullRow_ + 1;
167*8975f5c5SAndroid Build Coastguard Worker     bool found           = false;
168*8975f5c5SAndroid Build Coastguard Worker     for (int row = topNonFullRow_; row <= bottomRow; ++row)
169*8975f5c5SAndroid Build Coastguard Worker     {
170*8975f5c5SAndroid Build Coastguard Worker         bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
171*8975f5c5SAndroid Build Coastguard Worker         if (rowEmpty)
172*8975f5c5SAndroid Build Coastguard Worker         {
173*8975f5c5SAndroid Build Coastguard Worker             if (!found)
174*8975f5c5SAndroid Build Coastguard Worker             {
175*8975f5c5SAndroid Build Coastguard Worker                 topGoodRow = row;
176*8975f5c5SAndroid Build Coastguard Worker                 found      = true;
177*8975f5c5SAndroid Build Coastguard Worker             }
178*8975f5c5SAndroid Build Coastguard Worker         }
179*8975f5c5SAndroid Build Coastguard Worker         else
180*8975f5c5SAndroid Build Coastguard Worker         {
181*8975f5c5SAndroid Build Coastguard Worker             if (found)
182*8975f5c5SAndroid Build Coastguard Worker             {
183*8975f5c5SAndroid Build Coastguard Worker                 int size = row - topGoodRow;
184*8975f5c5SAndroid Build Coastguard Worker                 if (size >= numRows && size < smallestGoodSize)
185*8975f5c5SAndroid Build Coastguard Worker                 {
186*8975f5c5SAndroid Build Coastguard Worker                     smallestGoodSize = size;
187*8975f5c5SAndroid Build Coastguard Worker                     smallestGoodTop  = topGoodRow;
188*8975f5c5SAndroid Build Coastguard Worker                 }
189*8975f5c5SAndroid Build Coastguard Worker             }
190*8975f5c5SAndroid Build Coastguard Worker             found = false;
191*8975f5c5SAndroid Build Coastguard Worker         }
192*8975f5c5SAndroid Build Coastguard Worker     }
193*8975f5c5SAndroid Build Coastguard Worker     if (smallestGoodTop < 0)
194*8975f5c5SAndroid Build Coastguard Worker     {
195*8975f5c5SAndroid Build Coastguard Worker         return false;
196*8975f5c5SAndroid Build Coastguard Worker     }
197*8975f5c5SAndroid Build Coastguard Worker 
198*8975f5c5SAndroid Build Coastguard Worker     *destRow = smallestGoodTop;
199*8975f5c5SAndroid Build Coastguard Worker     if (destSize)
200*8975f5c5SAndroid Build Coastguard Worker     {
201*8975f5c5SAndroid Build Coastguard Worker         *destSize = smallestGoodSize;
202*8975f5c5SAndroid Build Coastguard Worker     }
203*8975f5c5SAndroid Build Coastguard Worker     return true;
204*8975f5c5SAndroid Build Coastguard Worker }
205*8975f5c5SAndroid Build Coastguard Worker 
checkExpandedVariablesWithinPackingLimits(unsigned int maxVectors,std::vector<sh::ShaderVariable> * variables)206*8975f5c5SAndroid Build Coastguard Worker bool VariablePacker::checkExpandedVariablesWithinPackingLimits(
207*8975f5c5SAndroid Build Coastguard Worker     unsigned int maxVectors,
208*8975f5c5SAndroid Build Coastguard Worker     std::vector<sh::ShaderVariable> *variables)
209*8975f5c5SAndroid Build Coastguard Worker {
210*8975f5c5SAndroid Build Coastguard Worker     ASSERT(maxVectors > 0);
211*8975f5c5SAndroid Build Coastguard Worker     maxRows_          = maxVectors;
212*8975f5c5SAndroid Build Coastguard Worker     topNonFullRow_    = 0;
213*8975f5c5SAndroid Build Coastguard Worker     bottomNonFullRow_ = maxRows_ - 1;
214*8975f5c5SAndroid Build Coastguard Worker 
215*8975f5c5SAndroid Build Coastguard Worker     // Check whether each variable fits in the available vectors.
216*8975f5c5SAndroid Build Coastguard Worker     for (const sh::ShaderVariable &variable : *variables)
217*8975f5c5SAndroid Build Coastguard Worker     {
218*8975f5c5SAndroid Build Coastguard Worker         // Structs should have been expanded before reaching here.
219*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!variable.isStruct());
220*8975f5c5SAndroid Build Coastguard Worker         if (variable.getArraySizeProduct() > maxVectors / GetTypePackingRows(variable.type))
221*8975f5c5SAndroid Build Coastguard Worker         {
222*8975f5c5SAndroid Build Coastguard Worker             return false;
223*8975f5c5SAndroid Build Coastguard Worker         }
224*8975f5c5SAndroid Build Coastguard Worker     }
225*8975f5c5SAndroid Build Coastguard Worker 
226*8975f5c5SAndroid Build Coastguard Worker     // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
227*8975f5c5SAndroid Build Coastguard Worker     // order by type, then by size of array, largest first.
228*8975f5c5SAndroid Build Coastguard Worker     std::sort(variables->begin(), variables->end(), TVariableInfoComparer());
229*8975f5c5SAndroid Build Coastguard Worker     rows_.clear();
230*8975f5c5SAndroid Build Coastguard Worker     rows_.resize(maxVectors, 0);
231*8975f5c5SAndroid Build Coastguard Worker 
232*8975f5c5SAndroid Build Coastguard Worker     // Packs the 4 column variables.
233*8975f5c5SAndroid Build Coastguard Worker     size_t ii = 0;
234*8975f5c5SAndroid Build Coastguard Worker     for (; ii < variables->size(); ++ii)
235*8975f5c5SAndroid Build Coastguard Worker     {
236*8975f5c5SAndroid Build Coastguard Worker         const sh::ShaderVariable &variable = (*variables)[ii];
237*8975f5c5SAndroid Build Coastguard Worker         if (GetTypePackingComponentsPerRow(variable.type) != 4)
238*8975f5c5SAndroid Build Coastguard Worker         {
239*8975f5c5SAndroid Build Coastguard Worker             break;
240*8975f5c5SAndroid Build Coastguard Worker         }
241*8975f5c5SAndroid Build Coastguard Worker         topNonFullRow_ += GetVariablePackingRows(variable);
242*8975f5c5SAndroid Build Coastguard Worker         if (topNonFullRow_ > maxRows_)
243*8975f5c5SAndroid Build Coastguard Worker         {
244*8975f5c5SAndroid Build Coastguard Worker             return false;
245*8975f5c5SAndroid Build Coastguard Worker         }
246*8975f5c5SAndroid Build Coastguard Worker     }
247*8975f5c5SAndroid Build Coastguard Worker 
248*8975f5c5SAndroid Build Coastguard Worker     // Packs the 3 column variables.
249*8975f5c5SAndroid Build Coastguard Worker     int num3ColumnRows = 0;
250*8975f5c5SAndroid Build Coastguard Worker     for (; ii < variables->size(); ++ii)
251*8975f5c5SAndroid Build Coastguard Worker     {
252*8975f5c5SAndroid Build Coastguard Worker         const sh::ShaderVariable &variable = (*variables)[ii];
253*8975f5c5SAndroid Build Coastguard Worker         if (GetTypePackingComponentsPerRow(variable.type) != 3)
254*8975f5c5SAndroid Build Coastguard Worker         {
255*8975f5c5SAndroid Build Coastguard Worker             break;
256*8975f5c5SAndroid Build Coastguard Worker         }
257*8975f5c5SAndroid Build Coastguard Worker 
258*8975f5c5SAndroid Build Coastguard Worker         num3ColumnRows += GetVariablePackingRows(variable);
259*8975f5c5SAndroid Build Coastguard Worker         if (topNonFullRow_ + num3ColumnRows > maxRows_)
260*8975f5c5SAndroid Build Coastguard Worker         {
261*8975f5c5SAndroid Build Coastguard Worker             return false;
262*8975f5c5SAndroid Build Coastguard Worker         }
263*8975f5c5SAndroid Build Coastguard Worker     }
264*8975f5c5SAndroid Build Coastguard Worker 
265*8975f5c5SAndroid Build Coastguard Worker     fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
266*8975f5c5SAndroid Build Coastguard Worker 
267*8975f5c5SAndroid Build Coastguard Worker     // Packs the 2 column variables.
268*8975f5c5SAndroid Build Coastguard Worker     int top2ColumnRow            = topNonFullRow_ + num3ColumnRows;
269*8975f5c5SAndroid Build Coastguard Worker     int twoColumnRowsAvailable   = maxRows_ - top2ColumnRow;
270*8975f5c5SAndroid Build Coastguard Worker     int rowsAvailableInColumns01 = twoColumnRowsAvailable;
271*8975f5c5SAndroid Build Coastguard Worker     int rowsAvailableInColumns23 = twoColumnRowsAvailable;
272*8975f5c5SAndroid Build Coastguard Worker     for (; ii < variables->size(); ++ii)
273*8975f5c5SAndroid Build Coastguard Worker     {
274*8975f5c5SAndroid Build Coastguard Worker         const sh::ShaderVariable &variable = (*variables)[ii];
275*8975f5c5SAndroid Build Coastguard Worker         if (GetTypePackingComponentsPerRow(variable.type) != 2)
276*8975f5c5SAndroid Build Coastguard Worker         {
277*8975f5c5SAndroid Build Coastguard Worker             break;
278*8975f5c5SAndroid Build Coastguard Worker         }
279*8975f5c5SAndroid Build Coastguard Worker         int numRows = GetVariablePackingRows(variable);
280*8975f5c5SAndroid Build Coastguard Worker         if (numRows <= rowsAvailableInColumns01)
281*8975f5c5SAndroid Build Coastguard Worker         {
282*8975f5c5SAndroid Build Coastguard Worker             rowsAvailableInColumns01 -= numRows;
283*8975f5c5SAndroid Build Coastguard Worker         }
284*8975f5c5SAndroid Build Coastguard Worker         else if (numRows <= rowsAvailableInColumns23)
285*8975f5c5SAndroid Build Coastguard Worker         {
286*8975f5c5SAndroid Build Coastguard Worker             rowsAvailableInColumns23 -= numRows;
287*8975f5c5SAndroid Build Coastguard Worker         }
288*8975f5c5SAndroid Build Coastguard Worker         else
289*8975f5c5SAndroid Build Coastguard Worker         {
290*8975f5c5SAndroid Build Coastguard Worker             return false;
291*8975f5c5SAndroid Build Coastguard Worker         }
292*8975f5c5SAndroid Build Coastguard Worker     }
293*8975f5c5SAndroid Build Coastguard Worker 
294*8975f5c5SAndroid Build Coastguard Worker     int numRowsUsedInColumns01 = twoColumnRowsAvailable - rowsAvailableInColumns01;
295*8975f5c5SAndroid Build Coastguard Worker     int numRowsUsedInColumns23 = twoColumnRowsAvailable - rowsAvailableInColumns23;
296*8975f5c5SAndroid Build Coastguard Worker     fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
297*8975f5c5SAndroid Build Coastguard Worker     fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, 2, 2);
298*8975f5c5SAndroid Build Coastguard Worker 
299*8975f5c5SAndroid Build Coastguard Worker     // Packs the 1 column variables.
300*8975f5c5SAndroid Build Coastguard Worker     for (; ii < variables->size(); ++ii)
301*8975f5c5SAndroid Build Coastguard Worker     {
302*8975f5c5SAndroid Build Coastguard Worker         const sh::ShaderVariable &variable = (*variables)[ii];
303*8975f5c5SAndroid Build Coastguard Worker         ASSERT(1 == GetTypePackingComponentsPerRow(variable.type));
304*8975f5c5SAndroid Build Coastguard Worker         int numRows        = GetVariablePackingRows(variable);
305*8975f5c5SAndroid Build Coastguard Worker         int smallestColumn = -1;
306*8975f5c5SAndroid Build Coastguard Worker         int smallestSize   = maxRows_ + 1;
307*8975f5c5SAndroid Build Coastguard Worker         int topRow         = -1;
308*8975f5c5SAndroid Build Coastguard Worker         for (int column = 0; column < kNumColumns; ++column)
309*8975f5c5SAndroid Build Coastguard Worker         {
310*8975f5c5SAndroid Build Coastguard Worker             int row  = 0;
311*8975f5c5SAndroid Build Coastguard Worker             int size = 0;
312*8975f5c5SAndroid Build Coastguard Worker             if (searchColumn(column, numRows, &row, &size))
313*8975f5c5SAndroid Build Coastguard Worker             {
314*8975f5c5SAndroid Build Coastguard Worker                 if (size < smallestSize)
315*8975f5c5SAndroid Build Coastguard Worker                 {
316*8975f5c5SAndroid Build Coastguard Worker                     smallestSize   = size;
317*8975f5c5SAndroid Build Coastguard Worker                     smallestColumn = column;
318*8975f5c5SAndroid Build Coastguard Worker                     topRow         = row;
319*8975f5c5SAndroid Build Coastguard Worker                 }
320*8975f5c5SAndroid Build Coastguard Worker             }
321*8975f5c5SAndroid Build Coastguard Worker         }
322*8975f5c5SAndroid Build Coastguard Worker 
323*8975f5c5SAndroid Build Coastguard Worker         if (smallestColumn < 0)
324*8975f5c5SAndroid Build Coastguard Worker         {
325*8975f5c5SAndroid Build Coastguard Worker             return false;
326*8975f5c5SAndroid Build Coastguard Worker         }
327*8975f5c5SAndroid Build Coastguard Worker 
328*8975f5c5SAndroid Build Coastguard Worker         fillColumns(topRow, numRows, smallestColumn, 1);
329*8975f5c5SAndroid Build Coastguard Worker     }
330*8975f5c5SAndroid Build Coastguard Worker 
331*8975f5c5SAndroid Build Coastguard Worker     ASSERT(variables->size() == ii);
332*8975f5c5SAndroid Build Coastguard Worker 
333*8975f5c5SAndroid Build Coastguard Worker     return true;
334*8975f5c5SAndroid Build Coastguard Worker }
335*8975f5c5SAndroid Build Coastguard Worker 
336*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
337*8975f5c5SAndroid Build Coastguard Worker 
GetTypePackingComponentsPerRow(sh::GLenum type)338*8975f5c5SAndroid Build Coastguard Worker int GetTypePackingComponentsPerRow(sh::GLenum type)
339*8975f5c5SAndroid Build Coastguard Worker {
340*8975f5c5SAndroid Build Coastguard Worker     switch (type)
341*8975f5c5SAndroid Build Coastguard Worker     {
342*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT4:
343*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT2:
344*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT2x4:
345*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT3x4:
346*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT4x2:
347*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT4x3:
348*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_VEC4:
349*8975f5c5SAndroid Build Coastguard Worker         case GL_INT_VEC4:
350*8975f5c5SAndroid Build Coastguard Worker         case GL_BOOL_VEC4:
351*8975f5c5SAndroid Build Coastguard Worker         case GL_UNSIGNED_INT_VEC4:
352*8975f5c5SAndroid Build Coastguard Worker             return 4;
353*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT3:
354*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT2x3:
355*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT3x2:
356*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_VEC3:
357*8975f5c5SAndroid Build Coastguard Worker         case GL_INT_VEC3:
358*8975f5c5SAndroid Build Coastguard Worker         case GL_BOOL_VEC3:
359*8975f5c5SAndroid Build Coastguard Worker         case GL_UNSIGNED_INT_VEC3:
360*8975f5c5SAndroid Build Coastguard Worker             return 3;
361*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_VEC2:
362*8975f5c5SAndroid Build Coastguard Worker         case GL_INT_VEC2:
363*8975f5c5SAndroid Build Coastguard Worker         case GL_BOOL_VEC2:
364*8975f5c5SAndroid Build Coastguard Worker         case GL_UNSIGNED_INT_VEC2:
365*8975f5c5SAndroid Build Coastguard Worker             return 2;
366*8975f5c5SAndroid Build Coastguard Worker         default:
367*8975f5c5SAndroid Build Coastguard Worker             ASSERT(gl::VariableComponentCount(type) == 1);
368*8975f5c5SAndroid Build Coastguard Worker             return 1;
369*8975f5c5SAndroid Build Coastguard Worker     }
370*8975f5c5SAndroid Build Coastguard Worker }
371*8975f5c5SAndroid Build Coastguard Worker 
GetTypePackingRows(sh::GLenum type)372*8975f5c5SAndroid Build Coastguard Worker int GetTypePackingRows(sh::GLenum type)
373*8975f5c5SAndroid Build Coastguard Worker {
374*8975f5c5SAndroid Build Coastguard Worker     switch (type)
375*8975f5c5SAndroid Build Coastguard Worker     {
376*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT4:
377*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT2x4:
378*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT3x4:
379*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT4x3:
380*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT4x2:
381*8975f5c5SAndroid Build Coastguard Worker             return 4;
382*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT3:
383*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT2x3:
384*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT3x2:
385*8975f5c5SAndroid Build Coastguard Worker             return 3;
386*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT_MAT2:
387*8975f5c5SAndroid Build Coastguard Worker             return 2;
388*8975f5c5SAndroid Build Coastguard Worker         default:
389*8975f5c5SAndroid Build Coastguard Worker             ASSERT(gl::VariableRowCount(type) == 1);
390*8975f5c5SAndroid Build Coastguard Worker             return 1;
391*8975f5c5SAndroid Build Coastguard Worker     }
392*8975f5c5SAndroid Build Coastguard Worker }
393*8975f5c5SAndroid Build Coastguard Worker 
CheckVariablesInPackingLimits(unsigned int maxVectors,const std::vector<ShaderVariable> & variables)394*8975f5c5SAndroid Build Coastguard Worker bool CheckVariablesInPackingLimits(unsigned int maxVectors,
395*8975f5c5SAndroid Build Coastguard Worker                                    const std::vector<ShaderVariable> &variables)
396*8975f5c5SAndroid Build Coastguard Worker {
397*8975f5c5SAndroid Build Coastguard Worker     VariablePacker packer;
398*8975f5c5SAndroid Build Coastguard Worker     std::vector<sh::ShaderVariable> expandedVariables;
399*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderVariable &variable : variables)
400*8975f5c5SAndroid Build Coastguard Worker     {
401*8975f5c5SAndroid Build Coastguard Worker         ExpandVariable(variable, variable.name, &expandedVariables);
402*8975f5c5SAndroid Build Coastguard Worker     }
403*8975f5c5SAndroid Build Coastguard Worker     return packer.checkExpandedVariablesWithinPackingLimits(maxVectors, &expandedVariables);
404*8975f5c5SAndroid Build Coastguard Worker }
405*8975f5c5SAndroid Build Coastguard Worker 
406*8975f5c5SAndroid Build Coastguard Worker bool CheckVariablesInPackingLimits(unsigned int maxVectors,
407*8975f5c5SAndroid Build Coastguard Worker                                    const std::vector<ShaderVariable> &variables);
408*8975f5c5SAndroid Build Coastguard Worker 
409*8975f5c5SAndroid Build Coastguard Worker }  // namespace sh
410