xref: /aosp_15_r20/external/deqp/modules/egl/teglGLES2SharedRenderingPerfTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL 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 GLES2 resource sharing performnace tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglGLES2SharedRenderingPerfTests.hpp"
25 
26 #include "tcuTestLog.hpp"
27 
28 #include "egluUtil.hpp"
29 #include "eglwLibrary.hpp"
30 #include "eglwEnums.hpp"
31 
32 #include "gluDefs.hpp"
33 #include "glwDefs.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 
37 #include "deThread.hpp"
38 #include "deClock.h"
39 #include "deStringUtil.hpp"
40 #include "deSTLUtil.hpp"
41 
42 #include <vector>
43 #include <string>
44 #include <algorithm>
45 #include <cmath>
46 
47 namespace deqp
48 {
49 namespace egl
50 {
51 
52 using std::string;
53 using std::vector;
54 using tcu::TestLog;
55 
56 using namespace glw;
57 using namespace eglw;
58 
59 namespace
60 {
61 
62 struct TestConfig
63 {
64     enum TextureType
65     {
66         TEXTURETYPE_TEXTURE = 0,
67         TEXTURETYPE_SHARED_TEXTURE,
68         TEXTURETYPE_IMAGE,
69         TEXTURETYPE_SHARED_IMAGE,
70         TEXTURETYPE_SHARED_IMAGE_TEXTURE
71     };
72 
73     int threadCount;
74     int perThreadContextCount;
75 
76     int frameCount;
77     int drawCallCount;
78     int triangleCount;
79 
80     bool sharedContexts;
81 
82     bool useCoordBuffer;
83     bool sharedCoordBuffer;
84 
85     bool useIndices;
86     bool useIndexBuffer;
87     bool sharedIndexBuffer;
88 
89     bool useTexture;
90     TextureType textureType;
91 
92     bool sharedProgram;
93 
94     int textureWidth;
95     int textureHeight;
96 
97     int surfaceWidth;
98     int surfaceHeight;
99 };
100 
101 class TestContext
102 {
103 public:
104     TestContext(EglTestContext &eglTestCtx, EGLDisplay display, EGLConfig eglConfig, const TestConfig &config,
105                 bool share, TestContext *parent);
106     ~TestContext(void);
107 
108     void render(void);
109 
getEGLContext(void)110     EGLContext getEGLContext(void)
111     {
112         return m_eglContext;
113     }
114 
getCoordBuffer(void) const115     GLuint getCoordBuffer(void) const
116     {
117         return m_coordBuffer;
118     }
getIndexBuffer(void) const119     GLuint getIndexBuffer(void) const
120     {
121         return m_indexBuffer;
122     }
getTexture(void) const123     GLuint getTexture(void) const
124     {
125         return m_texture;
126     }
getProgram(void) const127     GLuint getProgram(void) const
128     {
129         return m_program;
130     }
getEGLImage(void) const131     EGLImageKHR getEGLImage(void) const
132     {
133         return m_eglImage;
134     }
135 
136 private:
137     TestContext *m_parent;
138     EglTestContext &m_testCtx;
139     TestConfig m_config;
140 
141     EGLDisplay m_eglDisplay;
142     EGLContext m_eglContext;
143     EGLSurface m_eglSurface;
144 
145     glw::Functions m_gl;
146 
147     GLuint m_coordBuffer;
148     GLuint m_indexBuffer;
149     GLuint m_texture;
150     GLuint m_program;
151 
152     EGLImageKHR m_eglImage;
153 
154     GLuint m_coordLoc;
155     GLuint m_textureLoc;
156 
157     vector<float> m_coordData;
158     vector<uint16_t> m_indexData;
159 
160     EGLImageKHR createEGLImage(void);
161     GLuint createTextureFromImage(EGLImageKHR image);
162 
163     // Not supported
164     TestContext &operator=(const TestContext &);
165     TestContext(const TestContext &);
166 };
167 
168 namespace
169 {
170 
createCoordData(vector<float> & data,const TestConfig & config)171 void createCoordData(vector<float> &data, const TestConfig &config)
172 {
173     if (config.useIndices)
174     {
175         for (int triangleNdx = 0; triangleNdx < 2; triangleNdx++)
176         {
177             const float x1 = -1.0f;
178             const float y1 = -1.0f;
179 
180             const float x2 = 1.0f;
181             const float y2 = 1.0f;
182 
183             const float side = ((triangleNdx % 2) == 0 ? 1.0f : -1.0f);
184 
185             data.push_back(side * x1);
186             data.push_back(side * y1);
187 
188             data.push_back(side * x2);
189             data.push_back(side * y1);
190 
191             data.push_back(side * x2);
192             data.push_back(side * y2);
193         }
194     }
195     else
196     {
197         data.reserve(config.triangleCount * 3 * 2);
198 
199         for (int triangleNdx = 0; triangleNdx < config.triangleCount; triangleNdx++)
200         {
201             const float x1 = -1.0f;
202             const float y1 = -1.0f;
203 
204             const float x2 = 1.0f;
205             const float y2 = 1.0f;
206 
207             const float side = ((triangleNdx % 2) == 0 ? 1.0f : -1.0f);
208 
209             data.push_back(side * x1);
210             data.push_back(side * y1);
211 
212             data.push_back(side * x2);
213             data.push_back(side * y1);
214 
215             data.push_back(side * x2);
216             data.push_back(side * y2);
217         }
218     }
219 }
220 
createCoordBuffer(const glw::Functions & gl,const TestConfig & config)221 GLuint createCoordBuffer(const glw::Functions &gl, const TestConfig &config)
222 {
223     GLuint buffer;
224     vector<float> data;
225 
226     createCoordData(data, config);
227 
228     gl.genBuffers(1, &buffer);
229     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()");
230     gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
231     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
232     gl.bufferData(GL_ARRAY_BUFFER, (GLsizei)(data.size() * sizeof(float)), &(data[0]), GL_STATIC_DRAW);
233     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()");
234     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
235     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
236 
237     return buffer;
238 }
239 
createIndexData(vector<uint16_t> & data,const TestConfig & config)240 void createIndexData(vector<uint16_t> &data, const TestConfig &config)
241 {
242     for (int triangleNdx = 0; triangleNdx < config.triangleCount; triangleNdx++)
243     {
244         if ((triangleNdx % 2) == 0)
245         {
246             data.push_back(0);
247             data.push_back(1);
248             data.push_back(2);
249         }
250         else
251         {
252             data.push_back(2);
253             data.push_back(3);
254             data.push_back(0);
255         }
256     }
257 }
258 
createIndexBuffer(const glw::Functions & gl,const TestConfig & config)259 GLuint createIndexBuffer(const glw::Functions &gl, const TestConfig &config)
260 {
261     GLuint buffer;
262     vector<uint16_t> data;
263 
264     createIndexData(data, config);
265 
266     gl.genBuffers(1, &buffer);
267     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()");
268     gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
269     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
270     gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizei)(data.size() * sizeof(uint16_t)), &(data[0]), GL_STATIC_DRAW);
271     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()");
272     gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
273     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
274 
275     return buffer;
276 }
277 
createTextureData(vector<uint8_t> & data,const TestConfig & config)278 void createTextureData(vector<uint8_t> &data, const TestConfig &config)
279 {
280     for (int x = 0; x < config.textureWidth; x++)
281     {
282         for (int y = 0; y < config.textureHeight; y++)
283         {
284             data.push_back((uint8_t)((255 * x) / 255));
285             data.push_back((uint8_t)((255 * y) / 255));
286             data.push_back((uint8_t)((255 * x * y) / (255 * 255)));
287             data.push_back(255);
288         }
289     }
290 }
291 
createTexture(const glw::Functions & gl,const TestConfig & config)292 GLuint createTexture(const glw::Functions &gl, const TestConfig &config)
293 {
294     GLuint texture;
295     vector<uint8_t> data;
296 
297     createTextureData(data, config);
298 
299     gl.genTextures(1, &texture);
300     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures()");
301     gl.bindTexture(GL_TEXTURE_2D, texture);
302     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()");
303     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
304     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
305     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
306     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
307     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
308     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
309     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
310     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
311     gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, config.textureWidth, config.textureWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE,
312                   &(data[0]));
313     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D()");
314     gl.bindTexture(GL_TEXTURE_2D, 0);
315     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()");
316 
317     return texture;
318 }
319 
createProgram(const glw::Functions & gl,const TestConfig & config)320 GLuint createProgram(const glw::Functions &gl, const TestConfig &config)
321 {
322     GLuint vertexShader   = gl.createShader(GL_VERTEX_SHADER);
323     GLuint fragmentShader = gl.createShader(GL_FRAGMENT_SHADER);
324 
325     if (config.useTexture)
326     {
327         const char *vertexShaderSource = "attribute mediump vec2 a_coord;\n"
328                                          "varying mediump vec2 v_texCoord;\n"
329                                          "void main(void)\n"
330                                          "{\n"
331                                          "\tv_texCoord = 0.5 * a_coord + vec2(0.5);\n"
332                                          "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
333                                          "}\n";
334 
335         const char *fragmentShaderSource = "uniform sampler2D u_sampler;\n"
336                                            "varying mediump vec2 v_texCoord;\n"
337                                            "void main(void)\n"
338                                            "{\n"
339                                            "\tgl_FragColor = texture2D(u_sampler, v_texCoord);\n"
340                                            "}\n";
341 
342         gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
343         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
344         gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
345         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
346     }
347     else
348     {
349         const char *vertexShaderSource = "attribute mediump vec2 a_coord;\n"
350                                          "varying mediump vec4 v_color;\n"
351                                          "void main(void)\n"
352                                          "{\n"
353                                          "\tv_color = vec4(0.5 * a_coord + vec2(0.5), 0.5, 1.0);\n"
354                                          "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
355                                          "}\n";
356 
357         const char *fragmentShaderSource = "varying mediump vec4 v_color;\n"
358                                            "void main(void)\n"
359                                            "{\n"
360                                            "\tgl_FragColor = v_color;\n"
361                                            "}\n";
362 
363         gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
364         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
365         gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
366         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
367     }
368 
369     gl.compileShader(vertexShader);
370     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()");
371     gl.compileShader(fragmentShader);
372     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()");
373 
374     {
375         GLint status;
376 
377         gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
378         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
379 
380         if (!status)
381         {
382             string log;
383             GLint length;
384 
385             gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &length);
386             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
387             log.resize(length, 0);
388 
389             gl.getShaderInfoLog(vertexShader, (GLsizei)log.size(), &length, &(log[0]));
390             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog()");
391 
392             throw std::runtime_error(log.c_str());
393         }
394     }
395 
396     {
397         GLint status;
398 
399         gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
400         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
401 
402         if (!status)
403         {
404             string log;
405             GLint length;
406 
407             gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &length);
408             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
409             log.resize(length, 0);
410 
411             gl.getShaderInfoLog(fragmentShader, (GLsizei)log.size(), &length, &(log[0]));
412             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog()");
413 
414             throw std::runtime_error(log.c_str());
415         }
416     }
417 
418     {
419         GLuint program = gl.createProgram();
420 
421         gl.attachShader(program, vertexShader);
422         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()");
423         gl.attachShader(program, fragmentShader);
424         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()");
425 
426         gl.linkProgram(program);
427         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()");
428 
429         {
430             GLint status;
431 
432             gl.getProgramiv(program, GL_LINK_STATUS, &status);
433             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");
434 
435             if (!status)
436             {
437                 string log;
438                 GLsizei length;
439 
440                 gl.getProgramInfoLog(program, 0, &length, DE_NULL);
441                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog()");
442                 log.resize(length, 0);
443 
444                 gl.getProgramInfoLog(program, (GLsizei)log.size(), &length, &(log[0]));
445                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog()");
446 
447                 throw std::runtime_error(log.c_str());
448             }
449         }
450 
451         gl.deleteShader(vertexShader);
452         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader()");
453         gl.deleteShader(fragmentShader);
454         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader()");
455 
456         return program;
457     }
458 }
459 
createEGLContext(EglTestContext & testCtx,EGLDisplay eglDisplay,EGLConfig eglConfig,EGLContext share)460 EGLContext createEGLContext(EglTestContext &testCtx, EGLDisplay eglDisplay, EGLConfig eglConfig, EGLContext share)
461 {
462     const Library &egl        = testCtx.getLibrary();
463     const EGLint attribList[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
464 
465     EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
466 
467     EGLContext context = egl.createContext(eglDisplay, eglConfig, share, attribList);
468     EGLU_CHECK_MSG(egl, "eglCreateContext()");
469 
470     return context;
471 }
472 
createEGLSurface(EglTestContext & testCtx,EGLDisplay display,EGLConfig eglConfig,const TestConfig & config)473 EGLSurface createEGLSurface(EglTestContext &testCtx, EGLDisplay display, EGLConfig eglConfig, const TestConfig &config)
474 {
475     const Library &egl        = testCtx.getLibrary();
476     const EGLint attribList[] = {EGL_WIDTH, config.surfaceWidth, EGL_HEIGHT, config.surfaceHeight, EGL_NONE};
477 
478     EGLSurface surface = egl.createPbufferSurface(display, eglConfig, attribList);
479     EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()");
480 
481     return surface;
482 }
483 
484 } // namespace
485 
TestContext(EglTestContext & testCtx,EGLDisplay eglDisplay,EGLConfig eglConfig,const TestConfig & config,bool share,TestContext * parent)486 TestContext::TestContext(EglTestContext &testCtx, EGLDisplay eglDisplay, EGLConfig eglConfig, const TestConfig &config,
487                          bool share, TestContext *parent)
488     : m_parent(parent)
489     , m_testCtx(testCtx)
490     , m_config(config)
491     , m_eglDisplay(eglDisplay)
492     , m_eglContext(EGL_NO_CONTEXT)
493     , m_eglSurface(EGL_NO_SURFACE)
494     , m_coordBuffer(0)
495     , m_indexBuffer(0)
496     , m_texture(0)
497     , m_program(0)
498     , m_eglImage(EGL_NO_IMAGE_KHR)
499 {
500     const Library &egl = m_testCtx.getLibrary();
501 
502     if (m_config.textureType == TestConfig::TEXTURETYPE_IMAGE ||
503         m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE ||
504         m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE)
505     {
506         const vector<string> extensions = eglu::getDisplayExtensions(egl, m_eglDisplay);
507 
508         if (!de::contains(extensions.begin(), extensions.end(), "EGL_KHR_image_base") ||
509             !de::contains(extensions.begin(), extensions.end(), "EGL_KHR_gl_texture_2D_image"))
510             TCU_THROW(NotSupportedError, "EGL_KHR_image_base extensions not supported");
511     }
512 
513     m_eglContext = createEGLContext(m_testCtx, m_eglDisplay, eglConfig,
514                                     (share && parent ? parent->getEGLContext() : EGL_NO_CONTEXT));
515     m_eglSurface = createEGLSurface(m_testCtx, m_eglDisplay, eglConfig, config);
516 
517     EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
518 
519     {
520         const char *reqExts[] = {"GL_OES_EGL_image"};
521         m_testCtx.initGLFunctions(&m_gl, glu::ApiType::es(2, 0), DE_LENGTH_OF_ARRAY(reqExts), reqExts);
522     }
523 
524     if (m_config.textureType == TestConfig::TEXTURETYPE_IMAGE ||
525         m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE ||
526         m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE)
527     {
528         vector<string> glExts = de::splitString((const char *)m_gl.getString(GL_EXTENSIONS), ' ');
529 
530         if (!de::contains(glExts.begin(), glExts.end(), "GL_OES_EGL_image"))
531             TCU_THROW(NotSupportedError, "GL_OES_EGL_image extensions not supported");
532 
533         TCU_CHECK(m_gl.eglImageTargetTexture2DOES);
534     }
535 
536     if (m_config.useCoordBuffer && (!m_config.sharedCoordBuffer || !parent))
537         m_coordBuffer = createCoordBuffer(m_gl, m_config);
538     else if (m_config.useCoordBuffer && m_config.sharedCoordBuffer)
539         m_coordBuffer = parent->getCoordBuffer();
540     else
541         createCoordData(m_coordData, m_config);
542 
543     if (m_config.useIndexBuffer && (!m_config.sharedIndexBuffer || !parent))
544         m_indexBuffer = createIndexBuffer(m_gl, m_config);
545     else if (m_config.useIndexBuffer && m_config.sharedIndexBuffer)
546         m_indexBuffer = parent->getIndexBuffer();
547     else if (m_config.useIndices)
548         createIndexData(m_indexData, m_config);
549 
550     if (m_config.useTexture)
551     {
552         if (m_config.textureType == TestConfig::TEXTURETYPE_TEXTURE)
553             m_texture = createTexture(m_gl, m_config);
554         else if (m_config.textureType == TestConfig::TEXTURETYPE_SHARED_TEXTURE)
555         {
556             if (parent)
557                 m_texture = parent->getTexture();
558             else
559                 m_texture = createTexture(m_gl, m_config);
560         }
561         else if (m_config.textureType == TestConfig::TEXTURETYPE_IMAGE)
562         {
563             m_eglImage = createEGLImage();
564             m_texture  = createTextureFromImage(m_eglImage);
565         }
566         else if (m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE)
567         {
568             if (parent)
569                 m_eglImage = parent->getEGLImage();
570             else
571                 m_eglImage = createEGLImage();
572 
573             m_texture = createTextureFromImage(m_eglImage);
574         }
575         else if (m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE)
576         {
577             if (parent)
578                 m_texture = parent->getTexture();
579             else
580             {
581                 m_eglImage = createEGLImage();
582                 m_texture  = createTextureFromImage(m_eglImage);
583             }
584         }
585     }
586 
587     if (!m_config.sharedProgram || !parent)
588         m_program = createProgram(m_gl, m_config);
589     else if (m_config.sharedProgram)
590         m_program = parent->getProgram();
591 
592     m_coordLoc = m_gl.getAttribLocation(m_program, "a_coord");
593 
594     if (m_config.useTexture)
595         m_textureLoc = m_gl.getUniformLocation(m_program, "u_sampler");
596 
597     EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
598 }
599 
createEGLImage(void)600 EGLImageKHR TestContext::createEGLImage(void)
601 {
602     GLuint sourceTexture = createTexture(m_gl, m_config);
603 
604     try
605     {
606         const Library &egl        = m_testCtx.getLibrary();
607         const EGLint attribList[] = {EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE};
608 
609         EGLImageKHR image = egl.createImageKHR(m_eglDisplay, m_eglContext, EGL_GL_TEXTURE_2D_KHR,
610                                                (EGLClientBuffer)(uintptr_t)sourceTexture, attribList);
611         EGLU_CHECK_MSG(egl, "eglCreateImageKHR()");
612 
613         m_gl.deleteTextures(1, &sourceTexture);
614         GLU_EXPECT_NO_ERROR(m_gl.getError(), "eglCreateImageKHR()");
615 
616         return image;
617     }
618     catch (...)
619     {
620         m_gl.deleteTextures(1, &sourceTexture);
621         throw;
622     }
623 }
624 
createTextureFromImage(EGLImageKHR image)625 GLuint TestContext::createTextureFromImage(EGLImageKHR image)
626 {
627     GLuint texture = 0;
628 
629     try
630     {
631         m_gl.genTextures(1, &texture);
632         m_gl.bindTexture(GL_TEXTURE_2D, texture);
633         m_gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D, image);
634         m_gl.bindTexture(GL_TEXTURE_2D, 0);
635         GLU_EXPECT_NO_ERROR(m_gl.getError(), "Creating texture from image");
636 
637         return texture;
638     }
639     catch (...)
640     {
641         m_gl.deleteTextures(1, &texture);
642         throw;
643     }
644 }
645 
~TestContext(void)646 TestContext::~TestContext(void)
647 {
648     const Library &egl = m_testCtx.getLibrary();
649 
650     EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
651 
652     if (m_parent == DE_NULL && m_eglImage)
653         EGLU_CHECK_CALL(egl, destroyImageKHR(m_eglDisplay, m_eglImage));
654 
655     EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
656     EGLU_CHECK_CALL(egl, destroyContext(m_eglDisplay, m_eglContext));
657     EGLU_CHECK_CALL(egl, destroySurface(m_eglDisplay, m_eglSurface));
658 }
659 
render(void)660 void TestContext::render(void)
661 {
662     const Library &egl = m_testCtx.getLibrary();
663 
664     egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
665 
666     for (int frameNdx = 0; frameNdx < m_config.frameCount; frameNdx++)
667     {
668         m_gl.clearColor(0.75f, 0.6f, 0.5f, 1.0f);
669         m_gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
670 
671         for (int callNdx = 0; callNdx < m_config.drawCallCount; callNdx++)
672         {
673             m_gl.useProgram(m_program);
674             m_gl.enableVertexAttribArray(m_coordLoc);
675 
676             if (m_config.useCoordBuffer)
677             {
678                 m_gl.bindBuffer(GL_ARRAY_BUFFER, m_coordBuffer);
679                 m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
680                 m_gl.bindBuffer(GL_ARRAY_BUFFER, 0);
681             }
682             else
683                 m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, &(m_coordData[0]));
684 
685             if (m_config.useTexture)
686             {
687                 m_gl.bindTexture(GL_TEXTURE_2D, m_texture);
688                 m_gl.uniform1i(m_textureLoc, 0);
689             }
690 
691             if (m_config.useIndices)
692             {
693                 if (m_config.useIndexBuffer)
694                 {
695                     m_gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
696                     m_gl.drawElements(GL_TRIANGLES, m_config.triangleCount, GL_UNSIGNED_SHORT, 0);
697                 }
698                 else
699                     m_gl.drawElements(GL_TRIANGLES, m_config.triangleCount, GL_UNSIGNED_SHORT, &(m_indexData[0]));
700             }
701             else
702                 m_gl.drawArrays(GL_TRIANGLES, 0, m_config.triangleCount);
703 
704             if (m_config.useTexture)
705                 m_gl.bindTexture(GL_TEXTURE_2D, 0);
706 
707             m_gl.disableVertexAttribArray(m_coordLoc);
708 
709             m_gl.useProgram(0);
710         }
711 
712         egl.swapBuffers(m_eglDisplay, m_eglSurface);
713     }
714 
715     m_gl.finish();
716     GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFinish()");
717     EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
718 }
719 
720 class TestThread : de::Thread
721 {
722 public:
723     TestThread(const vector<TestContext *> contexts, const Library &egl);
724     ~TestThread(void);
725 
726     void start(void);
727     void join(void);
728 
resultOk(void)729     bool resultOk(void)
730     {
731         return m_isOk;
732     }
733 
734 private:
735     vector<TestContext *> m_contexts;
736     const Library &m_egl;
737     bool m_isOk;
738     string m_errorString;
739 
740     uint64_t m_beginTimeUs;
741     uint64_t m_endTimeUs;
742 
743     uint64_t m_joinBeginUs;
744     uint64_t m_joinEndUs;
745 
746     uint64_t m_startBeginUs;
747     uint64_t m_startEndUs;
748 
749     virtual void run(void);
750 
751     TestThread &operator=(const TestThread &);
752     TestThread(const TestThread &);
753 };
754 
TestThread(const vector<TestContext * > contexts,const Library & egl)755 TestThread::TestThread(const vector<TestContext *> contexts, const Library &egl)
756     : m_contexts(contexts)
757     , m_egl(egl)
758     , m_isOk(false)
759     , m_errorString("")
760     , m_beginTimeUs(0)
761     , m_endTimeUs(0)
762     , m_joinBeginUs(0)
763     , m_joinEndUs(0)
764     , m_startBeginUs(0)
765     , m_startEndUs(0)
766 {
767 }
768 
~TestThread(void)769 TestThread::~TestThread(void)
770 {
771     m_contexts.clear();
772 }
773 
start(void)774 void TestThread::start(void)
775 {
776     m_startBeginUs = deGetMicroseconds();
777     de::Thread::start();
778     m_startEndUs = deGetMicroseconds();
779 }
780 
join(void)781 void TestThread::join(void)
782 {
783     m_joinBeginUs = deGetMicroseconds();
784     de::Thread::join();
785     m_joinEndUs = deGetMicroseconds();
786 }
787 
run(void)788 void TestThread::run(void)
789 {
790     try
791     {
792         m_beginTimeUs = deGetMicroseconds();
793 
794         for (int contextNdx = 0; contextNdx < (int)m_contexts.size(); contextNdx++)
795             m_contexts[contextNdx]->render();
796 
797         m_isOk      = true;
798         m_endTimeUs = deGetMicroseconds();
799     }
800     catch (const std::runtime_error &error)
801     {
802         m_isOk        = false;
803         m_errorString = error.what();
804     }
805     catch (...)
806     {
807         m_isOk        = false;
808         m_errorString = "Got unknown exception";
809     }
810 
811     m_egl.releaseThread();
812 }
813 
814 class SharedRenderingPerfCase : public TestCase
815 {
816 public:
817     SharedRenderingPerfCase(EglTestContext &eglTestCtx, const TestConfig &config, const char *name,
818                             const char *description);
819     ~SharedRenderingPerfCase(void);
820 
821     void init(void);
822     void deinit(void);
823     IterateResult iterate(void);
824 
825 private:
826     TestConfig m_config;
827     const int m_iterationCount;
828 
829     EGLDisplay m_display;
830     vector<TestContext *> m_contexts;
831     vector<uint64_t> m_results;
832 
833     SharedRenderingPerfCase &operator=(const SharedRenderingPerfCase &);
834     SharedRenderingPerfCase(const SharedRenderingPerfCase &);
835 };
836 
SharedRenderingPerfCase(EglTestContext & eglTestCtx,const TestConfig & config,const char * name,const char * description)837 SharedRenderingPerfCase::SharedRenderingPerfCase(EglTestContext &eglTestCtx, const TestConfig &config, const char *name,
838                                                  const char *description)
839     : TestCase(eglTestCtx, tcu::NODETYPE_PERFORMANCE, name, description)
840     , m_config(config)
841     , m_iterationCount(30)
842     , m_display(EGL_NO_DISPLAY)
843 {
844 }
845 
~SharedRenderingPerfCase(void)846 SharedRenderingPerfCase::~SharedRenderingPerfCase(void)
847 {
848     deinit();
849 }
850 
init(void)851 void SharedRenderingPerfCase::init(void)
852 {
853     m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
854 
855     {
856         const Library &egl        = m_eglTestCtx.getLibrary();
857         const EGLint attribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
858                                      EGL_NONE};
859         EGLConfig eglConfig       = eglu::chooseSingleConfig(egl, m_display, attribList);
860 
861         // Create contexts and resources
862         for (int threadNdx = 0; threadNdx < m_config.threadCount * m_config.perThreadContextCount; threadNdx++)
863             m_contexts.push_back(new TestContext(m_eglTestCtx, m_display, eglConfig, m_config, m_config.sharedContexts,
864                                                  (threadNdx == 0 ? DE_NULL : m_contexts[threadNdx - 1])));
865     }
866 }
867 
deinit(void)868 void SharedRenderingPerfCase::deinit(void)
869 {
870     // Destroy resources and contexts
871     for (int threadNdx = 0; threadNdx < (int)m_contexts.size(); threadNdx++)
872     {
873         delete m_contexts[threadNdx];
874         m_contexts[threadNdx] = DE_NULL;
875     }
876 
877     m_contexts.clear();
878     m_results.clear();
879 
880     if (m_display != EGL_NO_DISPLAY)
881     {
882         m_eglTestCtx.getLibrary().terminate(m_display);
883         m_display = EGL_NO_DISPLAY;
884     }
885 }
886 
887 namespace
888 {
889 
createThreads(vector<TestThread * > & threads,int threadCount,int perThreadContextCount,vector<TestContext * > & contexts,const Library & egl)890 void createThreads(vector<TestThread *> &threads, int threadCount, int perThreadContextCount,
891                    vector<TestContext *> &contexts, const Library &egl)
892 {
893     DE_ASSERT(threadCount * perThreadContextCount == (int)contexts.size());
894     DE_ASSERT(threads.empty());
895 
896     vector<TestContext *> threadContexts;
897 
898     for (int threadNdx = 0; threadNdx < threadCount; threadNdx++)
899     {
900         for (int contextNdx = 0; contextNdx < perThreadContextCount; contextNdx++)
901             threadContexts.push_back(contexts[threadNdx * perThreadContextCount + contextNdx]);
902 
903         threads.push_back(new TestThread(threadContexts, egl));
904 
905         threadContexts.clear();
906     }
907 }
908 
destroyThreads(vector<TestThread * > & threads)909 void destroyThreads(vector<TestThread *> &threads)
910 {
911     for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
912     {
913         delete threads[threadNdx];
914         threads[threadNdx] = DE_NULL;
915     }
916 
917     threads.clear();
918 }
919 
startThreads(vector<TestThread * > & threads)920 void startThreads(vector<TestThread *> &threads)
921 {
922     for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
923         threads[threadNdx]->start();
924 }
925 
joinThreads(vector<TestThread * > & threads)926 void joinThreads(vector<TestThread *> &threads)
927 {
928     for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
929         threads[threadNdx]->join();
930 }
931 
threadResultsOk(const vector<TestThread * > & threads)932 bool threadResultsOk(const vector<TestThread *> &threads)
933 {
934     for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
935     {
936         if (!threads[threadNdx]->resultOk())
937             return false;
938     }
939 
940     return true;
941 }
942 
logAndSetResults(tcu::TestContext & testCtx,const vector<uint64_t> & r)943 void logAndSetResults(tcu::TestContext &testCtx, const vector<uint64_t> &r)
944 {
945     TestLog &log               = testCtx.getLog();
946     vector<uint64_t> resultsUs = r;
947     uint64_t sum               = 0;
948     uint64_t average;
949     uint64_t median;
950     double deviation;
951 
952     log << TestLog::SampleList("Result", "Result") << TestLog::SampleInfo
953         << TestLog::ValueInfo("Time", "Time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE) << TestLog::EndSampleInfo;
954 
955     for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++)
956         log << TestLog::Sample << int64_t(resultsUs[resultNdx]) << TestLog::EndSample;
957 
958     log << TestLog::EndSampleList;
959 
960     std::sort(resultsUs.begin(), resultsUs.end());
961 
962     for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++)
963         sum += resultsUs[resultNdx];
964 
965     average = sum / resultsUs.size();
966     median  = resultsUs[resultsUs.size() / 2];
967 
968     deviation = 0.0;
969     for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++)
970         deviation += (double)((resultsUs[resultNdx] - average) * (resultsUs[resultNdx] - average));
971 
972     deviation = std::sqrt(deviation / (double)resultsUs.size());
973 
974     {
975         tcu::ScopedLogSection section(log, "Statistics from results", "Statistics from results");
976 
977         log << TestLog::Message << "Average: " << ((double)average / 1000.0) << "ms\n"
978             << "Standard deviation: " << ((double)deviation / 1000.0) << "ms\n"
979             << "Standard error of mean: " << (((double)deviation / std::sqrt((double)resultsUs.size())) / 1000.0)
980             << "ms\n"
981             << "Median: " << ((double)median / 1000.0) << "ms\n"
982             << TestLog::EndMessage;
983     }
984 
985     testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)((double)average / 1000.0), 2).c_str());
986 }
987 
logTestConfig(TestLog & log,const TestConfig & config)988 void logTestConfig(TestLog &log, const TestConfig &config)
989 {
990     tcu::ScopedLogSection threadSection(log, "Test info", "Test information");
991 
992     log << TestLog::Message << "Total triangles rendered: : "
993         << config.triangleCount * config.drawCallCount * config.frameCount * config.perThreadContextCount *
994                config.threadCount
995         << TestLog::EndMessage;
996     log << TestLog::Message << "Number of threads: " << config.threadCount << TestLog::EndMessage;
997     log << TestLog::Message << "Number of contexts used to render with each thread: " << config.perThreadContextCount
998         << TestLog::EndMessage;
999     log << TestLog::Message << "Number of frames rendered with each context: " << config.frameCount
1000         << TestLog::EndMessage;
1001     log << TestLog::Message << "Number of draw calls performed by each frame: " << config.drawCallCount
1002         << TestLog::EndMessage;
1003     log << TestLog::Message << "Number of triangles rendered by each draw call: " << config.triangleCount
1004         << TestLog::EndMessage;
1005 
1006     if (config.sharedContexts)
1007         log << TestLog::Message << "Shared contexts." << TestLog::EndMessage;
1008     else
1009         log << TestLog::Message << "No shared contexts." << TestLog::EndMessage;
1010 
1011     if (config.useCoordBuffer)
1012         log << TestLog::Message << (config.sharedCoordBuffer ? "Shared " : "") << "Coordinate buffer"
1013             << TestLog::EndMessage;
1014     else
1015         log << TestLog::Message << "Coordinates from pointer" << TestLog::EndMessage;
1016 
1017     if (config.useIndices)
1018         log << TestLog::Message << "Using glDrawElements with indices from "
1019             << (config.sharedIndexBuffer ? "shared " : "") << (config.useIndexBuffer ? "buffer." : "pointer.")
1020             << TestLog::EndMessage;
1021 
1022     if (config.useTexture)
1023     {
1024         if (config.textureType == TestConfig::TEXTURETYPE_TEXTURE)
1025             log << TestLog::Message << "Use texture." << TestLog::EndMessage;
1026         else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_TEXTURE)
1027             log << TestLog::Message << "Use shared texture." << TestLog::EndMessage;
1028         else if (config.textureType == TestConfig::TEXTURETYPE_IMAGE)
1029             log << TestLog::Message << "Use texture created from EGLImage." << TestLog::EndMessage;
1030         else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE)
1031             log << TestLog::Message << "Use texture created from shared EGLImage." << TestLog::EndMessage;
1032         else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE)
1033             log << TestLog::Message << "Use shared texture created from EGLImage." << TestLog::EndMessage;
1034         else
1035             DE_ASSERT(false);
1036 
1037         log << TestLog::Message << "Texture size: " << config.textureWidth << "x" << config.textureHeight
1038             << TestLog::EndMessage;
1039     }
1040 
1041     if (config.sharedProgram)
1042         log << TestLog::Message << "Shared program." << TestLog::EndMessage;
1043 
1044     log << TestLog::Message << "Surface size: " << config.surfaceWidth << "x" << config.surfaceHeight
1045         << TestLog::EndMessage;
1046 }
1047 
1048 } // namespace
1049 
iterate(void)1050 TestCase::IterateResult SharedRenderingPerfCase::iterate(void)
1051 {
1052     uint64_t beginTimeUs;
1053     uint64_t endTimeUs;
1054     vector<TestThread *> threads;
1055 
1056     if (m_results.empty())
1057         logTestConfig(m_testCtx.getLog(), m_config);
1058 
1059     createThreads(threads, m_config.threadCount, m_config.perThreadContextCount, m_contexts, m_eglTestCtx.getLibrary());
1060 
1061     beginTimeUs = deGetMicroseconds();
1062 
1063     startThreads(threads);
1064     joinThreads(threads);
1065 
1066     endTimeUs = deGetMicroseconds();
1067 
1068     if (!threadResultsOk(threads))
1069     {
1070         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1071         return STOP;
1072     }
1073 
1074     destroyThreads(threads);
1075 
1076     m_results.push_back(endTimeUs - beginTimeUs);
1077 
1078     if ((int)m_results.size() == m_iterationCount)
1079     {
1080         logAndSetResults(m_testCtx, m_results);
1081         return STOP;
1082     }
1083     else
1084         return CONTINUE;
1085 }
1086 
createTestName(int threads,int perThreadContextCount)1087 string createTestName(int threads, int perThreadContextCount)
1088 {
1089     std::ostringstream stream;
1090 
1091     stream << threads << (threads == 1 ? "_thread_" : "_threads_") << perThreadContextCount
1092            << (perThreadContextCount == 1 ? "_context" : "_contexts");
1093 
1094     return stream.str();
1095 }
1096 
1097 } // namespace
1098 
GLES2SharedRenderingPerfTests(EglTestContext & eglTestCtx)1099 GLES2SharedRenderingPerfTests::GLES2SharedRenderingPerfTests(EglTestContext &eglTestCtx)
1100     : TestCaseGroup(eglTestCtx, "gles2_shared_render", "")
1101 {
1102 }
1103 
init(void)1104 void GLES2SharedRenderingPerfTests::init(void)
1105 {
1106     TestConfig basicConfig;
1107 
1108     basicConfig.threadCount           = 1;
1109     basicConfig.perThreadContextCount = 1;
1110 
1111     basicConfig.sharedContexts = true;
1112     basicConfig.frameCount     = 10;
1113     basicConfig.drawCallCount  = 10;
1114     basicConfig.triangleCount  = 100;
1115 
1116     basicConfig.useCoordBuffer    = true;
1117     basicConfig.sharedCoordBuffer = false;
1118 
1119     basicConfig.useIndices        = true;
1120     basicConfig.useIndexBuffer    = true;
1121     basicConfig.sharedIndexBuffer = false;
1122 
1123     basicConfig.useTexture  = true;
1124     basicConfig.textureType = TestConfig::TEXTURETYPE_TEXTURE;
1125 
1126     basicConfig.sharedProgram = false;
1127 
1128     basicConfig.textureWidth  = 128;
1129     basicConfig.textureHeight = 128;
1130 
1131     basicConfig.surfaceWidth  = 256;
1132     basicConfig.surfaceHeight = 256;
1133 
1134     const int threadCounts[]           = {1, 2, 4};
1135     const int perThreadContextCounts[] = {1, 2, 4};
1136 
1137     // Add no sharing tests
1138     {
1139         TestCaseGroup *sharedNoneGroup =
1140             new TestCaseGroup(m_eglTestCtx, "no_shared_context", "Tests without sharing contexts.");
1141 
1142         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1143         {
1144             int threadCount = threadCounts[threadCountNdx];
1145 
1146             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1147                  contextCountNdx++)
1148             {
1149                 int contextCount = perThreadContextCounts[contextCountNdx];
1150 
1151                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1152                     continue;
1153 
1154                 TestConfig config            = basicConfig;
1155                 config.threadCount           = threadCount;
1156                 config.perThreadContextCount = contextCount;
1157                 config.sharedContexts        = false;
1158 
1159                 {
1160                     TestConfig smallConfig    = config;
1161                     smallConfig.triangleCount = 1;
1162                     smallConfig.drawCallCount = 1000;
1163                     smallConfig.frameCount    = 10;
1164 
1165                     if (threadCount * contextCount == 1)
1166                         smallConfig.frameCount *= 4;
1167 
1168                     sharedNoneGroup->addChild(new SharedRenderingPerfCase(
1169                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1170                         ""));
1171                 }
1172 
1173                 {
1174                     TestConfig bigConfig    = config;
1175                     bigConfig.triangleCount = 1000;
1176                     bigConfig.drawCallCount = 1;
1177                     bigConfig.frameCount    = 10;
1178 
1179                     if (threadCount * contextCount == 1)
1180                         bigConfig.frameCount *= 4;
1181 
1182                     sharedNoneGroup->addChild(new SharedRenderingPerfCase(
1183                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1184                         ""));
1185                 }
1186             }
1187         }
1188 
1189         addChild(sharedNoneGroup);
1190     }
1191 
1192     // Add no resource sharing tests
1193     {
1194         TestCaseGroup *sharedNoneGroup =
1195             new TestCaseGroup(m_eglTestCtx, "no_shared_resource", "Tests without shared resources.");
1196 
1197         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1198         {
1199             int threadCount = threadCounts[threadCountNdx];
1200 
1201             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1202                  contextCountNdx++)
1203             {
1204                 int contextCount = perThreadContextCounts[contextCountNdx];
1205 
1206                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1207                     continue;
1208 
1209                 TestConfig config            = basicConfig;
1210                 config.threadCount           = threadCount;
1211                 config.perThreadContextCount = contextCount;
1212 
1213                 {
1214                     TestConfig smallConfig    = config;
1215                     smallConfig.triangleCount = 1;
1216                     smallConfig.drawCallCount = 1000;
1217                     smallConfig.frameCount    = 10;
1218 
1219                     if (threadCount * contextCount == 1)
1220                         smallConfig.frameCount *= 4;
1221 
1222                     sharedNoneGroup->addChild(new SharedRenderingPerfCase(
1223                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1224                         ""));
1225                 }
1226 
1227                 {
1228                     TestConfig bigConfig    = config;
1229                     bigConfig.triangleCount = 1000;
1230                     bigConfig.drawCallCount = 1;
1231                     bigConfig.frameCount    = 10;
1232 
1233                     if (threadCount * contextCount == 1)
1234                         bigConfig.frameCount *= 4;
1235 
1236                     sharedNoneGroup->addChild(new SharedRenderingPerfCase(
1237                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1238                         ""));
1239                 }
1240             }
1241         }
1242 
1243         addChild(sharedNoneGroup);
1244     }
1245 
1246     // Add shared coord buffer tests
1247     {
1248         TestCaseGroup *sharedCoordBufferGroup =
1249             new TestCaseGroup(m_eglTestCtx, "shared_coord_buffer", "Shared coordinate bufffer");
1250 
1251         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1252         {
1253             int threadCount = threadCounts[threadCountNdx];
1254 
1255             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1256                  contextCountNdx++)
1257             {
1258                 int contextCount = perThreadContextCounts[contextCountNdx];
1259 
1260                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1261                     continue;
1262 
1263                 TestConfig config            = basicConfig;
1264                 config.sharedCoordBuffer     = true;
1265                 config.threadCount           = threadCount;
1266                 config.perThreadContextCount = contextCount;
1267 
1268                 {
1269                     TestConfig smallConfig    = config;
1270                     smallConfig.triangleCount = 1;
1271                     smallConfig.drawCallCount = 1000;
1272                     smallConfig.frameCount    = 10;
1273 
1274                     if (threadCount * contextCount == 1)
1275                         smallConfig.frameCount *= 4;
1276 
1277                     sharedCoordBufferGroup->addChild(new SharedRenderingPerfCase(
1278                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1279                         ""));
1280                 }
1281 
1282                 {
1283                     TestConfig bigConfig    = config;
1284                     bigConfig.triangleCount = 1000;
1285                     bigConfig.drawCallCount = 1;
1286                     bigConfig.frameCount    = 10;
1287 
1288                     if (threadCount * contextCount == 1)
1289                         bigConfig.frameCount *= 4;
1290 
1291                     sharedCoordBufferGroup->addChild(new SharedRenderingPerfCase(
1292                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1293                         ""));
1294                 }
1295             }
1296         }
1297 
1298         addChild(sharedCoordBufferGroup);
1299     }
1300 
1301     // Add shared index buffer tests
1302     {
1303         TestCaseGroup *sharedIndexBufferGroup =
1304             new TestCaseGroup(m_eglTestCtx, "shared_index_buffer", "Shared index bufffer");
1305 
1306         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1307         {
1308             int threadCount = threadCounts[threadCountNdx];
1309 
1310             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1311                  contextCountNdx++)
1312             {
1313                 int contextCount = perThreadContextCounts[contextCountNdx];
1314 
1315                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1316                     continue;
1317 
1318                 TestConfig config            = basicConfig;
1319                 config.sharedIndexBuffer     = true;
1320                 config.threadCount           = threadCount;
1321                 config.perThreadContextCount = contextCount;
1322 
1323                 {
1324                     TestConfig smallConfig    = config;
1325                     smallConfig.triangleCount = 1;
1326                     smallConfig.drawCallCount = 1000;
1327                     smallConfig.frameCount    = 10;
1328 
1329                     if (threadCount * contextCount == 1)
1330                         smallConfig.frameCount *= 4;
1331 
1332                     sharedIndexBufferGroup->addChild(new SharedRenderingPerfCase(
1333                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1334                         ""));
1335                 }
1336 
1337                 {
1338                     TestConfig bigConfig    = config;
1339                     bigConfig.triangleCount = 1000;
1340                     bigConfig.drawCallCount = 1;
1341                     bigConfig.frameCount    = 10;
1342 
1343                     if (threadCount * contextCount == 1)
1344                         bigConfig.frameCount *= 4;
1345 
1346                     sharedIndexBufferGroup->addChild(new SharedRenderingPerfCase(
1347                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1348                         ""));
1349                 }
1350             }
1351         }
1352 
1353         addChild(sharedIndexBufferGroup);
1354     }
1355 
1356     // Add shared texture tests
1357     {
1358         TestCaseGroup *sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_texture", "Shared texture tests.");
1359 
1360         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1361         {
1362             int threadCount = threadCounts[threadCountNdx];
1363 
1364             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1365                  contextCountNdx++)
1366             {
1367                 int contextCount = perThreadContextCounts[contextCountNdx];
1368 
1369                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1370                     continue;
1371 
1372                 TestConfig config            = basicConfig;
1373                 config.textureType           = TestConfig::TEXTURETYPE_SHARED_TEXTURE;
1374                 config.threadCount           = threadCount;
1375                 config.perThreadContextCount = contextCount;
1376 
1377                 {
1378                     TestConfig smallConfig    = config;
1379                     smallConfig.triangleCount = 1;
1380                     smallConfig.drawCallCount = 1000;
1381                     smallConfig.frameCount    = 10;
1382 
1383                     if (threadCount * contextCount == 1)
1384                         smallConfig.frameCount *= 4;
1385 
1386                     sharedTextureGroup->addChild(new SharedRenderingPerfCase(
1387                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1388                         ""));
1389                 }
1390 
1391                 {
1392                     TestConfig bigConfig    = config;
1393                     bigConfig.triangleCount = 1000;
1394                     bigConfig.drawCallCount = 1;
1395                     bigConfig.frameCount    = 10;
1396 
1397                     if (threadCount * contextCount == 1)
1398                         bigConfig.frameCount *= 4;
1399 
1400                     sharedTextureGroup->addChild(new SharedRenderingPerfCase(
1401                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1402                         ""));
1403                 }
1404             }
1405         }
1406 
1407         addChild(sharedTextureGroup);
1408     }
1409 
1410     // Add shared program tests
1411     {
1412         TestCaseGroup *sharedProgramGroup = new TestCaseGroup(m_eglTestCtx, "shared_program", "Shared program tests.");
1413 
1414         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1415         {
1416             int threadCount = threadCounts[threadCountNdx];
1417 
1418             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1419                  contextCountNdx++)
1420             {
1421                 int contextCount = perThreadContextCounts[contextCountNdx];
1422 
1423                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1424                     continue;
1425 
1426                 TestConfig config            = basicConfig;
1427                 config.sharedProgram         = true;
1428                 config.threadCount           = threadCount;
1429                 config.perThreadContextCount = contextCount;
1430 
1431                 {
1432                     TestConfig smallConfig    = config;
1433                     smallConfig.triangleCount = 1;
1434                     smallConfig.drawCallCount = 1000;
1435                     smallConfig.frameCount    = 10;
1436 
1437                     if (threadCount * contextCount == 1)
1438                         smallConfig.frameCount *= 4;
1439 
1440                     sharedProgramGroup->addChild(new SharedRenderingPerfCase(
1441                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1442                         ""));
1443                 }
1444 
1445                 {
1446                     TestConfig bigConfig    = config;
1447                     bigConfig.triangleCount = 1000;
1448                     bigConfig.drawCallCount = 1;
1449                     bigConfig.frameCount    = 10;
1450 
1451                     if (threadCount * contextCount == 1)
1452                         bigConfig.frameCount *= 4;
1453 
1454                     sharedProgramGroup->addChild(new SharedRenderingPerfCase(
1455                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1456                         ""));
1457                 }
1458             }
1459         }
1460 
1461         addChild(sharedProgramGroup);
1462     }
1463 
1464     // Add shared all tests
1465     {
1466         TestCaseGroup *sharedallGroup = new TestCaseGroup(m_eglTestCtx, "shared_all", "Share all possible resources.");
1467 
1468         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1469         {
1470             int threadCount = threadCounts[threadCountNdx];
1471 
1472             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1473                  contextCountNdx++)
1474             {
1475                 int contextCount = perThreadContextCounts[contextCountNdx];
1476 
1477                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1478                     continue;
1479 
1480                 TestConfig config            = basicConfig;
1481                 config.sharedCoordBuffer     = true;
1482                 config.sharedIndexBuffer     = true;
1483                 config.sharedProgram         = true;
1484                 config.textureType           = TestConfig::TEXTURETYPE_SHARED_TEXTURE;
1485                 config.threadCount           = threadCount;
1486                 config.perThreadContextCount = contextCount;
1487 
1488                 {
1489                     TestConfig smallConfig    = config;
1490                     smallConfig.triangleCount = 1;
1491                     smallConfig.drawCallCount = 1000;
1492                     smallConfig.frameCount    = 10;
1493 
1494                     if (threadCount * contextCount == 1)
1495                         smallConfig.frameCount *= 4;
1496 
1497                     sharedallGroup->addChild(new SharedRenderingPerfCase(
1498                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1499                         ""));
1500                 }
1501 
1502                 {
1503                     TestConfig bigConfig    = config;
1504                     bigConfig.triangleCount = 1000;
1505                     bigConfig.drawCallCount = 1;
1506                     bigConfig.frameCount    = 10;
1507 
1508                     if (threadCount * contextCount == 1)
1509                         bigConfig.frameCount *= 4;
1510 
1511                     sharedallGroup->addChild(new SharedRenderingPerfCase(
1512                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1513                         ""));
1514                 }
1515             }
1516         }
1517 
1518         addChild(sharedallGroup);
1519     }
1520 
1521     // Add EGLImage tests
1522     {
1523         TestCaseGroup *sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "egl_image", "EGL image tests.");
1524 
1525         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1526         {
1527             int threadCount = threadCounts[threadCountNdx];
1528 
1529             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1530                  contextCountNdx++)
1531             {
1532                 int contextCount = perThreadContextCounts[contextCountNdx];
1533 
1534                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1535                     continue;
1536 
1537                 TestConfig config = basicConfig;
1538 
1539                 config.textureType           = TestConfig::TEXTURETYPE_IMAGE;
1540                 config.threadCount           = threadCount;
1541                 config.perThreadContextCount = contextCount;
1542                 config.sharedContexts        = false;
1543 
1544                 {
1545                     TestConfig smallConfig    = config;
1546                     smallConfig.triangleCount = 1;
1547                     smallConfig.drawCallCount = 1000;
1548                     smallConfig.frameCount    = 10;
1549 
1550                     if (threadCount * contextCount == 1)
1551                         smallConfig.frameCount *= 4;
1552 
1553                     sharedTextureGroup->addChild(new SharedRenderingPerfCase(
1554                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1555                         ""));
1556                 }
1557 
1558                 {
1559                     TestConfig bigConfig    = config;
1560                     bigConfig.triangleCount = 1000;
1561                     bigConfig.drawCallCount = 1;
1562                     bigConfig.frameCount    = 10;
1563 
1564                     if (threadCount * contextCount == 1)
1565                         bigConfig.frameCount *= 4;
1566 
1567                     sharedTextureGroup->addChild(new SharedRenderingPerfCase(
1568                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1569                         ""));
1570                 }
1571             }
1572         }
1573 
1574         addChild(sharedTextureGroup);
1575     }
1576 
1577     // Add shared EGLImage tests
1578     {
1579         TestCaseGroup *sharedTextureGroup =
1580             new TestCaseGroup(m_eglTestCtx, "shared_egl_image", "Shared EGLImage tests.");
1581 
1582         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1583         {
1584             int threadCount = threadCounts[threadCountNdx];
1585 
1586             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1587                  contextCountNdx++)
1588             {
1589                 int contextCount = perThreadContextCounts[contextCountNdx];
1590 
1591                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1592                     continue;
1593 
1594                 TestConfig config = basicConfig;
1595 
1596                 config.textureType           = TestConfig::TEXTURETYPE_SHARED_IMAGE;
1597                 config.threadCount           = threadCount;
1598                 config.perThreadContextCount = contextCount;
1599                 config.sharedContexts        = false;
1600 
1601                 {
1602                     TestConfig smallConfig    = config;
1603                     smallConfig.triangleCount = 1;
1604                     smallConfig.drawCallCount = 1000;
1605                     smallConfig.frameCount    = 10;
1606 
1607                     if (threadCount * contextCount == 1)
1608                         smallConfig.frameCount *= 4;
1609 
1610                     sharedTextureGroup->addChild(new SharedRenderingPerfCase(
1611                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1612                         ""));
1613                 }
1614 
1615                 {
1616                     TestConfig bigConfig    = config;
1617                     bigConfig.triangleCount = 1000;
1618                     bigConfig.drawCallCount = 1;
1619                     bigConfig.frameCount    = 10;
1620 
1621                     if (threadCount * contextCount == 1)
1622                         bigConfig.frameCount *= 4;
1623 
1624                     sharedTextureGroup->addChild(new SharedRenderingPerfCase(
1625                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1626                         ""));
1627                 }
1628             }
1629         }
1630 
1631         addChild(sharedTextureGroup);
1632     }
1633 
1634     // Shared EGLImage texture test
1635     {
1636         TestCaseGroup *sharedTextureGroup =
1637             new TestCaseGroup(m_eglTestCtx, "shared_egl_image_texture", "Shared EGLImage texture tests.");
1638 
1639         for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1640         {
1641             int threadCount = threadCounts[threadCountNdx];
1642 
1643             for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts);
1644                  contextCountNdx++)
1645             {
1646                 int contextCount = perThreadContextCounts[contextCountNdx];
1647 
1648                 if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1649                     continue;
1650 
1651                 TestConfig config            = basicConfig;
1652                 config.textureType           = TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE;
1653                 config.threadCount           = threadCount;
1654                 config.perThreadContextCount = contextCount;
1655 
1656                 {
1657                     TestConfig smallConfig    = config;
1658                     smallConfig.triangleCount = 1;
1659                     smallConfig.drawCallCount = 1000;
1660                     smallConfig.frameCount    = 10;
1661 
1662                     if (threadCount * contextCount == 1)
1663                         smallConfig.frameCount *= 4;
1664 
1665                     sharedTextureGroup->addChild(new SharedRenderingPerfCase(
1666                         m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(),
1667                         ""));
1668                 }
1669 
1670                 {
1671                     TestConfig bigConfig    = config;
1672                     bigConfig.triangleCount = 1000;
1673                     bigConfig.drawCallCount = 1;
1674                     bigConfig.frameCount    = 10;
1675 
1676                     if (threadCount * contextCount == 1)
1677                         bigConfig.frameCount *= 4;
1678 
1679                     sharedTextureGroup->addChild(new SharedRenderingPerfCase(
1680                         m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(),
1681                         ""));
1682                 }
1683             }
1684         }
1685 
1686         addChild(sharedTextureGroup);
1687     }
1688 }
1689 
1690 } // namespace egl
1691 } // namespace deqp
1692