Made program binaries cache information needed for getTransformFeedbackVarying

BUG=angleproject:1173
Change-Id: Ib8883b32f54f5d38fb94e85decae2dcee108facf
Reviewed-on: https://chromium-review.googlesource.com/304381
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Tested-by: Brandon Jones <bajones@chromium.org>
diff --git a/src/tests/gl_tests/ProgramBinaryTest.cpp b/src/tests/gl_tests/ProgramBinaryTest.cpp
index 1f32f6b..8222b57 100644
--- a/src/tests/gl_tests/ProgramBinaryTest.cpp
+++ b/src/tests/gl_tests/ProgramBinaryTest.cpp
@@ -204,6 +204,135 @@
                        ES2_OPENGL(),
                        ES3_OPENGL());
 
+class ProgramBinaryTransformFeedbackTest : public ANGLETest
+{
+  protected:
+    ProgramBinaryTransformFeedbackTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (   #version 300 es\n
+            in vec4 inputAttribute;
+            out vec4 outputVarying;
+            void main()
+            {
+                outputVarying = inputAttribute;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (   #version 300 es\n
+            precision highp float;
+            out vec4 outputColor;
+            void main()
+            {
+                outputColor = vec4(1,0,0,1);
+            }
+        );
+
+        std::vector<std::string> transformFeedbackVaryings;
+        transformFeedbackVaryings.push_back("outputVarying");
+
+        mProgram = CompileProgramWithTransformFeedback(
+            vertexShaderSource, fragmentShaderSource, transformFeedbackVaryings,
+            GL_SEPARATE_ATTRIBS);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLint getAvailableProgramBinaryFormatCount() const
+    {
+        GLint formatCount;
+        glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &formatCount);
+        return formatCount;
+    }
+
+    GLuint mProgram;
+};
+
+// This tests the assumption that float attribs of different size
+// should not internally cause a vertex shader recompile (for conversion).
+TEST_P(ProgramBinaryTransformFeedbackTest, GetTransformFeedbackVarying)
+{
+    if (!extensionEnabled("GL_OES_get_program_binary"))
+    {
+        std::cout << "Test skipped because GL_OES_get_program_binary is not available."
+                  << std::endl;
+        return;
+    }
+
+    if (getAvailableProgramBinaryFormatCount() == 0)
+    {
+        std::cout << "Test skipped because no program binary formats are available." << std::endl;
+        return;
+    }
+
+    std::vector<uint8_t> binary(0);
+    GLint programLength = 0;
+    GLint writtenLength = 0;
+    GLenum binaryFormat = 0;
+
+    // Save the program binary out
+    glGetProgramiv(mProgram, GL_PROGRAM_BINARY_LENGTH_OES, &programLength);
+    ASSERT_GL_NO_ERROR();
+    binary.resize(programLength);
+    glGetProgramBinaryOES(mProgram, programLength, &writtenLength, &binaryFormat, binary.data());
+    ASSERT_GL_NO_ERROR();
+
+    glDeleteProgram(mProgram);
+
+    // Load program binary
+    mProgram = glCreateProgram();
+    glProgramBinaryOES(mProgram, binaryFormat, binary.data(), writtenLength);
+
+    // Ensure the loaded binary is linked
+    GLint linkStatus;
+    glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
+    EXPECT_TRUE(linkStatus != 0);
+
+    // Query information about the transform feedback varying
+    char varyingName[64];
+    GLsizei varyingSize = 0;
+    GLenum varyingType = GL_NONE;
+
+    glGetTransformFeedbackVarying(mProgram, 0, 64, &writtenLength, &varyingSize, &varyingType, varyingName);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_EQ(13, writtenLength);
+    EXPECT_STREQ("outputVarying", varyingName);
+    EXPECT_EQ(1, varyingSize);
+    EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varyingType);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_INSTANTIATE_TEST(ProgramBinaryTransformFeedbackTest,
+                       ES3_D3D11(),
+                       ES3_OPENGL());
+
 // For the ProgramBinariesAcrossPlatforms tests, we need two sets of params:
 // - a set to save the program binary
 // - a set to load the program binary