Use the CollectVariables path on the HLSL translator.

This approach consolidates our two methods, and lets us reuse the
same code for both methods of variable collection.

BUG=angle:466

Change-Id: Ie92f76ff0b6d0d0dbfd211a234d0ab86290fa798
Reviewed-on: https://chromium-review.googlesource.com/213504
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <capn@chromium.org>
diff --git a/src/compiler/translator/Compiler.h b/src/compiler/translator/Compiler.h
index 6bef5c1..ca0c157 100644
--- a/src/compiler/translator/Compiler.h
+++ b/src/compiler/translator/Compiler.h
@@ -83,6 +83,9 @@
     ShShaderOutput getOutputType() const { return outputType; }
     std::string getBuiltInResourcesString() const { return builtInResourcesString; }
 
+    // Get the resources set by InitBuiltInSymbolTable
+    const ShBuiltInResources& getResources() const;
+
   protected:
     sh::GLenum getShaderType() const { return shaderType; }
     // Initialize symbol-table with built-in symbols.
@@ -128,8 +131,6 @@
     bool limitExpressionComplexity(TIntermNode* root);
     // Get built-in extensions with default behavior.
     const TExtensionBehavior& getExtensionBehavior() const;
-    // Get the resources set by InitBuiltInSymbolTable
-    const ShBuiltInResources& getResources() const;
 
     const ArrayBoundsClamper& getArrayBoundsClamper() const;
     ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index defb34a..a5ea715 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -21,6 +21,7 @@
 #include "compiler/translator/util.h"
 #include "compiler/translator/UniformHLSL.h"
 #include "compiler/translator/StructureHLSL.h"
+#include "compiler/translator/TranslatorHLSL.h"
 
 #include <algorithm>
 #include <cfloat>
@@ -29,18 +30,6 @@
 namespace sh
 {
 
-static sh::Attribute MakeAttributeFromType(const TType &type, const TString &name)
-{
-    sh::Attribute attributeVar;
-    attributeVar.type = GLVariableType(type);
-    attributeVar.precision = GLVariablePrecision(type);
-    attributeVar.name = name.c_str();
-    attributeVar.arraySize = static_cast<unsigned int>(type.getArraySize());
-    attributeVar.location = type.getLayoutQualifier().location;
-
-    return attributeVar;
-}
-
 TString OutputHLSL::TextureFunction::name() const
 {
     TString name = "gl_texture";
@@ -105,8 +94,10 @@
     return false;
 }
 
-OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType)
-    : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType)
+OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator)
+    : TIntermTraverser(true, true, true),
+      mContext(context),
+      mOutputType(parentTranslator->getOutputType())
 {
     mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
     mInsideFunction = false;
@@ -138,6 +129,7 @@
     mUsesDiscardRewriting = false;
     mUsesNestedBreak = false;
 
+    const ShBuiltInResources &resources = parentTranslator->getResources();
     mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
 
     mUniqueIndex = 0;
@@ -150,7 +142,7 @@
     mExcessiveLoopIndex = NULL;
 
     mStructureHLSL = new StructureHLSL;
-    mUniformHLSL = new UniformHLSL(mStructureHLSL, mOutputType);
+    mUniformHLSL = new UniformHLSL(mStructureHLSL, parentTranslator);
 
     if (mOutputType == SH_HLSL9_OUTPUT)
     {
@@ -224,31 +216,6 @@
     return mBody;
 }
 
-const std::vector<sh::Uniform> &OutputHLSL::getUniforms()
-{
-    return mUniformHLSL->getUniforms();
-}
-
-const std::vector<sh::InterfaceBlock> &OutputHLSL::getInterfaceBlocks() const
-{
-    return mUniformHLSL->getInterfaceBlocks();
-}
-
-const std::vector<sh::Attribute> &OutputHLSL::getOutputVariables() const
-{
-    return mActiveOutputVariables;
-}
-
-const std::vector<sh::Attribute> &OutputHLSL::getAttributes() const
-{
-    return mActiveAttributes;
-}
-
-const std::vector<sh::Varying> &OutputHLSL::getVaryings() const
-{
-    return mActiveVaryings;
-}
-
 const std::map<std::string, unsigned int> &OutputHLSL::getInterfaceBlockRegisterMap() const
 {
     return mUniformHLSL->getInterfaceBlockRegisterMap();
@@ -336,8 +303,6 @@
         // Program linking depends on this exact format
         varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) + " " +
                     Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
-
-        declareVaryingToList(type, type.getQualifier(), name, mActiveVaryings);
     }
 
     for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++)
