1 //
2 // Copyright 2017 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 // BlitFramebufferPerf:
7 // Performance tests for glBlitFramebuffer in ES3. Includes tests for
8 // color, depth, and stencil blit, as well as the mutlisample versions.
9 // The test works by clearing a framebuffer, then blitting it to a second.
10
11 #include "ANGLEPerfTest.h"
12
13 #include "util/gles_loader_autogen.h"
14
15 namespace
16 {
17 constexpr unsigned int kIterationsPerStep = 5;
18
19 enum class BufferType
20 {
21 COLOR,
22 DEPTH,
23 STENCIL,
24 DEPTH_STENCIL
25 };
26
BufferTypeString(BufferType type)27 const char *BufferTypeString(BufferType type)
28 {
29 switch (type)
30 {
31 case BufferType::COLOR:
32 return "color";
33 case BufferType::DEPTH:
34 return "depth";
35 case BufferType::STENCIL:
36 return "stencil";
37 case BufferType::DEPTH_STENCIL:
38 return "depth_stencil";
39 default:
40 return "error";
41 }
42 }
43
BufferTypeMask(BufferType type)44 GLbitfield BufferTypeMask(BufferType type)
45 {
46 switch (type)
47 {
48 case BufferType::COLOR:
49 return GL_COLOR_BUFFER_BIT;
50 case BufferType::DEPTH:
51 return GL_DEPTH_BUFFER_BIT;
52 case BufferType::STENCIL:
53 return GL_STENCIL_BUFFER_BIT;
54 case BufferType::DEPTH_STENCIL:
55 return (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
56 default:
57 return 0;
58 }
59 }
60
BufferTypeFormat(BufferType type)61 GLenum BufferTypeFormat(BufferType type)
62 {
63 switch (type)
64 {
65 case BufferType::COLOR:
66 return GL_RGBA8;
67 case BufferType::DEPTH:
68 return GL_DEPTH_COMPONENT24;
69 case BufferType::STENCIL:
70 return GL_STENCIL_INDEX8;
71 case BufferType::DEPTH_STENCIL:
72 return GL_DEPTH24_STENCIL8;
73 default:
74 return GL_NONE;
75 }
76 }
77
BufferTypeAttachment(BufferType type)78 GLenum BufferTypeAttachment(BufferType type)
79 {
80 switch (type)
81 {
82 case BufferType::COLOR:
83 return GL_COLOR_ATTACHMENT0;
84 case BufferType::DEPTH:
85 return GL_DEPTH_ATTACHMENT;
86 case BufferType::STENCIL:
87 return GL_STENCIL_ATTACHMENT;
88 case BufferType::DEPTH_STENCIL:
89 return GL_DEPTH_STENCIL_ATTACHMENT;
90 default:
91 return GL_NONE;
92 }
93 }
94
95 struct BlitFramebufferParams final : public RenderTestParams
96 {
BlitFramebufferParams__anonc74dede70111::BlitFramebufferParams97 BlitFramebufferParams()
98 {
99 iterationsPerStep = kIterationsPerStep;
100 majorVersion = 3;
101 minorVersion = 0;
102 windowWidth = 256;
103 windowHeight = 256;
104 }
105
story__anonc74dede70111::BlitFramebufferParams106 std::string story() const override
107 {
108 std::stringstream storyStr;
109 storyStr << RenderTestParams::story();
110 storyStr << "_" << BufferTypeString(type);
111 if (samples > 1)
112 {
113 storyStr << "_" << samples << "_samples";
114 }
115 return storyStr.str();
116 }
117
118 BufferType type = BufferType::COLOR;
119 unsigned int framebufferSize = 512;
120 unsigned int samples = 0;
121 };
122
operator <<(std::ostream & os,const BlitFramebufferParams & params)123 std::ostream &operator<<(std::ostream &os, const BlitFramebufferParams ¶ms)
124 {
125 os << params.backendAndStory().substr(1);
126 return os;
127 }
128
129 class BlitFramebufferPerf : public ANGLERenderTest,
130 public ::testing::WithParamInterface<BlitFramebufferParams>
131 {
132 public:
BlitFramebufferPerf()133 BlitFramebufferPerf() : ANGLERenderTest("BlitFramebufferPerf", GetParam()) {}
134
135 void initializeBenchmark() override;
136 void destroyBenchmark() override;
137 void drawBenchmark() override;
138
139 private:
140 GLuint mReadFramebuffer = 0;
141 GLuint mReadRenderbuffer = 0;
142 GLuint mDrawFramebuffer = 0;
143 GLuint mDrawRenderbuffer = 0;
144 };
145
initializeBenchmark()146 void BlitFramebufferPerf::initializeBenchmark()
147 {
148 const auto ¶m = GetParam();
149
150 glGenFramebuffers(1, &mReadFramebuffer);
151 glGenFramebuffers(1, &mDrawFramebuffer);
152
153 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer);
154 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
155
156 // Create source and destination Renderbuffers.
157 glGenRenderbuffers(1, &mReadRenderbuffer);
158 glGenRenderbuffers(1, &mDrawRenderbuffer);
159
160 ASSERT_GL_NO_ERROR();
161
162 GLenum format = BufferTypeFormat(param.type);
163 GLuint size = param.framebufferSize;
164 GLenum attachment = BufferTypeAttachment(param.type);
165
166 glBindRenderbuffer(GL_RENDERBUFFER, mReadRenderbuffer);
167 glRenderbufferStorageMultisample(GL_RENDERBUFFER, param.samples, format, size, size);
168 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, attachment, GL_RENDERBUFFER, mReadRenderbuffer);
169 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
170
171 glBindRenderbuffer(GL_RENDERBUFFER, mDrawRenderbuffer);
172 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, size, size);
173 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, mDrawRenderbuffer);
174 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
175
176 ASSERT_GL_NO_ERROR();
177 }
178
destroyBenchmark()179 void BlitFramebufferPerf::destroyBenchmark()
180 {
181 glDeleteFramebuffers(1, &mReadFramebuffer);
182 glDeleteRenderbuffers(1, &mReadRenderbuffer);
183 glDeleteFramebuffers(1, &mDrawFramebuffer);
184 glDeleteRenderbuffers(1, &mDrawRenderbuffer);
185 }
186
drawBenchmark()187 void BlitFramebufferPerf::drawBenchmark()
188 {
189 const auto ¶m = GetParam();
190 auto size = param.framebufferSize;
191 auto mask = BufferTypeMask(param.type);
192
193 // We don't read from the draw buffer (ie rendering) to simplify the test, but we could.
194 // This might trigger a flush, or we could trigger a flush manually to ensure the blit happens.
195 // TODO(jmadill): Investigate performance on Vulkan, and placement of Clear call.
196
197 switch (param.type)
198 {
199 case BufferType::COLOR:
200 {
201 GLfloat clearValues[4] = {1.0f, 0.0f, 0.0f, 1.0f};
202 glClearBufferfv(GL_COLOR, 0, clearValues);
203 break;
204 }
205 case BufferType::DEPTH:
206 {
207 GLfloat clearDepthValue = 0.5f;
208 glClearBufferfv(GL_DEPTH, 0, &clearDepthValue);
209 break;
210 }
211 case BufferType::STENCIL:
212 {
213 GLint clearStencilValue = 1;
214 glClearBufferiv(GL_STENCIL, 0, &clearStencilValue);
215 break;
216 }
217 case BufferType::DEPTH_STENCIL:
218 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.5f, 1);
219 break;
220 }
221
222 for (unsigned int iteration = 0; iteration < param.iterationsPerStep; ++iteration)
223 {
224 glBlitFramebuffer(0, 0, size, size, 0, 0, size, size, mask, GL_NEAREST);
225 }
226 }
227
TEST_P(BlitFramebufferPerf,Run)228 TEST_P(BlitFramebufferPerf, Run)
229 {
230 run();
231 }
232
D3D11(BufferType type,unsigned int samples)233 BlitFramebufferParams D3D11(BufferType type, unsigned int samples)
234 {
235 BlitFramebufferParams params;
236 params.eglParameters = angle::egl_platform::D3D11();
237 params.type = type;
238 params.samples = samples;
239 return params;
240 }
241 } // anonymous namespace
242
243 // TODO(jmadill): Programatically generate these combinations.
244 ANGLE_INSTANTIATE_TEST(BlitFramebufferPerf,
245 D3D11(BufferType::COLOR, 0),
246 D3D11(BufferType::DEPTH, 0),
247 D3D11(BufferType::STENCIL, 0),
248 D3D11(BufferType::DEPTH_STENCIL, 0),
249 D3D11(BufferType::COLOR, 2),
250 D3D11(BufferType::DEPTH, 2),
251 D3D11(BufferType::STENCIL, 2),
252 D3D11(BufferType::DEPTH_STENCIL, 2));
253