Moving more D3D-only logic into ProgramBinaryD3D

BUG=angle:731

Change-Id: Ia62ec9a912c8bd63fcee51ca206d52688dd999da
Reviewed-on: https://chromium-review.googlesource.com/217495
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Brandon Jones <bajones@chromium.org>
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index cd070e2..2355352 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -192,8 +192,6 @@
 ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
     : RefCountObject(0),
       mProgram(impl),
-      mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
-      mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
       mGeometryExecutable(NULL),
       mUsedVertexSamplerRange(0),
       mUsedPixelSamplerRange(0),
@@ -275,16 +273,9 @@
         }
     }
 
-    std::string finalPixelHLSL = mProgram->getDynamicHLSL()->generatePixelShaderForOutputSignature(
-            mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
-
-    // Generate new pixel executable
     InfoLog tempInfoLog;
-    rx::Renderer* renderer = mProgram->getRenderer();
-    rx::ShaderExecutable *pixelExecutable = renderer->compileToExecutable(tempInfoLog, finalPixelHLSL.c_str(),
-                                                                          rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
-                                                                          (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                                          mPixelWorkarounds);
+    rx::ShaderExecutable *pixelExecutable = mProgram->getPixelExecutableForOutputLayout(tempInfoLog, outputSignature,
+            mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
 
     if (!pixelExecutable)
     {
@@ -313,16 +304,9 @@
         }
     }
 
-    // Generate new dynamic layout with attribute conversions
-    std::string finalVertexHLSL = mProgram->getDynamicHLSL()->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes);
-
-    // Generate new vertex executable
     InfoLog tempInfoLog;
-    rx::Renderer* renderer = mProgram->getRenderer();
-    rx::ShaderExecutable *vertexExecutable = renderer->compileToExecutable(tempInfoLog, finalVertexHLSL.c_str(),
-                                                                           rx::SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
-                                                                           (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                                           mVertexWorkarounds);
+    rx::ShaderExecutable *vertexExecutable = mProgram->getVertexExecutableForInputLayout(tempInfoLog, inputLayout, mShaderAttributes,
+            mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
 
     if (!vertexExecutable)
     {
@@ -1125,14 +1109,14 @@
 #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
     return false;
 #else
-    ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
+    ASSERT(binaryFormat == mProgram->getBinaryFormat());
 
     reset();
 
     BinaryInputStream stream(binary, length);
 
-    int format = stream.readInt<int>();
-    if (format != GL_PROGRAM_BINARY_ANGLE)
+    GLenum format = stream.readInt<GLenum>();
+    if (format != mProgram->getBinaryFormat())
     {
         infoLog.append("Invalid program binary format.");
         return false;
@@ -1283,10 +1267,6 @@
         stream.readInt(&varying.semanticIndexCount);
     }
 
-    stream.readString(&mVertexHLSL);
-
-    stream.readInt(&mVertexWorkarounds);
-
     const unsigned int vertexShaderCount = stream.readInt<unsigned int>();
     for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
     {
@@ -1323,20 +1303,6 @@
         stream.skip(vertexShaderSize);
     }
 
-    stream.readString(&mPixelHLSL);
-    stream.readInt(&mPixelWorkarounds);
-    stream.readBool(&mUsesFragDepth);
-
-    const size_t pixelShaderKeySize = stream.readInt<unsigned int>();
-    mPixelShaderKey.resize(pixelShaderKeySize);
-    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
-    {
-        stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
-        stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
-        stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
-        stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
-    }
-
     const size_t pixelShaderCount = stream.readInt<unsigned int>();
     for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
     {
@@ -1384,6 +1350,11 @@
         stream.skip(geometryShaderSize);
     }
 
+    if (!mProgram->load(infoLog, &stream))
+    {
+        return false;
+    }
+
     const char *ptr = (const char*) binary + stream.offset();
 
     const GUID *binaryIdentifier = (const GUID *) ptr;
@@ -1406,12 +1377,12 @@
 {
     if (binaryFormat)
     {
-        *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
+        *binaryFormat = mProgram->getBinaryFormat();
     }
 
     BinaryOutputStream stream;
 
-    stream.writeInt(GL_PROGRAM_BINARY_ANGLE);
+    stream.writeInt(mProgram->getBinaryFormat());
     stream.writeInt(ANGLE_MAJOR_VERSION);
     stream.writeInt(ANGLE_MINOR_VERSION);
     stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
@@ -1508,9 +1479,6 @@
         stream.writeInt(varying.semanticIndexCount);
     }
 
-    stream.writeString(mVertexHLSL);
-    stream.writeInt(mVertexWorkarounds);
-
     stream.writeInt(mVertexExecutables.size());
     for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
     {
@@ -1532,20 +1500,6 @@
         stream.writeBytes(vertexBlob, vertexShaderSize);
     }
 
-    stream.writeString(mPixelHLSL);
-    stream.writeInt(mPixelWorkarounds);
-    stream.writeInt(mUsesFragDepth);
-
-    stream.writeInt(mPixelShaderKey.size());
-    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < mPixelShaderKey.size(); pixelShaderKeyIndex++)
-    {
-        const rx::PixelShaderOutputVariable &variable = mPixelShaderKey[pixelShaderKeyIndex];
-        stream.writeInt(variable.type);
-        stream.writeString(variable.name);
-        stream.writeString(variable.source);
-        stream.writeInt(variable.outputIndex);
-    }
-
     stream.writeInt(mPixelExecutables.size());
     for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
     {
@@ -1574,6 +1528,16 @@
         stream.writeBytes(geometryBlob, geometryShaderSize);
     }
 
+    if (!mProgram->save(&stream))
+    {
+        if (length)
+        {
+            *length = 0;
+        }
+
+        return false;
+    }
+
     GUID identifier = mProgram->getRenderer()->getAdapterIdentifier();
 
     GLsizei streamLength = stream.length();
@@ -1648,36 +1612,14 @@
 
     mShaderVersion = vertexShaderD3D->getShaderVersion();
 
-    mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
-    mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
-
-    mVertexHLSL = vertexShaderD3D->getTranslatedSource();
-    mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
-
-    // Map the varyings to the register file
-    rx::VaryingPacking packing = { NULL };
-    int registers = mProgram->getDynamicHLSL()->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D,
-                                                             transformFeedbackVaryings);
-
-    if (registers < 0)
-    {
-        return false;
-    }
-
-    if (!linkVaryings(infoLog, fragmentShader, vertexShader))
+    int registers;
+    std::vector<LinkedVarying> linkedVaryings;
+    if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, &registers, &linkedVaryings, &mOutputVariables))
     {
         return false;
     }
 
     mUsesPointSize = vertexShaderD3D->usesPointSize();