@@ -346,9 +311,6 @@
         const TString &name = attribute->second->getSymbol();
 
         attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
-
-        sh::Attribute attributeVar = MakeAttributeFromType(type, name);
-        mActiveAttributes.push_back(attributeVar);
     }
 
     out << mStructureHLSL->structsHeader();
@@ -384,9 +346,6 @@
 
                 out << "static " + TypeString(variableType) + " out_" + variableName + ArrayString(variableType) +
                        " = " + initializer(variableType) + ";\n";
-
-                sh::Attribute outputVar = MakeAttributeFromType(variableType, variableName);
-                mActiveOutputVariables.push_back(outputVar);
             }
         }
         else
@@ -2922,12 +2881,4 @@
     return constUnion;
 }
 
-void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier,
-                                      const TString &name, std::vector<Varying> &fieldsOut)
-{
-    GetVariableTraverser traverser;
-    traverser.traverse(type, name, &fieldsOut);
-    fieldsOut.back().interpolation = GetInterpolationType(baseTypeQualifier);
-}
-
 }
diff --git a/src/compiler/translator/OutputHLSL.h b/src/compiler/translator/OutputHLSL.h
index 61afc41..bec0247 100644
--- a/src/compiler/translator/OutputHLSL.h
+++ b/src/compiler/translator/OutputHLSL.h
@@ -27,17 +27,12 @@
 class OutputHLSL : public TIntermTraverser
 {
   public:
-    OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType);
+    OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator);
     ~OutputHLSL();
 
     void output();
 
     TInfoSinkBase &getBodyStream();
-    const std::vector<sh::Uniform> &getUniforms();
-    const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const;
-    const std::vector<sh::Attribute> &getOutputVariables() const;
-    const std::vector<sh::Attribute> &getAttributes() const;
-    const std::vector<sh::Varying> &getVaryings() const;
 
     const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const;
     const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
@@ -155,13 +150,8 @@
 
     TIntermSymbol *mExcessiveLoopIndex;
 
-    void declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector<sh::Varying>& fieldsOut);
-
     TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName);
 
-    std::vector<sh::Attribute> mActiveOutputVariables;
-    std::vector<sh::Attribute> mActiveAttributes;
-    std::vector<sh::Varying> mActiveVaryings;
     std::map<TIntermTyped*, TString> mFlaggedStructMappedNames;
     std::map<TIntermTyped*, TString> mFlaggedStructOriginalNames;
 
diff --git a/src/compiler/translator/TranslatorHLSL.cpp b/src/compiler/translator/TranslatorHLSL.cpp
index 52588e4..22bf60e 100644
--- a/src/compiler/translator/TranslatorHLSL.cpp
+++ b/src/compiler/translator/TranslatorHLSL.cpp
@@ -17,16 +17,10 @@
 void TranslatorHLSL::translate(TIntermNode *root)
 {
     TParseContext& parseContext = *GetGlobalParseContext();
-    sh::OutputHLSL outputHLSL(parseContext, getResources(), getOutputType());
+    sh::OutputHLSL outputHLSL(parseContext, this);
 
     outputHLSL.output();
 
-    attributes      = outputHLSL.getAttributes();
-    outputVariables = outputHLSL.getOutputVariables();
-    uniforms        = outputHLSL.getUniforms();
-    varyings        = outputHLSL.getVaryings();
-    interfaceBlocks = outputHLSL.getInterfaceBlocks();
-
     mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap();
     mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
 }
diff --git a/src/compiler/translator/UniformHLSL.cpp b/src/compiler/translator/UniformHLSL.cpp
index 2c99a90..61b6ed7 100644
--- a/src/compiler/translator/UniformHLSL.cpp
+++ b/src/compiler/translator/UniformHLSL.cpp
@@ -14,6 +14,7 @@
 #include "compiler/translator/StructureHLSL.h"
 #include "compiler/translator/util.h"
 #include "compiler/translator/UtilsHLSL.h"
