ProgramD3D: Move some common code into a Metadata class.

This metadata class captures some of our commonly referenced but also
complex flats into a shared place. We can then re-use them in the
semantic code, the DynamicHLSL linking code, and the program code.

Refactoring patch only.

BUG=angleproject:1202

Change-Id: I8b6088cfa5488c5173a6f06c15abab5a4ead4cb8
Reviewed-on: https://chromium-review.googlesource.com/311700
Tryjob-Request: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/ShaderImpl.h b/src/libANGLE/renderer/ShaderImpl.h
index 3f2921e..5a46637 100644
--- a/src/libANGLE/renderer/ShaderImpl.h
+++ b/src/libANGLE/renderer/ShaderImpl.h
@@ -29,6 +29,8 @@
 
     virtual std::string getDebugInfo() const = 0;
 
+    const gl::Shader::Data &getData() const { return mData; }
+
   protected:
     const gl::Shader::Data &mData;
 };
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
index 0640407..8f5f006 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -444,14 +444,13 @@
 
 bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
                                          const gl::Program::Data &programData,
+                                         const ProgramD3DMetadata &programMetadata,
                                          InfoLog &infoLog,
                                          unsigned int registerCount,
                                          std::string *pixelHLSL,
                                          std::string *vertexHLSL,
                                          const std::vector<PackedVarying> &packedVaryings,
-                                         std::vector<D3DVarying> *d3dVaryingsOut,
-                                         std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
-                                         bool *outUsesFragDepth) const
+                                         std::vector<D3DVarying> *d3dVaryingsOut) const
 {
     ASSERT(pixelHLSL->empty() && vertexHLSL->empty());
 
@@ -461,15 +460,12 @@
     const ShaderD3D *fragmentShader    = GetImplAs<ShaderD3D>(fragmentShaderGL);
     const int shaderModel              = mRenderer->getMajorShaderModel();
 
-    bool usesMRT        = fragmentShader->usesMultipleRenderTargets();
-    bool usesFragCoord  = fragmentShader->usesFragCoord();
+    bool usesFragCoord  = programMetadata.usesFragCoord();
     bool usesPointCoord = fragmentShader->usesPointCoord();
     bool usesPointSize = vertexShader->usesPointSize();
     bool useInstancedPointSpriteEmulation =
-        usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
-    bool insertDummyPointCoordValue = !usesPointSize && usesPointCoord && shaderModel >= 4;
-    bool addPointCoord =
-        (useInstancedPointSpriteEmulation && usesPointCoord) || insertDummyPointCoordValue;
+        programMetadata.usesPointSize() &&
+        mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
 
     // Validation done in the compiler
     ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData());
@@ -478,19 +474,6 @@
     const unsigned int registersNeeded =
         registerCount + (usesFragCoord ? 1u : 0u) + (usesPointCoord ? 1u : 0u);
 
-    // Two cases when writing to gl_FragColor and using ESSL 1.0:
-    // - with a 3.0 context, the output color is copied to channel 0
-    // - with a 2.0 context, the output color is broadcast to all channels
-    const bool broadcast                = (fragmentShader->usesFragColor() && data.clientVersion < 3);
-    const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1);
-
-    // gl_Position only needs to be outputted from the vertex shader if transform feedback is
-    // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
-    // the vertex shader in this case. This saves us 1 output vector.
-    bool outputPositionFromVS = !(shaderModel >= 4 && mRenderer->getShaderModelSuffix() != "");
-
-    int shaderVersion = vertexShaderGL->getShaderVersion();
-
     if (static_cast<GLuint>(registersNeeded) > data.caps->maxVaryingVectors)
     {
         infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord";
@@ -504,9 +487,8 @@
     // 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, shaderModel, registerCount, outputPositionFromVS, usesFragCoord,
-        addPointCoord, (!useInstancedPointSpriteEmulation && usesPointSize));
+    const SemanticInfo &vertexSemantics =
+        GetSemanticInfo(SHADER_VERTEX, programMetadata, registerCount);
 
     storeUserVaryings(packedVaryings, usesPointSize, d3dVaryingsOut);
     storeBuiltinVaryings(vertexSemantics, d3dVaryingsOut);
@@ -545,7 +527,7 @@
                  << "\n"
                  << "    VS_OUTPUT output;\n";
 
-    if (outputPositionFromVS)
+    if (vertexSemantics.glPosition.enabled)
     {
         vertexStream << "    output.gl_Position = gl_Position;\n";
     }
