Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2016-02-08 15:05:17
    Hash : 39046169
    Message : CollectVariables: Don't include block name in field name. The spec mandates that the instance name of a block determines how the active uniform name for this field is reported. However, our handling of this was a bit bugged. We would include the proper prefix on the compiler-side, but this mangled the hashing, and was also not strictly needed. We now also expose the instance name, so we can determine the proper prefix for variable linking on the GL-side of things. This also is consistent with how we handle other spec issues, where the GL-side handles the GL-API specific functionality. This also allows us to fix name hashing of instanced uniform blocks, which was previously broken because we would hash the full name of the active uniform, instead of just the field. BUG=angleproject:1306 Change-Id: I06ace6dbc3f75fdd8129677360dcc142aa89136e Reviewed-on: https://chromium-review.googlesource.com/326681 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: 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;
    }
    
    std::string InterfaceBlock::fieldPrefix() const
    {
        return instanceName.empty() ? "" : name;
    }
    
    }  // namespace sh