+#include "compiler/translator/TranslatorHLSL.h"
 
 namespace sh
 {
@@ -60,12 +61,13 @@
     return DecoratePrivate(interfaceBlock.name()) + "_type";
 }
 
-UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType)
+UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator)
     : mUniformRegister(0),
       mInterfaceBlockRegister(0),
       mSamplerRegister(0),
       mStructureHLSL(structureHLSL),
-      mOutputType(outputType)
+      mOutputType(translator->getOutputType()),
+      mUniforms(translator->getUniforms())
 {}
 
 void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
@@ -78,18 +80,32 @@
     mInterfaceBlockRegister = registerCount;
 }
 
+const Uniform *UniformHLSL::findUniformByName(const TString &name) const
+{
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
+    {
+        if (mUniforms[uniformIndex].name == name.c_str())
+        {
+            return &mUniforms[uniformIndex];
+        }
+    }
+
+    UNREACHABLE();
+    return NULL;
+}
+
 unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
 {
     unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
 
-    GetVariableTraverser traverser;
-    traverser.traverse(type, name, &mActiveUniforms);
+    const Uniform *uniform = findUniformByName(name);
+    ASSERT(uniform);
 
-    const sh::Uniform &activeUniform = mActiveUniforms.back();
-    mUniformRegisterMap[activeUniform.name] = registerIndex;
+    mUniformRegisterMap[uniform->name] = registerIndex;
 
-    unsigned int registerCount = HLSLVariableRegisterCount(activeUniform, mOutputType);
-    if (IsSampler(type.getBasicType()))
+    unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
+
+    if (gl::IsSampler(uniform->type))
     {
         mSamplerRegister += registerCount;
     }
@@ -154,23 +170,10 @@
         unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
         unsigned int activeRegister = mInterfaceBlockRegister;
 
-        InterfaceBlock activeBlock;
-        activeBlock.name = interfaceBlock.name().c_str();
-        activeBlock.arraySize = arraySize;
-
-        GetInterfaceBlockFields(interfaceBlock, &activeBlock.fields);
-
-        mInterfaceBlockRegisterMap[activeBlock.name] = activeRegister;
+        mInterfaceBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
         mInterfaceBlockRegister += std::max(1u, arraySize);
 
-        activeBlock.layout = GetBlockLayoutType(interfaceBlock.blockStorage());
-
-        if (interfaceBlock.matrixPacking() == EmpRowMajor)
-        {
-            activeBlock.isRowMajorLayout = true;
-        }
-
-        mActiveInterfaceBlocks.push_back(activeBlock);
+        // FIXME: interface block field names
 
         if (interfaceBlock.hasInstanceName())
         {
diff --git a/src/compiler/translator/UniformHLSL.h b/src/compiler/translator/UniformHLSL.h
index d61457d..91fa515 100644
--- a/src/compiler/translator/UniformHLSL.h
+++ b/src/compiler/translator/UniformHLSL.h
@@ -19,7 +19,7 @@
 class UniformHLSL
 {
   public:
-    UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType);
+    UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator);
 
     void reserveUniformRegisters(unsigned int registerCount);
     void reserveInterfaceBlockRegisters(unsigned int registerCount);
@@ -29,8 +29,6 @@
     // Used for direct index references
     static TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex);
 
-    const std::vector<Uniform> &getUniforms() const { return mActiveUniforms; }
-    const std::vector<InterfaceBlock> &getInterfaceBlocks() const { return mActiveInterfaceBlocks; }
     const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const
     {
         return mInterfaceBlockRegisterMap;
@@ -44,6 +42,7 @@
     TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex);
     TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage);
     TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock);
+    const Uniform *findUniformByName(const TString &name) const;
 
     // Returns the uniform's register index
     unsigned int declareUniformAndAssignRegister(const TType &type, const TString &name);
@@ -54,8 +53,7 @@
     StructureHLSL *mStructureHLSL;
     ShShaderOutput mOutputType;
 
-    std::vector<Uniform> mActiveUniforms;
-    std::vector<InterfaceBlock> mActiveInterfaceBlocks;
+    const std::vector<Uniform> &mUniforms;
     std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
     std::map<std::string, unsigned int> mUniformRegisterMap;
 };
