Commit 3de2703d by Olli Etuaho Committed by Commit Bot

Fix handling matrix qualifiers on block members

Individual block member row_major/column_major layout qualifiers may override the qualifiers set on the block. During parsing, this was already being handled correctly, so that the qualifier is resolved for each block member and recorded for each TField / InterfaceBlockField. Now we always write the qualifiers on a per-member granularity to the output GLSL shaders, so that the native driver gets the correct per-member qualifiers. This replaces earlier behavior where the matrix qualifiers were only written per-block. Also only use qualifiers from individual members in block layout. Since the block-level qualifier information is no longer used after parsing, it is no longer kept in the AST. A dummy value is still set to the InterfaceBlock structs exposed through the ShaderVars interface, since that has existing usage in Chromium that needs to be removed before the field can be removed. Some AMD OpenGL drivers don't seem to handle matrix layout qualifiers correctly, so most of the added tests need to be skipped for AMD GL. On NVIDIA and Intel the tests pass. BUG=angleproject:2271 TEST=angle_unittests, angle_end2end_tests, dEQP-GLES31.functional.program_interface_query.uniform.matrix* Change-Id: I1baa7a633bc2da548743c2190cb72db491b5227a Reviewed-on: https://chromium-review.googlesource.com/800174Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent bf0a40bb
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 190 #define ANGLE_SH_VERSION 191
enum ShShaderSpec enum ShShaderSpec
{ {
......
...@@ -270,7 +270,11 @@ struct InterfaceBlock ...@@ -270,7 +270,11 @@ struct InterfaceBlock
std::string instanceName; std::string instanceName;
unsigned int arraySize; unsigned int arraySize;
BlockLayoutType layout; BlockLayoutType layout;
// Deprecated. Matrix packing should only be queried from individual fields of the block.
// TODO(oetuaho): Remove this once it is no longer used in Chromium.
bool isRowMajorLayout; bool isRowMajorLayout;
int binding; int binding;
bool staticUse; bool staticUse;
BlockType blockType; BlockType blockType;
......
...@@ -666,7 +666,8 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock ...@@ -666,7 +666,8 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM || if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
interfaceBlock->blockType == BlockType::BLOCK_BUFFER) interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
{ {
interfaceBlock->isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor); // TODO(oetuaho): Remove setting isRowMajorLayout.
interfaceBlock->isRowMajorLayout = false;
interfaceBlock->binding = blockType->blockBinding(); interfaceBlock->binding = blockType->blockBinding();
interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage()); interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
} }
......
...@@ -1221,29 +1221,10 @@ void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfa ...@@ -1221,29 +1221,10 @@ void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfa
break; break;
} }
out << ", ";
if (interfaceBlock->blockBinding() > 0) if (interfaceBlock->blockBinding() > 0)
{ {
out << "binding = " << interfaceBlock->blockBinding();
out << ", "; out << ", ";
} out << "binding = " << interfaceBlock->blockBinding();
switch (interfaceBlock->matrixPacking())
{
case EmpUnspecified:
case EmpColumnMajor:
// Default matrix packing is column major.
out << "column_major";
break;
case EmpRowMajor:
out << "row_major";
break;
default:
UNREACHABLE();
break;
} }
out << ") "; out << ") ";
...@@ -1255,9 +1236,30 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc ...@@ -1255,9 +1236,30 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc
out << hashName(TName(interfaceBlock->name())) << "{\n"; out << hashName(TName(interfaceBlock->name())) << "{\n";
const TFieldList &fields = interfaceBlock->fields(); const TFieldList &fields = interfaceBlock->fields();
for (size_t i = 0; i < fields.size(); ++i) for (const TField *field : fields)
{ {
const TField *field = fields[i]; if (field->type()->isMatrix() || field->type()->isStructureContainingMatrices())
{
out << "layout(";
switch (field->type()->getLayoutQualifier().matrixPacking)
{
case EmpUnspecified:
case EmpColumnMajor:
// Default matrix packing is column major.
out << "column_major";
break;
case EmpRowMajor:
out << "row_major";
break;
default:
UNREACHABLE();
break;
}
out << ") ";
}
if (writeVariablePrecision(field->type()->getPrecision())) if (writeVariablePrecision(field->type()->getPrecision()))
out << " "; out << " ";
out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
......
...@@ -437,6 +437,11 @@ bool TType::isStructureContainingArrays() const ...@@ -437,6 +437,11 @@ bool TType::isStructureContainingArrays() const
return mStructure ? mStructure->containsArrays() : false; return mStructure ? mStructure->containsArrays() : false;
} }
bool TType::isStructureContainingMatrices() const
{
return mStructure ? mStructure->containsMatrices() : false;
}
bool TType::isStructureContainingType(TBasicType t) const bool TType::isStructureContainingType(TBasicType t) const
{ {
return mStructure ? mStructure->containsType(t) : false; return mStructure ? mStructure->containsType(t) : false;
...@@ -930,6 +935,17 @@ bool TFieldListCollection::containsArrays() const ...@@ -930,6 +935,17 @@ bool TFieldListCollection::containsArrays() const
return false; return false;
} }
bool TFieldListCollection::containsMatrices() const
{
for (const auto *field : *mFields)
{
const TType *fieldType = field->type();
if (fieldType->isMatrix() || fieldType->isStructureContainingMatrices())
return true;
}
return false;
}
bool TFieldListCollection::containsType(TBasicType type) const bool TFieldListCollection::containsType(TBasicType type) const
{ {
for (const auto *field : *mFields) for (const auto *field : *mFields)
...@@ -1032,7 +1048,6 @@ TInterfaceBlock::TInterfaceBlock(const TString *name, ...@@ -1032,7 +1048,6 @@ TInterfaceBlock::TInterfaceBlock(const TString *name,
mName(name), mName(name),
mInstanceName(instanceName), mInstanceName(instanceName),
mBlockStorage(layoutQualifier.blockStorage), mBlockStorage(layoutQualifier.blockStorage),
mMatrixPacking(layoutQualifier.matrixPacking),
mBinding(layoutQualifier.binding) mBinding(layoutQualifier.binding)
{ {
} }
......
...@@ -55,6 +55,7 @@ class TFieldListCollection : angle::NonCopyable ...@@ -55,6 +55,7 @@ class TFieldListCollection : angle::NonCopyable
const TFieldList &fields() const { return *mFields; } const TFieldList &fields() const { return *mFields; }
bool containsArrays() const; bool containsArrays() const;
bool containsMatrices() const;
bool containsType(TBasicType t) const; bool containsType(TBasicType t) const;
bool containsSamplers() const; bool containsSamplers() const;
...@@ -92,15 +93,15 @@ class TInterfaceBlock : public TFieldListCollection ...@@ -92,15 +93,15 @@ class TInterfaceBlock : public TFieldListCollection
const TString &instanceName() const { return *mInstanceName; } const TString &instanceName() const { return *mInstanceName; }
bool hasInstanceName() const { return mInstanceName != nullptr; } bool hasInstanceName() const { return mInstanceName != nullptr; }
TLayoutBlockStorage blockStorage() const { return mBlockStorage; } TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; }
int blockBinding() const { return mBinding; } int blockBinding() const { return mBinding; }
private: private:
const TString *mName; const TString *mName;
const TString *mInstanceName; // for interface block instance names const TString *mInstanceName; // for interface block instance names
TLayoutBlockStorage mBlockStorage; TLayoutBlockStorage mBlockStorage;
TLayoutMatrixPacking mMatrixPacking;
int mBinding; int mBinding;
// Note that we only record matrix packing on a per-field granularity.
}; };
// //
...@@ -281,6 +282,7 @@ class TType ...@@ -281,6 +282,7 @@ class TType
bool isNamelessStruct() const; bool isNamelessStruct() const;
bool isStructureContainingArrays() const; bool isStructureContainingArrays() const;
bool isStructureContainingMatrices() const;
bool isStructureContainingType(TBasicType t) const; bool isStructureContainingType(TBasicType t) const;
bool isStructureContainingSamplers() const; bool isStructureContainingSamplers() const;
......
...@@ -28,6 +28,13 @@ bool IsRowMajorLayout(const ShaderVariable &var) ...@@ -28,6 +28,13 @@ bool IsRowMajorLayout(const ShaderVariable &var)
} }
template <typename VarT> template <typename VarT>
void GetUniformBlockInfo(const std::vector<VarT> &fields,
const std::string &prefix,
sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout,
BlockLayoutMap *blockInfoOut);
template <typename VarT>
void GetUniformBlockStructMemberInfo(const std::vector<VarT> &fields, void GetUniformBlockStructMemberInfo(const std::vector<VarT> &fields,
const std::string &fieldName, const std::string &fieldName,
sh::BlockLayoutEncoder *encoder, sh::BlockLayoutEncoder *encoder,
...@@ -71,7 +78,7 @@ void GetUniformBlockArrayOfArraysMemberInfo(const VarT &field, ...@@ -71,7 +78,7 @@ void GetUniformBlockArrayOfArraysMemberInfo(const VarT &field,
unsigned int arrayNestingIndex, unsigned int arrayNestingIndex,
const std::string &arrayName, const std::string &arrayName,
sh::BlockLayoutEncoder *encoder, sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout, bool isRowMajorMatrix,
BlockLayoutMap *blockInfoOut) BlockLayoutMap *blockInfoOut)
{ {
const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex); const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex);
...@@ -81,14 +88,61 @@ void GetUniformBlockArrayOfArraysMemberInfo(const VarT &field, ...@@ -81,14 +88,61 @@ void GetUniformBlockArrayOfArraysMemberInfo(const VarT &field,
if (arrayNestingIndex + 2u < field.arraySizes.size()) if (arrayNestingIndex + 2u < field.arraySizes.size())
{ {
GetUniformBlockArrayOfArraysMemberInfo(field, arrayNestingIndex + 1u, elementName, GetUniformBlockArrayOfArraysMemberInfo(field, arrayNestingIndex + 1u, elementName,
encoder, inRowMajorLayout, blockInfoOut); encoder, isRowMajorMatrix, blockInfoOut);
} }
else else
{ {
std::vector<unsigned int> innermostArraySize( std::vector<unsigned int> innermostArraySize(
1u, field.getNestedArraySize(arrayNestingIndex + 1u)); 1u, field.getNestedArraySize(arrayNestingIndex + 1u));
(*blockInfoOut)[elementName] = (*blockInfoOut)[elementName] =
encoder->encodeType(field.type, innermostArraySize, inRowMajorLayout); encoder->encodeType(field.type, innermostArraySize, isRowMajorMatrix);
}
}
}
template <typename VarT>
void GetUniformBlockInfo(const std::vector<VarT> &fields,
const std::string &prefix,
sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout,
BlockLayoutMap *blockInfoOut)
{
for (const VarT &field : fields)
{
// Skip samplers. On Vulkan we use this for the default uniform block, so samplers may be
// included.
if (gl::IsSamplerType(field.type))
{
continue;
}
const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
if (field.isStruct())
{
if (field.isArray())
{
GetUniformBlockStructArrayMemberInfo(field, 0u, fieldName, encoder, rowMajorLayout,
blockInfoOut);
}
else
{
GetUniformBlockStructMemberInfo(field.fields, fieldName, encoder, rowMajorLayout,
blockInfoOut);
}
}
else if (field.isArrayOfArrays())
{
GetUniformBlockArrayOfArraysMemberInfo(field, 0u, fieldName, encoder,
rowMajorLayout && gl::IsMatrixType(field.type),
blockInfoOut);
}
else
{
(*blockInfoOut)[fieldName] = encoder->encodeType(
field.type, field.arraySizes, rowMajorLayout && gl::IsMatrixType(field.type));
} }
} }
} }
...@@ -212,70 +266,25 @@ void Std140BlockEncoder::advanceOffset(GLenum type, ...@@ -212,70 +266,25 @@ void Std140BlockEncoder::advanceOffset(GLenum type,
} }
} }
template <typename VarT> void GetUniformBlockInfo(const std::vector<InterfaceBlockField> &fields,
void GetUniformBlockInfo(const std::vector<VarT> &fields,
const std::string &prefix, const std::string &prefix,
sh::BlockLayoutEncoder *encoder, sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout,
BlockLayoutMap *blockInfoOut) BlockLayoutMap *blockInfoOut)
{ {
for (const VarT &field : fields) // Matrix packing is always recorded in individual fields, so they'll set the row major layout
{ // flag to true if needed.
// Skip samplers. On Vulkan we use this for the default uniform block, so samplers may be GetUniformBlockInfo(fields, prefix, encoder, false, blockInfoOut);
// included. }
if (gl::IsSamplerType(field.type))
{
continue;
}
const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
if (field.isStruct())
{
bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
if (field.isArray()) void GetUniformBlockInfo(const std::vector<Uniform> &uniforms,
{ const std::string &prefix,
GetUniformBlockStructArrayMemberInfo(field, 0u, fieldName, encoder, rowMajorLayout, sh::BlockLayoutEncoder *encoder,
blockInfoOut); BlockLayoutMap *blockInfoOut)
} {
else // Matrix packing is always recorded in individual fields, so they'll set the row major layout
{ // flag to true if needed.
GetUniformBlockStructMemberInfo(field.fields, fieldName, encoder, rowMajorLayout, GetUniformBlockInfo(uniforms, prefix, encoder, false, blockInfoOut);
blockInfoOut);
}
}
else if (field.isArrayOfArrays())
{
bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
GetUniformBlockArrayOfArraysMemberInfo(field, 0u, fieldName, encoder, isRowMajorMatrix,
blockInfoOut);
}
else
{
bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
(*blockInfoOut)[fieldName] =
encoder->encodeType(field.type, field.arraySizes, isRowMajorMatrix);
}
}
} }
template void GetUniformBlockInfo(const std::vector<InterfaceBlockField> &,
const std::string &,
sh::BlockLayoutEncoder *,
bool,
BlockLayoutMap *);
template void GetUniformBlockInfo(const std::vector<Uniform> &,
const std::string &,
sh::BlockLayoutEncoder *,
bool,
BlockLayoutMap *);
template void GetUniformBlockInfo(const std::vector<ShaderVariable> &,
const std::string &,
sh::BlockLayoutEncoder *,
bool,
BlockLayoutMap *);
} // namespace sh } // namespace sh
...@@ -131,13 +131,16 @@ class Std140BlockEncoder : public BlockLayoutEncoder ...@@ -131,13 +131,16 @@ class Std140BlockEncoder : public BlockLayoutEncoder
using BlockLayoutMap = std::map<std::string, BlockMemberInfo>; using BlockLayoutMap = std::map<std::string, BlockMemberInfo>;
// Only valid to call with ShaderVariable, InterfaceBlockField and Uniform. void GetUniformBlockInfo(const std::vector<InterfaceBlockField> &fields,
template <typename VarT>
void GetUniformBlockInfo(const std::vector<VarT> &fields,
const std::string &prefix, const std::string &prefix,
sh::BlockLayoutEncoder *encoder, sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout, BlockLayoutMap *blockInfoOut);
BlockLayoutMap *blockLayoutMap);
// Used for laying out the default uniform block on the Vulkan backend.
void GetUniformBlockInfo(const std::vector<Uniform> &uniforms,
const std::string &prefix,
sh::BlockLayoutEncoder *encoder,
BlockLayoutMap *blockInfoOut);
} // namespace sh } // namespace sh
......
...@@ -2451,7 +2451,6 @@ bool Program::areMatchingInterfaceBlocks(InfoLog &infoLog, ...@@ -2451,7 +2451,6 @@ bool Program::areMatchingInterfaceBlocks(InfoLog &infoLog,
return false; return false;
} }
if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout ||
vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout ||
vertexInterfaceBlock.binding != fragmentInterfaceBlock.binding) vertexInterfaceBlock.binding != fragmentInterfaceBlock.binding)
{ {
infoLog << "Layout qualifiers differ for interface block '" << blockName infoLog << "Layout qualifiers differ for interface block '" << blockName
......
...@@ -252,7 +252,7 @@ size_t UniformBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock) ...@@ -252,7 +252,7 @@ size_t UniformBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock)
} }
sh::GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder, sh::GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
interfaceBlock.isRowMajorLayout, &mBlockLayout); &mBlockLayout);
return encoder->getBlockSize(); return encoder->getBlockSize();
} }
......
...@@ -39,7 +39,7 @@ gl::Error InitDefaultUniformBlock(const gl::Context *context, ...@@ -39,7 +39,7 @@ gl::Error InitDefaultUniformBlock(const gl::Context *context,
} }
sh::Std140BlockEncoder blockEncoder; sh::Std140BlockEncoder blockEncoder;
sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, false, blockLayoutMapOut); sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut);
size_t blockSize = blockEncoder.getBlockSize(); size_t blockSize = blockEncoder.getBlockSize();
......
...@@ -319,7 +319,6 @@ TEST_F(CollectVertexVariablesTest, SimpleInterfaceBlock) ...@@ -319,7 +319,6 @@ TEST_F(CollectVertexVariablesTest, SimpleInterfaceBlock)
const InterfaceBlock &interfaceBlock = interfaceBlocks[0]; const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize); EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name); EXPECT_EQ("b", interfaceBlock.name);
EXPECT_TRUE(interfaceBlock.staticUse); EXPECT_TRUE(interfaceBlock.staticUse);
...@@ -355,7 +354,6 @@ TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock) ...@@ -355,7 +354,6 @@ TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock)
const InterfaceBlock &interfaceBlock = interfaceBlocks[0]; const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize); EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name); EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ("blockInstance", interfaceBlock.instanceName); EXPECT_EQ("blockInstance", interfaceBlock.instanceName);
...@@ -393,7 +391,6 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock) ...@@ -393,7 +391,6 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
const InterfaceBlock &interfaceBlock = interfaceBlocks[0]; const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize); EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name); EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName); EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
...@@ -439,7 +436,6 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock) ...@@ -439,7 +436,6 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
const InterfaceBlock &interfaceBlock = interfaceBlocks[0]; const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize); EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name); EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName); EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
...@@ -486,7 +482,6 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock) ...@@ -486,7 +482,6 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
const InterfaceBlock &interfaceBlock = interfaceBlocks[0]; const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize); EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_TRUE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name); EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName); EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
...@@ -795,7 +790,6 @@ TEST_F(CollectHashedVertexVariablesTest, InstancedInterfaceBlock) ...@@ -795,7 +790,6 @@ TEST_F(CollectHashedVertexVariablesTest, InstancedInterfaceBlock)
const InterfaceBlock &interfaceBlock = interfaceBlocks[0]; const InterfaceBlock &interfaceBlock = interfaceBlocks[0];
EXPECT_EQ(0u, interfaceBlock.arraySize); EXPECT_EQ(0u, interfaceBlock.arraySize);
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("blockName", interfaceBlock.name); EXPECT_EQ("blockName", interfaceBlock.name);
EXPECT_EQ("blockInstance", interfaceBlock.instanceName); EXPECT_EQ("blockInstance", interfaceBlock.instanceName);
......
...@@ -538,8 +538,6 @@ ...@@ -538,8 +538,6 @@
1442 OPENGL : dEQP-GLES31.functional.program_interface_query.program_output.* = FAIL 1442 OPENGL : dEQP-GLES31.functional.program_interface_query.program_output.* = FAIL
1442 OPENGL : dEQP-GLES31.functional.program_interface_query.shader_storage_block.* = FAIL 1442 OPENGL : dEQP-GLES31.functional.program_interface_query.shader_storage_block.* = FAIL
1442 OPENGL : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.* = FAIL 1442 OPENGL : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.* = FAIL
1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform.matrix_row_major.* = FAIL
1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform.matrix_stride.* = FAIL
1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.* = FAIL 1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform.referenced_by_shader.* = FAIL
1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform.random.* = FAIL 1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform.random.* = FAIL
1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform_block.resource_list.block_array = FAIL 1442 OPENGL : dEQP-GLES31.functional.program_interface_query.uniform_block.resource_list.block_array = FAIL
......
...@@ -1196,6 +1196,200 @@ TEST_P(UniformBufferTest, DetachShaders) ...@@ -1196,6 +1196,200 @@ TEST_P(UniformBufferTest, DetachShaders)
glDeleteProgram(program); glDeleteProgram(program);
} }
// Test a uniform block where the whole block is set as row-major.
TEST_P(UniformBufferTest, Std140UniformBlockWithRowMajorQualifier)
{
// AMD OpenGL driver doesn't seem to apply the row-major qualifier right.
// http://anglebug.com/2273
ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
const std::string &fragmentShader =
R"(#version 300 es
precision highp float;
out vec4 my_FragColor;
layout(std140, row_major) uniform matrixBuffer
{
mat2 m;
} buffer;
void main()
{
// Vector constructor accesses elements in column-major order.
my_FragColor = vec4(buffer.m);
})";
ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
const GLsizei kElementsPerMatrix = 8; // Each mat2 row gets padded into a vec4.
const GLsizei kBytesPerElement = 4;
const GLsizei kDataSize = kElementsPerMatrix * kBytesPerElement;
std::vector<GLubyte> v(kDataSize, 0);
float *vAsFloat = reinterpret_cast<float *>(v.data());
vAsFloat[0u] = 1.0f;
vAsFloat[1u] = 128.0f / 255.0f;
vAsFloat[4u] = 64.0f / 255.0f;
vAsFloat[5u] = 32.0f / 255.0f;
glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
glUniformBlockBinding(program, uniformBufferIndex, 0);
drawQuad(program.get(), "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
}
// Test a uniform block where an individual matrix field is set as row-major whereas the whole block
// is set as column-major.
TEST_P(UniformBufferTest, Std140UniformBlockWithPerMemberRowMajorQualifier)
{
// AMD OpenGL driver doesn't seem to apply the row-major qualifier right.
// http://anglebug.com/2273
ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
const std::string &fragmentShader =
R"(#version 300 es
precision highp float;
out vec4 my_FragColor;
layout(std140, column_major) uniform matrixBuffer
{
layout(row_major) mat2 m;
} buffer;
void main()
{
// Vector constructor accesses elements in column-major order.
my_FragColor = vec4(buffer.m);
})";
ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
const GLsizei kElementsPerMatrix = 8; // Each mat2 row gets padded into a vec4.
const GLsizei kBytesPerElement = 4;
const GLsizei kDataSize = kElementsPerMatrix * kBytesPerElement;
std::vector<GLubyte> v(kDataSize, 0);
float *vAsFloat = reinterpret_cast<float *>(v.data());
vAsFloat[0u] = 1.0f;
vAsFloat[1u] = 128.0f / 255.0f;
vAsFloat[4u] = 64.0f / 255.0f;
vAsFloat[5u] = 32.0f / 255.0f;
glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
glUniformBlockBinding(program, uniformBufferIndex, 0);
drawQuad(program.get(), "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
}
// Test a uniform block where an individual matrix field is set as column-major whereas the whole
// block is set as row-major.
TEST_P(UniformBufferTest, Std140UniformBlockWithPerMemberColumnMajorQualifier)
{
const std::string &fragmentShader =
R"(#version 300 es
precision highp float;
out vec4 my_FragColor;
layout(std140, row_major) uniform matrixBuffer
{
// 2 columns, 3 rows.
layout(column_major) mat2x3 m;
} buffer;
void main()
{
// Vector constructor accesses elements in column-major order.
my_FragColor = vec4(buffer.m);
})";
ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
const GLsizei kElementsPerMatrix = 8; // Each mat2x3 column gets padded into a vec4.
const GLsizei kBytesPerElement = 4;
const GLsizei kDataSize = kElementsPerMatrix * kBytesPerElement;
std::vector<GLubyte> v(kDataSize, 0);
float *vAsFloat = reinterpret_cast<float *>(v.data());
vAsFloat[0u] = 1.0f;
vAsFloat[1u] = 192.0f / 255.0f;
vAsFloat[2u] = 128.0f / 255.0f;
vAsFloat[4u] = 96.0f / 255.0f;
vAsFloat[5u] = 64.0f / 255.0f;
vAsFloat[6u] = 32.0f / 255.0f;
glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
glUniformBlockBinding(program, uniformBufferIndex, 0);
drawQuad(program.get(), "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 192, 128, 96), 5);
}
// Test a uniform block where a struct field is set as row-major.
TEST_P(UniformBufferTest, Std140UniformBlockWithRowMajorQualifierOnStruct)
{
// AMD OpenGL driver doesn't seem to apply the row-major qualifier right.
// http://anglebug.com/2273
ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
const std::string &fragmentShader =
R"(#version 300 es
precision highp float;
out vec4 my_FragColor;
struct S
{
mat2 m;
};
layout(std140) uniform matrixBuffer
{
layout(row_major) S s;
} buffer;
void main()
{
// Vector constructor accesses elements in column-major order.
my_FragColor = vec4(buffer.s.m);
})";
ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
const GLsizei kElementsPerMatrix = 8; // Each mat2 row gets padded into a vec4.
const GLsizei kBytesPerElement = 4;
const GLsizei kDataSize = kElementsPerMatrix * kBytesPerElement;
std::vector<GLubyte> v(kDataSize, 0);
float *vAsFloat = reinterpret_cast<float *>(v.data());
vAsFloat[0u] = 1.0f;
vAsFloat[1u] = 128.0f / 255.0f;
vAsFloat[4u] = 64.0f / 255.0f;
vAsFloat[5u] = 32.0f / 255.0f;
glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
glUniformBlockBinding(program, uniformBufferIndex, 0);
drawQuad(program.get(), "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(UniformBufferTest, ANGLE_INSTANTIATE_TEST(UniformBufferTest,
ES3_D3D11(), ES3_D3D11(),
......
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