Edit

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

Branch :

  • Show log

    Commit

  • Author : Qin Jiajia
    Date : 2018-10-09 13:59:56
    Hash : 1d8a783c
    Message : Re-land: "ES31: Add vector and matrix support in SSBO for D3D" Re-land skips ProgramInterfaceTestES31.GetProgramInterface/ES3_1_D3D11 to pass the bots. In fact, ProgramInterfaceTestES31.GetProgramInterface/ES3_1_D3D11 is not a regression. The reverted CL added more SSBO features and triggered the failure. To enable ProgramInterfaceTestES31.GetProgramInterface/ES3_1_D3D11, we should support SSBO in render pipeline. This needs to bind SSBO to UAV registers in link time instead of compile time since output variables also occupies the UAVs. Let's enable this test when we support SSBO in render pipeline. Currently, we shouldn't block the SSBO implementation in some common features. Bug: angleproject:1951 Change-Id: Ic339e8327e79335e6db1d86bedf0072635976f5f Reviewed-on: https://chromium-review.googlesource.com/c/1282277 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Jiajia Qin <jiajia.qin@intel.com>

  • src/tests/gl_tests/ProgramInterfaceTest.cpp
  • //
    // Copyright 2017 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.
    //
    
    // ProgramInterfaceTest: Tests of program interfaces.
    
    #include "common/string_utils.h"
    #include "test_utils/ANGLETest.h"
    #include "test_utils/gl_raii.h"
    
    using namespace angle;
    
    namespace
    {
    
    class ProgramInterfaceTestES31 : public ANGLETest
    {
      protected:
        ProgramInterfaceTestES31()
        {
            setWindowWidth(64);
            setWindowHeight(64);
            setConfigRedBits(8);
            setConfigGreenBits(8);
            setConfigBlueBits(8);
            setConfigAlphaBits(8);
        }
    };
    
    // Tests glGetProgramResourceIndex.
    TEST_P(ProgramInterfaceTestES31, GetResourceIndex)
    {
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "uniform vec4 color;\n"
            "out vec4 oColor;\n"
            "void main()\n"
            "{\n"
            "    oColor = color;\n"
            "}";
    
        ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fragmentShaderSource);
    
        GLuint index =
            glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, essl31_shaders::PositionAttrib());
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "missing");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(GL_INVALID_INDEX, index);
    
        index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "missing");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(GL_INVALID_INDEX, index);
    
        index = glGetProgramResourceIndex(program, GL_ATOMIC_COUNTER_BUFFER, "missing");
        EXPECT_GL_ERROR(GL_INVALID_ENUM);
    }
    
    // Tests glGetProgramResourceName.
    TEST_P(ProgramInterfaceTestES31, GetResourceName)
    {
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "uniform vec4 color;\n"
            "out vec4 oColor[4];\n"
            "void main()\n"
            "{\n"
            "    oColor[0] = color;\n"
            "}";
    
        ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fragmentShaderSource);
    
        GLuint index =
            glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, essl31_shaders::PositionAttrib());
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        GLchar name[64];
        GLsizei length;
        glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, sizeof(name), &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(static_cast<int>(strlen(essl31_shaders::PositionAttrib())), length);
        EXPECT_EQ(essl31_shaders::PositionAttrib(), std::string(name));
    
        glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, 4, &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(3, length);
        EXPECT_TRUE(angle::BeginsWith(essl31_shaders::PositionAttrib(), name));
    
        glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, -1, &length, name);
        EXPECT_GL_ERROR(GL_INVALID_VALUE);
    
        glGetProgramResourceName(program, GL_PROGRAM_INPUT, GL_INVALID_INDEX, sizeof(name), &length,
                                 name);
        EXPECT_GL_ERROR(GL_INVALID_VALUE);
    
        index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, sizeof(name), &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(9, length);
        EXPECT_EQ("oColor[0]", std::string(name));
    
        glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, 8, &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(7, length);
        EXPECT_EQ("oColor[", std::string(name));
    }
    
    // Tests glGetProgramResourceLocation.
    TEST_P(ProgramInterfaceTestES31, GetResourceLocation)
    {
        const std::string &vertexShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "layout(location = 3) in highp vec4 position;\n"
            "in highp vec4 noLocationSpecified;\n"
            "void main()\n"
            "{\n"
            "    gl_Position = position;\n"
            "}";
    
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "uniform vec4 color;\n"
            "layout(location = 2) out vec4 oColor[4];\n"
            "void main()\n"
            "{\n"
            "    oColor[0] = color;\n"
            "}";
    
        ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
    
        GLenum invalidInterfaces[] = {GL_UNIFORM_BLOCK, GL_TRANSFORM_FEEDBACK_VARYING,
                                      GL_BUFFER_VARIABLE, GL_SHADER_STORAGE_BLOCK,
                                      GL_ATOMIC_COUNTER_BUFFER};
        GLint location;
        for (auto &invalidInterface : invalidInterfaces)
        {
            location = glGetProgramResourceLocation(program, invalidInterface, "any");
            EXPECT_GL_ERROR(GL_INVALID_ENUM);
            EXPECT_EQ(-1, location);
        }
    
        location = glGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(3, location);
    
        location = glGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "noLocationSpecified");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(-1, location);
    
        location = glGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "missing");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(-1, location);
    
        location = glGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "oColor");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(2, location);
        location = glGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "oColor[0]");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(2, location);
        location = glGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "oColor[3]");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(5, location);
    }
    
    // Tests glGetProgramResource.
    TEST_P(ProgramInterfaceTestES31, GetResource)
    {
        const std::string &vertexShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "layout(location = 3) in highp vec4 position;\n"
            "void main()\n"
            "{\n"
            "    gl_Position = position;\n"
            "}";
    
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "uniform vec4 color;\n"
            "layout(location = 2) out vec4 oColor[4];\n"
            "void main()\n"
            "{\n"
            "    oColor[0] = color;\n"
            "}";
    
        ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
    
        GLuint index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        GLenum props[]    = {GL_TYPE,
                          GL_ARRAY_SIZE,
                          GL_LOCATION,
                          GL_NAME_LENGTH,
                          GL_REFERENCED_BY_VERTEX_SHADER,
                          GL_REFERENCED_BY_FRAGMENT_SHADER,
                          GL_REFERENCED_BY_COMPUTE_SHADER};
        GLsizei propCount = static_cast<GLsizei>(ArraySize(props));
        GLint params[ArraySize(props)];
        GLsizei length;
    
        glGetProgramResourceiv(program, GL_PROGRAM_INPUT, index, propCount, props, propCount, &length,
                               params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount, length);
        EXPECT_EQ(GL_FLOAT_VEC4, params[0]);  // type
        EXPECT_EQ(1, params[1]);              // array_size
        EXPECT_EQ(3, params[2]);              // location
        EXPECT_EQ(9, params[3]);              // name_length
        EXPECT_EQ(1, params[4]);              // referenced_by_vertex_shader
        EXPECT_EQ(0, params[5]);              // referenced_by_fragment_shader
        EXPECT_EQ(0, params[6]);              // referenced_by_compute_shader
    
        index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor[0]");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(index, GL_INVALID_INDEX);
        // bufSize is smaller than propCount.
        glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, index, propCount, props, propCount - 1,
                               &length, params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount - 1, length);
        EXPECT_EQ(GL_FLOAT_VEC4, params[0]);  // type
        EXPECT_EQ(4, params[1]);              // array_size
        EXPECT_EQ(2, params[2]);              // location
        EXPECT_EQ(10, params[3]);             // name_length
        EXPECT_EQ(0, params[4]);              // referenced_by_vertex_shader
        EXPECT_EQ(1, params[5]);              // referenced_by_fragment_shader
    
        GLenum invalidOutputProp = GL_OFFSET;
        glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, index, 1, &invalidOutputProp, 1, &length,
                               params);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    }
    
    // Tests glGetProgramInterfaceiv.
    TEST_P(ProgramInterfaceTestES31, GetProgramInterface)
    {
        // TODO(jiajia.qin@intel.com): Don't skip this test once SSBO are supported on render pipeline.
        // http://anglebug.com/1951
        ANGLE_SKIP_TEST_IF(IsD3D11());
    
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "uniform vec4 color;\n"
            "out vec4 oColor;\n"
            "uniform ub {\n"
            "    vec4 mem0;\n"
            "    vec4 mem1;\n"
            "} instance;\n"
            "layout(std430) buffer shaderStorageBlock1 {\n"
            "    vec3 target;\n"
            "};\n"
            "layout(std430) buffer shaderStorageBlock2 {\n"
            "    vec3 target;\n"
            "} blockInstance2[1];\n"
            "void main()\n"
            "{\n"
            "    oColor = color;\n"
            "    target = vec3(0, 0, 0);\n"
            "    blockInstance2[0].target = vec3(1, 1, 1);\n"
            "}";
    
        ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fragmentShaderSource);
    
        GLint num;
        glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(1, num);
    
        glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(static_cast<GLint>(strlen(essl3_shaders::PositionAttrib())) + 1, num);
    
        glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    
        glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(1, num);
    
        glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(7, num);
    
        glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    
        glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(1, num);
    
        glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NAME_LENGTH, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(3, num);
    
        glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(2, num);  // mem0, mem1
    
        glGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(3, num);
    
        glGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(8, num);  // "ub.mem0"
    
        glGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    
        glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(2, num);
    
        glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(23, num);  // "shaderStorageBlock2[0]"
    
        glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(1, num);
    }
    
    // Tests the resource property query for uniform can be done correctly.
    TEST_P(ProgramInterfaceTestES31, GetUniformProperties)
    {
        // TODO(jiajia.qin@intel.com): Don't skip this test once atomic counter is supported on d3d
        // backend. http://anglebug.com/1729
        ANGLE_SKIP_TEST_IF(IsD3D11());
    
        const std::string &vertexShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "uniform layout(location=12) vec4 color;\n"
            "layout(binding = 2, offset = 4) uniform atomic_uint foo;\n"
            "void main()\n"
            "{\n"
            "    atomicCounterIncrement(foo);\n"
            "}";
    
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "uniform vec4 color;\n"
            "out vec4 oColor;\n"
            "void main()\n"
            "{\n"
            "    oColor = color;\n"
            "}";
    
        ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
    
        GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "color");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        GLchar name[64];
        GLsizei length;
        glGetProgramResourceName(program, GL_UNIFORM, index, sizeof(name), &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(5, length);
        EXPECT_EQ("color", std::string(name));
    
        GLint location = glGetProgramResourceLocation(program, GL_UNIFORM, "color");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(12, location);
    
        GLenum props[]    = {GL_TYPE,
                          GL_ARRAY_SIZE,
                          GL_LOCATION,
                          GL_NAME_LENGTH,
                          GL_REFERENCED_BY_VERTEX_SHADER,
                          GL_REFERENCED_BY_FRAGMENT_SHADER,
                          GL_REFERENCED_BY_COMPUTE_SHADER,
                          GL_ARRAY_STRIDE,
                          GL_BLOCK_INDEX,
                          GL_IS_ROW_MAJOR,
                          GL_MATRIX_STRIDE,
                          GL_OFFSET,
                          GL_ATOMIC_COUNTER_BUFFER_INDEX};
        GLsizei propCount = static_cast<GLsizei>(ArraySize(props));
        GLint params[ArraySize(props)];
        glGetProgramResourceiv(program, GL_UNIFORM, index, propCount, props, propCount, &length,
                               params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount, length);
        EXPECT_EQ(GL_FLOAT_VEC4, params[0]);  // type
        EXPECT_EQ(1, params[1]);              // array_size
        EXPECT_EQ(12, params[2]);             // location
        EXPECT_EQ(6, params[3]);              // name_length
        EXPECT_EQ(0, params[4]);              // referenced_by_vertex_shader
        EXPECT_EQ(1, params[5]);              // referenced_by_fragment_shader
        EXPECT_EQ(0, params[6]);              // referenced_by_compute_shader
        EXPECT_EQ(-1, params[7]);             // array_stride
        EXPECT_EQ(-1, params[8]);             // block_index
        EXPECT_EQ(0, params[9]);              // is_row_major
        EXPECT_EQ(-1, params[10]);            // matrix_stride
        EXPECT_EQ(-1, params[11]);            // offset
        EXPECT_EQ(-1, params[12]);            // atomic_counter_buffer_index
    
        index = glGetProgramResourceIndex(program, GL_UNIFORM, "foo");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        glGetProgramResourceName(program, GL_UNIFORM, index, sizeof(name), &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(3, length);
        EXPECT_EQ("foo", std::string(name));
    
        location = glGetProgramResourceLocation(program, GL_UNIFORM, "foo");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(-1, location);
    
        glGetProgramResourceiv(program, GL_UNIFORM, index, propCount, props, propCount, &length,
                               params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount, length);
        EXPECT_EQ(GL_UNSIGNED_INT_ATOMIC_COUNTER, params[0]);  // type
        EXPECT_EQ(1, params[1]);                               // array_size
        EXPECT_EQ(-1, params[2]);                              // location
        EXPECT_EQ(4, params[3]);                               // name_length
        EXPECT_EQ(1, params[4]);                               // referenced_by_vertex_shader
        EXPECT_EQ(0, params[5]);                               // referenced_by_fragment_shader
        EXPECT_EQ(0, params[6]);                               // referenced_by_compute_shader
        EXPECT_EQ(0, params[7]);                               // array_stride
        EXPECT_EQ(-1, params[8]);                              // block_index
        EXPECT_EQ(0, params[9]);                               // is_row_major
        EXPECT_EQ(0, params[10]);                              // matrix_stride
        EXPECT_EQ(4, params[11]);                              // offset
        EXPECT_NE(-1, params[12]);                             // atomic_counter_buffer_index
    }
    
    // Tests the resource property query for uniform block can be done correctly.
    TEST_P(ProgramInterfaceTestES31, GetUniformBlockProperties)
    {
        const std::string &vertexShaderSource =
            "#version 310 es\n"
            "in vec2 position;\n"
            "out vec2 v;\n"
            "layout(binding = 2) uniform blockName {\n"
            "  float f1;\n"
            "  float f2;\n"
            "} instanceName;\n"
            "void main() {\n"
            "  v = vec2(instanceName.f1, instanceName.f2);\n"
            "  gl_Position = vec4(position, 0, 1);\n"
            "}";
    
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "in vec2 v;\n"
            "out vec4 color;\n"
            "void main() {\n"
            "  color = vec4(v, 0, 1);\n"
            "}";
    
        ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
    
        GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, "blockName");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        GLchar name[64];
        GLsizei length;
        glGetProgramResourceName(program, GL_UNIFORM_BLOCK, index, sizeof(name), &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(9, length);
        EXPECT_EQ("blockName", std::string(name));
    
        GLenum props[]         = {GL_BUFFER_BINDING,
                          GL_BUFFER_DATA_SIZE,
                          GL_NAME_LENGTH,
                          GL_NUM_ACTIVE_VARIABLES,
                          GL_ACTIVE_VARIABLES,
                          GL_REFERENCED_BY_VERTEX_SHADER,
                          GL_REFERENCED_BY_FRAGMENT_SHADER,
                          GL_REFERENCED_BY_COMPUTE_SHADER};
        GLsizei propCount      = static_cast<GLsizei>(ArraySize(props));
        constexpr int kBufSize = 256;
        GLint params[kBufSize];
        GLint magic = 0xBEEF;
    
        // Tests bufSize is respected even some prop returns more than one value.
        params[propCount] = magic;
        glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, propCount, props, propCount, &length,
                               params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount, length);
        EXPECT_EQ(2, params[0]);   // buffer_binding
        EXPECT_NE(0, params[1]);   // buffer_data_size
        EXPECT_EQ(10, params[2]);  // name_length
        EXPECT_EQ(2, params[3]);   // num_active_variables
        EXPECT_LE(0, params[4]);   // index of 'f1' or 'f2'
        EXPECT_LE(0, params[5]);   // index of 'f1' or 'f2'
        EXPECT_EQ(1, params[6]);   // referenced_by_vertex_shader
        EXPECT_EQ(0, params[7]);   // referenced_by_fragment_shader
        EXPECT_EQ(magic, params[8]);
    
        glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, propCount, props, kBufSize, &length,
                               params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount + 1, length);
        EXPECT_EQ(0, params[8]);  // referenced_by_compute_shader
    
        // bufSize is reached in middle of outputting values for GL_ACTIVE_VARIABLES.
        GLenum actvieVariablesProperty = GL_ACTIVE_VARIABLES;
        params[1]                      = magic;
        glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, 1, &actvieVariablesProperty, 1,
                               &length, params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(1, length);
        EXPECT_LE(0, params[0]);  // index of 'f1' or 'f2'
        EXPECT_EQ(magic, params[1]);
    }
    
    // Tests atomic counter buffer qeury works correctly.
    TEST_P(ProgramInterfaceTestES31, QueryAtomicCounteBuffer)
    {
        // TODO(jiajia.qin@intel.com): Don't skip this test once atomic counter is supported on d3d
        // backend. http://anglebug.com/1729
        ANGLE_SKIP_TEST_IF(IsD3D11());
    
        const std::string &vertShader =
            "#version 310 es\n"
            "precision highp float;\n"
            "layout(binding = 2, offset = 0) uniform atomic_uint vcounter;\n"
            "in highp vec4 a_position;\n"
            "void main()\n"
            "{\n"
            "    atomicCounterIncrement(vcounter);\n"
            "    gl_Position = a_position;\n"
            "}\n";
    
        const std::string &fragShader =
            "#version 310 es\n"
            "precision highp float;\n"
            "layout(binding = 2, offset = 4) uniform atomic_uint fcounter;\n"
            "out highp vec4 my_color;\n"
            "void main()\n"
            "{\n"
            "    atomicCounterDecrement(fcounter);\n"
            "    my_color = vec4(0.0);\n"
            "}\n";
    
        ANGLE_GL_PROGRAM(program, vertShader, fragShader);
        GLint num;
        glGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(1, num);
    
        glGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(2, num);
    
        GLenum props[]    = {GL_BUFFER_BINDING, GL_NUM_ACTIVE_VARIABLES, GL_REFERENCED_BY_VERTEX_SHADER,
                          GL_REFERENCED_BY_FRAGMENT_SHADER, GL_REFERENCED_BY_COMPUTE_SHADER};
        GLsizei propCount = static_cast<GLsizei>(ArraySize(props));
        GLint params[ArraySize(props)];
        GLsizei length = 0;
        glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, 0, propCount, props, propCount,
                               &length, params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount, length);
        EXPECT_EQ(2, params[0]);  // buffer_binding
        EXPECT_EQ(2, params[1]);  // num_active_variables
        EXPECT_EQ(1, params[2]);  // referenced_by_vertex_shader
        EXPECT_EQ(1, params[3]);  // referenced_by_fragment_shader
        EXPECT_EQ(0, params[4]);  // referenced_by_compute_shader
    }
    
    // Tests the resource property query for buffer variable can be done correctly.
    TEST_P(ProgramInterfaceTestES31, GetBufferVariableProperties)
    {
        // TODO(jiajia.qin@intel.com): Don't skip this test once non-simple SSBO sentences are supported
        // on d3d backend. http://anglebug.com/1951
        ANGLE_SKIP_TEST_IF(IsD3D11());
    
        const std::string &vertexShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "struct S {\n"
            "    vec3 a;\n"
            "    ivec2 b[4];\n"
            "};\n"
            "layout(std140) buffer blockName0 {\n"
            "    S s0;\n"
            "    vec2 v0;\n"
            "    S s1[2];\n"
            "    uint u0;\n"
            "};\n"
            "layout(binding = 1) buffer blockName1 {\n"
            "    uint u1[2];\n"
            "    float f1;\n"
            "} instanceName1[2];\n"
            "void main()\n"
            "{\n"
            "    gl_Position = vec4(instanceName1[0].f1, s1[0].a);\n"
            "}\n";
    
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "layout(binding = 1) buffer blockName1 {\n"
            "    uint u1[2];\n"
            "    float f1;\n"
            "} instanceName1[2];\n"
            "out vec4 oColor;\n"
            "void main()\n"
            "{\n"
            "    oColor = vec4(instanceName1[0].f1, 0, 0, 1);\n"
            "}";
    
        ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
    
        GLuint index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockName1.f1");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        GLchar name[64];
        GLsizei length;
        glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(13, length);
        EXPECT_EQ("blockName1.f1", std::string(name));
    
        GLenum props[]         = {GL_ARRAY_SIZE,
                          GL_ARRAY_STRIDE,
                          GL_BLOCK_INDEX,
                          GL_IS_ROW_MAJOR,
                          GL_MATRIX_STRIDE,
                          GL_NAME_LENGTH,
                          GL_OFFSET,
                          GL_REFERENCED_BY_VERTEX_SHADER,
                          GL_REFERENCED_BY_FRAGMENT_SHADER,
                          GL_REFERENCED_BY_COMPUTE_SHADER,
                          GL_TOP_LEVEL_ARRAY_SIZE,
                          GL_TOP_LEVEL_ARRAY_STRIDE,
                          GL_TYPE};
        GLsizei propCount      = static_cast<GLsizei>(ArraySize(props));
        constexpr int kBufSize = 256;
        GLint params[kBufSize];
    
        glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length,
                               params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount, length);
        EXPECT_EQ(1, params[0]);   // array_size
        EXPECT_LE(0, params[1]);   // array_stride
        EXPECT_LE(0, params[2]);   // block_index
        EXPECT_EQ(0, params[3]);   // is_row_major
        EXPECT_EQ(0, params[4]);   // matrix_stride
        EXPECT_EQ(14, params[5]);  // name_length
        EXPECT_LE(0, params[6]);   // offset
    
        EXPECT_EQ(1, params[7]);  // referenced_by_vertex_shader
        EXPECT_EQ(1, params[8]);  // referenced_by_fragment_shader
        EXPECT_EQ(0, params[9]);  // referenced_by_compute_shader
    
        EXPECT_EQ(1, params[10]);  // top_level_array_size
        EXPECT_LE(0, params[11]);  // top_level_array_stride
    
        EXPECT_EQ(GL_FLOAT, params[12]);  // type
    
        index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "s1[0].a");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(7, length);
        EXPECT_EQ("s1[0].a", std::string(name));
    
        glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length,
                               params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount, length);
        EXPECT_EQ(1, params[0]);  // array_size
        EXPECT_LE(0, params[1]);  // array_stride
        EXPECT_LE(0, params[2]);  // block_index
        EXPECT_EQ(0, params[3]);  // is_row_major
        EXPECT_EQ(0, params[4]);  // matrix_stride
        EXPECT_EQ(8, params[5]);  // name_length
        EXPECT_LE(0, params[6]);  // offset
    
        EXPECT_EQ(1, params[7]);  // referenced_by_vertex_shader
        EXPECT_EQ(0, params[8]);  // referenced_by_fragment_shader
        EXPECT_EQ(0, params[9]);  // referenced_by_compute_shader
    
        EXPECT_EQ(2, params[10]);   // top_level_array_size
        EXPECT_EQ(80, params[11]);  // top_level_array_stride
    
        EXPECT_EQ(GL_FLOAT_VEC3, params[12]);  // type
    }
    
    // Tests the resource property query for shader storage block can be done correctly.
    TEST_P(ProgramInterfaceTestES31, GetShaderStorageBlockProperties)
    {
        // TODO(jiajia.qin@intel.com): Don't skip this test once non-simple SSBO sentences are supported
        // on d3d backend. http://anglebug.com/1951
        ANGLE_SKIP_TEST_IF(IsD3D11());
    
        const std::string &vertexShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "struct S {\n"
            "    vec3 a;\n"
            "    ivec2 b[4];\n"
            "};\n"
            "layout(std140) buffer blockName0 {\n"
            "    S s0;\n"
            "    vec2 v0;\n"
            "    S s1[2];\n"
            "    uint u0;\n"
            "};\n"
            "layout(binding = 1) buffer blockName1 {\n"
            "    uint u1[2];\n"
            "    float f1;\n"
            "} instanceName1[2];\n"
            "layout(binding = 2) buffer blockName2 {\n"
            "    uint u2;\n"
            "    float f2;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    gl_Position = vec4(instanceName1[0].f1, s1[0].a);\n"
            "}\n";
    
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "precision highp float;\n"
            "uniform vec4 color;\n"
            "out vec4 oColor;\n"
            "void main()\n"
            "{\n"
            "    oColor = color;\n"
            "}";
    
        ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
    
        GLuint index = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "blockName0");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        GLchar name[64];
        GLsizei length;
        glGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, index, sizeof(name), &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(10, length);
        EXPECT_EQ("blockName0", std::string(name));
    
        GLenum props[]         = {GL_ACTIVE_VARIABLES,
                          GL_BUFFER_BINDING,
                          GL_NUM_ACTIVE_VARIABLES,
                          GL_BUFFER_DATA_SIZE,
                          GL_NAME_LENGTH,
                          GL_REFERENCED_BY_VERTEX_SHADER,
                          GL_REFERENCED_BY_FRAGMENT_SHADER,
                          GL_REFERENCED_BY_COMPUTE_SHADER};
        GLsizei propCount      = static_cast<GLsizei>(ArraySize(props));
        constexpr int kBufSize = 256;
        GLint params[kBufSize];
    
        glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, index, propCount, props, kBufSize,
                               &length, params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(13, length);
        EXPECT_LE(0, params[0]);   // active_variables s0.a
        EXPECT_LE(0, params[1]);   // active_variables s0.b
        EXPECT_LE(0, params[2]);   // active_variables v0
        EXPECT_LE(0, params[3]);   // active_variables s1[0].a
        EXPECT_LE(0, params[4]);   // active_variables s1[0].b
        EXPECT_LE(0, params[5]);   // active_variables u0
        EXPECT_EQ(0, params[6]);   // buffer_binding
        EXPECT_EQ(6, params[7]);   // num_active_variables
        EXPECT_LE(0, params[8]);   // buffer_data_size
        EXPECT_EQ(11, params[9]);  // name_length
    
        EXPECT_EQ(1, params[10]);  // referenced_by_vertex_shader
        EXPECT_EQ(0, params[11]);  // referenced_by_fragment_shader
        EXPECT_EQ(0, params[12]);  // referenced_by_compute_shader
    
        index = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "blockName1");
        EXPECT_GL_NO_ERROR();
        EXPECT_NE(GL_INVALID_INDEX, index);
    
        glGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, index, sizeof(name), &length, name);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(13, length);
        EXPECT_EQ("blockName1[0]", std::string(name));
    }
    
    // Tests transform feedback varying qeury works correctly.
    TEST_P(ProgramInterfaceTestES31, QueryTransformFeedbackVarying)
    {
        const std::string &vertexShaderSource =
            R"(#version 310 es
    
            in vec3 position;\
            out float outSingleType;
            out vec2 outWholeArray[2];
            out vec3 outArrayElements[16];
            void main() {
              outSingleType = 0.0;
              outWholeArray[0] = vec2(position);
              outArrayElements[7] = vec3(0, 0, 0);
              outArrayElements[15] = position;
              gl_Position = vec4(position, 1);
            })";
    
        const std::string &fragmentShaderSource =
            R"(#version 310 es
    
            precision mediump float;
            out vec4 color;
            in float outSingleType;
            in vec2 outWholeArray[2];
            in vec3 outArrayElements[16];
            void main() {
              color = vec4(0);
            })";
    
        std::vector<std::string> tfVaryings;
        tfVaryings.push_back("outArrayElements[7]");
        tfVaryings.push_back("outArrayElements[15]");
        tfVaryings.push_back("outSingleType");
        tfVaryings.push_back("outWholeArray");
    
        GLuint program = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
                                                             tfVaryings, GL_INTERLEAVED_ATTRIBS);
        ASSERT_NE(0u, program);
    
        GLint num;
        glGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_ACTIVE_RESOURCES, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(4, num);
    
        glGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_MAX_NAME_LENGTH, &num);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(21, num);  // outArrayElements[15]
    
        // GLES 3.10, Page 77:
        // For TRANSFORM_FEEDBACK_VARYING, the active resource list will use the variable order
        // specified in the most recent call to TransformFeedbackVaryings before the last call to
        // LinkProgram.
        GLuint index =
            glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outArrayElements[7]");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(0u, index);
        index =
            glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outArrayElements[15]");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(1u, index);
        index = glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outSingleType");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(2u, index);
        index = glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outWholeArray");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(3u, index);
    
        // GLES 3.10, Page 80:
        // For TRANSFORM_FEEDBACK_VARYING resources, name must match one of the variables to be captured
        // as specified by a previous call to TransformFeedbackVaryings. Otherwise, INVALID_INDEX is
        // returned.
        // If name does not match a resource as described above, the value INVALID_INDEX is returned,
        // but no GL error is generated.
        index = glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outWholeArray[0]");
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(GL_INVALID_INDEX, index);
    
        GLenum props[]    = {GL_TYPE, GL_ARRAY_SIZE, GL_NAME_LENGTH};
        GLsizei propCount = static_cast<GLsizei>(ArraySize(props));
        GLint params[ArraySize(props)];
        GLsizei length = 0;
        // Query properties of 'outArrayElements[15]'.
        glGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, 1, propCount, props, propCount,
                               &length, params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount, length);
        EXPECT_EQ(GL_FLOAT_VEC3, params[0]);  // type
        EXPECT_EQ(1, params[1]);              // array_size
        EXPECT_EQ(21, params[2]);             // name_length
    
        // Query properties of 'outWholeArray'.
        glGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, 3, propCount, props, propCount,
                               &length, params);
        EXPECT_GL_NO_ERROR();
        EXPECT_EQ(propCount, length);
        EXPECT_EQ(GL_FLOAT_VEC2, params[0]);  // type
        EXPECT_EQ(2, params[1]);              // array_size
        EXPECT_EQ(14, params[2]);             // name_length
    
        glDeleteProgram(program);
    }
    
    ANGLE_INSTANTIATE_TEST(ProgramInterfaceTestES31, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
    
    }  // anonymous namespace