Add support for structures in interface and uniform blocks.
Also redesigns the uniform block layout computation to be more general.
TRAC #23018
Signed-off-by: Geoff Lang
Signed-off-by: Nicolas Capens
Author: Jamie Madill
git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2387 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/Uniform.cpp b/src/compiler/Uniform.cpp
index e55af75..917e08f 100644
--- a/src/compiler/Uniform.cpp
+++ b/src/compiler/Uniform.cpp
@@ -33,151 +33,172 @@
InterfaceBlock::InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex)
: name(name),
arraySize(arraySize),
+ layout(BLOCKLAYOUT_SHARED),
registerIndex(registerIndex)
{
}
// Use the same layout for packed and shared
-void InterfaceBlock::setSharedBlockLayout()
+void InterfaceBlock::setBlockLayout(BlockLayoutType newLayout)
{
- setPackedBlockLayout();
+ layout = newLayout;
+
+ const size_t componentSize = 4;
+ unsigned int currentOffset = 0;
+
+ blockInfo.clear();
+ getBlockLayoutInfo(activeUniforms, ¤tOffset);
+
+ dataSize = currentOffset * componentSize;
+}
+
+void InterfaceBlock::getBlockLayoutInfo(const sh::ActiveUniforms &fields, unsigned int *currentOffset)
+{
+ const size_t componentSize = 4;
+
+ // TODO: row major matrices
+ bool isRowMajorMatrix = false;
+
+ for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+ {
+ int arrayStride;
+ int matrixStride;
+
+ const sh::Uniform &uniform = fields[fieldIndex];
+
+ if (getBlockLayoutInfo(uniform, currentOffset, &arrayStride, &matrixStride))
+ {
+ const BlockMemberInfo memberInfo(*currentOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, isRowMajorMatrix);
+ blockInfo.push_back(memberInfo);
+
+ if (uniform.arraySize > 0)
+ {
+ *currentOffset += arrayStride * uniform.arraySize;
+ }
+ else if (gl::IsMatrixType(uniform.type))
+ {
+ const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
+ *currentOffset += matrixStride * componentGroups;
+ }
+ else
+ {
+ *currentOffset += gl::UniformComponentCount(uniform.type);
+ }
+ }
+ }
+}
+
+bool InterfaceBlock::getBlockLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
+{
+ if (!uniform.fields.empty())
+ {
+ getBlockLayoutInfo(uniform.fields, currentOffset);
+ return false;
+ }
+
+ switch (layout)
+ {
+ case BLOCKLAYOUT_SHARED:
+ case BLOCKLAYOUT_PACKED:
+ getD3DLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
+ return true;
+
+ case BLOCKLAYOUT_STANDARD:
+ getStandardLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
+ return true;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
}
// Block layout packed according to the default D3D11 register packing rules
// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
-void InterfaceBlock::setPackedBlockLayout()
+void InterfaceBlock::getD3DLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
{
- const size_t componentSize = 4;
+ ASSERT(uniform.fields.empty());
+
const unsigned int registerSize = 4;
- unsigned int currentOffset = 0;
+ const size_t componentSize = 4;
- blockInfo.clear();
+ // TODO: row major matrices
+ bool isRowMajorMatrix = false;
+ // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
+ ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
+ int matrixStride = 0;
+ int arrayStride = 0;
- for (unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++)
+ if (gl::IsMatrixType(uniform.type))
{
- const sh::Uniform &uniform = activeUniforms[uniformIndex];
+ *currentOffset = rx::roundUp(*currentOffset, 4u);
+ matrixStride = registerSize;
- // TODO: structs
- // TODO: row major matrices
- bool isRowMajorMatrix = false;
-
- // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
- ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
-
- int arrayStride = 0;
- int matrixStride = 0;
-
- if (gl::IsMatrixType(uniform.type))
- {
- currentOffset = rx::roundUp(currentOffset, 4u);
- matrixStride = registerSize;
-
- if (uniform.arraySize > 0)
- {
- const int componentGroups = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
- arrayStride = matrixStride * componentGroups;
- }
- }
- else if (uniform.arraySize > 0)
- {
- currentOffset = rx::roundUp(currentOffset, registerSize);
- arrayStride = registerSize;
- }
- else
- {
- int numComponents = gl::UniformComponentCount(uniform.type);
- if ((numComponents + (currentOffset % registerSize)) >= registerSize)
- {
- currentOffset = rx::roundUp(currentOffset, registerSize);
- }
- }
-
- BlockMemberInfo memberInfo(currentOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, isRowMajorMatrix);
- blockInfo.push_back(memberInfo);
-
- // for arrays/matrices, the next element is in a multiple of register size
if (uniform.arraySize > 0)
{
- currentOffset += arrayStride * uniform.arraySize;
+ const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
+ arrayStride = matrixStride * componentGroups;
}
- else if (gl::IsMatrixType(uniform.type))
+ }
+ else if (uniform.arraySize > 0)
+ {
+ *currentOffset = rx::roundUp(*currentOffset, registerSize);
+ arrayStride = registerSize;
+ }
+ else
+ {
+ int numComponents = gl::UniformComponentCount(uniform.type);
+ if ((numComponents + (*currentOffset % registerSize)) >= registerSize)
{
- const int componentGroups = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
- currentOffset += matrixStride * componentGroups;
- }
- else
- {
- currentOffset += gl::UniformComponentCount(uniform.type);
+ *currentOffset = rx::roundUp(*currentOffset, registerSize);
}
}
- dataSize = currentOffset * componentSize;
+ *matrixStrideOut = matrixStride;
+ *arrayStrideOut = arrayStride;
}
-void InterfaceBlock::setStandardBlockLayout()
+// Block layout according to the std140 block layout
+// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
+void InterfaceBlock::getStandardLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
{
+ ASSERT(uniform.fields.empty());
+
const size_t componentSize = 4;
- unsigned int currentOffset = 0;
- blockInfo.clear();
+ // TODO: row major matrices
+ bool isRowMajorMatrix = false;
- for (unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++)
+ // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
+ ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
+
+ int numComponents = gl::UniformComponentCount(uniform.type);
+ size_t baseAlignment = static_cast<size_t>(numComponents == 3 ? 4 : numComponents);
+ int matrixStride = 0;
+ int arrayStride = 0;
+
+ if (gl::IsMatrixType(uniform.type))
{
- const sh::Uniform &uniform = activeUniforms[uniformIndex];
-
- // TODO: structs
- // TODO: row major matrices
- bool isRowMajorMatrix = false;
-
- // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
- ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
-
- int numComponents = gl::UniformComponentCount(uniform.type);
- size_t baseAlignment = static_cast<size_t>(numComponents == 3 ? 4 : numComponents);
- int arrayStride = 0;
- int matrixStride = 0;
-
- if (gl::IsMatrixType(uniform.type))
- {
- numComponents = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
- baseAlignment = rx::roundUp(baseAlignment, 4u);
- matrixStride = baseAlignment;
-
- if (uniform.arraySize > 0)
- {
- const int componentGroups = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
- arrayStride = matrixStride * componentGroups;
- }
- }
- else if (uniform.arraySize > 0)
- {
- baseAlignment = rx::roundUp(baseAlignment, 4u);
- arrayStride = baseAlignment;
- }
-
- const unsigned int alignedOffset = rx::roundUp(currentOffset, baseAlignment);
-
- BlockMemberInfo memberInfo(alignedOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, isRowMajorMatrix);
- blockInfo.push_back(memberInfo);
+ numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
+ baseAlignment = rx::roundUp(baseAlignment, 4u);
+ matrixStride = baseAlignment;
if (uniform.arraySize > 0)
{
- currentOffset += arrayStride * uniform.arraySize;
- currentOffset = rx::roundUp(currentOffset, baseAlignment);
- }
- else if (gl::IsMatrixType(uniform.type))
- {
- const int componentGroups = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
- currentOffset += matrixStride * componentGroups;
- currentOffset = rx::roundUp(currentOffset, baseAlignment);
- }
- else
- {
- currentOffset += gl::UniformComponentCount(uniform.type);
+ const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
+ arrayStride = matrixStride * componentGroups;
}
}
+ else if (uniform.arraySize > 0)
+ {
+ baseAlignment = rx::roundUp(baseAlignment, 4u);
+ arrayStride = baseAlignment;
+ }
- dataSize = currentOffset * componentSize;
+ *currentOffset = rx::roundUp(*currentOffset, baseAlignment);
+
+ *matrixStrideOut = matrixStride;
+ *arrayStrideOut = arrayStride;
}
}