Add a GetVariableInfo helper method.
This method replaces the similar logic in storing uniforms,
varyings, and interface blocks when collecting variable info.
We can also re-use this method for both GLSL and HLSL programs.
BUG=angle:466
Change-Id: Ie6c13abe0f09f38b2f9b36e117caae4833eaccbf
Reviewed-on: https://chromium-review.googlesource.com/206566
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <capn@chromium.org>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 226d025..7d14070 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -2900,31 +2900,29 @@
return constUnion;
}
-void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector<Varying> &fieldsOut)
+class DeclareVaryingTraverser : public GetVariableTraverser<Varying>
{
- const TStructure *structure = type.getStruct();
+ public:
+ DeclareVaryingTraverser(std::vector<Varying> *output,
+ InterpolationType interpolation)
+ : GetVariableTraverser(output),
+ mInterpolation(interpolation)
+ {}
- InterpolationType interpolation = GetInterpolationType(baseTypeQualifier);
- if (!structure)
+ private:
+ void visitVariable(Varying *varying)
{
- sh::Varying varying(GLVariableType(type), GLVariablePrecision(type), name.c_str(), (unsigned int)type.getArraySize(), interpolation);
- fieldsOut.push_back(varying);
+ varying->interpolation = mInterpolation;
}
- else
- {
- sh::Varying structVarying(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), interpolation);
- const TFieldList &fields = structure->fields();
- structVarying.structName = structure->name().c_str();
+ InterpolationType mInterpolation;
+};
- for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
- {
- const TField &field = *fields[fieldIndex];
- declareVaryingToList(*field.type(), baseTypeQualifier, field.name(), structVarying.fields);
- }
-
- fieldsOut.push_back(structVarying);
- }
+void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier,
+ const TString &name, std::vector<Varying> &fieldsOut)
+{
+ DeclareVaryingTraverser traverser(&fieldsOut, GetInterpolationType(baseTypeQualifier));
+ traverser.traverse(type, name);
}
}
diff --git a/src/compiler/translator/UniformHLSL.cpp b/src/compiler/translator/UniformHLSL.cpp
index fb2208c..18c5f37 100644
--- a/src/compiler/translator/UniformHLSL.cpp
+++ b/src/compiler/translator/UniformHLSL.cpp
@@ -136,54 +136,57 @@
{
int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
- const Uniform &uniform = declareUniformToList(type, name, registerIndex, &mActiveUniforms);
+ declareUniformToList(type, name, registerIndex, &mActiveUniforms);
+
+ unsigned int registerCount = HLSLVariableRegisterCount(mActiveUniforms.back(), mOutputType);
if (IsSampler(type.getBasicType()))
{
- mSamplerRegister += HLSLVariableRegisterCount(uniform, mOutputType);
+ mSamplerRegister += registerCount;
}
else
{
- mUniformRegister += HLSLVariableRegisterCount(uniform, mOutputType);
+ mUniformRegister += registerCount;
}
return registerIndex;
}
-Uniform UniformHLSL::declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<Uniform> *output)
+class DeclareUniformsTraverser : public GetVariableTraverser<Uniform>
{
- const TStructure *structure = type.getStruct();
+ public:
+ DeclareUniformsTraverser(std::vector<Uniform> *output,
+ unsigned int registerIndex,
+ ShShaderOutput outputType)
+ : GetVariableTraverser(output),
+ mRegisterIndex(registerIndex),
+ mOutputType(outputType)
+ {}
- if (!structure)
+ private:
+ virtual void visitVariable(Uniform *uniform)
{
- Uniform uniform(GLVariableType(type), GLVariablePrecision(type), name.c_str(),
- (unsigned int)type.getArraySize(), (unsigned int)registerIndex, 0);
- output->push_back(uniform);
-
- return uniform;
- }
- else
- {
- Uniform structUniform(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(),
- (unsigned int)registerIndex, GL_INVALID_INDEX);
-
- const TFieldList &fields = structure->fields();
-
- for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+ if (!uniform->isStruct())
{
- TField *field = fields[fieldIndex];
- TType *fieldType = field->type();
-
- declareUniformToList(*fieldType, field->name(), GL_INVALID_INDEX, &structUniform.fields);
+ uniform->registerIndex = mRegisterIndex;
+ uniform->elementIndex = 0;
}
-
- // assign register offset information -- this will override the information in any sub-structures.
- HLSLVariableGetRegisterInfo(registerIndex, &structUniform, mOutputType);
-
- output->push_back(structUniform);
-
- return structUniform;
+ else
+ {
+ // Assign register offset information.
+ // This will override the offsets in any nested structures.
+ HLSLVariableGetRegisterInfo(mRegisterIndex, uniform, mOutputType);
+ }
}
+
+ unsigned int mRegisterIndex;
+ ShShaderOutput mOutputType;
+};
+
+void UniformHLSL::declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<Uniform> *output)
+{
+ DeclareUniformsTraverser traverser(output, registerIndex, mOutputType);
+ traverser.traverse(type, name);
}
TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms)
@@ -237,8 +240,11 @@
for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++)
{
const TField &field = *fieldList[typeIndex];
- const TString &fullUniformName = InterfaceBlockFieldName(interfaceBlock, field);
- declareInterfaceBlockField(*field.type(), fullUniformName, activeBlock.fields);
+ const TString &fullFieldName = InterfaceBlockFieldName(interfaceBlock, field);
+
+ bool isRowMajor = (field.type()->getLayoutQualifier().matrixPacking == EmpRowMajor);
+ GetInterfaceBlockFieldTraverser traverser(&activeBlock.fields, isRowMajor);
+ traverser.traverse(*field.type(), fullFieldName);
}
mInterfaceBlockRegister += std::max(1u, arraySize);
@@ -356,36 +362,4 @@
"};\n\n";
}
-void UniformHLSL::declareInterfaceBlockField(const TType &type, const TString &name, std::vector<InterfaceBlockField>& output)
-{
- const TStructure *structure = type.getStruct();
-
- if (!structure)
- {
- const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
- InterfaceBlockField field(GLVariableType(type), GLVariablePrecision(type), name.c_str(),
- (unsigned int)type.getArraySize(), isRowMajorMatrix);
- output.push_back(field);
- }
- else
- {
- InterfaceBlockField structField(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), false);
-
- const TFieldList &fields = structure->fields();
-
- for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
- {
- TField *field = fields[fieldIndex];
- TType *fieldType = field->type();
-
- // make sure to copy matrix packing information
- fieldType->setLayoutQualifier(type.getLayoutQualifier());
-
- declareInterfaceBlockField(*fieldType, field->name(), structField.fields);
- }
-
- output.push_back(structField);
- }
-}
-
}
diff --git a/src/compiler/translator/UniformHLSL.h b/src/compiler/translator/UniformHLSL.h
index 3060661..7de3112 100644
--- a/src/compiler/translator/UniformHLSL.h
+++ b/src/compiler/translator/UniformHLSL.h
@@ -40,8 +40,7 @@
// Returns the uniform's register index
int declareUniformAndAssignRegister(const TType &type, const TString &name);
- void declareInterfaceBlockField(const TType &type, const TString &name, std::vector<InterfaceBlockField>& output);
- Uniform declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<Uniform> *output);
+ void declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<Uniform> *output);
unsigned int mUniformRegister;
unsigned int mInterfaceBlockRegister;
diff --git a/src/compiler/translator/util.cpp b/src/compiler/translator/util.cpp
index 2b6e0ee..b9fc0b4 100644
--- a/src/compiler/translator/util.cpp
+++ b/src/compiler/translator/util.cpp
@@ -10,6 +10,7 @@
#include "compiler/preprocessor/numeric_lex.h"
#include "common/shadervars.h"
+#include "common/utilities.h"
bool atof_clamp(const char *str, float *value)
{
@@ -279,4 +280,66 @@
}
}
+template <typename VarT>
+void GetVariableTraverser<VarT>::traverse(const TType &type, const TString &name)
+{
+ const TStructure *structure = type.getStruct();
+
+ VarT variable;
+ variable.name = name.c_str();
+ variable.arraySize = static_cast<unsigned int>(type.getArraySize());
+
+ if (!structure)
+ {
+ variable.type = GLVariableType(type);
+ variable.precision = GLVariablePrecision(type);
+ }
+ else
+ {
+ variable.type = GL_STRUCT_ANGLEX;
+
+ mOutputStack.push(&variable.fields);
+
+ const TFieldList &fields = structure->fields();
+
+ for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+ {
+ TField *field = fields[fieldIndex];
+ traverse(*field->type(), field->name());
+ }
+
+ mOutputStack.pop();
+ }
+
+ visitVariable(&variable);
+
+ ASSERT(!mOutputStack.empty());
+ mOutputStack.top()->push_back(variable);
+}
+
+template <typename VarT>
+GetVariableTraverser<VarT>::GetVariableTraverser(std::vector<VarT> *output)
+{
+ ASSERT(output);
+ mOutputStack.push(output);
+}
+
+template class GetVariableTraverser<Uniform>;
+template class GetVariableTraverser<Varying>;
+template class GetVariableTraverser<InterfaceBlockField>;
+
+GetInterfaceBlockFieldTraverser::GetInterfaceBlockFieldTraverser(std::vector<InterfaceBlockField> *output, bool isRowMajorMatrix)
+ : GetVariableTraverser(output),
+ mIsRowMajorMatrix(isRowMajorMatrix)
+{
+}
+
+void GetInterfaceBlockFieldTraverser::visitVariable(InterfaceBlockField *newField)
+{
+ if (gl::IsMatrixType(newField->type))
+ {
+ newField->isRowMajorMatrix = mIsRowMajorMatrix;
+ }
+}
+
}
diff --git a/src/compiler/translator/util.h b/src/compiler/translator/util.h
index 4dbaf3c..7eac07b 100644
--- a/src/compiler/translator/util.h
+++ b/src/compiler/translator/util.h
@@ -7,6 +7,8 @@
#ifndef COMPILER_UTIL_H
#define COMPILER_UTIL_H
+#include <stack>
+
#include "compiler/translator/Types.h"
#include "angle_gl.h"
#include "common/shadervars.h"
@@ -32,6 +34,33 @@
InterpolationType GetInterpolationType(TQualifier qualifier);
TString ArrayString(const TType &type);
+template <typename VarT>
+class GetVariableTraverser
+{
+ public:
+ void traverse(const TType &type, const TString &name);
+
+ protected:
+ GetVariableTraverser(std::vector<VarT> *output);
+
+ // Must be overloaded
+ virtual void visitVariable(VarT *newVar) = 0;
+
+ private:
+ std::stack<std::vector<VarT> *> mOutputStack;
+};
+
+struct GetInterfaceBlockFieldTraverser : public GetVariableTraverser<InterfaceBlockField>
+{
+ public:
+ GetInterfaceBlockFieldTraverser(std::vector<InterfaceBlockField> *output, bool isRowMajorMatrix);
+
+ private:
+ virtual void visitVariable(InterfaceBlockField *newField);
+
+ bool mIsRowMajorMatrix;
+};
+
}
#endif // COMPILER_UTIL_H