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)
stream.read(&mUniforms[i]->psRegisterIndex);
stream.read(&mUniforms[i]->vsRegisterIndex);
stream.read(&mUniforms[i]->registerCount);
stream.read(&mUniforms[i]->registerElement);
}
stream.read(&size);
......@@ -1898,6 +1899,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
stream.write(uniform.psRegisterIndex);
stream.write(uniform.vsRegisterIndex);
stream.write(uniform.registerCount);
stream.write(uniform.registerElement);
}
stream.write(mUniformBlocks.size());
......
......@@ -23,13 +23,14 @@ Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigne
dirty(true),
psRegisterIndex(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
// Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
if (isInDefaultBlock())
{
size_t bytes = UniformInternalSize(type) * elementCount();
size_t bytes = dataSize();
data = new unsigned char[bytes];
memset(data, 0, bytes);
registerCount = VariableRowCount(type) * elementCount();
......@@ -66,6 +67,11 @@ bool Uniform::isInDefaultBlock() const
return blockIndex == -1;
}
size_t Uniform::dataSize() const
{
return UniformInternalSize(type) * elementCount();
}
UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize)
: name(name),
elementIndex(elementIndex),
......
......@@ -33,6 +33,7 @@ struct Uniform
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
bool isInDefaultBlock() const;
size_t dataSize() const;
const GLenum type;
const GLenum precision;
......@@ -47,6 +48,10 @@ struct Uniform
unsigned int psRegisterIndex;
unsigned int vsRegisterIndex;
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;
......
......@@ -1442,20 +1442,31 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra
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))
{
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)
{
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)
{
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