Edit

kc3-lang/angle/src/tests/perf_tests/BufferSubData.cpp

Branch :

  • Show log

    Commit

  • Author : Yuly Novikov
    Date : 2017-10-27 18:14:14
    Hash : b8d2664f
    Message : Run angle_perftests on GLES backend Adds OPENGLES_NULL configuration and selects between OPENGL and OPENGLES based on whether building for Android. Also 2 small changes to get the newly enabled tests to pass on N5X: 1. Require GL_EXT_texture_storage in TexSubImage test 2. Limit numVertexUniforms and numFragmentUniforms to 64 in MatrixUniforms test BUG=675997 Change-Id: I5439e5fb7e93b3a928f12594761115d56f60d81b Reviewed-on: https://chromium-review.googlesource.com/748522 Commit-Queue: Yuly Novikov <ynovikov@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/tests/perf_tests/BufferSubData.cpp
  • //
    // Copyright (c) 2014 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.
    //
    // BufferSubDataBenchmark:
    //   Performance test for ANGLE buffer updates.
    //
    
    #include <sstream>
    
    #include "ANGLEPerfTest.h"
    #include "test_utils/draw_call_perf_utils.h"
    
    using namespace angle;
    
    namespace
    {
    
    struct BufferSubDataParams final : public RenderTestParams
    {
        BufferSubDataParams()
        {
            // Common default values
            majorVersion = 2;
            minorVersion = 0;
            windowWidth = 512;
            windowHeight = 512;
            updateSize = 3000;
            bufferSize = 40000000;
            iterations   = 4;
            updateRate = 1;
        }
    
        std::string suffix() const override;
    
        GLboolean vertexNormalized;
        GLenum vertexType;
        GLint vertexComponentCount;
        unsigned int updateRate;
    
        // static parameters
        GLsizeiptr updateSize;
        GLsizeiptr bufferSize;
        unsigned int iterations;
    };
    
    std::ostream &operator<<(std::ostream &os, const BufferSubDataParams &params)
    {
        os << params.suffix().substr(1);
        return os;
    }
    
    class BufferSubDataBenchmark : public ANGLERenderTest,
                                   public ::testing::WithParamInterface<BufferSubDataParams>
    {
      public:
        BufferSubDataBenchmark();
    
        void initializeBenchmark() override;
        void destroyBenchmark() override;
        void drawBenchmark() override;
    
      private:
        GLuint mProgram;
        GLuint mBuffer;
        uint8_t *mUpdateData;
        int mNumTris;
    };
    
    GLfloat *GetFloatData(GLint componentCount)
    {
        static GLfloat vertices2[] =
        {
            1, 2,
            0, 0,
            2, 0,
        };
    
        static GLfloat vertices3[] =
        {
            1, 2, 1,
            0, 0, 1,
            2, 0, 1,
        };
    
        static GLfloat vertices4[] =
        {
            1, 2, 1, 3,
            0, 0, 1, 3,
            2, 0, 1, 3,
        };
    
        switch (componentCount)
        {
            case 2:
                return vertices2;
            case 3:
                return vertices3;
            case 4:
                return vertices4;
            default:
                return nullptr;
        }
    }
    
    template <class T>
    GLsizeiptr GetNormalizedData(GLsizeiptr numElements, GLfloat *floatData, std::vector<uint8_t> *data)
    {
        GLsizeiptr triDataSize = sizeof(T) * numElements;
        data->resize(triDataSize);
    
        T *destPtr = reinterpret_cast<T*>(data->data());
    
        for (GLsizeiptr dataIndex = 0; dataIndex < numElements; dataIndex++)
        {
            GLfloat scaled = floatData[dataIndex] * 0.25f;
            destPtr[dataIndex] = static_cast<T>(scaled * static_cast<GLfloat>(std::numeric_limits<T>::max()));
        }
    
        return triDataSize;
    }
    
    template <class T>
    GLsizeiptr GetIntData(GLsizeiptr numElements, GLfloat *floatData, std::vector<uint8_t> *data)
    {
        GLsizeiptr triDataSize = sizeof(T) * numElements;
        data->resize(triDataSize);
    
        T *destPtr = reinterpret_cast<T*>(data->data());
    
        for (GLsizeiptr dataIndex = 0; dataIndex < numElements; dataIndex++)
        {
            destPtr[dataIndex] = static_cast<T>(floatData[dataIndex]);
        }
    
        return triDataSize;
    }
    
    GLsizeiptr GetVertexData(GLenum type, GLint componentCount, GLboolean normalized, std::vector<uint8_t> *data)
    {
        GLsizeiptr triDataSize = 0;
        GLfloat *floatData = GetFloatData(componentCount);
    
        if (type == GL_FLOAT)
        {
            triDataSize = sizeof(GLfloat) * componentCount * 3;
            data->resize(triDataSize);
            memcpy(data->data(), floatData, triDataSize);
        }
        else if (normalized == GL_TRUE)
        {
            GLsizeiptr numElements = componentCount * 3;
    
            switch (type)
            {
                case GL_BYTE:
                    triDataSize = GetNormalizedData<GLbyte>(numElements, floatData, data);
                    break;
                case GL_SHORT:
                    triDataSize = GetNormalizedData<GLshort>(numElements, floatData, data);
                    break;
                case GL_INT:
                    triDataSize = GetNormalizedData<GLint>(numElements, floatData, data);
                    break;
                case GL_UNSIGNED_BYTE:
                    triDataSize = GetNormalizedData<GLubyte>(numElements, floatData, data);
                    break;
                case GL_UNSIGNED_SHORT:
                    triDataSize = GetNormalizedData<GLushort>(numElements, floatData, data);
                    break;
                case GL_UNSIGNED_INT:
                    triDataSize = GetNormalizedData<GLuint>(numElements, floatData, data);
                    break;
                default:
                    assert(0);
            }
        }
        else
        {
            GLsizeiptr numElements = componentCount * 3;
    
            switch (type)
            {
                case GL_BYTE:
                    triDataSize = GetIntData<GLbyte>(numElements, floatData, data);
                    break;
                case GL_SHORT:
                    triDataSize = GetIntData<GLshort>(numElements, floatData, data);
                    break;
                case GL_INT:
                    triDataSize = GetIntData<GLint>(numElements, floatData, data);
                    break;
                case GL_UNSIGNED_BYTE:
                    triDataSize = GetIntData<GLubyte>(numElements, floatData, data);
                    break;
                case GL_UNSIGNED_SHORT:
                    triDataSize = GetIntData<GLushort>(numElements, floatData, data);
                    break;
                case GL_UNSIGNED_INT:
                    triDataSize = GetIntData<GLuint>(numElements, floatData, data);
                    break;
                default:
                    assert(0);
            }
        }
    
        return triDataSize;
    }
    
    std::string BufferSubDataParams::suffix() const
    {
        std::stringstream strstr;
    
        strstr << RenderTestParams::suffix();
    
        if (vertexNormalized)
        {
            strstr << "_norm";
        }
    
        switch (vertexType)
        {
            case GL_FLOAT:
                strstr << "_float";
                break;
            case GL_INT:
                strstr << "_int";
                break;
            case GL_BYTE:
                strstr << "_byte";
                break;
            case GL_SHORT:
                strstr << "_short";
                break;
            case GL_UNSIGNED_INT:
                strstr << "_uint";
                break;
            case GL_UNSIGNED_BYTE:
                strstr << "_ubyte";
                break;
            case GL_UNSIGNED_SHORT:
                strstr << "_ushort";
                break;
            default:
                strstr << "_vunk_" << vertexType << "_";
                break;
        }
    
        strstr << vertexComponentCount;
        strstr << "_every" << updateRate;
    
        return strstr.str();
    }
    
    BufferSubDataBenchmark::BufferSubDataBenchmark()
        : ANGLERenderTest("BufferSubData", GetParam()),
          mProgram(0),
          mBuffer(0),
          mUpdateData(nullptr),
          mNumTris(0)
    {
    }
    
    void BufferSubDataBenchmark::initializeBenchmark()
    {
        const auto &params = GetParam();
    
        ASSERT_LT(1, params.vertexComponentCount);
        ASSERT_LT(0u, params.iterations);
    
        mProgram = SetupSimpleScaleAndOffsetProgram();
        ASSERT_NE(0u, mProgram);
    
        if (params.vertexNormalized == GL_TRUE)
        {
            GLfloat scale  = 2.0f;
            GLfloat offset = -0.5f;
            glUniform1f(glGetUniformLocation(mProgram, "uScale"), scale);
            glUniform1f(glGetUniformLocation(mProgram, "uOffset"), offset);
        }
    
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    
        std::vector<uint8_t> zeroData(params.bufferSize);
        memset(&zeroData[0], 0, zeroData.size());
    
        glGenBuffers(1, &mBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
        glBufferData(GL_ARRAY_BUFFER, params.bufferSize, &zeroData[0], GL_DYNAMIC_DRAW);
    
        glVertexAttribPointer(0, params.vertexComponentCount, params.vertexType,
                              params.vertexNormalized, 0, 0);
        glEnableVertexAttribArray(0);
    
        if (params.updateSize > 0)
        {
            mUpdateData = new uint8_t[params.updateSize];
        }
    
        std::vector<uint8_t> data;
        GLsizei triDataSize = static_cast<GLsizei>(GetVertexData(params.vertexType,
                                                                 params.vertexComponentCount,
                                                                 params.vertexNormalized, &data));
    
        mNumTris = static_cast<int>(params.updateSize / triDataSize);
        for (int i = 0, offset = 0; i < mNumTris; ++i)
        {
            memcpy(mUpdateData + offset, &data[0], triDataSize);
            offset += triDataSize;
        }
    
        if (params.updateSize == 0)
        {
            mNumTris = 1;
            glBufferSubData(GL_ARRAY_BUFFER, 0, data.size(), &data[0]);
        }
    
        // Set the viewport
        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
    
        ASSERT_GL_NO_ERROR();
    }
    
    void BufferSubDataBenchmark::destroyBenchmark()
    {
        glDeleteProgram(mProgram);
        glDeleteBuffers(1, &mBuffer);
        SafeDeleteArray(mUpdateData);
    }
    
    void BufferSubDataBenchmark::drawBenchmark()
    {
        glClear(GL_COLOR_BUFFER_BIT);
    
        const auto &params = GetParam();
    
        for (unsigned int it = 0; it < params.iterations; it++)
        {
            if (params.updateSize > 0 && ((getNumStepsPerformed() % params.updateRate) == 0))
            {
                glBufferSubData(GL_ARRAY_BUFFER, 0, params.updateSize, mUpdateData);
            }
    
            glDrawArrays(GL_TRIANGLES, 0, 3 * mNumTris);
        }
    
        ASSERT_GL_NO_ERROR();
    }
    
    BufferSubDataParams BufferUpdateD3D11Params()
    {
        BufferSubDataParams params;
        params.eglParameters = egl_platform::D3D11();
        params.vertexType = GL_FLOAT;
        params.vertexComponentCount = 4;
        params.vertexNormalized = GL_FALSE;
        return params;
    }
    
    BufferSubDataParams BufferUpdateD3D9Params()
    {
        BufferSubDataParams params;
        params.eglParameters = egl_platform::D3D9();
        params.vertexType = GL_FLOAT;
        params.vertexComponentCount = 4;
        params.vertexNormalized = GL_FALSE;
        return params;
    }
    
    BufferSubDataParams BufferUpdateOpenGLOrGLESParams()
    {
        BufferSubDataParams params;
        params.eglParameters        = egl_platform::OPENGL_OR_GLES(false);
        params.vertexType = GL_FLOAT;
        params.vertexComponentCount = 4;
        params.vertexNormalized = GL_FALSE;
        return params;
    }
    
    TEST_P(BufferSubDataBenchmark, Run)
    {
        run();
    }
    
    ANGLE_INSTANTIATE_TEST(BufferSubDataBenchmark,
                           BufferUpdateD3D11Params(),
                           BufferUpdateD3D9Params(),
                           BufferUpdateOpenGLOrGLESParams());
    
    } // namespace