Edit

kc3-lang/angle/src/tests/gl_tests/BindUniformLocationTest.cpp

Branch :

  • Show log

    Commit

  • Author : Olli Etuaho
    Date : 2017-09-18 13:32:29
    Hash : a20af6d7
    Message : Use C++11 raw string literals instead of SHADER_SOURCE macro This is better in many ways: 1. It doesn't confuse clang format 2. \n doesn't need to be included after preprocessor directives like the version directive. 3. It's using built-in functionality instead of something custom. Raw string literals should be the preferred way to include shader source in C++ files going forward. BUG=angleproject:2157 TEST=angle_end2end_tests Change-Id: I8b236a6e2d5c25d920297e5bc5b5b143eddeba1f Reviewed-on: https://chromium-review.googlesource.com/671046 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>

  • src/tests/gl_tests/BindUniformLocationTest.cpp
  • //
    // 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.
    //
    
    // BindUniformLocationTest.cpp : Tests of the GL_CHROMIUM_bind_uniform_location extension.
    
    #include "test_utils/ANGLETest.h"
    
    #include <cmath>
    
    using namespace angle;
    
    namespace
    {
    
    class BindUniformLocationTest : public ANGLETest
    {
      protected:
        BindUniformLocationTest()
        {
            setWindowWidth(128);
            setWindowHeight(128);
            setConfigRedBits(8);
            setConfigGreenBits(8);
            setConfigBlueBits(8);
            setConfigAlphaBits(8);
        }
    
        void SetUp() override
        {
            ANGLETest::SetUp();
            mBindUniformLocation = reinterpret_cast<PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC>(
                eglGetProcAddress("glBindUniformLocationCHROMIUM"));
        }
    
        void TearDown() override
        {
            if (mProgram != 0)
            {
                glDeleteProgram(mProgram);
            }
            ANGLETest::TearDown();
        }
    
        typedef void(GL_APIENTRYP PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC)(GLuint mProgram,
                                                                        GLint location,
                                                                        const GLchar *name);
        PFNGLBINDUNIFORMLOCATIONCHROMIUMPROC mBindUniformLocation = nullptr;
    
        GLuint mProgram = 0;
    };
    
    // Test basic functionality of GL_CHROMIUM_bind_uniform_location
    TEST_P(BindUniformLocationTest, Basic)
    {
        if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
        {
            std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
                      << std::endl;
            return;
        }
    
        ASSERT_NE(mBindUniformLocation, nullptr);
    
        const std::string vsSource =
            R"(attribute vec4 a_position;
            void main()
            {
                gl_Position = a_position;
            })";
    
        const std::string fsSource =
            R"(precision mediump float;
            uniform vec4 u_colorC;
            uniform vec4 u_colorB[2];
            uniform vec4 u_colorA;
            void main()
            {
                gl_FragColor = u_colorA + u_colorB[0] + u_colorB[1] + u_colorC;
            })";
    
        GLint colorALocation = 3;
        GLint colorBLocation = 10;
        GLint colorCLocation = 5;
    
        GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
    
        mProgram = glCreateProgram();
    
        mBindUniformLocation(mProgram, colorALocation, "u_colorA");
        mBindUniformLocation(mProgram, colorBLocation, "u_colorB[0]");
        mBindUniformLocation(mProgram, colorCLocation, "u_colorC");
    
        glAttachShader(mProgram, vs);
        glDeleteShader(vs);
    
        glAttachShader(mProgram, fs);
        glDeleteShader(fs);
    
        // Link the mProgram
        glLinkProgram(mProgram);
        // Check the link status
        GLint linked = 0;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        ASSERT_EQ(1, linked);
    
        glUseProgram(mProgram);
    
        static const float colorB[] = {
            0.0f, 0.50f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.0f,
        };
    
        glUniform4f(colorALocation, 0.25f, 0.0f, 0.0f, 0.0f);
        glUniform4fv(colorBLocation, 2, colorB);
        glUniform4f(colorCLocation, 0.0f, 0.0f, 0.0f, 1.0f);
    
        drawQuad(mProgram, "a_position", 0.5f);
    
        EXPECT_GL_NO_ERROR();
        EXPECT_PIXEL_NEAR(0, 0, 64, 128, 192, 255, 1.0);
    }
    
    // Test that conflicts are detected when two uniforms are bound to the same location
    TEST_P(BindUniformLocationTest, ConflictsDetection)
    {
        if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
        {
            std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
                      << std::endl;
            return;
        }
    
        ASSERT_NE(nullptr, mBindUniformLocation);
    
        const std::string vsSource =
            R"(attribute vec4 a_position;
            void main()
            {
                gl_Position = a_position;
            })";
    
        const std::string fsSource =
            R"(precision mediump float;
            uniform vec4 u_colorA;
            uniform vec4 u_colorB;
            void main()
            {
                gl_FragColor = u_colorA + u_colorB;
            })";
    
        GLint colorALocation = 3;
        GLint colorBLocation = 4;
    
        GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
    
        mProgram = glCreateProgram();
        glAttachShader(mProgram, vs);
        glDeleteShader(vs);
        glAttachShader(mProgram, fs);
        glDeleteShader(fs);
    
        mBindUniformLocation(mProgram, colorALocation, "u_colorA");
        // Bind u_colorB to location a, causing conflicts, link should fail.
        mBindUniformLocation(mProgram, colorALocation, "u_colorB");
        glLinkProgram(mProgram);
        GLint linked = 0;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        ASSERT_EQ(0, linked);
    
        // Bind u_colorB to location b, no conflicts, link should succeed.
        mBindUniformLocation(mProgram, colorBLocation, "u_colorB");
        glLinkProgram(mProgram);
        linked = 0;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        EXPECT_EQ(1, linked);
    }
    
    // Test a use case of the chromium compositor
    TEST_P(BindUniformLocationTest, Compositor)
    {
        if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
        {
            std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
                      << std::endl;
            return;
        }
    
        ASSERT_NE(nullptr, mBindUniformLocation);
    
        const std::string vsSource =
            R"(attribute vec4 a_position;
            attribute vec2 a_texCoord;
            uniform mat4 matrix;
            uniform vec2 color_a[4];
            uniform vec4 color_b;
            varying vec4 v_color;
            void main()
            {
                v_color.xy = color_a[0] + color_a[1];
                v_color.zw = color_a[2] + color_a[3];
                v_color += color_b;
                gl_Position = matrix * a_position;
            })";
    
        const std::string fsSource =
            R"(precision mediump float;
            varying vec4 v_color;
            uniform float alpha;
            uniform vec4 multiplier;
            uniform vec3 color_c[8];
            void main()
            {
                vec4 color_c_sum = vec4(0.0);
                color_c_sum.xyz += color_c[0];
                color_c_sum.xyz += color_c[1];
                color_c_sum.xyz += color_c[2];
                color_c_sum.xyz += color_c[3];
                color_c_sum.xyz += color_c[4];
                color_c_sum.xyz += color_c[5];
                color_c_sum.xyz += color_c[6];
                color_c_sum.xyz += color_c[7];
                color_c_sum.w = alpha;
                color_c_sum *= multiplier;
                gl_FragColor = v_color + color_c_sum;
            })";
    
        int counter            = 6;
        int matrixLocation     = counter++;
        int colorALocation     = counter++;
        int colorBLocation     = counter++;
        int alphaLocation      = counter++;
        int multiplierLocation = counter++;
        int colorCLocation     = counter++;
    
        GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
    
        mProgram = glCreateProgram();
    
        mBindUniformLocation(mProgram, matrixLocation, "matrix");
        mBindUniformLocation(mProgram, colorALocation, "color_a");
        mBindUniformLocation(mProgram, colorBLocation, "color_b");
        mBindUniformLocation(mProgram, alphaLocation, "alpha");
        mBindUniformLocation(mProgram, multiplierLocation, "multiplier");
        mBindUniformLocation(mProgram, colorCLocation, "color_c");
    
        glAttachShader(mProgram, vs);
        glDeleteShader(vs);
        glAttachShader(mProgram, fs);
        glDeleteShader(fs);
    
        // Link the mProgram
        glLinkProgram(mProgram);
        // Check the link status
        GLint linked = 0;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        ASSERT_EQ(1, linked);
    
        glUseProgram(mProgram);
    
        static const float colorA[] = {
            0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,
        };
    
        static const float colorC[] = {
            0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,
            0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f,
        };
    
        static const float identity[] = {
            1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
        };
    
        glUniformMatrix4fv(matrixLocation, 1, false, identity);
        glUniform2fv(colorALocation, 4, colorA);
        glUniform4f(colorBLocation, 0.2f, 0.2f, 0.2f, 0.2f);
        glUniform1f(alphaLocation, 0.8f);
        glUniform4f(multiplierLocation, 0.5f, 0.5f, 0.5f, 0.5f);
        glUniform3fv(colorCLocation, 8, colorC);
    
        glDrawArrays(GL_TRIANGLES, 0, 6);
    
        drawQuad(mProgram, "a_position", 0.5f);
    
        EXPECT_PIXEL_EQ(0, 0, 204, 204, 204, 204);
    }
    
    // Test that unused uniforms don't conflict when bound to the same location
    TEST_P(BindUniformLocationTest, UnusedUniformUpdate)
    {
        if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
        {
            std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
                      << std::endl;
            return;
        }
    
        ASSERT_NE(nullptr, mBindUniformLocation);
    
        const std::string vsSource =
            R"(attribute vec4 a_position;
            void main()
            {
                gl_Position = a_position;
            })";
    
        const std::string fsSource =
            R"(precision mediump float;
            uniform vec4 u_colorA;
            uniform float u_colorU;
            uniform vec4 u_colorC;
            void main()
            {
                gl_FragColor = u_colorA + u_colorC;
            })";
    
        const GLint colorULocation      = 1;
        const GLint nonexistingLocation = 5;
        const GLint unboundLocation     = 6;
    
        GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
    
        mProgram = glCreateProgram();
        mBindUniformLocation(mProgram, colorULocation, "u_colorU");
        // The non-existing uniform should behave like existing, but optimized away
        // uniform.
        mBindUniformLocation(mProgram, nonexistingLocation, "nonexisting");
        // Let A and C be assigned automatic locations.
        glAttachShader(mProgram, vs);
        glDeleteShader(vs);
        glAttachShader(mProgram, fs);
        glDeleteShader(fs);
        glLinkProgram(mProgram);
        GLint linked = 0;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        ASSERT_EQ(1, linked);
        glUseProgram(mProgram);
    
        // No errors on bound locations, since caller does not know
        // if the driver optimizes them away or not.
        glUniform1f(colorULocation, 0.25f);
        EXPECT_GL_NO_ERROR();
    
        // No errors on bound locations of names that do not exist
        // in the shader. Otherwise it would be inconsistent wrt the
        // optimization case.
        glUniform1f(nonexistingLocation, 0.25f);
        EXPECT_GL_NO_ERROR();
    
        // The above are equal to updating -1.
        glUniform1f(-1, 0.25f);
        EXPECT_GL_NO_ERROR();
    
        // No errors when updating with other type either.
        // The type can not be known with the non-existing case.
        glUniform2f(colorULocation, 0.25f, 0.25f);
        EXPECT_GL_NO_ERROR();
        glUniform2f(nonexistingLocation, 0.25f, 0.25f);
        EXPECT_GL_NO_ERROR();
        glUniform2f(-1, 0.25f, 0.25f);
        EXPECT_GL_NO_ERROR();
    
        // Ensure that driver or ANGLE has optimized the variable
        // away and the test tests what it is supposed to.
        EXPECT_EQ(-1, glGetUniformLocation(mProgram, "u_colorU"));
    
        // The bound location gets marked as used and the driver
        // does not allocate other variables to that location.
        EXPECT_NE(colorULocation, glGetUniformLocation(mProgram, "u_colorA"));
        EXPECT_NE(colorULocation, glGetUniformLocation(mProgram, "u_colorC"));
        EXPECT_NE(nonexistingLocation, glGetUniformLocation(mProgram, "u_colorA"));
        EXPECT_NE(nonexistingLocation, glGetUniformLocation(mProgram, "u_colorC"));
    
        // Unintuitive: while specifying value works, getting the value does not.
        GLfloat getResult = 0.0f;
        glGetUniformfv(mProgram, colorULocation, &getResult);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
        glGetUniformfv(mProgram, nonexistingLocation, &getResult);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
        glGetUniformfv(mProgram, -1, &getResult);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    
        // Updating an unbound, non-existing location still causes
        // an error.
        glUniform1f(unboundLocation, 0.25f);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    }
    
    // Test for a bug where using a sampler caused GL error if the mProgram had
    // uniforms that were optimized away by the driver. This was only a problem with
    // glBindUniformLocationCHROMIUM implementation. This could be reproed by
    // binding the sampler to a location higher than the amount of active uniforms.
    TEST_P(BindUniformLocationTest, UseSamplerWhenUnusedUniforms)
    {
        if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
        {
            std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
                      << std::endl;
            return;
        }
    
        ASSERT_NE(nullptr, mBindUniformLocation);
    
        const std::string vsSource =
            R"(void main()
            {
                gl_Position = vec4(0);
            })";
    
        const std::string fsSource =
            R"(uniform sampler2D tex;
            void main()
            {
                gl_FragColor = texture2D(tex, vec2(1));
            })";
    
        const GLuint texLocation = 54;
    
        GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
    
        mProgram = glCreateProgram();
        mBindUniformLocation(mProgram, texLocation, "tex");
    
        glAttachShader(mProgram, vs);
        glDeleteShader(vs);
        glAttachShader(mProgram, fs);
        glDeleteShader(fs);
    
        glLinkProgram(mProgram);
    
        GLint linked = 0;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        EXPECT_NE(0, linked);
        glUseProgram(mProgram);
        glUniform1i(texLocation, 0);
        EXPECT_GL_NO_ERROR();
    }
    
    // Test for binding a statically used uniform to the same location as a non-statically used uniform.
    // This is valid according to the extension spec.
    TEST_P(BindUniformLocationTest, SameLocationForUsedAndUnusedUniform)
    {
        if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
        {
            std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
                      << std::endl;
            return;
        }
    
        ASSERT_NE(nullptr, mBindUniformLocation);
    
        const std::string vsSource =
            R"(void main()
            {
                gl_Position = vec4(0);
            })";
    
        const std::string fsSource =
            R"(precision mediump float;
            uniform vec4 a;
            uniform vec4 b;
            void main()
            {
                gl_FragColor = a;
            })";
    
        const GLuint location = 54;
    
        GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
    
        mProgram = glCreateProgram();
        mBindUniformLocation(mProgram, location, "a");
        mBindUniformLocation(mProgram, location, "b");
    
        glAttachShader(mProgram, vs);
        glDeleteShader(vs);
        glAttachShader(mProgram, fs);
        glDeleteShader(fs);
    
        glLinkProgram(mProgram);
    
        GLint linked = GL_FALSE;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        ASSERT_GL_TRUE(linked);
        glUseProgram(mProgram);
        glUniform4f(location, 0.0, 1.0, 0.0, 1.0);
        EXPECT_GL_NO_ERROR();
    }
    
    class BindUniformLocationES31Test : public BindUniformLocationTest
    {
      protected:
        BindUniformLocationES31Test() : BindUniformLocationTest() {}
    
        void linkProgramWithUniformLocation(GLuint vs,
                                            GLuint fs,
                                            const char *uniformName,
                                            GLint uniformLocation)
        {
            mProgram = glCreateProgram();
            mBindUniformLocation(mProgram, uniformLocation, uniformName);
    
            glAttachShader(mProgram, vs);
            glDeleteShader(vs);
            glAttachShader(mProgram, fs);
            glDeleteShader(fs);
    
            glLinkProgram(mProgram);
        }
    };
    
    // Test for when the shader specifies an explicit uniform location with a layout qualifier and the
    // bindUniformLocation API sets a consistent location.
    TEST_P(BindUniformLocationES31Test, ConsistentWithLocationLayoutQualifier)
    {
        if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
        {
            std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
                      << std::endl;
            return;
        }
    
        const std::string vsSource =
            "#version 310 es\n"
            "void main()\n"
            "{\n"
            "    gl_Position = vec4(0);\n"
            "}\n";
    
        const std::string fsSource =
            "#version 310 es\n"
            "uniform layout(location=2) highp sampler2D tex;\n"
            "out highp vec4 my_FragColor;\n"
            "void main()\n"
            "{\n"
            "    my_FragColor = texture(tex, vec2(1));\n"
            "}\n";
    
        const GLuint texLocation = 2;
    
        GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
        EXPECT_NE(0u, vs);
        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
        EXPECT_NE(0u, fs);
        linkProgramWithUniformLocation(vs, fs, "tex", texLocation);
    
        GLint linked = GL_FALSE;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        ASSERT_GL_TRUE(linked);
    
        EXPECT_EQ(static_cast<GLint>(texLocation), glGetUniformLocation(mProgram, "tex"));
        glUseProgram(mProgram);
        glUniform1i(texLocation, 0);
        EXPECT_GL_NO_ERROR();
    }
    
    // Test for when the shader specifies an explicit uniform location with a layout qualifier and the
    // bindUniformLocation API sets a conflicting location for the same variable. The shader-set
    // location should prevail.
    TEST_P(BindUniformLocationES31Test, LocationLayoutQualifierOverridesAPIBinding)
    {
        if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
        {
            std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
                      << std::endl;
            return;
        }
    
        const std::string vsSource =
            "#version 310 es\n"
            "void main()\n"
            "{\n"
            "    gl_Position = vec4(0);\n"
            "}\n";
    
        const std::string fsSource =
            "#version 310 es\n"
            "uniform layout(location=2) highp sampler2D tex;\n"
            "out highp vec4 my_FragColor;\n"
            "void main()\n"
            "{\n"
            "    my_FragColor = texture(tex, vec2(1));\n"
            "}\n";
    
        const GLuint shaderTexLocation = 2;
        const GLuint texLocation       = 3;
    
        GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
        EXPECT_NE(0u, vs);
        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
        EXPECT_NE(0u, fs);
        linkProgramWithUniformLocation(vs, fs, "tex", texLocation);
    
        GLint linked = GL_FALSE;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        ASSERT_GL_TRUE(linked);
    
        EXPECT_EQ(static_cast<GLint>(shaderTexLocation), glGetUniformLocation(mProgram, "tex"));
        glUseProgram(mProgram);
        glUniform1i(shaderTexLocation, 1);
        EXPECT_GL_NO_ERROR();
        glUniform1i(texLocation, 2);
        EXPECT_GL_NO_ERROR();
    }
    
    // Test for when the shader specifies an explicit uniform location with a layout qualifier and the
    // bindUniformLocation API sets a conflicting location for a different variable. Linking should
    // fail.
    TEST_P(BindUniformLocationES31Test, LocationLayoutQualifierConflictsWithAPIBinding)
    {
        if (!extensionEnabled("GL_CHROMIUM_bind_uniform_location"))
        {
            std::cout << "Test skipped because GL_CHROMIUM_bind_uniform_location is not available."
                      << std::endl;
            return;
        }
    
        const std::string vsSource =
            "#version 310 es\n"
            "void main()\n"
            "{\n"
            "    gl_Position = vec4(0);\n"
            "}\n";
    
        const std::string fsSource =
            "#version 310 es\n"
            "uniform layout(location=2) highp sampler2D tex;\n"
            "uniform highp sampler2D tex2;\n"
            "out highp vec4 my_FragColor;\n"
            "void main()\n"
            "{\n"
            "    my_FragColor = texture(tex2, vec2(1));\n"
            "}\n";
    
        const GLuint tex2Location = 2;
    
        GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
        EXPECT_NE(0u, vs);
        GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
        EXPECT_NE(0u, fs);
        linkProgramWithUniformLocation(vs, fs, "tex2", tex2Location);
    
        GLint linked = GL_FALSE;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
        ASSERT_GL_FALSE(linked);
    }
    
    // Use this to select which configurations (e.g. which renderer, which GLES major version) these
    // tests should be run against.
    ANGLE_INSTANTIATE_TEST(BindUniformLocationTest,
                           ES2_D3D9(),
                           ES2_D3D11(),
                           ES2_D3D11_FL9_3(),
                           ES2_OPENGL(),
                           ES2_OPENGLES());
    
    ANGLE_INSTANTIATE_TEST(BindUniformLocationES31Test, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES())
    
    }  // namespace