| // |
| // Copyright 2016 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. |
| // |
| // DynamicPromotionPerfTest: |
| // Tests that ANGLE will promote buffer specfied with DYNAMIC usage to static after a number of |
| // iterations without changing the data. It specifically affects the D3D back-end, which treats |
| // dynamic and static buffers quite differently. |
| // |
| |
| #include "ANGLEPerfTest.h" |
| #include "common/vector_utils.h" |
| #include "random_utils.h" |
| #include "shader_utils.h" |
| |
| using namespace angle; |
| |
| namespace |
| { |
| |
| struct DynamicPromotionParams final : public RenderTestParams |
| { |
| DynamicPromotionParams(); |
| std::string suffix() const override; |
| |
| size_t vertexCount; |
| unsigned int iterations; |
| }; |
| |
| DynamicPromotionParams::DynamicPromotionParams() : vertexCount(1024), iterations(4) |
| { |
| } |
| |
| std::string DynamicPromotionParams::suffix() const |
| { |
| return RenderTestParams::suffix(); |
| } |
| |
| std::ostream &operator<<(std::ostream &os, const DynamicPromotionParams ¶ms) |
| { |
| os << params.suffix().substr(1); |
| return os; |
| } |
| |
| class DynamicPromotionPerfTest : public ANGLERenderTest, |
| public testing::WithParamInterface<DynamicPromotionParams> |
| { |
| public: |
| DynamicPromotionPerfTest(); |
| |
| void initializeBenchmark() override; |
| void destroyBenchmark() override; |
| void drawBenchmark() override; |
| |
| private: |
| GLuint mProgram; |
| GLuint mElementArrayBuffer; |
| GLuint mArrayBuffer; |
| }; |
| |
| DynamicPromotionPerfTest::DynamicPromotionPerfTest() |
| : ANGLERenderTest("DynamicPromotion", GetParam()), |
| mProgram(0), |
| mElementArrayBuffer(0), |
| mArrayBuffer(0) |
| { |
| } |
| |
| void DynamicPromotionPerfTest::initializeBenchmark() |
| { |
| const std::string &vertexShaderSource = |
| "attribute vec2 position;\n" |
| "attribute vec3 color;\n" |
| "varying vec3 vColor;\n" |
| "void main()\n" |
| "{\n" |
| " vColor = color;\n" |
| " gl_Position = vec4(position, 0, 1);\n" |
| "}"; |
| |
| const std::string &fragmentShaderSource = |
| "varying mediump vec3 vColor;\n" |
| "void main()\n" |
| "{\n" |
| " gl_FragColor = vec4(vColor, 1);\n" |
| "}"; |
| |
| mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource); |
| ASSERT_NE(0u, mProgram); |
| |
| const size_t vertexCount = GetParam().vertexCount; |
| |
| std::vector<GLushort> indexData; |
| std::vector<Vector2> positionData; |
| std::vector<Vector3> colorData; |
| |
| ASSERT_GE(static_cast<size_t>(std::numeric_limits<GLushort>::max()), vertexCount); |
| |
| RNG rng(1); |
| |
| for (size_t index = 0; index < vertexCount; ++index) |
| { |
| indexData.push_back(static_cast<GLushort>(index)); |
| |
| Vector2 position(rng.randomNegativeOneToOne(), rng.randomNegativeOneToOne()); |
| positionData.push_back(position); |
| |
| Vector3 color(rng.randomFloat(), rng.randomFloat(), rng.randomFloat()); |
| colorData.push_back(color); |
| } |
| |
| glGenBuffers(1, &mElementArrayBuffer); |
| glGenBuffers(1, &mArrayBuffer); |
| |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementArrayBuffer); |
| glBindBuffer(GL_ARRAY_BUFFER, mArrayBuffer); |
| |
| GLsizeiptr elementArraySize = sizeof(GLushort) * vertexCount; |
| GLsizeiptr positionArraySize = sizeof(Vector2) * vertexCount; |
| GLsizeiptr colorArraySize = sizeof(Vector3) * vertexCount; |
| |
| // The DYNAMIC_DRAW usage is the key to the test. |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementArraySize, indexData.data(), GL_DYNAMIC_DRAW); |
| glBufferData(GL_ARRAY_BUFFER, positionArraySize + colorArraySize, nullptr, GL_DYNAMIC_DRAW); |
| glBufferSubData(GL_ARRAY_BUFFER, 0, positionArraySize, positionData.data()); |
| glBufferSubData(GL_ARRAY_BUFFER, positionArraySize, colorArraySize, colorData.data()); |
| |
| glUseProgram(mProgram); |
| GLint positionLocation = glGetAttribLocation(mProgram, "position"); |
| ASSERT_NE(-1, positionLocation); |
| GLint colorLocation = glGetAttribLocation(mProgram, "color"); |
| ASSERT_NE(-1, colorLocation); |
| |
| glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr); |
| glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 0, |
| reinterpret_cast<const void *>(positionArraySize)); |
| |
| glEnableVertexAttribArray(positionLocation); |
| glEnableVertexAttribArray(colorLocation); |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| void DynamicPromotionPerfTest::destroyBenchmark() |
| { |
| glDeleteProgram(mProgram); |
| glDeleteBuffers(1, &mElementArrayBuffer); |
| glDeleteBuffers(1, &mArrayBuffer); |
| } |
| |
| void DynamicPromotionPerfTest::drawBenchmark() |
| { |
| unsigned int iterations = GetParam().iterations; |
| size_t vertexCount = GetParam().vertexCount; |
| |
| glClear(GL_COLOR_BUFFER_BIT); |
| for (unsigned int count = 0; count < iterations; ++count) |
| { |
| glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(vertexCount), GL_UNSIGNED_SHORT, nullptr); |
| } |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| DynamicPromotionParams DynamicPromotionD3D11Params() |
| { |
| DynamicPromotionParams params; |
| params.eglParameters = egl_platform::D3D11(); |
| return params; |
| } |
| |
| DynamicPromotionParams DynamicPromotionD3D9Params() |
| { |
| DynamicPromotionParams params; |
| params.eglParameters = egl_platform::D3D9(); |
| return params; |
| } |
| |
| TEST_P(DynamicPromotionPerfTest, Run) |
| { |
| run(); |
| } |
| |
| ANGLE_INSTANTIATE_TEST(DynamicPromotionPerfTest, |
| DynamicPromotionD3D11Params(), |
| DynamicPromotionD3D9Params()); |
| |
| } // anonymous namespace |