diff --git a/src/compiler/translator/VariableInfo.cpp b/src/compiler/translator/VariableInfo.cpp
index b023c29..d58770f 100644
--- a/src/compiler/translator/VariableInfo.cpp
+++ b/src/compiler/translator/VariableInfo.cpp
@@ -9,17 +9,43 @@
 #include "compiler/translator/util.h"
 #include "common/utilities.h"
 
-static void ExpandUserDefinedVariable(const sh::ShaderVariable &variable,
-                                      const std::string &name,
-                                      const std::string &mappedName,
-                                      bool markStaticUse,
-                                      std::vector<sh::ShaderVariable> *expanded);
+namespace
+{
 
-static void ExpandVariable(const sh::ShaderVariable &variable,
-                           const std::string &name,
-                           const std::string &mappedName,
-                           bool markStaticUse,
-                           std::vector<sh::ShaderVariable> *expanded)
+TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
+{
+    if (interfaceBlock.hasInstanceName())
+    {
+        return interfaceBlock.name() + "." + field.name();
+    }
+    else
+    {
+        return field.name();
+    }
+}
+
+sh::BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
+{
+    switch (blockStorage)
+    {
+      case EbsPacked:         return sh::BLOCKLAYOUT_PACKED;
+      case EbsShared:         return sh::BLOCKLAYOUT_SHARED;
+      case EbsStd140:         return sh::BLOCKLAYOUT_STANDARD;
+      default: UNREACHABLE(); return sh::BLOCKLAYOUT_SHARED;
+    }
+}
+
+void ExpandUserDefinedVariable(const sh::ShaderVariable &variable,
+                               const std::string &name,
+                               const std::string &mappedName,
+                               bool markStaticUse,
+                               std::vector<sh::ShaderVariable> *expanded);
+
+void ExpandVariable(const sh::ShaderVariable &variable,
+                    const std::string &name,
+                    const std::string &mappedName,
+                    bool markStaticUse,
+                    std::vector<sh::ShaderVariable> *expanded)
 {
     if (variable.isStruct())
     {
@@ -60,11 +86,11 @@
     }
 }
 
-static void ExpandUserDefinedVariable(const sh::ShaderVariable &variable,
-                                      const std::string &name,
-                                      const std::string &mappedName,
-                                      bool markStaticUse,
-                                      std::vector<sh::ShaderVariable> *expanded)
+void ExpandUserDefinedVariable(const sh::ShaderVariable &variable,
+                               const std::string &name,
+                               const std::string &mappedName,
+                               bool markStaticUse,
+                               std::vector<sh::ShaderVariable> *expanded)
 {
     ASSERT(variable.isStruct());
 
@@ -82,8 +108,8 @@
 }
 
 template <class VarT>
-static VarT *FindVariable(const TString &name,
-                          std::vector<VarT> *infoList)
+VarT *FindVariable(const TString &name,
+                  std::vector<VarT> *infoList)
 {
     // TODO(zmo): optimize this function.
     for (size_t ii = 0; ii < infoList->size(); ++ii)
@@ -95,6 +121,8 @@
     return NULL;
 }
 
+}
+
 CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
                                    std::vector<sh::Attribute> *outputVariables,
                                    std::vector<sh::Uniform> *uniforms,
@@ -270,10 +298,22 @@
     interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
     interfaceBlock.arraySize = variable->getArraySize();
     interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
-    interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage());
+    interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
 
     // Gather field information
-    sh::GetInterfaceBlockFields(*blockType, &interfaceBlock.fields);
+    const TFieldList &fieldList = blockType->fields();
+
+    for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
+    {
+        const TField &field = *fieldList[fieldIndex];
+        const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
+        const TType &fieldType = *field.type();
+
+        sh::GetVariableTraverser traverser;
+        traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
+
+        interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
+    }
 
     infoList->push_back(interfaceBlock);
 }
diff --git a/src/compiler/translator/util.cpp b/src/compiler/translator/util.cpp
index 40c90d8..f74c7d1 100644
--- a/src/compiler/translator/util.cpp
+++ b/src/compiler/translator/util.cpp
@@ -320,44 +320,4 @@
 template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *);
 template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
 
-BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
-{
-    switch (blockStorage)
-    {
-      case EbsPacked:         return BLOCKLAYOUT_PACKED;
-      case EbsShared:         return BLOCKLAYOUT_SHARED;
-      case EbsStd140:         return BLOCKLAYOUT_STANDARD;
-      default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
-    }
-}
-
-static TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
-{
-    if (interfaceBlock.hasInstanceName())
-    {
-        return interfaceBlock.name() + "." + field.name();
-    }
-    else
-    {
-        return field.name();
-    }
-}
-
-void GetInterfaceBlockFields(const TInterfaceBlock &interfaceBlock, std::vector<InterfaceBlockField> *fieldsOut)
-{
-    const TFieldList &fieldList = interfaceBlock.fields();
-
-    for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
-    {
-        const TField &field = *fieldList[fieldIndex];
-        const TString &fullFieldName = InterfaceBlockFieldName(interfaceBlock, field);
-        const TType &fieldType = *field.type();
-
-        GetVariableTraverser traverser;
-        traverser.traverse(fieldType, fullFieldName, fieldsOut);
-
-        fieldsOut->back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
-    }
-}
-
 }
diff --git a/src/compiler/translator/util.h b/src/compiler/translator/util.h
index 6a39d56..241e2cc 100644
--- a/src/compiler/translator/util.h
+++ b/src/compiler/translator/util.h
@@ -33,7 +33,6 @@
 bool IsVaryingOut(TQualifier qualifier);
 bool IsVarying(TQualifier qualifier);
 InterpolationType GetInterpolationType(TQualifier qualifier);
-BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage);
 TString ArrayString(const TType &type);
 
 class GetVariableTraverser
@@ -52,8 +51,6 @@
     DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser);
 };
 
-void GetInterfaceBlockFields(const TInterfaceBlock &interfaceBlock, std::vector<InterfaceBlockField> *fieldsOut);
-
 }
 
 #endif // COMPILER_UTIL_H
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index 65b3c14..9767275 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -1068,6 +1068,12 @@
         PackedVarying *input = &fragmentVaryings[fragVaryingIndex];
         bool matched = false;
 
+        // Built-in varyings obey special rules
+        if (input->isBuiltIn())
+        {
+            continue;
+        }
+
         for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
         {
             PackedVarying *output = &vertexVaryings[vertVaryingIndex];
@@ -1085,7 +1091,8 @@
             }
         }
 
-        if (!matched)
+        // We permit unmatched, unreferenced varyings
+        if (!matched && input->staticUse)
         {
             infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
             return false;
@@ -1721,12 +1728,15 @@
     const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
 
     unsigned int usedLocations = 0;
-    const std::vector<sh::Attribute> &activeAttributes = vertexShader->getActiveAttributes();
+    const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes();
 
     // Link attributes that have a binding location
-    for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
+    for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
     {
-        const sh::Attribute &attribute = activeAttributes[attributeIndex];
+        const sh::Attribute &attribute = shaderAttributes[attributeIndex];
+
+        ASSERT(attribute.staticUse);
+
         const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
 
         mShaderAttributes[attributeIndex] = attribute;
@@ -1765,9 +1775,12 @@
     }
 
     // Link attributes that don't have a binding location
-    for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
+    for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
     {
-        const sh::Attribute &attribute = activeAttributes[attributeIndex];
+        const sh::Attribute &attribute = shaderAttributes[attributeIndex];
+
+        ASSERT(attribute.staticUse);
+
         const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
 
         if (location == -1)   // Not set by glBindAttribLocation or by location layout qualifier
@@ -1930,13 +1943,21 @@
     for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
     {
         const sh::Uniform &uniform = vertexUniforms[uniformIndex];
-        defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
+
+        if (uniform.staticUse)
+        {
+            defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
+        }
     }
 
     for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
     {
         const sh::Uniform &uniform = fragmentUniforms[uniformIndex];
-        defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
+
+        if (uniform.staticUse)
+        {
+            defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
+        }
     }
 
     if (!indexUniforms(infoLog, caps))
@@ -2197,17 +2218,27 @@
 
     for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
     {
-        if (!defineUniformBlock(infoLog, vertexShader, vertexInterfaceBlocks[blockIndex], caps))
+        const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex];
+
+        if (interfaceBlock.staticUse)
         {
-            return false;
+            if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps))
+            {
+                return false;
+            }
         }
     }
 
     for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
     {
-        if (!defineUniformBlock(infoLog, fragmentShader, fragmentInterfaceBlocks[blockIndex], caps))
+        const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex];
+
+        if (interfaceBlock.staticUse)
         {
-            return false;
+            if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps))
+            {
+                return false;
+            }
         }
     }
 
