diff options
Diffstat (limited to 'gfx/angle/src/tests/perf_tests/BufferSubData.cpp')
-rwxr-xr-x | gfx/angle/src/tests/perf_tests/BufferSubData.cpp | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/gfx/angle/src/tests/perf_tests/BufferSubData.cpp b/gfx/angle/src/tests/perf_tests/BufferSubData.cpp new file mode 100755 index 000000000..5818d52ee --- /dev/null +++ b/gfx/angle/src/tests/perf_tests/BufferSubData.cpp @@ -0,0 +1,418 @@ +// +// 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 "shader_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 ¶ms) +{ + 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 ¶ms = GetParam(); + + ASSERT_LT(1, params.vertexComponentCount); + ASSERT_LT(0u, params.iterations); + + const std::string vs = SHADER_SOURCE + ( + attribute vec2 vPosition; + uniform float uScale; + uniform float uOffset; + void main() + { + gl_Position = vec4(vPosition * vec2(uScale) - vec2(uOffset), 0, 1); + } + ); + + const std::string fs = SHADER_SOURCE + ( + precision mediump float; + void main() + { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + ); + + mProgram = CompileProgram(vs, fs); + ASSERT_NE(0u, mProgram); + + // Use the program object + glUseProgram(mProgram); + + 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()); + + GLfloat scale = 0.5f; + GLfloat offset = 0.5f; + + if (params.vertexNormalized == GL_TRUE) + { + scale = 2.0f; + offset = 0.5f; + } + + glUniform1f(glGetUniformLocation(mProgram, "uScale"), scale); + glUniform1f(glGetUniformLocation(mProgram, "uOffset"), offset); + + ASSERT_GL_NO_ERROR(); +} + +void BufferSubDataBenchmark::destroyBenchmark() +{ + glDeleteProgram(mProgram); + glDeleteBuffers(1, &mBuffer); + SafeDeleteArray(mUpdateData); +} + +void BufferSubDataBenchmark::drawBenchmark() +{ + glClear(GL_COLOR_BUFFER_BIT); + + const auto ¶ms = 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 BufferUpdateOpenGLParams() +{ + BufferSubDataParams params; + params.eglParameters = egl_platform::OPENGL(); + params.vertexType = GL_FLOAT; + params.vertexComponentCount = 4; + params.vertexNormalized = GL_FALSE; + return params; +} + +TEST_P(BufferSubDataBenchmark, Run) +{ + run(); +} + +ANGLE_INSTANTIATE_TEST(BufferSubDataBenchmark, + BufferUpdateD3D11Params(), BufferUpdateD3D9Params(), + BufferUpdateOpenGLParams()); + +} // namespace |