Commit d7487b13 by Olli Etuaho Committed by Commit Bot

Clean up checking variable packing limits

This encapsulates expanding struct variables inside the VariablePacker class that packs variables according to the GLSL ES spec. The variable expansion step is no longer run twice when checking uniforms against the max uniforms limit. BUG=angleproject:2068 TEST=angle_unittests Change-Id: I012ddaa249f71c0a78d937c98007c61352e64888 Reviewed-on: https://chromium-review.googlesource.com/608367 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 9b11ea4f
...@@ -484,13 +484,9 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -484,13 +484,9 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
} }
if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
{ {
std::vector<sh::ShaderVariable> expandedUniforms;
sh::ExpandUniforms(uniforms, &expandedUniforms);
VariablePacker packer;
// Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
// Appendix A, section 7, the shader does not use too many uniforms. // Appendix A, section 7, the shader does not use too many uniforms.
success = success = CheckVariablesInPackingLimits(maxUniformVectors, uniforms);
packer.CheckVariablesWithinPackingLimits(maxUniformVectors, expandedUniforms);
if (!success) if (!success)
{ {
mDiagnostics.globalError("too many uniforms"); mDiagnostics.globalError("too many uniforms");
......
...@@ -448,8 +448,7 @@ int GetVertexShaderNumViews(const ShHandle handle) ...@@ -448,8 +448,7 @@ int GetVertexShaderNumViews(const ShHandle handle)
bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables) bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables)
{ {
VariablePacker packer; return CheckVariablesInPackingLimits(maxVectors, variables);
return packer.CheckVariablesWithinPackingLimits(maxVectors, variables);
} }
bool GetUniformBlockRegister(const ShHandle handle, bool GetUniformBlockRegister(const ShHandle handle,
......
...@@ -49,24 +49,6 @@ BlockType GetBlockType(TQualifier qualifier) ...@@ -49,24 +49,6 @@ BlockType GetBlockType(TQualifier qualifier)
} }
} }
void ExpandUserDefinedVariable(const ShaderVariable &variable,
const std::string &name,
const std::string &mappedName,
bool markStaticUse,
std::vector<ShaderVariable> *expanded)
{
ASSERT(variable.isStruct());
const std::vector<ShaderVariable> &fields = variable.fields;
for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
{
const ShaderVariable &field = fields[fieldIndex];
ExpandVariable(field, name + "." + field.name, mappedName + "." + field.mappedName,
markStaticUse, expanded);
}
}
template <class VarT> template <class VarT>
VarT *FindVariable(const TString &name, std::vector<VarT> *infoList) VarT *FindVariable(const TString &name, std::vector<VarT> *infoList)
{ {
...@@ -716,58 +698,4 @@ void CollectVariables(TIntermBlock *root, ...@@ -716,58 +698,4 @@ void CollectVariables(TIntermBlock *root,
root->traverse(&collect); root->traverse(&collect);
} }
void ExpandVariable(const ShaderVariable &variable,
const std::string &name,
const std::string &mappedName,
bool markStaticUse,
std::vector<ShaderVariable> *expanded)
{
if (variable.isStruct())
{
if (variable.isArray())
{
for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
elementIndex++)
{
std::string lname = name + ::ArrayString(elementIndex);
std::string lmappedName = mappedName + ::ArrayString(elementIndex);
ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
}
}
else
{
ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
}
}
else
{
ShaderVariable expandedVar = variable;
expandedVar.name = name;
expandedVar.mappedName = mappedName;
// Mark all expanded fields as used if the parent is used
if (markStaticUse)
{
expandedVar.staticUse = true;
}
if (expandedVar.isArray())
{
expandedVar.name += "[0]";
expandedVar.mappedName += "[0]";
}
expanded->push_back(expandedVar);
}
}
void ExpandUniforms(const std::vector<Uniform> &compact, std::vector<ShaderVariable> *expanded)
{
for (const Uniform &variable : compact)
{
ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
}
}
} // namespace sh } // namespace sh
...@@ -29,15 +29,6 @@ void CollectVariables(TIntermBlock *root, ...@@ -29,15 +29,6 @@ void CollectVariables(TIntermBlock *root,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
int shaderVersion, int shaderVersion,
const TExtensionBehavior &extensionBehavior); const TExtensionBehavior &extensionBehavior);
void ExpandVariable(const ShaderVariable &variable,
const std::string &name,
const std::string &mappedName,
bool markStaticUse,
std::vector<ShaderVariable> *expanded);
// Expand struct uniforms to flattened lists of split variables
void ExpandUniforms(const std::vector<Uniform> &compact, std::vector<ShaderVariable> *expanded);
} }
#endif // COMPILER_TRANSLATOR_VARIABLEINFO_H_ #endif // COMPILER_TRANSLATOR_VARIABLEINFO_H_
...@@ -3,39 +3,30 @@ ...@@ -3,39 +3,30 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// Check whether variables fit within packing limits according to the packing rules from the GLSL ES
// 1.00.17 spec, Appendix A, section 7.
#ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_ #ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_
#define COMPILER_TRANSLATOR_VARIABLEPACKER_H_ #define COMPILER_TRANSLATOR_VARIABLEPACKER_H_
#include <vector> #include <vector>
#include "compiler/translator/VariableInfo.h"
class VariablePacker #include <GLSLANG/ShaderLang.h>
namespace sh
{ {
public:
// Returns true if the passed in variables pack in maxVectors following // Gets how many components in a row a data type takes.
// the packing rules from the GLSL 1.017 spec, Appendix A, section 7. int GetVariablePackingComponentsPerRow(sh::GLenum type);
bool CheckVariablesWithinPackingLimits(unsigned int maxVectors,
const std::vector<sh::ShaderVariable> &in_variables); // Gets how many rows a data type takes.
int GetVariablePackingRows(sh::GLenum type);
// Gets how many components in a row a data type takes.
static int GetNumComponentsPerRow(sh::GLenum type); // Returns true if the passed in variables pack in maxVectors.
// T should be ShaderVariable or one of the subclasses of ShaderVariable.
// Gets how many rows a data type takes. template <typename T>
static int GetNumRows(sh::GLenum type); bool CheckVariablesInPackingLimits(unsigned int maxVectors, const std::vector<T> &variables);
private: } // namespace sh
static const int kNumColumns = 4;
static const unsigned kColumnMask = (1 << kNumColumns) - 1;
unsigned makeColumnFlags(int column, int numComponentsPerRow);
void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
bool searchColumn(int column, int numRows, int *destRow, int *destSize);
int topNonFullRow_;
int bottomNonFullRow_;
int maxRows_;
std::vector<unsigned> rows_;
};
#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_ #endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "compiler/translator/VariablePacker.h" #include "compiler/translator/VariablePacker.h"
namespace
{
static sh::GLenum types[] = { static sh::GLenum types[] = {
GL_FLOAT_MAT4, // 0 GL_FLOAT_MAT4, // 0
GL_FLOAT_MAT2, // 1 GL_FLOAT_MAT2, // 1
...@@ -54,42 +57,38 @@ static sh::GLenum types[] = { ...@@ -54,42 +57,38 @@ static sh::GLenum types[] = {
GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, // 41 GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, // 41
}; };
static sh::GLenum nonSqMatTypes[] = { static sh::GLenum nonSqMatTypes[] = {GL_FLOAT_MAT2x3, GL_FLOAT_MAT2x4, GL_FLOAT_MAT3x2,
GL_FLOAT_MAT2x3, GL_FLOAT_MAT3x4, GL_FLOAT_MAT4x2, GL_FLOAT_MAT4x3};
GL_FLOAT_MAT2x4,
GL_FLOAT_MAT3x2, } // anonymous namespace
GL_FLOAT_MAT3x4,
GL_FLOAT_MAT4x2,
GL_FLOAT_MAT4x3
};
TEST(VariablePacking, Pack) { TEST(VariablePacking, Pack)
VariablePacker packer; {
std::vector<sh::ShaderVariable> vars; std::vector<sh::ShaderVariable> vars;
const int kMaxRows = 16; const int kMaxRows = 16;
// test no vars. // test no vars.
EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
for (size_t tt = 0; tt < ArraySize(types); ++tt) for (size_t tt = 0; tt < ArraySize(types); ++tt)
{ {
sh::GLenum type = types[tt]; sh::GLenum type = types[tt];
int num_rows = VariablePacker::GetNumRows(type); int num_rows = sh::GetVariablePackingRows(type);
int num_components_per_row = VariablePacker::GetNumComponentsPerRow(type); int num_components_per_row = sh::GetVariablePackingComponentsPerRow(type);
// Check 1 of the type. // Check 1 of the type.
vars.clear(); vars.clear();
vars.push_back(sh::ShaderVariable(type, 0)); vars.push_back(sh::ShaderVariable(type, 0));
EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
// Check exactly the right amount of 1 type as an array. // Check exactly the right amount of 1 type as an array.
int num_vars = kMaxRows / num_rows; int num_vars = kMaxRows / num_rows;
vars.clear(); vars.clear();
vars.push_back(sh::ShaderVariable(type, num_vars == 1 ? 0 : num_vars)); vars.push_back(sh::ShaderVariable(type, num_vars == 1 ? 0 : num_vars));
EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
// test too many // test too many
vars.clear(); vars.clear();
vars.push_back(sh::ShaderVariable(type, num_vars == 0 ? 0 : (num_vars + 1))); vars.push_back(sh::ShaderVariable(type, num_vars == 0 ? 0 : (num_vars + 1)));
EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_FALSE(CheckVariablesInPackingLimits(kMaxRows, vars));
// Check exactly the right amount of 1 type as individual vars. // Check exactly the right amount of 1 type as individual vars.
num_vars = num_vars =
...@@ -99,11 +98,11 @@ TEST(VariablePacking, Pack) { ...@@ -99,11 +98,11 @@ TEST(VariablePacking, Pack) {
{ {
vars.push_back(sh::ShaderVariable(type, 0)); vars.push_back(sh::ShaderVariable(type, 0));
} }
EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
// Check 1 too many. // Check 1 too many.
vars.push_back(sh::ShaderVariable(type, 0)); vars.push_back(sh::ShaderVariable(type, 0));
EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_FALSE(CheckVariablesInPackingLimits(kMaxRows, vars));
} }
// Test example from GLSL ES 3.0 spec chapter 11. // Test example from GLSL ES 3.0 spec chapter 11.
...@@ -117,66 +116,70 @@ TEST(VariablePacking, Pack) { ...@@ -117,66 +116,70 @@ TEST(VariablePacking, Pack) {
vars.push_back(sh::ShaderVariable(GL_FLOAT, 3)); vars.push_back(sh::ShaderVariable(GL_FLOAT, 3));
vars.push_back(sh::ShaderVariable(GL_FLOAT, 2)); vars.push_back(sh::ShaderVariable(GL_FLOAT, 2));
vars.push_back(sh::ShaderVariable(GL_FLOAT, 0)); vars.push_back(sh::ShaderVariable(GL_FLOAT, 0));
EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
} }
TEST(VariablePacking, PackSizes) { TEST(VariablePacking, PackSizes)
for (size_t tt = 0; tt < ArraySize(types); ++tt) { {
GLenum type = types[tt]; for (size_t tt = 0; tt < ArraySize(types); ++tt)
{
sh::GLenum type = types[tt];
int expectedComponents = gl::VariableComponentCount(type); int expectedComponents = gl::VariableComponentCount(type);
int expectedRows = gl::VariableRowCount(type); int expectedRows = gl::VariableRowCount(type);
if (type == GL_FLOAT_MAT2) { if (type == GL_FLOAT_MAT2)
expectedComponents = 4; {
} else if (gl::IsMatrixType(type)) { expectedComponents = 4;
int squareSize = std::max(gl::VariableRowCount(type), }
gl::VariableColumnCount(type)); else if (gl::IsMatrixType(type))
expectedComponents = squareSize; {
expectedRows = squareSize; int squareSize = std::max(gl::VariableRowCount(type), gl::VariableColumnCount(type));
} expectedComponents = squareSize;
expectedRows = squareSize;
}
EXPECT_EQ(expectedComponents, EXPECT_EQ(expectedComponents, sh::GetVariablePackingComponentsPerRow(type));
VariablePacker::GetNumComponentsPerRow(type)); EXPECT_EQ(expectedRows, sh::GetVariablePackingRows(type));
EXPECT_EQ(expectedRows, VariablePacker::GetNumRows(type)); }
}
} }
// Check special assumptions about packing non-square mats // Check special assumptions about packing non-square mats
TEST(VariablePacking, NonSquareMats) { TEST(VariablePacking, NonSquareMats)
{
for (size_t mt = 0; mt < ArraySize(nonSqMatTypes); ++mt) { for (size_t mt = 0; mt < ArraySize(nonSqMatTypes); ++mt)
{
GLenum type = nonSqMatTypes[mt];
int rows = gl::VariableRowCount(type); sh::GLenum type = nonSqMatTypes[mt];
int cols = gl::VariableColumnCount(type);
int squareSize = std::max(rows, cols);
std::vector<sh::ShaderVariable> vars; int rows = gl::VariableRowCount(type);
vars.push_back(sh::ShaderVariable(type, 0)); int cols = gl::VariableColumnCount(type);
int squareSize = std::max(rows, cols);
// Fill columns std::vector<sh::ShaderVariable> vars;
for (int row = 0; row < squareSize; row++) { vars.push_back(sh::ShaderVariable(type, 0));
for (int col = squareSize; col < 4; ++col) {
vars.push_back(sh::ShaderVariable(GL_FLOAT, 0));
}
}
VariablePacker packer; // Fill columns
for (int row = 0; row < squareSize; row++)
{
for (int col = squareSize; col < 4; ++col)
{
vars.push_back(sh::ShaderVariable(GL_FLOAT, 0));
}
}
EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(squareSize, vars)); EXPECT_TRUE(CheckVariablesInPackingLimits(squareSize, vars));
// and one scalar and packing should fail // and one scalar and packing should fail
vars.push_back(sh::ShaderVariable(GL_FLOAT, 0)); vars.push_back(sh::ShaderVariable(GL_FLOAT, 0));
EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(squareSize, vars)); EXPECT_FALSE(CheckVariablesInPackingLimits(squareSize, vars));
} }
} }
// Scalar type variables can be packed sharing rows with other variables. // Scalar type variables can be packed sharing rows with other variables.
TEST(VariablePacking, ReuseRows) TEST(VariablePacking, ReuseRows)
{ {
VariablePacker packer;
std::vector<sh::ShaderVariable> vars; std::vector<sh::ShaderVariable> vars;
const int kMaxRows = 512; const int kMaxRows = 512;
...@@ -185,13 +188,13 @@ TEST(VariablePacking, ReuseRows) ...@@ -185,13 +188,13 @@ TEST(VariablePacking, ReuseRows)
// uniform bool u2[129]; // uniform bool u2[129];
// uniform bool u3[129]; // uniform bool u3[129];
{ {
int num_arrays = 4; int num_arrays = 4;
int num_elements_per_array = kMaxRows / num_arrays + 1; int num_elements_per_array = kMaxRows / num_arrays + 1;
for (int ii = 0; ii < num_arrays; ++ii) for (int ii = 0; ii < num_arrays; ++ii)
{ {
vars.push_back(sh::ShaderVariable(GL_BOOL, num_elements_per_array)); vars.push_back(sh::ShaderVariable(GL_BOOL, num_elements_per_array));
} }
EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
} }
vars.clear(); vars.clear();
...@@ -203,14 +206,13 @@ TEST(VariablePacking, ReuseRows) ...@@ -203,14 +206,13 @@ TEST(VariablePacking, ReuseRows)
vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, num_elements_per_array)); 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_FLOAT, num_elements_per_array));
vars.push_back(sh::ShaderVariable(GL_INT, num_elements_per_array)); vars.push_back(sh::ShaderVariable(GL_INT, num_elements_per_array));
EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
} }
} }
// Check the packer supports and flattens structures. // Check the packer supports and flattens structures.
TEST(VariablePacking, Struct) TEST(VariablePacking, Struct)
{ {
VariablePacker packer;
std::vector<sh::ShaderVariable> fields; std::vector<sh::ShaderVariable> fields;
const int kMaxRows = 16; const int kMaxRows = 16;
...@@ -233,5 +235,5 @@ TEST(VariablePacking, Struct) ...@@ -233,5 +235,5 @@ TEST(VariablePacking, Struct)
parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 2)); parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 2));
parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 0)); parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 0));
EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars)); EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment