Edit

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

Branch :

  • Show log

    Commit

  • Author : jchen10
    Date : 2017-07-18 16:11:39
    Hash : 05c31dae
    Message : ES31: Enable atomic counter for GL backend This simply translates the offset qualifier and synchronizes the buffer binding state for GL translator and renderer. BUG=angleproject:1729 TEST=angle_end2end_tests:AtomicCounterBufferTest31 Change-Id: Ib8424918478ae4c47049d5856ea20ef022f12913 Reviewed-on: https://chromium-review.googlesource.com/575913 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org>

  • src/tests/gl_tests/AtomicCounterBufferTest.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.
    //
    // AtomicCounterBufferTest:
    //   Various tests related for atomic counter buffers.
    //
    
    #include "test_utils/ANGLETest.h"
    #include "test_utils/gl_raii.h"
    
    using namespace angle;
    
    namespace
    {
    
    class AtomicCounterBufferTest : public ANGLETest
    {
      protected:
        AtomicCounterBufferTest()
        {
            setWindowWidth(128);
            setWindowHeight(128);
            setConfigRedBits(8);
            setConfigGreenBits(8);
            setConfigBlueBits(8);
            setConfigAlphaBits(8);
        }
    };
    
    // Test GL_ATOMIC_COUNTER_BUFFER is not supported with version lower than ES31.
    TEST_P(AtomicCounterBufferTest, AtomicCounterBufferBindings)
    {
        ASSERT_EQ(3, getClientMajorVersion());
        GLBuffer atomicCounterBuffer;
        glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 1, atomicCounterBuffer.get());
        if (getClientMinorVersion() < 1)
        {
            EXPECT_GL_ERROR(GL_INVALID_ENUM);
        }
        else
        {
            EXPECT_GL_NO_ERROR();
        }
    }
    
    class AtomicCounterBufferTest31 : public AtomicCounterBufferTest
    {
    };
    
    // Linking should fail if counters in vertex shader exceed gl_MaxVertexAtomicCounters.
    TEST_P(AtomicCounterBufferTest31, ExceedMaxVertexAtomicCounters)
    {
        const std::string &vertexShaderSource =
            "#version 310 es\n"
            "layout(binding = 2) uniform atomic_uint foo[gl_MaxVertexAtomicCounters + 1];\n"
            "void main()\n"
            "{\n"
            "    atomicCounterIncrement(foo[0]);\n"
            "}\n";
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "void main()\n"
            "{\n"
            "}\n";
    
        GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
        EXPECT_EQ(0u, program);
    }
    
    // Counters matching across shader stages should fail if offsets aren't all specified.
    // GLSL ES Spec 3.10.4, section 9.2.1.
    TEST_P(AtomicCounterBufferTest31, OffsetNotAllSpecified)
    {
        const std::string &vertexShaderSource =
            "#version 310 es\n"
            "layout(binding = 2, offset = 4) uniform atomic_uint foo;\n"
            "void main()\n"
            "{\n"
            "    atomicCounterIncrement(foo);\n"
            "}\n";
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "layout(binding = 2) uniform atomic_uint foo;\n"
            "void main()\n"
            "{\n"
            "}\n";
    
        GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
        EXPECT_EQ(0u, program);
    }
    
    // Counters matching across shader stages should fail if offsets aren't all specified with same
    // value.
    TEST_P(AtomicCounterBufferTest31, OffsetNotAllSpecifiedWithSameValue)
    {
        const std::string &vertexShaderSource =
            "#version 310 es\n"
            "layout(binding = 2, offset = 4) uniform atomic_uint foo;\n"
            "void main()\n"
            "{\n"
            "    atomicCounterIncrement(foo);\n"
            "}\n";
        const std::string &fragmentShaderSource =
            "#version 310 es\n"
            "layout(binding = 2, offset = 8) uniform atomic_uint foo;\n"
            "void main()\n"
            "{\n"
            "}\n";
    
        GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
        EXPECT_EQ(0u, program);
    }
    
    // Test atomic counter read.
    TEST_P(AtomicCounterBufferTest31, AtomicCounterRead)
    {
        const std::string &vertShader =
            "#version 310 es\n"
            "precision highp float;\n"
            "in highp vec4 a_position;\n"
            "void main()\n"
            "{\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 ac;\n"
            "out highp vec4 my_color;\n"
            "void main()\n"
            "{\n"
            "    my_color = vec4(0.0);\n"
            "    uint a1 = atomicCounter(ac);\n"
            "    if (a1 == 3u) my_color = vec4(1.0);\n"
            "}\n";
    
        ANGLE_GL_PROGRAM(program, vertShader, fragShader);
    
        glUseProgram(program.get());
    
        // The initial value of counter 'ac' is 3u.
        unsigned int bufferData[3] = {11u, 3u, 1u};
        GLBuffer atomicCounterBuffer;
        glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
        glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
    
        glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, atomicCounterBuffer);
    
        drawQuad(program.get(), "a_position", 0.0f);
        ASSERT_GL_NO_ERROR();
        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
    }
    
    // Test atomic counter increment and decrement.
    TEST_P(AtomicCounterBufferTest31, AtomicCounterIncrementAndDecrement)
    {
        const std::string &csSource =
            "#version 310 es\n"
            "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
            "layout(binding = 2, offset = 4) uniform atomic_uint ac[2];\n"
            "void main()\n"
            "{\n"
            "    atomicCounterIncrement(ac[0]);\n"
            "    atomicCounterDecrement(ac[1]);\n"
            "}\n";
    
        ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
    
        glUseProgram(program.get());
    
        // The initial value of 'ac[0]' is 3u, 'ac[1]' is 1u.
        unsigned int bufferData[3] = {11u, 3u, 1u};
        GLBuffer atomicCounterBuffer;
        glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
        glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
    
        glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, atomicCounterBuffer);
    
        glDispatchCompute(1, 1, 1);
        EXPECT_GL_NO_ERROR();
    
        glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
        void *mappedBuffer =
            glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
        memcpy(bufferData, mappedBuffer, sizeof(bufferData));
        glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
    
        EXPECT_EQ(11u, bufferData[0]);
        EXPECT_EQ(4u, bufferData[1]);
        EXPECT_EQ(0u, bufferData[2]);
    }
    
    ANGLE_INSTANTIATE_TEST(AtomicCounterBufferTest,
                           ES3_OPENGL(),
                           ES3_OPENGLES(),
                           ES31_OPENGL(),
                           ES31_OPENGLES());
    ANGLE_INSTANTIATE_TEST(AtomicCounterBufferTest31, ES31_OPENGL(), ES31_OPENGLES());
    
    }  // namespace