@@ -614,7 +596,7 @@
                         "gl_PointSize / (dx_ViewCoords.y*2), input.spriteVertexPos.z) * "
                         "output.dx_Position.w;\n";
 
-        if (usesPointCoord)
+        if (programMetadata.usesPointCoord())
         {
             vertexStream << "\n"
                          << "    output.gl_PointCoord = input.spriteTexCoord;\n";
@@ -624,7 +606,7 @@
     // Renderers that enable instanced pointsprite emulation require the vertex shader output member
     // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same
     // default value used in the generated pixel shader.
-    if (insertDummyPointCoordValue)
+    if (programMetadata.usesInsertedPointCoordValue())
     {
         ASSERT(!useInstancedPointSpriteEmulation);
         vertexStream << "\n"
@@ -638,57 +620,13 @@
     std::stringstream pixelStream;
     pixelStream << fragmentShaderGL->getTranslatedSource();
 
-    const SemanticInfo &pixelSemantics = GetSemanticInfo(
-        SHADER_PIXEL, shaderModel, registerCount, outputPositionFromVS, usesFragCoord,
-        usesPointCoord, (!useInstancedPointSpriteEmulation && usesPointSize));
+    const SemanticInfo &pixelSemantics =
+        GetSemanticInfo(SHADER_PIXEL, programMetadata, registerCount);
 
     pixelStream << "struct PS_INPUT\n";
     generateVaryingLinkHLSL(*data.caps, usesPointSize, pixelSemantics, packedVaryings, pixelStream);
     pixelStream << "\n";
 
-    if (shaderVersion < 300)
-    {
-        for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets;
-             renderTargetIndex++)
-        {
-            PixelShaderOutputVariable outputKeyVariable;
-            outputKeyVariable.type = GL_FLOAT_VEC4;
-            outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
-            outputKeyVariable.source =
-                broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
-            outputKeyVariable.outputIndex = renderTargetIndex;
-
-            outPixelShaderKey->push_back(outputKeyVariable);
-        }
-
-        *outUsesFragDepth = fragmentShader->usesFragDepth();
-    }
-    else
-    {
-        const auto &shaderOutputVars = fragmentShaderGL->getActiveOutputVariables();
-
-        for (auto outputPair : programData.getOutputVariables())
-        {
-            const VariableLocation &outputLocation   = outputPair.second;
-            const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
-            const std::string &variableName = "out_" + outputLocation.name;
-            const std::string &elementString =
-                (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
-
-            ASSERT(outputVariable.staticUse);
-
-            PixelShaderOutputVariable outputKeyVariable;
-            outputKeyVariable.type        = outputVariable.type;
-            outputKeyVariable.name        = variableName + elementString;
-            outputKeyVariable.source      = variableName + ArrayString(outputLocation.element);
-            outputKeyVariable.outputIndex = outputPair.first;
-
-            outPixelShaderKey->push_back(outputKeyVariable);
-        }
-
-        *outUsesFragDepth = false;
-    }
-
     pixelStream << PIXEL_OUTPUT_STUB_STRING + "\n";
 
     if (fragmentShader->usesFrontFacing())
@@ -830,6 +768,7 @@
 std::string DynamicHLSL::generateGeometryShaderPreamble(
     const gl::Data &data,
     const gl::Program::Data &programData,
+    const ProgramD3DMetadata &programMetadata,
     unsigned int registerCount,
     const std::vector<PackedVarying> &packedVaryings) const
 {
@@ -844,14 +783,12 @@
     ASSERT(vertexShader && fragmentShader);
 
     bool usesFragCoord  = fragmentShader->usesFragCoord();
-    bool usesPointCoord = fragmentShader->usesPointCoord();
     bool usesPointSize  = vertexShader->usesPointSize();
 
-    const SemanticInfo &inSemantics = GetSemanticInfo(
-        SHADER_VERTEX, majorShaderModel, registerCount, true, usesFragCoord, false, usesPointSize);
+    const SemanticInfo &inSemantics =
+        GetSemanticInfo(SHADER_VERTEX, programMetadata, registerCount);
     const SemanticInfo &outSemantics =
-        GetSemanticInfo(SHADER_GEOMETRY, majorShaderModel, registerCount, true, usesFragCoord,
-                        usesPointCoord, usesPointSize);
+        GetSemanticInfo(SHADER_GEOMETRY, programMetadata, registerCount);
 
     std::stringstream preambleStream;
 
@@ -1085,4 +1022,58 @@
     // No conversion necessary
     return attribString;
 }
+
+void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data,
+                                          const gl::Program::Data &programData,
+                                          const ProgramD3DMetadata &metadata,
+                                          std::vector<PixelShaderOutputVariable> *outPixelShaderKey)
+{
+    // Two cases when writing to gl_FragColor and using ESSL 1.0:
+    // - with a 3.0 context, the output color is copied to channel 0
+    // - with a 2.0 context, the output color is broadcast to all channels
+    bool broadcast = metadata.usesBroadcast(data);
+    const unsigned int numRenderTargets =
+        (broadcast || metadata.usesMultipleFragmentOuts() ? data.caps->maxDrawBuffers : 1);
+
+    if (metadata.getMajorShaderVersion() < 300)
+    {
+        for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets;
+             renderTargetIndex++)
+        {
+            PixelShaderOutputVariable outputKeyVariable;
+            outputKeyVariable.type = GL_FLOAT_VEC4;
+            outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
+            outputKeyVariable.source =
+                broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
+            outputKeyVariable.outputIndex = renderTargetIndex;
+
+            outPixelShaderKey->push_back(outputKeyVariable);
+        }
+    }
+    else
+    {
+        const auto &shaderOutputVars =
+            metadata.getFragmentShader()->getData().getActiveOutputVariables();
+
+        for (auto outputPair : programData.getOutputVariables())
+        {
+            const VariableLocation &outputLocation   = outputPair.second;
+            const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
+            const std::string &variableName = "out_" + outputLocation.name;
+            const std::string &elementString =
+                (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
+
+            ASSERT(outputVariable.staticUse);
+
+            PixelShaderOutputVariable outputKeyVariable;
+            outputKeyVariable.type        = outputVariable.type;
+            outputKeyVariable.name        = variableName + elementString;
+            outputKeyVariable.source      = variableName + ArrayString(outputLocation.element);
+            outputKeyVariable.outputIndex = outputPair.first;
+
+            outPixelShaderKey->push_back(outputKeyVariable);
+        }
+    }
+}
+
 }  // namespace rx
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/libANGLE/renderer/d3d/DynamicHLSL.h
index 3f960ca..a42c50f 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.h
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -36,6 +36,7 @@
 namespace rx
 {
 struct PackedVarying;
+class ProgramD3DMetadata;
 struct SemanticInfo;
 class ShaderD3D;
 
@@ -63,18 +64,18 @@
         const std::vector<GLenum> &outputLayout) const;
     bool generateShaderLinkHLSL(const gl::Data &data,
                                 const gl::Program::Data &programData,
+                                const ProgramD3DMetadata &programMetadata,
                                 gl::InfoLog &infoLog,
                                 unsigned int registerCount,
                                 std::string *pixelHLSL,
                                 std::string *vertexHLSL,
                                 const std::vector<PackedVarying> &packedVaryings,
-                                std::vector<D3DVarying> *d3dVaryingsOut,
-                                std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
-                                bool *outUsesFragDepth) const;
+                                std::vector<D3DVarying> *d3dVaryingsOut) const;
 
     std::string generateGeometryShaderPreamble(
         const gl::Data &data,
         const gl::Program::Data &programData,
+        const ProgramD3DMetadata &programMetadata,
         unsigned int registers,
         const std::vector<PackedVarying> &packedVaryings) const;
 
