src/third_party/angle/src/libANGLE/VaryingPacking.cpp
// Packs varyings into generic varying registers, using the algorithm from
// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
// Returns false if unsuccessful.
Packs varyings into generic varying registers, using the algorithm from
See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
Returns false if unsuccessful.
Packs varyings into generic varying registers using the algorithm from See [ OpenGL ES Shading Language 1 . 00 rev . 17 ] appendix A section 7 page 111 Also [ OpenGL ES Shading Language 3 . 00 rev . 4 ] Section 11 page 119 Returns false if unsuccessful .
bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
{
    const sh::ShaderVariable &varying = packedVarying.varying();
    ASSERT(!varying.isStruct());
    GLenum transposedType       = gl::TransposeMatrixType(varying.type);
    unsigned int varyingRows    = gl::VariableRowCount(transposedType);
    unsigned int varyingColumns = gl::VariableColumnCount(transposedType);
    if (mPackMode == PackMode::ANGLE_NON_CONFORMANT_D3D9)
    {
        varyingColumns = 4;
    }
    else if (mPackMode == PackMode::WEBGL_STRICT && varying.type == GL_FLOAT_MAT2)
    {
        varyingColumns = 4;
    }
    const unsigned int elementCount = varying.getBasicTypeElementCount();
    varyingRows *= (packedVarying.isArrayElement() ? 1 : elementCount);
    unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
    if (varyingRows > maxVaryingVectors)
    {
        return false;
    }
    if (varyingColumns >= 2 && varyingColumns <= 4)
    {
        for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row)
        {
            if (isFree(row, 0, varyingRows, varyingColumns))
            {
                insert(row, 0, packedVarying);
                return true;
            }
        }
        if (varyingColumns == 2)
        {
            for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;)
            {
                if (isFree(r, 2, varyingRows, 2))
                {
                    insert(r, 2, packedVarying);
                    return true;
                }
            }
        }
        return false;
    }
    ASSERT(varyingColumns == 1);
    unsigned int contiguousSpace[4]     = {0};
    unsigned int bestContiguousSpace[4] = {0};
    unsigned int totalSpace[4]          = {0};
    for (unsigned int row = 0; row < maxVaryingVectors; ++row)
    {
        for (unsigned int column = 0; column < 4; ++column)
        {
            if (mRegisterMap[row][column])
            {
                contiguousSpace[column] = 0;
            }
            else
            {
                contiguousSpace[column]++;
                totalSpace[column]++;
                if (contiguousSpace[column] > bestContiguousSpace[column])
                {
                    bestContiguousSpace[column] = contiguousSpace[column];
                }
            }
        }
    }
    unsigned int bestColumn = 0;
    for (unsigned int column = 1; column < 4; ++column)
    {
        if (bestContiguousSpace[column] >= varyingRows &&
            (bestContiguousSpace[bestColumn] < varyingRows ||
             totalSpace[column] < totalSpace[bestColumn]))
        {
            bestColumn = column;
        }
    }
    if (bestContiguousSpace[bestColumn] >= varyingRows)
    {
        for (unsigned int row = 0; row < maxVaryingVectors; row++)
        {
            if (isFree(row, bestColumn, varyingRows, 1))
            {
                for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex)
                {
                    PackedVaryingRegister registerInfo;
                    registerInfo.packedVarying  = &packedVarying;
                    registerInfo.registerRow    = row + arrayIndex;
                    registerInfo.registerColumn = bestColumn;
                    registerInfo.varyingArrayIndex =
                        (packedVarying.isArrayElement() ? packedVarying.arrayIndex : arrayIndex);
                    registerInfo.varyingRowIndex = 0;
                    if (!varying.isBuiltIn())
                    {
                        mRegisterList.push_back(registerInfo);
                    }
                    mRegisterMap[row + arrayIndex][bestColumn] = true;
                }
                break;
            }
        }
        return true;
    }
    return false;
}
bool VaryingPacking :: packVarying ( const PackedVarying & packedVarying ) { const sh :: ShaderVariable & varying = packedVarying . varying ( ) ; ASSERT ( ! varying . isStruct ( ) ) ; GLenum transposedType = gl :: TransposeMatrixType ( varying . type ) ; unsigned int varyingRows = gl :: VariableRowCount ( transposedType ) ; unsigned int varyingColumns = gl :: VariableColumnCount ( transposedType ) ; if ( mPackMode == PackMode :: ANGLE_NON_CONFORMANT_D3D9 ) { varyingColumns = 4 ; } else if ( mPackMode == PackMode :: WEBGL_STRICT && varying . type == GL_FLOAT_MAT2 ) { varyingColumns = 4 ; } const unsigned int elementCount = varying . getBasicTypeElementCount ( ) ; varyingRows *= ( packedVarying . isArrayElement ( ) ? 1 : elementCount ) ; unsigned int maxVaryingVectors = static_cast < unsigned int > ( mRegisterMap . size ( ) ) ; if ( varyingRows > maxVaryingVectors ) { return false ; } if ( varyingColumns >= 2 && varyingColumns <= 4 ) { for ( unsigned int row = 0 ; row <= maxVaryingVectors - varyingRows ; ++ row ) { if ( isFree ( row , 0 , varyingRows , varyingColumns ) ) { insert ( row , 0 , packedVarying ) ; return true ; } } if ( varyingColumns == 2 ) { for ( unsigned int r = maxVaryingVectors - varyingRows + 1 ; r -- >= 1 ; ) { if ( isFree ( r , 2 , varyingRows , 2 ) ) { insert ( r , 2 , packedVarying ) ; return true ; } } } return false ; } ASSERT ( varyingColumns == 1 ) ; unsigned int contiguousSpace [ 4 ] = { 0 } ; unsigned int bestContiguousSpace [ 4 ] = { 0 } ; unsigned int totalSpace [ 4 ] = { 0 } ; for ( unsigned int row = 0 ; row < maxVaryingVectors ; ++ row ) { for ( unsigned int column = 0 ; column < 4 ; ++ column ) { if ( mRegisterMap [ row ] [ column ] ) { contiguousSpace [ column ] = 0 ; } else { contiguousSpace [ column ] ++ ; totalSpace [ column ] ++ ; if ( contiguousSpace [ column ] > bestContiguousSpace [ column ] ) { bestContiguousSpace [ column ] = contiguousSpace [ column ] ; } } } } unsigned int bestColumn = 0 ; for ( unsigned int column = 1 ; column < 4 ; ++ column ) { if ( bestContiguousSpace [ column ] >= varyingRows && ( bestContiguousSpace [ bestColumn ] < varyingRows || totalSpace [ column ] < totalSpace [ bestColumn ] ) ) { bestColumn = column ; } } if ( bestContiguousSpace [ bestColumn ] >= varyingRows ) { for ( unsigned int row = 0 ; row < maxVaryingVectors ; row ++ ) { if ( isFree ( row , bestColumn , varyingRows , 1 ) ) { for ( unsigned int arrayIndex = 0 ; arrayIndex < varyingRows ; ++ arrayIndex ) { PackedVaryingRegister registerInfo ; registerInfo . packedVarying = & packedVarying ; registerInfo . registerRow = row + arrayIndex ; registerInfo . registerColumn = bestColumn ; registerInfo . varyingArrayIndex = ( packedVarying . isArrayElement ( ) ? packedVarying . arrayIndex : arrayIndex ) ; registerInfo . varyingRowIndex = 0 ; if ( ! varying . isBuiltIn ( ) ) { mRegisterList . push_back ( registerInfo ) ; } mRegisterMap [ row + arrayIndex ] [ bestColumn ] = true ; } break ; } } return true ; } return false ; }
Packs varyings into generic varying registers, using the algorithm from
See [OpenGL ES Shading Language 1.00 rev.
Packs varyings into generic varying registers using the algorithm from See [ OpenGL ES Shading Language 1 . 00 rev .
// "Non - square matrices of type matCxR consume the same space as a square matrix of type matN // where N is the greater of C and R." // Here we are a bit more conservative and allow packing non-square matrices more tightly. // Make sure we use transposed matrix types to count registers correctly. // Special pack mode for D3D9. Each varying takes a full register, no sharing. // TODO(jmadill): Implement more sophisticated component packing in D3D9. // "Variables of type mat2 occupies 2 complete rows." // For non-WebGL contexts, we allow mat2 to occupy only two columns per row. // "Arrays of size N are assumed to take N times the size of the base type" // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of // structures, so we may use getBasicTypeElementCount(). // Fail if we are packing a single over-large varying. // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row. // Variables are then allocated to successive rows, aligning them to the 1st column." // "For 2 component variables, when there are no spare rows, the strategy is switched to // using the highest numbered row and the lowest numbered column where the variable will // fit." // "1 component variables have their own packing rule. They are packed in order of size, largest // first. Each variable is placed in the column that leaves the least amount of space in the // column and aligned to the lowest available rows within that column." // If varyingRows > 1, it must be an array. // Do not record register info for builtins. // TODO(jmadill): Clean this up.