Re-land "Compute packed varyings in ProgramD3D only."

Instead of storing varying information in the shader, use a temporary
set when linking a D3D program. This also means we won't have to
modify information in the Shader object when linking a D3D program.

This completes the refactoring for PackedVaryings.

Re-land with fix for missing init of PackedVarying::vertexOnly.

BUG=angleproject:1123

Change-Id: If110809c3817d88b0370ac575d739d7385b067d9
Reviewed-on: https://chromium-review.googlesource.com/296731
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
index 942efa4..9684320 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -236,8 +236,7 @@
 // Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
 // Returns the number of used varying registers, or -1 if unsuccesful
 int DynamicHLSL::packVaryings(InfoLog &infoLog,
-                              ShaderD3D *fragmentShader,
-                              ShaderD3D *vertexShader,
+                              std::vector<PackedVarying> *packedVaryings,
                               const std::vector<std::string> &transformFeedbackVaryings)
 {
     // TODO (geofflang):  Use context's caps
@@ -245,17 +244,11 @@
 
     VaryingPacking packing = {};
 
-    vertexShader->resetVaryingsRegisterAssignment();
-    fragmentShader->resetVaryingsRegisterAssignment();
+    std::set<std::string> uniqueVaryingNames;
 
-    std::set<std::string> packedVaryings;
-
-    std::vector<PackedVarying> &vertexVaryings   = vertexShader->getPackedVaryings();
-    std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getPackedVaryings();
-    for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++)
+    for (PackedVarying &packedVarying : *packedVaryings)
     {
-        PackedVarying *packedVarying = &fragmentVaryings[varyingIndex];
-        const sh::Varying &varying   = *packedVarying->varying;
+        const sh::Varying &varying = *packedVarying.varying;
 
         // Do not assign registers to built-in or unreferenced varyings
         if (varying.isBuiltIn() || !varying.staticUse)
@@ -263,9 +256,11 @@
             continue;
         }
 
-        if (PackVarying(packedVarying, maxVaryingVectors, packing))
+        ASSERT(uniqueVaryingNames.count(varying.name) == 0);
+
+        if (PackVarying(&packedVarying, maxVaryingVectors, packing))
         {
-            packedVaryings.insert(varying.name);
+            uniqueVaryingNames.insert(varying.name);
         }
         else
         {
@@ -274,26 +269,24 @@
         }
     }
 
-    for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++)
+    for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings)
     {
-        const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex];
-
-        if (transformFeedbackVarying == "gl_Position" || transformFeedbackVarying == "gl_PointSize")
+        if (transformFeedbackVaryingName == "gl_Position" ||
+            transformFeedbackVaryingName == "gl_PointSize")
         {
             // do not pack builtin XFB varyings
             continue;
         }
 
