xref: /aosp_15_r20/external/deqp/modules/gles2/performance/es2pTextureUploadTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Texture upload performance tests.
22  *
23  * \todo [2012-10-01 pyry]
24  *  - Test different pixel unpack alignments
25  *  - Use multiple textures
26  *  - Trash cache prior to uploading from data ptr
27  *//*--------------------------------------------------------------------*/
28 
29 #include "es2pTextureUploadTests.hpp"
30 #include "tcuTexture.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "tcuTestLog.hpp"
33 #include "tcuSurface.hpp"
34 #include "gluTextureUtil.hpp"
35 #include "gluShaderProgram.hpp"
36 #include "gluPixelTransfer.hpp"
37 #include "deStringUtil.hpp"
38 #include "deRandom.hpp"
39 #include "deClock.h"
40 #include "deString.h"
41 
42 #include "glsCalibration.hpp"
43 
44 #include "glwEnums.hpp"
45 #include "glwFunctions.hpp"
46 
47 #include <algorithm>
48 #include <vector>
49 
50 namespace deqp
51 {
52 namespace gles2
53 {
54 namespace Performance
55 {
56 
57 using std::string;
58 using std::vector;
59 using tcu::IVec4;
60 using tcu::TestLog;
61 using tcu::TextureFormat;
62 using tcu::Vec2;
63 using tcu::Vec3;
64 using tcu::Vec4;
65 using namespace glw; // GL types
66 
67 static const int VIEWPORT_SIZE  = 64;
68 static const float quadCoords[] = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f};
69 
70 class TextureUploadCase : public TestCase
71 {
72 public:
73     TextureUploadCase(Context &context, const char *name, const char *description, UploadFunction uploadFunction,
74                       uint32_t format, uint32_t type, int texSize);
75     ~TextureUploadCase(void);
76 
77     virtual void init(void);
78     void deinit(void);
79 
80     virtual IterateResult iterate(void) = 0;
81     void logResults(void);
82 
83 protected:
84     UploadFunction m_uploadFunction;
85     uint32_t m_format;
86     uint32_t m_type;
87     int m_texSize;
88     int m_alignment;
89 
90     gls::TheilSenCalibrator m_calibrator;
91     glu::ShaderProgram *m_program;
92     uint32_t m_texture;
93     de::Random m_rnd;
94     TestLog &m_log;
95 
96     vector<uint8_t> m_texData;
97 };
98 
TextureUploadCase(Context & context,const char * name,const char * description,UploadFunction uploadFunction,uint32_t format,uint32_t type,int texSize)99 TextureUploadCase::TextureUploadCase(Context &context, const char *name, const char *description,
100                                      UploadFunction uploadFunction, uint32_t format, uint32_t type, int texSize)
101     : TestCase(context, tcu::NODETYPE_PERFORMANCE, name, description)
102     , m_uploadFunction(uploadFunction)
103     , m_format(format)
104     , m_type(type)
105     , m_texSize(texSize)
106     , m_alignment(4)
107     , m_calibrator()
108     , m_program(DE_NULL)
109     , m_texture(0)
110     , m_rnd(deStringHash(name))
111     , m_log(context.getTestContext().getLog())
112 {
113 }
114 
~TextureUploadCase(void)115 TextureUploadCase::~TextureUploadCase(void)
116 {
117     TextureUploadCase::deinit();
118 }
119 
deinit(void)120 void TextureUploadCase::deinit(void)
121 {
122     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
123 
124     if (m_program)
125     {
126         delete m_program;
127         m_program = DE_NULL;
128     }
129 
130     gl.deleteTextures(1, &m_texture);
131     m_texture = 0;
132 
133     m_texData.clear();
134 }
135 
init(void)136 void TextureUploadCase::init(void)
137 {
138     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
139     int maxTextureSize;
140     gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
141 
142     if (m_texSize > maxTextureSize)
143     {
144         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported texture size");
145         return;
146     }
147 
148     // Create program
149 
150     string vertexShaderSource   = "";
151     string fragmentShaderSource = "";
152 
153     vertexShaderSource.append("precision mediump    float;\n"
154                               "attribute vec2        a_pos;\n"
155                               "varying   vec2        v_texCoord;\n"
156                               "\n"
157                               "void main (void)\n"
158                               "{\n"
159                               "    v_texCoord = a_pos;\n"
160                               "    gl_Position = vec4(a_pos, 0.5, 1.0);\n"
161                               "}\n");
162 
163     fragmentShaderSource.append("precision    mediump    float;\n"
164                                 "uniform    lowp sampler2D    u_sampler;\n"
165                                 "varying    vec2            v_texCoord;\n"
166                                 "\n"
167                                 "void main (void)\n"
168                                 "{\n"
169                                 "    gl_FragColor = texture2D(u_sampler, v_texCoord.xy);\n"
170                                 "}\n");
171 
172     DE_ASSERT(!m_program);
173     m_program = new glu::ShaderProgram(m_context.getRenderContext(),
174                                        glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
175 
176     if (!m_program->isOk())
177     {
178         m_log << *m_program;
179         TCU_FAIL("Failed to create shader program (m_programRender)");
180     }
181 
182     gl.useProgram(m_program->getProgram());
183 
184     // Init GL state
185 
186     gl.viewport(0, 0, VIEWPORT_SIZE, VIEWPORT_SIZE);
187     gl.disable(GL_DEPTH_TEST);
188     gl.disable(GL_CULL_FACE);
189     gl.enable(GL_BLEND);
190     gl.blendFunc(GL_ONE, GL_ONE);
191     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
192     gl.clear(GL_COLOR_BUFFER_BIT);
193 
194     uint32_t uSampler = gl.getUniformLocation(m_program->getProgram(), "u_sampler");
195     uint32_t aPos     = gl.getAttribLocation(m_program->getProgram(), "a_pos");
196     gl.enableVertexAttribArray(aPos);
197     gl.vertexAttribPointer(aPos, 2, GL_FLOAT, GL_FALSE, 0, &quadCoords[0]);
198     gl.uniform1i(uSampler, 0);
199 
200     // Create texture
201 
202     gl.activeTexture(GL_TEXTURE0);
203     gl.genTextures(1, &m_texture);
204     gl.bindTexture(GL_TEXTURE_2D, m_texture);
205     gl.pixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
206     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
207     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
208     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
209     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
210 
211     // Prepare texture data
212 
213     {
214         const tcu::TextureFormat &texFmt = glu::mapGLTransferFormat(m_format, m_type);
215         int pixelSize                    = texFmt.getPixelSize();
216         int stride                       = deAlign32(pixelSize * m_texSize, m_alignment);
217 
218         m_texData.resize(stride * m_texSize);
219 
220         tcu::PixelBufferAccess access(texFmt, m_texSize, m_texSize, 1, stride, 0, &m_texData[0]);
221 
222         tcu::fillWithComponentGradients(access, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
223     }
224 
225     // Do a dry-run to ensure the pipes are hot
226 
227     gl.texImage2D(GL_TEXTURE_2D, 0, m_format, m_texSize, m_texSize, 0, m_format, m_type, &m_texData[0]);
228     gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
229     gl.finish();
230 }
231 
logResults(void)232 void TextureUploadCase::logResults(void)
233 {
234     const gls::MeasureState &measureState = m_calibrator.getMeasureState();
235 
236     // Log measurement details
237 
238     m_log << TestLog::Section("Measurement details", "Measurement details");
239     m_log << TestLog::Message << "Uploading texture with "
240           << (m_uploadFunction == UPLOAD_TEXIMAGE2D ? "glTexImage2D" : "glTexSubImage2D") << "."
241           << TestLog::EndMessage; // \todo [arttu] Change enum to struct with name included
242     m_log << TestLog::Message << "Texture size = " << m_texSize << "x" << m_texSize << "." << TestLog::EndMessage;
243     m_log << TestLog::Message << "Viewport size = " << VIEWPORT_SIZE << "x" << VIEWPORT_SIZE << "."
244           << TestLog::EndMessage;
245     m_log << TestLog::Message << measureState.numDrawCalls << " upload calls / iteration" << TestLog::EndMessage;
246     m_log << TestLog::EndSection;
247 
248     // Log results
249 
250     TestLog &log = m_testCtx.getLog();
251     log << TestLog::Section("Results", "Results");
252 
253     // Log individual frame durations
254     //for (int i = 0; i < m_calibrator.measureState.numFrames; i++)
255     // m_log << TestLog::Message << "Frame " << i+1 << " duration: \t" << m_calibrator.measureState.frameTimes[i] << " us."<< TestLog::EndMessage;
256 
257     std::vector<uint64_t> sortedFrameTimes(measureState.frameTimes.begin(), measureState.frameTimes.end());
258     std::sort(sortedFrameTimes.begin(), sortedFrameTimes.end());
259     vector<uint64_t>::const_iterator first  = sortedFrameTimes.begin();
260     vector<uint64_t>::const_iterator last   = sortedFrameTimes.end();
261     vector<uint64_t>::const_iterator middle = first + (last - first) / 2;
262 
263     uint64_t medianFrameTime = *middle;
264     double medianMTexelsPerSeconds =
265         (double)(m_texSize * m_texSize * measureState.numDrawCalls) / (double)medianFrameTime;
266     double medianTexelDrawDurationNs =
267         (double)medianFrameTime * 1000.0 / (double)(m_texSize * m_texSize * measureState.numDrawCalls);
268 
269     uint64_t totalTime       = measureState.getTotalTime();
270     int numFrames            = (int)measureState.frameTimes.size();
271     int64_t numTexturesDrawn = measureState.numDrawCalls * numFrames;
272     int64_t numPixels        = (int64_t)m_texSize * (int64_t)m_texSize * numTexturesDrawn;
273 
274     double framesPerSecond        = (double)numFrames / ((double)totalTime / 1000000.0);
275     double avgFrameTime           = (double)totalTime / (double)numFrames;
276     double avgMTexelsPerSeconds   = (double)numPixels / (double)totalTime;
277     double avgTexelDrawDurationNs = (double)totalTime * 1000.0 / (double)numPixels;
278 
279     log << TestLog::Float("FramesPerSecond", "Frames per second in measurement\t\t", "Frames/s", QP_KEY_TAG_PERFORMANCE,
280                           (float)framesPerSecond);
281     log << TestLog::Float("AverageFrameTime", "Average frame duration in measurement\t", "us", QP_KEY_TAG_PERFORMANCE,
282                           (float)avgFrameTime);
283     log << TestLog::Float("AverageTexelPerf", "Average texel upload performance\t\t", "MTex/s", QP_KEY_TAG_PERFORMANCE,
284                           (float)avgMTexelsPerSeconds);
285     log << TestLog::Float("AverageTexelTime", "Average texel upload duration\t\t", "ns", QP_KEY_TAG_PERFORMANCE,
286                           (float)avgTexelDrawDurationNs);
287     log << TestLog::Float("MedianTexelPerf", "Median texel upload performance\t\t", "MTex/s", QP_KEY_TAG_PERFORMANCE,
288                           (float)medianMTexelsPerSeconds);
289     log << TestLog::Float("MedianTexelTime", "Median texel upload duration\t\t", "ns", QP_KEY_TAG_PERFORMANCE,
290                           (float)medianTexelDrawDurationNs);
291 
292     log << TestLog::EndSection;
293 
294     gls::logCalibrationInfo(log, m_calibrator); // Log calibration details
295     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)avgMTexelsPerSeconds, 2).c_str());
296 }
297 
298 // Texture upload call case
299 
300 class TextureUploadCallCase : public TextureUploadCase
301 {
302 public:
303     TextureUploadCallCase(Context &context, const char *name, const char *description, UploadFunction uploadFunction,
304                           uint32_t format, uint32_t type, int texSize);
305     ~TextureUploadCallCase(void);
306 
307     IterateResult iterate(void);
308     void render(void);
309 };
310 
TextureUploadCallCase(Context & context,const char * name,const char * description,UploadFunction uploadFunction,uint32_t format,uint32_t type,int texSize)311 TextureUploadCallCase::TextureUploadCallCase(Context &context, const char *name, const char *description,
312                                              UploadFunction uploadFunction, uint32_t format, uint32_t type, int texSize)
313     : TextureUploadCase(context, name, description, uploadFunction, format, type, texSize)
314 {
315 }
316 
~TextureUploadCallCase(void)317 TextureUploadCallCase::~TextureUploadCallCase(void)
318 {
319     TextureUploadCase::deinit();
320 }
321 
render(void)322 void TextureUploadCallCase::render(void)
323 {
324     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
325 
326     // Draw multiple quads to ensure enough workload
327 
328     switch (m_uploadFunction)
329     {
330     case UPLOAD_TEXIMAGE2D:
331         gl.texImage2D(GL_TEXTURE_2D, 0, m_format, m_texSize, m_texSize, 0, m_format, m_type, &m_texData[0]);
332         break;
333     case UPLOAD_TEXSUBIMAGE2D:
334         gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_texSize, m_texSize, m_format, m_type, &m_texData[0]);
335         break;
336     default:
337         DE_ASSERT(false);
338     }
339 }
340 
iterate(void)341 tcu::TestNode::IterateResult TextureUploadCallCase::iterate(void)
342 {
343     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
344 
345     if (m_testCtx.getTestResult() == QP_TEST_RESULT_NOT_SUPPORTED)
346         return STOP;
347 
348     for (;;)
349     {
350         gls::TheilSenCalibrator::State state = m_calibrator.getState();
351 
352         if (state == gls::TheilSenCalibrator::STATE_MEASURE)
353         {
354             int numCalls       = m_calibrator.getCallCount();
355             uint64_t startTime = deGetMicroseconds();
356 
357             for (int i = 0; i < numCalls; i++)
358                 render();
359 
360             gl.finish();
361 
362             uint64_t endTime  = deGetMicroseconds();
363             uint64_t duration = endTime - startTime;
364 
365             m_calibrator.recordIteration(duration);
366         }
367         else if (state == gls::TheilSenCalibrator::STATE_RECOMPUTE_PARAMS)
368         {
369             m_calibrator.recomputeParameters();
370         }
371         else
372         {
373             DE_ASSERT(state == gls::TheilSenCalibrator::STATE_FINISHED);
374             break;
375         }
376 
377         // Touch watchdog between iterations to avoid timeout.
378         {
379             qpWatchDog *dog = m_testCtx.getWatchDog();
380             if (dog)
381                 qpWatchDog_touch(dog);
382         }
383     }
384 
385     GLU_EXPECT_NO_ERROR(gl.getError(), "iterate");
386     logResults();
387     return STOP;
388 }
389 
390 // Texture upload and draw case
391 
392 class TextureUploadAndDrawCase : public TextureUploadCase
393 {
394 public:
395     TextureUploadAndDrawCase(Context &context, const char *name, const char *description, UploadFunction uploadFunction,
396                              uint32_t format, uint32_t type, int texSize);
397     ~TextureUploadAndDrawCase(void);
398 
399     IterateResult iterate(void);
400     void render(void);
401 
402 private:
403     bool m_lastIterationRender;
404     uint64_t m_renderStart;
405 };
406 
TextureUploadAndDrawCase(Context & context,const char * name,const char * description,UploadFunction uploadFunction,uint32_t format,uint32_t type,int texSize)407 TextureUploadAndDrawCase::TextureUploadAndDrawCase(Context &context, const char *name, const char *description,
408                                                    UploadFunction uploadFunction, uint32_t format, uint32_t type,
409                                                    int texSize)
410     : TextureUploadCase(context, name, description, uploadFunction, format, type, texSize)
411     , m_lastIterationRender(false)
412     , m_renderStart(0)
413 {
414 }
415 
~TextureUploadAndDrawCase(void)416 TextureUploadAndDrawCase::~TextureUploadAndDrawCase(void)
417 {
418     TextureUploadCase::deinit();
419 }
420 
render(void)421 void TextureUploadAndDrawCase::render(void)
422 {
423     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
424 
425     // Draw multiple quads to ensure enough workload
426 
427     switch (m_uploadFunction)
428     {
429     case UPLOAD_TEXIMAGE2D:
430         gl.texImage2D(GL_TEXTURE_2D, 0, m_format, m_texSize, m_texSize, 0, m_format, m_type, &m_texData[0]);
431         break;
432     case UPLOAD_TEXSUBIMAGE2D:
433         gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_texSize, m_texSize, m_format, m_type, &m_texData[0]);
434         break;
435     default:
436         DE_ASSERT(false);
437     }
438 
439     gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
440 }
441 
iterate(void)442 tcu::TestNode::IterateResult TextureUploadAndDrawCase::iterate(void)
443 {
444     if (m_testCtx.getTestResult() == QP_TEST_RESULT_NOT_SUPPORTED)
445         return STOP;
446 
447     if (m_lastIterationRender && (m_calibrator.getState() == gls::TheilSenCalibrator::STATE_MEASURE))
448     {
449         uint64_t curTime = deGetMicroseconds();
450         m_calibrator.recordIteration(curTime - m_renderStart);
451     }
452 
453     gls::TheilSenCalibrator::State state = m_calibrator.getState();
454 
455     if (state == gls::TheilSenCalibrator::STATE_MEASURE)
456     {
457         // Render
458         int numCalls = m_calibrator.getCallCount();
459 
460         m_renderStart         = deGetMicroseconds();
461         m_lastIterationRender = true;
462 
463         for (int i = 0; i < numCalls; i++)
464             render();
465 
466         return CONTINUE;
467     }
468     else if (state == gls::TheilSenCalibrator::STATE_RECOMPUTE_PARAMS)
469     {
470         m_calibrator.recomputeParameters();
471         m_lastIterationRender = false;
472         return CONTINUE;
473     }
474     else
475     {
476         DE_ASSERT(state == gls::TheilSenCalibrator::STATE_FINISHED);
477         GLU_EXPECT_NO_ERROR(m_context.getRenderContext().getFunctions().getError(), "finish");
478         logResults();
479         return STOP;
480     }
481 }
482 
483 // Texture upload tests
484 
TextureUploadTests(Context & context)485 TextureUploadTests::TextureUploadTests(Context &context) : TestCaseGroup(context, "upload", "Texture upload tests")
486 {
487 }
488 
~TextureUploadTests(void)489 TextureUploadTests::~TextureUploadTests(void)
490 {
491     TextureUploadTests::deinit();
492 }
493 
deinit(void)494 void TextureUploadTests::deinit(void)
495 {
496 }
497 
init(void)498 void TextureUploadTests::init(void)
499 {
500     TestCaseGroup *uploadCall = new TestCaseGroup(m_context, "upload", "Texture upload");
501     TestCaseGroup *uploadAndDraw =
502         new TestCaseGroup(m_context, "upload_draw_swap", "Texture upload, draw & buffer swap");
503 
504     addChild(uploadCall);
505     addChild(uploadAndDraw);
506 
507     static const struct
508     {
509         const char *name;
510         const char *nameLower;
511         UploadFunction func;
512     } uploadFunctions[] = {{"texImage2D", "teximage2d", UPLOAD_TEXIMAGE2D},
513                            {"texSubImage2D", "texsubimage2d", UPLOAD_TEXSUBIMAGE2D}};
514 
515     static const struct
516     {
517         const char *name;
518         uint32_t format;
519         uint32_t type;
520     } textureCombinations[] = {
521         {"rgb_ubyte", GL_RGB, GL_UNSIGNED_BYTE},
522         {"rgba_ubyte", GL_RGBA, GL_UNSIGNED_BYTE},
523         {"alpha_ubyte", GL_ALPHA, GL_UNSIGNED_BYTE},
524         {"luminance_ubyte", GL_LUMINANCE, GL_UNSIGNED_BYTE},
525         {"luminance-alpha_ubyte", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
526         {"rgb_ushort565", GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
527         {"rgba_ushort4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
528         {"rgba_ushort5551", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1},
529     };
530 
531     static const struct
532     {
533         int size;
534         TestCaseGroup *uploadCallGroup;
535         TestCaseGroup *uploadAndDrawGroup;
536     } textureSizes[] = {
537         {16, new TestCaseGroup(m_context, "16x16", "Texture size 16x16"),
538          new TestCaseGroup(m_context, "16x16", "Texture size 16x16")},
539         {256, new TestCaseGroup(m_context, "256x256", "Texture size 256x256"),
540          new TestCaseGroup(m_context, "256x256", "Texture size 256x256")},
541         {257, new TestCaseGroup(m_context, "257x257", "Texture size 257x257"),
542          new TestCaseGroup(m_context, "257x257", "Texture size 257x257")},
543         {1024, new TestCaseGroup(m_context, "1024x1024", "Texture size 1024x1024"),
544          new TestCaseGroup(m_context, "1024x1024", "Texture size 1024x1024")},
545         {2048, new TestCaseGroup(m_context, "2048x2048", "Texture size 2048x2048"),
546          new TestCaseGroup(m_context, "2048x2048", "Texture size 2048x2048")},
547     };
548 
549 #define FOR_EACH(ITERATOR, ARRAY, BODY)                                      \
550     for (int ITERATOR = 0; ITERATOR < DE_LENGTH_OF_ARRAY(ARRAY); ITERATOR++) \
551     BODY
552 
553     FOR_EACH(uploadFunc, uploadFunctions,
554              FOR_EACH(texSize, textureSizes, FOR_EACH(texCombination, textureCombinations, {
555                           string caseName = string("") + uploadFunctions[uploadFunc].nameLower + "_" +
556                                             textureCombinations[texCombination].name;
557                           UploadFunction function = uploadFunctions[uploadFunc].func;
558                           uint32_t format         = textureCombinations[texCombination].format;
559                           uint32_t type           = textureCombinations[texCombination].type;
560                           int size                = textureSizes[texSize].size;
561 
562                           textureSizes[texSize].uploadCallGroup->addChild(
563                               new TextureUploadCallCase(m_context, caseName.c_str(), "", function, format, type, size));
564                           textureSizes[texSize].uploadAndDrawGroup->addChild(new TextureUploadAndDrawCase(
565                               m_context, caseName.c_str(), "", function, format, type, size));
566                       })))
567 
568     for (int i = 0; i < DE_LENGTH_OF_ARRAY(textureSizes); i++)
569     {
570         uploadCall->addChild(textureSizes[i].uploadCallGroup);
571         uploadAndDraw->addChild(textureSizes[i].uploadAndDrawGroup);
572     }
573 }
574 
575 } // namespace Performance
576 } // namespace gles2
577 } // namespace deqp
578