Commit 4e712be2 by Jamie Madill Committed by Commit Bot

Refactor BlockLayoutEncoder APIs for std430.

This splits HLSL SSBO access into two steps. First we compute a mapping from the collected SSBO variable names to TField pointers. Then during tree traversal we use a block encoding visitor class that uses the shader names to store BlockMemberInfo structures for the structures and variables. Each nested structure is traversed separately so that the BlockMemberInfo offsets are relative to the structure start rather than the enclosing block. The array stride for a structure is the size of the struct after all the alignment is included. This gives the correct results for the SSBO access chain in the HLSL code. It also will allow us to use the same encoding and visiting logic for SSBOs on the API side. Bug: angleproject:3024 Change-Id: I42b1db0e7547782ae77fe5f64a797f803f203f45 Reviewed-on: https://chromium-review.googlesource.com/c/1352731 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent f83a28a6
...@@ -235,7 +235,8 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, ...@@ -235,7 +235,8 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize, sh::WorkGroupSize workGroupSize,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics) PerformanceDiagnostics *perfDiagnostics,
const std::vector<InterfaceBlock> &shaderStorageBlocks)
: TIntermTraverser(true, true, true, symbolTable), : TIntermTraverser(true, true, true, symbolTable),
mShaderType(shaderType), mShaderType(shaderType),
mShaderVersion(shaderVersion), mShaderVersion(shaderVersion),
...@@ -303,7 +304,8 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, ...@@ -303,7 +304,8 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
// Reserve registers for the default uniform block and driver constants // Reserve registers for the default uniform block and driver constants
mResourcesHLSL->reserveUniformBlockRegisters(2); mResourcesHLSL->reserveUniformBlockRegisters(2);
mSSBOOutputHLSL = new ShaderStorageBlockOutputHLSL(this, symbolTable, mResourcesHLSL); mSSBOOutputHLSL =
new ShaderStorageBlockOutputHLSL(this, symbolTable, mResourcesHLSL, shaderStorageBlocks);
} }
OutputHLSL::~OutputHLSL() OutputHLSL::~OutputHLSL()
......
...@@ -47,7 +47,8 @@ class OutputHLSL : public TIntermTraverser ...@@ -47,7 +47,8 @@ class OutputHLSL : public TIntermTraverser
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize, sh::WorkGroupSize workGroupSize,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics); PerformanceDiagnostics *perfDiagnostics,
const std::vector<InterfaceBlock> &shaderStorageBlocks);
~OutputHLSL(); ~OutputHLSL();
......
...@@ -132,149 +132,160 @@ const TField *GetFieldMemberInShaderStorageBlock(const TInterfaceBlock *interfac ...@@ -132,149 +132,160 @@ const TField *GetFieldMemberInShaderStorageBlock(const TInterfaceBlock *interfac
return nullptr; return nullptr;
} }
void GetShaderStorageBlockFieldMemberInfo(const TFieldList &fields, const InterfaceBlock *FindInterfaceBlock(const TInterfaceBlock *needle,
sh::BlockLayoutEncoder *encoder, const std::vector<InterfaceBlock> &haystack)
TLayoutBlockStorage storage,
bool rowMajor,
bool isSSBOFieldMember,
BlockMemberInfoMap *blockInfoOut);
size_t GetBlockFieldMemberInfoAndReturnBlockSize(const TFieldList &fields,
TLayoutBlockStorage storage,
bool rowMajor,
BlockMemberInfoMap *blockInfoOut,
int *structureBaseAlignment)
{ {
sh::Std140BlockEncoder std140Encoder; for (const InterfaceBlock &block : haystack)
sh::Std430BlockEncoder std430Encoder;
sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
sh::BlockLayoutEncoder *structureEncoder = nullptr;
if (storage == EbsStd140)
{
structureEncoder = &std140Encoder;
}
else if (storage == EbsStd430)
{ {
structureEncoder = &std430Encoder; if (strcmp(block.name.c_str(), needle->name().data()) == 0)
{
ASSERT(block.fields.size() == needle->fields().size());
return &block;
}
} }
else
UNREACHABLE();
return nullptr;
}
std::string StripArrayIndices(const std::string &nameIn)
{
std::string name = nameIn;
size_t pos = name.find('[');
while (pos != std::string::npos)
{ {
structureEncoder = &hlslEncoder; size_t closePos = name.find(']', pos);
ASSERT(closePos != std::string::npos && closePos > pos);
name.erase(pos, closePos - pos + 1);
pos = name.find('[');
} }
ASSERT(name.find(']') == std::string::npos);
GetShaderStorageBlockFieldMemberInfo(fields, structureEncoder, storage, rowMajor, false, return name;
blockInfoOut);
structureEncoder->exitAggregateType();
*structureBaseAlignment = static_cast<int>(structureEncoder->getStructureBaseAlignment());
return structureEncoder->getBlockSize();
} }
void GetShaderStorageBlockFieldMemberInfo(const TFieldList &fields, // Does not include any array indices.
sh::BlockLayoutEncoder *encoder, void MapVariableToField(const ShaderVariable &variable,
TLayoutBlockStorage storage, const TField *field,
bool rowMajor, std::string currentName,
bool isSSBOFieldMember, ShaderVarToFieldMap *shaderVarToFieldMap)
BlockMemberInfoMap *blockInfoOut)
{ {
for (const TField *field : fields) ASSERT((field->type()->getStruct() == nullptr) == variable.fields.empty());
(*shaderVarToFieldMap)[currentName] = field;
if (!variable.fields.empty())
{ {
const TType &fieldType = *field->type(); const TStructure *subStruct = field->type()->getStruct();
bool isRowMajorLayout = rowMajor; ASSERT(variable.fields.size() == subStruct->fields().size());
if (isSSBOFieldMember)
for (size_t index = 0; index < variable.fields.size(); ++index)
{ {
isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); const TField *subField = subStruct->fields()[index];
const ShaderVariable &subVariable = variable.fields[index];
std::string subName = currentName + "." + subVariable.name;
MapVariableToField(subVariable, subField, subName, shaderVarToFieldMap);
} }
if (fieldType.getStruct()) }
}
class BlockInfoVisitor final : public BlockEncoderVisitor
{
public:
BlockInfoVisitor(const std::string &prefix,
TLayoutBlockStorage storage,
const ShaderVarToFieldMap &shaderVarToFieldMap,
BlockMemberInfoMap *blockInfoOut)
: BlockEncoderVisitor(prefix, "", getEncoder(storage)),
mShaderVarToFieldMap(shaderVarToFieldMap),
mBlockInfoOut(blockInfoOut),
mHLSLEncoder(HLSLBlockEncoder::ENCODE_PACKED, false),
mStorage(storage)
{}
BlockLayoutEncoder *getEncoder(TLayoutBlockStorage storage)
{
switch (storage)
{ {
int structureBaseAlignment = 0; case EbsStd140:
// This is to set structure member offset and array stride using a new encoder to ensure return &mStd140Encoder;
// that the first field member offset in structure is always zero. case EbsStd430:
size_t structureStride = GetBlockFieldMemberInfoAndReturnBlockSize( return &mStd430Encoder;
fieldType.getStruct()->fields(), storage, isRowMajorLayout, blockInfoOut, default:
&structureBaseAlignment); return &mHLSLEncoder;
// According to OpenGL ES 3.1 spec, session 7.6.2.2 Standard Uniform Block Layout. In
// rule 9, if the member is a structure, the base alignment of the structure is N, where
// N is the largest base alignment value of any of its members. When using the std430
// storage layout, the base alignment and stride of structures in rule 9 are not rounded
// up a multiple of the base alignment of a vec4. So we must set structure base
// alignment before enterAggregateType.
encoder->setStructureBaseAlignment(structureBaseAlignment);
encoder->enterAggregateType();
const BlockMemberInfo memberInfo(static_cast<int>(encoder->getBlockSize()),
static_cast<int>(structureStride), 0, false);
(*blockInfoOut)[field] = memberInfo;
// Below if-else is in order to get correct offset for the field members after structure
// field.
if (fieldType.isArray())
{
size_t size = fieldType.getArraySizeProduct() * structureStride;
encoder->increaseCurrentOffset(size);
}
else
{
encoder->increaseCurrentOffset(structureStride);
}
} }
else if (fieldType.isArrayOfArrays()) }
void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override
{
BlockEncoderVisitor::enterStructAccess(structVar, isRowMajor);
std::string variableName = StripArrayIndices(collapseNameStack());
// Remove the trailing "."
variableName.pop_back();
BlockInfoVisitor childVisitor(variableName, mStorage, mShaderVarToFieldMap, mBlockInfoOut);
childVisitor.getEncoder(mStorage)->enterAggregateType(structVar);
TraverseShaderVariables(structVar.fields, isRowMajor, &childVisitor);
childVisitor.getEncoder(mStorage)->exitAggregateType(structVar);
int offset = getEncoder(mStorage)->getCurrentOffset();
int arrayStride = childVisitor.getEncoder(mStorage)->getCurrentOffset();
auto iter = mShaderVarToFieldMap.find(variableName);
if (iter == mShaderVarToFieldMap.end())
return;
const TField *structField = iter->second;
if (mBlockInfoOut->count(structField) == 0)
{ {
size_t beginSize = encoder->getBlockSize(); mBlockInfoOut->emplace(structField, BlockMemberInfo(offset, arrayStride, -1, false));
const TVector<unsigned int> &arraySizes = *fieldType.getArraySizes();
// arraySizes[0] stores the innermost array's size.
std::vector<unsigned int> innermostArraySize(1u, arraySizes[0]);
const BlockMemberInfo &memberInfo =
encoder->encodeType(GLVariableType(fieldType), innermostArraySize,
isRowMajorLayout && fieldType.isMatrix());
(*blockInfoOut)[field] = memberInfo;
size_t endSize = encoder->getBlockSize();
// The total size of array of arrays is memberInfo.arrayStride *
// fieldType.getArraySizeProduct(). However, encoder->encodeType will change the current
// offset of encoder. So the final increase size will be total size of arrays of arrays
// minus the increased sized by encoder->encodeType.
size_t arrayOfArraysSize = memberInfo.arrayStride * fieldType.getArraySizeProduct();
size_t increaseSize = arrayOfArraysSize - (endSize - beginSize);
encoder->increaseCurrentOffset(increaseSize);
} }
else }
void encodeVariable(const ShaderVariable &variable,
const BlockMemberInfo &variableInfo,
const std::string &name,
const std::string &mappedName) override
{
auto iter = mShaderVarToFieldMap.find(StripArrayIndices(name));
if (iter == mShaderVarToFieldMap.end())
return;
const TField *field = iter->second;
if (mBlockInfoOut->count(field) == 0)
{ {
std::vector<unsigned int> fieldArraySizes; mBlockInfoOut->emplace(field, variableInfo);
if (auto *arraySizes = fieldType.getArraySizes())
{
fieldArraySizes.assign(arraySizes->begin(), arraySizes->end());
}
const BlockMemberInfo &memberInfo =
encoder->encodeType(GLVariableType(fieldType), fieldArraySizes,
isRowMajorLayout && fieldType.isMatrix());
(*blockInfoOut)[field] = memberInfo;
} }
} }
}
private:
const ShaderVarToFieldMap &mShaderVarToFieldMap;
BlockMemberInfoMap *mBlockInfoOut;
Std140BlockEncoder mStd140Encoder;
Std430BlockEncoder mStd430Encoder;
HLSLBlockEncoder mHLSLEncoder;
TLayoutBlockStorage mStorage;
};
void GetShaderStorageBlockMembersInfo(const TInterfaceBlock *interfaceBlock, void GetShaderStorageBlockMembersInfo(const TInterfaceBlock *interfaceBlock,
const std::vector<InterfaceBlock> &shaderStorageBlocks,
BlockMemberInfoMap *blockInfoOut) BlockMemberInfoMap *blockInfoOut)
{ {
sh::Std140BlockEncoder std140Encoder; // Find the sh::InterfaceBlock.
sh::Std430BlockEncoder std430Encoder; const InterfaceBlock *block = FindInterfaceBlock(interfaceBlock, shaderStorageBlocks);
sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false); ASSERT(block);
sh::BlockLayoutEncoder *encoder = nullptr;
if (interfaceBlock->blockStorage() == EbsStd140) // Map ShaderVariable to TField.
ShaderVarToFieldMap shaderVarToFieldMap;
for (size_t index = 0; index < block->fields.size(); ++index)
{ {
encoder = &std140Encoder; const TField *field = interfaceBlock->fields()[index];
} const ShaderVariable &variable = block->fields[index];
else if (interfaceBlock->blockStorage() == EbsStd430) MapVariableToField(variable, field, variable.name, &shaderVarToFieldMap);
{
encoder = &std430Encoder;
}
else
{
encoder = &hlslEncoder;
} }
GetShaderStorageBlockFieldMemberInfo(interfaceBlock->fields(), encoder, BlockInfoVisitor visitor("", interfaceBlock->blockStorage(), shaderVarToFieldMap, blockInfoOut);
interfaceBlock->blockStorage(), false, true, blockInfoOut); TraverseShaderVariables(block->fields, false, &visitor);
} }
bool IsInArrayOfArraysChain(TIntermTyped *node) bool IsInArrayOfArraysChain(TIntermTyped *node)
...@@ -290,18 +301,20 @@ bool IsInArrayOfArraysChain(TIntermTyped *node) ...@@ -290,18 +301,20 @@ bool IsInArrayOfArraysChain(TIntermTyped *node)
return false; return false;
} }
} // anonymous namespace } // anonymous namespace
ShaderStorageBlockOutputHLSL::ShaderStorageBlockOutputHLSL(OutputHLSL *outputHLSL, ShaderStorageBlockOutputHLSL::ShaderStorageBlockOutputHLSL(
TSymbolTable *symbolTable, OutputHLSL *outputHLSL,
ResourcesHLSL *resourcesHLSL) TSymbolTable *symbolTable,
ResourcesHLSL *resourcesHLSL,
const std::vector<InterfaceBlock> &shaderStorageBlocks)
: TIntermTraverser(true, true, true, symbolTable), : TIntermTraverser(true, true, true, symbolTable),
mMatrixStride(0), mMatrixStride(0),
mRowMajor(false), mRowMajor(false),
mLocationAsTheLastArgument(false), mLocationAsTheLastArgument(false),
mOutputHLSL(outputHLSL), mOutputHLSL(outputHLSL),
mResourcesHLSL(resourcesHLSL) mResourcesHLSL(resourcesHLSL),
mShaderStorageBlocks(shaderStorageBlocks)
{ {
mSSBOFunctionHLSL = new ShaderStorageBlockFunctionHLSL; mSSBOFunctionHLSL = new ShaderStorageBlockFunctionHLSL;
} }
...@@ -432,7 +445,7 @@ void ShaderStorageBlockOutputHLSL::writeShaderStorageBlocksHeader(TInfoSinkBase ...@@ -432,7 +445,7 @@ void ShaderStorageBlockOutputHLSL::writeShaderStorageBlocksHeader(TInfoSinkBase
mSSBOFunctionHLSL->shaderStorageBlockFunctionHeader(out); mSSBOFunctionHLSL->shaderStorageBlockFunctionHeader(out);
} }
// Check if the current node is the end of the sssbo access chain. If true, we should output ')' for // Check if the current node is the end of the SSBO access chain. If true, we should output ')' for
// Load method. // Load method.
bool ShaderStorageBlockOutputHLSL::isEndOfSSBOAccessChain() bool ShaderStorageBlockOutputHLSL::isEndOfSSBOAccessChain()
{ {
...@@ -484,7 +497,8 @@ void ShaderStorageBlockOutputHLSL::visitSymbol(TIntermSymbol *node) ...@@ -484,7 +497,8 @@ void ShaderStorageBlockOutputHLSL::visitSymbol(TIntermSymbol *node)
} }
mReferencedShaderStorageBlocks[interfaceBlock->uniqueId().get()] = mReferencedShaderStorageBlocks[interfaceBlock->uniqueId().get()] =
new TReferencedBlock(interfaceBlock, instanceVariable); new TReferencedBlock(interfaceBlock, instanceVariable);
GetShaderStorageBlockMembersInfo(interfaceBlock, &mBlockMemberInfoMap); GetShaderStorageBlockMembersInfo(interfaceBlock, mShaderStorageBlocks,
&mBlockMemberInfoMap);
} }
if (variableType.isInterfaceBlock()) if (variableType.isInterfaceBlock())
{ {
...@@ -572,7 +586,8 @@ bool ShaderStorageBlockOutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -572,7 +586,8 @@ bool ShaderStorageBlockOutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
{ {
mReferencedShaderStorageBlocks[interfaceBlock->uniqueId().get()] = mReferencedShaderStorageBlocks[interfaceBlock->uniqueId().get()] =
new TReferencedBlock(interfaceBlock, &instanceArraySymbol->variable()); new TReferencedBlock(interfaceBlock, &instanceArraySymbol->variable());
GetShaderStorageBlockMembersInfo(interfaceBlock, &mBlockMemberInfoMap); GetShaderStorageBlockMembersInfo(interfaceBlock, mShaderStorageBlocks,
&mBlockMemberInfoMap);
} }
const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0); const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
......
...@@ -34,12 +34,15 @@ using ReferencedInterfaceBlocks = std::map<int, const TReferencedBlock *>; ...@@ -34,12 +34,15 @@ using ReferencedInterfaceBlocks = std::map<int, const TReferencedBlock *>;
// Used to save shader storage block field member information. // Used to save shader storage block field member information.
using BlockMemberInfoMap = std::map<const TField *, BlockMemberInfo>; using BlockMemberInfoMap = std::map<const TField *, BlockMemberInfo>;
using ShaderVarToFieldMap = std::map<std::string, const TField *>;
class ShaderStorageBlockOutputHLSL : public TIntermTraverser class ShaderStorageBlockOutputHLSL : public TIntermTraverser
{ {
public: public:
ShaderStorageBlockOutputHLSL(OutputHLSL *outputHLSL, ShaderStorageBlockOutputHLSL(OutputHLSL *outputHLSL,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
ResourcesHLSL *resourcesHLSL); ResourcesHLSL *resourcesHLSL,
const std::vector<InterfaceBlock> &shaderStorageBlocks);
~ShaderStorageBlockOutputHLSL(); ~ShaderStorageBlockOutputHLSL();
...@@ -82,6 +85,7 @@ class ShaderStorageBlockOutputHLSL : public TIntermTraverser ...@@ -82,6 +85,7 @@ class ShaderStorageBlockOutputHLSL : public TIntermTraverser
ReferencedInterfaceBlocks mReferencedShaderStorageBlocks; ReferencedInterfaceBlocks mReferencedShaderStorageBlocks;
BlockMemberInfoMap mBlockMemberInfoMap; BlockMemberInfoMap mBlockMemberInfoMap;
const std::vector<InterfaceBlock> &mShaderStorageBlocks;
}; };
} // namespace sh } // namespace sh
......
...@@ -138,7 +138,7 @@ void TranslatorHLSL::translate(TIntermBlock *root, ...@@ -138,7 +138,7 @@ void TranslatorHLSL::translate(TIntermBlock *root,
sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(), sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), getSourcePath(), getOutputType(), numRenderTargets, getUniforms(),
compileOptions, getComputeShaderLocalSize(), &getSymbolTable(), compileOptions, getComputeShaderLocalSize(), &getSymbolTable(),
perfDiagnostics); perfDiagnostics, mShaderStorageBlocks);
outputHLSL.output(root, getInfoSink().obj); outputHLSL.output(root, getInfoSink().obj);
......
...@@ -46,10 +46,6 @@ void GetInterfaceBlockInfo(const std::vector<VarT> &fields, ...@@ -46,10 +46,6 @@ void GetInterfaceBlockInfo(const std::vector<VarT> &fields,
bool inRowMajorLayout, bool inRowMajorLayout,
BlockLayoutMap *blockInfoOut) BlockLayoutMap *blockInfoOut)
{ {
// TODO(jiajia.qin@intel.com):we need to set the right structure base alignment before
// enterAggregateType for std430 layout just like GetShaderStorageBlockFieldMemberInfo did in
// ShaderStorageBlockOutputHLSL.cpp. http://anglebug.com/1920
BlockLayoutMapVisitor visitor(blockInfoOut, prefix, encoder); BlockLayoutMapVisitor visitor(blockInfoOut, prefix, encoder);
TraverseShaderVariables(fields, inRowMajorLayout, &visitor); TraverseShaderVariables(fields, inRowMajorLayout, &visitor);
} }
...@@ -60,13 +56,12 @@ void TraverseStructVariable(const ShaderVariable &variable, ...@@ -60,13 +56,12 @@ void TraverseStructVariable(const ShaderVariable &variable,
{ {
const std::vector<ShaderVariable> &fields = variable.fields; const std::vector<ShaderVariable> &fields = variable.fields;
visitor->enterStructAccess(variable); visitor->enterStructAccess(variable, isRowMajorLayout);
TraverseShaderVariables(fields, isRowMajorLayout, visitor); TraverseShaderVariables(fields, isRowMajorLayout, visitor);
visitor->exitStructAccess(variable); visitor->exitStructAccess(variable, isRowMajorLayout);
} }
void TraverseStructArrayVariable(const ShaderVariable &variable, void TraverseStructArrayVariable(const ShaderVariable &variable,
unsigned int arrayNestingIndex,
bool inRowMajorLayout, bool inRowMajorLayout,
ShaderVariableVisitor *visitor) ShaderVariableVisitor *visitor)
{ {
...@@ -74,7 +69,7 @@ void TraverseStructArrayVariable(const ShaderVariable &variable, ...@@ -74,7 +69,7 @@ void TraverseStructArrayVariable(const ShaderVariable &variable,
// Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
// innermost. We make a special case for unsized arrays. // innermost. We make a special case for unsized arrays.
const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex); const unsigned int currentArraySize = variable.getNestedArraySize(0);
unsigned int count = std::max(currentArraySize, 1u); unsigned int count = std::max(currentArraySize, 1u);
for (unsigned int arrayElement = 0u; arrayElement < count; ++arrayElement) for (unsigned int arrayElement = 0u; arrayElement < count; ++arrayElement)
{ {
...@@ -83,9 +78,9 @@ void TraverseStructArrayVariable(const ShaderVariable &variable, ...@@ -83,9 +78,9 @@ void TraverseStructArrayVariable(const ShaderVariable &variable,
ShaderVariable elementVar = variable; ShaderVariable elementVar = variable;
elementVar.indexIntoArray(arrayElement); elementVar.indexIntoArray(arrayElement);
if (arrayNestingIndex + 1u < variable.arraySizes.size()) if (variable.arraySizes.size() > 1u)
{ {
TraverseStructArrayVariable(elementVar, arrayNestingIndex, inRowMajorLayout, visitor); TraverseStructArrayVariable(elementVar, inRowMajorLayout, visitor);
} }
else else
{ {
...@@ -145,9 +140,34 @@ std::string CollapseNameStack(const std::vector<std::string> &nameStack) ...@@ -145,9 +140,34 @@ std::string CollapseNameStack(const std::vector<std::string> &nameStack)
} }
return strstr.str(); return strstr.str();
} }
size_t GetStd430BaseAlignment(GLenum variableType, bool isRowMajor)
{
GLenum flippedType = isRowMajor ? variableType : gl::TransposeMatrixType(variableType);
size_t numComponents = static_cast<size_t>(gl::VariableColumnCount(flippedType));
return ComponentAlignment(numComponents);
}
class BaseAlignmentVisitor : public ShaderVariableVisitor
{
public:
BaseAlignmentVisitor() = default;
void visitVariable(const ShaderVariable &variable, bool isRowMajor) override
{
size_t baseAlignment = GetStd430BaseAlignment(variable.type, isRowMajor);
mCurrentAlignment = std::max(mCurrentAlignment, baseAlignment);
}
// This is in components rather than bytes.
size_t getBaseAlignment() const { return mCurrentAlignment; }
private:
size_t mCurrentAlignment = 0;
};
} // anonymous namespace } // anonymous namespace
BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0), mStructureBaseAlignment(0) {} // BlockLayoutEncoder implementation.
BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) {}
BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
const std::vector<unsigned int> &arraySizes, const std::vector<unsigned int> &arraySizes,
...@@ -168,16 +188,6 @@ BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, ...@@ -168,16 +188,6 @@ BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
return memberInfo; return memberInfo;
} }
void BlockLayoutEncoder::increaseCurrentOffset(size_t offsetInBytes)
{
mCurrentOffset += (offsetInBytes / kBytesPerComponent);
}
void BlockLayoutEncoder::setStructureBaseAlignment(size_t baseAlignment)
{
mStructureBaseAlignment = baseAlignment;
}
// static // static
size_t BlockLayoutEncoder::GetBlockRegister(const BlockMemberInfo &info) size_t BlockLayoutEncoder::GetBlockRegister(const BlockMemberInfo &info)
{ {
...@@ -190,21 +200,22 @@ size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info) ...@@ -190,21 +200,22 @@ size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info)
return (info.offset / kBytesPerComponent) % kComponentsPerRegister; return (info.offset / kBytesPerComponent) % kComponentsPerRegister;
} }
void BlockLayoutEncoder::nextRegister() void BlockLayoutEncoder::align(size_t baseAlignment)
{ {
mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, kComponentsPerRegister); mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, baseAlignment);
} }
// Std140BlockEncoder implementation.
Std140BlockEncoder::Std140BlockEncoder() {} Std140BlockEncoder::Std140BlockEncoder() {}
void Std140BlockEncoder::enterAggregateType() void Std140BlockEncoder::enterAggregateType(const ShaderVariable &structVar)
{ {
nextRegister(); align(getBaseAlignment(structVar));
} }
void Std140BlockEncoder::exitAggregateType() void Std140BlockEncoder::exitAggregateType(const ShaderVariable &structVar)
{ {
nextRegister(); align(getBaseAlignment(structVar));
} }
void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
...@@ -222,24 +233,24 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, ...@@ -222,24 +233,24 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
if (gl::IsMatrixType(type)) if (gl::IsMatrixType(type))
{ {
baseAlignment = kComponentsPerRegister; baseAlignment = getTypeBaseAlignment(type, isRowMajorMatrix);
matrixStride = kComponentsPerRegister; matrixStride = getTypeBaseAlignment(type, isRowMajorMatrix);
if (!arraySizes.empty()) if (!arraySizes.empty())
{ {
const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
arrayStride = kComponentsPerRegister * numRegisters; arrayStride = getTypeBaseAlignment(type, isRowMajorMatrix) * numRegisters;
} }
} }
else if (!arraySizes.empty()) else if (!arraySizes.empty())
{ {
baseAlignment = kComponentsPerRegister; baseAlignment = getTypeBaseAlignment(type, false);
arrayStride = kComponentsPerRegister; arrayStride = getTypeBaseAlignment(type, false);
} }
else else
{ {
const int numComponents = gl::VariableComponentCount(type); const size_t numComponents = static_cast<size_t>(gl::VariableComponentCount(type));
baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents)); baseAlignment = ComponentAlignment(numComponents);
} }
mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
...@@ -269,52 +280,24 @@ void Std140BlockEncoder::advanceOffset(GLenum type, ...@@ -269,52 +280,24 @@ void Std140BlockEncoder::advanceOffset(GLenum type,
} }
} }
// Std430BlockEncoder implementation.
Std430BlockEncoder::Std430BlockEncoder() {} Std430BlockEncoder::Std430BlockEncoder() {}
void Std430BlockEncoder::nextRegister() size_t Std430BlockEncoder::getBaseAlignment(const ShaderVariable &shaderVar) const
{ {
mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, mStructureBaseAlignment); if (shaderVar.isStruct())
}
void Std430BlockEncoder::getBlockLayoutInfo(GLenum type,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int *arrayStrideOut,
int *matrixStrideOut)
{
// We assume we are only dealing with 4 byte components (no doubles or half-words currently)
ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == kBytesPerComponent);
size_t baseAlignment = 0;
int matrixStride = 0;
int arrayStride = 0;
if (gl::IsMatrixType(type))
{ {
const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix); BaseAlignmentVisitor visitor;
baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents)); TraverseShaderVariables(shaderVar.fields, false, &visitor);
matrixStride = baseAlignment; return visitor.getBaseAlignment();
if (!arraySizes.empty())
{
const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
arrayStride = matrixStride * numRegisters;
}
}
else
{
const int numComponents = gl::VariableComponentCount(type);
baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
if (!arraySizes.empty())
{
arrayStride = baseAlignment;
}
} }
mStructureBaseAlignment = std::max(baseAlignment, mStructureBaseAlignment);
mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
*matrixStrideOut = matrixStride; return GetStd430BaseAlignment(shaderVar.type, shaderVar.isRowMajorLayout);
*arrayStrideOut = arrayStride; }
size_t Std430BlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const
{
return GetStd430BaseAlignment(type, isRowMajorMatrix);
} }
void GetInterfaceBlockInfo(const std::vector<InterfaceBlockField> &fields, void GetInterfaceBlockInfo(const std::vector<InterfaceBlockField> &fields,
...@@ -366,13 +349,13 @@ void VariableNameVisitor::exitStruct(const ShaderVariable &structVar) ...@@ -366,13 +349,13 @@ void VariableNameVisitor::exitStruct(const ShaderVariable &structVar)
mMappedNameStack.pop_back(); mMappedNameStack.pop_back();
} }
void VariableNameVisitor::enterStructAccess(const ShaderVariable &structVar) void VariableNameVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor)
{ {
mNameStack.push_back("."); mNameStack.push_back(".");
mMappedNameStack.push_back("."); mMappedNameStack.push_back(".");
} }
void VariableNameVisitor::exitStructAccess(const ShaderVariable &structVar) void VariableNameVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor)
{ {
mNameStack.pop_back(); mNameStack.pop_back();
mMappedNameStack.pop_back(); mMappedNameStack.pop_back();
...@@ -380,7 +363,7 @@ void VariableNameVisitor::exitStructAccess(const ShaderVariable &structVar) ...@@ -380,7 +363,7 @@ void VariableNameVisitor::exitStructAccess(const ShaderVariable &structVar)
void VariableNameVisitor::enterArray(const ShaderVariable &arrayVar) void VariableNameVisitor::enterArray(const ShaderVariable &arrayVar)
{ {
if (!arrayVar.hasParentArrayIndex()) if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct())
{ {
mNameStack.push_back(arrayVar.name); mNameStack.push_back(arrayVar.name);
mMappedNameStack.push_back(arrayVar.mappedName); mMappedNameStack.push_back(arrayVar.mappedName);
...@@ -389,7 +372,7 @@ void VariableNameVisitor::enterArray(const ShaderVariable &arrayVar) ...@@ -389,7 +372,7 @@ void VariableNameVisitor::enterArray(const ShaderVariable &arrayVar)
void VariableNameVisitor::exitArray(const ShaderVariable &arrayVar) void VariableNameVisitor::exitArray(const ShaderVariable &arrayVar)
{ {
if (!arrayVar.hasParentArrayIndex()) if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct())
{ {
mNameStack.pop_back(); mNameStack.pop_back();
mMappedNameStack.pop_back(); mMappedNameStack.pop_back();
...@@ -465,16 +448,16 @@ BlockEncoderVisitor::BlockEncoderVisitor(const std::string &namePrefix, ...@@ -465,16 +448,16 @@ BlockEncoderVisitor::BlockEncoderVisitor(const std::string &namePrefix,
BlockEncoderVisitor::~BlockEncoderVisitor() = default; BlockEncoderVisitor::~BlockEncoderVisitor() = default;
void BlockEncoderVisitor::enterStructAccess(const ShaderVariable &structVar) void BlockEncoderVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor)
{ {
VariableNameVisitor::enterStructAccess(structVar); VariableNameVisitor::enterStructAccess(structVar, isRowMajor);
mEncoder->enterAggregateType(); mEncoder->enterAggregateType(structVar);
} }
void BlockEncoderVisitor::exitStructAccess(const ShaderVariable &structVar) void BlockEncoderVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor)
{ {
mEncoder->exitAggregateType(); mEncoder->exitAggregateType(structVar);
VariableNameVisitor::exitStructAccess(structVar); VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
} }
void BlockEncoderVisitor::visitNamedVariable(const ShaderVariable &variable, void BlockEncoderVisitor::visitNamedVariable(const ShaderVariable &variable,
...@@ -502,16 +485,16 @@ void TraverseShaderVariable(const ShaderVariable &variable, ...@@ -502,16 +485,16 @@ void TraverseShaderVariable(const ShaderVariable &variable,
if (variable.isStruct()) if (variable.isStruct())
{ {
visitor->enterStruct(variable);
if (variable.isArray()) if (variable.isArray())
{ {
TraverseStructArrayVariable(variable, 0u, rowMajorLayout, visitor); TraverseStructArrayVariable(variable, rowMajorLayout, visitor);
} }
else else
{ {
visitor->enterStruct(variable);
TraverseStructVariable(variable, rowMajorLayout, visitor); TraverseStructVariable(variable, rowMajorLayout, visitor);
visitor->exitStruct(variable);
} }
visitor->exitStruct(variable);
} }
else if (variable.isArrayOfArrays()) else if (variable.isArrayOfArrays())
{ {
......
...@@ -66,6 +66,11 @@ struct BlockMemberInfo ...@@ -66,6 +66,11 @@ struct BlockMemberInfo
int topLevelArrayStride = -1; int topLevelArrayStride = -1;
}; };
constexpr size_t ComponentAlignment(size_t numComponents)
{
return (numComponents == 3u ? 4u : numComponents);
}
constexpr BlockMemberInfo kDefaultBlockMemberInfo; constexpr BlockMemberInfo kDefaultBlockMemberInfo;
class BlockLayoutEncoder class BlockLayoutEncoder
...@@ -78,13 +83,11 @@ class BlockLayoutEncoder ...@@ -78,13 +83,11 @@ class BlockLayoutEncoder
const std::vector<unsigned int> &arraySizes, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix); bool isRowMajorMatrix);
size_t getBlockSize() const { return mCurrentOffset * kBytesPerComponent; } size_t getCurrentOffset() const { return mCurrentOffset * kBytesPerComponent; }
size_t getStructureBaseAlignment() const { return mStructureBaseAlignment; }
void increaseCurrentOffset(size_t offsetInBytes);
void setStructureBaseAlignment(size_t baseAlignment);
virtual void enterAggregateType() = 0; // Called when entering/exiting a structure variable.
virtual void exitAggregateType() = 0; virtual void enterAggregateType(const ShaderVariable &structVar) = 0;
virtual void exitAggregateType(const ShaderVariable &structVar) = 0;
static constexpr size_t kBytesPerComponent = 4u; static constexpr size_t kBytesPerComponent = 4u;
static constexpr unsigned int kComponentsPerRegister = 4u; static constexpr unsigned int kComponentsPerRegister = 4u;
...@@ -93,10 +96,7 @@ class BlockLayoutEncoder ...@@ -93,10 +96,7 @@ class BlockLayoutEncoder
static size_t GetBlockRegisterElement(const BlockMemberInfo &info); static size_t GetBlockRegisterElement(const BlockMemberInfo &info);
protected: protected:
size_t mCurrentOffset; void align(size_t baseAlignment);
size_t mStructureBaseAlignment;
virtual void nextRegister();
virtual void getBlockLayoutInfo(GLenum type, virtual void getBlockLayoutInfo(GLenum type,
const std::vector<unsigned int> &arraySizes, const std::vector<unsigned int> &arraySizes,
...@@ -108,6 +108,8 @@ class BlockLayoutEncoder ...@@ -108,6 +108,8 @@ class BlockLayoutEncoder
bool isRowMajorMatrix, bool isRowMajorMatrix,
int arrayStride, int arrayStride,
int matrixStride) = 0; int matrixStride) = 0;
size_t mCurrentOffset;
}; };
// Will return default values for everything. // Will return default values for everything.
...@@ -116,8 +118,8 @@ class DummyBlockEncoder : public BlockLayoutEncoder ...@@ -116,8 +118,8 @@ class DummyBlockEncoder : public BlockLayoutEncoder
public: public:
DummyBlockEncoder() = default; DummyBlockEncoder() = default;
void enterAggregateType() override {} void enterAggregateType(const ShaderVariable &structVar) override {}
void exitAggregateType() override {} void exitAggregateType(const ShaderVariable &structVar) override {}
protected: protected:
void getBlockLayoutInfo(GLenum type, void getBlockLayoutInfo(GLenum type,
...@@ -146,8 +148,8 @@ class Std140BlockEncoder : public BlockLayoutEncoder ...@@ -146,8 +148,8 @@ class Std140BlockEncoder : public BlockLayoutEncoder
public: public:
Std140BlockEncoder(); Std140BlockEncoder();
void enterAggregateType() override; void enterAggregateType(const ShaderVariable &structVar) override;
void exitAggregateType() override; void exitAggregateType(const ShaderVariable &structVar) override;
protected: protected:
void getBlockLayoutInfo(GLenum type, void getBlockLayoutInfo(GLenum type,
...@@ -160,6 +162,16 @@ class Std140BlockEncoder : public BlockLayoutEncoder ...@@ -160,6 +162,16 @@ class Std140BlockEncoder : public BlockLayoutEncoder
bool isRowMajorMatrix, bool isRowMajorMatrix,
int arrayStride, int arrayStride,
int matrixStride) override; int matrixStride) override;
virtual size_t getBaseAlignment(const ShaderVariable &variable) const
{
return kComponentsPerRegister;
}
virtual size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const
{
return kComponentsPerRegister;
}
}; };
class Std430BlockEncoder : public Std140BlockEncoder class Std430BlockEncoder : public Std140BlockEncoder
...@@ -168,12 +180,8 @@ class Std430BlockEncoder : public Std140BlockEncoder ...@@ -168,12 +180,8 @@ class Std430BlockEncoder : public Std140BlockEncoder
Std430BlockEncoder(); Std430BlockEncoder();
protected: protected:
void nextRegister() override; size_t getBaseAlignment(const ShaderVariable &variable) const override;
void getBlockLayoutInfo(GLenum type, size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const override;
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int *arrayStrideOut,
int *matrixStrideOut) override;
}; };
using BlockLayoutMap = std::map<std::string, BlockMemberInfo>; using BlockLayoutMap = std::map<std::string, BlockMemberInfo>;
...@@ -197,8 +205,8 @@ class ShaderVariableVisitor ...@@ -197,8 +205,8 @@ class ShaderVariableVisitor
virtual void enterStruct(const ShaderVariable &structVar) {} virtual void enterStruct(const ShaderVariable &structVar) {}
virtual void exitStruct(const ShaderVariable &structVar) {} virtual void exitStruct(const ShaderVariable &structVar) {}
virtual void enterStructAccess(const ShaderVariable &structVar) {} virtual void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) {}
virtual void exitStructAccess(const ShaderVariable &structVar) {} virtual void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) {}
virtual void enterArray(const ShaderVariable &arrayVar) {} virtual void enterArray(const ShaderVariable &arrayVar) {}
virtual void exitArray(const ShaderVariable &arrayVar) {} virtual void exitArray(const ShaderVariable &arrayVar) {}
...@@ -222,8 +230,8 @@ class VariableNameVisitor : public ShaderVariableVisitor ...@@ -222,8 +230,8 @@ class VariableNameVisitor : public ShaderVariableVisitor
void enterStruct(const ShaderVariable &structVar) override; void enterStruct(const ShaderVariable &structVar) override;
void exitStruct(const ShaderVariable &structVar) override; void exitStruct(const ShaderVariable &structVar) override;
void enterStructAccess(const ShaderVariable &structVar) override; void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
void exitStructAccess(const ShaderVariable &structVar) override; void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
void enterArray(const ShaderVariable &arrayVar) override; void enterArray(const ShaderVariable &arrayVar) override;
void exitArray(const ShaderVariable &arrayVar) override; void exitArray(const ShaderVariable &arrayVar) override;
void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override; void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
...@@ -243,11 +251,12 @@ class VariableNameVisitor : public ShaderVariableVisitor ...@@ -243,11 +251,12 @@ class VariableNameVisitor : public ShaderVariableVisitor
const std::string &name, const std::string &name,
const std::string &mappedName) = 0; const std::string &mappedName) = 0;
std::string collapseNameStack() const;
std::string collapseMappedNameStack() const;
private: private:
void visitSampler(const sh::ShaderVariable &sampler) final; void visitSampler(const sh::ShaderVariable &sampler) final;
void visitVariable(const ShaderVariable &variable, bool isRowMajor) final; void visitVariable(const ShaderVariable &variable, bool isRowMajor) final;
std::string collapseNameStack() const;
std::string collapseMappedNameStack() const;
std::vector<std::string> mNameStack; std::vector<std::string> mNameStack;
std::vector<std::string> mMappedNameStack; std::vector<std::string> mMappedNameStack;
...@@ -261,8 +270,8 @@ class BlockEncoderVisitor : public VariableNameVisitor ...@@ -261,8 +270,8 @@ class BlockEncoderVisitor : public VariableNameVisitor
BlockLayoutEncoder *encoder); BlockLayoutEncoder *encoder);
~BlockEncoderVisitor(); ~BlockEncoderVisitor();
void enterStructAccess(const ShaderVariable &structVar) override; void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
void exitStructAccess(const ShaderVariable &structVar) override; void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
void visitNamedVariable(const ShaderVariable &variable, void visitNamedVariable(const ShaderVariable &variable,
bool isRowMajor, bool isRowMajor,
......
...@@ -19,12 +19,12 @@ HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool trans ...@@ -19,12 +19,12 @@ HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool trans
: mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices) : mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices)
{} {}
void HLSLBlockEncoder::enterAggregateType() void HLSLBlockEncoder::enterAggregateType(const ShaderVariable &structVar)
{ {
nextRegister(); align(kComponentsPerRegister);
} }
void HLSLBlockEncoder::exitAggregateType() {} void HLSLBlockEncoder::exitAggregateType(const ShaderVariable &structVar) {}
void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
const std::vector<unsigned int> &arraySizes, const std::vector<unsigned int> &arraySizes,
...@@ -45,7 +45,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, ...@@ -45,7 +45,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
// register // register
if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty()) if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty())
{ {
nextRegister(); align(kComponentsPerRegister);
} }
if (gl::IsMatrixType(type)) if (gl::IsMatrixType(type))
...@@ -67,7 +67,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, ...@@ -67,7 +67,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
int numComponents = gl::VariableComponentCount(type); int numComponents = gl::VariableComponentCount(type);
if ((numComponents + (mCurrentOffset % kComponentsPerRegister)) > kComponentsPerRegister) if ((numComponents + (mCurrentOffset % kComponentsPerRegister)) > kComponentsPerRegister)
{ {
nextRegister(); align(kComponentsPerRegister);
} }
} }
...@@ -134,14 +134,14 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder * ...@@ -134,14 +134,14 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
{ {
for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++) for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++)
{ {
encoder->enterAggregateType(); encoder->enterAggregateType(variable);
for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++) for (const ShaderVariable &field : variable.fields)
{ {
HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder); HLSLVariableRegisterCount(field, encoder);
} }
encoder->exitAggregateType(); encoder->exitAggregateType(variable);
} }
} }
else else
...@@ -157,7 +157,7 @@ unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput o ...@@ -157,7 +157,7 @@ unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput o
HLSLVariableRegisterCount(variable, &encoder); HLSLVariableRegisterCount(variable, &encoder);
const size_t registerBytes = (encoder.kBytesPerComponent * encoder.kComponentsPerRegister); const size_t registerBytes = (encoder.kBytesPerComponent * encoder.kComponentsPerRegister);
return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / return static_cast<unsigned int>(
registerBytes); rx::roundUp<size_t>(encoder.getCurrentOffset(), registerBytes) / registerBytes);
} }
} // namespace sh } // namespace sh
...@@ -35,8 +35,8 @@ class HLSLBlockEncoder : public BlockLayoutEncoder ...@@ -35,8 +35,8 @@ class HLSLBlockEncoder : public BlockLayoutEncoder
HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices); HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices);
void enterAggregateType() override; void enterAggregateType(const ShaderVariable &structVar) override;
void exitAggregateType() override; void exitAggregateType(const ShaderVariable &structVar) override;
void skipRegisters(unsigned int numRegisters); void skipRegisters(unsigned int numRegisters);
bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
......
...@@ -350,16 +350,16 @@ class ShaderStorageBlockVisitor : public sh::VariableNameVisitor ...@@ -350,16 +350,16 @@ class ShaderStorageBlockVisitor : public sh::VariableNameVisitor
sh::VariableNameVisitor::exitArrayElement(arrayVar, arrayElement); sh::VariableNameVisitor::exitArrayElement(arrayVar, arrayElement);
} }
void enterStructAccess(const sh::ShaderVariable &structVar) override void enterStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
{ {
mStructStackSize++; mStructStackSize++;
sh::VariableNameVisitor::enterStructAccess(structVar); sh::VariableNameVisitor::enterStructAccess(structVar, isRowMajor);
} }
void exitStructAccess(const sh::ShaderVariable &structVar) override void exitStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
{ {
mStructStackSize--; mStructStackSize--;
sh::VariableNameVisitor::exitStructAccess(structVar); sh::VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
} }
void visitNamedVariable(const sh::ShaderVariable &variable, void visitNamedVariable(const sh::ShaderVariable &variable,
...@@ -560,16 +560,16 @@ class FlattenUniformVisitor : public sh::VariableNameVisitor ...@@ -560,16 +560,16 @@ class FlattenUniformVisitor : public sh::VariableNameVisitor
} }
} }
void enterStructAccess(const sh::ShaderVariable &structVar) override void enterStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
{ {
mStructStackSize++; mStructStackSize++;
sh::VariableNameVisitor::enterStructAccess(structVar); sh::VariableNameVisitor::enterStructAccess(structVar, isRowMajor);
} }
void exitStructAccess(const sh::ShaderVariable &structVar) override void exitStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
{ {
mStructStackSize--; mStructStackSize--;
sh::VariableNameVisitor::exitStructAccess(structVar); sh::VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
} }
ShaderUniformCount getCounts() const { return mUniformCount; } ShaderUniformCount getCounts() const { return mUniformCount; }
......
...@@ -210,7 +210,7 @@ size_t InterfaceBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock ...@@ -210,7 +210,7 @@ size_t InterfaceBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock
sh::GetInterfaceBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder, sh::GetInterfaceBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
&mBlockLayout); &mBlockLayout);
return encoder->getBlockSize(); return encoder->getCurrentOffset();
} }
bool InterfaceBlockInfo::getBlockSize(const std::string &name, bool InterfaceBlockInfo::getBlockSize(const std::string &name,
......
...@@ -40,7 +40,7 @@ void InitDefaultUniformBlock(const std::vector<sh::Uniform> &uniforms, ...@@ -40,7 +40,7 @@ void InitDefaultUniformBlock(const std::vector<sh::Uniform> &uniforms,
sh::Std140BlockEncoder blockEncoder; sh::Std140BlockEncoder blockEncoder;
sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut); sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut);
size_t blockSize = blockEncoder.getBlockSize(); size_t blockSize = blockEncoder.getCurrentOffset();
// TODO(jmadill): I think we still need a valid block for the pipeline even if zero sized. // TODO(jmadill): I think we still need a valid block for the pipeline even if zero sized.
if (blockSize == 0) if (blockSize == 0)
......
...@@ -93,15 +93,18 @@ class ShaderStorageBufferTest31 : public ANGLETest ...@@ -93,15 +93,18 @@ class ShaderStorageBufferTest31 : public ANGLETest
const GLfloat *ptr = reinterpret_cast<const GLfloat *>( const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
matrixCase.mRows * matrixCase.mMatrixStride, GL_MAP_READ_BIT)); matrixCase.mRows * matrixCase.mMatrixStride, GL_MAP_READ_BIT));
for (unsigned int idx = 0; idx < matrixCase.mRows; idx++)
for (unsigned int row = 0; row < matrixCase.mRows; row++)
{ {
for (unsigned int idy = 0; idy < matrixCase.mColumns; idy++) for (unsigned int col = 0; col < matrixCase.mColumns; col++)
{ {
EXPECT_EQ(matrixCase.mInputdata[idx * (matrixCase.mMatrixStride / GLfloat expected = matrixCase.mInputdata[row * (matrixCase.mMatrixStride /
matrixCase.kBytesPerComponent) + matrixCase.kBytesPerComponent) +
idy], col];
*(ptr + idx * (matrixCase.mMatrixStride / matrixCase.kBytesPerComponent) + GLfloat actual =
idy)); *(ptr + row * (matrixCase.mMatrixStride / matrixCase.kBytesPerComponent) + col);
EXPECT_EQ(expected, actual) << " at row " << row << " and column " << col;
} }
} }
......
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