| // |
| // 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(GLint maxVaryings, |
| PackMode packMode, |
| const std::vector<sh::ShaderVariable> &shVaryings) |
| { |
| ProgramMergedVaryings mergedVaryings; |
| for (const sh::ShaderVariable &shVarying : shVaryings) |
| { |
| ProgramVaryingRef ref; |
| ref.frontShader = &shVarying; |
| ref.backShader = &shVarying; |
| ref.frontShaderStage = ShaderType::Vertex; |
| ref.backShaderStage = ShaderType::Fragment; |
| mergedVaryings.push_back(ref); |
| } |
| |
| InfoLog infoLog; |
| std::vector<std::string> transformFeedbackVaryings; |
| |
| VaryingPacking varyingPacking; |
| return varyingPacking.collectAndPackUserVaryings( |
| infoLog, maxVaryings, packMode, ShaderType::Vertex, ShaderType::Fragment, |
| mergedVaryings, transformFeedbackVaryings, false); |
| } |
| |
| // Uses the "relaxed" ANGLE packing mode. |
| bool packVaryings(GLint maxVaryings, const std::vector<sh::ShaderVariable> &shVaryings) |
| { |
| return testVaryingPacking(maxVaryings, PackMode::ANGLE_RELAXED, shVaryings); |
| } |
| |
| // Uses the stricter WebGL style packing rules. |
| bool packVaryingsStrict(GLint maxVaryings, const std::vector<sh::ShaderVariable> &shVaryings) |
| { |
| return testVaryingPacking(maxVaryings, PackMode::WEBGL_STRICT, shVaryings); |
| } |
| |
| 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 |