Make TF Feedback buffer mode a GL-level variable.

Don't query this as an Impl method, since it exists on the GL level.
Also some related refactorings and cleanups.

BUG=angleproject:1123

Change-Id: I3610bc0db2bcaa96408506e06a65a2f4dab93150
Reviewed-on: https://chromium-review.googlesource.com/293761
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 38ade23..fb3449f 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -290,11 +290,15 @@
         return Error(GL_NO_ERROR);
     }
 
+    if (!linkVaryings(mInfoLog, mData.mAttachedVertexShader, mData.mAttachedFragmentShader))
+    {
+        return Error(GL_NO_ERROR);
+    }
+
     int registers;
     std::vector<LinkedVarying> linkedVaryings;
     rx::LinkResult result =
         mProgram->link(data, mInfoLog, mData.mAttachedFragmentShader, mData.mAttachedVertexShader,
-                       mData.mTransformFeedbackVaryings, mData.mTransformFeedbackBufferMode,
                        &registers, &linkedVaryings, &mOutputVariables);
     if (result.error.isError() || !result.linkSuccess)
     {
@@ -314,9 +318,7 @@
     }
 
     if (!gatherTransformFeedbackLinkedVaryings(
-            mInfoLog, linkedVaryings, mData.mTransformFeedbackVaryings,
-            mData.mTransformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(),
-            *data.caps))
+            mInfoLog, linkedVaryings, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps))
     {
         return Error(GL_NO_ERROR);
     }
@@ -434,6 +436,8 @@
         mProgram->setShaderAttribute(attribIndex, type, precision, name, arraySize, location);
     }
 
+    stream.readInt(&mData.mTransformFeedbackBufferMode);
+
     rx::LinkResult result = mProgram->load(mInfoLog, &stream);
     if (result.error.isError() || !result.linkSuccess)
     {
@@ -478,6 +482,8 @@
         stream.writeInt(attrib.location);
     }
 
+    stream.writeInt(mData.mTransformFeedbackBufferMode);
+
     gl::Error error = mProgram->save(&stream);
     if (error.isError())
     {
@@ -1238,48 +1244,49 @@
     return mData.mTransformFeedbackBufferMode;
 }
 
-bool Program::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader)
+// static
+bool Program::linkVaryings(InfoLog &infoLog,
+                           const Shader *vertexShader,
+                           const Shader *fragmentShader)
 {
-    std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
-    std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
+    const std::vector<PackedVarying> &vertexVaryings   = vertexShader->getVaryings();
+    const std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
 
-    for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++)
+    for (const PackedVarying &output : fragmentVaryings)
     {
-        PackedVarying *input = &fragmentVaryings[fragVaryingIndex];
         bool matched = false;
 
         // Built-in varyings obey special rules
-        if (input->isBuiltIn())
+        if (output.isBuiltIn())
         {
             continue;
         }
 
-        for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
+        for (const PackedVarying &input : vertexVaryings)
         {
-            PackedVarying *output = &vertexVaryings[vertVaryingIndex];
-            if (output->name == input->name)
+            if (output.name == input.name)
             {
-                if (!linkValidateVaryings(infoLog, output->name, *input, *output))
+                ASSERT(!input.isBuiltIn());
+                if (!linkValidateVaryings(infoLog, output.name, input, output))
                 {
                     return false;
                 }
 
-                output->registerIndex = input->registerIndex;
-                output->columnIndex = input->columnIndex;
-
                 matched = true;
                 break;
             }
         }
 
         // We permit unmatched, unreferenced varyings
-        if (!matched && input->staticUse)
+        if (!matched && output.staticUse)
         {
-            infoLog << "Fragment varying " << input->name << " does not match any vertex varying";
+            infoLog << "Fragment varying " << output.name << " does not match any vertex varying";
             return false;
         }
     }
 
+    // TODO(jmadill): verify no unmatched vertex varyings?
+
     return true;
 }
 
@@ -1583,8 +1590,6 @@
 }
 
 bool Program::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
