Add logic to compute the size and offsets of interface blocks stored in shared…

Add logic to compute the size and offsets of interface blocks stored in shared (packed) and standard layouts. The shared layout follows the standard HLSL packing rules for optimal shader performance. TRAC #22930 Signed-off-by: Nicolas Capens Signed-off-by: Geoff Lang Author: Jamie Madill git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2343 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent a2ecfccc
...@@ -26,6 +26,7 @@ struct Color; ...@@ -26,6 +26,7 @@ struct Color;
int UniformComponentCount(GLenum type); int UniformComponentCount(GLenum type);
GLenum UniformComponentType(GLenum type); GLenum UniformComponentType(GLenum type);
size_t UniformComponentSize(GLenum type);
size_t UniformInternalSize(GLenum type); size_t UniformInternalSize(GLenum type);
size_t UniformExternalSize(GLenum type); size_t UniformExternalSize(GLenum type);
GLenum UniformBoolVectorType(GLenum type); GLenum UniformBoolVectorType(GLenum type);
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
// //
#include "compiler/Uniform.h" #include "compiler/Uniform.h"
#include "common/mathutil.h"
#include "common/utilities.h"
namespace sh namespace sh
{ {
...@@ -35,4 +37,147 @@ InterfaceBlock::InterfaceBlock(const char *name, unsigned int arraySize, unsigne ...@@ -35,4 +37,147 @@ InterfaceBlock::InterfaceBlock(const char *name, unsigned int arraySize, unsigne
{ {
} }
// Use the same layout for packed and shared
void InterfaceBlock::setSharedBlockLayout()
{
setPackedBlockLayout();
}
// 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()
{
const size_t componentSize = 4;
const unsigned int registerSize = 4;
unsigned int currentOffset = 0;
blockInfo.clear();
for (unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++)
{
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 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;
}
else if (gl::IsMatrixType(uniform.type))
{
const int componentGroups = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
currentOffset += matrixStride * componentGroups;
}
else
{
currentOffset += gl::UniformComponentCount(uniform.type);
}
}
dataSize = currentOffset * componentSize;
}
void InterfaceBlock::setStandardBlockLayout()
{
const size_t componentSize = 4;
unsigned int currentOffset = 0;
blockInfo.clear();
for (unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++)
{
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);
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);
}
}
dataSize = currentOffset * componentSize;
}
} }
...@@ -56,6 +56,10 @@ struct InterfaceBlock ...@@ -56,6 +56,10 @@ struct InterfaceBlock
std::vector<BlockMemberInfo> blockInfo; std::vector<BlockMemberInfo> blockInfo;
unsigned int registerIndex; unsigned int registerIndex;
void setSharedBlockLayout();
void setPackedBlockLayout();
void setStandardBlockLayout();
}; };
typedef std::vector<InterfaceBlock> ActiveInterfaceBlocks; typedef std::vector<InterfaceBlock> ActiveInterfaceBlocks;
......
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