Commit 3891fd27 by Jamie Madill

Add a std140 padding helper class.

Using a helper class keeps our main parser stateless as we define std140 structs which need padding. The only functional change should be that we no longer use a global counter for struct padding hidden variables, but a local padding per-struct. BUG=angle:466 Change-Id: I8b92d65884b86571c8b2f052b0cba6150a4bbab0 Reviewed-on: https://chromium-review.googlesource.com/202911Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Reviewed-by: 's avatarNicolas Capens <nicolascapens@chromium.org>
parent cec3590a
...@@ -25,6 +25,119 @@ ...@@ -25,6 +25,119 @@
namespace sh namespace sh
{ {
class OutputHLSL::Std140PaddingHelper
{
public:
explicit Std140PaddingHelper(const std::map<TString, int> &structElementIndexes)
: mPaddingCounter(0),
mElementIndex(0),
mStructElementIndexes(structElementIndexes)
{}
int elementIndex() const { return mElementIndex; }
int prePadding(const TType &type)
{
if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
{
// no padding needed, HLSL will align the field to a new register
mElementIndex = 0;
return 0;
}
const GLenum glType = glVariableType(type);
const int numComponents = gl::UniformComponentCount(glType);
if (numComponents >= 4)
{
// no padding needed, HLSL will align the field to a new register
mElementIndex = 0;
return 0;
}
if (mElementIndex + numComponents > 4)
{
// no padding needed, HLSL will align the field to a new register
mElementIndex = numComponents;
return 0;
}
const int alignment = numComponents == 3 ? 4 : numComponents;
const int paddingOffset = (mElementIndex % alignment);
const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0);
mElementIndex += paddingCount;
mElementIndex += numComponents;
mElementIndex %= 4;
return paddingCount;
}
TString prePaddingString(const TType &type)
{
int paddingCount = prePadding(type);
TString padding;
for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++)
{
padding += " float pad_" + str(mPaddingCounter++) + ";\n";
}
return padding;
}
TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking)
{
if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
{
return "";
}
int numComponents = 0;
if (type.isMatrix())
{
// This method can also be called from structureString, which does not use layout qualifiers.
// Thus, use the method parameter for determining the matrix packing.
//
// Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we
// wish to always transpose GL matrices to play well with HLSL's matrix array indexing.
//
const bool isRowMajorMatrix = !useHLSLRowMajorPacking;
const GLenum glType = glVariableType(type);
numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
}
else if (type.getStruct())
{
const TString &structName = structureTypeName(*type.getStruct(), useHLSLRowMajorPacking, true);
numComponents = mStructElementIndexes.find(structName)->second;
if (numComponents == 0)
{
return "";
}
}
else
{
const GLenum glType = glVariableType(type);
numComponents = gl::UniformComponentCount(glType);
}
TString padding;
for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++)
{
padding += " float pad_" + str(mPaddingCounter++) + ";\n";
}
return padding;
}
private:
int mPaddingCounter;
int mElementIndex;
const std::map<TString, int> &mStructElementIndexes;
};
TString OutputHLSL::TextureFunction::name() const TString OutputHLSL::TextureFunction::name() const
{ {
TString name = "gl_texture"; TString name = "gl_texture";
...@@ -163,7 +276,6 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc ...@@ -163,7 +276,6 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc
mSamplerRegister = 0; mSamplerRegister = 0;
mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants
mPaddingCounter = 0;
} }
OutputHLSL::~OutputHLSL() OutputHLSL::~OutputHLSL()
...@@ -316,7 +428,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl ...@@ -316,7 +428,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl
{ {
TString hlsl; TString hlsl;
int elementIndex = 0; Std140PaddingHelper padHelper(mStd140StructElementIndexes);
for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++) for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
{ {
...@@ -326,7 +438,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl ...@@ -326,7 +438,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl
if (blockStorage == EbsStd140) if (blockStorage == EbsStd140)
{ {
// 2 and 3 component vector types in some cases need pre-padding // 2 and 3 component vector types in some cases need pre-padding
hlsl += std140PrePaddingString(fieldType, &elementIndex); hlsl += padHelper.prePaddingString(fieldType);
} }
hlsl += " " + interfaceBlockFieldTypeString(field, blockStorage) + hlsl += " " + interfaceBlockFieldTypeString(field, blockStorage) +
...@@ -336,7 +448,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl ...@@ -336,7 +448,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl
if (blockStorage == EbsStd140) if (blockStorage == EbsStd140)
{ {
const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor); const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
hlsl += std140PostPaddingString(fieldType, useHLSLRowMajorPacking); hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
} }
} }
...@@ -377,99 +489,6 @@ TString OutputHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, ...@@ -377,99 +489,6 @@ TString OutputHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock,
return hlsl; return hlsl;
} }
TString OutputHLSL::std140PrePaddingString(const TType &type, int *elementIndex)
{
if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
{
// no padding needed, HLSL will align the field to a new register
*elementIndex = 0;
return "";
}
const GLenum glType = glVariableType(type);
const int numComponents = gl::UniformComponentCount(glType);
if (numComponents >= 4)
{
// no padding needed, HLSL will align the field to a new register
*elementIndex = 0;
return "";
}
if (*elementIndex + numComponents > 4)
{
// no padding needed, HLSL will align the field to a new register
*elementIndex = numComponents;
return "";
}
TString padding;
const int alignment = numComponents == 3 ? 4 : numComponents;
const int paddingOffset = (*elementIndex % alignment);
if (paddingOffset != 0)
{
// padding is neccessary
for (int paddingIndex = paddingOffset; paddingIndex < alignment; paddingIndex++)
{
padding += " float pad_" + str(mPaddingCounter++) + ";\n";
}
*elementIndex += (alignment - paddingOffset);
}
*elementIndex += numComponents;
*elementIndex %= 4;
return padding;
}
TString OutputHLSL::std140PostPaddingString(const TType &type, bool useHLSLRowMajorPacking)
{
if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
{
return "";
}
int numComponents = 0;
if (type.isMatrix())
{
// This method can also be called from structureString, which does not use layout qualifiers.
// Thus, use the method parameter for determining the matrix packing.
//
// Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we
// wish to always transpose GL matrices to play well with HLSL's matrix array indexing.
//
const bool isRowMajorMatrix = !useHLSLRowMajorPacking;
const GLenum glType = glVariableType(type);
numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
}
else if (type.getStruct())
{
const TString &structName = structureTypeName(*type.getStruct(), useHLSLRowMajorPacking, true);
numComponents = mStd140StructElementIndexes[structName];
if (numComponents == 0)
{
return "";
}
}
else
{
const GLenum glType = glVariableType(type);
numComponents = gl::UniformComponentCount(glType);
}
TString padding;
for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++)
{
padding += " float pad_" + str(mPaddingCounter++) + ";\n";
}
return padding;
}
// Use the same layout for packed and shared // Use the same layout for packed and shared
void setBlockLayout(gl::InterfaceBlock *interfaceBlock, gl::BlockLayoutType newLayout) void setBlockLayout(gl::InterfaceBlock *interfaceBlock, gl::BlockLayoutType newLayout)
{ {
...@@ -3401,25 +3420,27 @@ TString OutputHLSL::structureString(const TStructure &structure, bool useHLSLRow ...@@ -3401,25 +3420,27 @@ TString OutputHLSL::structureString(const TStructure &structure, bool useHLSLRow
string += declareString + "\n" string += declareString + "\n"
"{\n"; "{\n";
int elementIndex = 0; Std140PaddingHelper padHelper(mStd140StructElementIndexes);
for (unsigned int i = 0; i < fields.size(); i++) for (unsigned int i = 0; i < fields.size(); i++)
{ {
const TField &field = *fields[i]; const TField &field = *fields[i];
const TType &fieldType = *field.type(); const TType &fieldType = *field.type();
const TStructure *fieldStruct = fieldType.getStruct(); const TStructure *fieldStruct = fieldType.getStruct();
const TString &fieldTypeString = fieldStruct ? structureTypeName(*fieldStruct, useHLSLRowMajorPacking, useStd140Packing) : typeString(fieldType); const TString &fieldTypeString = fieldStruct ?
structureTypeName(*fieldStruct, useHLSLRowMajorPacking, useStd140Packing) :
typeString(fieldType);
if (useStd140Packing) if (useStd140Packing)
{ {
string += std140PrePaddingString(*field.type(), &elementIndex); string += padHelper.prePaddingString(fieldType);
} }
string += " " + fieldTypeString + " " + decorateField(field.name(), structure) + arrayString(fieldType) + ";\n"; string += " " + fieldTypeString + " " + decorateField(field.name(), structure) + arrayString(fieldType) + ";\n";
if (useStd140Packing) if (useStd140Packing)
{ {
string += std140PostPaddingString(*field.type(), useHLSLRowMajorPacking); string += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
} }
} }
...@@ -3728,17 +3749,17 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI ...@@ -3728,17 +3749,17 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
void OutputHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking) void OutputHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking)
{ {
int elementIndex = 0; Std140PaddingHelper padHelper(mStd140StructElementIndexes);
const TFieldList &fields = structure.fields(); const TFieldList &fields = structure.fields();
for (unsigned int i = 0; i < fields.size(); i++) for (unsigned int i = 0; i < fields.size(); i++)
{ {
std140PrePaddingString(*fields[i]->type(), &elementIndex); padHelper.prePadding(*fields[i]->type());
} }
// Add remaining element index to the global map, for use with nested structs in standard layouts // Add remaining element index to the global map, for use with nested structs in standard layouts
const TString &structName = structureTypeName(structure, useHLSLRowMajorPacking, true); const TString &structName = structureTypeName(structure, useHLSLRowMajorPacking, true);
mStd140StructElementIndexes[structName] = elementIndex; mStd140StructElementIndexes[structName] = padHelper.elementIndex();
} }
const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
......
...@@ -42,7 +42,7 @@ class OutputHLSL : public TIntermTraverser ...@@ -42,7 +42,7 @@ class OutputHLSL : public TIntermTraverser
TString samplerString(const TType &type); TString samplerString(const TType &type);
TString interpolationString(TQualifier qualifier); TString interpolationString(TQualifier qualifier);
TString structureString(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); TString structureString(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing);
TString structureTypeName(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); static TString structureTypeName(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing);
static TString qualifierString(TQualifier qualifier); static TString qualifierString(TQualifier qualifier);
static TString arrayString(const TType &type); static TString arrayString(const TType &type);
static TString initializer(const TType &type); static TString initializer(const TType &type);
...@@ -76,7 +76,7 @@ class OutputHLSL : public TIntermTraverser ...@@ -76,7 +76,7 @@ class OutputHLSL : public TIntermTraverser
void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking); void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking);
const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
TString structNameString(const TStructure &structure); static TString structNameString(const TStructure &structure);
TParseContext &mContext; TParseContext &mContext;
const ShShaderOutput mOutputType; const ShShaderOutput mOutputType;
...@@ -174,7 +174,6 @@ class OutputHLSL : public TIntermTraverser ...@@ -174,7 +174,6 @@ class OutputHLSL : public TIntermTraverser
int mUniformRegister; int mUniformRegister;
int mInterfaceBlockRegister; int mInterfaceBlockRegister;
int mSamplerRegister; int mSamplerRegister;
int mPaddingCounter;
TString registerString(TIntermSymbol *operand); TString registerString(TIntermSymbol *operand);
int samplerRegister(TIntermSymbol *sampler); int samplerRegister(TIntermSymbol *sampler);
...@@ -195,10 +194,10 @@ class OutputHLSL : public TIntermTraverser ...@@ -195,10 +194,10 @@ class OutputHLSL : public TIntermTraverser
TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage); TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage);
TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock); TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock);
TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex); TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex);
TString std140PrePaddingString(const TType &type, int *elementIndex);
TString std140PostPaddingString(const TType &type, bool useHLSLRowMajorPacking);
TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName); TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName);
class Std140PaddingHelper;
static GLenum glVariableType(const TType &type); static GLenum glVariableType(const TType &type);
static GLenum glVariablePrecision(const TType &type); static GLenum glVariablePrecision(const TType &type);
static bool isVaryingIn(TQualifier qualifier); static bool isVaryingIn(TQualifier qualifier);
......
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