// // 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 "random_utils.h" #include "shader_utils.h" #include "Vector.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 { 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 indexData; std::vector positionData; std::vector colorData; ASSERT_GE(static_cast(std::numeric_limits::max()), vertexCount); RNG rng(1); for (size_t index = 0; index < vertexCount; ++index) { indexData.push_back(static_cast(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(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(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