-        if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end())
+        if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0)
         {
             bool found = false;
-            for (unsigned int varyingIndex = 0; varyingIndex < vertexVaryings.size(); varyingIndex++)
+            for (PackedVarying &packedVarying : *packedVaryings)
             {
-                PackedVarying *packedVarying = &vertexVaryings[varyingIndex];
-                const sh::Varying &varying = *packedVarying->varying;
-                if (transformFeedbackVarying == varying.name)
+                const sh::Varying &varying = *packedVarying.varying;
+                if (transformFeedbackVaryingName == varying.name)
                 {
-                    if (!PackVarying(packedVarying, maxVaryingVectors, packing))
+                    if (!PackVarying(&packedVarying, maxVaryingVectors, packing))
                     {
                         infoLog << "Could not pack varying " << varying.name;
                         return -1;
@@ -306,8 +299,7 @@
 
             if (!found)
             {
-                infoLog << "Transform feedback varying "
-                        << transformFeedbackVarying
+                infoLog << "Transform feedback varying " << transformFeedbackVaryingName
                         << " does not exist in the vertex shader.";
                 return -1;
             }
@@ -328,13 +320,12 @@
     return registers;
 }
 
-std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const
+std::string DynamicHLSL::generateVaryingHLSL(const std::vector<PackedVarying> &varyings,
+                                             bool shaderUsesPointSize) const
 {
-    std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize);
+    std::string varyingSemantic = getVaryingSemantic(shaderUsesPointSize);
     std::string varyingHLSL;
 
-    const std::vector<PackedVarying> &varyings = shader->getPackedVaryings();
-
     for (const PackedVarying &packedVarying : varyings)
     {
         if (!packedVarying.registerAssigned())
@@ -735,12 +726,13 @@
     }
 }
 
-void DynamicHLSL::storeUserLinkedVaryings(const ShaderD3D *vertexShader,
+void DynamicHLSL::storeUserLinkedVaryings(const std::vector<PackedVarying> &packedVaryings,
+                                          bool shaderUsesPointSize,
                                           std::vector<LinkedVarying> *linkedVaryings) const
 {
-    const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize);
+    const std::string &varyingSemantic = getVaryingSemantic(shaderUsesPointSize);
 
-    for (const PackedVarying &packedVarying : vertexShader->getPackedVaryings())
+    for (const PackedVarying &packedVarying : packedVaryings)
     {
         if (packedVarying.registerAssigned())
         {
@@ -763,6 +755,7 @@
                                          int registers,
                                          std::string &pixelHLSL,
                                          std::string &vertexHLSL,
+                                         const std::vector<PackedVarying> &packedVaryings,
                                          std::vector<LinkedVarying> *linkedVaryings,
                                          std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
                                          bool *outUsesFragDepth) const
@@ -807,7 +800,7 @@
         return false;
     }
 
-    const std::string &varyingHLSL = generateVaryingHLSL(vertexShader);
+    const std::string &varyingHLSL = generateVaryingHLSL(packedVaryings, usesPointSize);
 
     // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader VS_OUTPUT
     // structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
@@ -820,7 +813,7 @@
                                                           usesFragCoord, (useInstancedPointSpriteEmulation && usesPointCoord),
                                                           (!useInstancedPointSpriteEmulation && usesPointSize), false);
 
-    storeUserLinkedVaryings(vertexShader, linkedVaryings);
+    storeUserLinkedVaryings(packedVaryings, usesPointSize, linkedVaryings);
     storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings);
 
     // Instanced PointSprite emulation requires additional entries originally generated in the
@@ -881,8 +874,7 @@
         vertexHLSL += "    output.gl_FragCoord = gl_Position;\n";
     }
 
-    const std::vector<PackedVarying> &vertexVaryings = vertexShader->getPackedVaryings();
-    for (const PackedVarying &packedVarying : vertexVaryings)
+    for (const PackedVarying &packedVarying : packedVaryings)
     {
         if (!packedVarying.registerAssigned())
         {
@@ -1051,8 +1043,7 @@
         }
     }
 
-    const std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getPackedVaryings();
-    for (const PackedVarying &packedVarying : fragmentVaryings)
+    for (const PackedVarying &packedVarying : packedVaryings)
     {
         const sh::Varying &varying = *packedVarying.varying;
 
@@ -1062,6 +1053,10 @@
             continue;
         }
 
+        // Don't reference VS-only transform feedback varyings in the PS.
+        if (packedVarying.vertexOnly)
+            continue;
+
         ASSERT(!varying.isBuiltIn());
         for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
         {
@@ -1128,21 +1123,22 @@
     return true;
 }
 
-std::string DynamicHLSL::generateGeometryShaderHLSL(int registers,
-                                                    const ShaderD3D *fragmentShader,
-                                                    const ShaderD3D *vertexShader) const
+std::string DynamicHLSL::generateGeometryShaderHLSL(
+    int registers,
+    const ShaderD3D *fragmentShader,
+    const std::vector<PackedVarying> &packedVaryings) const
 {
     // for now we only handle point sprite emulation
-    ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4);
-    return generatePointSpriteHLSL(registers, fragmentShader, vertexShader);
+    ASSERT(mRenderer->getMajorShaderModel() >= 4);
+    return generatePointSpriteHLSL(registers, fragmentShader, packedVaryings);
 }
 
