1 //
2 // Copyright 2019 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 // ClearPerf:
7 // Performance test for clearing framebuffers.
8 //
9
10 #include "ANGLEPerfTest.h"
11
12 #include <iostream>
13 #include <random>
14 #include <sstream>
15
16 #include "test_utils/ANGLETest.h"
17 #include "test_utils/gl_raii.h"
18 #include "util/random_utils.h"
19 #include "util/shader_utils.h"
20
21 using namespace angle;
22
23 namespace
24 {
25 constexpr unsigned int kIterationsPerStep = 256;
26
27 struct ClearParams final : public RenderTestParams
28 {
ClearParams__anon23f243090111::ClearParams29 ClearParams()
30 {
31 iterationsPerStep = kIterationsPerStep;
32 trackGpuTime = true;
33
34 fboSize = 2048;
35
36 internalFormat = GL_RGBA8;
37
38 scissoredClear = false;
39 }
40
41 std::string story() const override;
42
43 GLsizei fboSize;
44 GLsizei textureSize;
45
46 GLenum internalFormat;
47
48 bool scissoredClear;
49 };
50
operator <<(std::ostream & os,const ClearParams & params)51 std::ostream &operator<<(std::ostream &os, const ClearParams ¶ms)
52 {
53 os << params.backendAndStory().substr(1);
54 return os;
55 }
56
story() const57 std::string ClearParams::story() const
58 {
59 std::stringstream strstr;
60
61 strstr << RenderTestParams::story();
62
63 if (internalFormat == GL_RGB8)
64 {
65 strstr << "_rgb";
66 }
67
68 if (scissoredClear)
69 {
70 strstr << "_scissoredClear";
71 }
72
73 return strstr.str();
74 }
75
76 class ClearBenchmark : public ANGLERenderTest, public ::testing::WithParamInterface<ClearParams>
77 {
78 public:
79 ClearBenchmark();
80
81 void initializeBenchmark() override;
82 void destroyBenchmark() override;
83 void drawBenchmark() override;
84
85 private:
86 void initShaders();
87
88 std::vector<GLuint> mTextures;
89
90 GLuint mProgram;
91 };
92
ClearBenchmark()93 ClearBenchmark::ClearBenchmark() : ANGLERenderTest("Clear", GetParam()), mProgram(0u)
94 {
95 if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
96 {
97 skipTest("http://crbug.com/945415 Crashes on nvidia+d3d11");
98 }
99 }
100
initializeBenchmark()101 void ClearBenchmark::initializeBenchmark()
102 {
103 initShaders();
104 glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
105
106 ASSERT_GL_NO_ERROR();
107 }
108
initShaders()109 void ClearBenchmark::initShaders()
110 {
111 constexpr char kVS[] = R"(void main()
112 {
113 gl_Position = vec4(0, 0, 0, 1);
114 })";
115
116 constexpr char kFS[] = R"(precision mediump float;
117 void main()
118 {
119 gl_FragColor = vec4(0);
120 })";
121
122 mProgram = CompileProgram(kVS, kFS);
123 ASSERT_NE(0u, mProgram);
124
125 glUseProgram(mProgram);
126
127 glDisable(GL_DEPTH_TEST);
128
129 ASSERT_GL_NO_ERROR();
130 }
131
destroyBenchmark()132 void ClearBenchmark::destroyBenchmark()
133 {
134 glDeleteProgram(mProgram);
135 }
136
drawBenchmark()137 void ClearBenchmark::drawBenchmark()
138 {
139 const auto ¶ms = GetParam();
140
141 GLRenderbuffer colorRbo;
142 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
143 glRenderbufferStorage(GL_RENDERBUFFER, params.internalFormat, params.fboSize, params.fboSize);
144
145 GLRenderbuffer depthRbo;
146 glBindRenderbuffer(GL_RENDERBUFFER, depthRbo);
147 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, params.fboSize, params.fboSize);
148
149 GLFramebuffer fbo;
150 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
151 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
152 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRbo);
153
154 glViewport(0, 0, params.fboSize, params.fboSize);
155 glDisable(GL_SCISSOR_TEST);
156
157 startGpuTimer();
158
159 if (params.scissoredClear)
160 {
161 angle::RNG rng;
162 const GLuint width = params.fboSize;
163 const GLuint height = params.fboSize;
164 for (GLuint index = 0; index < (width - 1) / 2; index++)
165 {
166 // Do the first clear without the scissor.
167 if (index > 0)
168 {
169 glEnable(GL_SCISSOR_TEST);
170 glScissor(index, index, width - (index * 2), height - (index * 2));
171 }
172
173 GLColor color = RandomColor(&rng);
174 Vector4 floatColor = color.toNormalizedVector();
175 glClearColor(floatColor[0], floatColor[1], floatColor[2], floatColor[3]);
176 glClear(GL_COLOR_BUFFER_BIT);
177 }
178 }
179 else
180 {
181 for (size_t it = 0; it < params.iterationsPerStep; ++it)
182 {
183 float clearValue = (it % 2) * 0.5f + 0.2f;
184 glClearColor(clearValue, clearValue, clearValue, clearValue);
185 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
186 glDrawArrays(GL_TRIANGLES, 0, 3);
187 }
188 }
189
190 stopGpuTimer();
191
192 ASSERT_GL_NO_ERROR();
193 }
194
D3D11Params()195 ClearParams D3D11Params()
196 {
197 ClearParams params;
198 params.eglParameters = egl_platform::D3D11();
199 return params;
200 }
201
MetalParams()202 ClearParams MetalParams()
203 {
204 ClearParams params;
205 params.eglParameters = egl_platform::METAL();
206 return params;
207 }
208
OpenGLOrGLESParams()209 ClearParams OpenGLOrGLESParams()
210 {
211 ClearParams params;
212 params.eglParameters = egl_platform::OPENGL_OR_GLES();
213 return params;
214 }
215
VulkanParams(bool emulatedFormat,bool scissoredClear)216 ClearParams VulkanParams(bool emulatedFormat, bool scissoredClear)
217 {
218 ClearParams params;
219 params.eglParameters = egl_platform::VULKAN();
220 if (emulatedFormat)
221 {
222 params.internalFormat = GL_RGB8;
223 }
224 params.scissoredClear = scissoredClear;
225 return params;
226 }
227
228 } // anonymous namespace
229
TEST_P(ClearBenchmark,Run)230 TEST_P(ClearBenchmark, Run)
231 {
232 run();
233 }
234
235 ANGLE_INSTANTIATE_TEST(ClearBenchmark,
236 D3D11Params(),
237 MetalParams(),
238 OpenGLOrGLESParams(),
239 VulkanParams(false, false),
240 VulkanParams(true, false),
241 VulkanParams(false, true));
242