1 //
2 // Copyright 2014 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 // InterleavedAttributeData:
7 // Performance test for draws using interleaved attribute data in vertex buffers.
8 //
9
10 #include <sstream>
11
12 #include "ANGLEPerfTest.h"
13 #include "util/shader_utils.h"
14
15 using namespace angle;
16
17 namespace
18 {
19
20 struct InterleavedAttributeDataParams final : public RenderTestParams
21 {
InterleavedAttributeDataParams__anon69ff6b160111::InterleavedAttributeDataParams22 InterleavedAttributeDataParams()
23 {
24 iterationsPerStep = 1;
25
26 // Common default values
27 majorVersion = 2;
28 minorVersion = 0;
29 windowWidth = 512;
30 windowHeight = 512;
31 numSprites = 3000;
32 }
33
34 // static parameters
35 unsigned int numSprites;
36 };
37
operator <<(std::ostream & os,const InterleavedAttributeDataParams & params)38 std::ostream &operator<<(std::ostream &os, const InterleavedAttributeDataParams ¶ms)
39 {
40 os << params.backendAndStory().substr(1);
41
42 if (params.eglParameters.majorVersion != EGL_DONT_CARE)
43 {
44 os << "_" << params.eglParameters.majorVersion << "_" << params.eglParameters.minorVersion;
45 }
46
47 return os;
48 }
49
50 class InterleavedAttributeDataBenchmark
51 : public ANGLERenderTest,
52 public ::testing::WithParamInterface<InterleavedAttributeDataParams>
53 {
54 public:
55 InterleavedAttributeDataBenchmark();
56
57 void initializeBenchmark() override;
58 void destroyBenchmark() override;
59 void drawBenchmark() override;
60
61 private:
62 GLuint mPointSpriteProgram;
63 GLuint mPositionColorBuffer[2];
64
65 // The buffers contain two floats and 3 unsigned bytes per point sprite
66 // Has to be aligned for float access on arm
67 const size_t mBytesPerSpriteUnaligned = 2 * sizeof(float) + 3;
68 const size_t mBytesPerSprite =
69 ((mBytesPerSpriteUnaligned + sizeof(float) - 1) / sizeof(float)) * sizeof(float);
70 };
71
InterleavedAttributeDataBenchmark()72 InterleavedAttributeDataBenchmark::InterleavedAttributeDataBenchmark()
73 : ANGLERenderTest("InterleavedAttributeData", GetParam()), mPointSpriteProgram(0)
74 {
75 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
76 {
77 skipTest("http://crbug.com/921004 Timing out on Intel");
78 }
79 }
80
initializeBenchmark()81 void InterleavedAttributeDataBenchmark::initializeBenchmark()
82 {
83 const auto ¶ms = GetParam();
84
85 // Compile point sprite shaders
86 constexpr char kVS[] =
87 "attribute vec4 aPosition;"
88 "attribute vec4 aColor;"
89 "varying vec4 vColor;"
90 "void main()"
91 "{"
92 " gl_PointSize = 25.0;"
93 " gl_Position = aPosition;"
94 " vColor = aColor;"
95 "}";
96
97 constexpr char kFS[] =
98 "precision mediump float;"
99 "varying vec4 vColor;"
100 "void main()"
101 "{"
102 " gl_FragColor = vColor;"
103 "}";
104
105 mPointSpriteProgram = CompileProgram(kVS, kFS);
106 ASSERT_NE(0u, mPointSpriteProgram);
107
108 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
109
110 for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
111 {
112 // Set up initial data for pointsprite positions and colors
113 std::vector<uint8_t> positionColorData(mBytesPerSprite * params.numSprites);
114 for (unsigned int j = 0; j < params.numSprites; j++)
115 {
116 float pointSpriteX =
117 (static_cast<float>(rand() % getWindow()->getWidth()) / getWindow()->getWidth()) *
118 2.0f -
119 1.0f;
120 float pointSpriteY =
121 (static_cast<float>(rand() % getWindow()->getHeight()) / getWindow()->getHeight()) *
122 2.0f -
123 1.0f;
124 GLubyte pointSpriteRed = static_cast<GLubyte>(rand() % 255);
125 GLubyte pointSpriteGreen = static_cast<GLubyte>(rand() % 255);
126 GLubyte pointSpriteBlue = static_cast<GLubyte>(rand() % 255);
127
128 // Add position data for the pointsprite
129 *reinterpret_cast<float *>(
130 &(positionColorData[j * mBytesPerSprite + 0 * sizeof(float) + 0])) =
131 pointSpriteX; // X
132 *reinterpret_cast<float *>(
133 &(positionColorData[j * mBytesPerSprite + 1 * sizeof(float) + 0])) =
134 pointSpriteY; // Y
135
136 // Add color data for the pointsprite
137 positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 0] = pointSpriteRed; // R
138 positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 1] = pointSpriteGreen; // G
139 positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 2] = pointSpriteBlue; // B
140 }
141
142 // Generate the GL buffer with the position/color data
143 glGenBuffers(1, &mPositionColorBuffer[i]);
144 glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
145 glBufferData(GL_ARRAY_BUFFER, params.numSprites * mBytesPerSprite, &(positionColorData[0]),
146 GL_STATIC_DRAW);
147 }
148
149 ASSERT_GL_NO_ERROR();
150 }
151
destroyBenchmark()152 void InterleavedAttributeDataBenchmark::destroyBenchmark()
153 {
154 glDeleteProgram(mPointSpriteProgram);
155
156 for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
157 {
158 glDeleteBuffers(1, &mPositionColorBuffer[i]);
159 }
160 }
161
drawBenchmark()162 void InterleavedAttributeDataBenchmark::drawBenchmark()
163 {
164 glClear(GL_COLOR_BUFFER_BIT);
165
166 for (size_t k = 0; k < 20; k++)
167 {
168 for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
169 {
170 // Firstly get the attribute locations for the program
171 glUseProgram(mPointSpriteProgram);
172 GLint positionLocation = glGetAttribLocation(mPointSpriteProgram, "aPosition");
173 ASSERT_NE(positionLocation, -1);
174 GLint colorLocation = glGetAttribLocation(mPointSpriteProgram, "aColor");
175 ASSERT_NE(colorLocation, -1);
176
177 // Bind the position data from one buffer
178 glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
179 glEnableVertexAttribArray(positionLocation);
180 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE,
181 static_cast<GLsizei>(mBytesPerSprite), 0);
182
183 // But bind the color data from the other buffer.
184 glBindBuffer(GL_ARRAY_BUFFER,
185 mPositionColorBuffer[(i + 1) % ArraySize(mPositionColorBuffer)]);
186 glEnableVertexAttribArray(colorLocation);
187 glVertexAttribPointer(colorLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE,
188 static_cast<GLsizei>(mBytesPerSprite),
189 reinterpret_cast<void *>(2 * sizeof(float)));
190
191 // Then draw the colored pointsprites
192 glDrawArrays(GL_POINTS, 0, GetParam().numSprites);
193
194 glDisableVertexAttribArray(positionLocation);
195 glDisableVertexAttribArray(colorLocation);
196 }
197 }
198
199 ASSERT_GL_NO_ERROR();
200 }
201
TEST_P(InterleavedAttributeDataBenchmark,Run)202 TEST_P(InterleavedAttributeDataBenchmark, Run)
203 {
204 run();
205 }
206
D3D11Params()207 InterleavedAttributeDataParams D3D11Params()
208 {
209 InterleavedAttributeDataParams params;
210 params.eglParameters = egl_platform::D3D11();
211 return params;
212 }
213
MetalParams()214 InterleavedAttributeDataParams MetalParams()
215 {
216 InterleavedAttributeDataParams params;
217 params.eglParameters = egl_platform::METAL();
218 return params;
219 }
220
OpenGLOrGLESParams()221 InterleavedAttributeDataParams OpenGLOrGLESParams()
222 {
223 InterleavedAttributeDataParams params;
224 params.eglParameters = egl_platform::OPENGL_OR_GLES();
225 return params;
226 }
227
VulkanParams()228 InterleavedAttributeDataParams VulkanParams()
229 {
230 InterleavedAttributeDataParams params;
231 params.eglParameters = egl_platform::VULKAN();
232 return params;
233 }
234
235 ANGLE_INSTANTIATE_TEST(InterleavedAttributeDataBenchmark,
236 D3D11Params(),
237 MetalParams(),
238 OpenGLOrGLESParams(),
239 VulkanParams());
240
241 } // anonymous namespace
242