-std::string DynamicHLSL::generatePointSpriteHLSL(int registers,
-                                                 const ShaderD3D *fragmentShader,
-                                                 const ShaderD3D *vertexShader) const
+std::string DynamicHLSL::generatePointSpriteHLSL(
+    int registers,
+    const ShaderD3D *fragmentShader,
+    const std::vector<PackedVarying> &packedVaryings) const
 {
     ASSERT(registers >= 0);
-    ASSERT(vertexShader->mUsesPointSize);
     ASSERT(mRenderer->getMajorShaderModel() >= 4);
 
     std::string geomHLSL;
@@ -1152,7 +1148,8 @@
     const SemanticInfo &outSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord,
                                                        fragmentShader->mUsesPointCoord, true, false);
 
-    std::string varyingHLSL = generateVaryingHLSL(vertexShader);
+    // If we're generating the geometry shader, we assume the vertex shader uses point size.
+    std::string varyingHLSL = generateVaryingHLSL(packedVaryings, true);
     std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL);
     std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL);
 
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/libANGLE/renderer/d3d/DynamicHLSL.h
index 9c91083..4529033 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.h
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -46,14 +46,36 @@
     size_t outputIndex;
 };
 
+struct PackedVarying
+{
+    PackedVarying(const sh::Varying &varyingIn)
+        : varying(&varyingIn), registerIndex(GL_INVALID_INDEX), columnIndex(0), vertexOnly(false)
+    {
+    }
+
+    bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; }
+
+    void resetRegisterAssignment() { registerIndex = GL_INVALID_INDEX; }
+
+    const sh::Varying *varying;
+
+    // Assigned during link
+    unsigned int registerIndex;
+
+    // Assigned during link, Defaults to 0
+    unsigned int columnIndex;
+
+    // Transform feedback varyings can be only referenced in the VS.
+    bool vertexOnly;
+};
+
 class DynamicHLSL : angle::NonCopyable
 {
   public:
     explicit DynamicHLSL(RendererD3D *const renderer);
 
     int packVaryings(gl::InfoLog &infoLog,
-                     ShaderD3D *fragmentShader,
-                     ShaderD3D *vertexShader,
+                     std::vector<PackedVarying> *packedVaryings,
                      const std::vector<std::string> &transformFeedbackVaryings);
     std::string generateVertexShaderForInputLayout(const std::string &sourceShader,
                                                    const gl::InputLayout &inputLayout,
@@ -66,13 +88,14 @@
                                 int registers,
                                 std::string &pixelHLSL,
                                 std::string &vertexHLSL,
+                                const std::vector<PackedVarying> &packedVaryings,
                                 std::vector<gl::LinkedVarying> *linkedVaryings,
                                 std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
                                 bool *outUsesFragDepth) const;
 
     std::string generateGeometryShaderHLSL(int registers,
                                            const ShaderD3D *fragmentShader,
-                                           const ShaderD3D *vertexShader) const;
+                                           const std::vector<PackedVarying> &packedVaryings) const;
 
   private:
     RendererD3D *const mRenderer;
@@ -83,12 +106,15 @@
     SemanticInfo getSemanticInfo(int startRegisters, bool position, bool fragCoord, bool pointCoord,
                                  bool pointSize, bool pixelShader) const;
     std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const;
