Re-land "D3D: Move some varying packing code into a new file."

Re-land with fix for compile errors.

Refactoring patch which moves code only. Work and full description
will follow in a subsequent CL.

BUG=angleproject:1202

Change-Id: Ib7c7dbd32491cdd9512dbecdc0e1e90303d8f28d
Reviewed-on: https://chromium-review.googlesource.com/312481
Tryjob-Request: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
index 9a7d24b..0640407 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -16,6 +16,7 @@
 #include "libANGLE/renderer/d3d/ProgramD3D.h"
 #include "libANGLE/renderer/d3d/RendererD3D.h"
 #include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/VaryingPacking.h"
 
 // For use with ArrayString, see angleutils.h
 static_assert(GL_INVALID_INDEX == UINT_MAX,
@@ -106,386 +107,19 @@
     return nullptr;
 }
 
-typedef const PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4];
-
-bool PackVarying(PackedVarying *packedVarying, const int maxVaryingVectors, VaryingPacking &packing)
-{
-    // Make sure we use transposed matrix types to count registers correctly.
-    int registers = 0;
-    int elements  = 0;
-
-    const sh::Varying &varying = *packedVarying->varying;
-
-    if (varying.isStruct())
-    {
-        registers = HLSLVariableRegisterCount(varying, true) * varying.elementCount();
-        elements  = 4;
-    }
-    else
-    {
-        GLenum transposedType = TransposeMatrixType(varying.type);
-        registers             = VariableRowCount(transposedType) * varying.elementCount();
-        elements              = VariableColumnCount(transposedType);
-    }
-
-    if (elements >= 2 && elements <= 4)
-    {
-        for (int r = 0; r <= maxVaryingVectors - registers; r++)
-        {
-            bool available = true;
-
-            for (int y = 0; y < registers && available; y++)
-            {
-                for (int x = 0; x < elements && available; x++)
-                {
-                    if (packing[r + y][x])
-                    {
-                        available = false;
-                    }
-                }
-            }
-
-            if (available)
-            {
-                packedVarying->registerIndex = r;
-                packedVarying->columnIndex   = 0;
-
-                for (int y = 0; y < registers; y++)
-                {
-                    for (int x = 0; x < elements; x++)
-                    {
-                        packing[r + y][x] = packedVarying;
-                    }
-                }
-
-                return true;
-            }
-        }
-
-        if (elements == 2)
-        {
-            for (int r = maxVaryingVectors - registers; r >= 0; r--)
-            {
-                bool available = true;
-
-                for (int y = 0; y < registers && available; y++)
-                {
-                    for (int x = 2; x < 4 && available; x++)
-                    {
-                        if (packing[r + y][x])
-                        {
-                            available = false;
-                        }
-                    }
-                }
-
-                if (available)
-                {
-                    packedVarying->registerIndex = r;
-                    packedVarying->columnIndex   = 2;
-
-                    for (int y = 0; y < registers; y++)
-                    {
-                        for (int x = 2; x < 4; x++)
-                        {
-                            packing[r + y][x] = packedVarying;
-                        }
-                    }
-
-                    return true;
-                }
-            }
-        }
-    }
-    else if (elements == 1)
-    {
-        int space[4] = {0};
-
-        for (int y = 0; y < maxVaryingVectors; y++)
-        {
-            for (int x = 0; x < 4; x++)
-            {
-                space[x] += packing[y][x] ? 0 : 1;
-            }
-        }
-
-        int column = 0;
-
-        for (int x = 0; x < 4; x++)
-        {
-            if (space[x] >= registers && (space[column] < registers || space[x] < space[column]))
-            {
-                column = x;
-            }
-        }
-
-        if (space[column] >= registers)
-        {
-            for (int r = 0; r < maxVaryingVectors; r++)
-            {
-                if (!packing[r][column])
-                {
-                    packedVarying->registerIndex = r;
-                    packedVarying->columnIndex   = column;
-
-                    for (int y = r; y < r + registers; y++)
-                    {
-                        packing[y][column] = packedVarying;
-                    }
-
-                    break;
-                }
-            }
-
-            return true;
-        }
-    }
-    else
-        UNREACHABLE();
-
-    return false;
-}
-
-unsigned int VaryingRegisterIndex(const gl::Caps &caps,
-                                  const PackedVarying &packedVarying,
-                                  unsigned int elementIndex,
-                                  unsigned int row)
-{
-    const sh::Varying &varying = *packedVarying.varying;
-
-    GLenum transposedType = TransposeMatrixType(varying.type);
-    unsigned int variableRows =
-        static_cast<unsigned int>(varying.isStruct() ? 1 : VariableRowCount(transposedType));
-
-    return (elementIndex * variableRows + (packedVarying.columnIndex * caps.maxVaryingVectors) +
-            (packedVarying.registerIndex + row));
-}
-
-struct PackedVaryingRegister final
-{
-    PackedVaryingRegister() : varyingIndex(0), elementIndex(0), rowIndex(0) {}
-
-    PackedVaryingRegister(const PackedVaryingRegister &) = default;
-    PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
-
-    unsigned int registerIndex(const gl::Caps &caps,
-                               const std::vector<PackedVarying> &packedVaryings) const
-    {
-        const PackedVarying &packedVarying = packedVaryings[varyingIndex];
-        return VaryingRegisterIndex(caps, packedVarying, elementIndex, rowIndex);
-    }
-
-    size_t varyingIndex;
-    unsigned int elementIndex;
-    unsigned int rowIndex;
-};
-
-class PackedVaryingIterator final : public angle::NonCopyable
-{
-  public:
-    PackedVaryingIterator(const std::vector<PackedVarying> &packedVaryings);
-
-    class Iterator final
-    {
-      public:
-        Iterator(const PackedVaryingIterator &parent);
-
-        Iterator(const Iterator &) = default;
-        Iterator &operator=(const Iterator &) = delete;
-
-        Iterator &operator++();
-        bool operator==(const Iterator &other) const;
-        bool operator!=(const Iterator &other) const;
-
-        const PackedVaryingRegister &operator*() const { return mRegister; }
-        void setEnd() { mRegister.varyingIndex = mParent.mPackedVaryings.size(); }
-
-      private:
-        const PackedVaryingIterator &mParent;
-        PackedVaryingRegister mRegister;
-    };
-
-    Iterator begin() const;
-    const Iterator &end() const;
-
-  private:
-    const std::vector<PackedVarying> &mPackedVaryings;
-    Iterator mEnd;
-};
-
-PackedVaryingIterator::PackedVaryingIterator(const std::vector<PackedVarying> &packedVaryings)
-    : mPackedVaryings(packedVaryings), mEnd(*this)
-{
-    mEnd.setEnd();
-}
-
-PackedVaryingIterator::Iterator PackedVaryingIterator::begin() const
-{
-    return Iterator(*this);
-}
-
-const PackedVaryingIterator::Iterator &PackedVaryingIterator::end() const
-{
-    return mEnd;
-}
-
-PackedVaryingIterator::Iterator::Iterator(const PackedVaryingIterator &parent) : mParent(parent)
-{
-    while (mRegister.varyingIndex < mParent.mPackedVaryings.size() &&
-           !mParent.mPackedVaryings[mRegister.varyingIndex].registerAssigned())
-    {
-        ++mRegister.varyingIndex;
-    }
-}
-
-PackedVaryingIterator::Iterator &PackedVaryingIterator::Iterator::operator++()
-{
-    const sh::Varying *varying = mParent.mPackedVaryings[mRegister.varyingIndex].varying;
-    GLenum transposedType = TransposeMatrixType(varying->type);
-    unsigned int variableRows =
-        static_cast<unsigned int>(varying->isStruct() ? 1 : VariableRowCount(transposedType));
-
-    // Innermost iteration: row count
-    if (mRegister.rowIndex + 1 < variableRows)
-    {
-        ++mRegister.rowIndex;
-        return *this;
-    }
-
-    mRegister.rowIndex = 0;
-
-    // Middle iteration: element count
-    if (mRegister.elementIndex + 1 < varying->elementCount())
-    {
-        ++mRegister.elementIndex;
-        return *this;
-    }
-
-    mRegister.elementIndex = 0;
-
-    // Outer iteration: the varying itself. Once we pass the last varying, this Iterator will
-    // equal the end Iterator.
-    do
-    {
-        ++mRegister.varyingIndex;
-    } while (mRegister.varyingIndex < mParent.mPackedVaryings.size() &&
-             !mParent.mPackedVaryings[mRegister.varyingIndex].registerAssigned());
-    return *this;
-}
-
-bool PackedVaryingIterator::Iterator::operator==(const Iterator &other) const
-{
-    return mRegister.elementIndex == other.mRegister.elementIndex &&
-           mRegister.rowIndex == other.mRegister.rowIndex &&
-           mRegister.varyingIndex == other.mRegister.varyingIndex;
-}
-
-bool PackedVaryingIterator::Iterator::operator!=(const Iterator &other) const
-{
-    return !(*this == other);
-}
-
 const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
 const std::string PIXEL_OUTPUT_STUB_STRING     = "@@ PIXEL OUTPUT @@";
 }  // anonymous namespace
 
-DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer)
+std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
 {
+    // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+    // In D3D11 we manually compute gl_PointCoord in the GS.
+    return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
 }
 
-// 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
-bool DynamicHLSL::packVaryings(const gl::Caps &caps,
-                               InfoLog &infoLog,
-                               std::vector<PackedVarying> *packedVaryings,
-                               const std::vector<std::string> &transformFeedbackVaryings,
-                               unsigned int *registerCountOut)
+DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer)
 {
-    VaryingPacking packing = {};
-    *registerCountOut      = 0;
-
-    std::set<std::string> uniqueVaryingNames;
-
-    for (PackedVarying &packedVarying : *packedVaryings)
-    {
-        const sh::Varying &varying = *packedVarying.varying;
-
-        // Do not assign registers to built-in or unreferenced varyings
-        if (varying.isBuiltIn() || !varying.staticUse)
-        {
-            continue;
-        }
-
-        ASSERT(uniqueVaryingNames.count(varying.name) == 0);
-
-        if (PackVarying(&packedVarying, caps.maxVaryingVectors, packing))
-        {
-            uniqueVaryingNames.insert(varying.name);
-        }
-        else
-        {
-            infoLog << "Could not pack varying " << varying.name;
-            return false;
-        }
-    }
-
-    for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings)
-    {
-        if (transformFeedbackVaryingName.compare(0, 3, "gl_") == 0)
-        {
-            // do not pack builtin XFB varyings
-            continue;
-        }
-
-        for (PackedVarying &packedVarying : *packedVaryings)
-        {
-            const sh::Varying &varying = *packedVarying.varying;
-
-            // Make sure transform feedback varyings aren't optimized out.
-            if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0)
-            {
-                bool found = false;
-                if (transformFeedbackVaryingName == varying.name)
-                {
-                    if (!PackVarying(&packedVarying, caps.maxVaryingVectors, packing))
-                    {
-                        infoLog << "Could not pack varying " << varying.name;
-                        return false;
-                    }
-
-                    found = true;
-                    break;
-                }
-                if (!found)
-                {
-                    infoLog << "Transform feedback varying " << transformFeedbackVaryingName
-                            << " does not exist in the vertex shader.";
-                    return false;
-                }
-            }
-
-            // Add duplicate transform feedback varyings for 'flat' shaded attributes. This is
-            // necessary because we write out modified vertex data to correct for the provoking
-            // vertex in D3D11. This extra transform feedback varying is the unmodified stream.
-            if (varying.interpolation == sh::INTERPOLATION_FLAT)
-            {
-                sh::Varying duplicateVarying(varying);
-                duplicateVarying.name = "StreamOut_" + duplicateVarying.name;
-            }
-        }
-    }
-
-    // Return the number of used registers
-    for (GLuint r = 0; r < caps.maxVaryingVectors; r++)
-    {
-        if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
-        {
-            (*registerCountOut)++;
-        }
-    }
-
-    return true;
 }
 
 void DynamicHLSL::generateVaryingHLSL(const gl::Caps &caps,
@@ -493,7 +127,8 @@
                                       bool programUsesPointSize,
                                       std::stringstream &hlslStream) const
 {
-    std::string varyingSemantic = getVaryingSemantic(programUsesPointSize);
+    std::string varyingSemantic =
+        GetVaryingSemantic(mRenderer->getMajorShaderModel(), programUsesPointSize);
 
     for (const PackedVaryingRegister &registerInfo : PackedVaryingIterator(varyings))
     {
@@ -725,108 +360,6 @@
     return pixelHLSL;
 }
 
-std::string DynamicHLSL::getVaryingSemantic(bool programUsesPointSize) const
-{
-    // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
-    // In D3D11 we manually compute gl_PointCoord in the GS.
-    int shaderModel = mRenderer->getMajorShaderModel();
-    return ((programUsesPointSize && shaderModel < 4) ? "COLOR" : "TEXCOORD");
-}
-
-struct DynamicHLSL::SemanticInfo
-{
-    struct BuiltinInfo
-    {
-        BuiltinInfo() : enabled(false), index(0), systemValue(false) {}
-
-        bool enabled;
-        std::string semantic;
-        unsigned int index;
-        bool systemValue;
-
-        std::string str() const { return (systemValue ? semantic : (semantic + Str(index))); }
-
-        void enableSystem(const std::string &systemValueSemantic)
-        {
-            enabled     = true;
-            semantic    = systemValueSemantic;
-            systemValue = true;
-        }
-
-        void enable(const std::string &semanticVal, unsigned int indexVal)
-        {
-            enabled  = true;
-            semantic = semanticVal;
-            index    = indexVal;
-        }
-    };
-
-    BuiltinInfo dxPosition;
-    BuiltinInfo glPosition;
-    BuiltinInfo glFragCoord;
-    BuiltinInfo glPointCoord;
-    BuiltinInfo glPointSize;
-};
-
-DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(ShaderType shaderType,
-                                                       unsigned int startRegisters,
-                                                       bool position,
-                                                       bool fragCoord,
-                                                       bool pointCoord,
-                                                       bool pointSize) const
-{
-    SemanticInfo info;
-    bool hlsl4                         = (mRenderer->getMajorShaderModel() >= 4);
-    const std::string &varyingSemantic = getVaryingSemantic(pointSize);
-
-    unsigned int reservedRegisterIndex = startRegisters;
-
-    if (hlsl4)
-    {
-        info.dxPosition.enableSystem("SV_Position");
-    }
-    else if (shaderType == SHADER_PIXEL)
-    {
-        info.dxPosition.enableSystem("VPOS");
-    }
-    else
-    {
-        info.dxPosition.enableSystem("POSITION");
-    }
-
-    if (position)
-    {
-        info.glPosition.enable(varyingSemantic, reservedRegisterIndex++);
-    }
-
-    if (fragCoord)
-    {
-        info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++);
-    }
-
-    if (pointCoord)
-    {
-        // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
-        // In D3D11 we manually compute gl_PointCoord in the GS.
-        if (hlsl4)
-        {
-            info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++);
-        }
-        else
-        {
-            info.glPointCoord.enable("TEXCOORD", 0);
-        }
-    }
-
-    // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
-    if (pointSize && (shaderType != SHADER_PIXEL || hlsl4))
-    {
-        info.glPointSize.enableSystem("PSIZE");
-    }
-
-    return info;
-}
-
 void DynamicHLSL::generateVaryingLinkHLSL(const gl::Caps &caps,
                                           bool programUsesPointSize,
                                           const SemanticInfo &info,
@@ -889,7 +422,8 @@
                                     bool programUsesPointSize,
                                     std::vector<D3DVarying> *d3dVaryingsOut) const
 {
-    const std::string &varyingSemantic = getVaryingSemantic(programUsesPointSize);
+    const std::string &varyingSemantic =
+        GetVaryingSemantic(mRenderer->getMajorShaderModel(), programUsesPointSize);
 
     for (const PackedVarying &packedVarying : packedVaryings)
     {
@@ -970,9 +504,9 @@
     // PS_INPUT of the generated pixel shader. The Geometry Shader point sprite implementation needs
     // gl_PointSize to be in VS_OUTPUT and GS_INPUT. Instanced point sprites doesn't need
     // gl_PointSize in VS_OUTPUT.
-    const SemanticInfo &vertexSemantics =
-        getSemanticInfo(SHADER_VERTEX, registerCount, outputPositionFromVS, usesFragCoord,
-                        addPointCoord, (!useInstancedPointSpriteEmulation && usesPointSize));
+    const SemanticInfo &vertexSemantics = GetSemanticInfo(
+        SHADER_VERTEX, shaderModel, registerCount, outputPositionFromVS, usesFragCoord,
+        addPointCoord, (!useInstancedPointSpriteEmulation && usesPointSize));
 
     storeUserVaryings(packedVaryings, usesPointSize, d3dVaryingsOut);
     storeBuiltinVaryings(vertexSemantics, d3dVaryingsOut);
@@ -1104,9 +638,9 @@
     std::stringstream pixelStream;
     pixelStream << fragmentShaderGL->getTranslatedSource();
 
-    const SemanticInfo &pixelSemantics =
-        getSemanticInfo(SHADER_PIXEL, registerCount, outputPositionFromVS, usesFragCoord,
-                        usesPointCoord, (!useInstancedPointSpriteEmulation && usesPointSize));
+    const SemanticInfo &pixelSemantics = GetSemanticInfo(
+        SHADER_PIXEL, shaderModel, registerCount, outputPositionFromVS, usesFragCoord,
+        usesPointCoord, (!useInstancedPointSpriteEmulation && usesPointSize));
 
     pixelStream << "struct PS_INPUT\n";
     generateVaryingLinkHLSL(*data.caps, usesPointSize, pixelSemantics, packedVaryings, pixelStream);
@@ -1299,8 +833,10 @@
     unsigned int registerCount,
     const std::vector<PackedVarying> &packedVaryings) const
 {
+    int majorShaderModel = mRenderer->getMajorShaderModel();
+
     ASSERT(registerCount >= 0 && registerCount <= data.caps->maxVaryingVectors);
-    ASSERT(mRenderer->getMajorShaderModel() >= 4);
+    ASSERT(majorShaderModel >= 4);
 
     // Must be called during link, not from a binary load.
     const ShaderD3D *vertexShader   = GetImplAs<ShaderD3D>(programData.getAttachedVertexShader());
@@ -1311,10 +847,11 @@
     bool usesPointCoord = fragmentShader->usesPointCoord();
     bool usesPointSize  = vertexShader->usesPointSize();
 
-    const SemanticInfo &inSemantics =
-        getSemanticInfo(SHADER_VERTEX, registerCount, true, usesFragCoord, false, usesPointSize);
-    const SemanticInfo &outSemantics = getSemanticInfo(
-        SHADER_GEOMETRY, registerCount, true, usesFragCoord, usesPointCoord, usesPointSize);
+    const SemanticInfo &inSemantics = GetSemanticInfo(
+        SHADER_VERTEX, majorShaderModel, registerCount, true, usesFragCoord, false, usesPointSize);
+    const SemanticInfo &outSemantics =
+        GetSemanticInfo(SHADER_GEOMETRY, majorShaderModel, registerCount, true, usesFragCoord,
+                        usesPointCoord, usesPointSize);
 
     std::stringstream preambleStream;
 
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/libANGLE/renderer/d3d/DynamicHLSL.h
index a3ff7db..3f960ca 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.h
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -35,6 +35,8 @@
 
 namespace rx
 {
+struct PackedVarying;
+struct SemanticInfo;
 class ShaderD3D;
 
 struct PixelShaderOutputVariable
@@ -45,39 +47,11 @@
     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);
 
-    bool packVaryings(const gl::Caps &caps,
-                      gl::InfoLog &infoLog,
-                      std::vector<PackedVarying> *packedVaryings,
-                      const std::vector<std::string> &transformFeedbackVaryings,
-                      unsigned int *registerCountOut);
     std::string generateVertexShaderForInputLayout(
         const std::string &sourceShader,
         const gl::InputLayout &inputLayout,
@@ -112,15 +86,6 @@
   private:
     RendererD3D *const mRenderer;
 
-    struct SemanticInfo;
-
-    std::string getVaryingSemantic(bool programUsesPointSize) const;
-    SemanticInfo getSemanticInfo(ShaderType shaderType,
-                                 unsigned int startRegisters,
-                                 bool position,
-                                 bool fragCoord,
-                                 bool pointCoord,
-                                 bool pointSize) const;
     void generateVaryingLinkHLSL(const gl::Caps &caps,
                                  bool programUsesPointSize,
                                  const SemanticInfo &info,
@@ -142,6 +107,8 @@
     std::string generateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType,
                                                 const sh::ShaderVariable &shaderAttrib) const;
 };
+
+std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize);
 }
 
 #endif  // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 9268bff..21eb6b5 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -20,6 +20,7 @@
 #include "libANGLE/renderer/d3d/RendererD3D.h"
 #include "libANGLE/renderer/d3d/ShaderD3D.h"
 #include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+#include "libANGLE/renderer/d3d/VaryingPacking.h"
 #include "libANGLE/renderer/d3d/VertexDataManager.h"
 
 namespace rx
