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