@@ -83,6 +84,11 @@
                                            const gl::Program::Data &programData,
                                            const std::string &preambleString) const;
 
+    void getPixelShaderOutputKey(const gl::Data &data,
+                                 const gl::Program::Data &programData,
+                                 const ProgramD3DMetadata &metadata,
+                                 std::vector<PixelShaderOutputVariable> *outPixelShaderKey);
+
   private:
     RendererD3D *const mRenderer;
 
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 21eb6b5..d937441 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -363,6 +363,98 @@
 {
 }
 
+// ProgramD3DMetadata Implementation
+
+ProgramD3DMetadata::ProgramD3DMetadata(int rendererMajorShaderModel,
+                                       const std::string &shaderModelSuffix,
+                                       bool usesInstancedPointSpriteEmulation,
+                                       const ShaderD3D *vertexShader,
+                                       const ShaderD3D *fragmentShader)
+    : mRendererMajorShaderModel(rendererMajorShaderModel),
+      mShaderModelSuffix(shaderModelSuffix),
+      mUsesInstancedPointSpriteEmulation(usesInstancedPointSpriteEmulation),
+      mVertexShader(vertexShader),
+      mFragmentShader(fragmentShader)
+{
+}
+
+int ProgramD3DMetadata::getRendererMajorShaderModel() const
+{
+    return mRendererMajorShaderModel;
+}
+
+bool ProgramD3DMetadata::usesBroadcast(const gl::Data &data) const
+{
+    return (mFragmentShader->usesFragColor() && data.clientVersion < 3);
+}
+
+bool ProgramD3DMetadata::usesFragDepth(const gl::Program::Data &programData) const
+{
+    // TODO(jmadill): Rename this or check if we need it for version 300
+    return (getMajorShaderVersion() < 300 && mFragmentShader->usesFragDepth());
+}
+
+bool ProgramD3DMetadata::usesPointCoord() const
+{
+    return mFragmentShader->usesPointCoord();
+}
+
+bool ProgramD3DMetadata::usesFragCoord() const
+{
+    return mFragmentShader->usesFragCoord();
+}
+
+bool ProgramD3DMetadata::usesPointSize() const
+{
+    return mVertexShader->usesPointSize();
+}
+
+bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
+{
+    return !usesPointSize() && usesPointCoord() && mRendererMajorShaderModel >= 4;
+}
+
+bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
+{
+    // 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.
+    // GeometryShader PointSprite emulation does not require this additional entry because the
+    // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the
+    // 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.
+    return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
+           usesInsertedPointCoordValue();
+}
+
+bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
+{
+    // gl_Position only needs to be outputted from the vertex shader if transform feedback is
+    // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
+    // the vertex shader in this case. This saves us 1 output vector.
+    return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
+}
+
+bool ProgramD3DMetadata::usesSystemValuePointSize() const
+{
+    return !mUsesInstancedPointSpriteEmulation && usesPointSize();
+}
+
+bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
+{
+    return mFragmentShader->usesMultipleRenderTargets();
+}
+
+GLint ProgramD3DMetadata::getMajorShaderVersion() const
+{
+    return mVertexShader->getData().getShaderVersion();
+}
+
+const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
+{
+    return mFragmentShader;
+}
+
 // ProgramD3D Implementation
 
 ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
