xref: /aosp_15_r20/external/angle/src/tests/perf_tests/VertexArrayPerfTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2021 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 // VertexArrayPerfTest:
7 //   Performance test for glBindVertexArray.
8 //
9 
10 #include "ANGLEPerfTest.h"
11 #include "DrawCallPerfParams.h"
12 #include "test_utils/gl_raii.h"
13 
14 using namespace angle;
15 
16 namespace
17 {
18 enum class TestMode
19 {
20     BufferData,
21     BindBuffer,
22     UpdateBufferData,
23 };
24 
25 struct VertexArrayParams final : public RenderTestParams
26 {
VertexArrayParams__anon5ac9623f0111::VertexArrayParams27     VertexArrayParams()
28     {
29         iterationsPerStep = 1;
30 
31         // Common default params
32         majorVersion = 3;
33         minorVersion = 0;
34         windowWidth  = 720;
35         windowHeight = 720;
36     }
37 
38     std::string story() const override;
39 
40     int numVertexArrays  = 2000;
41     int numBuffers       = 5;
42     GLuint bufferSize[5] = {384, 1028, 192, 384, 192};
43     TestMode testMode    = TestMode::BufferData;
44 };
45 
operator <<(std::ostream & os,const VertexArrayParams & params)46 std::ostream &operator<<(std::ostream &os, const VertexArrayParams &params)
47 {
48     os << params.backendAndStory().substr(1);
49     return os;
50 }
51 
story() const52 std::string VertexArrayParams::story() const
53 {
54     std::stringstream strstr;
55 
56     strstr << RenderTestParams::story();
57 
58     if (testMode == TestMode::BindBuffer)
59     {
60         strstr << "_bindbuffer";
61     }
62     else if (testMode == TestMode::UpdateBufferData)
63     {
64         strstr << "_updatebufferdata";
65     }
66 
67     return strstr.str();
68 }
69 
70 class VertexArrayBenchmark : public ANGLERenderTest,
71                              public ::testing::WithParamInterface<VertexArrayParams>
72 {
73   public:
74     VertexArrayBenchmark();
75 
76     void initializeBenchmark() override;
77     void destroyBenchmark() override;
78     void drawBenchmark() override;
79 
80     void rebindVertexArray(GLuint vertexArrayID, GLuint bufferID);
81     void updateBufferData(GLuint vertexArrayID, GLuint bufferID, GLuint bufferSize);
82 
83   private:
84     std::vector<GLuint> mBuffers;
85     GLuint mProgram       = 0;
86     GLint mAttribLocation = 0;
87     std::vector<GLuint> mVertexArrays;
88 };
89 
VertexArrayBenchmark()90 VertexArrayBenchmark::VertexArrayBenchmark() : ANGLERenderTest("VertexArrayPerf", GetParam()) {}
91 
initializeBenchmark()92 void VertexArrayBenchmark::initializeBenchmark()
93 {
94     constexpr char kVS[] = R"(attribute vec4 position;
95 attribute float in_attrib;
96 varying float v_attrib;
97 void main()
98 {
99     v_attrib = in_attrib;
100     gl_Position = position;
101 })";
102 
103     constexpr char kFS[] = R"(precision mediump float;
104 varying float v_attrib;
105 void main()
106 {
107     gl_FragColor = vec4(v_attrib, 0, 0, 1);
108 })";
109 
110     mProgram = CompileProgram(kVS, kFS);
111     ASSERT_NE(0u, mProgram);
112 
113     mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
114     ASSERT_NE(mAttribLocation, -1);
115 
116     // Generate 5 buffers.
117     int numBuffers = GetParam().numBuffers;
118     mBuffers.resize(numBuffers, 0);
119     glGenBuffers(numBuffers, mBuffers.data());
120 
121     int numVertexArrays = GetParam().numVertexArrays;
122     mVertexArrays.resize(numVertexArrays, 0);
123     glGenVertexArrays(numVertexArrays, mVertexArrays.data());
124 
125     // Bind one VBO to all VAOs.
126     for (GLuint vertexArray : mVertexArrays)
127     {
128         rebindVertexArray(vertexArray, mBuffers[0]);
129     }
130 
131     glBindVertexArray(0);
132     glBindBuffer(GL_ARRAY_BUFFER, mBuffers[0]);
133 }
134 
rebindVertexArray(GLuint vertexArrayID,GLuint bufferID)135 void VertexArrayBenchmark::rebindVertexArray(GLuint vertexArrayID, GLuint bufferID)
136 {
137     // Rebind a vertex array object and a generic vertex attribute inside of it.
138     glBindVertexArray(vertexArrayID);
139     glBindBuffer(GL_ARRAY_BUFFER, bufferID);
140     glEnableVertexAttribArray(mAttribLocation);
141     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
142     glVertexAttribDivisor(mAttribLocation, 1);
143     glBindVertexArray(0);
144     glBindBuffer(GL_ARRAY_BUFFER, 0);
145 }
146 
updateBufferData(GLuint vertexArrayID,GLuint bufferID,GLuint bufferSize)147 void VertexArrayBenchmark::updateBufferData(GLuint vertexArrayID,
148                                             GLuint bufferID,
149                                             GLuint bufferSize)
150 {
151     glBindVertexArray(vertexArrayID);
152     glBindBuffer(GL_ARRAY_BUFFER, bufferID);
153     glEnableVertexAttribArray(mAttribLocation);
154     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
155     glBufferData(GL_ARRAY_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
156     glBindVertexArray(0);
157     glBindBuffer(GL_ARRAY_BUFFER, 0);
158 }
159 
destroyBenchmark()160 void VertexArrayBenchmark::destroyBenchmark()
161 {
162     glDeleteProgram(mProgram);
163     glDeleteVertexArrays(static_cast<GLsizei>(mVertexArrays.size()), mVertexArrays.data());
164     mVertexArrays.clear();
165     glDeleteBuffers(static_cast<GLsizei>(mBuffers.size()), mBuffers.data());
166     mBuffers.clear();
167 }
168 
drawBenchmark()169 void VertexArrayBenchmark::drawBenchmark()
170 {
171     const VertexArrayParams &params = GetParam();
172     if (params.testMode == TestMode::BufferData)
173     {
174         glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_STATIC_DRAW);
175     }
176     else if (params.testMode == TestMode::UpdateBufferData)
177     {
178         int bufferSizeIndex = 0;
179         for (GLuint vertexArray : mVertexArrays)
180         {
181             bufferSizeIndex = ((bufferSizeIndex + 1) == 5) ? 0 : (bufferSizeIndex + 1);
182             updateBufferData(vertexArray, mBuffers[0], params.bufferSize[bufferSizeIndex]);
183         }
184     }
185     else
186     {
187         int bufferIndex = 0;
188         for (GLuint vertexArray : mVertexArrays)
189         {
190             bufferIndex = ((bufferIndex + 1) == params.numBuffers) ? 0 : (bufferIndex + 1);
191             rebindVertexArray(vertexArray, mBuffers[bufferIndex]);
192         }
193     }
194 }
195 
TEST_P(VertexArrayBenchmark,Run)196 TEST_P(VertexArrayBenchmark, Run)
197 {
198     run();
199 }
200 
MetalParams()201 VertexArrayParams MetalParams()
202 {
203     VertexArrayParams params;
204     params.eglParameters = egl_platform::METAL();
205     return params;
206 }
207 
VulkanParams()208 VertexArrayParams VulkanParams()
209 {
210     VertexArrayParams params;
211     params.eglParameters = egl_platform::VULKAN();
212     return params;
213 }
214 
VulkanNullParams(TestMode testMode)215 VertexArrayParams VulkanNullParams(TestMode testMode)
216 {
217     VertexArrayParams params;
218     params.eglParameters = egl_platform::VULKAN_NULL();
219     params.testMode      = testMode;
220     return params;
221 }
222 
223 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexArrayBenchmark);
224 ANGLE_INSTANTIATE_TEST(VertexArrayBenchmark,
225                        MetalParams(),
226                        VulkanParams(),
227                        VulkanNullParams(TestMode::BindBuffer),
228                        VulkanNullParams(TestMode::BufferData),
229                        VulkanNullParams(TestMode::UpdateBufferData),
230                        params::Native(VertexArrayParams()));
231 }  // namespace
232