// // Copyright (c) 2002-2012 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. // #include "gtest/gtest.h" #include "angle_gl.h" #include "common/utilities.h" #include "common/angleutils.h" #include "compiler/translator/VariablePacker.h" static sh::GLenum types[] = { GL_FLOAT_MAT4, // 0 GL_FLOAT_MAT2, // 1 GL_FLOAT_VEC4, // 2 GL_INT_VEC4, // 3 GL_BOOL_VEC4, // 4 GL_FLOAT_MAT3, // 5 GL_FLOAT_VEC3, // 6 GL_INT_VEC3, // 7 GL_BOOL_VEC3, // 8 GL_FLOAT_VEC2, // 9 GL_INT_VEC2, // 10 GL_BOOL_VEC2, // 11 GL_FLOAT, // 12 GL_INT, // 13 GL_BOOL, // 14 GL_SAMPLER_2D, // 15 GL_SAMPLER_CUBE, // 16 GL_SAMPLER_EXTERNAL_OES, // 17 GL_SAMPLER_2D_RECT_ARB, // 18 GL_UNSIGNED_INT, // 19 GL_UNSIGNED_INT_VEC2, // 20 GL_UNSIGNED_INT_VEC3, // 21 GL_UNSIGNED_INT_VEC4, // 22 GL_FLOAT_MAT2x3, // 23 GL_FLOAT_MAT2x4, // 24 GL_FLOAT_MAT3x2, // 25 GL_FLOAT_MAT3x4, // 26 GL_FLOAT_MAT4x2, // 27 GL_FLOAT_MAT4x3, // 28 GL_SAMPLER_3D, // 29 GL_SAMPLER_2D_ARRAY, // 30 GL_SAMPLER_2D_SHADOW, // 31 GL_SAMPLER_CUBE_SHADOW, // 32 GL_SAMPLER_2D_ARRAY_SHADOW, // 33 GL_INT_SAMPLER_2D, // 34 GL_INT_SAMPLER_CUBE, // 35 GL_INT_SAMPLER_3D, // 36 GL_INT_SAMPLER_2D_ARRAY, // 37 GL_UNSIGNED_INT_SAMPLER_2D, // 38 GL_UNSIGNED_INT_SAMPLER_CUBE, // 39 GL_UNSIGNED_INT_SAMPLER_3D, // 40 GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, // 41 }; static sh::GLenum nonSqMatTypes[] = { GL_FLOAT_MAT2x3, GL_FLOAT_MAT2x4, GL_FLOAT_MAT3x2, GL_FLOAT_MAT3x4, GL_FLOAT_MAT4x2, GL_FLOAT_MAT4x3 }; TEST(VariablePacking, Pack) { VariablePacker packer; std::vector vars; const int kMaxRows = 16; // test no vars. EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); for (size_t tt = 0; tt < ArraySize(types); ++tt) { sh::GLenum type = types[tt]; int num_rows = VariablePacker::GetNumRows(type); int num_components_per_row = VariablePacker::GetNumComponentsPerRow(type); // Check 1 of the type. vars.clear(); vars.push_back(sh::ShaderVariable(type, 0)); EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); // Check exactly the right amount of 1 type as an array. int num_vars = kMaxRows / num_rows; vars.clear(); vars.push_back(sh::ShaderVariable(type, num_vars == 1 ? 0 : num_vars)); EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); // test too many vars.clear(); vars.push_back(sh::ShaderVariable(type, num_vars == 0 ? 0 : (num_vars + 1))); EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); // Check exactly the right amount of 1 type as individual vars. num_vars = kMaxRows / num_rows * ((num_components_per_row > 2) ? 1 : (4 / num_components_per_row)); vars.clear(); for (int ii = 0; ii < num_vars; ++ii) { vars.push_back(sh::ShaderVariable(type, 0)); } EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); // Check 1 too many. vars.push_back(sh::ShaderVariable(type, 0)); EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); } // Test example from GLSL ES 3.0 spec chapter 11. vars.clear(); vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC4, 0)); vars.push_back(sh::ShaderVariable(GL_FLOAT_MAT3, 0)); vars.push_back(sh::ShaderVariable(GL_FLOAT_MAT3, 0)); vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 6)); vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 4)); vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 0)); vars.push_back(sh::ShaderVariable(GL_FLOAT, 3)); vars.push_back(sh::ShaderVariable(GL_FLOAT, 2)); vars.push_back(sh::ShaderVariable(GL_FLOAT, 0)); EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); } TEST(VariablePacking, PackSizes) { for (size_t tt = 0; tt < ArraySize(types); ++tt) { GLenum type = types[tt]; int expectedComponents = gl::VariableComponentCount(type); int expectedRows = gl::VariableRowCount(type); if (type == GL_FLOAT_MAT2) { expectedComponents = 4; } else if (gl::IsMatrixType(type)) { int squareSize = std::max(gl::VariableRowCount(type), gl::VariableColumnCount(type)); expectedComponents = squareSize; expectedRows = squareSize; } EXPECT_EQ(expectedComponents, VariablePacker::GetNumComponentsPerRow(type)); EXPECT_EQ(expectedRows, VariablePacker::GetNumRows(type)); } } // Check special assumptions about packing non-square mats TEST(VariablePacking, NonSquareMats) { for (size_t mt = 0; mt < ArraySize(nonSqMatTypes); ++mt) { GLenum type = nonSqMatTypes[mt]; int rows = gl::VariableRowCount(type); int cols = gl::VariableColumnCount(type); int squareSize = std::max(rows, cols); std::vector vars; vars.push_back(sh::ShaderVariable(type, 0)); // Fill columns for (int row = 0; row < squareSize; row++) { for (int col = squareSize; col < 4; ++col) { vars.push_back(sh::ShaderVariable(GL_FLOAT, 0)); } } VariablePacker packer; EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(squareSize, vars)); // and one scalar and packing should fail vars.push_back(sh::ShaderVariable(GL_FLOAT, 0)); EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(squareSize, vars)); } } // Scalar type variables can be packed sharing rows with other variables. TEST(VariablePacking, ReuseRows) { VariablePacker packer; std::vector vars; const int kMaxRows = 512; // uniform bool u0[129]; // uniform bool u1[129]; // uniform bool u2[129]; // uniform bool u3[129]; { int num_arrays = 4; int num_elements_per_array = kMaxRows / num_arrays + 1; for (int ii = 0; ii < num_arrays; ++ii) { vars.push_back(sh::ShaderVariable(GL_BOOL, num_elements_per_array)); } EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); } vars.clear(); // uniform vec2 u0[257]; // uniform float u1[257]; // uniform int u1[257]; { int num_elements_per_array = kMaxRows / 2 + 1; vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, num_elements_per_array)); vars.push_back(sh::ShaderVariable(GL_FLOAT, num_elements_per_array)); vars.push_back(sh::ShaderVariable(GL_INT, num_elements_per_array)); EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); } } // Check the packer supports and flattens structures. TEST(VariablePacking, Struct) { VariablePacker packer; std::vector fields; const int kMaxRows = 16; // Test example from GLSL ES 3.0 spec chapter 11, but with structs std::vector vars; vars.push_back(sh::ShaderVariable(GL_STRUCT_ANGLEX, 0)); sh::ShaderVariable &parentStruct = vars[0]; parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC4, 0)); parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_MAT3, 0)); parentStruct.fields.push_back(sh::ShaderVariable(GL_STRUCT_ANGLEX, 0)); sh::ShaderVariable &innerStruct = parentStruct.fields.back(); innerStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_MAT3, 0)); innerStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 6)); innerStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 4)); parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 0)); parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 3)); parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 2)); parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 0)); EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); }