Edit

kc3-lang/angle/src/libANGLE/VaryingPacking.h

Branch :

  • Show log

    Commit

  • Author : Shahbaz Youssefi
    Date : 2019-04-15 15:39:39
    Hash : 051b0896
    Message : Vulkan: Fix layout substitution for struct varyings If the shader contains code such as the following: struct S { vec4 field; }; out S varStruct; The layout qualifier macro is defined as @@ LAYOUT-varStruct @@. However, the Vulkan backend was replacing @@ LAYOUT-field @@. Bug: angleproject:3220 Change-Id: Iae15003867e0bed2cc939159a6653429c7a431e0 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1571389 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>

  • src/libANGLE/VaryingPacking.h
  • //
    // Copyright 2015 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.
    //
    // VaryingPacking:
    //   Class which describes a mapping from varyings to registers, according
    //   to the spec, or using custom packing algorithms. We also keep a register
    //   allocation list for the D3D renderer.
    //
    
    #ifndef LIBANGLE_VARYINGPACKING_H_
    #define LIBANGLE_VARYINGPACKING_H_
    
    #include <GLSLANG/ShaderVars.h>
    
    #include "angle_gl.h"
    #include "common/angleutils.h"
    
    #include <map>
    
    namespace gl
    {
    class InfoLog;
    struct ProgramVaryingRef;
    
    using ProgramMergedVaryings = std::map<std::string, ProgramVaryingRef>;
    
    struct PackedVarying
    {
        PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn)
            : PackedVarying(varyingIn, interpolationIn, "", false)
        {}
        PackedVarying(const sh::ShaderVariable &varyingIn,
                      sh::InterpolationType interpolationIn,
                      const std::string &parentStructNameIn,
                      GLuint fieldIndexIn)
            : varying(&varyingIn),
              vertexOnly(false),
              interpolation(interpolationIn),
              parentStructName(parentStructNameIn),
              arrayIndex(GL_INVALID_INDEX),
              fieldIndex(fieldIndexIn)
        {}
    
        bool isStructField() const { return !parentStructName.empty(); }
    
        bool isArrayElement() const { return arrayIndex != GL_INVALID_INDEX; }
    
        std::string fullName() const
        {
            std::stringstream fullNameStr;
            if (isStructField())
            {
                fullNameStr << parentStructName << ".";
            }
    
            fullNameStr << varying->name;
            if (arrayIndex != GL_INVALID_INDEX)
            {
                fullNameStr << "[" << arrayIndex << "]";
            }
            return fullNameStr.str();
        }
    
        const sh::ShaderVariable *varying;
    
        // Transform feedback varyings can be only referenced in the VS.
        bool vertexOnly;
    
        // Cached so we can store sh::ShaderVariable to point to varying fields.
        sh::InterpolationType interpolation;
    
        // Struct name
        std::string parentStructName;
    
        GLuint arrayIndex;
    
        // Field index in the struct.  In Vulkan, this is used to assign a
        // struct-typed varying location to the location of its first field.
        GLuint fieldIndex;
    };
    
    struct PackedVaryingRegister final
    {
        PackedVaryingRegister()
            : packedVarying(nullptr),
              varyingArrayIndex(0),
              varyingRowIndex(0),
              registerRow(0),
              registerColumn(0)
        {}
    
        PackedVaryingRegister(const PackedVaryingRegister &) = default;
        PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
    
        bool operator<(const PackedVaryingRegister &other) const
        {
            return sortOrder() < other.sortOrder();
        }
    
        unsigned int sortOrder() const
        {
            // TODO(jmadill): Handle interpolation types
            return registerRow * 4 + registerColumn;
        }
    
        std::string tfVaryingName() const
        {
            if (packedVarying->isArrayElement() || packedVarying->isStructField())
            {
                return packedVarying->fullName();
            }
            else
            {
                return packedVarying->varying->name;
            }
        }
    
        // Index to the array of varyings.
        const PackedVarying *packedVarying;
    
        // The array element of the packed varying.
        unsigned int varyingArrayIndex;
    
        // The row of the array element of the packed varying.
        unsigned int varyingRowIndex;
    
        // The register row to which we've assigned this packed varying.
        unsigned int registerRow;
    
        // The column of the register row into which we've packed this varying.
        unsigned int registerColumn;
    };
    
    // Supported packing modes:
    enum class PackMode
    {
        // We treat mat2 arrays as taking two full rows.
        WEBGL_STRICT,
    
        // We allow mat2 to take a 2x2 chunk.
        ANGLE_RELAXED,
    
        // Each varying takes a separate register. No register sharing.
        ANGLE_NON_CONFORMANT_D3D9,
    };
    
    class VaryingPacking final : angle::NonCopyable
    {
      public:
        VaryingPacking(GLuint maxVaryingVectors, PackMode packMode);
        ~VaryingPacking();
    
        bool packUserVaryings(gl::InfoLog &infoLog, const std::vector<PackedVarying> &packedVaryings);
    
        bool collectAndPackUserVaryings(gl::InfoLog &infoLog,
                                        const ProgramMergedVaryings &mergedVaryings,
                                        const std::vector<std::string> &tfVaryings);
    
        struct Register
        {
            Register() { data[0] = data[1] = data[2] = data[3] = false; }
    
            bool &operator[](unsigned int index) { return data[index]; }
            bool operator[](unsigned int index) const { return data[index]; }
    
            bool data[4];
        };
    
        Register &operator[](unsigned int index) { return mRegisterMap[index]; }
        const Register &operator[](unsigned int index) const { return mRegisterMap[index]; }
    
        const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; }
        unsigned int getMaxSemanticIndex() const
        {
            return static_cast<unsigned int>(mRegisterList.size());
        }
    
        const std::vector<std::string> &getInactiveVaryingNames() const
        {
            return mInactiveVaryingNames;
        }
    
      private:
        bool packVarying(const PackedVarying &packedVarying);
        bool isFree(unsigned int registerRow,
                    unsigned int registerColumn,
                    unsigned int varyingRows,
                    unsigned int varyingColumns) const;
        void insert(unsigned int registerRow,
                    unsigned int registerColumn,
                    const PackedVarying &packedVarying);
    
        std::vector<Register> mRegisterMap;
        std::vector<PackedVaryingRegister> mRegisterList;
        std::vector<PackedVarying> mPackedVaryings;
        std::vector<std::string> mInactiveVaryingNames;
    
        PackMode mPackMode;
    };
    
    }  // namespace gl
    
    #endif  // LIBANGLE_VARYINGPACKING_H_