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,
ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics)
PerformanceDiagnostics *perfDiagnostics,
const std::vector<InterfaceBlock> &shaderStorageBlocks)
: TIntermTraverser(true, true, true, symbolTable),
mShaderType(shaderType),
mShaderVersion(shaderVersion),
......@@ -303,7 +304,8 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
// Reserve registers for the default uniform block and driver constants
mResourcesHLSL->reserveUniformBlockRegisters(2);
mSSBOOutputHLSL = new ShaderStorageBlockOutputHLSL(this, symbolTable, mResourcesHLSL);
mSSBOOutputHLSL =
new ShaderStorageBlockOutputHLSL(this, symbolTable, mResourcesHLSL, shaderStorageBlocks);
}
OutputHLSL::~OutputHLSL()
......
......@@ -47,7 +47,8 @@ class OutputHLSL : public TIntermTraverser
ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics);
PerformanceDiagnostics *perfDiagnostics,
const std::vector<InterfaceBlock> &shaderStorageBlocks);
~OutputHLSL();
......
......@@ -34,12 +34,15 @@ using ReferencedInterfaceBlocks = std::map<int, const TReferencedBlock *>;
// Used to save shader storage block field member information.
using BlockMemberInfoMap = std::map<const TField *, BlockMemberInfo>;
using ShaderVarToFieldMap = std::map<std::string, const TField *>;
class ShaderStorageBlockOutputHLSL : public TIntermTraverser
{
public:
ShaderStorageBlockOutputHLSL(OutputHLSL *outputHLSL,
TSymbolTable *symbolTable,
ResourcesHLSL *resourcesHLSL);
ResourcesHLSL *resourcesHLSL,
const std::vector<InterfaceBlock> &shaderStorageBlocks);
~ShaderStorageBlockOutputHLSL();
......@@ -82,6 +85,7 @@ class ShaderStorageBlockOutputHLSL : public TIntermTraverser
ReferencedInterfaceBlocks mReferencedShaderStorageBlocks;
BlockMemberInfoMap mBlockMemberInfoMap;
const std::vector<InterfaceBlock> &mShaderStorageBlocks;
};
} // namespace sh
......
......@@ -138,7 +138,7 @@ void TranslatorHLSL::translate(TIntermBlock *root,
sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
getSourcePath(), getOutputType(), numRenderTargets, getUniforms(),
compileOptions, getComputeShaderLocalSize(), &getSymbolTable(),
perfDiagnostics);
perfDiagnostics, mShaderStorageBlocks);
outputHLSL.output(root, getInfoSink().obj);
......
......@@ -66,6 +66,11 @@ struct BlockMemberInfo
int topLevelArrayStride = -1;
};
constexpr size_t ComponentAlignment(size_t numComponents)
{
return (numComponents == 3u ? 4u : numComponents);
}
constexpr BlockMemberInfo kDefaultBlockMemberInfo;
class BlockLayoutEncoder
......@@ -78,13 +83,11 @@ class BlockLayoutEncoder
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix);
size_t getBlockSize() const { return mCurrentOffset * kBytesPerComponent; }
size_t getStructureBaseAlignment() const { return mStructureBaseAlignment; }
void increaseCurrentOffset(size_t offsetInBytes);
void setStructureBaseAlignment(size_t baseAlignment);
size_t getCurrentOffset() const { return mCurrentOffset * kBytesPerComponent; }
virtual void enterAggregateType() = 0;
virtual void exitAggregateType() = 0;
// Called when entering/exiting a structure variable.
virtual void enterAggregateType(const ShaderVariable &structVar) = 0;
virtual void exitAggregateType(const ShaderVariable &structVar) = 0;
static constexpr size_t kBytesPerComponent = 4u;
static constexpr unsigned int kComponentsPerRegister = 4u;
......@@ -93,10 +96,7 @@ class BlockLayoutEncoder
static size_t GetBlockRegisterElement(const BlockMemberInfo &info);
protected:
size_t mCurrentOffset;
size_t mStructureBaseAlignment;
virtual void nextRegister();
void align(size_t baseAlignment);
virtual void getBlockLayoutInfo(GLenum type,
const std::vector<unsigned int> &arraySizes,
......@@ -108,6 +108,8 @@ class BlockLayoutEncoder
bool isRowMajorMatrix,
int arrayStride,
int matrixStride) = 0;
size_t mCurrentOffset;
};
// Will return default values for everything.
......@@ -116,8 +118,8 @@ class DummyBlockEncoder : public BlockLayoutEncoder
public:
DummyBlockEncoder() = default;
void enterAggregateType() override {}
void exitAggregateType() override {}
void enterAggregateType(const ShaderVariable &structVar) override {}
void exitAggregateType(const ShaderVariable &structVar) override {}
protected:
void getBlockLayoutInfo(GLenum type,
......@@ -146,8 +148,8 @@ class Std140BlockEncoder : public BlockLayoutEncoder
public:
Std140BlockEncoder();
void enterAggregateType() override;
void exitAggregateType() override;
void enterAggregateType(const ShaderVariable &structVar) override;
void exitAggregateType(const ShaderVariable &structVar) override;
protected:
void getBlockLayoutInfo(GLenum type,
......@@ -160,6 +162,16 @@ class Std140BlockEncoder : public BlockLayoutEncoder
bool isRowMajorMatrix,
int arrayStride,
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
......@@ -168,12 +180,8 @@ class Std430BlockEncoder : public Std140BlockEncoder
Std430BlockEncoder();
protected:
void nextRegister() override;
void getBlockLayoutInfo(GLenum type,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int *arrayStrideOut,
int *matrixStrideOut) override;
size_t getBaseAlignment(const ShaderVariable &variable) const override;
size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const override;
};
using BlockLayoutMap = std::map<std::string, BlockMemberInfo>;
......@@ -197,8 +205,8 @@ class ShaderVariableVisitor
virtual void enterStruct(const ShaderVariable &structVar) {}
virtual void exitStruct(const ShaderVariable &structVar) {}
virtual void enterStructAccess(const ShaderVariable &structVar) {}
virtual void exitStructAccess(const ShaderVariable &structVar) {}
virtual void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) {}
virtual void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) {}
virtual void enterArray(const ShaderVariable &arrayVar) {}
virtual void exitArray(const ShaderVariable &arrayVar) {}
......@@ -222,8 +230,8 @@ class VariableNameVisitor : public ShaderVariableVisitor
void enterStruct(const ShaderVariable &structVar) override;
void exitStruct(const ShaderVariable &structVar) override;
void enterStructAccess(const ShaderVariable &structVar) override;
void exitStructAccess(const ShaderVariable &structVar) override;
void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
void enterArray(const ShaderVariable &arrayVar) override;
void exitArray(const ShaderVariable &arrayVar) override;
void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
......@@ -243,11 +251,12 @@ class VariableNameVisitor : public ShaderVariableVisitor
const std::string &name,
const std::string &mappedName) = 0;
std::string collapseNameStack() const;
std::string collapseMappedNameStack() const;
private:
void visitSampler(const sh::ShaderVariable &sampler) 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> mMappedNameStack;
......@@ -261,8 +270,8 @@ class BlockEncoderVisitor : public VariableNameVisitor
BlockLayoutEncoder *encoder);
~BlockEncoderVisitor();
void enterStructAccess(const ShaderVariable &structVar) override;
void exitStructAccess(const ShaderVariable &structVar) override;
void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
void visitNamedVariable(const ShaderVariable &variable,
bool isRowMajor,
......
......@@ -19,12 +19,12 @@ HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool trans
: 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,
const std::vector<unsigned int> &arraySizes,
......@@ -45,7 +45,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
// register
if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty())
{
nextRegister();
align(kComponentsPerRegister);
}
if (gl::IsMatrixType(type))
......@@ -67,7 +67,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
int numComponents = gl::VariableComponentCount(type);
if ((numComponents + (mCurrentOffset % kComponentsPerRegister)) > kComponentsPerRegister)
{
nextRegister();
align(kComponentsPerRegister);
}
}
......@@ -134,14 +134,14 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
{
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
......@@ -157,7 +157,7 @@ unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput o
HLSLVariableRegisterCount(variable, &encoder);
const size_t registerBytes = (encoder.kBytesPerComponent * encoder.kComponentsPerRegister);
return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) /
registerBytes);
return static_cast<unsigned int>(
rx::roundUp<size_t>(encoder.getCurrentOffset(), registerBytes) / registerBytes);
}
} // namespace sh
......@@ -35,8 +35,8 @@ class HLSLBlockEncoder : public BlockLayoutEncoder
HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices);
void enterAggregateType() override;
void exitAggregateType() override;
void enterAggregateType(const ShaderVariable &structVar) override;
void exitAggregateType(const ShaderVariable &structVar) override;
void skipRegisters(unsigned int numRegisters);
bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
......
......@@ -350,16 +350,16 @@ class ShaderStorageBlockVisitor : public sh::VariableNameVisitor
sh::VariableNameVisitor::exitArrayElement(arrayVar, arrayElement);
}
void enterStructAccess(const sh::ShaderVariable &structVar) override
void enterStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
{
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--;
sh::VariableNameVisitor::exitStructAccess(structVar);
sh::VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
}
void visitNamedVariable(const sh::ShaderVariable &variable,
......@@ -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++;
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--;
sh::VariableNameVisitor::exitStructAccess(structVar);
sh::VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
}
ShaderUniformCount getCounts() const { return mUniformCount; }
......
......@@ -210,7 +210,7 @@ size_t InterfaceBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock
sh::GetInterfaceBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
&mBlockLayout);
return encoder->getBlockSize();
return encoder->getCurrentOffset();
}
bool InterfaceBlockInfo::getBlockSize(const std::string &name,
......
......@@ -40,7 +40,7 @@ void InitDefaultUniformBlock(const std::vector<sh::Uniform> &uniforms,
sh::Std140BlockEncoder blockEncoder;
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.
if (blockSize == 0)
......
......@@ -93,15 +93,18 @@ class ShaderStorageBufferTest31 : public ANGLETest
const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
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 /
matrixCase.kBytesPerComponent) +
idy],
*(ptr + idx * (matrixCase.mMatrixStride / matrixCase.kBytesPerComponent) +
idy));
GLfloat expected = matrixCase.mInputdata[row * (matrixCase.mMatrixStride /
matrixCase.kBytesPerComponent) +
col];
GLfloat actual =
*(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