-    std::string generateVaryingHLSL(const ShaderD3D *shader) const;
-    void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const;
+    std::string generateVaryingHLSL(const std::vector<PackedVarying> &varyings,
+                                    bool shaderUsesPointSize) const;
+    void storeUserLinkedVaryings(const std::vector<PackedVarying> &packedVaryings,
+                                 bool shaderUsesPointSize,
+                                 std::vector<gl::LinkedVarying> *linkedVaryings) const;
     void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<gl::LinkedVarying> *linkedVaryings) const;
     std::string generatePointSpriteHLSL(int registers,
                                         const ShaderD3D *fragmentShader,
-                                        const ShaderD3D *vertexShader) const;
+                                        const std::vector<PackedVarying> &packedVaryings) const;
 
     // Prepend an underscore
     static std::string decorateVariable(const std::string &name);
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp
new file mode 100644
index 0000000..ea7a331
--- /dev/null
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp
@@ -0,0 +1,30 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DynamicHLSL unittests:
+//   Tests for DynamicHLSL and related classes.
+//
+
+#include <gtest/gtest.h>
+
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+
+using namespace rx;
+
+namespace
+{
+
+TEST(PackedVarying, DefaultInitialization)
+{
+    sh::Varying defaultVarying;
+    PackedVarying pv(defaultVarying);
+
+    EXPECT_EQ(&defaultVarying, pv.varying);
+    EXPECT_EQ(GL_INVALID_INDEX, pv.registerIndex);
+    EXPECT_EQ(0, pv.columnIndex);
+    EXPECT_FALSE(pv.vertexOnly);
+}
+
+}  // anonymous namespace
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index daa7779..6d1d46e 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -127,37 +127,48 @@
     const ProgramD3D::SemanticIndexArray *originalIndices;
 };
 
-bool LinkVaryingRegisters(gl::InfoLog &infoLog,
-                          ShaderD3D *vertexShaderD3D,
-                          ShaderD3D *fragmentShaderD3D)
+std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
+                                         const gl::Shader &fragmentShader,
+                                         const std::vector<std::string> &tfVaryings)
 {
-    for (PackedVarying &input : fragmentShaderD3D->getPackedVaryings())
+    std::vector<PackedVarying> packedVaryings;
+
+    for (const sh::Varying &output : vertexShader.getVaryings())
     {
-        bool matched = false;
+        bool packed = false;
 
         // Built-in varyings obey special rules
-        if (input.varying->isBuiltIn())
+        if (output.isBuiltIn())
         {
             continue;
         }
 
-        for (PackedVarying &output : vertexShaderD3D->getPackedVaryings())
+        for (const sh::Varying &input : fragmentShader.getVaryings())
         {
-            if (output.varying->name == input.varying->name)
+            if (output.name == input.name)
             {
-                output.registerIndex = input.registerIndex;
-                output.columnIndex   = input.columnIndex;
-
-                matched = true;
+                packedVaryings.push_back(PackedVarying(input));
+                packed = true;
                 break;
             }
         }
 
-        // We permit unmatched, unreferenced varyings
-        ASSERT(matched || !input.varying->staticUse);
+        // Keep Transform FB varyings in the merged list always.
+        if (!packed)
+        {
+            for (const std::string &tfVarying : tfVaryings)
+            {
+                if (tfVarying == output.name)
+                {
+                    packedVaryings.push_back(PackedVarying(output));
+                    packedVaryings.back().vertexOnly = true;
+                    break;
+                }
+            }
+        }
     }
 
-    return true;
+    return packedVaryings;
 }
 
 }  // anonymous namespace
@@ -1048,9 +1059,10 @@
     return gl::Error(GL_NO_ERROR);
 }
 
-LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, int registers)
+LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog,
+                                                 int registers,
+                                                 const std::vector<PackedVarying> &packedVaryings)
 {
-    const ShaderD3D *vertexShaderD3D   = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
     const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
 
     const gl::InputLayout &defaultInputLayout =
@@ -1072,7 +1084,8 @@
 
     if (usesGeometryShader())
     {
-        std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
+        std::string geometryHLSL =
+            mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, packedVaryings);
 
         error = mRenderer->compileToExecutable(
             infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
@@ -1085,6 +1098,8 @@
     }
 
 #if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
+    const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
+
     if (usesGeometryShader() && mGeometryExecutable)
     {
         // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
@@ -1136,8 +1151,11 @@
         }
     }
 
+    std::vector<PackedVarying> packedVaryings =
+        MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
+
     // Map the varyings to the register file
-    int registers = mDynamicHLSL->packVaryings(infoLog, fragmentShaderD3D, vertexShaderD3D,
+    int registers = mDynamicHLSL->packVaryings(infoLog, &packedVaryings,
                                                mData.getTransformFeedbackVaryingNames());
 
     if (registers < 0)
@@ -1145,12 +1163,10 @@
         return LinkResult(false, gl::Error(GL_NO_ERROR));
     }
 
