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__anon1a905d180111::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 // Timing out on Intel. http://crbug.com/921004
76 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
77 {
78 mSkipTest = true;
79 }
80 }
81
initializeBenchmark()82 void InterleavedAttributeDataBenchmark::initializeBenchmark()
83 {
84 const auto ¶ms = GetParam();
85
86 // Compile point sprite shaders
87 constexpr char kVS[] =
88 "attribute vec4 aPosition;"
89 "attribute vec4 aColor;"
90 "varying vec4 vColor;"
91 "void main()"
92 "{"
93 " gl_PointSize = 25.0;"
94 " gl_Position = aPosition;"
95 " vColor = aColor;"
96 "}";
97
98 constexpr char kFS[] =
99 "precision mediump float;"
100 "varying vec4 vColor;"
101 "void main()"
102 "{"
103 " gl_FragColor = vColor;"
104 "}";
105
106 mPointSpriteProgram = CompileProgram(kVS, kFS);
107 ASSERT_NE(0u, mPointSpriteProgram);
108
109 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
110
111 for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
112 {
113 // Set up initial data for pointsprite positions and colors
114 std::vector<uint8_t> positionColorData(mBytesPerSprite * params.numSprites);
115 for (unsigned int j = 0; j < params.numSprites; j++)
116 {
117 float pointSpriteX =
118 (static_cast<float>(rand() % getWindow()->getWidth()) / getWindow()->getWidth()) *
119 2.0f -
120 1.0f;
121 float pointSpriteY =
122 (static_cast<float>(rand() % getWindow()->getHeight()) / getWindow()->getHeight()) *
123 2.0f -
124 1.0f;
125 GLubyte pointSpriteRed = static_cast<GLubyte>(rand() % 255);
126 GLubyte pointSpriteGreen = static_cast<GLubyte>(rand() % 255);
127 GLubyte pointSpriteBlue = static_cast<GLubyte>(rand() % 255);
128
129 // Add position data for the pointsprite
130 *reinterpret_cast<float *>(
131 &(positionColorData[j * mBytesPerSprite + 0 * sizeof(float) + 0])) =
132 pointSpriteX; // X
133 *reinterpret_cast<float *>(
134 &(positionColorData[j * mBytesPerSprite + 1 * sizeof(float) + 0])) =
135 pointSpriteY; // Y
136
137 // Add color data for the pointsprite
138 positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 0] = pointSpriteRed; // R
139 positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 1] = pointSpriteGreen; // G
140 positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 2] = pointSpriteBlue; // B
141 }
142
143 // Generate the GL buffer with the position/color data
144 glGenBuffers(1, &mPositionColorBuffer[i]);
145 glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
146 glBufferData(GL_ARRAY_BUFFER, params.numSprites * mBytesPerSprite, &(positionColorData[0]),
147 GL_STATIC_DRAW);
148 }
149
150 ASSERT_GL_NO_ERROR();
151 }
152
destroyBenchmark()153 void InterleavedAttributeDataBenchmark::destroyBenchmark()
154 {
155 glDeleteProgram(mPointSpriteProgram);
156
157 for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
158 {
159 glDeleteBuffers(1, &mPositionColorBuffer[i]);
160 }
161 }
162
drawBenchmark()163 void InterleavedAttributeDataBenchmark::drawBenchmark()
164 {
165 glClear(GL_COLOR_BUFFER_BIT);
166
167 for (size_t k = 0; k < 20; k++)
168 {
169 for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
170 {
171 // Firstly get the attribute locations for the program
172 glUseProgram(mPointSpriteProgram);
173 GLint positionLocation = glGetAttribLocation(mPointSpriteProgram, "aPosition");
174 ASSERT_NE(positionLocation, -1);
175 GLint colorLocation = glGetAttribLocation(mPointSpriteProgram, "aColor");
176 ASSERT_NE(colorLocation, -1);
177
178 // Bind the position data from one buffer
179 glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
180 glEnableVertexAttribArray(positionLocation);
181 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE,
182 static_cast<GLsizei>(mBytesPerSprite), 0);
183
184 // But bind the color data from the other buffer.
185 glBindBuffer(GL_ARRAY_BUFFER,
186 mPositionColorBuffer[(i + 1) % ArraySize(mPositionColorBuffer)]);
187 glEnableVertexAttribArray(colorLocation);
188 glVertexAttribPointer(colorLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE,
189 static_cast<GLsizei>(mBytesPerSprite),
190 reinterpret_cast<void *>(2 * sizeof(float)));
191
192 // Then draw the colored pointsprites
193 glDrawArrays(GL_POINTS, 0, GetParam().numSprites);
194
195 glDisableVertexAttribArray(positionLocation);
196 glDisableVertexAttribArray(colorLocation);
197 }
198 }
199
200 ASSERT_GL_NO_ERROR();
201 }
202
TEST_P(InterleavedAttributeDataBenchmark,Run)203 TEST_P(InterleavedAttributeDataBenchmark, Run)
204 {
205 run();
206 }
207
D3D11Params()208 InterleavedAttributeDataParams D3D11Params()
209 {
210 InterleavedAttributeDataParams params;
211 params.eglParameters = egl_platform::D3D11();
212 return params;
213 }
214
OpenGLOrGLESParams()215 InterleavedAttributeDataParams OpenGLOrGLESParams()
216 {
217 InterleavedAttributeDataParams params;
218 params.eglParameters = egl_platform::OPENGL_OR_GLES();
219 return params;
220 }
221
VulkanParams()222 InterleavedAttributeDataParams VulkanParams()
223 {
224 InterleavedAttributeDataParams params;
225 params.eglParameters = egl_platform::VULKAN();
226 return params;
227 }
228
229 ANGLE_INSTANTIATE_TEST(InterleavedAttributeDataBenchmark,
230 D3D11Params(),
231 OpenGLOrGLESParams(),
232 VulkanParams());
233
234 } // anonymous namespace
235