Edit

kc3-lang/angle/src/libANGLE/VaryingPacking_unittest.cpp

Branch :

  • Show log

    Commit

  • Author : Shahbaz Youssefi
    Date : 2020-02-03 10:33:58
    Hash : f764fc02
    Message : Fix varying linking by location This change breaks the assumption everywhere that varyings can be identified uniquely by name throughout all stages of the pipeline. It further implements linking of varyings by location, if specified. Bug: angleproject:4355 Change-Id: Ie45e48879008c3f0c22d1da3d0d26f37c655e54e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2030026 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com>

  • src/libANGLE/VaryingPacking_unittest.cpp
  • //
    // Copyright 2016 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_unittest.cpp:
    //   Tests for ANGLE's internal varying packing algorithm.
    //
    
    #include <gtest/gtest.h>
    // 'None' is defined as 'struct None {};' in
    // third_party/googletest/src/googletest/include/gtest/internal/gtest-type-util.h.
    // But 'None' is also define as a numberic constant 0L in <X11/X.h>.
    // So we need to include gtest first to avoid such conflict.
    
    #include "libANGLE/Program.h"
    #include "libANGLE/VaryingPacking.h"
    
    using namespace gl;
    
    namespace
    {
    
    class VaryingPackingTest : public ::testing::TestWithParam<GLuint>
    {
      protected:
        VaryingPackingTest() {}
    
        bool testVaryingPacking(const std::vector<sh::ShaderVariable> &shVaryings,
                                VaryingPacking *varyingPacking)
        {
            std::vector<PackedVarying> packedVaryings;
            for (const sh::ShaderVariable &shVarying : shVaryings)
            {
                packedVaryings.push_back(PackedVarying(
                    VaryingInShaderRef(ShaderType::Vertex, &shVarying),
                    VaryingInShaderRef(ShaderType::Fragment, &shVarying), shVarying.interpolation));
            }
    
            InfoLog infoLog;
            std::vector<std::string> transformFeedbackVaryings;
    
            return varyingPacking->packUserVaryings(infoLog, packedVaryings);
        }
    
        // Uses the "relaxed" ANGLE packing mode.
        bool packVaryings(GLuint maxVaryings, const std::vector<sh::ShaderVariable> &shVaryings)
        {
            VaryingPacking varyingPacking(maxVaryings, PackMode::ANGLE_RELAXED);
            return testVaryingPacking(shVaryings, &varyingPacking);
        }
    
        // Uses the stricter WebGL style packing rules.
        bool packVaryingsStrict(GLuint maxVaryings, const std::vector<sh::ShaderVariable> &shVaryings)
        {
            VaryingPacking varyingPacking(maxVaryings, PackMode::WEBGL_STRICT);
            return testVaryingPacking(shVaryings, &varyingPacking);
        }
    
        const int kMaxVaryings = GetParam();
    };
    
    std::vector<sh::ShaderVariable> MakeVaryings(GLenum type, size_t count, size_t arraySize)
    {
        std::vector<sh::ShaderVariable> varyings;
    
        for (size_t index = 0; index < count; ++index)
        {
            std::stringstream strstr;
            strstr << type << index;
    
            sh::ShaderVariable varying;
            varying.type       = type;
            varying.precision  = GL_MEDIUM_FLOAT;
            varying.name       = strstr.str();
            varying.mappedName = strstr.str();
            if (arraySize > 0)
            {
                varying.arraySizes.push_back(static_cast<unsigned int>(arraySize));
            }
            varying.staticUse     = true;
            varying.interpolation = sh::INTERPOLATION_FLAT;
            varying.isInvariant   = false;
    
            varyings.push_back(varying);
        }
    
        return varyings;
    }
    
    void AddVaryings(std::vector<sh::ShaderVariable> *varyings,
                     GLenum type,
                     size_t count,
                     size_t arraySize)
    {
        const auto &newVaryings = MakeVaryings(type, count, arraySize);
        varyings->insert(varyings->end(), newVaryings.begin(), newVaryings.end());
    }
    
    // Test that a single varying can't overflow the packing.
    TEST_P(VaryingPackingTest, OneVaryingLargerThanMax)
    {
        ASSERT_FALSE(packVaryings(1, MakeVaryings(GL_FLOAT_MAT4, 1, 0)));
    }
    
    // This will overflow the available varying space.
    TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec3)
    {
        ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings + 1, 0)));
    }
    
    // This will overflow the available varying space.
    TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec3Array)
    {
        ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2 + 1, 2)));
    }
    
    // This will overflow the available varying space.
    TEST_P(VaryingPackingTest, MaxVaryingVec3AndOneVec2)
    {
        std::vector<sh::ShaderVariable> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings, 0);
        AddVaryings(&varyings, GL_FLOAT_VEC2, 1, 0);
        ASSERT_FALSE(packVaryings(kMaxVaryings, varyings));
    }
    
    // This should work since two vec2s are packed in a single register.
    TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec2)
    {
        ASSERT_TRUE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings + 1, 0)));
    }
    
    // Same for this one as above.
    TEST_P(VaryingPackingTest, TwiceMaxVaryingVec2)
    {
        ASSERT_TRUE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings * 2, 0)));
    }
    
    // This should not work since it overflows available varying space.
    TEST_P(VaryingPackingTest, TooManyVaryingVec2)
    {
        ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings * 2 + 1, 0)));
    }
    
    // This should work according to the example GL packing rules - the float varyings are slotted
    // into the end of the vec3 varying arrays.
    TEST_P(VaryingPackingTest, MaxVaryingVec3ArrayAndFloatArrays)
    {
        std::vector<sh::ShaderVariable> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2, 2);
        AddVaryings(&varyings, GL_FLOAT, kMaxVaryings / 2, 2);
        ASSERT_TRUE(packVaryings(kMaxVaryings, varyings));
    }
    
    // This should not work - it has one too many float arrays.
    TEST_P(VaryingPackingTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
    {
        std::vector<sh::ShaderVariable> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2, 2);
        AddVaryings(&varyings, GL_FLOAT, kMaxVaryings / 2 + 1, 2);
        ASSERT_FALSE(packVaryings(kMaxVaryings, varyings));
    }
    
    // WebGL should fail to pack max+1 vec2 arrays, unlike our more relaxed packing.
    TEST_P(VaryingPackingTest, MaxPlusOneMat2VaryingsFailsWebGL)
    {
        auto varyings = MakeVaryings(GL_FLOAT_MAT2, kMaxVaryings / 2 + 1, 0);
        ASSERT_FALSE(packVaryingsStrict(kMaxVaryings, varyings));
    }
    
    // Makes separate tests for different values of kMaxVaryings.
    INSTANTIATE_TEST_SUITE_P(, VaryingPackingTest, ::testing::Values(1, 4, 8));
    
    }  // anonymous namespace