-                                                    const std::vector<std::string> &transformFeedbackVaryingNames,
-                                                    GLenum transformFeedbackBufferMode,
                                                     std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
                                                     const Caps &caps) const
 {
@@ -1592,12 +1597,12 @@
 
     // Gather the linked varyings that are used for transform feedback, they should all exist.
     outTransformFeedbackLinkedVaryings->clear();
-    for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++)
+    for (size_t i = 0; i < mData.mTransformFeedbackVaryings.size(); i++)
     {
         bool found = false;
         for (size_t j = 0; j < linkedVaryings.size(); j++)
         {
-            if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name)
+            if (mData.mTransformFeedbackVaryings[i] == linkedVaryings[j].name)
             {
                 for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++)
                 {
@@ -1610,7 +1615,7 @@
                 }
 
                 size_t componentCount = linkedVaryings[j].semanticIndexCount * 4;
-                if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
+                if (mData.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
                     componentCount > caps.maxTransformFeedbackSeparateComponents)
                 {
                     infoLog << "Transform feedback varying's " << linkedVaryings[j].name
@@ -1633,7 +1638,7 @@
         UNUSED_ASSERTION_VARIABLE(found);
     }
 
-    if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
+    if (mData.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
         totalComponents > caps.maxTransformFeedbackInterleavedComponents)
     {
         infoLog << "Transform feedback varying total components (" << totalComponents
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index 0724754..84e891f 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -170,6 +170,11 @@
 
         const Shader *getAttachedVertexShader() const { return mAttachedVertexShader; }
         const Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; }
+        const std::vector<std::string> &getTransformFeedbackVaryings() const
+        {
+            return mTransformFeedbackVaryings;
+        }
+        GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
 
       private:
         friend class Program;
@@ -281,7 +286,6 @@
     GLsizei getTransformFeedbackVaryingMaxLength() const;
     GLenum getTransformFeedbackBufferMode() const;
 
-    static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader);
     static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
     static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
 
@@ -305,6 +309,9 @@
                         const AttributeBindings &attributeBindings,
                         const Shader *vertexShader);
     bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
+    static bool linkVaryings(InfoLog &infoLog,
+                             const Shader *vertexShader,
+                             const Shader *fragmentShader);
     bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
                                     const sh::InterfaceBlock &fragmentInterfaceBlock);
 
@@ -316,8 +323,6 @@
 
     static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
     bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
-                                               const std::vector<std::string> &transformFeedbackVaryingNames,
-                                               GLenum transformFeedbackBufferMode,
                                                std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
                                                const Caps &caps) const;
     bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps);
diff --git a/src/libANGLE/Shader.h b/src/libANGLE/Shader.h
index 9c31ae8..221a545 100644
--- a/src/libANGLE/Shader.h
+++ b/src/libANGLE/Shader.h
@@ -35,6 +35,7 @@
 
 struct PackedVarying : public sh::Varying
 {
+    // TODO(jmadill): Make these D3D-only or otherwise clearly separate from GL.
     unsigned int registerIndex; // Assigned during link
     unsigned int columnIndex; // Assigned during link, defaults to 0
 
diff --git a/src/libANGLE/renderer/ProgramImpl.h b/src/libANGLE/renderer/ProgramImpl.h
index 813324d..f8d7c33 100644
--- a/src/libANGLE/renderer/ProgramImpl.h
+++ b/src/libANGLE/renderer/ProgramImpl.h
@@ -38,7 +38,6 @@
 
     virtual bool usesPointSize() const = 0;
     virtual int getShaderVersion() const = 0;
-    virtual GLenum getTransformFeedbackBufferMode() const = 0;
 
     virtual GLenum getBinaryFormat() = 0;
     virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
@@ -46,8 +45,6 @@
 
     virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog,
                             gl::Shader *fragmentShader, gl::Shader *vertexShader,
-                            const std::vector<std::string> &transformFeedbackVaryings,
-                            GLenum transformFeedbackBufferMode,
                             int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
                             std::map<int, gl::VariableLocation> *outputVariables) = 0;
 
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
index 0cfa42a..142ef6d 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -736,10 +736,14 @@
     }
 }
 
-bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, int registers,
+bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
+                                         InfoLog &infoLog,
+                                         int registers,
                                          const VaryingPacking packing,
