ES31: Implement binding layout for uniform blocks
The binding point of uniform blocks can be specified in shaders with
this CL. See spec ESSL 3.10, section 4.4.4, page 58 for more info.
dEQP-GLES31.functional.ubo.* still can't completely pass as
the missing of arrays-of-arrays feature. Neither can
dEQP-GLES31.functional.layout_binding.ubo.* due to the incomplete
implementation of program interface APIs.
TEST=angle_end2end_tests:UniformBufferTest
BUG=angleproject:1442
Change-Id: If95d468fc109834a132b9b817730d3fdc3a615da
Reviewed-on: https://chromium-review.googlesource.com/483848
Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index 2680741..a0f7436 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -878,6 +878,7 @@
stream.readString(&uniformBlock.name);
stream.readBool(&uniformBlock.isArray);
stream.readInt(&uniformBlock.arrayElement);
+ stream.readInt(&uniformBlock.binding);
stream.readInt(&uniformBlock.dataSize);
stream.readBool(&uniformBlock.vertexStaticUse);
stream.readBool(&uniformBlock.fragmentStaticUse);
@@ -1025,6 +1026,7 @@
stream.writeString(uniformBlock.name);
stream.writeInt(uniformBlock.isArray);
stream.writeInt(uniformBlock.arrayElement);
+ stream.writeInt(uniformBlock.binding);
stream.writeInt(uniformBlock.dataSize);
stream.writeInt(uniformBlock.vertexStaticUse);
@@ -1794,12 +1796,8 @@
const UniformBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex];
if (!uniformBlock.name.empty())
{
- const int length = static_cast<int>(uniformBlock.name.length()) + 1;
-
- // Counting in "[0]".
- const int arrayLength = (uniformBlock.isArray ? 3 : 0);
-
- maxLength = std::max(length + arrayLength, maxLength);
+ int length = static_cast<int>(uniformBlock.nameWithArrayIndex().length());
+ maxLength = std::max(length + 1, maxLength);
}
}
}
@@ -2283,7 +2281,9 @@
<< "' between vertex and fragment shaders";
return false;
}
- if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
+ if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout ||
+ vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout ||
+ vertexInterfaceBlock.binding != fragmentInterfaceBlock.binding)
{
infoLog << "Layout qualifiers differ for interface block '" << blockName
<< "' between vertex and fragment shaders";
@@ -2787,6 +2787,12 @@
defineUniformBlock(fragmentBlock, GL_FRAGMENT_SHADER);
visitedList.insert(fragmentBlock.name);
}
+ // Set initial bindings from shader.
+ for (unsigned int blockIndex = 0; blockIndex < mState.mUniformBlocks.size(); blockIndex++)
+ {
+ UniformBlock &uniformBlock = mState.mUniformBlocks[blockIndex];
+ bindUniformBlock(blockIndex, uniformBlock.binding);
+ }
}
template <typename VarT>
@@ -2831,18 +2837,6 @@
int blockIndex = static_cast<int>(mState.mUniformBlocks.size());
size_t blockSize = 0;
- // Don't define this block at all if it's not active in the implementation.
- std::stringstream blockNameStr;
- blockNameStr << interfaceBlock.name;
- if (interfaceBlock.arraySize > 0)
- {
- blockNameStr << "[0]";
- }
- if (!mProgram->getUniformBlockSize(blockNameStr.str(), &blockSize))
- {
- return;
- }
-
// Track the first and last uniform index to determine the range of active uniforms in the
// block.
size_t firstBlockUniformIndex = mState.mUniforms.size();
@@ -2855,12 +2849,22 @@
{
blockUniformIndexes.push_back(static_cast<unsigned int>(blockUniformIndex));
}
-
+ // ESSL 3.10 section 4.4.4 page 58:
+ // Any uniform or shader storage block declared without a binding qualifier is initially
+ // assigned to block binding point zero.
+ int blockBinding = (interfaceBlock.binding == -1 ? 0 : interfaceBlock.binding);
if (interfaceBlock.arraySize > 0)
{
for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement)
{
- UniformBlock block(interfaceBlock.name, true, arrayElement);
+ // Don't define this block at all if it's not active in the implementation.
+ if (!mProgram->getUniformBlockSize(interfaceBlock.name + ArrayString(arrayElement),
+ &blockSize))
+ {
+ continue;
+ }
+ UniformBlock block(interfaceBlock.name, true, arrayElement,
+ blockBinding + arrayElement);
block.memberUniformIndexes = blockUniformIndexes;
switch (shaderType)
@@ -2893,7 +2897,11 @@
}
else
{
- UniformBlock block(interfaceBlock.name, false, 0);
+ if (!mProgram->getUniformBlockSize(interfaceBlock.name, &blockSize))
+ {
+ return;
+ }
+ UniformBlock block(interfaceBlock.name, false, 0, blockBinding);
block.memberUniformIndexes = blockUniformIndexes;
switch (shaderType)