Commit 44861c48 by Olli Etuaho Committed by Commit Bot

Clarify aliasing rules in CHROMIUM_bind_uniform_location

The CHROMIUM_bind_uniform_location spec previously had some conflicting information on when uniform location aliasing was allowed. Now the section on uniform location aliasing makes it clear that aliasing locations of two statically used uniforms is an error. This guarantees compatibility between different compiler versions that may treat a different subset of uniforms as active, depending on optimizations. It follows the spirit of GLSL ES 3.00.6 spec section 12.46, that has similar rules for attributes. The implementation is fixed to correctly follow the spec. When flattening uniforms, static use is tracked separately from activeness. BUG=angleproject:2262 TEST=angle_end2end_tests Change-Id: I570fd384064aec66ef0380a53fa01ac5e43eec5a Reviewed-on: https://chromium-review.googlesource.com/978144Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent a571f28d
......@@ -96,7 +96,7 @@ New Procedures and Functions
(MAX_VERTEX_UNIFORM_VECTORS + MAX_FRAGMENT_UNIFORM_VECTORS) * 4
or less than 0. BindUniformLocation has no effect until the program is
linked. In particular, it doesn't modify the bindings of active uniforms
linked. In particular, it doesn't modify the bindings of uniform
variables in a program that has already been linked.
The error INVALID_OPERATION is generated if name starts with the reserved
......@@ -117,10 +117,9 @@ New Procedures and Functions
It is possible for an application to bind more than one uniform name to
the same location. This is referred to as aliasing. This will only work
if only one of the aliased uniforms is active in the executable program,
or if no path through the shader consumes more than one uniform of a set
of uniforms aliased to the same location. If two statically used uniforms
in a program are bound to the name location, link must fail.
if only one of the aliased uniforms is statically used in the executable
program. If two statically used uniforms in a program are bound to the same
location, link must fail.
Errors
......@@ -139,3 +138,4 @@ Revision History
to behave like location -1.
3/9/2017 Locations set in the shader override ones set by the binding
API.
3/26/2018 Clarify that aliasing rules apply to statically used uniforms.
\ No newline at end of file
......@@ -215,8 +215,6 @@ bool UniformLinker::validateGraphicsUniforms(const Context *context, InfoLog &in
bool UniformLinker::indexUniforms(InfoLog &infoLog, const ProgramBindings &uniformLocationBindings)
{
// All the locations where another uniform can't be located.
std::set<GLuint> reservedLocations;
// Locations which have been allocated for an unused uniform.
std::set<GLuint> ignoredLocations;
......@@ -225,8 +223,7 @@ bool UniformLinker::indexUniforms(InfoLog &infoLog, const ProgramBindings &unifo
// Gather uniform locations that have been set either using the bindUniformLocation API or by
// using a location layout qualifier and check conflicts between them.
if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings,
&reservedLocations, &ignoredLocations,
&maxUniformLocation))
&ignoredLocations, &maxUniformLocation))
{
return false;
}
......@@ -311,10 +308,12 @@ bool UniformLinker::indexUniforms(InfoLog &infoLog, const ProgramBindings &unifo
bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
InfoLog &infoLog,
const ProgramBindings &uniformLocationBindings,
std::set<GLuint> *reservedLocations,
std::set<GLuint> *ignoredLocations,
int *maxUniformLocation)
{
// All the locations where another uniform can't be located.
std::set<GLuint> reservedLocations;
for (const LinkedUniform &uniform : mUniforms)
{
if (uniform.isBuiltIn())
......@@ -334,28 +333,32 @@ bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
// GLSL ES 3.10 section 4.4.3
int elementLocation = shaderLocation + arrayIndex;
*maxUniformLocation = std::max(*maxUniformLocation, elementLocation);
if (reservedLocations->find(elementLocation) != reservedLocations->end())
if (reservedLocations.find(elementLocation) != reservedLocations.end())
{
infoLog << "Multiple uniforms bound to location " << elementLocation << ".";
return false;
}
reservedLocations->insert(elementLocation);
reservedLocations.insert(elementLocation);
if (!uniform.active)
{
ignoredLocations->insert(elementLocation);
}
}
}
else if (apiBoundLocation != -1 && uniform.active)
else if (apiBoundLocation != -1 && uniform.staticUse)
{
// Only the first location is reserved even if the uniform is an array.
*maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation);
if (reservedLocations->find(apiBoundLocation) != reservedLocations->end())
if (reservedLocations.find(apiBoundLocation) != reservedLocations.end())
{
infoLog << "Multiple uniforms bound to location " << apiBoundLocation << ".";
return false;
}
reservedLocations->insert(apiBoundLocation);
reservedLocations.insert(apiBoundLocation);
if (!uniform.active)
{
ignoredLocations->insert(apiBoundLocation);
}
}
}
......@@ -364,7 +367,7 @@ bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
for (const auto &locationBinding : uniformLocationBindings)
{
GLuint location = locationBinding.second;
if (reservedLocations->find(location) == reservedLocations->end())
if (reservedLocations.find(location) == reservedLocations.end())
{
ignoredLocations->insert(location);
*maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location));
......@@ -531,7 +534,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniform(
ShaderUniformCount shaderUniformCount =
flattenUniformImpl(uniform, uniform.name, uniform.mappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType, uniform.active,
uniform.binding, uniform.offset, &location);
uniform.staticUse, uniform.binding, uniform.offset, &location);
if (uniform.active)
{
return shaderUniformCount;
......@@ -549,6 +552,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayOfStructsUniform(
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markActive,
bool markStaticUse,
int binding,
int offset,
int *location)
......@@ -565,14 +569,15 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayOfStructsUniform(
{
shaderUniformCount += flattenArrayOfStructsUniform(
uniform, arrayNestingIndex + 1u, elementName, elementMappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType, markActive, binding, offset,
location);
imageUniforms, atomicCounterUniforms, shaderType, markActive, markStaticUse,
binding, offset, location);
}
else
{
shaderUniformCount += flattenStructUniform(
uniform.fields, elementName, elementMappedName, samplerUniforms, imageUniforms,
atomicCounterUniforms, shaderType, markActive, binding, offset, location);
atomicCounterUniforms, shaderType, markActive, markStaticUse, binding, offset,
location);
}
}
return shaderUniformCount;
......@@ -587,6 +592,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenStructUniform(
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markActive,
bool markStaticUse,
int binding,
int offset,
int *location)
......@@ -597,9 +603,9 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenStructUniform(
const std::string &fieldName = namePrefix + "." + field.name;
const std::string &fieldMappedName = mappedNamePrefix + "." + field.mappedName;
shaderUniformCount +=
flattenUniformImpl(field, fieldName, fieldMappedName, samplerUniforms, imageUniforms,
atomicCounterUniforms, shaderType, markActive, -1, -1, location);
shaderUniformCount += flattenUniformImpl(field, fieldName, fieldMappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType,
markActive, markStaticUse, -1, -1, location);
}
return shaderUniformCount;
}
......@@ -613,6 +619,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayUniform(
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markActive,
bool markStaticUse,
int binding,
int offset,
int *location)
......@@ -628,9 +635,10 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayUniform(
const std::string elementName = namePrefix + ArrayString(arrayElement);
const std::string elementMappedName = mappedNamePrefix + ArrayString(arrayElement);
shaderUniformCount += flattenUniformImpl(
uniformElement, elementName, elementMappedName, samplerUniforms, imageUniforms,
atomicCounterUniforms, shaderType, markActive, binding, offset, location);
shaderUniformCount +=
flattenUniformImpl(uniformElement, elementName, elementMappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType, markActive,
markStaticUse, binding, offset, location);
}
return shaderUniformCount;
}
......@@ -644,6 +652,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markActive,
bool markStaticUse,
int binding,
int offset,
int *location)
......@@ -655,15 +664,17 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
{
if (uniform.isArray())
{
shaderUniformCount += flattenArrayOfStructsUniform(
uniform, 0u, fullName, fullMappedName, samplerUniforms, imageUniforms,
atomicCounterUniforms, shaderType, markActive, binding, offset, location);
shaderUniformCount +=
flattenArrayOfStructsUniform(uniform, 0u, fullName, fullMappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType,
markActive, markStaticUse, binding, offset, location);
}
else
{
shaderUniformCount += flattenStructUniform(
uniform.fields, fullName, fullMappedName, samplerUniforms, imageUniforms,
atomicCounterUniforms, shaderType, markActive, binding, offset, location);
shaderUniformCount +=
flattenStructUniform(uniform.fields, fullName, fullMappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType, markActive,
markStaticUse, binding, offset, location);
}
return shaderUniformCount;
}
......@@ -674,7 +685,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
// arrays), a separate entry will be generated for each active array element"
return flattenArrayUniform(uniform, fullName, fullMappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType, markActive,
binding, offset, location);
markStaticUse, binding, offset, location);
}
// Not a struct
......@@ -726,6 +737,10 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
existingUniform->active = true;
existingUniform->setActive(shaderType, true);
}
if (markStaticUse)
{
existingUniform->staticUse = true;
}
}
else
{
......@@ -735,6 +750,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
sh::BlockMemberInfo::getDefaultBlockInfo());
linkedUniform.mappedName = fullMappedNameWithArrayIndex;
linkedUniform.active = markActive;
linkedUniform.staticUse = markStaticUse;
linkedUniform.flattenedOffsetInParentArrays = uniform.flattenedOffsetInParentArrays;
if (markActive)
{
......
......@@ -115,6 +115,7 @@ class UniformLinker final : angle::NonCopyable
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markActive,
bool markStaticUse,
int binding,
int offset,
int *location);
......@@ -127,6 +128,7 @@ class UniformLinker final : angle::NonCopyable
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markActive,
bool markStaticUse,
int binding,
int offset,
int *location);
......@@ -139,12 +141,13 @@ class UniformLinker final : angle::NonCopyable
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markActive,
bool markStaticUse,
int binding,
int offset,
int *location);
// markActive is given as a separate parameter because it is tracked here at struct
// granularity.
// markActive and markStaticUse are given as separate parameters because they are tracked here
// at struct granularity.
ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform,
const std::string &fullName,
const std::string &fullMappedName,
......@@ -153,6 +156,7 @@ class UniformLinker final : angle::NonCopyable
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markActive,
bool markStaticUse,
int binding,
int offset,
int *location);
......@@ -160,7 +164,6 @@ class UniformLinker final : angle::NonCopyable
bool indexUniforms(InfoLog &infoLog, const ProgramBindings &uniformLocationBindings);
bool gatherUniformLocationsAndCheckConflicts(InfoLog &infoLog,
const ProgramBindings &uniformLocationBindings,
std::set<GLuint> *reservedLocations,
std::set<GLuint> *ignoredLocations,
int *maxUniformLocation);
void pruneUnusedUniforms();
......
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