-                                         std::string &pixelHLSL, std::string &vertexHLSL,
-                                         ShaderD3D *fragmentShader, ShaderD3D *vertexShader,
+                                         std::string &pixelHLSL,
+                                         std::string &vertexHLSL,
+                                         const ShaderD3D *fragmentShader,
+                                         const ShaderD3D *vertexShader,
                                          const std::vector<std::string> &transformFeedbackVaryings,
                                          std::vector<LinkedVarying> *linkedVaryings,
                                          std::map<int, VariableLocation> *programOutputVars,
@@ -1086,7 +1090,8 @@
     return true;
 }
 
-void DynamicHLSL::defineOutputVariables(ShaderD3D *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const
+void DynamicHLSL::defineOutputVariables(const ShaderD3D *fragmentShader,
+                                        std::map<int, VariableLocation> *programOutputVars) const
 {
     const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
 
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/libANGLE/renderer/d3d/DynamicHLSL.h
index 3ab9f71..3a1c2f4 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.h
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -60,10 +60,14 @@
                                                    const std::vector<sh::Attribute> &shaderAttributes) const;
     std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables,
                                                       bool usesFragDepth, const std::vector<GLenum> &outputLayout) const;
-    bool generateShaderLinkHLSL(const gl::Data &data, gl::InfoLog &infoLog, int registers,
+    bool generateShaderLinkHLSL(const gl::Data &data,
+                                gl::InfoLog &infoLog,
+                                int registers,
                                 const VaryingPacking packing,
-                                std::string &pixelHLSL, std::string &vertexHLSL,
-                                ShaderD3D *fragmentShader, ShaderD3D *vertexShader,
+                                std::string &pixelHLSL,
+                                std::string &vertexHLSL,
+                                const ShaderD3D *fragmentShader,
+                                const ShaderD3D *vertexShader,
                                 const std::vector<std::string> &transformFeedbackVaryings,
                                 std::vector<gl::LinkedVarying> *linkedVaryings,
                                 std::map<int, gl::VariableLocation> *programOutputVars,
@@ -86,7 +90,8 @@
     std::string generateVaryingHLSL(const ShaderD3D *shader) const;
     void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const;
     void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<gl::LinkedVarying> *linkedVaryings) const;
-    void defineOutputVariables(ShaderD3D *fragmentShader, std::map<int, gl::VariableLocation> *programOutputVars) const;
+    void defineOutputVariables(const ShaderD3D *fragmentShader,
+                               std::map<int, gl::VariableLocation> *programOutputVars) const;
     std::string generatePointSpriteHLSL(int registers,
                                         const ShaderD3D *fragmentShader,
                                         const ShaderD3D *vertexShader) const;
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 212b391..614c21f 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -127,8 +127,41 @@
     const ProgramImpl::SemanticIndexArray *originalIndices;
 };
 
+bool LinkVaryingRegisters(gl::InfoLog &infoLog,
+                          ShaderD3D *vertexShaderD3D,
+                          ShaderD3D *fragmentShaderD3D)
+{
+    for (gl::PackedVarying &input : fragmentShaderD3D->getVaryings())
+    {
+        bool matched = false;
+
+        // Built-in varyings obey special rules
+        if (input.isBuiltIn())
+        {
+            continue;
+        }
+
+        for (gl::PackedVarying &output : vertexShaderD3D->getVaryings())
+        {
+            if (output.name == input.name)
+            {
+                output.registerIndex = input.registerIndex;
+                output.columnIndex   = input.columnIndex;
+
+                matched = true;
+                break;
+            }
+        }
+
+        // We permit unmatched, unreferenced varyings
+        ASSERT(matched || !input.staticUse);
+    }
+
+    return true;
 }
 
+}  // anonymous namespace
+
 ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
                                                const Signature &signature,
                                                ShaderExecutableD3D *shaderExecutable)
@@ -584,7 +617,6 @@
         mUniformBlocks[uniformBlockIndex] = uniformBlock;
     }
 
-    stream->readInt(&mTransformFeedbackBufferMode);
     const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
     mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
     for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
@@ -632,12 +664,11 @@
         unsigned int vertexShaderSize = stream->readInt<unsigned int>();
         const unsigned char *vertexShaderFunction = binary + stream->offset();
 
