• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // TextureUploadBenchmark:
7 //   Performance test for uploading texture data.
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 unsigned int kIterationsPerStep = 2;
24 
25 struct TextureUploadParams final : public RenderTestParams
26 {
TextureUploadParams__anon1d676fa70111::TextureUploadParams27     TextureUploadParams()
28     {
29         iterationsPerStep = kIterationsPerStep;
30         trackGpuTime      = true;
31 
32         baseSize     = 1024;
33         subImageSize = 64;
34 
35         webgl = false;
36     }
37 
38     std::string story() const override;
39 
40     GLsizei baseSize;
41     GLsizei subImageSize;
42 
43     bool webgl;
44 };
45 
operator <<(std::ostream & os,const TextureUploadParams & params)46 std::ostream &operator<<(std::ostream &os, const TextureUploadParams &params)
47 {
48     os << params.backendAndStory().substr(1);
49     return os;
50 }
51 
story() const52 std::string TextureUploadParams::story() const
53 {
54     std::stringstream strstr;
55 
56     strstr << RenderTestParams::story();
57 
58     if (webgl)
59     {
60         strstr << "_webgl";
61     }
62 
63     return strstr.str();
64 }
65 
66 class TextureUploadBenchmarkBase : public ANGLERenderTest,
67                                    public ::testing::WithParamInterface<TextureUploadParams>
68 {
69   public:
70     TextureUploadBenchmarkBase(const char *benchmarkName);
71 
72     void initializeBenchmark() override;
73     void destroyBenchmark() override;
74 
75   protected:
76     void initShaders();
77 
78     GLuint mProgram    = 0;
79     GLint mPositionLoc = -1;
80     GLint mSamplerLoc  = -1;
81     GLuint mTexture    = 0;
82     std::vector<float> mTextureData;
83 };
84 
85 class TextureUploadSubImageBenchmark : public TextureUploadBenchmarkBase
86 {
87   public:
TextureUploadSubImageBenchmark()88     TextureUploadSubImageBenchmark() : TextureUploadBenchmarkBase("TexSubImage")
89     {
90         addExtensionPrerequisite("GL_EXT_texture_storage");
91 
92         if (IsLinux() && IsIntel() &&
93             GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
94         {
95             skipTest("http://anglebug.com/6319");
96         }
97     }
98 
initializeBenchmark()99     void initializeBenchmark() override
100     {
101         TextureUploadBenchmarkBase::initializeBenchmark();
102 
103         const auto &params = GetParam();
104         glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.baseSize, params.baseSize);
105     }
106 
107     void drawBenchmark() override;
108 };
109 
110 class TextureUploadFullMipBenchmark : public TextureUploadBenchmarkBase
111 {
112   public:
TextureUploadFullMipBenchmark()113     TextureUploadFullMipBenchmark() : TextureUploadBenchmarkBase("TextureUpload") {}
114 
115     void drawBenchmark() override;
116 };
117 
118 class PBOSubImageBenchmark : public TextureUploadBenchmarkBase
119 {
120   public:
PBOSubImageBenchmark()121     PBOSubImageBenchmark() : TextureUploadBenchmarkBase("PBO") {}
122 
initializeBenchmark()123     void initializeBenchmark() override
124     {
125         TextureUploadBenchmarkBase::initializeBenchmark();
126 
127         const auto &params = GetParam();
128 
129         glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.baseSize, params.baseSize);
130 
131         glGenBuffers(1, &mPBO);
132         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
133         glBufferData(GL_PIXEL_UNPACK_BUFFER, params.baseSize * params.baseSize * 4,
134                      mTextureData.data(), GL_STREAM_DRAW);
135     }
136 
destroyBenchmark()137     void destroyBenchmark()
138     {
139         TextureUploadBenchmarkBase::destroyBenchmark();
140         glDeleteBuffers(1, &mPBO);
141     }
142 
143     void drawBenchmark() override;
144 
145   private:
146     GLuint mPBO;
147 };
148 
149 class PBOCompressedSubImageBenchmark : public TextureUploadBenchmarkBase
150 {
151   public:
PBOCompressedSubImageBenchmark()152     PBOCompressedSubImageBenchmark() : TextureUploadBenchmarkBase("PBOCompressed") {}
153 
initializeBenchmark()154     void initializeBenchmark() override
155     {
156         TextureUploadBenchmarkBase::initializeBenchmark();
157 
158         const auto &params = GetParam();
159 
160         glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, params.baseSize,
161                           params.baseSize);
162 
163         glGenBuffers(1, &mPBO);
164         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
165         glBufferData(GL_PIXEL_UNPACK_BUFFER, params.subImageSize * params.subImageSize / 2,
166                      mTextureData.data(), GL_STREAM_DRAW);
167     }
168 
destroyBenchmark()169     void destroyBenchmark()
170     {
171         TextureUploadBenchmarkBase::destroyBenchmark();
172         glDeleteBuffers(1, &mPBO);
173     }
174 
175     void drawBenchmark() override;
176 
177   private:
178     GLuint mPBO;
179 };
180 
TextureUploadBenchmarkBase(const char * benchmarkName)181 TextureUploadBenchmarkBase::TextureUploadBenchmarkBase(const char *benchmarkName)
182     : ANGLERenderTest(benchmarkName, GetParam())
183 {
184     setWebGLCompatibilityEnabled(GetParam().webgl);
185     setRobustResourceInit(GetParam().webgl);
186 
187     if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
188     {
189         skipTest("http://crbug.com/945415 Crashes on nvidia+d3d11");
190     }
191 }
192 
initializeBenchmark()193 void TextureUploadBenchmarkBase::initializeBenchmark()
194 {
195     const auto &params = GetParam();
196 
197     initShaders();
198     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
199     glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
200 
201     glActiveTexture(GL_TEXTURE0);
202     glGenTextures(1, &mTexture);
203     glBindTexture(GL_TEXTURE_2D, mTexture);
204 
205     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
206     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
207     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
208     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
209 
210     ASSERT_TRUE(params.baseSize >= params.subImageSize);
211     mTextureData.resize(params.baseSize * params.baseSize * 4, 0.5);
212 
213     ASSERT_GL_NO_ERROR();
214 }
215 
initShaders()216 void TextureUploadBenchmarkBase::initShaders()
217 {
218     constexpr char kVS[] = R"(attribute vec4 a_position;
219 void main()
220 {
221     gl_Position = a_position;
222 })";
223 
224     constexpr char kFS[] = R"(precision mediump float;
225 uniform sampler2D s_texture;
226 void main()
227 {
228     gl_FragColor = texture2D(s_texture, vec2(0, 0));
229 })";
230 
231     mProgram = CompileProgram(kVS, kFS);
232     ASSERT_NE(0u, mProgram);
233 
234     mPositionLoc = glGetAttribLocation(mProgram, "a_position");
235     mSamplerLoc  = glGetUniformLocation(mProgram, "s_texture");
236     glUseProgram(mProgram);
237     glUniform1i(mSamplerLoc, 0);
238 
239     glDisable(GL_DEPTH_TEST);
240 
241     ASSERT_GL_NO_ERROR();
242 }
243 
destroyBenchmark()244 void TextureUploadBenchmarkBase::destroyBenchmark()
245 {
246     glDeleteTextures(1, &mTexture);
247     glDeleteProgram(mProgram);
248 }
249 
drawBenchmark()250 void TextureUploadSubImageBenchmark::drawBenchmark()
251 {
252     const auto &params = GetParam();
253 
254     startGpuTimer();
255     for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
256     {
257         glTexSubImage2D(GL_TEXTURE_2D, 0, rand() % (params.baseSize - params.subImageSize),
258                         rand() % (params.baseSize - params.subImageSize), params.subImageSize,
259                         params.subImageSize, GL_RGBA, GL_UNSIGNED_BYTE, mTextureData.data());
260 
261         // Perform a draw just so the texture data is flushed.  With the position attributes not
262         // set, a constant default value is used, resulting in a very cheap draw.
263         glDrawArrays(GL_TRIANGLES, 0, 3);
264     }
265     stopGpuTimer();
266 
267     ASSERT_GL_NO_ERROR();
268 }
269 
drawBenchmark()270 void TextureUploadFullMipBenchmark::drawBenchmark()
271 {
272     const auto &params = GetParam();
273 
274     startGpuTimer();
275     for (size_t it = 0; it < params.iterationsPerStep; ++it)
276     {
277         // Stage data for all mips
278         GLint mip = 0;
279         for (GLsizei levelSize = params.baseSize; levelSize > 0; levelSize >>= 1)
280         {
281             glTexImage2D(GL_TEXTURE_2D, mip++, GL_RGBA, levelSize, levelSize, 0, GL_RGBA,
282                          GL_UNSIGNED_BYTE, mTextureData.data());
283         }
284 
285         // Perform a draw just so the texture data is flushed.  With the position attributes not
286         // set, a constant default value is used, resulting in a very cheap draw.
287         glDrawArrays(GL_TRIANGLES, 0, 3);
288     }
289     stopGpuTimer();
290 
291     ASSERT_GL_NO_ERROR();
292 }
293 
drawBenchmark()294 void PBOSubImageBenchmark::drawBenchmark()
295 {
296     const auto &params = GetParam();
297 
298     startGpuTimer();
299     for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
300     {
301         glTexSubImage2D(GL_TEXTURE_2D, 0, rand() % (params.baseSize - params.subImageSize),
302                         rand() % (params.baseSize - params.subImageSize), params.subImageSize,
303                         params.subImageSize, GL_RGBA, GL_UNSIGNED_BYTE, 0);
304 
305         // Perform a draw just so the texture data is flushed.  With the position attributes not
306         // set, a constant default value is used, resulting in a very cheap draw.
307         glDrawArrays(GL_TRIANGLES, 0, 3);
308     }
309     stopGpuTimer();
310 
311     ASSERT_GL_NO_ERROR();
312 }
313 
drawBenchmark()314 void PBOCompressedSubImageBenchmark::drawBenchmark()
315 {
316     const auto &params = GetParam();
317 
318     startGpuTimer();
319     for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
320     {
321         glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, params.subImageSize, params.subImageSize,
322                                   GL_COMPRESSED_RGB8_ETC2,
323                                   params.subImageSize * params.subImageSize / 2, 0);
324 
325         // Perform a draw just so the texture data is flushed.  With the position attributes not
326         // set, a constant default value is used, resulting in a very cheap draw.
327         glDrawArrays(GL_TRIANGLES, 0, 3);
328     }
329     stopGpuTimer();
330 
331     ASSERT_GL_NO_ERROR();
332 }
333 
D3D11Params(bool webglCompat)334 TextureUploadParams D3D11Params(bool webglCompat)
335 {
336     TextureUploadParams params;
337     params.eglParameters = egl_platform::D3D11();
338     params.webgl         = webglCompat;
339     return params;
340 }
341 
MetalParams(bool webglCompat)342 TextureUploadParams MetalParams(bool webglCompat)
343 {
344     TextureUploadParams params;
345     params.eglParameters = egl_platform::METAL();
346     params.webgl         = webglCompat;
347     return params;
348 }
349 
OpenGLOrGLESParams(bool webglCompat)350 TextureUploadParams OpenGLOrGLESParams(bool webglCompat)
351 {
352     TextureUploadParams params;
353     params.eglParameters = egl_platform::OPENGL_OR_GLES();
354     params.webgl         = webglCompat;
355     return params;
356 }
357 
VulkanParams(bool webglCompat)358 TextureUploadParams VulkanParams(bool webglCompat)
359 {
360     TextureUploadParams params;
361     params.eglParameters = egl_platform::VULKAN();
362     params.webgl         = webglCompat;
363     return params;
364 }
365 
MetalPBOParams(GLsizei baseSize,GLsizei subImageSize)366 TextureUploadParams MetalPBOParams(GLsizei baseSize, GLsizei subImageSize)
367 {
368     TextureUploadParams params;
369     params.eglParameters = egl_platform::METAL();
370     params.webgl         = false;
371     params.trackGpuTime  = false;
372     params.baseSize      = baseSize;
373     params.subImageSize  = subImageSize;
374     return params;
375 }
376 
VulkanPBOParams(GLsizei baseSize,GLsizei subImageSize)377 TextureUploadParams VulkanPBOParams(GLsizei baseSize, GLsizei subImageSize)
378 {
379     TextureUploadParams params;
380     params.eglParameters = egl_platform::VULKAN();
381     params.webgl         = false;
382     params.trackGpuTime  = false;
383     params.baseSize      = baseSize;
384     params.subImageSize  = subImageSize;
385     return params;
386 }
387 
ES3OpenGLPBOParams(GLsizei baseSize,GLsizei subImageSize)388 TextureUploadParams ES3OpenGLPBOParams(GLsizei baseSize, GLsizei subImageSize)
389 {
390     TextureUploadParams params;
391     params.eglParameters = egl_platform::OPENGL();
392     params.majorVersion  = 3;
393     params.minorVersion  = 0;
394     params.webgl         = false;
395     params.trackGpuTime  = false;
396     params.baseSize      = baseSize;
397     params.subImageSize  = subImageSize;
398     return params;
399 }
400 
401 }  // anonymous namespace
402 
TEST_P(TextureUploadSubImageBenchmark,Run)403 TEST_P(TextureUploadSubImageBenchmark, Run)
404 {
405     run();
406 }
407 
TEST_P(TextureUploadFullMipBenchmark,Run)408 TEST_P(TextureUploadFullMipBenchmark, Run)
409 {
410     run();
411 }
412 
TEST_P(PBOSubImageBenchmark,Run)413 TEST_P(PBOSubImageBenchmark, Run)
414 {
415     run();
416 }
417 
TEST_P(PBOCompressedSubImageBenchmark,Run)418 TEST_P(PBOCompressedSubImageBenchmark, Run)
419 {
420     run();
421 }
422 
423 using namespace params;
424 
425 ANGLE_INSTANTIATE_TEST(TextureUploadSubImageBenchmark,
426                        D3D11Params(false),
427                        D3D11Params(true),
428                        MetalParams(false),
429                        MetalParams(true),
430                        OpenGLOrGLESParams(false),
431                        OpenGLOrGLESParams(true),
432                        VulkanParams(false),
433                        NullDevice(VulkanParams(false)),
434                        VulkanParams(true));
435 
436 ANGLE_INSTANTIATE_TEST(TextureUploadFullMipBenchmark,
437                        D3D11Params(false),
438                        D3D11Params(true),
439                        MetalParams(false),
440                        MetalParams(true),
441                        OpenGLOrGLESParams(false),
442                        OpenGLOrGLESParams(true),
443                        VulkanParams(false),
444                        VulkanParams(true));
445 
446 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PBOSubImageBenchmark);
447 ANGLE_INSTANTIATE_TEST(PBOSubImageBenchmark,
448                        ES3OpenGLPBOParams(1024, 128),
449                        MetalPBOParams(1024, 128),
450                        VulkanPBOParams(1024, 128));
451 
452 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PBOCompressedSubImageBenchmark);
453 ANGLE_INSTANTIATE_TEST(PBOCompressedSubImageBenchmark,
454                        ES3OpenGLPBOParams(128, 128),
455                        MetalPBOParams(128, 128),
456                        VulkanPBOParams(128, 128));
457