diff --git a/src/libGLESv2/Shader.h b/src/libGLESv2/Shader.h
index 44f0500..f28b805 100644
--- a/src/libGLESv2/Shader.h
+++ b/src/libGLESv2/Shader.h
@@ -42,6 +42,7 @@
     {}
 
     bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; }
+    bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; }
 
     void resetRegisterAssignment()
     {
diff --git a/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp b/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp
index 404525c..6aa0d13 100644
--- a/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp
+++ b/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp
@@ -223,6 +223,13 @@
     for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++)
     {
         PackedVarying *varying = &fragmentVaryings[varyingIndex];
+
+        // Do not assign registers to built-in or unreferenced varyings
+        if (varying->isBuiltIn() || !varying->staticUse)
+        {
+            continue;
+        }
+
         if (packVarying(varying, maxVaryingVectors, packing))
         {
             packedVaryings.insert(varying->name);
@@ -278,17 +285,19 @@
     return registers;
 }
 
-std::string DynamicHLSL::generateVaryingHLSL(rx::ShaderD3D *shader) const
+std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const
 {
     std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize);
     std::string varyingHLSL;
 
-    std::vector<gl::PackedVarying> &varyings = shader->getVaryings();
+    const std::vector<gl::PackedVarying> &varyings = shader->getVaryings();
+
     for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++)
     {
         const PackedVarying &varying = varyings[varyingIndex];
         if (varying.registerAssigned())
         {
+            ASSERT(!varying.isBuiltIn());
             GLenum transposedType = TransposeMatrixType(varying.type);
             int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
 
@@ -616,8 +625,10 @@
     for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++)
     {
         const PackedVarying &varying = varyings[varyingIndex];
+
         if (varying.registerAssigned())
         {
+            ASSERT(!varying.isBuiltIn());
             GLenum transposedType = TransposeMatrixType(varying.type);
             int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
 
@@ -825,6 +836,8 @@
             const std::string &variableName = "out_" + outputLocation.name;
             const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
 
+            ASSERT(outputVariable.staticUse);
+
             PixelShaderOuputVariable outputKeyVariable;
             outputKeyVariable.type = outputVariable.type;
             outputKeyVariable.name = variableName + elementString;
@@ -907,6 +920,7 @@
         const PackedVarying &varying = fragmentVaryings[varyingIndex];
         if (varying.registerAssigned())
         {
+            ASSERT(!varying.isBuiltIn());
             for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
             {
                 GLenum transposedType = TransposeMatrixType(varying.type);
@@ -944,7 +958,10 @@
                 }
             }
         }
-        else UNREACHABLE();
+        else
+        {
+            ASSERT(varying.isBuiltIn() || !varying.staticUse);
+        }
     }
 
     pixelHLSL += "\n"
@@ -965,6 +982,8 @@
         const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex];
         const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
 
+        ASSERT(outputVariable.staticUse);
+
         if (outputVariable.arraySize > 0)
         {
             for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
diff --git a/src/libGLESv2/renderer/d3d/DynamicHLSL.h b/src/libGLESv2/renderer/d3d/DynamicHLSL.h
index cf61995..6242012 100644
--- a/src/libGLESv2/renderer/d3d/DynamicHLSL.h
+++ b/src/libGLESv2/renderer/d3d/DynamicHLSL.h
@@ -87,7 +87,7 @@
     SemanticInfo getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, bool pointSize,
                                         bool pixelShader) const;
     std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const;
-    std::string generateVaryingHLSL(rx::ShaderD3D *shader) const;
+    std::string generateVaryingHLSL(const ShaderD3D *shader) const;
     void storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const;
     void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<gl::LinkedVarying> *linkedVaryings) const;
     void defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map<int, gl::VariableLocation> *programOutputVars) const;