@@ -1261,8 +1262,8 @@
 
     // Map the varyings to the register file
     unsigned int registerCount = 0;
-    if (!mDynamicHLSL->packVaryings(*data.caps, infoLog, &packedVaryings,
-                                    mData.getTransformFeedbackVaryingNames(), &registerCount))
+    if (!PackVaryings(*data.caps, infoLog, &packedVaryings,
+                      mData.getTransformFeedbackVaryingNames(), &registerCount))
     {
         return LinkResult(false, gl::Error(GL_NO_ERROR));
     }
diff --git a/src/libANGLE/renderer/d3d/VaryingPacking.cpp b/src/libANGLE/renderer/d3d/VaryingPacking.cpp
new file mode 100644
index 0000000..0de512b
--- /dev/null
+++ b/src/libANGLE/renderer/d3d/VaryingPacking.cpp
@@ -0,0 +1,423 @@
+//
+// 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.
+//
+// VaryingPacking:
+//   Class which describes a mapping from varyings to registers in D3D
+//   for linking between shader stages.
+//
+
+#include "libANGLE/renderer/d3d/VaryingPacking.h"
+
+#include "common/utilities.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+
+namespace rx
+{
+
+SemanticInfo::BuiltinInfo::BuiltinInfo() : enabled(false), index(0), systemValue(false)
+{
+}
+
+std::string SemanticInfo::BuiltinInfo::str() const
+{
+    return (systemValue ? semantic : (semantic + Str(index)));
+}
+
+void SemanticInfo::BuiltinInfo::enableSystem(const std::string &systemValueSemantic)
+{
+    enabled     = true;
+    semantic    = systemValueSemantic;
+    systemValue = true;
+}
+
+void SemanticInfo::BuiltinInfo::enable(const std::string &semanticVal, unsigned int indexVal)
+{
+    enabled  = true;
+    semantic = semanticVal;
+    index    = indexVal;
+}
+
+bool PackVarying(PackedVarying *packedVarying, const int maxVaryingVectors, VaryingPacking &packing)
+{
+    // Make sure we use transposed matrix types to count registers correctly.
+    int registers = 0;
+    int elements  = 0;
+
+    const sh::Varying &varying = *packedVarying->varying;
+
+    if (varying.isStruct())
+    {
+        registers = HLSLVariableRegisterCount(varying, true) * varying.elementCount();
+        elements  = 4;
+    }
+    else
+    {
+        GLenum transposedType = gl::TransposeMatrixType(varying.type);
+        registers             = gl::VariableRowCount(transposedType) * varying.elementCount();
+        elements              = gl::VariableColumnCount(transposedType);
+    }
+
+    if (elements >= 2 && elements <= 4)
+    {
+        for (int r = 0; r <= maxVaryingVectors - registers; r++)
+        {
+            bool available = true;
+
+            for (int y = 0; y < registers && available; y++)
+            {
+                for (int x = 0; x < elements && available; x++)
+                {
+                    if (packing[r + y][x])
+                    {
+                        available = false;
+                    }
+                }
+            }
+
+            if (available)
+            {
+                packedVarying->registerIndex = r;
+                packedVarying->columnIndex   = 0;
+
+                for (int y = 0; y < registers; y++)
+                {
+                    for (int x = 0; x < elements; x++)
+                    {
+                        packing[r + y][x] = packedVarying;
+                    }
+                }
+
+                return true;
+            }
+        }
+
+        if (elements == 2)
+        {
+            for (int r = maxVaryingVectors - registers; r >= 0; r--)
+            {
+                bool available = true;
+
+                for (int y = 0; y < registers && available; y++)
+                {
+                    for (int x = 2; x < 4 && available; x++)
+                    {
+                        if (packing[r + y][x])
+                        {
+                            available = false;
+                        }
+                    }
+                }
+
+                if (available)
+                {
+                    packedVarying->registerIndex = r;
+                    packedVarying->columnIndex   = 2;
+
+                    for (int y = 0; y < registers; y++)
+                    {
+                        for (int x = 2; x < 4; x++)
+                        {
+                            packing[r + y][x] = packedVarying;
+                        }
+                    }
+
+                    return true;
+                }
+            }
+        }
+    }
+    else if (elements == 1)
+    {
+        int space[4] = {0};
+
+        for (int y = 0; y < maxVaryingVectors; y++)
+        {
+            for (int x = 0; x < 4; x++)
+            {
+                space[x] += packing[y][x] ? 0 : 1;
+            }
+        }
+
+        int column = 0;
+
+        for (int x = 0; x < 4; x++)
+        {
+            if (space[x] >= registers && (space[column] < registers || space[x] < space[column]))
+            {
+                column = x;
+            }
+        }
+
+        if (space[column] >= registers)
+        {
+            for (int r = 0; r < maxVaryingVectors; r++)
+            {
+                if (!packing[r][column])
+                {
+                    packedVarying->registerIndex = r;
+                    packedVarying->columnIndex   = column;
+
+                    for (int y = r; y < r + registers; y++)
+                    {
+                        packing[y][column] = packedVarying;
+                    }
+
+                    break;
+                }
+            }
+
+            return true;
+        }
+    }
+    else
+        UNREACHABLE();
+
+    return false;
+}
+
+unsigned int PackedVaryingRegister::registerIndex(
+    const gl::Caps &caps,
+    const std::vector<PackedVarying> &packedVaryings) const
+{
+    const PackedVarying &packedVarying = packedVaryings[varyingIndex];
+    const sh::Varying &varying         = *packedVarying.varying;
+
+    GLenum transposedType = gl::TransposeMatrixType(varying.type);
+    unsigned int variableRows =
+        static_cast<unsigned int>(varying.isStruct() ? 1 : gl::VariableRowCount(transposedType));
+
+    return (elementIndex * variableRows + (packedVarying.columnIndex * caps.maxVaryingVectors) +
+            (packedVarying.registerIndex + rowIndex));
+}
+
+PackedVaryingIterator::PackedVaryingIterator(const std::vector<PackedVarying> &packedVaryings)
+    : mPackedVaryings(packedVaryings), mEnd(*this)
+{
+    mEnd.setEnd();
+}
+
+PackedVaryingIterator::Iterator PackedVaryingIterator::begin() const
+{
+    return Iterator(*this);
+}
+
+const PackedVaryingIterator::Iterator &PackedVaryingIterator::end() const
+{
+    return mEnd;
+}
+
+PackedVaryingIterator::Iterator::Iterator(const PackedVaryingIterator &parent) : mParent(parent)
+{
+    while (mRegister.varyingIndex < mParent.mPackedVaryings.size() &&
+           !mParent.mPackedVaryings[mRegister.varyingIndex].registerAssigned())
+    {
+        ++mRegister.varyingIndex;
+    }
+}
+
+PackedVaryingIterator::Iterator &PackedVaryingIterator::Iterator::operator++()
+{
+    const sh::Varying *varying = mParent.mPackedVaryings[mRegister.varyingIndex].varying;
+    GLenum transposedType = gl::TransposeMatrixType(varying->type);
+    unsigned int variableRows =
+        static_cast<unsigned int>(varying->isStruct() ? 1 : gl::VariableRowCount(transposedType));
+
+    // Innermost iteration: row count
+    if (mRegister.rowIndex + 1 < variableRows)
+    {
+        ++mRegister.rowIndex;
+        return *this;
+    }
+
+    mRegister.rowIndex = 0;
+
+    // Middle iteration: element count
+    if (mRegister.elementIndex + 1 < varying->elementCount())
+    {
+        ++mRegister.elementIndex;
+        return *this;
+    }
+
+    mRegister.elementIndex = 0;
+
+    // Outer iteration: the varying itself. Once we pass the last varying, this Iterator will
+    // equal the end Iterator.
+    do
+    {
+        ++mRegister.varyingIndex;
+    } while (mRegister.varyingIndex < mParent.mPackedVaryings.size() &&
+             !mParent.mPackedVaryings[mRegister.varyingIndex].registerAssigned());
+    return *this;
+}
+
+bool PackedVaryingIterator::Iterator::operator==(const Iterator &other) const
+{
+    return mRegister.elementIndex == other.mRegister.elementIndex &&
+           mRegister.rowIndex == other.mRegister.rowIndex &&
+           mRegister.varyingIndex == other.mRegister.varyingIndex;
+}
+
+bool PackedVaryingIterator::Iterator::operator!=(const Iterator &other) const
+{
+    return !(*this == other);
+}
+
+// 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
+bool PackVaryings(const gl::Caps &caps,
+                  gl::InfoLog &infoLog,
+                  std::vector<PackedVarying> *packedVaryings,
+                  const std::vector<std::string> &transformFeedbackVaryings,
+                  unsigned int *registerCountOut)
+{
+    VaryingPacking packing = {};
+    *registerCountOut      = 0;
+
+    std::set<std::string> uniqueVaryingNames;
+
+    for (PackedVarying &packedVarying : *packedVaryings)
+    {
+        const sh::Varying &varying = *packedVarying.varying;
+
+        // Do not assign registers to built-in or unreferenced varyings
+        if (varying.isBuiltIn() || !varying.staticUse)
+        {
+            continue;
+        }
+
+        ASSERT(uniqueVaryingNames.count(varying.name) == 0);
+
+        if (PackVarying(&packedVarying, caps.maxVaryingVectors, packing))
+        {
+            uniqueVaryingNames.insert(varying.name);
+        }
+        else
+        {
+            infoLog << "Could not pack varying " << varying.name;
+            return false;
+        }
+    }
+
+    for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings)
+    {
+        if (transformFeedbackVaryingName.compare(0, 3, "gl_") == 0)
+        {
+            // do not pack builtin XFB varyings
+            continue;
+        }
+
+        for (PackedVarying &packedVarying : *packedVaryings)
+        {
+            const sh::Varying &varying = *packedVarying.varying;
+
+            // Make sure transform feedback varyings aren't optimized out.
+            if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0)
+            {
+                bool found = false;
+                if (transformFeedbackVaryingName == varying.name)
+                {
+                    if (!PackVarying(&packedVarying, caps.maxVaryingVectors, packing))
+                    {
+                        infoLog << "Could not pack varying " << varying.name;
+                        return false;
+                    }
+
+                    found = true;
+                    break;
+                }
+                if (!found)
+                {
+                    infoLog << "Transform feedback varying " << transformFeedbackVaryingName
+                            << " does not exist in the vertex shader.";
+                    return false;
+                }
+            }
+
+            // Add duplicate transform feedback varyings for 'flat' shaded attributes. This is
+            // necessary because we write out modified vertex data to correct for the provoking
+            // vertex in D3D11. This extra transform feedback varying is the unmodified stream.
+            if (varying.interpolation == sh::INTERPOLATION_FLAT)
+            {
+                sh::Varying duplicateVarying(varying);
+                duplicateVarying.name = "StreamOut_" + duplicateVarying.name;
+            }
+        }
+    }
+
+    // Return the number of used registers
+    for (GLuint r = 0; r < caps.maxVaryingVectors; r++)
+    {
+        if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
+        {
+            (*registerCountOut)++;
+        }
+    }
+
+    return true;
+}
+
+SemanticInfo GetSemanticInfo(ShaderType shaderType,
+                             int majorShaderModel,
+                             unsigned int startRegisters,
+                             bool position,
+                             bool fragCoord,
+                             bool pointCoord,
+                             bool pointSize)
+{
+    SemanticInfo info;
+    bool hlsl4                         = (majorShaderModel >= 4);
+    const std::string &varyingSemantic = GetVaryingSemantic(majorShaderModel, pointSize);
+
+    unsigned int reservedRegisterIndex = startRegisters;
+
+    if (hlsl4)
+    {
+        info.dxPosition.enableSystem("SV_Position");
+    }
+    else if (shaderType == SHADER_PIXEL)
+    {
+        info.dxPosition.enableSystem("VPOS");
+    }
+    else
+    {
+        info.dxPosition.enableSystem("POSITION");
+    }
+
+    if (position)
+    {
+        info.glPosition.enable(varyingSemantic, reservedRegisterIndex++);
+    }
+
+    if (fragCoord)
+    {
+        info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++);
+    }
+
+    if (pointCoord)
+    {
+        // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+        // In D3D11 we manually compute gl_PointCoord in the GS.
+        if (hlsl4)
+        {
+            info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++);
+        }
+        else
+        {
+            info.glPointCoord.enable("TEXCOORD", 0);
+        }
+    }
+
+    // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
+    if (pointSize && (shaderType != SHADER_PIXEL || hlsl4))
+    {
+        info.glPointSize.enableSystem("PSIZE");
+    }
+
+    return info;
+}
+
+}  // namespace rx
diff --git a/src/libANGLE/renderer/d3d/VaryingPacking.h b/src/libANGLE/renderer/d3d/VaryingPacking.h
new file mode 100644
index 0000000..61e6123
--- /dev/null
+++ b/src/libANGLE/renderer/d3d/VaryingPacking.h
@@ -0,0 +1,131 @@
+//
+// 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.
+//
+// VaryingPacking:
+//   Class which describes a mapping from varyings to registers in D3D
+//   for linking between shader stages.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
+#define LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
+
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+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;
+};
+
+struct PackedVaryingRegister final
+{
+    PackedVaryingRegister() : varyingIndex(0), elementIndex(0), rowIndex(0) {}
+
+    PackedVaryingRegister(const PackedVaryingRegister &) = default;
+    PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
+
+    unsigned int registerIndex(const gl::Caps &caps,
+                               const std::vector<PackedVarying> &packedVaryings) const;
+
+    size_t varyingIndex;
+    unsigned int elementIndex;
+    unsigned int rowIndex;
+};
+
+class PackedVaryingIterator final : public angle::NonCopyable
+{
+  public:
+    PackedVaryingIterator(const std::vector<PackedVarying> &packedVaryings);
+
+    class Iterator final
+    {
+      public:
+        Iterator(const PackedVaryingIterator &parent);
+
+        Iterator(const Iterator &) = default;
+        Iterator &operator=(const Iterator &) = delete;
+
+        Iterator &operator++();
+        bool operator==(const Iterator &other) const;
+        bool operator!=(const Iterator &other) const;
+
+        const PackedVaryingRegister &operator*() const { return mRegister; }
+        void setEnd() { mRegister.varyingIndex = mParent.mPackedVaryings.size(); }
+
+      private:
+        const PackedVaryingIterator &mParent;
+        PackedVaryingRegister mRegister;
+    };
+
+    Iterator begin() const;
+    const Iterator &end() const;
+
+  private:
+    const std::vector<PackedVarying> &mPackedVaryings;
+    Iterator mEnd;
+};
+
+typedef const PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4];
+
+bool PackVaryings(const gl::Caps &caps,
+                  gl::InfoLog &infoLog,
+                  std::vector<PackedVarying> *packedVaryings,
+                  const std::vector<std::string> &transformFeedbackVaryings,
+                  unsigned int *registerCountOut);
+
+struct SemanticInfo final
+{
+    struct BuiltinInfo final
+    {
+        BuiltinInfo();
+
+        std::string str() const;
+        void enableSystem(const std::string &systemValueSemantic);
+        void enable(const std::string &semanticVal, unsigned int indexVal);
+
+        bool enabled;
+        std::string semantic;
+        unsigned int index;
+        bool systemValue;
+    };
+
+    BuiltinInfo dxPosition;
+    BuiltinInfo glPosition;
+    BuiltinInfo glFragCoord;
+    BuiltinInfo glPointCoord;
+    BuiltinInfo glPointSize;
+};
+
+SemanticInfo GetSemanticInfo(ShaderType shaderType,
+                             int majorShaderModel,
+                             unsigned int startRegisters,
+                             bool position,
+                             bool fragCoord,
+                             bool pointCoord,
+                             bool pointSize);
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
diff --git a/src/libGLESv2.gypi b/src/libGLESv2.gypi
index 3e54a6b..ddb60bb 100644
--- a/src/libGLESv2.gypi
+++ b/src/libGLESv2.gypi
@@ -223,6 +223,8 @@
             'libANGLE/renderer/d3d/TextureStorage.h',
             'libANGLE/renderer/d3d/TransformFeedbackD3D.cpp',
             'libANGLE/renderer/d3d/TransformFeedbackD3D.h',
+            'libANGLE/renderer/d3d/VaryingPacking.cpp',
+            'libANGLE/renderer/d3d/VaryingPacking.h',
             'libANGLE/renderer/d3d/VertexBuffer.cpp',
             'libANGLE/renderer/d3d/VertexBuffer.h',
             'libANGLE/renderer/d3d/VertexDataManager.cpp',