// // 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 // '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 . // 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 { protected: VaryingPackingTest() {} bool testVaryingPacking(const std::vector &shVaryings, VaryingPacking *varyingPacking) { std::vector 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 transformFeedbackVaryings; return varyingPacking->packUserVaryings(infoLog, packedVaryings); } // Uses the "relaxed" ANGLE packing mode. bool packVaryings(GLuint maxVaryings, const std::vector &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 &shVaryings) { VaryingPacking varyingPacking(maxVaryings, PackMode::WEBGL_STRICT); return testVaryingPacking(shVaryings, &varyingPacking); } const int kMaxVaryings = GetParam(); }; std::vector MakeVaryings(GLenum type, size_t count, size_t arraySize) { std::vector 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(arraySize)); } varying.staticUse = true; varying.interpolation = sh::INTERPOLATION_FLAT; varying.isInvariant = false; varyings.push_back(varying); } return varyings; } void AddVaryings(std::vector *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 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 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 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