Add state for uniform blocks to ProgramBinary, along with loading and saving of…

Add state for uniform blocks to ProgramBinary, along with loading and saving of the new binary format. Updated Version.h with this patch. TRAC #22858 Signed-off-by: Geoff Lang Signed-off-by: Nicolas Capens Author: Jamie Madill Conflicts: src/common/version.h git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2306 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 38676dc1
#define MAJOR_VERSION 1
#define MINOR_VERSION 1
#define BUILD_VERSION 0
#define BUILD_REVISION 2181
#define BUILD_REVISION 1990
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
......
......@@ -18,4 +18,14 @@ Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int a
this->registerIndex = registerIndex;
}
BlockMemberInfo::BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
: offset(offset),
arrayStride(arrayStride),
matrixStride(matrixStride),
isRowMajorMatrix(isRowMajorMatrix)
{
}
const BlockMemberInfo BlockMemberInfo::defaultBlockInfo(-1, -1, -1, false);
}
......@@ -31,6 +31,18 @@ struct Uniform
typedef std::vector<Uniform> ActiveUniforms;
struct BlockMemberInfo
{
BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix);
int offset;
int arrayStride;
int matrixStride;
bool isRowMajorMatrix;
static const BlockMemberInfo defaultBlockInfo;
};
}
#endif // COMPILER_UNIFORM_H_
......@@ -107,6 +107,12 @@ ProgramBinary::~ProgramBinary()
delete mUniforms.back();
mUniforms.pop_back();
}
while (!mUniformBlocks.empty())
{
delete mUniformBlocks.back();
mUniformBlocks.pop_back();
}
}
unsigned int ProgramBinary::getSerial() const
......@@ -1461,13 +1467,27 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
GLenum precision;
std::string name;
unsigned int arraySize;
int blockIndex;
stream.read(&type);
stream.read(&precision);
stream.read(&name);
stream.read(&arraySize);
stream.read(&blockIndex);
int offset;
int arrayStride;
int matrixStride;
bool isRowMajorMatrix;
stream.read(&offset);
stream.read(&arrayStride);
stream.read(&matrixStride);
stream.read(&isRowMajorMatrix);
mUniforms[i] = new Uniform(type, precision, name, arraySize);
const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
mUniforms[i] = new Uniform(type, precision, name, arraySize, blockIndex, blockInfo);
stream.read(&mUniforms[i]->psRegisterIndex);
stream.read(&mUniforms[i]->vsRegisterIndex);
......@@ -1481,6 +1501,39 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
return false;
}
mUniformBlocks.resize(size);
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < size; ++uniformBlockIndex)
{
std::string name;
unsigned int elementIndex;
unsigned int dataSize;
stream.read(&name);
stream.read(&elementIndex);
stream.read(&dataSize);
mUniformBlocks[uniformBlockIndex] = new UniformBlock(name, elementIndex, dataSize);
UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
stream.read(&uniformBlock.psRegisterIndex);
stream.read(&uniformBlock.vsRegisterIndex);
size_t numMembers;
stream.read(&numMembers);
uniformBlock.memberUniformIndexes.resize(numMembers);
for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
{
stream.read(&uniformBlock.memberUniformIndexes[blockMemberIndex]);
}
}
stream.read(&size);
if (stream.error())
{
infoLog.append("Invalid program binary.");
return false;
}
mUniformIndex.resize(size);
for (unsigned int i = 0; i < size; ++i)
{
......@@ -1592,16 +1645,43 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
stream.write(mUsesPointSize);
stream.write(mUniforms.size());
for (unsigned int i = 0; i < mUniforms.size(); ++i)
for (unsigned int uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
{
const Uniform &uniform = *mUniforms[uniformIndex];
stream.write(uniform.type);
stream.write(uniform.precision);
stream.write(uniform.name);
stream.write(uniform.arraySize);
stream.write(uniform.blockIndex);
stream.write(uniform.blockInfo.offset);
stream.write(uniform.blockInfo.arrayStride);
stream.write(uniform.blockInfo.matrixStride);
stream.write(uniform.blockInfo.isRowMajorMatrix);
stream.write(uniform.psRegisterIndex);
stream.write(uniform.vsRegisterIndex);
stream.write(uniform.registerCount);
}
stream.write(mUniformBlocks.size());
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
{
stream.write(mUniforms[i]->type);
stream.write(mUniforms[i]->precision);
stream.write(mUniforms[i]->name);
stream.write(mUniforms[i]->arraySize);
const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
stream.write(mUniforms[i]->psRegisterIndex);
stream.write(mUniforms[i]->vsRegisterIndex);
stream.write(mUniforms[i]->registerCount);
stream.write(uniformBlock.name);
stream.write(uniformBlock.elementIndex);
stream.write(uniformBlock.dataSize);
stream.write(uniformBlock.memberUniformIndexes.size());
for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
{
stream.write(uniformBlock.memberUniformIndexes[blockMemberIndex]);
}
stream.write(uniformBlock.psRegisterIndex);
stream.write(uniformBlock.vsRegisterIndex);
}
stream.write(mUniformIndex.size());
......@@ -1748,9 +1828,9 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
// special case for gl_DepthRange, the only built-in uniform (also a struct)
if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange)
{
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0));
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0));
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0));
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, sh::BlockMemberInfo::defaultBlockInfo));
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, sh::BlockMemberInfo::defaultBlockInfo));
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, sh::BlockMemberInfo::defaultBlockInfo));
}
return success;
......@@ -1914,7 +1994,7 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In
}
else
{
uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize);
uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize, -1, sh::BlockMemberInfo::defaultBlockInfo);
}
if (!uniform)
......@@ -2241,17 +2321,12 @@ GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const
case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount());
case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(uniform.name.size() + 1);
case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex;
case GL_UNIFORM_BLOCK_INDEX:
case GL_UNIFORM_OFFSET:
case GL_UNIFORM_ARRAY_STRIDE:
case GL_UNIFORM_MATRIX_STRIDE:
// the default block gives a value of -1 for these parameters
return -1;
case GL_UNIFORM_IS_ROW_MAJOR:
// TODO: column/row major layout for uniform blocks
return 0;
case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset;
case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
default:
UNREACHABLE();
......
......@@ -184,6 +184,7 @@ class ProgramBinary : public RefCountObject
bool mUsesPointSize;
UniformArray mUniforms;
UniformBlockArray mUniformBlocks;
typedef std::vector<UniformLocation> UniformIndex;
UniformIndex mUniformIndex;
......
......@@ -12,17 +12,28 @@
namespace gl
{
Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize)
: type(type), precision(precision), name(name), arraySize(arraySize)
Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo)
: type(type),
precision(precision),
name(name),
arraySize(arraySize),
blockIndex(blockIndex),
blockInfo(blockInfo),
data(NULL),
dirty(true),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX),
registerCount(0)
{
int bytes = gl::UniformInternalSize(type) * elementCount();
data = new unsigned char[bytes];
memset(data, 0, bytes);
dirty = true;
psRegisterIndex = GL_INVALID_INDEX;
vsRegisterIndex = GL_INVALID_INDEX;
registerCount = VariableRowCount(type) * elementCount();
// We use data storage for default block uniforms to cache values that are sent to D3D during rendering
// Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
if (isInDefaultBlock())
{
size_t bytes = UniformInternalSize(type) * elementCount();
data = new unsigned char[bytes];
memset(data, 0, bytes);
registerCount = VariableRowCount(type) * elementCount();
}
}
Uniform::~Uniform()
......@@ -50,4 +61,33 @@ bool Uniform::isReferencedByFragmentShader() const
return psRegisterIndex != GL_INVALID_INDEX;
}
bool Uniform::isInDefaultBlock() const
{
return blockIndex == -1;
}
UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize)
: name(name),
elementIndex(elementIndex),
dataSize(dataSize),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX)
{
}
bool UniformBlock::isArrayElement() const
{
return elementIndex != GL_INVALID_INDEX;
}
bool UniformBlock::isReferencedByVertexShader() const
{
return vsRegisterIndex != GL_INVALID_INDEX;
}
bool UniformBlock::isReferencedByFragmentShader() const
{
return psRegisterIndex != GL_INVALID_INDEX;
}
}
......@@ -15,6 +15,8 @@
#include <GLES2/gl2.h>
#include "common/debug.h"
#include "angletypes.h"
#include "compiler/Uniform.h"
namespace gl
{
......@@ -22,7 +24,7 @@ namespace gl
// Helper struct representing a single shader uniform
struct Uniform
{
Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize);
Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo);
~Uniform();
......@@ -30,11 +32,14 @@ struct Uniform
unsigned int elementCount() const;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
bool isInDefaultBlock() const;
const GLenum type;
const GLenum precision;
const std::string name;
const unsigned int arraySize;
const int blockIndex;
const sh::BlockMemberInfo blockInfo;
unsigned char *data;
bool dirty;
......@@ -46,6 +51,28 @@ struct Uniform
typedef std::vector<Uniform*> UniformArray;
// Helper struct representing a single shader uniform block
struct UniformBlock
{
// use GL_INVALID_INDEX for non-array elements
UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize);
bool isArrayElement() const;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
const std::string name;
const unsigned int elementIndex;
const unsigned int dataSize;
std::vector<unsigned int> memberUniformIndexes;
unsigned int psRegisterIndex;
unsigned int vsRegisterIndex;
};
typedef std::vector<UniformBlock*> UniformBlockArray;
}
#endif // LIBGLESV2_UNIFORM_H_
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