Edit

kc3-lang/angle/src/common/blocklayout.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2014-07-17 14:16:26
    Hash : e294bb87
    Message : Add new shader inspection APIs. Each new entry point corresponds to one of the variable types: varyings, attributes, uniforms, output variables, and interface blocks. They return a pointer to the vector with all of the parsed variables, which then the app can copy to its own memory. Currently we do not support the staticUse field in the HLSL translator. BUG=angle:466 Change-Id: I7dc09e761ab070feef5360ad27740110c44853b3 Reviewed-on: https://chromium-review.googlesource.com/208750 Tested-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Zhenyao Mo <zmo@chromium.org> Reviewed-by: Nicolas Capens <capn@chromium.org>

  • src/common/blocklayout.cpp
  • //
    // Copyright (c) 2013-2014 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.
    //
    // blocklayout.cpp:
    //   Implementation for block layout classes and methods.
    //
    
    #include "common/blocklayout.h"
    #include "common/mathutil.h"
    #include "common/utilities.h"
    
    namespace sh
    {
    
    BlockLayoutEncoder::BlockLayoutEncoder()
        : mCurrentOffset(0)
    {
    }
    
    void BlockLayoutEncoder::encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields)
    {
        for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
        {
            const InterfaceBlockField &variable = fields[fieldIndex];
    
            if (variable.fields.size() > 0)
            {
                const unsigned int elementCount = std::max(1u, variable.arraySize);
    
                for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
                {
                    enterAggregateType();
                    encodeInterfaceBlockFields(variable.fields);
                    exitAggregateType();
                }
            }
            else
            {
                encodeInterfaceBlockField(variable);
            }
        }
    }
    
    BlockMemberInfo BlockLayoutEncoder::encodeInterfaceBlockField(const InterfaceBlockField &field)
    {
        int arrayStride;
        int matrixStride;
    
        ASSERT(field.fields.empty());
        getBlockLayoutInfo(field.type, field.arraySize, field.isRowMajorMatrix, &arrayStride, &matrixStride);
    
        const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, field.isRowMajorMatrix);
    
        advanceOffset(field.type, field.arraySize, field.isRowMajorMatrix, arrayStride, matrixStride);
    
        return memberInfo;
    }
    
    void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
    {
        int arrayStride;
        int matrixStride;
    
        getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
    
        const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
    
        advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
    }
    
    void BlockLayoutEncoder::nextRegister()
    {
        mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
    }
    
    Std140BlockEncoder::Std140BlockEncoder()
    {
    }
    
    void Std140BlockEncoder::enterAggregateType()
    {
        nextRegister();
    }
    
    void Std140BlockEncoder::exitAggregateType()
    {
        nextRegister();
    }
    
    void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
    {
        // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
        ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
    
        size_t baseAlignment = 0;
        int matrixStride = 0;
        int arrayStride = 0;
    
        if (gl::IsMatrixType(type))
        {
            baseAlignment = ComponentsPerRegister;
            matrixStride = ComponentsPerRegister;
    
            if (arraySize > 0)
            {
                const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
                arrayStride = ComponentsPerRegister * numRegisters;
            }
        }
        else if (arraySize > 0)
        {
            baseAlignment = ComponentsPerRegister;
            arrayStride = ComponentsPerRegister;
        }
        else
        {
            const int numComponents = gl::VariableComponentCount(type);
            baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
        }
    
        mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
    
        *matrixStrideOut = matrixStride;
        *arrayStrideOut = arrayStride;
    }
    
    void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
    {
        if (arraySize > 0)
        {
            mCurrentOffset += arrayStride * arraySize;
        }
        else if (gl::IsMatrixType(type))
        {
            ASSERT(matrixStride == ComponentsPerRegister);
            const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
            mCurrentOffset += ComponentsPerRegister * numRegisters;
        }
        else
        {
            mCurrentOffset += gl::VariableComponentCount(type);
        }
    }
    
    HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy)
        : mEncoderStrategy(strategy)
    {
    }
    
    void HLSLBlockEncoder::enterAggregateType()
    {
        nextRegister();
    }
    
    void HLSLBlockEncoder::exitAggregateType()
    {
    }
    
    void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
    {
        // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
        ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
    
        int matrixStride = 0;
        int arrayStride = 0;
    
        // if variables are not to be packed, or we're about to
        // pack a matrix or array, skip to the start of the next
        // register
        if (!isPacked() ||
            gl::IsMatrixType(type) ||
            arraySize > 0)
        {
            nextRegister();
        }
    
        if (gl::IsMatrixType(type))
        {
            matrixStride = ComponentsPerRegister;
    
            if (arraySize > 0)
            {
                const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
                arrayStride = ComponentsPerRegister * numRegisters;
            }
        }
        else if (arraySize > 0)
        {
            arrayStride = ComponentsPerRegister;
        }
        else if (isPacked())
        {
            int numComponents = gl::VariableComponentCount(type);
            if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
            {
                nextRegister();
            }
        }
    
        *matrixStrideOut = matrixStride;
        *arrayStrideOut = arrayStride;
    }
    
    void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
    {
        if (arraySize > 0)
        {
            mCurrentOffset += arrayStride * (arraySize - 1);
        }
    
        if (gl::IsMatrixType(type))
        {
            ASSERT(matrixStride == ComponentsPerRegister);
            const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
            const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
            mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
            mCurrentOffset += numComponents;
        }
        else if (isPacked())
        {
            mCurrentOffset += gl::VariableComponentCount(type);
        }
        else
        {
            mCurrentOffset += ComponentsPerRegister;
        }
    }
    
    void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
    {
        mCurrentOffset += (numRegisters * ComponentsPerRegister);
    }
    
    HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
    {
        switch (outputType)
        {
          case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
          case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
          default: UNREACHABLE(); return ENCODE_PACKED;
        }
    }
    
    template <class ShaderVarType>
    void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
    {
        if (variable.isStruct())
        {
            for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
            {
                encoder->enterAggregateType();
    
                for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
                {
                    HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
                }
    
                encoder->exitAggregateType();
            }
        }
        else
        {
            // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
            encoder->encodeType(variable.type, variable.arraySize, false);
        }
    }
    
    unsigned int HLSLVariableRegisterCount(const Varying &variable)
    {
        HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
        HLSLVariableRegisterCount(variable, &encoder);
    
        const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
        return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
    }
    
    unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
    {
        HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
        HLSLVariableRegisterCount(variable, &encoder);
    
        const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
        return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
    }
    
    }