-    LinkVaryingRegisters(infoLog, vertexShaderD3D, fragmentShaderD3D);
-
     std::vector<gl::LinkedVarying> linkedVaryings;
     if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, mPixelHLSL,
-                                              mVertexHLSL, &linkedVaryings, &mPixelShaderKey,
-                                              &mUsesFragDepth))
+                                              mVertexHLSL, packedVaryings, &linkedVaryings,
+                                              &mPixelShaderKey, &mUsesFragDepth))
     {
         return LinkResult(false, gl::Error(GL_NO_ERROR));
     }
@@ -1168,7 +1184,7 @@
 
     gatherTransformFeedbackVaryings(linkedVaryings);
 
-    LinkResult result = compileProgramExecutables(infoLog, registers);
+    LinkResult result = compileProgramExecutables(infoLog, registers, packedVaryings);
     if (result.error.isError() || !result.linkSuccess)
     {
         infoLog << "Failed to create D3D shaders.";
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/libANGLE/renderer/d3d/ProgramD3D.h
index 37a476f..9ce3b0d 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -207,7 +207,9 @@
                                    sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
                                    bool inRowMajorLayout);
 
-    LinkResult compileProgramExecutables(gl::InfoLog &infoLog, int registers);
+    LinkResult compileProgramExecutables(gl::InfoLog &infoLog,
+                                         int registers,
+                                         const std::vector<PackedVarying> &packedVaryings);
 
     void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings);
 
diff --git a/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/src/libANGLE/renderer/d3d/ShaderD3D.cpp
index f71250e..0a3e8e5 100644
--- a/src/libANGLE/renderer/d3d/ShaderD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -110,11 +110,6 @@
 
         mVaryings = *varyings;
 
-        for (size_t varyingIndex = 0; varyingIndex < varyings->size(); varyingIndex++)
-        {
-            mPackedVaryings.push_back(PackedVarying(mVaryings[varyingIndex]));
-        }
-
         mUsesMultipleRenderTargets   = mTranslatedSource.find("GL_USES_MRT")                          != std::string::npos;
         mUsesFragColor               = mTranslatedSource.find("GL_USES_FRAG_COLOR")                   != std::string::npos;
         mUsesFragData                = mTranslatedSource.find("GL_USES_FRAG_DATA")                    != std::string::npos;
@@ -131,14 +126,6 @@
     }
 }
 
-void ShaderD3D::resetVaryingsRegisterAssignment()
-{
-    for (size_t varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++)
-    {
-        mPackedVaryings[varyingIndex].resetRegisterAssignment();
-    }
-}
-
 // initialize/clean up previous state
 void ShaderD3D::uncompile()
 {
diff --git a/src/libANGLE/renderer/d3d/ShaderD3D.h b/src/libANGLE/renderer/d3d/ShaderD3D.h
index 9cdd541..b6630f2 100644
--- a/src/libANGLE/renderer/d3d/ShaderD3D.h
+++ b/src/libANGLE/renderer/d3d/ShaderD3D.h
@@ -20,24 +20,6 @@
 class DynamicHLSL;
 class RendererD3D;
 
-struct PackedVarying
-{
-    PackedVarying(const sh::Varying &varyingIn)
-        : varying(&varyingIn), registerIndex(GL_INVALID_INDEX), columnIndex(0)
-    {
-    }
-
-    bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; }
-
-    void resetRegisterAssignment() { registerIndex = GL_INVALID_INDEX; }
-
-    const sh::Varying *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
-};
-
 class ShaderD3D : public ShaderImpl
 {
     friend class DynamicHLSL;
@@ -51,7 +33,6 @@
 
     // D3D-specific methods
     virtual void uncompile();
-    void resetVaryingsRegisterAssignment();
     unsigned int getUniformRegister(const std::string &uniformName) const;
     unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
     void appendDebugInfo(const std::string &info) { mDebugInfo += info; }
@@ -68,11 +49,6 @@
 
     virtual bool compile(gl::Compiler *compiler, const std::string &source);
 
-    const std::vector<PackedVarying> &getPackedVaryings() const { return mPackedVaryings; }
-
-    // TODO(jmadill): remove this
-    std::vector<PackedVarying> &getPackedVaryings() { return mPackedVaryings; }
-
   private:
     void compileToHLSL(ShHandle compiler, const std::string &source);
     void parseVaryings(ShHandle compiler);
@@ -100,7 +76,6 @@
     std::map<std::string, unsigned int> mUniformRegisterMap;
     std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
     RendererD3D *mRenderer;
-    std::vector<PackedVarying> mPackedVaryings;
 };
 
 }
