tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

VariablePacker.cpp (12126B)


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