1 //
2 // Copyright 2020 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 // MultisampledRenderToTextureBenchmark:
7 // Performance test for rendering to multisampled-render-to-texture attachments.
8 //
9
10 #include "ANGLEPerfTest.h"
11
12 #include <iostream>
13 #include <random>
14 #include <sstream>
15
16 #include "test_utils/gl_raii.h"
17 #include "util/shader_utils.h"
18
19 using namespace angle;
20
21 namespace
22 {
23 constexpr uint32_t kMultipassPassCount = 5;
24
25 struct MultisampledRenderToTextureParams final : public RenderTestParams
26 {
MultisampledRenderToTextureParams__anon99bcfd070111::MultisampledRenderToTextureParams27 MultisampledRenderToTextureParams()
28 {
29 iterationsPerStep = 1;
30 trackGpuTime = true;
31
32 textureWidth = 1920;
33 textureHeight = 1080;
34
35 multiplePasses = false;
36 withDepthStencil = false;
37 }
38
39 std::string story() const override;
40
41 GLsizei textureWidth;
42 GLsizei textureHeight;
43
44 bool multiplePasses;
45 bool withDepthStencil;
46 };
47
operator <<(std::ostream & os,const MultisampledRenderToTextureParams & params)48 std::ostream &operator<<(std::ostream &os, const MultisampledRenderToTextureParams ¶ms)
49 {
50 return os << params.backendAndStory().substr(1);
51 }
52
story() const53 std::string MultisampledRenderToTextureParams::story() const
54 {
55 std::stringstream strstr;
56
57 strstr << RenderTestParams::story();
58
59 if (multiplePasses)
60 {
61 strstr << "_multipass";
62 }
63
64 if (withDepthStencil)
65 {
66 strstr << "_ds";
67 }
68
69 return strstr.str();
70 }
71
72 class MultisampledRenderToTextureBenchmark
73 : public ANGLERenderTest,
74 public ::testing::WithParamInterface<MultisampledRenderToTextureParams>
75 {
76 public:
77 MultisampledRenderToTextureBenchmark();
78
79 void initializeBenchmark() override;
80 void destroyBenchmark() override;
81 void drawBenchmark() override;
82
83 protected:
84 void initShaders();
85
86 GLuint mFramebuffer = 0;
87 GLuint mProgram = 0;
88 GLuint mColorTexture = 0;
89 GLuint mDepthStencilRenderbuffer = 0;
90
91 std::vector<uint8_t> mTextureData;
92 };
93
MultisampledRenderToTextureBenchmark()94 MultisampledRenderToTextureBenchmark::MultisampledRenderToTextureBenchmark()
95 : ANGLERenderTest("MultisampledRenderToTexture", GetParam())
96 {
97 if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
98 {
99 skipTest("http://crbug.com/945415 Crashes on nvidia+d3d11");
100 }
101
102 if (IsWindows7() && IsNVIDIA() &&
103 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
104 {
105 skipTest(
106 "http://crbug.com/1096510 Fails on Windows7 NVIDIA Vulkan, presumably due to old "
107 "drivers");
108 }
109
110 if (IsPixel4() && GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
111 {
112 skipTest("http://anglebug.com/40096724 Fails on Pixel 4 GLES");
113 }
114
115 if (IsLinux() && IsAMD() &&
116 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE &&
117 GetParam().multiplePasses && GetParam().withDepthStencil)
118 {
119 skipTest("http://anglebug.com/42263920");
120 }
121
122 if (IsLinux() && IsIntel() &&
123 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
124 {
125 skipTest("http://anglebug.com/42264836");
126 }
127 }
128
initializeBenchmark()129 void MultisampledRenderToTextureBenchmark::initializeBenchmark()
130 {
131 if (!IsGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"))
132 {
133 skipTest("missing GL_EXT_multisampled_render_to_texture");
134 return;
135 }
136
137 const auto ¶ms = GetParam();
138
139 initShaders();
140 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
141 glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
142
143 glGenFramebuffers(1, &mFramebuffer);
144 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
145
146 glGenTextures(1, &mColorTexture);
147 glBindTexture(GL_TEXTURE_2D, mColorTexture);
148
149 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, params.textureWidth, params.textureHeight, 0, GL_RGBA,
150 GL_UNSIGNED_BYTE, nullptr);
151 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
152 mColorTexture, 0, 4);
153
154 if (params.withDepthStencil)
155 {
156 glGenRenderbuffers(1, &mDepthStencilRenderbuffer);
157 glBindRenderbuffer(GL_RENDERBUFFER, mDepthStencilRenderbuffer);
158 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8,
159 params.textureWidth, params.textureHeight);
160 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
161 mDepthStencilRenderbuffer);
162 }
163
164 ASSERT_GL_NO_ERROR();
165 }
166
initShaders()167 void MultisampledRenderToTextureBenchmark::initShaders()
168 {
169 constexpr char kVS[] = R"(void main()
170 {
171 gl_Position = vec4(0, 0, 0, 1);
172 })";
173
174 constexpr char kFS[] = R"(precision mediump float;
175 void main()
176 {
177 gl_FragColor = vec4(0);
178 })";
179
180 mProgram = CompileProgram(kVS, kFS);
181 ASSERT_NE(0u, mProgram);
182
183 glUseProgram(mProgram);
184
185 ASSERT_GL_NO_ERROR();
186 }
187
destroyBenchmark()188 void MultisampledRenderToTextureBenchmark::destroyBenchmark()
189 {
190 glDeleteFramebuffers(1, &mFramebuffer);
191 glDeleteRenderbuffers(1, &mDepthStencilRenderbuffer);
192 glDeleteTextures(1, &mColorTexture);
193 glDeleteProgram(mProgram);
194 }
195
drawBenchmark()196 void MultisampledRenderToTextureBenchmark::drawBenchmark()
197 {
198 const auto ¶ms = GetParam();
199
200 GLTexture mMockTexture;
201 glBindTexture(GL_TEXTURE_2D, mMockTexture);
202
203 startGpuTimer();
204
205 // Initially clear the color attachment to avoid having to load from the resolved image. The
206 // depth/stencil attachment doesn't need this as it's contents are always undefined between
207 // render passes.
208 glClear(GL_COLOR_BUFFER_BIT);
209
210 const uint32_t passCount = params.multiplePasses ? kMultipassPassCount : 1;
211 for (uint32_t pass = 0; pass < passCount; ++pass)
212 {
213 // Perform a draw just to have something in the render pass. With the position attributes
214 // not set, a constant default value is used, resulting in a very cheap draw.
215 glDrawArrays(GL_TRIANGLES, 0, 3);
216
217 // Force the render pass to break by cheaply reading back from the color attachment.
218 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0);
219 }
220 stopGpuTimer();
221
222 ASSERT_GL_NO_ERROR();
223 }
224
D3D11Params(bool multiplePasses,bool withDepthStencil)225 MultisampledRenderToTextureParams D3D11Params(bool multiplePasses, bool withDepthStencil)
226 {
227 MultisampledRenderToTextureParams params;
228 params.eglParameters = egl_platform::D3D11();
229 params.majorVersion = 3;
230 params.minorVersion = 0;
231 params.multiplePasses = multiplePasses;
232 params.withDepthStencil = withDepthStencil;
233 return params;
234 }
235
MetalParams(bool multiplePasses,bool withDepthStencil)236 MultisampledRenderToTextureParams MetalParams(bool multiplePasses, bool withDepthStencil)
237 {
238 MultisampledRenderToTextureParams params;
239 params.eglParameters = egl_platform::METAL();
240 params.majorVersion = 3;
241 params.minorVersion = 0;
242 params.multiplePasses = multiplePasses;
243 params.withDepthStencil = withDepthStencil;
244 return params;
245 }
246
OpenGLOrGLESParams(bool multiplePasses,bool withDepthStencil)247 MultisampledRenderToTextureParams OpenGLOrGLESParams(bool multiplePasses, bool withDepthStencil)
248 {
249 MultisampledRenderToTextureParams params;
250 params.eglParameters = egl_platform::OPENGL_OR_GLES();
251 params.majorVersion = 3;
252 params.minorVersion = 0;
253 params.multiplePasses = multiplePasses;
254 params.withDepthStencil = withDepthStencil;
255 return params;
256 }
257
VulkanParams(bool multiplePasses,bool withDepthStencil)258 MultisampledRenderToTextureParams VulkanParams(bool multiplePasses, bool withDepthStencil)
259 {
260 MultisampledRenderToTextureParams params;
261 params.eglParameters = egl_platform::VULKAN();
262 params.majorVersion = 3;
263 params.minorVersion = 0;
264 params.multiplePasses = multiplePasses;
265 params.withDepthStencil = withDepthStencil;
266 return params;
267 }
268
269 } // anonymous namespace
270
TEST_P(MultisampledRenderToTextureBenchmark,Run)271 TEST_P(MultisampledRenderToTextureBenchmark, Run)
272 {
273 run();
274 }
275
276 using namespace params;
277
278 ANGLE_INSTANTIATE_TEST(MultisampledRenderToTextureBenchmark,
279 D3D11Params(false, false),
280 D3D11Params(true, true),
281 MetalParams(false, false),
282 MetalParams(true, true),
283 OpenGLOrGLESParams(false, false),
284 OpenGLOrGLESParams(true, true),
285 VulkanParams(false, false),
286 VulkanParams(true, false),
287 VulkanParams(false, true),
288 VulkanParams(true, true));
289