Commit d33ffb22 by Jamie Madill Committed by Commit Bot

Organize VaryingPacking methods.

This clarifies the difference between "collect" and "pack" methods. Previously the naming was overlapping between the two. Also makes the "packUserVaryings" method private. Refactoring change only. Will enable further improvements for capturing varyings with multiple shader stages. Bug: angleproject:5496 Change-Id: I854590ceab39f3a0e7a785516e0d1fd44e4ccc98 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2606529 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 92e7bc89
......@@ -203,7 +203,7 @@ void VaryingPacking::clearRegisterMap()
// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
// Returns false if unsuccessful.
bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
bool VaryingPacking::packVaryingIntoRegisterMap(const PackedVarying &packedVarying)
{
const sh::ShaderVariable &varying = packedVarying.varying();
......@@ -250,9 +250,9 @@ bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
{
for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row)
{
if (isFree(row, 0, varyingRows, varyingColumns))
if (isRegisterRangeFree(row, 0, varyingRows, varyingColumns))
{
insert(row, 0, packedVarying);
insertVaryingIntoRegisterMap(row, 0, packedVarying);
return true;
}
}
......@@ -264,9 +264,9 @@ bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
{
for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;)
{
if (isFree(r, 2, varyingRows, 2))
if (isRegisterRangeFree(r, 2, varyingRows, 2))
{
insert(r, 2, packedVarying);
insertVaryingIntoRegisterMap(r, 2, packedVarying);
return true;
}
}
......@@ -319,7 +319,7 @@ bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
{
for (unsigned int row = 0; row < maxVaryingVectors; row++)
{
if (isFree(row, bestColumn, varyingRows, 1))
if (isRegisterRangeFree(row, bestColumn, varyingRows, 1))
{
for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex)
{
......@@ -349,7 +349,7 @@ bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
return false;
}
bool VaryingPacking::isFree(unsigned int registerRow,
bool VaryingPacking::isRegisterRangeFree(unsigned int registerRow,
unsigned int registerColumn,
unsigned int varyingRows,
unsigned int varyingColumns) const
......@@ -370,7 +370,7 @@ bool VaryingPacking::isFree(unsigned int registerRow,
return true;
}
void VaryingPacking::insert(unsigned int registerRow,
void VaryingPacking::insertVaryingIntoRegisterMap(unsigned int registerRow,
unsigned int registerColumn,
const PackedVarying &packedVarying)
{
......@@ -417,7 +417,7 @@ void VaryingPacking::insert(unsigned int registerRow,
}
}
void VaryingPacking::packUserVarying(const ProgramVaryingRef &ref,
void VaryingPacking::collectUserVarying(const ProgramVaryingRef &ref,
VaryingUniqueFullNames *uniqueFullNames)
{
const sh::ShaderVariable *input = ref.frontShader;
......@@ -442,7 +442,7 @@ void VaryingPacking::packUserVarying(const ProgramVaryingRef &ref,
}
}
void VaryingPacking::packUserVaryingField(const ProgramVaryingRef &ref,
void VaryingPacking::collectUserVaryingField(const ProgramVaryingRef &ref,
GLuint arrayIndex,
GLuint fieldIndex,
GLuint secondaryFieldIndex,
......@@ -511,7 +511,7 @@ void VaryingPacking::packUserVaryingField(const ProgramVaryingRef &ref,
}
}
void VaryingPacking::packUserVaryingTF(const ProgramVaryingRef &ref, size_t subscript)
void VaryingPacking::collectUserVaryingTF(const ProgramVaryingRef &ref, size_t subscript)
{
const sh::ShaderVariable *input = ref.frontShader;
......@@ -524,7 +524,7 @@ void VaryingPacking::packUserVaryingTF(const ProgramVaryingRef &ref, size_t subs
mPackedVaryings.back().isTransformFeedback = true;
}
void VaryingPacking::packUserVaryingFieldTF(const ProgramVaryingRef &ref,
void VaryingPacking::collectUserVaryingFieldTF(const ProgramVaryingRef &ref,
const sh::ShaderVariable &field,
GLuint fieldIndex,
GLuint secondaryFieldIndex)
......@@ -557,54 +557,21 @@ void VaryingPacking::packUserVaryingFieldTF(const ProgramVaryingRef &ref,
secondaryFieldIndex == GL_INVALID_INDEX ? 0 : secondaryFieldIndex);
}
bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
const ProgramMergedVaryings &mergedVaryings,
const std::vector<std::string> &tfVaryings,
const bool isSeparableProgram)
void VaryingPacking::collectVarying(const sh::ShaderVariable &varying,
const ProgramVaryingRef &ref,
VaryingUniqueFullNames *uniqueFullNames)
{
VaryingUniqueFullNames uniqueFullNames;
reset();
for (const ProgramVaryingRef &ref : mergedVaryings)
{
const sh::ShaderVariable *input = ref.frontShader;
const sh::ShaderVariable *output = ref.backShader;
const bool isActiveBuiltInInput = input && input->isBuiltIn() && input->active;
const bool isActiveBuiltInOutput = output && output->isBuiltIn() && output->active;
// Keep track of output builtins that are used by the shader, such as gl_Position,
// gl_PointSize etc.
if (isActiveBuiltInInput)
if (varying.isStruct())
{
mActiveOutputBuiltIns[ref.frontShaderStage].push_back(input->name);
}
// Only pack statically used varyings that have a matched input or output, plus special
// builtins. Note that we pack all statically used user-defined varyings even if they are
// not active. GLES specs are a bit vague on whether it's allowed to only pack active
// varyings, though GLES 3.1 spec section 11.1.2.1 says that "device-dependent
// optimizations" may be used to make vertex shader outputs fit.
if ((input && output && output->staticUse) || isActiveBuiltInInput ||
isActiveBuiltInOutput ||
(isSeparableProgram && ((input && input->active) || (output && output->active))))
{
const sh::ShaderVariable *varying = output ? output : input;
// Don't count gl_Position. Also don't count gl_PointSize for D3D9.
if (varying->name != "gl_Position" &&
!(varying->name == "gl_PointSize" &&
mPackMode == PackMode::ANGLE_NON_CONFORMANT_D3D9))
{
if (varying->isStruct())
{
const std::vector<unsigned int> &arraySizes = varying->arraySizes;
const std::vector<unsigned int> &arraySizes = varying.arraySizes;
size_t arrayDimensions = arraySizes.size();
// Geometry shader inputs have an extra level of array-ness that should be
// removed.
if (varying == output && ref.backShaderStage == ShaderType::Geometry)
if (&varying == output && ref.backShaderStage == ShaderType::Geometry)
{
ASSERT(arrayDimensions > 0);
--arrayDimensions;
......@@ -617,77 +584,62 @@ bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
for (GLuint arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
{
const GLuint effectiveArrayIndex = isArray ? arrayIndex : GL_INVALID_INDEX;
for (GLuint fieldIndex = 0; fieldIndex < varying->fields.size();
++fieldIndex)
for (GLuint fieldIndex = 0; fieldIndex < varying.fields.size(); ++fieldIndex)
{
if (varying->fields[fieldIndex].isStruct())
if (varying.fields[fieldIndex].isStruct())
{
for (GLuint nestedIndex = 0;
nestedIndex < varying->fields[fieldIndex].fields.size();
nestedIndex++)
nestedIndex < varying.fields[fieldIndex].fields.size(); nestedIndex++)
{
packUserVaryingField(ref, effectiveArrayIndex, fieldIndex,
nestedIndex, &uniqueFullNames);
collectUserVaryingField(ref, effectiveArrayIndex, fieldIndex, nestedIndex,
uniqueFullNames);
}
}
else
{
packUserVaryingField(ref, effectiveArrayIndex, fieldIndex,
GL_INVALID_INDEX, &uniqueFullNames);
collectUserVaryingField(ref, effectiveArrayIndex, fieldIndex, GL_INVALID_INDEX,
uniqueFullNames);
}
}
}
if (input)
{
uniqueFullNames[ref.frontShaderStage].insert(input->name);
(*uniqueFullNames)[ref.frontShaderStage].insert(input->name);
if (input->isShaderIOBlock)
{
uniqueFullNames[ref.frontShaderStage].insert(input->structName);
(*uniqueFullNames)[ref.frontShaderStage].insert(input->structName);
}
}
if (output)
{
uniqueFullNames[ref.backShaderStage].insert(output->name);
(*uniqueFullNames)[ref.backShaderStage].insert(output->name);
}
}
else
{
packUserVarying(ref, &uniqueFullNames);
}
continue;
}
collectUserVarying(ref, uniqueFullNames);
}
}
// If the varying is not used in the input, we know it is inactive, unless it's a separable
// program, in which case the input shader may not exist in this program.
if (!input && !isSeparableProgram)
{
if (!output->isBuiltIn())
{
mInactiveVaryingMappedNames[ref.backShaderStage].push_back(output->mappedName);
}
continue;
}
void VaryingPacking::collectTFVarying(const std::string &tfVarying,
const ProgramVaryingRef &ref,
VaryingUniqueFullNames *uniqueFullNames)
{
const sh::ShaderVariable *input = ref.frontShader;
// Keep Transform FB varyings in the merged list always.
for (const std::string &tfVarying : tfVaryings)
{
std::vector<unsigned int> subscripts;
std::string baseName = ParseResourceName(tfVarying, &subscripts);
size_t subscript = GL_INVALID_INDEX;
if (!subscripts.empty())
{
subscript = subscripts.back();
}
// Already packed as active varying.
if (uniqueFullNames[ref.frontShaderStage].count(tfVarying) > 0 ||
uniqueFullNames[ref.frontShaderStage].count(baseName) > 0 ||
if ((*uniqueFullNames)[ref.frontShaderStage].count(tfVarying) > 0 ||
(*uniqueFullNames)[ref.frontShaderStage].count(baseName) > 0 ||
(input->isShaderIOBlock &&
uniqueFullNames[ref.frontShaderStage].count(input->structName) > 0))
(*uniqueFullNames)[ref.frontShaderStage].count(input->structName) > 0))
{
continue;
return;
}
if (input->isStruct())
{
GLuint fieldIndex = 0;
......@@ -706,49 +658,110 @@ bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
{
for (GLuint nestedIndex = 0;
nestedIndex < input->fields[fieldIndex].fields.size();
nestedIndex++)
nestedIndex < input->fields[fieldIndex].fields.size(); nestedIndex++)
{
packUserVaryingFieldTF(ref, input->fields[fieldIndex],
fieldIndex, nestedIndex);
collectUserVaryingFieldTF(ref, input->fields[fieldIndex], fieldIndex,
nestedIndex);
}
}
else
{
packUserVaryingFieldTF(ref, input->fields[fieldIndex], fieldIndex,
collectUserVaryingFieldTF(ref, input->fields[fieldIndex], fieldIndex,
GL_INVALID_INDEX);
}
}
uniqueFullNames[ref.frontShaderStage].insert(input->structName);
(*uniqueFullNames)[ref.frontShaderStage].insert(input->structName);
}
else
{
packUserVaryingFieldTF(ref, *field, fieldIndex, GL_INVALID_INDEX);
collectUserVaryingFieldTF(ref, *field, fieldIndex, GL_INVALID_INDEX);
}
uniqueFullNames[ref.frontShaderStage].insert(tfVarying);
(*uniqueFullNames)[ref.frontShaderStage].insert(tfVarying);
}
uniqueFullNames[ref.frontShaderStage].insert(input->name);
(*uniqueFullNames)[ref.frontShaderStage].insert(input->name);
}
// Array as a whole and array element conflict has already been checked in
// linkValidateTransformFeedback.
else if (baseName == input->name)
{
size_t subscript = GL_INVALID_INDEX;
if (!subscripts.empty())
{
subscript = subscripts.back();
}
// only pack varyings that are not builtins.
if (tfVarying.compare(0, 3, "gl_") != 0)
{
packUserVaryingTF(ref, subscript);
uniqueFullNames[ref.frontShaderStage].insert(tfVarying);
collectUserVaryingTF(ref, subscript);
(*uniqueFullNames)[ref.frontShaderStage].insert(tfVarying);
}
}
// Continue to match next array element for 'input' if the current match is array
// element.
if (subscript == GL_INVALID_INDEX)
}
bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
const ProgramMergedVaryings &mergedVaryings,
const std::vector<std::string> &tfVaryings,
const bool isSeparableProgram)
{
VaryingUniqueFullNames uniqueFullNames;
reset();
for (const ProgramVaryingRef &ref : mergedVaryings)
{
break;
const sh::ShaderVariable *input = ref.frontShader;
const sh::ShaderVariable *output = ref.backShader;
const bool isActiveBuiltInInput = input && input->isBuiltIn() && input->active;
const bool isActiveBuiltInOutput = output && output->isBuiltIn() && output->active;
// Keep track of output builtins that are used by the shader, such as gl_Position,
// gl_PointSize etc.
if (isActiveBuiltInInput)
{
mActiveOutputBuiltIns[ref.frontShaderStage].push_back(input->name);
}
// Only pack statically used varyings that have a matched input or output, plus special
// builtins. Note that we pack all statically used user-defined varyings even if they are
// not active. GLES specs are a bit vague on whether it's allowed to only pack active
// varyings, though GLES 3.1 spec section 11.1.2.1 says that "device-dependent
// optimizations" may be used to make vertex shader outputs fit.
if ((input && output && output->staticUse) || isActiveBuiltInInput ||
isActiveBuiltInOutput ||
(isSeparableProgram && ((input && input->active) || (output && output->active))))
{
const sh::ShaderVariable *varying = output ? output : input;
// Don't count gl_Position. Also don't count gl_PointSize for D3D9.
if (varying->name != "gl_Position" &&
!(varying->name == "gl_PointSize" &&
mPackMode == PackMode::ANGLE_NON_CONFORMANT_D3D9))
{
collectVarying(*varying, ref, &uniqueFullNames);
continue;
}
}
// If the varying is not used in the input, we know it is inactive, unless it's a separable
// program, in which case the input shader may not exist in this program.
if (!input && !isSeparableProgram)
{
if (!output->isBuiltIn())
{
mInactiveVaryingMappedNames[ref.backShaderStage].push_back(output->mappedName);
}
continue;
}
// Keep Transform FB varyings in the merged list always.
for (const std::string &tfVarying : tfVaryings)
{
collectTFVarying(tfVarying, ref, &uniqueFullNames);
}
if (input && !input->isBuiltIn() &&
uniqueFullNames[ref.frontShaderStage].count(input->name) == 0)
{
......@@ -774,7 +787,7 @@ bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog,
// subrectangle. No splitting of variables is permitted."
for (const PackedVarying &packedVarying : packedVaryings)
{
if (!packVarying(packedVarying))
if (!packVaryingIntoRegisterMap(packedVarying))
{
ShaderType eitherStage = packedVarying.frontVarying.varying
? packedVarying.frontVarying.stage
......
......@@ -207,8 +207,6 @@ class VaryingPacking final : angle::NonCopyable
void init(GLuint maxVaryingVectors, PackMode packMode);
bool packUserVaryings(gl::InfoLog &infoLog, const std::vector<PackedVarying> &packedVaryings);
bool collectAndPackUserVaryings(gl::InfoLog &infoLog,
const ProgramMergedVaryings &mergedVaryings,
const std::vector<std::string> &tfVaryings,
......@@ -246,29 +244,38 @@ class VaryingPacking final : angle::NonCopyable
void reset();
private:
bool packVarying(const PackedVarying &packedVarying);
bool isFree(unsigned int registerRow,
using VaryingUniqueFullNames = ShaderMap<std::set<std::string>>;
// Register map functions.
bool packUserVaryings(gl::InfoLog &infoLog, const std::vector<PackedVarying> &packedVaryings);
bool packVaryingIntoRegisterMap(const PackedVarying &packedVarying);
bool isRegisterRangeFree(unsigned int registerRow,
unsigned int registerColumn,
unsigned int varyingRows,
unsigned int varyingColumns) const;
void insert(unsigned int registerRow,
void insertVaryingIntoRegisterMap(unsigned int registerRow,
unsigned int registerColumn,
const PackedVarying &packedVarying);
void clearRegisterMap();
using VaryingUniqueFullNames = ShaderMap<std::set<std::string>>;
void packUserVarying(const ProgramVaryingRef &ref, VaryingUniqueFullNames *uniqueFullNames);
void packUserVaryingField(const ProgramVaryingRef &ref,
// Collection functions.
void collectUserVarying(const ProgramVaryingRef &ref, VaryingUniqueFullNames *uniqueFullNames);
void collectUserVaryingField(const ProgramVaryingRef &ref,
GLuint arrayIndex,
GLuint fieldIndex,
GLuint secondaryFieldIndex,
VaryingUniqueFullNames *uniqueFullNames);
void packUserVaryingTF(const ProgramVaryingRef &ref, size_t subscript);
void packUserVaryingFieldTF(const ProgramVaryingRef &ref,
void collectUserVaryingTF(const ProgramVaryingRef &ref, size_t subscript);
void collectUserVaryingFieldTF(const ProgramVaryingRef &ref,
const sh::ShaderVariable &field,
GLuint fieldIndex,
GLuint secondaryFieldIndex);
void clearRegisterMap();
void collectVarying(const sh::ShaderVariable &varying,
const ProgramVaryingRef &ref,
VaryingUniqueFullNames *uniqueFullNames);
void collectTFVarying(const std::string &tfVarying,
const ProgramVaryingRef &ref,
VaryingUniqueFullNames *uniqueFullNames);
std::vector<Register> mRegisterMap;
std::vector<PackedVaryingRegister> mRegisterList;
......
......@@ -29,18 +29,22 @@ class VaryingPackingTest : public ::testing::TestWithParam<GLuint>
bool testVaryingPacking(const std::vector<sh::ShaderVariable> &shVaryings,
VaryingPacking *varyingPacking)
{
std::vector<PackedVarying> packedVaryings;
ProgramMergedVaryings mergedVaryings;
for (const sh::ShaderVariable &shVarying : shVaryings)
{
packedVaryings.push_back(PackedVarying(
VaryingInShaderRef(ShaderType::Vertex, &shVarying),
VaryingInShaderRef(ShaderType::Fragment, &shVarying), shVarying.interpolation));
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;
return varyingPacking->packUserVaryings(infoLog, packedVaryings);
return varyingPacking->collectAndPackUserVaryings(infoLog, mergedVaryings,
transformFeedbackVaryings, false);
}
// Uses the "relaxed" ANGLE packing mode.
......
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