1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/compiler/VariablePacker.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,297 @@ 1.4 +// 1.5 +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 +// 1.9 +#include "compiler/VariablePacker.h" 1.10 + 1.11 +#include <algorithm> 1.12 +#include "compiler/ShHandle.h" 1.13 + 1.14 +namespace { 1.15 +int GetSortOrder(ShDataType type) 1.16 +{ 1.17 + switch (type) { 1.18 + case SH_FLOAT_MAT4: 1.19 + return 0; 1.20 + case SH_FLOAT_MAT2: 1.21 + return 1; 1.22 + case SH_FLOAT_VEC4: 1.23 + case SH_INT_VEC4: 1.24 + case SH_BOOL_VEC4: 1.25 + return 2; 1.26 + case SH_FLOAT_MAT3: 1.27 + return 3; 1.28 + case SH_FLOAT_VEC3: 1.29 + case SH_INT_VEC3: 1.30 + case SH_BOOL_VEC3: 1.31 + return 4; 1.32 + case SH_FLOAT_VEC2: 1.33 + case SH_INT_VEC2: 1.34 + case SH_BOOL_VEC2: 1.35 + return 5; 1.36 + case SH_FLOAT: 1.37 + case SH_INT: 1.38 + case SH_BOOL: 1.39 + case SH_SAMPLER_2D: 1.40 + case SH_SAMPLER_CUBE: 1.41 + case SH_SAMPLER_EXTERNAL_OES: 1.42 + case SH_SAMPLER_2D_RECT_ARB: 1.43 + return 6; 1.44 + default: 1.45 + ASSERT(false); 1.46 + return 7; 1.47 + } 1.48 +} 1.49 +} // namespace 1.50 + 1.51 +int VariablePacker::GetNumComponentsPerRow(ShDataType type) 1.52 +{ 1.53 + switch (type) { 1.54 + case SH_FLOAT_MAT4: 1.55 + case SH_FLOAT_MAT2: 1.56 + case SH_FLOAT_VEC4: 1.57 + case SH_INT_VEC4: 1.58 + case SH_BOOL_VEC4: 1.59 + return 4; 1.60 + case SH_FLOAT_MAT3: 1.61 + case SH_FLOAT_VEC3: 1.62 + case SH_INT_VEC3: 1.63 + case SH_BOOL_VEC3: 1.64 + return 3; 1.65 + case SH_FLOAT_VEC2: 1.66 + case SH_INT_VEC2: 1.67 + case SH_BOOL_VEC2: 1.68 + return 2; 1.69 + case SH_FLOAT: 1.70 + case SH_INT: 1.71 + case SH_BOOL: 1.72 + case SH_SAMPLER_2D: 1.73 + case SH_SAMPLER_CUBE: 1.74 + case SH_SAMPLER_EXTERNAL_OES: 1.75 + case SH_SAMPLER_2D_RECT_ARB: 1.76 + return 1; 1.77 + default: 1.78 + ASSERT(false); 1.79 + return 5; 1.80 + } 1.81 +} 1.82 + 1.83 +int VariablePacker::GetNumRows(ShDataType type) 1.84 +{ 1.85 + switch (type) { 1.86 + case SH_FLOAT_MAT4: 1.87 + return 4; 1.88 + case SH_FLOAT_MAT3: 1.89 + return 3; 1.90 + case SH_FLOAT_MAT2: 1.91 + return 2; 1.92 + case SH_FLOAT_VEC4: 1.93 + case SH_INT_VEC4: 1.94 + case SH_BOOL_VEC4: 1.95 + case SH_FLOAT_VEC3: 1.96 + case SH_INT_VEC3: 1.97 + case SH_BOOL_VEC3: 1.98 + case SH_FLOAT_VEC2: 1.99 + case SH_INT_VEC2: 1.100 + case SH_BOOL_VEC2: 1.101 + case SH_FLOAT: 1.102 + case SH_INT: 1.103 + case SH_BOOL: 1.104 + case SH_SAMPLER_2D: 1.105 + case SH_SAMPLER_CUBE: 1.106 + case SH_SAMPLER_EXTERNAL_OES: 1.107 + case SH_SAMPLER_2D_RECT_ARB: 1.108 + return 1; 1.109 + default: 1.110 + ASSERT(false); 1.111 + return 100000; 1.112 + } 1.113 +} 1.114 + 1.115 +struct TVariableInfoComparer { 1.116 + bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const 1.117 + { 1.118 + int lhsSortOrder = GetSortOrder(lhs.type); 1.119 + int rhsSortOrder = GetSortOrder(rhs.type); 1.120 + if (lhsSortOrder != rhsSortOrder) { 1.121 + return lhsSortOrder < rhsSortOrder; 1.122 + } 1.123 + // Sort by largest first. 1.124 + return lhs.size > rhs.size; 1.125 + } 1.126 +}; 1.127 + 1.128 +unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow) 1.129 +{ 1.130 + return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & 1.131 + kColumnMask) >> column; 1.132 +} 1.133 + 1.134 +void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow) 1.135 +{ 1.136 + unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow); 1.137 + for (int r = 0; r < numRows; ++r) { 1.138 + int row = topRow + r; 1.139 + ASSERT((rows_[row] & columnFlags) == 0); 1.140 + rows_[row] |= columnFlags; 1.141 + } 1.142 +} 1.143 + 1.144 +bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize) 1.145 +{ 1.146 + ASSERT(destRow); 1.147 + 1.148 + for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; 1.149 + ++topNonFullRow_) { 1.150 + } 1.151 + 1.152 + for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; 1.153 + --bottomNonFullRow_) { 1.154 + } 1.155 + 1.156 + if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) { 1.157 + return false; 1.158 + } 1.159 + 1.160 + unsigned columnFlags = makeColumnFlags(column, 1); 1.161 + int topGoodRow = 0; 1.162 + int smallestGoodTop = -1; 1.163 + int smallestGoodSize = maxRows_ + 1; 1.164 + int bottomRow = bottomNonFullRow_ + 1; 1.165 + bool found = false; 1.166 + for (int row = topNonFullRow_; row <= bottomRow; ++row) { 1.167 + bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false; 1.168 + if (rowEmpty) { 1.169 + if (!found) { 1.170 + topGoodRow = row; 1.171 + found = true; 1.172 + } 1.173 + } else { 1.174 + if (found) { 1.175 + int size = row - topGoodRow; 1.176 + if (size >= numRows && size < smallestGoodSize) { 1.177 + smallestGoodSize = size; 1.178 + smallestGoodTop = topGoodRow; 1.179 + } 1.180 + } 1.181 + found = false; 1.182 + } 1.183 + } 1.184 + if (smallestGoodTop < 0) { 1.185 + return false; 1.186 + } 1.187 + 1.188 + *destRow = smallestGoodTop; 1.189 + if (destSize) { 1.190 + *destSize = smallestGoodSize; 1.191 + } 1.192 + return true; 1.193 +} 1.194 + 1.195 +bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables) 1.196 +{ 1.197 + ASSERT(maxVectors > 0); 1.198 + maxRows_ = maxVectors; 1.199 + topNonFullRow_ = 0; 1.200 + bottomNonFullRow_ = maxRows_ - 1; 1.201 + TVariableInfoList variables(in_variables); 1.202 + 1.203 + // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific 1.204 + // order by type, then by size of array, largest first. 1.205 + std::sort(variables.begin(), variables.end(), TVariableInfoComparer()); 1.206 + rows_.clear(); 1.207 + rows_.resize(maxVectors, 0); 1.208 + 1.209 + // Packs the 4 column variables. 1.210 + size_t ii = 0; 1.211 + for (; ii < variables.size(); ++ii) { 1.212 + const TVariableInfo& variable = variables[ii]; 1.213 + if (GetNumComponentsPerRow(variable.type) != 4) { 1.214 + break; 1.215 + } 1.216 + topNonFullRow_ += GetNumRows(variable.type) * variable.size; 1.217 + } 1.218 + 1.219 + if (topNonFullRow_ > maxRows_) { 1.220 + return false; 1.221 + } 1.222 + 1.223 + // Packs the 3 column variables. 1.224 + int num3ColumnRows = 0; 1.225 + for (; ii < variables.size(); ++ii) { 1.226 + const TVariableInfo& variable = variables[ii]; 1.227 + if (GetNumComponentsPerRow(variable.type) != 3) { 1.228 + break; 1.229 + } 1.230 + num3ColumnRows += GetNumRows(variable.type) * variable.size; 1.231 + } 1.232 + 1.233 + if (topNonFullRow_ + num3ColumnRows > maxRows_) { 1.234 + return false; 1.235 + } 1.236 + 1.237 + fillColumns(topNonFullRow_, num3ColumnRows, 0, 3); 1.238 + 1.239 + // Packs the 2 column variables. 1.240 + int top2ColumnRow = topNonFullRow_ + num3ColumnRows; 1.241 + int twoColumnRowsAvailable = maxRows_ - top2ColumnRow; 1.242 + int rowsAvailableInColumns01 = twoColumnRowsAvailable; 1.243 + int rowsAvailableInColumns23 = twoColumnRowsAvailable; 1.244 + for (; ii < variables.size(); ++ii) { 1.245 + const TVariableInfo& variable = variables[ii]; 1.246 + if (GetNumComponentsPerRow(variable.type) != 2) { 1.247 + break; 1.248 + } 1.249 + int numRows = GetNumRows(variable.type) * variable.size; 1.250 + if (numRows <= rowsAvailableInColumns01) { 1.251 + rowsAvailableInColumns01 -= numRows; 1.252 + } else if (numRows <= rowsAvailableInColumns23) { 1.253 + rowsAvailableInColumns23 -= numRows; 1.254 + } else { 1.255 + return false; 1.256 + } 1.257 + } 1.258 + 1.259 + int numRowsUsedInColumns01 = 1.260 + twoColumnRowsAvailable - rowsAvailableInColumns01; 1.261 + int numRowsUsedInColumns23 = 1.262 + twoColumnRowsAvailable - rowsAvailableInColumns23; 1.263 + fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2); 1.264 + fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, 1.265 + 2, 2); 1.266 + 1.267 + // Packs the 1 column variables. 1.268 + for (; ii < variables.size(); ++ii) { 1.269 + const TVariableInfo& variable = variables[ii]; 1.270 + ASSERT(1 == GetNumComponentsPerRow(variable.type)); 1.271 + int numRows = GetNumRows(variable.type) * variable.size; 1.272 + int smallestColumn = -1; 1.273 + int smallestSize = maxRows_ + 1; 1.274 + int topRow = -1; 1.275 + for (int column = 0; column < kNumColumns; ++column) { 1.276 + int row = 0; 1.277 + int size = 0; 1.278 + if (searchColumn(column, numRows, &row, &size)) { 1.279 + if (size < smallestSize) { 1.280 + smallestSize = size; 1.281 + smallestColumn = column; 1.282 + topRow = row; 1.283 + } 1.284 + } 1.285 + } 1.286 + 1.287 + if (smallestColumn < 0) { 1.288 + return false; 1.289 + } 1.290 + 1.291 + fillColumns(topRow, numRows, smallestColumn, 1); 1.292 + } 1.293 + 1.294 + ASSERT(variables.size() == ii); 1.295 + 1.296 + return true; 1.297 +} 1.298 + 1.299 + 1.300 +