@@ -1268,15 +1360,21 @@
         return LinkResult(false, gl::Error(GL_NO_ERROR));
     }
 
+    ProgramD3DMetadata metadata(mRenderer->getMajorShaderModel(), mRenderer->getShaderModelSuffix(),
+                                usesInstancedPointSpriteEmulation(), vertexShaderD3D,
+                                fragmentShaderD3D);
+
     std::vector<D3DVarying> d3dVaryings;
-    if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registerCount, &mPixelHLSL,
-                                              &mVertexHLSL, packedVaryings, &d3dVaryings,
-                                              &mPixelShaderKey, &mUsesFragDepth))
+    if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, metadata, infoLog, registerCount,
+                                              &mPixelHLSL, &mVertexHLSL, packedVaryings,
+                                              &d3dVaryings))
     {
         return LinkResult(false, gl::Error(GL_NO_ERROR));
     }
 
     mUsesPointSize = vertexShaderD3D->usesPointSize();
+    mDynamicHLSL->getPixelShaderOutputKey(data, mData, metadata, &mPixelShaderKey);
+    mUsesFragDepth = metadata.usesFragDepth(mData);
 
     // Cache if we use flat shading
     for (const auto &varying : packedVaryings)
@@ -1291,7 +1389,7 @@
     if (mRenderer->getMajorShaderModel() >= 4)
     {
         mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
-            data, mData, registerCount, packedVaryings);
+            data, mData, metadata, registerCount, packedVaryings);
     }
 
     initSemanticIndex();
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/libANGLE/renderer/d3d/ProgramD3D.h
index 6238e90..17f381f 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -102,6 +102,37 @@
     unsigned int semanticIndexCount;
 };
 