diff --git a/src/tests/angle_unittests.gypi b/src/tests/angle_unittests.gypi
index 22fbd91..3021909 100644
--- a/src/tests/angle_unittests.gypi
+++ b/src/tests/angle_unittests.gypi
@@ -75,8 +75,10 @@
             '<(angle_path)/src/tests/test_utils/compiler_test.cpp',
             '<(angle_path)/src/tests/test_utils/compiler_test.h',
         ],
+        # TODO(jmadill): should probably call this windows sources
         'angle_unittests_hlsl_sources':
         [
+            '<(angle_path)/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp',
             '<(angle_path)/src/tests/compiler_tests/UnrollFlatten_test.cpp',
         ],
     },
diff --git a/src/tests/gl_tests/TransformFeedbackTest.cpp b/src/tests/gl_tests/TransformFeedbackTest.cpp
index 5b9cdd5..23b5bf5 100644
--- a/src/tests/gl_tests/TransformFeedbackTest.cpp
+++ b/src/tests/gl_tests/TransformFeedbackTest.cpp
@@ -264,6 +264,71 @@
     glDeleteBuffers(1, &scratchBuffer);
 }
 
+// Test that we can capture varyings only used in the vertex shader.
+TEST_P(TransformFeedbackTest, VertexOnly)
+{
+    const std::string &vertexShaderSource =
+        "#version 300 es\n"
+        "in vec2 position;\n"
+        "in float attrib;\n"
+        "out float varyingAttrib;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(position, 0, 1);\n"
+        "  varyingAttrib = attrib;\n"
+        "}";
+
+    const std::string &fragmentShaderSource =
+        "#version 300 es\n"
+        "out mediump vec4 color;\n"
+        "void main() {\n"
+        "  color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+        "}";
+
+    std::vector<std::string> tfVaryings;
+    tfVaryings.push_back("varyingAttrib");
+
+    GLuint program = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
+                                                         tfVaryings, GL_INTERLEAVED_ATTRIBS);
+    ASSERT_NE(0u, program);
+
+    GLuint transformFeedback;
+    glGenTransformFeedbacks(1, &transformFeedback);
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
+    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
+
+    std::vector<float> attribData;
+    for (unsigned int cnt = 0; cnt < 100; ++cnt)
+    {
+        attribData.push_back(static_cast<float>(cnt));
+    }
+
+    GLint attribLocation = glGetAttribLocation(program, "attrib");
+    ASSERT_NE(-1, attribLocation);
+
+    glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, &attribData[0]);
+    glEnableVertexAttribArray(attribLocation);
+
+    glBeginTransformFeedback(GL_TRIANGLES);
+    drawQuad(program, "position", 0.5f);
+    glEndTransformFeedback();
+    ASSERT_GL_NO_ERROR();
+
+    GLvoid *mappedBuffer =
+        glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(float) * 6, GL_MAP_READ_BIT);
+    ASSERT_NE(nullptr, mappedBuffer);
+
+    float *mappedFloats = static_cast<float *>(mappedBuffer);
+    for (unsigned int cnt = 0; cnt < 6; ++cnt)
+    {
+        EXPECT_EQ(attribData[cnt], mappedFloats[cnt]);
+    }
+
+    glDeleteTransformFeedbacks(1, &transformFeedback);
+    glDeleteProgram(program);
+
+    EXPECT_GL_NO_ERROR();
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 ANGLE_INSTANTIATE_TEST(TransformFeedbackTest, ES3_D3D11());