xref: /aosp_15_r20/external/angle/src/tests/perf_tests/MultisampledRenderToTexturePerf.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 &params)
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 &params = 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 &params = 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