src/third_party/angle/src/tests/gl_tests/UniformBufferTest.cpp
// Test a uniform block with large struct array member and a uniform block with small
// struct array member in different programs, but they share the same uniform buffer.
Test a uniform block with large struct array member and a uniform block with small
struct array member in different programs, but they share the same uniform buffer.
Test a uniform block with large struct array member and a uniform block with small struct array member in different programs but they share the same uniform buffer .
TEST_P(UniformBlockWithOneLargeArrayMemberTest, TwoUniformBlocksInDiffProgram)
{
    std::ostringstream stream1;
    std::ostringstream stream2;
    generateArraySizeAndDivisorsDeclaration(stream1, false, true, false);
    generateArraySizeAndDivisorsDeclaration(stream2, false, false, false);
    const std::string &kFS1 =
        "#version 300 es\n"
        "precision highp float;\n" +
        stream1.str() +
        "out vec4 my_FragColor;\n"
        "struct S { mat4 color;};\n"
        "layout(std140) uniform buffer { S s[arraySize]; };\n"
        "void main()\n"
        "{\n"
        "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
        "    uint index = coord.x +  coord.y * 128u;\n"
        "    uint index_x = index / divisor1;\n"
        "    uint index_y = (index % divisor1) / divisor2;\n"
        "    my_FragColor = s[index_x].color[index_y];\n"
        "}\n";
    const std::string &kFS2 =
        "#version 300 es\n"
        "precision highp float;\n" +
        stream2.str() +
        "out vec4 my_FragColor;\n"
        "struct S { mat4 color;};\n"
        "layout(std140) uniform buffer { S s[arraySize]; };\n"
        "void main()\n"
        "{\n"
        "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
        "    uint index_x = coord.x / divisor;\n"
        "    uint index_y = coord.x % 4u;\n"
        "    my_FragColor = s[index_x].color[index_y];\n"
        "}\n";
    GLint blockSize1, blockSize2;
    ANGLE_GL_PROGRAM(program1, essl3_shaders::vs::Simple(), kFS1.c_str());
    ANGLE_GL_PROGRAM(program2, essl3_shaders::vs::Simple(), kFS2.c_str());
    GLint uniformBufferIndex1 = glGetUniformBlockIndex(program1, "buffer");
    GLint uniformBufferIndex2 = glGetUniformBlockIndex(program2, "buffer");
    glGetActiveUniformBlockiv(program1, uniformBufferIndex1, GL_UNIFORM_BLOCK_DATA_SIZE,
                              &blockSize1);
    glGetActiveUniformBlockiv(program2, uniformBufferIndex2, GL_UNIFORM_BLOCK_DATA_SIZE,
                              &blockSize2);
    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
    glBufferData(GL_UNIFORM_BUFFER, std::max(blockSize1, blockSize2), nullptr, GL_STATIC_DRAW);
    glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, blockSize2);
    glUniformBlockBinding(program2, uniformBufferIndex2, 0);
    glBindBufferRange(GL_UNIFORM_BUFFER, 1, mUniformBuffer, 0, blockSize1);
    glUniformBlockBinding(program1, uniformBufferIndex1, 1);
    const GLuint arraySize1  = getArraySize();
    const GLuint arraySize2  = getArraySize2();
    const GLuint floatCount1 = arraySize1 * kVectorPerMat * kFloatPerVector;
    const GLuint floatCount2 = arraySize2 * kVectorPerMat * kFloatPerVector;
    const GLuint floatCount  = floatCount1;
    std::vector<GLfloat> floatData(floatCount, 0.0f);
    setArrayValues(floatData, 0, arraySize1, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f, 1.0f);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), &floatData[0]);
    drawQuad(program1.get(), essl3_shaders::PositionAttrib(), 0.5f);
    checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
    setArrayValues(floatData, 0, arraySize2, 16, 0, 4, 4, 0.0f, 1.0f, 0.0f, 1.0f);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount2 * sizeof(GLfloat), &floatData[0]);
    drawQuad(program2.get(), essl3_shaders::PositionAttrib(), 0.5f);
    checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
    setArrayValues(floatData, arraySize2, arraySize2 + arraySize1 / 2, 16, 0, 4, 4, 0.0f, 1.0f,
                   0.0f, 1.0f);
    glBufferSubData(GL_UNIFORM_BUFFER, floatCount2 * sizeof(GLfloat),
                    (floatCount1 / 2 - floatCount2) * sizeof(GLfloat), &floatData[0]);
    drawQuad(program1.get(), essl3_shaders::PositionAttrib(), 0.5f);
    checkResults(GLColor::green, GLColor::green, GLColor::blue, GLColor::blue);
}
TEST_P ( UniformBlockWithOneLargeArrayMemberTest , TwoUniformBlocksInDiffProgram ) { std :: ostringstream stream1 ; std :: ostringstream stream2 ; generateArraySizeAndDivisorsDeclaration ( stream1 , false , true , false ) ; generateArraySizeAndDivisorsDeclaration ( stream2 , false , false , false ) ; const std :: string & kFS1 = " \n " " \n " + stream1 . str ( ) + " \n " " \n " " \n " " \n " " \n " " \n " " \n " " \n " " \n " " \n " " \n " ; const std :: string & kFS2 = " \n " " \n " + stream2 . str ( ) + " \n " " \n " " \n " " \n " " \n " " \n " " \n " " \n " " \n " " \n " ; GLint blockSize1 , blockSize2 ; ANGLE_GL_PROGRAM ( program1 , essl3_shaders :: vs :: Simple ( ) , kFS1 . c_str ( ) ) ; ANGLE_GL_PROGRAM ( program2 , essl3_shaders :: vs :: Simple ( ) , kFS2 . c_str ( ) ) ; GLint uniformBufferIndex1 = glGetUniformBlockIndex ( program1 , " " ) ; GLint uniformBufferIndex2 = glGetUniformBlockIndex ( program2 , " " ) ; glGetActiveUniformBlockiv ( program1 , uniformBufferIndex1 , GL_UNIFORM_BLOCK_DATA_SIZE , & blockSize1 ) ; glGetActiveUniformBlockiv ( program2 , uniformBufferIndex2 , GL_UNIFORM_BLOCK_DATA_SIZE , & blockSize2 ) ; glBindBuffer ( GL_UNIFORM_BUFFER , mUniformBuffer ) ; glBufferData ( GL_UNIFORM_BUFFER , std :: max ( blockSize1 , blockSize2 ) , nullptr , GL_STATIC_DRAW ) ; glBindBufferRange ( GL_UNIFORM_BUFFER , 0 , mUniformBuffer , 0 , blockSize2 ) ; glUniformBlockBinding ( program2 , uniformBufferIndex2 , 0 ) ; glBindBufferRange ( GL_UNIFORM_BUFFER , 1 , mUniformBuffer , 0 , blockSize1 ) ; glUniformBlockBinding ( program1 , uniformBufferIndex1 , 1 ) ; const GLuint arraySize1 = getArraySize ( ) ; const GLuint arraySize2 = getArraySize2 ( ) ; const GLuint floatCount1 = arraySize1 * kVectorPerMat * kFloatPerVector ; const GLuint floatCount2 = arraySize2 * kVectorPerMat * kFloatPerVector ; const GLuint floatCount = floatCount1 ; std :: vector < GLfloat > floatData ( floatCount , 0.0f ) ; setArrayValues ( floatData , 0 , arraySize1 , 16 , 0 , 4 , 4 , 0.0f , 0.0f , 1.0f , 1.0f ) ; glBufferSubData ( GL_UNIFORM_BUFFER , 0 , floatCount * sizeof ( GLfloat ) , & floatData [ 0 ] ) ; drawQuad ( program1 . get ( ) , essl3_shaders :: PositionAttrib ( ) , 0.5f ) ; checkResults ( GLColor :: blue , GLColor :: blue , GLColor :: blue , GLColor :: blue ) ; setArrayValues ( floatData , 0 , arraySize2 , 16 , 0 , 4 , 4 , 0.0f , 1.0f , 0.0f , 1.0f ) ; glBufferSubData ( GL_UNIFORM_BUFFER , 0 , floatCount2 * sizeof ( GLfloat ) , & floatData [ 0 ] ) ; drawQuad ( program2 . get ( ) , essl3_shaders :: PositionAttrib ( ) , 0.5f ) ; checkResults ( GLColor :: green , GLColor :: green , GLColor :: green , GLColor :: green ) ; setArrayValues ( floatData , arraySize2 , arraySize2 + arraySize1 / 2 , 16 , 0 , 4 , 4 , 0.0f , 1.0f , 0.0f , 1.0f ) ; glBufferSubData ( GL_UNIFORM_BUFFER , floatCount2 * sizeof ( GLfloat ) , ( floatCount1 / 2 - floatCount2 ) * sizeof ( GLfloat ) , & floatData [ 0 ] ) ; drawQuad ( program1 . get ( ) , essl3_shaders :: PositionAttrib ( ) , 0.5f ) ; checkResults ( GLColor :: green , GLColor :: green , GLColor :: blue , GLColor :: blue ) ; }
Test a uniform block with large struct array member and a uniform block with small
struct array member in different programs, but they share the same uniform buffer.
Test a uniform block with large struct array member and a uniform block with small struct array member in different programs but they share the same uniform buffer .