Edit

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

Branch :

  • Show log

    Commit

  • Author : Olli Etuaho
    Date : 2015-04-27 13:18:50
    Hash : 37ad4744
    Message : Add support for parsing ESSL3 invariant qualifiers The parser recognizes ESSL3 invariant variable declaration syntax and marks the variables as invariant. In ESSL3, invariant out variables can be linked to non-invariant in variables, so linking checks should now be different depending on shading language version. A shading language version dependent varying matching check is added to the translator API to facilitate this. Tested by deqp/data/gles3/shaders/qualification_order.html after patching Chrome to use the new linking check API. A previous revision of this change that broke API compatibility was reverted since it broke Chromium FYI bots. This revision keeps deprecated API functionality around for now so that changes can be rolled step-by-step to Chromium without breakage. TEST=WebGL 2 conformance tests, angle_unittests BUG=angleproject:987 Change-Id: Iecb64e3afd23e267ba999bc17f44390affcdfc13 Reviewed-on: https://chromium-review.googlesource.com/269940 Reviewed-by: Jamie Madill <jmadill@chromium.org> Tested-by: Olli Etuaho <oetuaho@nvidia.com>

  • 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);
    }
    
    Attribute::Attribute()
        : location(-1)
    {}
    
    Attribute::~Attribute()
    {}
    
    Attribute::Attribute(const Attribute &other)
        : ShaderVariable(other),
          location(other.location)
    {}
    
    Attribute &Attribute::operator=(const Attribute &other)
    {
        ShaderVariable::operator=(other);
        location = other.location;
        return *this;
    }
    
    bool Attribute::operator==(const Attribute &other) const
    {
        return (ShaderVariable::operator==(other) &&
                location == other.location);
    }
    
    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;
    }
    
    }