| // |
| // 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 |