-    std::vector<LinkedVarying> linkedVaryings;
-    if (!mProgram->getDynamicHLSL()->generateShaderLinkHLSL(infoLog, registers, packing, mPixelHLSL, mVertexHLSL,
-                                                            fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
-                                                            &linkedVaryings, &mOutputVariables, &mPixelShaderKey,
-                                                            &mUsesFragDepth))
-    {
-        return false;
-    }
 
     bool success = true;
 
@@ -1718,7 +1660,7 @@
         GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
         rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
 
-        std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(mPixelShaderKey);
+        std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey());
         rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput);
 
         if (usesGeometryShader())
@@ -2871,14 +2813,7 @@
 
 void ProgramBinary::reset()
 {
-    mVertexHLSL.clear();
-    mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
     SafeDeleteContainer(mVertexExecutables);
-
-    mPixelHLSL.clear();
-    mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
-    mUsesFragDepth = false;
-    mPixelShaderKey.clear();
     SafeDeleteContainer(mPixelExecutables);
 
     SafeDelete(mGeometryExecutable);
diff --git a/src/libGLESv2/ProgramBinary.h b/src/libGLESv2/ProgramBinary.h
index 3c9316f..2fe924b 100644
--- a/src/libGLESv2/ProgramBinary.h
+++ b/src/libGLESv2/ProgramBinary.h
@@ -194,6 +194,8 @@
 
     const std::vector<LinkedUniform*> &getUniforms() const { return mUniforms; }
 
+    static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader);
+
   private:
     DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
 
@@ -208,18 +210,17 @@
 
     void reset();
 
-    bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader);
     bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader);
 
-    bool linkValidateVariablesBase(InfoLog &infoLog,
-                                   const std::string &variableName,
-                                   const sh::ShaderVariable &vertexVariable,
-                                   const sh::ShaderVariable &fragmentVariable,
-                                   bool validatePrecision);
+    static bool linkValidateVariablesBase(InfoLog &infoLog,
+                                          const std::string &variableName,
+                                          const sh::ShaderVariable &vertexVariable,
+                                          const sh::ShaderVariable &fragmentVariable,
+                                          bool validatePrecision);
 
