3rdparty/bgfx/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp
// Implement base-alignment and size rules from section 7.6.2.2 Standard Uniform Block Layout
// Operates recursively.
//
// If std140 is true, it does the rounding up to vec4 size required by std140,
// otherwise it does not, yielding std430 rules.
//
// The size is returned in the 'size' parameter
//
// The stride is only non-0 for arrays or matrices, and is the stride of the
// top-level object nested within the type.  E.g., for an array of matrices,
// it is the distances needed between matrices, despite the rules saying the
// stride comes from the flattening down to vectors.
//
// Return value is the alignment of the type.
Implement base-alignment and size rules from section 7.6.2.2 Standard Uniform Block Layout
Operates recursively.

If std140 is true, it does the rounding up to vec4 size required by std140,
otherwise it does not, yielding std430 rules.

The size is returned in the 'size' parameter

The stride is only non-0 for arrays or matrices, and is the stride of the
top-level object nested within the type.  E.g., for an array of matrices,
it is the distances needed between matrices, despite the rules saying the
stride comes from the flattening down to vectors.

Return value is the alignment of the type.
Implement base - alignment and size rules from section 7 . 6 . 2 . 2 Standard Uniform Block Layout Operates recursively . If std140 is true it does the rounding up to vec4 size required by std140 otherwise it does not yielding std430 rules . The size is returned in the ' size ' parameter The stride is only non - 0 for arrays or matrices and is the stride of the top - level object nested within the type . E . g . for an array of matrices it is the distances needed between matrices despite the rules saying the stride comes from the flattening down to vectors . Return value is the alignment of the type .
int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, bool std140, bool rowMajor)
{
    int alignment;
       1. If the member is a scalar consuming N basic machine units, the base alignment is N.
       2. If the member is a two- or four-component vector with components consuming N basic
          machine units, the base alignment is 2N or 4N, respectively.
       3. If the member is a three-component vector with components consuming N
          basic machine units, the base alignment is 4N.
       4. If the member is an array of scalars or vectors, the base alignment and array
          stride are set to match the base alignment of a single array element, according
          to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The
          array may have padding at the end; the base offset of the member following
          the array is rounded up to the next multiple of the base alignment.
       5. If the member is a column-major matrix with C columns and R rows, the
          matrix is stored identically to an array of C column vectors with R
          components each, according to rule (4).
       6. If the member is an array of S column-major matrices with C columns and
          R rows, the matrix is stored identically to a row of S X C column vectors
          with R components each, according to rule (4).
       7. If the member is a row-major matrix with C columns and R rows, the matrix
          is stored identically to an array of R row vectors with C components each,
          according to rule (4).
       8. If the member is an array of S row-major matrices with C columns and R
          rows, the matrix is stored identically to a row of S X R row vectors with C
          components each, according to rule (4).
       9. If the member is a structure, the base alignment of the structure is N , where
          N is the largest base alignment value of any    of its members, and rounded
          up to the base alignment of a vec4. The individual members of this substructure
          are then assigned offsets by applying this set of rules recursively,
          where the base offset of the first member of the sub-structure is equal to the
          aligned offset of the structure. The structure may have padding at the end;
          the base offset of the member following the sub-structure is rounded up to
          the next multiple of the base alignment of the structure.
       10. If the member is an array of S structures, the S elements of the array are laid
           out in order, according to rule (9).
       Assuming, for rule 10:  The stride is the same as the size of an element.
    stride = 0;
    int dummyStride;
     rules 4, 6, 8, and 10
    if (type.isArray()) {
         TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
        TType derefType(type, 0);
        alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
        if (std140)
            alignment = std::max(baseAlignmentVec4Std140, alignment);
        RoundToPow2(size, alignment);
        stride = size;   uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected)
                         uses the assumption for rule 10 in the comment above
        size = stride * type.getOuterArraySize();
        return alignment;
    }
     rule 9
    if (type.getBasicType() == EbtStruct) {
        const TTypeList& memberList = *type.getStruct();
        size = 0;
        int maxAlignment = std140 ? baseAlignmentVec4Std140 : 0;
        for (size_t m = 0; m < memberList.size(); ++m) {
            int memberSize;
             modify just the children's view of matrix layout, if there is one for this member
            TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
            int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, std140,
                                                   (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
            maxAlignment = std::max(maxAlignment, memberAlignment);
            RoundToPow2(size, memberAlignment);
            size += memberSize;
        }
         The structure may have padding at the end; the base offset of
         the member following the sub-structure is rounded up to the next
         multiple of the base alignment of the structure.
        RoundToPow2(size, maxAlignment);
        return maxAlignment;
    }
     rule 1
    if (type.isScalar())
        return getBaseAlignmentScalar(type, size);
     rules 2 and 3
    if (type.isVector()) {
        int scalarAlign = getBaseAlignmentScalar(type, size);
        switch (type.getVectorSize()) {
        case 2:
            size *= 2;
            return 2 * scalarAlign;
        default:
            size *= type.getVectorSize();
            return 4 * scalarAlign;
        }
    }
     rules 5 and 7
    if (type.isMatrix()) {
         rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
        TType derefType(type, 0, rowMajor);
        alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
        if (std140)
            alignment = std::max(baseAlignmentVec4Std140, alignment);
        RoundToPow2(size, alignment);
        stride = size;   use intra-matrix stride for stride of a just a matrix
        if (rowMajor)
            size = stride * type.getMatrixRows();
        else
            size = stride * type.getMatrixCols();
        return alignment;
    }
    assert(0);   all cases should be covered above
    size = baseAlignmentVec4Std140;
    return baseAlignmentVec4Std140;
}
int TIntermediate :: getBaseAlignment ( const TType & type , int & size , int & stride , bool std140 , bool rowMajor ) { int alignment ; stride = 0 ; int dummyStride ; if ( type . isArray ( ) ) { TType derefType ( type , 0 ) ; alignment = getBaseAlignment ( derefType , size , dummyStride , std140 , rowMajor ) ; if ( std140 ) alignment = std :: max ( baseAlignmentVec4Std140 , alignment ) ; RoundToPow2 ( size , alignment ) ; stride = size ; size = stride * type . getOuterArraySize ( ) ; return alignment ; } if ( type . getBasicType ( ) == EbtStruct ) { const TTypeList & memberList = * type . getStruct ( ) ; size = 0 ; int maxAlignment = std140 ? baseAlignmentVec4Std140 : 0 ; for ( size_t m = 0 ; m < memberList . size ( ) ; ++ m ) { int memberSize ; TLayoutMatrix subMatrixLayout = memberList [ m ] . type -> getQualifier ( ) . layoutMatrix ; int memberAlignment = getBaseAlignment ( * memberList [ m ] . type , memberSize , dummyStride , std140 , ( subMatrixLayout != ElmNone ) ? ( subMatrixLayout == ElmRowMajor ) : rowMajor ) ; maxAlignment = std :: max ( maxAlignment , memberAlignment ) ; RoundToPow2 ( size , memberAlignment ) ; size += memberSize ; } RoundToPow2 ( size , maxAlignment ) ; return maxAlignment ; } if ( type . isScalar ( ) ) return getBaseAlignmentScalar ( type , size ) ; if ( type . isVector ( ) ) { int scalarAlign = getBaseAlignmentScalar ( type , size ) ; switch ( type . getVectorSize ( ) ) { case 2 : size *= 2 ; return 2 * scalarAlign ; default : size *= type . getVectorSize ( ) ; return 4 * scalarAlign ; } } if ( type . isMatrix ( ) ) { TType derefType ( type , 0 , rowMajor ) ; alignment = getBaseAlignment ( derefType , size , dummyStride , std140 , rowMajor ) ; if ( std140 ) alignment = std :: max ( baseAlignmentVec4Std140 , alignment ) ; RoundToPow2 ( size , alignment ) ; stride = size ; if ( rowMajor ) size = stride * type . getMatrixRows ( ) ; else size = stride * type . getMatrixCols ( ) ; return alignment ; } assert ( 0 ) ; size = baseAlignmentVec4Std140 ; return baseAlignmentVec4Std140 ; }
Implement base-alignment and size rules from section 7.6.2.2 Standard Uniform Block Layout
Operates recursively.
Implement base - alignment and size rules from section 7 . 6 . 2 . 2 Standard Uniform Block Layout Operates recursively .
// When using the std140 storage layout, structures will be laid out in buffer // storage with its members stored in monotonically increasing order based on their // location in the declaration. A structure and each structure member have a base // offset and a base alignment, from which an aligned offset is computed by rounding // the base offset up to a multiple of the base alignment. The base offset of the first // member of a structure is taken from the aligned offset of the structure itself. The // base offset of all other structure members is derived by taking the offset of the // last basic machine unit consumed by the previous member and adding one. Each // structure member is stored in memory at its aligned offset. The members of a top- // level uniform block are laid out in buffer storage by treating the uniform block as // a structure with a base offset of zero. // //   1. If the member is a scalar consuming N basic machine units, the base alignment is N. // //   2. If the member is a two- or four-component vector with components consuming N basic //      machine units, the base alignment is 2N or 4N, respectively. // //   3. If the member is a three-component vector with components consuming N //      basic machine units, the base alignment is 4N. // //   4. If the member is an array of scalars or vectors, the base alignment and array //      stride are set to match the base alignment of a single array element, according //      to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The //      array may have padding at the end; the base offset of the member following //      the array is rounded up to the next multiple of the base alignment. // //   5. If the member is a column-major matrix with C columns and R rows, the //      matrix is stored identically to an array of C column vectors with R //      components each, according to rule (4). // //   6. If the member is an array of S column-major matrices with C columns and //      R rows, the matrix is stored identically to a row of S X C column vectors //      with R components each, according to rule (4). // //   7. If the member is a row-major matrix with C columns and R rows, the matrix //      is stored identically to an array of R row vectors with C components each, //      according to rule (4). // //   8. If the member is an array of S row-major matrices with C columns and R //      rows, the matrix is stored identically to a row of S X R row vectors with C //      components each, according to rule (4). // //   9. If the member is a structure, the base alignment of the structure is N , where //      N is the largest base alignment value of any    of its members, and rounded //      up to the base alignment of a vec4. The individual members of this substructure //      are then assigned offsets by applying this set of rules recursively, //      where the base offset of the first member of the sub-structure is equal to the //      aligned offset of the structure. The structure may have padding at the end; //      the base offset of the member following the sub-structure is rounded up to //      the next multiple of the base alignment of the structure. // //   10. If the member is an array of S structures, the S elements of the array are laid //       out in order, according to rule (9). // //   Assuming, for rule 10:  The stride is the same as the size of an element. // rules 4, 6, 8, and 10 // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected) // uses the assumption for rule 10 in the comment above // rule 9 // modify just the children's view of matrix layout, if there is one for this member // The structure may have padding at the end; the base offset of // the member following the sub-structure is rounded up to the next // multiple of the base alignment of the structure. // rule 1 // rules 2 and 3 // rules 5 and 7 // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows // use intra-matrix stride for stride of a just a matrix // all cases should be covered above