Edit

kc3-lang/angle/src/compiler/translator/ShaderVars.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2015-09-02 15:54:30
    Hash : a0a9e12d
    Message : translator: Add sh::OutputVariable type. This replaces the dual-use of sh::Attribute, which can be a bit confusing to people expecting a literal output variable. Currently not used in Chromium, so should be safe to land. BUG=angleproject:1146 Change-Id: I436f2bc9dc4ddc3709369cb2baa344c6b13a21a2 Reviewed-on: https://chromium-review.googlesource.com/296683 Reviewed-by: Kenneth Russell <kbr@chromium.org> Reviewed-by: Zhenyao Mo <zmo@chromium.org> Tested-by: Jamie Madill <jmadill@chromium.org>

  • src/compiler/translator/ShaderVars.cpp
  • //
    // Copyright (c) 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.
    //
    // ShaderVars.cpp:
    //  Methods for GL variable types (varyings, uniforms, etc)
    //
    
    #include <GLSLANG/ShaderLang.h>
    
    #include "common/debug.h"
    
    namespace sh
    {
    
    namespace
    {
    
    InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation)
    {
        return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation);
    }
    
    }
    // The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion
    // on Khronos.org, clarifies that a smooth/flat mismatch produces a link error,
    // but auxiliary qualifier mismatch (centroid) does not.
    bool InterpolationTypesMatch(InterpolationType a, InterpolationType b)
    {
        return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b));
    }
    
    ShaderVariable::ShaderVariable()
        : type(0),
          precision(0),
          arraySize(0),
          staticUse(false)
    {}
    
    ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn)
        : type(typeIn),
          precision(0),
          arraySize(arraySizeIn),
          staticUse(false)
    {}
    
    ShaderVariable::~ShaderVariable()
    {}
    
    ShaderVariable::ShaderVariable(const ShaderVariable &other)
        : type(other.type),
          precision(other.precision),
          name(other.name),
          mappedName(other.mappedName),
          arraySize(other.arraySize),
          staticUse(other.staticUse),
          fields(other.fields),
          structName(other.structName)
    {}
    
    ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
    {
        type = other.type;
        precision = other.precision;
        name = other.name;
        mappedName = other.mappedName;
        arraySize = other.arraySize;
        staticUse = other.staticUse;
        fields = other.fields;
        structName = other.structName;
        return *this;
    }
    
    bool ShaderVariable::operator==(const ShaderVariable &other) const
    {
        if (type != other.type ||
            precision != other.precision ||
            name != other.name ||
            mappedName != other.mappedName ||
            arraySize != other.arraySize ||
            staticUse != other.staticUse ||
            fields.size() != other.fields.size() ||
            structName != other.structName)
        {
            return false;
        }
        for (size_t ii = 0; ii < fields.size(); ++ii)
        {
            if (fields[ii] != other.fields[ii])
                return false;
        }
        return true;
    }
    
    bool ShaderVariable::findInfoByMappedName(
        const std::string &mappedFullName,
        const ShaderVariable **leafVar, std::string *originalFullName) const
    {
        ASSERT(leafVar && originalFullName);
        // There are three cases:
        // 1) the top variable is of struct type;
        // 2) the top variable is an array;
        // 3) otherwise.
        size_t pos = mappedFullName.find_first_of(".[");
    
        if (pos == std::string::npos)
        {
            // Case 3.
            if (mappedFullName != this->mappedName)
                return false;
            *originalFullName = this->name;
            *leafVar = this;
            return true;
        }
        else
        {
            std::string topName = mappedFullName.substr(0, pos);
            if (topName != this->mappedName)
                return false;
            std::string originalName = this->name;
            std::string remaining;
            if (mappedFullName[pos] == '[')
            {
                // Case 2.
                size_t closePos = mappedFullName.find_first_of(']');
                if (closePos < pos || closePos == std::string::npos)
                    return false;
                // Append '[index]'.
                originalName += mappedFullName.substr(pos, closePos - pos + 1);
                if (closePos + 1 == mappedFullName.size())
                {
                    *originalFullName = originalName;
                    *leafVar = this;
                    return true;
                }
                else
                {
                    // In the form of 'a[0].b', so after ']', '.' is expected.
                    if (mappedFullName[closePos + 1]  != '.')
                        return false;
                    remaining = mappedFullName.substr(closePos + 2);  // Skip "]."
                }
            }
            else
            {
                // Case 1.
                remaining = mappedFullName.substr(pos + 1);  // Skip "."
            }
            for (size_t ii = 0; ii < this->fields.size(); ++ii)
            {
                const ShaderVariable *fieldVar = NULL;
                std::string originalFieldName;
                bool found = fields[ii].findInfoByMappedName(
                    remaining, &fieldVar, &originalFieldName);
                if (found)
                {
                    *originalFullName = originalName + "." + originalFieldName;
                    *leafVar = fieldVar;
                    return true;
                }
            }
            return false;
        }
    }
    
    bool ShaderVariable::isSameVariableAtLinkTime(
        const ShaderVariable &other, bool matchPrecision) const
    {
        if (type != other.type)
            return false;
        if (matchPrecision && precision != other.precision)
            return false;
        if (name != other.name)
            return false;
        ASSERT(mappedName == other.mappedName);
        if (arraySize != other.arraySize)
            return false;
        if (fields.size() != other.fields.size())
            return false;
        for (size_t ii = 0; ii < fields.size(); ++ii)
        {
            if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii],
                                                     matchPrecision))
            {
                return false;
            }
        }
        if (structName != other.structName)
            return false;
        return true;
    }
    
    Uniform::Uniform()
    {}
    
    Uniform::~Uniform()
    {}
    
    Uniform::Uniform(const Uniform &other)
        : ShaderVariable(other)
    {}
    
    Uniform &Uniform::operator=(const Uniform &other)
    {
        ShaderVariable::operator=(other);
        return *this;
    }
    
    bool Uniform::operator==(const Uniform &other) const
    {
        return ShaderVariable::operator==(other);
    }
    
    bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
    {
        return ShaderVariable::isSameVariableAtLinkTime(other, true);
    }
    
    InterfaceVariable::InterfaceVariable() : location(-1)
    {}
    
    InterfaceVariable::~InterfaceVariable()
    {}
    
    InterfaceVariable::InterfaceVariable(const InterfaceVariable &other)
        : ShaderVariable(other), location(other.location)
    {}
    
    InterfaceVariable &InterfaceVariable::operator=(const InterfaceVariable &other)
    {
        ShaderVariable::operator=(other);
        location = other.location;
        return *this;
    }
    
    bool InterfaceVariable::operator==(const InterfaceVariable &other) const
    {
        return (ShaderVariable::operator==(other) &&
                location == other.location);
    }
    
    Attribute::Attribute()
    {
    }
    
    Attribute::~Attribute()
    {
    }
    
    Attribute::Attribute(const Attribute &other) : InterfaceVariable(other)
    {
    }
    
    Attribute &Attribute::operator=(const Attribute &other)
    {
        InterfaceVariable::operator=(other);
        return *this;
    }
    
    bool Attribute::operator==(const Attribute &other) const
    {
        return InterfaceVariable::operator==(other);
    }
    
    OutputVariable::OutputVariable()
    {
    }
    
    OutputVariable::~OutputVariable()
    {
    }
    
    OutputVariable::OutputVariable(const OutputVariable &other) : InterfaceVariable(other)
    {
    }
    
    OutputVariable &OutputVariable::operator=(const OutputVariable &other)
    {
        InterfaceVariable::operator=(other);
        return *this;
    }
    
    bool OutputVariable::operator==(const OutputVariable &other) const
    {
        return InterfaceVariable::operator==(other);
    }
    
    InterfaceBlockField::InterfaceBlockField()
        : isRowMajorLayout(false)
    {}
    
    InterfaceBlockField::~InterfaceBlockField()
    {}
    
    InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other)
        : ShaderVariable(other),
          isRowMajorLayout(other.isRowMajorLayout)
    {}
    
    InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other)
    {
        ShaderVariable::operator=(other);
        isRowMajorLayout = other.isRowMajorLayout;
        return *this;
    }
    
    bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
    {
        return (ShaderVariable::operator==(other) &&
                isRowMajorLayout == other.isRowMajorLayout);
    }
    
    bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
        const InterfaceBlockField &other) const
    {
        return (ShaderVariable::isSameVariableAtLinkTime(other, true) &&
                isRowMajorLayout == other.isRowMajorLayout);
    }
    
    Varying::Varying()
        : interpolation(INTERPOLATION_SMOOTH),
          isInvariant(false)
    {}
    
    Varying::~Varying()
    {}
    
    Varying::Varying(const Varying &other)
        : ShaderVariable(other),
          interpolation(other.interpolation),
          isInvariant(other.isInvariant)
    {}
    
    Varying &Varying::operator=(const Varying &other)
    {
        ShaderVariable::operator=(other);
        interpolation = other.interpolation;
        isInvariant = other.isInvariant;
        return *this;
    }
    
    bool Varying::operator==(const Varying &other) const
    {
        return (ShaderVariable::operator==(other) &&
                interpolation == other.interpolation &&
                isInvariant == other.isInvariant);
    }
    
    bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
    {
        return isSameVaryingAtLinkTime(other, 100);
    }
    
    bool Varying::isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const
    {
        return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
                interpolation == other.interpolation &&
                (shaderVersion >= 300 || isInvariant == other.isInvariant));
    }
    
    InterfaceBlock::InterfaceBlock()
        : arraySize(0),
          layout(BLOCKLAYOUT_PACKED),
          isRowMajorLayout(false),
          staticUse(false)
    {}
    
    InterfaceBlock::~InterfaceBlock()
    {}
    
    InterfaceBlock::InterfaceBlock(const InterfaceBlock &other)
        : name(other.name),
          mappedName(other.mappedName),
          instanceName(other.instanceName),
          arraySize(other.arraySize),
          layout(other.layout),
          isRowMajorLayout(other.isRowMajorLayout),
          staticUse(other.staticUse),
          fields(other.fields)
    {}
    
    InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
    {
        name = other.name;
        mappedName = other.mappedName;
        instanceName = other.instanceName;
        arraySize = other.arraySize;
        layout = other.layout;
        isRowMajorLayout = other.isRowMajorLayout;
        staticUse = other.staticUse;
        fields = other.fields;
        return *this;
    }
    
    }