-    bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
-    bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
-    bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
+    static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
+    static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
+    static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
     bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
     void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister);
     void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder);
@@ -289,14 +290,7 @@
 
     rx::ProgramImpl *mProgram;
 
-    std::string mVertexHLSL;
-    rx::D3DWorkaroundType mVertexWorkarounds;
     std::vector<VertexExecutable *> mVertexExecutables;
-
-    std::string mPixelHLSL;
-    rx::D3DWorkaroundType mPixelWorkarounds;
-    bool mUsesFragDepth;
-    std::vector<rx::PixelShaderOutputVariable> mPixelShaderKey;
     std::vector<PixelExecutable *> mPixelExecutables;
 
     rx::ShaderExecutable *mGeometryExecutable;
diff --git a/src/libGLESv2/renderer/ProgramImpl.h b/src/libGLESv2/renderer/ProgramImpl.h
index 28c026a..ba0955f 100644
--- a/src/libGLESv2/renderer/ProgramImpl.h
+++ b/src/libGLESv2/renderer/ProgramImpl.h
@@ -10,6 +10,7 @@
 #define LIBGLESV2_RENDERER_PROGRAMIMPL_H_
 
 #include "common/angleutils.h"
+#include "libGLESv2/BinaryStream.h"
 #include "libGLESv2/Constants.h"
 #include "libGLESv2/ProgramBinary.h"
 
@@ -27,6 +28,26 @@
     // TODO: Temporary interfaces to ease migration. Remove soon!
     virtual Renderer *getRenderer() = 0;
     virtual DynamicHLSL *getDynamicHLSL() = 0;
+    virtual const std::vector<rx::PixelShaderOutputVariable> &getPixelShaderKey() = 0;
+
+    virtual GLenum getBinaryFormat() = 0;
+    virtual bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
+    virtual bool save(gl::BinaryOutputStream *stream) = 0;
+
+    virtual rx::ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
+                                                                    const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+                                                                    bool separatedOutputBuffers) = 0;
+    virtual rx::ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
+                                                                    const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
+                                                                    const sh::Attribute shaderAttributes[],
+                                                                    const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+                                                                    bool separatedOutputBuffers) = 0;
+
+    virtual bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+                      const std::vector<std::string> &transformFeedbackVaryings, int *registers,
+                      std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int,
+                      gl::VariableLocation> *outputVariables) = 0;
+
     virtual void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms) = 0;
 
     virtual void reset() = 0;
diff --git a/src/libGLESv2/renderer/d3d/ProgramD3D.cpp b/src/libGLESv2/renderer/d3d/ProgramD3D.cpp
index 87e0132..f74196c 100644
--- a/src/libGLESv2/renderer/d3d/ProgramD3D.cpp
+++ b/src/libGLESv2/renderer/d3d/ProgramD3D.cpp
@@ -13,6 +13,7 @@
 #include "libGLESv2/renderer/Renderer.h"
 #include "libGLESv2/renderer/ShaderExecutable.h"
 #include "libGLESv2/renderer/d3d/DynamicHLSL.h"
+#include "libGLESv2/renderer/d3d/ShaderD3D.h"
 #include "libGLESv2/main.h"
 
 namespace rx
@@ -22,6 +23,8 @@
     : ProgramImpl(),
       mRenderer(renderer),
       mDynamicHLSL(NULL),
+      mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
+      mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
       mVertexUniformStorage(NULL),
       mFragmentUniformStorage(NULL)
 {
@@ -46,6 +49,119 @@
     return static_cast<const ProgramD3D*>(impl);
 }
 
+bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
+{
+    stream->readString(&mVertexHLSL);
+    stream->readInt(&mVertexWorkarounds);
+    stream->readString(&mPixelHLSL);
+    stream->readInt(&mPixelWorkarounds);
+    stream->readBool(&mUsesFragDepth);
+
+    const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
+    mPixelShaderKey.resize(pixelShaderKeySize);
+    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
+    {
+        stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
+        stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
+        stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
+        stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
+    }
+
+    return true;
+}
+
+bool ProgramD3D::save(gl::BinaryOutputStream *stream)
+{
+    stream->writeString(mVertexHLSL);
+    stream->writeInt(mVertexWorkarounds);
+    stream->writeString(mPixelHLSL);
+    stream->writeInt(mPixelWorkarounds);
+    stream->writeInt(mUsesFragDepth);
+
+    const std::vector<rx::PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
+    stream->writeInt(pixelShaderKey.size());
+    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
+    {
+        const rx::PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
+        stream->writeInt(variable.type);
+        stream->writeString(variable.name);
+        stream->writeString(variable.source);
+        stream->writeInt(variable.outputIndex);
+    }
+
+    return true;
+}
+
+rx::ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
+                                                                    const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+                                                                    bool separatedOutputBuffers)
+{
+    std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
+                                                                                     outputSignature);
+
+    // Generate new pixel executable
+    rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(infoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL,
+                                                                           transformFeedbackLinkedVaryings, separatedOutputBuffers,
+                                                                           mPixelWorkarounds);
+
+    return pixelExecutable;
+}
+
+rx::ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
+                                                                    const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
+                                                                    const sh::Attribute shaderAttributes[],
+                                                                    const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+                                                                    bool separatedOutputBuffers)
+{
+    // Generate new dynamic layout with attribute conversions
+    std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes);
+
+    // Generate new vertex executable
+    rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL.c_str(),
+                                                                            rx::SHADER_VERTEX,
+                                                                            transformFeedbackLinkedVaryings, separatedOutputBuffers,
+                                                                            mVertexWorkarounds);
+
+    return vertexExecutable;
+}
+
+bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+                      const std::vector<std::string> &transformFeedbackVaryings, int *registers,
+                      std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int, gl::VariableLocation> *outputVariables)
+{
+    rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
+    rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
+
+    mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
+    mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
+
+    mVertexHLSL = vertexShaderD3D->getTranslatedSource();
+    mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
+
+    // Map the varyings to the register file
+    rx::VaryingPacking packing = { NULL };
+    *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
+
+    if (registers < 0)
+    {
+        return false;
+    }
+
+    if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
+    {
+        return false;
+    }
+
+    if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
+                                              fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
+                                              linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
+    {
+        return false;
+    }
+
+    return true;
+}
+
 void ProgramD3D::initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms)
 {
     // Compute total default block size
@@ -74,6 +190,14 @@
 
 void ProgramD3D::reset()
 {
+    mVertexHLSL.clear();
+    mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
+
+    mPixelHLSL.clear();
+    mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
+    mUsesFragDepth = false;
+    mPixelShaderKey.clear();
+
     SafeDelete(mVertexUniformStorage);
     SafeDelete(mFragmentUniformStorage);
 }
diff --git a/src/libGLESv2/renderer/d3d/ProgramD3D.h b/src/libGLESv2/renderer/d3d/ProgramD3D.h
index 3dd3b1f..d645c57 100644
--- a/src/libGLESv2/renderer/d3d/ProgramD3D.h
+++ b/src/libGLESv2/renderer/d3d/ProgramD3D.h
@@ -11,9 +11,13 @@
 
 #include "libGLESv2/renderer/ProgramImpl.h"
 
+#include <string>
+#include <vector>
+
 namespace gl
 {
 struct LinkedUniform;
+struct VariableLocation;
 struct VertexFormat;
 }
 
@@ -33,6 +37,24 @@
 
     Renderer *getRenderer() { return mRenderer; }
     DynamicHLSL *getDynamicHLSL() { return mDynamicHLSL; }
+    const std::vector<rx::PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
+
+    GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; }
+    bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
+    bool save(gl::BinaryOutputStream *stream);
+
+    ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
+                                                        const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+                                                        bool separatedOutputBuffers);
+    ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
+                                                        const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
+                                                        const sh::Attribute shaderAttributes[],
+                                                        const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+                                                        bool separatedOutputBuffers);
+
+    bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+              const std::vector<std::string> &transformFeedbackVaryings, int *registers,
+              std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int, gl::VariableLocation> *outputVariables);
 
     // D3D only
     void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms);
@@ -48,6 +70,14 @@
     Renderer *mRenderer;
     DynamicHLSL *mDynamicHLSL;
 
+    std::string mVertexHLSL;
+    rx::D3DWorkaroundType mVertexWorkarounds;
+
+    std::string mPixelHLSL;
+    rx::D3DWorkaroundType mPixelWorkarounds;
+    bool mUsesFragDepth;
+    std::vector<rx::PixelShaderOutputVariable> mPixelShaderKey;
+
     UniformStorage *mVertexUniformStorage;
     UniformStorage *mFragmentUniformStorage;
 };