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 @@
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 name = "gl_texture";
......@@ -163,7 +276,6 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc
mSamplerRegister = 0;
mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants
mPaddingCounter = 0;
}
OutputHLSL::~OutputHLSL()
......@@ -316,7 +428,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl
{
TString hlsl;
int elementIndex = 0;
Std140PaddingHelper padHelper(mStd140StructElementIndexes);
for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
{
......@@ -326,7 +438,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl
if (blockStorage == EbsStd140)
{
// 2 and 3 component vector types in some cases need pre-padding
hlsl += std140PrePaddingString(fieldType, &elementIndex);
hlsl += padHelper.prePaddingString(fieldType);
}
hlsl += " " + interfaceBlockFieldTypeString(field, blockStorage) +
......@@ -336,7 +448,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl
if (blockStorage == EbsStd140)
{
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,
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
void setBlockLayout(gl::InterfaceBlock *interfaceBlock, gl::BlockLayoutType newLayout)
{
......@@ -3401,25 +3420,27 @@ TString OutputHLSL::structureString(const TStructure &structure, bool useHLSLRow
string += declareString + "\n"
"{\n";
int elementIndex = 0;
Std140PaddingHelper padHelper(mStd140StructElementIndexes);
for (unsigned int i = 0; i < fields.size(); i++)
{
const TField &field = *fields[i];
const TType &fieldType = *field.type();
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)
{
string += std140PrePaddingString(*field.type(), &elementIndex);
string += padHelper.prePaddingString(fieldType);
}
string += " " + fieldTypeString + " " + decorateField(field.name(), structure) + arrayString(fieldType) + ";\n";
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
void OutputHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking)
{
int elementIndex = 0;
Std140PaddingHelper padHelper(mStd140StructElementIndexes);
const TFieldList &fields = structure.fields();
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
const TString &structName = structureTypeName(structure, useHLSLRowMajorPacking, true);
mStd140StructElementIndexes[structName] = elementIndex;
mStd140StructElementIndexes[structName] = padHelper.elementIndex();
}
const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
......
......@@ -42,7 +42,7 @@ class OutputHLSL : public TIntermTraverser
TString samplerString(const TType &type);
TString interpolationString(TQualifier qualifier);
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 arrayString(const TType &type);
static TString initializer(const TType &type);
......@@ -76,7 +76,7 @@ class OutputHLSL : public TIntermTraverser
void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking);
const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
TString structNameString(const TStructure &structure);
static TString structNameString(const TStructure &structure);
TParseContext &mContext;
const ShShaderOutput mOutputType;
......@@ -174,7 +174,6 @@ class OutputHLSL : public TIntermTraverser
int mUniformRegister;
int mInterfaceBlockRegister;
int mSamplerRegister;
int mPaddingCounter;
TString registerString(TIntermSymbol *operand);
int samplerRegister(TIntermSymbol *sampler);
......@@ -195,10 +194,10 @@ class OutputHLSL : public TIntermTraverser
TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage);
TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock);
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);
class Std140PaddingHelper;
static GLenum glVariableType(const TType &type);
static GLenum glVariablePrecision(const TType &type);
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