Clean up Program::linkUniforms.

This method previously relied on output from the D3D back-end from
ProgramImpl::link. Split the D3D-specific code into its own method,
and do the linking validation before we call link.

BUG=angleproject:1123

Change-Id: I582671e21af605af9f4451b02fc96ad29c923048
Reviewed-on: https://chromium-review.googlesource.com/293762
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index fb3449f..a041440 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -295,6 +295,11 @@
         return Error(GL_NO_ERROR);
     }
 
+    if (!linkUniforms(mInfoLog, *data.caps))
+    {
+        return Error(GL_NO_ERROR);
+    }
+
     int registers;
     std::vector<LinkedVarying> linkedVaryings;
     rx::LinkResult result =
@@ -305,12 +310,6 @@
         return result.error;
     }
 
-    if (!mProgram->linkUniforms(mInfoLog, *mData.mAttachedVertexShader,
-                                *mData.mAttachedFragmentShader, *data.caps))
-    {
-        return Error(GL_NO_ERROR);
-    }
-
     if (!linkUniformBlocks(mInfoLog, *mData.mAttachedVertexShader, *mData.mAttachedFragmentShader,
                            *data.caps))
     {
@@ -1290,6 +1289,37 @@
     return true;
 }
 
+bool Program::linkUniforms(gl::InfoLog &infoLog, const gl::Caps & /*caps*/) const
+{
+    const std::vector<sh::Uniform> &vertexUniforms   = mData.mAttachedVertexShader->getUniforms();
+    const std::vector<sh::Uniform> &fragmentUniforms = mData.mAttachedFragmentShader->getUniforms();
+
+    // Check that uniforms defined in the vertex and fragment shaders are identical
+    std::map<std::string, const sh::Uniform *> linkedUniforms;
+
+    for (const sh::Uniform &vertexUniform : vertexUniforms)
+    {
+        linkedUniforms[vertexUniform.name] = &vertexUniform;
+    }
+
+    for (const sh::Uniform &fragmentUniform : fragmentUniforms)
+    {
+        auto entry = linkedUniforms.find(fragmentUniform.name);
+        if (entry != linkedUniforms.end())
+        {
+            const sh::Uniform &vertexUniform = *entry->second;
+            const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
+            if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
+            {
+                return false;
+            }
+        }
+    }
+
+    // TODO(jmadill): check sampler uniforms with caps
+    return true;
+}
+
 bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
 {
     if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))