Refactor sh::Uniform and sh::ShaderVariable into a shader variable base type with different child types.
This change gives us better memory usage (many fields are unnecessary in different types) with better static
typing and clear type abstraction for specific methods that might take Attributes or Varyings, etc.
TRAC #23754
Signed-off-by: Nicolas Capens
Signed-off-by: Shannon Woods
diff --git a/src/compiler/BlockLayoutEncoder.cpp b/src/compiler/BlockLayoutEncoder.cpp
index ef2a0e9..a75305c 100644
--- a/src/compiler/BlockLayoutEncoder.cpp
+++ b/src/compiler/BlockLayoutEncoder.cpp
@@ -18,42 +18,42 @@
{
}
-void BlockLayoutEncoder::encodeFields(const std::vector<Uniform> &fields)
+void BlockLayoutEncoder::encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields)
{
for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
{
- const Uniform &uniform = fields[fieldIndex];
+ const InterfaceBlockField &variable = fields[fieldIndex];
- if (uniform.fields.size() > 0)
+ if (variable.fields.size() > 0)
{
- const unsigned int elementCount = std::max(1u, uniform.arraySize);
+ const unsigned int elementCount = std::max(1u, variable.arraySize);
for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
{
enterAggregateType();
- encodeFields(uniform.fields);
+ encodeInterfaceBlockFields(variable.fields);
exitAggregateType();
}
}
else
{
- encodeType(uniform);
+ encodeInterfaceBlockField(variable);
}
}
}
-void BlockLayoutEncoder::encodeType(const Uniform &uniform)
+void BlockLayoutEncoder::encodeInterfaceBlockField(const InterfaceBlockField &field)
{
int arrayStride;
int matrixStride;
- ASSERT(uniform.fields.empty());
- getBlockLayoutInfo(uniform.type, uniform.arraySize, uniform.isRowMajorMatrix, &arrayStride, &matrixStride);
+ ASSERT(field.fields.empty());
+ getBlockLayoutInfo(field.type, field.arraySize, field.isRowMajorMatrix, &arrayStride, &matrixStride);
- const BlockMemberInfo memberInfo(mCurrentOffset * ComponentSize, arrayStride * ComponentSize, matrixStride * ComponentSize, uniform.isRowMajorMatrix);
+ const BlockMemberInfo memberInfo(mCurrentOffset * ComponentSize, arrayStride * ComponentSize, matrixStride * ComponentSize, field.isRowMajorMatrix);
mBlockInfoOut->push_back(memberInfo);
- advanceOffset(uniform.type, uniform.arraySize, uniform.isRowMajorMatrix, arrayStride, matrixStride);
+ advanceOffset(field.type, field.arraySize, field.isRowMajorMatrix, arrayStride, matrixStride);
}
void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
diff --git a/src/compiler/BlockLayoutEncoder.h b/src/compiler/BlockLayoutEncoder.h
index 57a8d81..3ff1a2d 100644
--- a/src/compiler/BlockLayoutEncoder.h
+++ b/src/compiler/BlockLayoutEncoder.h
@@ -15,7 +15,8 @@
namespace sh
{
-struct Uniform;
+struct ShaderVariable;
+struct InterfaceBlockField;
struct BlockMemberInfo;
class BlockLayoutEncoder
@@ -23,8 +24,8 @@
public:
BlockLayoutEncoder(std::vector<BlockMemberInfo> *blockInfoOut);
- void encodeFields(const std::vector<Uniform> &fields);
- void encodeType(const Uniform &uniform);
+ void encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields);
+ void encodeInterfaceBlockField(const InterfaceBlockField &field);
void encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
size_t getBlockSize() { return mCurrentOffset * ComponentSize; }
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 4ec5b2b..aa32292 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -185,7 +185,7 @@
return mBody;
}
-const ActiveUniforms &OutputHLSL::getUniforms()
+const std::vector<Uniform> &OutputHLSL::getUniforms()
{
return mActiveUniforms;
}
@@ -195,12 +195,12 @@
return mActiveInterfaceBlocks;
}
-const ActiveShaderVariables &OutputHLSL::getOutputVariables() const
+const std::vector<Attribute> &OutputHLSL::getOutputVariables() const
{
return mActiveOutputVariables;
}
-const ActiveShaderVariables &OutputHLSL::getAttributes() const
+const std::vector<Attribute> &OutputHLSL::getAttributes() const
{
return mActiveAttributes;
}
@@ -444,7 +444,7 @@
case BLOCKLAYOUT_PACKED:
{
HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo);
- hlslEncoder.encodeFields(interfaceBlock->activeUniforms);
+ hlslEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
interfaceBlock->dataSize = hlslEncoder.getBlockSize();
}
break;
@@ -452,7 +452,7 @@
case BLOCKLAYOUT_STANDARD:
{
Std140BlockEncoder stdEncoder(&interfaceBlock->blockInfo);
- stdEncoder.encodeFields(interfaceBlock->activeUniforms);
+ stdEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
interfaceBlock->dataSize = stdEncoder.getBlockSize();
}
break;
@@ -559,7 +559,7 @@
{
const TField &field = *fieldList[typeIndex];
const TString &fullUniformName = interfaceBlockFieldString(interfaceBlock, field);
- declareUniformToList(*field.type(), fullUniformName, typeIndex, activeBlock.activeUniforms);
+ declareInterfaceBlockField(*field.type(), fullUniformName, activeBlock.fields);
}
mInterfaceBlockRegister += std::max(1u, arraySize);
@@ -621,9 +621,9 @@
attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
- ShaderVariable shaderVar(glVariableType(type), glVariablePrecision(type), name.c_str(),
- (unsigned int)type.getArraySize(), type.getLayoutQualifier().location);
- mActiveAttributes.push_back(shaderVar);
+ Attribute attributeVar(glVariableType(type), glVariablePrecision(type), name.c_str(),
+ (unsigned int)type.getArraySize(), type.getLayoutQualifier().location);
+ mActiveAttributes.push_back(attributeVar);
}
for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
@@ -656,8 +656,8 @@
out << "static " + typeString(variableType) + " out_" + variableName + arrayString(variableType) +
" = " + initializer(variableType) + ";\n";
- ShaderVariable outputVar(glVariableType(variableType), glVariablePrecision(variableType), variableName.c_str(),
- (unsigned int)variableType.getArraySize(), layoutQualifier.location);
+ Attribute outputVar(glVariableType(variableType), glVariablePrecision(variableType), variableName.c_str(),
+ (unsigned int)variableType.getArraySize(), layoutQualifier.location);
mActiveOutputVariables.push_back(outputVar);
}
}
@@ -3570,18 +3570,52 @@
return index;
}
-void OutputHLSL::declareUniformToList(const TType &type, const TString &name, int registerIndex, ActiveUniforms& output)
+void OutputHLSL::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);
- output.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)registerIndex, isRowMajorMatrix));
- }
+ InterfaceBlockField field(glVariableType(type), glVariablePrecision(type), name.c_str(),
+ (unsigned int)type.getArraySize(), isRowMajorMatrix);
+ output.push_back(field);
+ }
else
{
- Uniform structUniform(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)registerIndex, false);
+ InterfaceBlockField structField(GL_NONE, 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);
+ }
+}
+
+void OutputHLSL::declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<Uniform>& output)
+{
+ const TStructure *structure = type.getStruct();
+
+ if (!structure)
+ {
+ const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
+ Uniform uniform(glVariableType(type), glVariablePrecision(type), name.c_str(),
+ (unsigned int)type.getArraySize(), (unsigned int)registerIndex);
+ output.push_back(uniform);
+ }
+ else
+ {
+ Uniform structUniform(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)registerIndex);
int fieldRegister = registerIndex;
const TFieldList &fields = structure->fields();
diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h
index d258306..2d32dbc 100644
--- a/src/compiler/OutputHLSL.h
+++ b/src/compiler/OutputHLSL.h
@@ -32,10 +32,10 @@
void output();
TInfoSinkBase &getBodyStream();
- const ActiveUniforms &getUniforms();
+ const std::vector<Uniform> &getUniforms();
const ActiveInterfaceBlocks &getInterfaceBlocks() const;
- const ActiveShaderVariables &getOutputVariables() const;
- const ActiveShaderVariables &getAttributes() const;
+ const std::vector<Attribute> &getOutputVariables() const;
+ const std::vector<Attribute> &getAttributes() const;
TString typeString(const TType &type);
TString textureString(const TType &type);
@@ -176,7 +176,8 @@
TString registerString(TIntermSymbol *operand);
int samplerRegister(TIntermSymbol *sampler);
int uniformRegister(TIntermSymbol *uniform);
- void declareUniformToList(const TType &type, const TString &name, int registerIndex, ActiveUniforms& output);
+ void declareInterfaceBlockField(const TType &type, const TString &name, std::vector<InterfaceBlockField>& output);
+ void declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<Uniform>& output);
void declareUniform(const TType &type, const TString &name, int index);
TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, const TField &field);
@@ -197,10 +198,10 @@
static bool isVaryingOut(TQualifier qualifier);
static bool isVarying(TQualifier qualifier);
- ActiveUniforms mActiveUniforms;
+ std::vector<Uniform> mActiveUniforms;
ActiveInterfaceBlocks mActiveInterfaceBlocks;
- ActiveShaderVariables mActiveOutputVariables;
- ActiveShaderVariables mActiveAttributes;
+ std::vector<Attribute> mActiveOutputVariables;
+ std::vector<Attribute> mActiveAttributes;
std::map<TString, int> mStd140StructElementIndexes;
std::map<TIntermTyped*, TString> mFlaggedStructMappedNames;
std::map<TIntermTyped*, TString> mFlaggedStructOriginalNames;
diff --git a/src/compiler/TranslatorHLSL.h b/src/compiler/TranslatorHLSL.h
index e53e831..e3c4d2e 100644
--- a/src/compiler/TranslatorHLSL.h
+++ b/src/compiler/TranslatorHLSL.h
@@ -15,18 +15,18 @@
TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output);
virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; }
- const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; }
+ const std::vector<sh::Uniform> &getUniforms() { return mActiveUniforms; }
const sh::ActiveInterfaceBlocks &getInterfaceBlocks() const { return mActiveInterfaceBlocks; }
- const sh::ActiveShaderVariables &getOutputVariables() { return mActiveOutputVariables; }
- const sh::ActiveShaderVariables &getAttributes() { return mActiveAttributes; }
+ const std::vector<sh::Attribute> &getOutputVariables() { return mActiveOutputVariables; }
+ const std::vector<sh::Attribute> &getAttributes() { return mActiveAttributes; }
protected:
virtual void translate(TIntermNode* root);
- sh::ActiveUniforms mActiveUniforms;
+ std::vector<sh::Uniform> mActiveUniforms;
sh::ActiveInterfaceBlocks mActiveInterfaceBlocks;
- sh::ActiveShaderVariables mActiveOutputVariables;
- sh::ActiveShaderVariables mActiveAttributes;
+ std::vector<sh::Attribute> mActiveOutputVariables;
+ std::vector<sh::Attribute> mActiveAttributes;
ShShaderOutput mOutputType;
};
diff --git a/src/compiler/Uniform.cpp b/src/compiler/Uniform.cpp
index 6bfdef5..43a040e 100644
--- a/src/compiler/Uniform.cpp
+++ b/src/compiler/Uniform.cpp
@@ -9,31 +9,36 @@
namespace sh
{
-ShaderVariable::ShaderVariable()
- : type(GL_NONE),
- precision(GL_NONE),
- arraySize(0),
+ShaderVariable::ShaderVariable(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn)
+ : type(typeIn),
+ precision(precisionIn),
+ name(nameIn),
+ arraySize(arraySizeIn)
+{
+}
+
+Uniform::Uniform(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, unsigned int registerIndexIn)
+ : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn),
+ registerIndex(registerIndexIn)
+{
+}
+
+Attribute::Attribute()
+ : ShaderVariable(GL_NONE, GL_NONE, "", 0),
location(-1)
{
}
-ShaderVariable::ShaderVariable(GLenum type, GLenum precision, const char *name, unsigned int arraySize, int location)
- : type(type),
- precision(precision),
- name(name),
- arraySize(arraySize),
- location(location)
+Attribute::Attribute(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, int locationIn)
+ : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn),
+ location(locationIn)
{
}
-Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex, bool isRowMajorMatrix)
+InterfaceBlockField::InterfaceBlockField(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, bool isRowMajorMatrix)
+ : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn),
+ isRowMajorMatrix(isRowMajorMatrix)
{
- this->type = type;
- this->precision = precision;
- this->name = name;
- this->arraySize = arraySize;
- this->registerIndex = registerIndex;
- this->isRowMajorMatrix = isRowMajorMatrix;
}
BlockMemberInfo::BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
diff --git a/src/compiler/Uniform.h b/src/compiler/Uniform.h
index ef17697..d5275c0 100644
--- a/src/compiler/Uniform.h
+++ b/src/compiler/Uniform.h
@@ -19,34 +19,41 @@
struct ShaderVariable
{
- ShaderVariable();
- ShaderVariable(GLenum type, GLenum precision, const char *name, unsigned int arraySize, int location);
-
GLenum type;
GLenum precision;
std::string name;
unsigned int arraySize;
- int location;
+
+ ShaderVariable(GLenum type, GLenum precision, const char *name, unsigned int arraySize);
};
-typedef std::vector<ShaderVariable> ActiveShaderVariables;
-
-struct Uniform
+struct Uniform : public ShaderVariable
{
- Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex, bool isRowMajorMatrix);
-
- GLenum type;
- GLenum precision;
- std::string name;
- unsigned int arraySize;
-
unsigned int registerIndex;
- bool isRowMajorMatrix;
-
std::vector<Uniform> fields;
+
+ Uniform(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, unsigned int registerIndexIn);
+
+ bool isStruct() const { return !fields.empty(); }
};
-typedef std::vector<Uniform> ActiveUniforms;
+struct Attribute : public ShaderVariable
+{
+ int location;
+
+ Attribute();
+ Attribute(GLenum type, GLenum precision, const char *name, unsigned int arraySize, int location);
+};
+
+struct InterfaceBlockField : public ShaderVariable
+{
+ bool isRowMajorMatrix;
+ std::vector<InterfaceBlockField> fields;
+
+ InterfaceBlockField(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, bool isRowMajorMatrix);
+
+ bool isStruct() const { return !fields.empty(); }
+};
struct BlockMemberInfo
{
@@ -75,11 +82,11 @@
std::string name;
unsigned int arraySize;
- ActiveUniforms activeUniforms;
size_t dataSize;
- std::vector<BlockMemberInfo> blockInfo;
BlockLayoutType layout;
bool isRowMajorLayout;
+ std::vector<InterfaceBlockField> fields;
+ std::vector<BlockMemberInfo> blockInfo;
unsigned int registerIndex;
};