-        ShaderExecutableD3D *shaderExecutable = NULL;
-        gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
-                                                    SHADER_VERTEX,
-                                                    mTransformFeedbackLinkedVaryings,
-                                                    (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                    &shaderExecutable);
+        ShaderExecutableD3D *shaderExecutable = nullptr;
+
+        gl::Error error = mRenderer->loadExecutable(
+            vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
+            (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
         if (error.isError())
         {
             return LinkResult(false, error);
@@ -671,11 +702,11 @@
 
         const size_t pixelShaderSize = stream->readInt<unsigned int>();
         const unsigned char *pixelShaderFunction = binary + stream->offset();
-        ShaderExecutableD3D *shaderExecutable = NULL;
-        gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
-                                                    mTransformFeedbackLinkedVaryings,
-                                                    (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                    &shaderExecutable);
+        ShaderExecutableD3D *shaderExecutable    = nullptr;
+
+        gl::Error error = mRenderer->loadExecutable(
+            pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
+            (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
         if (error.isError())
         {
             return LinkResult(false, error);
@@ -698,10 +729,10 @@
     if (geometryShaderSize > 0)
     {
         const unsigned char *geometryShaderFunction = binary + stream->offset();
-        gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
-                                                    mTransformFeedbackLinkedVaryings,
-                                                    (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                    &mGeometryExecutable);
+        gl::Error error                             = mRenderer->loadExecutable(
+            geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
+            mTransformFeedbackLinkedVaryings,
+            (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &mGeometryExecutable);
         if (error.isError())
         {
             return LinkResult(false, error);
@@ -804,7 +835,6 @@
         stream->writeInt(uniformBlock.vsRegisterIndex);
     }
 
-    stream->writeInt(mTransformFeedbackBufferMode);
     stream->writeInt(mTransformFeedbackLinkedVaryings.size());
     for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
     {
@@ -933,10 +963,10 @@
     gl::InfoLog tempInfoLog;
     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
 
-    gl::Error error = mRenderer->compileToExecutable(*currentInfoLog, finalPixelHLSL, SHADER_PIXEL,
-                                                     mTransformFeedbackLinkedVaryings,
-                                                     (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                     mPixelWorkarounds, &pixelExecutable);
+    gl::Error error = mRenderer->compileToExecutable(
+        *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
+        (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
+        &pixelExecutable);
     if (error.isError())
     {
         return error;
@@ -981,10 +1011,10 @@
     gl::InfoLog tempInfoLog;
     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
 
-    gl::Error error = mRenderer->compileToExecutable(*currentInfoLog, finalVertexHLSL, SHADER_VERTEX,
-                                                     mTransformFeedbackLinkedVaryings,
-                                                     (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                     mVertexWorkarounds, &vertexExecutable);
+    gl::Error error = mRenderer->compileToExecutable(
+        *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
+        (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
+        &vertexExecutable);
     if (error.isError())
     {
         return error;
@@ -1031,10 +1061,10 @@
     {
         std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
 
-
-        error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
-                                               (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                               D3DCompilerWorkarounds(), &mGeometryExecutable);
+        error = mRenderer->compileToExecutable(
+            infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
+            (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
+            D3DCompilerWorkarounds(), &mGeometryExecutable);
         if (error.isError())
         {
             return LinkResult(false, error);
@@ -1068,8 +1098,6 @@
 
 LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog,
                             gl::Shader *fragmentShader, gl::Shader *vertexShader,
-                            const std::vector<std::string> &transformFeedbackVaryings,
-                            GLenum transformFeedbackBufferMode,
                             int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
                             std::map<int, gl::VariableLocation> *outputVariables)
 {
@@ -1079,8 +1107,6 @@
     mSamplersPS.resize(data.caps->maxTextureImageUnits);
     mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
 
-    mTransformFeedbackBufferMode = transformFeedbackBufferMode;
-
     mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
     fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
 
@@ -1099,21 +1125,20 @@
 
     // Map the varyings to the register file
     VaryingPacking packing = {};
-    *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
+    *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D,
+                                            mData.getTransformFeedbackVaryings());
 
     if (*registers < 0)
     {
         return LinkResult(false, gl::Error(GL_NO_ERROR));
     }
 
-    if (!gl::Program::linkVaryings(infoLog, fragmentShader, vertexShader))
-    {
-        return LinkResult(false, gl::Error(GL_NO_ERROR));
-    }
+    LinkVaryingRegisters(infoLog, vertexShaderD3D, fragmentShaderD3D);
 
-    if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
-                                              fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
-                                              linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
+    if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL,
+                                              mVertexHLSL, fragmentShaderD3D, vertexShaderD3D,
+                                              mData.getTransformFeedbackVaryings(), linkedVaryings,
+                                              outputVariables, &mPixelShaderKey, &mUsesFragDepth))
     {
         return LinkResult(false, gl::Error(GL_NO_ERROR));
     }
@@ -2016,8 +2041,6 @@
     SafeDeleteContainer(mPixelExecutables);
     SafeDelete(mGeometryExecutable);
 
-    mTransformFeedbackBufferMode = GL_NONE;
-
     mVertexHLSL.clear();
     mVertexWorkarounds = D3DCompilerWorkarounds();
     mShaderVersion = 100;
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/libANGLE/renderer/d3d/ProgramD3D.h
index 3cc6b16..5ab73c5 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -47,7 +47,6 @@
 
     const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
     int getShaderVersion() const { return mShaderVersion; }
-    GLenum getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
 
     GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const;
     GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const;
@@ -73,8 +72,6 @@
 
     LinkResult link(const gl::Data &data, gl::InfoLog &infoLog,
                     gl::Shader *fragmentShader, gl::Shader *vertexShader,
-                    const std::vector<std::string> &transformFeedbackVaryings,
-                    GLenum transformFeedbackBufferMode,
                     int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
                     std::map<int, gl::VariableLocation> *outputVariables);
 
@@ -225,8 +222,6 @@
     UniformStorageD3D *mVertexUniformStorage;
     UniformStorageD3D *mFragmentUniformStorage;
 
-    GLenum mTransformFeedbackBufferMode;
-
     std::vector<Sampler> mSamplersPS;
     std::vector<Sampler> mSamplersVS;
     GLuint mUsedVertexSamplerRange;
diff --git a/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/libANGLE/renderer/gl/ProgramGL.cpp
index 247f5df..d100c56 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -46,12 +46,6 @@
     return int();
 }
 
-GLenum ProgramGL::getTransformFeedbackBufferMode() const
-{
-    UNIMPLEMENTED();
-    return GLenum();
-}
-
 GLenum ProgramGL::getBinaryFormat()
 {
     UNIMPLEMENTED();
@@ -72,16 +66,14 @@
 
 LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog,
                            gl::Shader *fragmentShader, gl::Shader *vertexShader,
-                           const std::vector<std::string> &transformFeedbackVaryings,
-                           GLenum transformFeedbackBufferMode,
                            int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
                            std::map<int, gl::VariableLocation> *outputVariables)
 {
     // Reset the program state, delete the current program if one exists
     reset();
 
-    ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(vertexShader);
-    ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(fragmentShader);
+    const ShaderGL *vertexShaderGL   = GetImplAs<ShaderGL>(vertexShader);
+    const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(fragmentShader);
 
     // Attach the shaders
     mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
diff --git a/src/libANGLE/renderer/gl/ProgramGL.h b/src/libANGLE/renderer/gl/ProgramGL.h
index 7a98fc6..4e82216 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.h
+++ b/src/libANGLE/renderer/gl/ProgramGL.h
@@ -33,7 +33,6 @@
 
     bool usesPointSize() const override;
     int getShaderVersion() const override;
-    GLenum getTransformFeedbackBufferMode() const override;
 
     GLenum getBinaryFormat() override;
     LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
@@ -41,8 +40,6 @@
 
     LinkResult link(const gl::Data &data, gl::InfoLog &infoLog,
                     gl::Shader *fragmentShader, gl::Shader *vertexShader,
-                    const std::vector<std::string> &transformFeedbackVaryings,
-                    GLenum transformFeedbackBufferMode,
                     int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
                     std::map<int, gl::VariableLocation> *outputVariables) override;