diff --git a/src/libGLESv2/renderer/d3d/ShaderD3D.cpp b/src/libGLESv2/renderer/d3d/ShaderD3D.cpp
index a6d5266..57edb29 100644
--- a/src/libGLESv2/renderer/d3d/ShaderD3D.cpp
+++ b/src/libGLESv2/renderer/d3d/ShaderD3D.cpp
@@ -16,13 +16,30 @@
 namespace rx
 {
 
+template <typename VarT>
+void FilterInactiveVariables(std::vector<VarT> *variableList)
+{
+    ASSERT(variableList);
+
+    for (size_t varIndex = 0; varIndex < variableList->size();)
+    {
+        if (!(*variableList)[varIndex].staticUse)
+        {
+            variableList->erase(variableList->begin() + varIndex);
+        }
+        else
+        {
+            varIndex++;
+        }
+    }
+}
+
 void *ShaderD3D::mFragmentCompiler = NULL;
 void *ShaderD3D::mVertexCompiler = NULL;
 
 template <typename VarT>
 const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableList)
 {
-    // TODO: handle staticUse. for now, assume all returned variables are active.
     ASSERT(variableList);
     return variableList;
 }
@@ -111,12 +128,12 @@
 {
      if (!mHlsl.empty())
     {
-        const std::vector<sh::Varying> *activeVaryings = ShGetVaryings(compiler);
-        ASSERT(activeVaryings);
+        const std::vector<sh::Varying> *varyings = ShGetVaryings(compiler);
+        ASSERT(varyings);
 
-        for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++)
+        for (size_t varyingIndex = 0; varyingIndex < varyings->size(); varyingIndex++)
         {
-            mVaryings.push_back(gl::PackedVarying((*activeVaryings)[varyingIndex]));
+            mVaryings.push_back(gl::PackedVarying((*varyings)[varyingIndex]));
         }
 
         mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT")          != std::string::npos;
@@ -173,7 +190,7 @@
     // ensure the compiler is loaded
     initializeCompiler();
 
-    int compileOptions = SH_OBJECT_CODE;
+    int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES);
     std::string sourcePath;
     if (gl::perfActive())
     {
@@ -251,12 +268,15 @@
         {
             const sh::Uniform &uniform = mUniforms[uniformIndex];
 
-            unsigned int index = -1;
-            bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index);
-            UNUSED_ASSERTION_VARIABLE(result);
-            ASSERT(result);
+            if (uniform.staticUse)
+            {
+                unsigned int index = -1;
+                bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index);
+                UNUSED_ASSERTION_VARIABLE(result);
+                ASSERT(result);
 
-            mUniformRegisterMap[uniform.name] = index;
+                mUniformRegisterMap[uniform.name] = index;
+            }
         }
 
         mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler));
@@ -265,12 +285,15 @@
         {
             const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex];
 
-            unsigned int index = -1;
-            bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index);
-            UNUSED_ASSERTION_VARIABLE(result);
-            ASSERT(result);
+            if (interfaceBlock.staticUse)
+            {
+                unsigned int index = -1;
+                bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index);
+                UNUSED_ASSERTION_VARIABLE(result);
+                ASSERT(result);
 
-            mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
+                mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
+            }
         }
     }
     else
@@ -393,6 +416,7 @@
         if (!hlsl.empty())
         {
             mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compiler));
+            FilterInactiveVariables(&mActiveOutputVariables);
         }
     }
 
@@ -405,6 +429,7 @@
     if (!hlsl.empty())
     {
         mActiveAttributes = *GetShaderVariables(ShGetAttributes(compiler));
+        FilterInactiveVariables(&mActiveAttributes);
     }
 }
 
diff --git a/src/libGLESv2/renderer/d3d/ShaderD3D.h b/src/libGLESv2/renderer/d3d/ShaderD3D.h
index 9f7dc0b..40e64cf 100644
--- a/src/libGLESv2/renderer/d3d/ShaderD3D.h
+++ b/src/libGLESv2/renderer/d3d/ShaderD3D.h
@@ -16,6 +16,7 @@
 
 namespace rx
 {
+class DynamicHLSL;
 class Renderer;
 
 class ShaderD3D : public ShaderImpl