1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // DynamicPromotionPerfTest:
7 // Tests that ANGLE will promote buffer specfied with DYNAMIC usage to static after a number of
8 // iterations without changing the data. It specifically affects the D3D back-end, which treats
9 // dynamic and static buffers quite differently.
10 //
11
12 #include "ANGLEPerfTest.h"
13 #include "common/vector_utils.h"
14 #include "util/random_utils.h"
15 #include "util/shader_utils.h"
16
17 using namespace angle;
18
19 namespace
20 {
21 constexpr unsigned int kIterationsPerStep = 4;
22
23 struct DynamicPromotionParams final : public RenderTestParams
24 {
DynamicPromotionParams__anondc1f1dff0111::DynamicPromotionParams25 DynamicPromotionParams() { iterationsPerStep = kIterationsPerStep; }
26
27 std::string story() const override;
28
29 size_t vertexCount = 1024;
30 };
31
story() const32 std::string DynamicPromotionParams::story() const
33 {
34 return RenderTestParams::story();
35 }
36
operator <<(std::ostream & os,const DynamicPromotionParams & params)37 std::ostream &operator<<(std::ostream &os, const DynamicPromotionParams ¶ms)
38 {
39 os << params.backendAndStory().substr(1);
40 return os;
41 }
42
43 class DynamicPromotionPerfTest : public ANGLERenderTest,
44 public testing::WithParamInterface<DynamicPromotionParams>
45 {
46 public:
47 DynamicPromotionPerfTest();
48
49 void initializeBenchmark() override;
50 void destroyBenchmark() override;
51 void drawBenchmark() override;
52
53 private:
54 GLuint mProgram;
55 GLuint mElementArrayBuffer;
56 GLuint mArrayBuffer;
57 };
58
DynamicPromotionPerfTest()59 DynamicPromotionPerfTest::DynamicPromotionPerfTest()
60 : ANGLERenderTest("DynamicPromotion", GetParam()),
61 mProgram(0),
62 mElementArrayBuffer(0),
63 mArrayBuffer(0)
64 {}
65
initializeBenchmark()66 void DynamicPromotionPerfTest::initializeBenchmark()
67 {
68 constexpr char kVertexShaderSource[] =
69 "attribute vec2 position;\n"
70 "attribute vec3 color;\n"
71 "varying vec3 vColor;\n"
72 "void main()\n"
73 "{\n"
74 " vColor = color;\n"
75 " gl_Position = vec4(position, 0, 1);\n"
76 "}";
77
78 constexpr char kFragmentShaderSource[] =
79 "varying mediump vec3 vColor;\n"
80 "void main()\n"
81 "{\n"
82 " gl_FragColor = vec4(vColor, 1);\n"
83 "}";
84
85 mProgram = CompileProgram(kVertexShaderSource, kFragmentShaderSource);
86 ASSERT_NE(0u, mProgram);
87
88 const size_t vertexCount = GetParam().vertexCount;
89
90 std::vector<GLushort> indexData;
91 std::vector<Vector2> positionData;
92 std::vector<Vector3> colorData;
93
94 ASSERT_GE(static_cast<size_t>(std::numeric_limits<GLushort>::max()), vertexCount);
95
96 RNG rng(1);
97
98 for (size_t index = 0; index < vertexCount; ++index)
99 {
100 indexData.push_back(static_cast<GLushort>(index));
101
102 Vector2 position(rng.randomNegativeOneToOne(), rng.randomNegativeOneToOne());
103 positionData.push_back(position);
104
105 Vector3 color(rng.randomFloat(), rng.randomFloat(), rng.randomFloat());
106 colorData.push_back(color);
107 }
108
109 glGenBuffers(1, &mElementArrayBuffer);
110 glGenBuffers(1, &mArrayBuffer);
111
112 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementArrayBuffer);
113 glBindBuffer(GL_ARRAY_BUFFER, mArrayBuffer);
114
115 GLsizeiptr elementArraySize = sizeof(GLushort) * vertexCount;
116 GLsizeiptr positionArraySize = sizeof(Vector2) * vertexCount;
117 GLsizeiptr colorArraySize = sizeof(Vector3) * vertexCount;
118
119 // The DYNAMIC_DRAW usage is the key to the test.
120 glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementArraySize, indexData.data(), GL_DYNAMIC_DRAW);
121 glBufferData(GL_ARRAY_BUFFER, positionArraySize + colorArraySize, nullptr, GL_DYNAMIC_DRAW);
122 glBufferSubData(GL_ARRAY_BUFFER, 0, positionArraySize, positionData.data());
123 glBufferSubData(GL_ARRAY_BUFFER, positionArraySize, colorArraySize, colorData.data());
124
125 glUseProgram(mProgram);
126 GLint positionLocation = glGetAttribLocation(mProgram, "position");
127 ASSERT_NE(-1, positionLocation);
128 GLint colorLocation = glGetAttribLocation(mProgram, "color");
129 ASSERT_NE(-1, colorLocation);
130
131 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
132 glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 0,
133 reinterpret_cast<const void *>(positionArraySize));
134
135 glEnableVertexAttribArray(positionLocation);
136 glEnableVertexAttribArray(colorLocation);
137
138 ASSERT_GL_NO_ERROR();
139 }
140
destroyBenchmark()141 void DynamicPromotionPerfTest::destroyBenchmark()
142 {
143 glDeleteProgram(mProgram);
144 glDeleteBuffers(1, &mElementArrayBuffer);
145 glDeleteBuffers(1, &mArrayBuffer);
146 }
147
drawBenchmark()148 void DynamicPromotionPerfTest::drawBenchmark()
149 {
150 unsigned int iterations = GetParam().iterationsPerStep;
151 size_t vertexCount = GetParam().vertexCount;
152
153 glClear(GL_COLOR_BUFFER_BIT);
154 for (unsigned int count = 0; count < iterations; ++count)
155 {
156 glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(vertexCount), GL_UNSIGNED_SHORT, nullptr);
157 }
158
159 ASSERT_GL_NO_ERROR();
160 }
161
DynamicPromotionD3D11Params()162 DynamicPromotionParams DynamicPromotionD3D11Params()
163 {
164 DynamicPromotionParams params;
165 params.eglParameters = egl_platform::D3D11();
166 return params;
167 }
168
TEST_P(DynamicPromotionPerfTest,Run)169 TEST_P(DynamicPromotionPerfTest, Run)
170 {
171 run();
172 }
173
174 ANGLE_INSTANTIATE_TEST(DynamicPromotionPerfTest, DynamicPromotionD3D11Params());
175
176 // This test suite is not instantiated on some OSes.
177 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DynamicPromotionPerfTest);
178
179 } // anonymous namespace
180