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 ...@@ -96,7 +96,7 @@ New Procedures and Functions
(MAX_VERTEX_UNIFORM_VECTORS + MAX_FRAGMENT_UNIFORM_VECTORS) * 4 (MAX_VERTEX_UNIFORM_VECTORS + MAX_FRAGMENT_UNIFORM_VECTORS) * 4
or less than 0. BindUniformLocation has no effect until the program is 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. variables in a program that has already been linked.
The error INVALID_OPERATION is generated if name starts with the reserved The error INVALID_OPERATION is generated if name starts with the reserved
...@@ -117,10 +117,9 @@ New Procedures and Functions ...@@ -117,10 +117,9 @@ New Procedures and Functions
It is possible for an application to bind more than one uniform name to 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 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, if only one of the aliased uniforms is statically used in the executable
or if no path through the shader consumes more than one uniform of a set program. If two statically used uniforms in a program are bound to the same
of uniforms aliased to the same location. If two statically used uniforms location, link must fail.
in a program are bound to the name location, link must fail.
Errors Errors
...@@ -139,3 +138,4 @@ Revision History ...@@ -139,3 +138,4 @@ Revision History
to behave like location -1. to behave like location -1.
3/9/2017 Locations set in the shader override ones set by the binding 3/9/2017 Locations set in the shader override ones set by the binding
API. 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 ...@@ -215,8 +215,6 @@ bool UniformLinker::validateGraphicsUniforms(const Context *context, InfoLog &in
bool UniformLinker::indexUniforms(InfoLog &infoLog, const ProgramBindings &uniformLocationBindings) 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. // Locations which have been allocated for an unused uniform.
std::set<GLuint> ignoredLocations; std::set<GLuint> ignoredLocations;
...@@ -225,8 +223,7 @@ bool UniformLinker::indexUniforms(InfoLog &infoLog, const ProgramBindings &unifo ...@@ -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 // Gather uniform locations that have been set either using the bindUniformLocation API or by
// using a location layout qualifier and check conflicts between them. // using a location layout qualifier and check conflicts between them.
if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings, if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings,
&reservedLocations, &ignoredLocations, &ignoredLocations, &maxUniformLocation))
&maxUniformLocation))
{ {
return false; return false;
} }
...@@ -311,10 +308,12 @@ bool UniformLinker::indexUniforms(InfoLog &infoLog, const ProgramBindings &unifo ...@@ -311,10 +308,12 @@ bool UniformLinker::indexUniforms(InfoLog &infoLog, const ProgramBindings &unifo
bool UniformLinker::gatherUniformLocationsAndCheckConflicts( bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
InfoLog &infoLog, InfoLog &infoLog,
const ProgramBindings &uniformLocationBindings, const ProgramBindings &uniformLocationBindings,
std::set<GLuint> *reservedLocations,
std::set<GLuint> *ignoredLocations, std::set<GLuint> *ignoredLocations,
int *maxUniformLocation) int *maxUniformLocation)
{ {
// All the locations where another uniform can't be located.
std::set<GLuint> reservedLocations;
for (const LinkedUniform &uniform : mUniforms) for (const LinkedUniform &uniform : mUniforms)
{ {
if (uniform.isBuiltIn()) if (uniform.isBuiltIn())
...@@ -334,28 +333,32 @@ bool UniformLinker::gatherUniformLocationsAndCheckConflicts( ...@@ -334,28 +333,32 @@ bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
// GLSL ES 3.10 section 4.4.3 // GLSL ES 3.10 section 4.4.3
int elementLocation = shaderLocation + arrayIndex; int elementLocation = shaderLocation + arrayIndex;
*maxUniformLocation = std::max(*maxUniformLocation, elementLocation); *maxUniformLocation = std::max(*maxUniformLocation, elementLocation);
if (reservedLocations->find(elementLocation) != reservedLocations->end()) if (reservedLocations.find(elementLocation) != reservedLocations.end())
{ {
infoLog << "Multiple uniforms bound to location " << elementLocation << "."; infoLog << "Multiple uniforms bound to location " << elementLocation << ".";
return false; return false;
} }
reservedLocations->insert(elementLocation); reservedLocations.insert(elementLocation);
if (!uniform.active) if (!uniform.active)
{ {
ignoredLocations->insert(elementLocation); 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. // Only the first location is reserved even if the uniform is an array.
*maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation); *maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation);
if (reservedLocations->find(apiBoundLocation) != reservedLocations->end()) if (reservedLocations.find(apiBoundLocation) != reservedLocations.end())
{ {
infoLog << "Multiple uniforms bound to location " << apiBoundLocation << "."; infoLog << "Multiple uniforms bound to location " << apiBoundLocation << ".";
return false; return false;
} }
reservedLocations->insert(apiBoundLocation); reservedLocations.insert(apiBoundLocation);
if (!uniform.active)
{
ignoredLocations->insert(apiBoundLocation);
}
} }
} }
...@@ -364,7 +367,7 @@ bool UniformLinker::gatherUniformLocationsAndCheckConflicts( ...@@ -364,7 +367,7 @@ bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
for (const auto &locationBinding : uniformLocationBindings) for (const auto &locationBinding : uniformLocationBindings)
{ {
GLuint location = locationBinding.second; GLuint location = locationBinding.second;
if (reservedLocations->find(location) == reservedLocations->end()) if (reservedLocations.find(location) == reservedLocations.end())
{ {
ignoredLocations->insert(location); ignoredLocations->insert(location);
*maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location)); *maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location));
...@@ -531,7 +534,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniform( ...@@ -531,7 +534,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniform(
ShaderUniformCount shaderUniformCount = ShaderUniformCount shaderUniformCount =
flattenUniformImpl(uniform, uniform.name, uniform.mappedName, samplerUniforms, flattenUniformImpl(uniform, uniform.name, uniform.mappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType, uniform.active, imageUniforms, atomicCounterUniforms, shaderType, uniform.active,
uniform.binding, uniform.offset, &location); uniform.staticUse, uniform.binding, uniform.offset, &location);
if (uniform.active) if (uniform.active)
{ {
return shaderUniformCount; return shaderUniformCount;
...@@ -549,6 +552,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayOfStructsUniform( ...@@ -549,6 +552,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayOfStructsUniform(
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType, GLenum shaderType,
bool markActive, bool markActive,
bool markStaticUse,
int binding, int binding,
int offset, int offset,
int *location) int *location)
...@@ -565,14 +569,15 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayOfStructsUniform( ...@@ -565,14 +569,15 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayOfStructsUniform(
{ {
shaderUniformCount += flattenArrayOfStructsUniform( shaderUniformCount += flattenArrayOfStructsUniform(
uniform, arrayNestingIndex + 1u, elementName, elementMappedName, samplerUniforms, uniform, arrayNestingIndex + 1u, elementName, elementMappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType, markActive, binding, offset, imageUniforms, atomicCounterUniforms, shaderType, markActive, markStaticUse,
location); binding, offset, location);
} }
else else
{ {
shaderUniformCount += flattenStructUniform( shaderUniformCount += flattenStructUniform(
uniform.fields, elementName, elementMappedName, samplerUniforms, imageUniforms, uniform.fields, elementName, elementMappedName, samplerUniforms, imageUniforms,
atomicCounterUniforms, shaderType, markActive, binding, offset, location); atomicCounterUniforms, shaderType, markActive, markStaticUse, binding, offset,
location);
} }
} }
return shaderUniformCount; return shaderUniformCount;
...@@ -587,6 +592,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenStructUniform( ...@@ -587,6 +592,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenStructUniform(
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType, GLenum shaderType,
bool markActive, bool markActive,
bool markStaticUse,
int binding, int binding,
int offset, int offset,
int *location) int *location)
...@@ -597,9 +603,9 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenStructUniform( ...@@ -597,9 +603,9 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenStructUniform(
const std::string &fieldName = namePrefix + "." + field.name; const std::string &fieldName = namePrefix + "." + field.name;
const std::string &fieldMappedName = mappedNamePrefix + "." + field.mappedName; const std::string &fieldMappedName = mappedNamePrefix + "." + field.mappedName;
shaderUniformCount += shaderUniformCount += flattenUniformImpl(field, fieldName, fieldMappedName, samplerUniforms,
flattenUniformImpl(field, fieldName, fieldMappedName, samplerUniforms, imageUniforms, imageUniforms, atomicCounterUniforms, shaderType,
atomicCounterUniforms, shaderType, markActive, -1, -1, location); markActive, markStaticUse, -1, -1, location);
} }
return shaderUniformCount; return shaderUniformCount;
} }
...@@ -613,6 +619,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayUniform( ...@@ -613,6 +619,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayUniform(
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType, GLenum shaderType,
bool markActive, bool markActive,
bool markStaticUse,
int binding, int binding,
int offset, int offset,
int *location) int *location)
...@@ -628,9 +635,10 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayUniform( ...@@ -628,9 +635,10 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenArrayUniform(
const std::string elementName = namePrefix + ArrayString(arrayElement); const std::string elementName = namePrefix + ArrayString(arrayElement);
const std::string elementMappedName = mappedNamePrefix + ArrayString(arrayElement); const std::string elementMappedName = mappedNamePrefix + ArrayString(arrayElement);
shaderUniformCount += flattenUniformImpl( shaderUniformCount +=
uniformElement, elementName, elementMappedName, samplerUniforms, imageUniforms, flattenUniformImpl(uniformElement, elementName, elementMappedName, samplerUniforms,
atomicCounterUniforms, shaderType, markActive, binding, offset, location); imageUniforms, atomicCounterUniforms, shaderType, markActive,
markStaticUse, binding, offset, location);
} }
return shaderUniformCount; return shaderUniformCount;
} }
...@@ -644,6 +652,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl( ...@@ -644,6 +652,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType, GLenum shaderType,
bool markActive, bool markActive,
bool markStaticUse,
int binding, int binding,
int offset, int offset,
int *location) int *location)
...@@ -655,15 +664,17 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl( ...@@ -655,15 +664,17 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
{ {
if (uniform.isArray()) if (uniform.isArray())
{ {
shaderUniformCount += flattenArrayOfStructsUniform( shaderUniformCount +=
uniform, 0u, fullName, fullMappedName, samplerUniforms, imageUniforms, flattenArrayOfStructsUniform(uniform, 0u, fullName, fullMappedName, samplerUniforms,
atomicCounterUniforms, shaderType, markActive, binding, offset, location); imageUniforms, atomicCounterUniforms, shaderType,
markActive, markStaticUse, binding, offset, location);
} }
else else
{ {
shaderUniformCount += flattenStructUniform( shaderUniformCount +=
uniform.fields, fullName, fullMappedName, samplerUniforms, imageUniforms, flattenStructUniform(uniform.fields, fullName, fullMappedName, samplerUniforms,
atomicCounterUniforms, shaderType, markActive, binding, offset, location); imageUniforms, atomicCounterUniforms, shaderType, markActive,
markStaticUse, binding, offset, location);
} }
return shaderUniformCount; return shaderUniformCount;
} }
...@@ -674,7 +685,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl( ...@@ -674,7 +685,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
// arrays), a separate entry will be generated for each active array element" // arrays), a separate entry will be generated for each active array element"
return flattenArrayUniform(uniform, fullName, fullMappedName, samplerUniforms, return flattenArrayUniform(uniform, fullName, fullMappedName, samplerUniforms,
imageUniforms, atomicCounterUniforms, shaderType, markActive, imageUniforms, atomicCounterUniforms, shaderType, markActive,
binding, offset, location); markStaticUse, binding, offset, location);
} }
// Not a struct // Not a struct
...@@ -726,6 +737,10 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl( ...@@ -726,6 +737,10 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
existingUniform->active = true; existingUniform->active = true;
existingUniform->setActive(shaderType, true); existingUniform->setActive(shaderType, true);
} }
if (markStaticUse)
{
existingUniform->staticUse = true;
}
} }
else else
{ {
...@@ -735,6 +750,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl( ...@@ -735,6 +750,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
sh::BlockMemberInfo::getDefaultBlockInfo()); sh::BlockMemberInfo::getDefaultBlockInfo());
linkedUniform.mappedName = fullMappedNameWithArrayIndex; linkedUniform.mappedName = fullMappedNameWithArrayIndex;
linkedUniform.active = markActive; linkedUniform.active = markActive;
linkedUniform.staticUse = markStaticUse;
linkedUniform.flattenedOffsetInParentArrays = uniform.flattenedOffsetInParentArrays; linkedUniform.flattenedOffsetInParentArrays = uniform.flattenedOffsetInParentArrays;
if (markActive) if (markActive)
{ {
......
...@@ -115,6 +115,7 @@ class UniformLinker final : angle::NonCopyable ...@@ -115,6 +115,7 @@ class UniformLinker final : angle::NonCopyable
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType, GLenum shaderType,
bool markActive, bool markActive,
bool markStaticUse,
int binding, int binding,
int offset, int offset,
int *location); int *location);
...@@ -127,6 +128,7 @@ class UniformLinker final : angle::NonCopyable ...@@ -127,6 +128,7 @@ class UniformLinker final : angle::NonCopyable
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType, GLenum shaderType,
bool markActive, bool markActive,
bool markStaticUse,
int binding, int binding,
int offset, int offset,
int *location); int *location);
...@@ -139,12 +141,13 @@ class UniformLinker final : angle::NonCopyable ...@@ -139,12 +141,13 @@ class UniformLinker final : angle::NonCopyable
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType, GLenum shaderType,
bool markActive, bool markActive,
bool markStaticUse,
int binding, int binding,
int offset, int offset,
int *location); int *location);
// markActive is given as a separate parameter because it is tracked here at struct // markActive and markStaticUse are given as separate parameters because they are tracked here
// granularity. // at struct granularity.
ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform, ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform,
const std::string &fullName, const std::string &fullName,
const std::string &fullMappedName, const std::string &fullMappedName,
...@@ -153,6 +156,7 @@ class UniformLinker final : angle::NonCopyable ...@@ -153,6 +156,7 @@ class UniformLinker final : angle::NonCopyable
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType, GLenum shaderType,
bool markActive, bool markActive,
bool markStaticUse,
int binding, int binding,
int offset, int offset,
int *location); int *location);
...@@ -160,7 +164,6 @@ class UniformLinker final : angle::NonCopyable ...@@ -160,7 +164,6 @@ class UniformLinker final : angle::NonCopyable
bool indexUniforms(InfoLog &infoLog, const ProgramBindings &uniformLocationBindings); bool indexUniforms(InfoLog &infoLog, const ProgramBindings &uniformLocationBindings);
bool gatherUniformLocationsAndCheckConflicts(InfoLog &infoLog, bool gatherUniformLocationsAndCheckConflicts(InfoLog &infoLog,
const ProgramBindings &uniformLocationBindings, const ProgramBindings &uniformLocationBindings,
std::set<GLuint> *reservedLocations,
std::set<GLuint> *ignoredLocations, std::set<GLuint> *ignoredLocations,
int *maxUniformLocation); int *maxUniformLocation);
void pruneUnusedUniforms(); 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