Commit 5b085dc3 by Jamie Madill

Add a field to uniforms to track which element within a register the uniform should be uploaded to.

This is necessary to support HLSL-backed uniform structs. TRAC #23750 Signed-off-by: Geoff Lang Signed-off-by: Nicolas Capens
parent 28167c62
...@@ -1725,6 +1725,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) ...@@ -1725,6 +1725,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
stream.read(&mUniforms[i]->psRegisterIndex); stream.read(&mUniforms[i]->psRegisterIndex);
stream.read(&mUniforms[i]->vsRegisterIndex); stream.read(&mUniforms[i]->vsRegisterIndex);
stream.read(&mUniforms[i]->registerCount); stream.read(&mUniforms[i]->registerCount);
stream.read(&mUniforms[i]->registerElement);
} }
stream.read(&size); stream.read(&size);
...@@ -1898,6 +1899,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) ...@@ -1898,6 +1899,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
stream.write(uniform.psRegisterIndex); stream.write(uniform.psRegisterIndex);
stream.write(uniform.vsRegisterIndex); stream.write(uniform.vsRegisterIndex);
stream.write(uniform.registerCount); stream.write(uniform.registerCount);
stream.write(uniform.registerElement);
} }
stream.write(mUniformBlocks.size()); stream.write(mUniformBlocks.size());
......
...@@ -23,13 +23,14 @@ Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigne ...@@ -23,13 +23,14 @@ Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigne
dirty(true), dirty(true),
psRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX), vsRegisterIndex(GL_INVALID_INDEX),
registerCount(0) registerCount(0),
registerElement(0)
{ {
// We use data storage for default block uniforms to cache values that are sent to D3D during rendering // 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) // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
if (isInDefaultBlock()) if (isInDefaultBlock())
{ {
size_t bytes = UniformInternalSize(type) * elementCount(); size_t bytes = dataSize();
data = new unsigned char[bytes]; data = new unsigned char[bytes];
memset(data, 0, bytes); memset(data, 0, bytes);
registerCount = VariableRowCount(type) * elementCount(); registerCount = VariableRowCount(type) * elementCount();
...@@ -66,6 +67,11 @@ bool Uniform::isInDefaultBlock() const ...@@ -66,6 +67,11 @@ bool Uniform::isInDefaultBlock() const
return blockIndex == -1; return blockIndex == -1;
} }
size_t Uniform::dataSize() const
{
return UniformInternalSize(type) * elementCount();
}
UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize) UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize)
: name(name), : name(name),
elementIndex(elementIndex), elementIndex(elementIndex),
......
...@@ -33,6 +33,7 @@ struct Uniform ...@@ -33,6 +33,7 @@ struct Uniform
bool isReferencedByVertexShader() const; bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const; bool isReferencedByFragmentShader() const;
bool isInDefaultBlock() const; bool isInDefaultBlock() const;
size_t dataSize() const;
const GLenum type; const GLenum type;
const GLenum precision; const GLenum precision;
...@@ -47,6 +48,10 @@ struct Uniform ...@@ -47,6 +48,10 @@ struct Uniform
unsigned int psRegisterIndex; unsigned int psRegisterIndex;
unsigned int vsRegisterIndex; unsigned int vsRegisterIndex;
unsigned int registerCount; unsigned int registerCount;
// Register "elements" are used for uniform structs in ES3, to appropriately identify single uniforms
// inside aggregate types, which are packed according C-like structure rules.
unsigned int registerElement;
}; };
typedef std::vector<Uniform*> UniformArray; typedef std::vector<Uniform*> UniformArray;
......
...@@ -1442,20 +1442,31 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra ...@@ -1442,20 +1442,31 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra
mapPS = (float(*)[4])map.pData; mapPS = (float(*)[4])map.pData;
} }
for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) for (size_t uniformIndex = 0; uniformIndex < uniformArray->size(); uniformIndex++)
{ {
gl::Uniform *uniform = *uniform_iterator; gl::Uniform *uniform = (*uniformArray)[uniformIndex];
if (!gl::IsSampler(uniform->type)) if (!gl::IsSampler(uniform->type))
{ {
unsigned int componentCount = (4 - uniform->registerElement);
// we always assume that uniforms from structs are arranged in struct order in our uniforms list. otherwise we would
// overwrite previously written regions of memory.
if (uniformIndex > 0)
{
gl::Uniform *previousUniform = (*uniformArray)[uniformIndex-1];
ASSERT(!uniform->isReferencedByVertexShader() || previousUniform->vsRegisterIndex != uniform->vsRegisterIndex || uniform->registerElement > previousUniform->registerElement);
ASSERT(!uniform->isReferencedByFragmentShader() || previousUniform->psRegisterIndex != uniform->psRegisterIndex || uniform->registerElement > previousUniform->registerElement);
}
if (uniform->isReferencedByVertexShader() && mapVS) if (uniform->isReferencedByVertexShader() && mapVS)
{ {
memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount);
} }
if (uniform->isReferencedByFragmentShader() && mapPS) if (uniform->isReferencedByFragmentShader() && mapPS)
{ {
memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount);
} }
} }
......
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