Implement location layout qualifier for uniforms
This is a complete implementation of the uniform location layout
qualifier. Uniform location set in the shader is plumbed to shader
linking, which does several link-time checks for conflicts and
recursively applies the location to struct members.
Validate that location is consistent as specified in the table in
section 9.2.1 of the ESSL 3.10.4 spec. The location set in the shader
overrides the one set via the CHROMIUM_bind_uniform_location API.
Location conflicts must be checked even if the uniforms are not
statically used. Because of this unused uniforms are now recorded
during uniform linking. After linking checks are done, unused uniforms
are pruned from the program state.
Location is validated against the maximum number of uniform locations
at compile time as specified in section 4.4.3 of the ESSL 3.10.4 spec.
All dEQP uniform location tests don't yet pass due to unrelated bugs.
BUG=angleproject:1442
TEST=angle_end2end_tests, dEQP-GLES31.functional.uniform_location.*
Change-Id: I1f968e971f521fbc804b01e1a7c2b4d14f24d20f
Reviewed-on: https://chromium-review.googlesource.com/447942
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index cbf9718..f2b28fa 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -211,7 +211,6 @@
const std::vector<UniformBlock> &getUniformBlocks() const { return mUniformBlocks; }
const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
- const LinkedUniform *getUniformByName(const std::string &name) const;
GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndexFromName(const std::string &name) const;
GLuint getUniformIndexFromLocation(GLint location) const;
@@ -446,9 +445,19 @@
InfoLog &infoLog) const;
bool linkUniformBlocks(InfoLog &infoLog, const Caps &caps);
bool linkVaryings(InfoLog &infoLog) const;
- bool validateVertexAndFragmentUniforms(InfoLog &infoLog) const;
+
bool linkUniforms(InfoLog &infoLog, const Caps &caps, const Bindings &uniformLocationBindings);
- bool indexUniforms(InfoLog &infoLog, const Caps &caps, const Bindings &uniformLocationBindings);
+ bool validateVertexAndFragmentUniforms(InfoLog &infoLog) const;
+ bool indexUniforms(InfoLog &infoLog, const Bindings &uniformLocationBindings);
+ bool gatherUniformLocationsAndCheckConflicts(InfoLog &infoLog,
+ const Bindings &uniformLocationBindings,
+ std::set<GLuint> *reservedLocations,
+ std::set<GLuint> *ignoredLocations,
+ int *maxUniformLocation);
+ void pruneUnusedUniforms();
+
+ void updateSamplerBindings();
+
bool areMatchingInterfaceBlocks(InfoLog &infoLog,
const sh::InterfaceBlock &vertexInterfaceBlock,
const sh::InterfaceBlock &fragmentInterfaceBlock) const;
@@ -501,10 +510,17 @@
unsigned int samplerCount;
};
- VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform,
- const std::string &fullName,
+ VectorAndSamplerCount flattenUniform(const sh::Uniform &uniform,
std::vector<LinkedUniform> *samplerUniforms);
+ // staticUse is given as a separate parameter because it is tracked here at struct granularity.
+ VectorAndSamplerCount flattenUniformImpl(const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ std::vector<LinkedUniform> *samplerUniforms,
+ bool markStaticUse,
+ int binding,
+ int *location);
+
void gatherInterfaceBlockInfo();
template <typename VarT>
void defineUniformBlockMembers(const std::vector<VarT> &fields,