+class ProgramD3DMetadata : angle::NonCopyable
+{
+  public:
+    ProgramD3DMetadata(int rendererMajorShaderModel,
+                       const std::string &shaderModelSuffix,
+                       bool usesInstancedPointSpriteEmulation,
+                       const ShaderD3D *vertexShader,
+                       const ShaderD3D *fragmentShader);
+
+    int getRendererMajorShaderModel() const;
+    bool usesBroadcast(const gl::Data &data) const;
+    bool usesFragDepth(const gl::Program::Data &programData) const;
+    bool usesPointCoord() const;
+    bool usesFragCoord() const;
+    bool usesPointSize() const;
+    bool usesInsertedPointCoordValue() const;
+    bool addsPointCoordToVertexShader() const;
+    bool usesTransformFeedbackGLPosition() const;
+    bool usesSystemValuePointSize() const;
+    bool usesMultipleFragmentOuts() const;
+    GLint getMajorShaderVersion() const;
+    const ShaderD3D *getFragmentShader() const;
+
+  private:
+    const int mRendererMajorShaderModel;
+    const std::string mShaderModelSuffix;
+    const bool mUsesInstancedPointSpriteEmulation;
+    const ShaderD3D *mVertexShader;
+    const ShaderD3D *mFragmentShader;
+};
+
 class ProgramD3D : public ProgramImpl
 {
   public:
diff --git a/src/libANGLE/renderer/d3d/VaryingPacking.cpp b/src/libANGLE/renderer/d3d/VaryingPacking.cpp
index 0de512b..94f1857 100644
--- a/src/libANGLE/renderer/d3d/VaryingPacking.cpp
+++ b/src/libANGLE/renderer/d3d/VaryingPacking.cpp
@@ -13,6 +13,7 @@
 #include "common/utilities.h"
 #include "compiler/translator/blocklayoutHLSL.h"
 #include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
 
 namespace rx
 {
@@ -361,19 +362,21 @@
 }
 
 SemanticInfo GetSemanticInfo(ShaderType shaderType,
-                             int majorShaderModel,
-                             unsigned int startRegisters,
-                             bool position,
-                             bool fragCoord,
-                             bool pointCoord,
-                             bool pointSize)
+                             const ProgramD3DMetadata &programMetadata,
+                             unsigned int startRegisters)
 {
-    SemanticInfo info;
-    bool hlsl4                         = (majorShaderModel >= 4);
-    const std::string &varyingSemantic = GetVaryingSemantic(majorShaderModel, pointSize);
+    int majorShaderModel = programMetadata.getRendererMajorShaderModel();
+    bool position        = programMetadata.usesTransformFeedbackGLPosition();
+    bool fragCoord       = programMetadata.usesFragCoord();
+    bool pointCoord = shaderType == SHADER_VERTEX ? programMetadata.addsPointCoordToVertexShader()
+                                                  : programMetadata.usesPointCoord();
+    bool pointSize = programMetadata.usesSystemValuePointSize();
+    bool hlsl4     = (majorShaderModel >= 4);
 
+    const std::string &userSemantic    = GetVaryingSemantic(majorShaderModel, pointSize);
     unsigned int reservedRegisterIndex = startRegisters;
 
+    SemanticInfo info;
     if (hlsl4)
     {
         info.dxPosition.enableSystem("SV_Position");
@@ -389,12 +392,12 @@
 
     if (position)
     {
-        info.glPosition.enable(varyingSemantic, reservedRegisterIndex++);
+        info.glPosition.enable(userSemantic, reservedRegisterIndex++);
     }
 
     if (fragCoord)
     {
-        info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++);
+        info.glFragCoord.enable(userSemantic, reservedRegisterIndex++);
     }
 
     if (pointCoord)
@@ -403,7 +406,7 @@
         // In D3D11 we manually compute gl_PointCoord in the GS.
         if (hlsl4)
         {
-            info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++);
+            info.glPointCoord.enable(userSemantic, reservedRegisterIndex++);
         }
         else
         {
diff --git a/src/libANGLE/renderer/d3d/VaryingPacking.h b/src/libANGLE/renderer/d3d/VaryingPacking.h
index 61e6123..9d32a4f 100644
--- a/src/libANGLE/renderer/d3d/VaryingPacking.h
+++ b/src/libANGLE/renderer/d3d/VaryingPacking.h
@@ -15,6 +15,7 @@
 
 namespace rx
 {
+class ProgramD3DMetadata;
 
 struct PackedVarying
 {
@@ -119,12 +120,8 @@
 };
 
 SemanticInfo GetSemanticInfo(ShaderType shaderType,
-                             int majorShaderModel,
-                             unsigned int startRegisters,
-                             bool position,
-                             bool fragCoord,
-                             bool pointCoord,
-                             bool pointSize);
+                             const ProgramD3DMetadata &programMetadata,
+                             unsigned int startRegisters);
 
 }  // namespace rx