Edit

kc3-lang/angle/src/compiler/Uniform.cpp

Branch :

  • Show log

    Commit

  • Author : shannonwoods@chromium.org
    Date : 2013-05-30 00:17:57
    Hash : 5f8d9b46
    Message : Add support for arrays of aggregates (aka structs) in uniform blocks. TRAC #23018 Signed-off-by: Geoff Lang Signed-off-by: Nicolas Capens Author: Jamie Madill git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2388 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/compiler/Uniform.cpp
  • //
    // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    #include "compiler/Uniform.h"
    #include "common/mathutil.h"
    #include "common/utilities.h"
    
    namespace sh
    {
    
    Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex)
    {
        this->type = type;
        this->precision = precision;
        this->name = name;
        this->arraySize = arraySize;
        this->registerIndex = registerIndex;
    }
    
    BlockMemberInfo::BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
        : offset(offset),
          arrayStride(arrayStride),
          matrixStride(matrixStride),
          isRowMajorMatrix(isRowMajorMatrix)
    {
    }
    
    const BlockMemberInfo BlockMemberInfo::defaultBlockInfo(-1, -1, -1, false);
    
    InterfaceBlock::InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex)
        : name(name),
          arraySize(arraySize),
          layout(BLOCKLAYOUT_SHARED),
          registerIndex(registerIndex)
    {
    }
    
    // Use the same layout for packed and shared
    void InterfaceBlock::setBlockLayout(BlockLayoutType newLayout)
    {
        layout = newLayout;
    
        const size_t componentSize = 4;
        unsigned int currentOffset = 0;
    
        blockInfo.clear();
        getBlockLayoutInfo(activeUniforms, &currentOffset);
    
        dataSize = currentOffset * componentSize;
    }
    
    void InterfaceBlock::getBlockLayoutInfo(const sh::ActiveUniforms &fields, unsigned int *currentOffset)
    {
        const size_t componentSize = 4;
    
        // TODO: row major matrices
        bool isRowMajorMatrix = false;
    
        for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
        {
            int arrayStride;
            int matrixStride;
    
            const sh::Uniform &uniform = fields[fieldIndex];
    
            if (getBlockLayoutInfo(uniform, currentOffset, &arrayStride, &matrixStride))
            {
                const BlockMemberInfo memberInfo(*currentOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, isRowMajorMatrix);
                blockInfo.push_back(memberInfo);
    
                if (uniform.arraySize > 0)
                {
                    *currentOffset += arrayStride * uniform.arraySize;
                }
                else if (gl::IsMatrixType(uniform.type))
                {
                    const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
                    *currentOffset += matrixStride * componentGroups;
                }
                else
                {
                    *currentOffset += gl::UniformComponentCount(uniform.type);
                }
            }
        }
    }
    
    bool InterfaceBlock::getBlockLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
    {
        if (!uniform.fields.empty())
        {
            if (uniform.arraySize > 0)
            {
                for (unsigned int arrayElement = 0; arrayElement < uniform.arraySize; arrayElement++)
                {
                    getBlockLayoutInfo(uniform.fields, currentOffset);
                }
            }
            else
            {
                getBlockLayoutInfo(uniform.fields, currentOffset);
            }
            return false;
        }
    
        switch (layout)
        {
          case BLOCKLAYOUT_SHARED:
          case BLOCKLAYOUT_PACKED:
            getD3DLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
            return true;
    
          case BLOCKLAYOUT_STANDARD:
            getStandardLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
            return true;
    
          default:
            UNREACHABLE();
            return false;
        }
    }
    
    // Block layout packed according to the default D3D11 register packing rules
    // See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
    void InterfaceBlock::getD3DLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
    {
        ASSERT(uniform.fields.empty());
    
        const unsigned int registerSize = 4;
        const size_t componentSize = 4;
    
        // TODO: row major matrices
        bool isRowMajorMatrix = false;
        // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
        ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
        int matrixStride = 0;
        int arrayStride = 0;
    
        if (gl::IsMatrixType(uniform.type))
        {
            *currentOffset = rx::roundUp(*currentOffset, 4u);
            matrixStride = registerSize;
    
            if (uniform.arraySize > 0)
            {
                const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
                arrayStride = matrixStride * componentGroups;
            }
        }
        else if (uniform.arraySize > 0)
        {
            *currentOffset = rx::roundUp(*currentOffset, registerSize);
            arrayStride = registerSize;
        }
        else
        {
            int numComponents = gl::UniformComponentCount(uniform.type);
            if ((numComponents + (*currentOffset % registerSize)) >= registerSize)
            {
                *currentOffset = rx::roundUp(*currentOffset, registerSize);
            }
        }
    
        *matrixStrideOut = matrixStride;
        *arrayStrideOut = arrayStride;
    }
    
    // Block layout according to the std140 block layout
    // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
    void InterfaceBlock::getStandardLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
    {
        ASSERT(uniform.fields.empty());
    
        const size_t componentSize = 4;
    
        // TODO: row major matrices
        bool isRowMajorMatrix = false;
    
        // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
        ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
    
        int numComponents = gl::UniformComponentCount(uniform.type);
        size_t baseAlignment = static_cast<size_t>(numComponents == 3 ? 4 : numComponents);
        int matrixStride = 0;
        int arrayStride = 0;
    
        if (gl::IsMatrixType(uniform.type))
        {
            numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
            baseAlignment = rx::roundUp(baseAlignment, 4u);
            matrixStride = baseAlignment;
    
            if (uniform.arraySize > 0)
            {
                const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
                arrayStride = matrixStride * componentGroups;
            }
        }
        else if (uniform.arraySize > 0)
        {
            baseAlignment = rx::roundUp(baseAlignment, 4u);
            arrayStride = baseAlignment;
        }
    
        *currentOffset = rx::roundUp(*currentOffset, baseAlignment);
    
        *matrixStrideOut = matrixStride;
        *arrayStrideOut = arrayStride;
    }
    
    }