Add packaging for TIZEN
[platform/upstream/VK-GL-CTS.git] / modules / egl / teglRobustnessTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL Module
3  * ---------------------------------------
4  *
5  * Copyright 2017 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 Robustness tests for KHR_robustness.
22  *//*--------------------------------------------------------------------*/
23
24 #include "teglRobustnessTests.hpp"
25
26 #include "tcuTestLog.hpp"
27 #include "tcuStringTemplate.hpp"
28
29 #include "egluConfigFilter.hpp"
30 #include "egluStrUtil.hpp"
31 #include "egluUtil.hpp"
32 #include "eglwLibrary.hpp"
33
34 #include "gluStrUtil.hpp"
35 #include "gluShaderProgram.hpp"
36 #include "gluDrawUtil.hpp"
37
38 #include "glwFunctions.hpp"
39 #include "glwEnums.hpp"
40
41 #include "deSTLUtil.hpp"
42 #include "deStringUtil.hpp"
43 #include "deThread.hpp"
44 #include "deSharedPtr.hpp"
45
46 #include <set>
47
48 using std::string;
49 using std::vector;
50 using std::set;
51 using tcu::TestLog;
52
53 using namespace eglw;
54
55 DE_STATIC_ASSERT(GL_RESET_NOTIFICATION_STRATEGY == 0x8256);
56 DE_STATIC_ASSERT(GL_LOSE_CONTEXT_ON_RESET               == 0x8252);
57 DE_STATIC_ASSERT(GL_NO_RESET_NOTIFICATION               == 0x8261);
58
59 namespace deqp
60 {
61 namespace egl
62 {
63 namespace
64 {
65
66 enum ContextResetType
67 {
68         CONTEXTRESETTYPE_INFINITE_LOOP,
69         CONTEXTRESETTYPE_SHADER_OOB,
70         CONTEXTRESETTYPE_FIXED_FUNC_OOB,
71 };
72
73 enum ShaderType
74 {
75         SHADERTYPE_VERT,
76         SHADERTYPE_FRAG,
77         SHADERTYPE_COMPUTE,
78         SHADERTYPE_VERT_AND_FRAG,
79 };
80
81 enum ReadWriteType
82 {
83         READWRITETYPE_READ,
84         READWRITETYPE_WRITE,
85 };
86
87 enum ResourceType
88 {
89         RESOURCETYPE_UBO,
90         RESOURCETYPE_SSBO,
91         RESOURCETYPE_LOCAL_ARRAY,
92 };
93
94 enum FixedFunctionType
95 {
96         FIXEDFUNCTIONTYPE_INDICES,
97         FIXEDFUNCTIONTYPE_VERTICES,
98 };
99
100 enum RobustAccessType
101 {
102         ROBUSTACCESS_TRUE,
103         ROBUSTACCESS_FALSE,
104 };
105
106 void requireEGLExtension (const Library& egl, EGLDisplay eglDisplay, const char* requiredExtension)
107 {
108         if (!eglu::hasExtension(egl, eglDisplay, requiredExtension))
109                 TCU_THROW(NotSupportedError, (string(requiredExtension) + " not supported").c_str());
110 }
111
112 bool isWindow (const eglu::CandidateConfig& c)
113 {
114         return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT;
115 }
116
117 template <deUint32 Type>
118 bool renderable (const eglu::CandidateConfig& c)
119 {
120         return (c.renderableType() & Type) == Type;
121 }
122
123 eglu::ConfigFilter getRenderableFilter (deUint32 bits)
124 {
125         switch (bits)
126         {
127                 case EGL_OPENGL_ES2_BIT:        return renderable<EGL_OPENGL_ES2_BIT>;
128                 case EGL_OPENGL_ES3_BIT:        return renderable<EGL_OPENGL_ES3_BIT>;
129                 case EGL_OPENGL_BIT:            return renderable<EGL_OPENGL_BIT>;
130                 default:
131                         DE_FATAL("Unknown EGL bitfied value");
132                         return renderable<0>;
133         }
134 }
135
136 const char* eglResetNotificationStrategyToString (EGLint strategy)
137 {
138         switch (strategy)
139         {
140                 case EGL_NO_RESET_NOTIFICATION_KHR:             return "EGL_NO_RESET_NOTIFICATION_KHR";
141                 case EGL_LOSE_CONTEXT_ON_RESET_KHR:             return "EGL_LOSE_CONTEXT_ON_RESET_KHR";
142                 default:
143                         return "<Unknown>";
144         }
145 }
146
147 void logAttribList (const EglTestContext& eglTestCtx, const EGLint* attribList)
148 {
149         const EGLint*           iter = &(attribList[0]);
150         std::ostringstream      attribListString;
151
152         while ((*iter) != EGL_NONE)
153         {
154                 switch (*iter)
155                 {
156                 //      case EGL_CONTEXT_CLIENT_VERSION:
157                         case EGL_CONTEXT_MAJOR_VERSION_KHR:
158                                 iter++;
159                                 attribListString << "EGL_CONTEXT_CLIENT_VERSION, " << (*iter) << ", ";
160                                 iter++;
161                                 break;
162
163                         case EGL_CONTEXT_MINOR_VERSION_KHR:
164                                 iter++;
165                                 attribListString << "EGL_CONTEXT_MINOR_VERSION_KHR, " << (*iter) << ", ";
166                                 iter++;
167                                 break;
168
169                         case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
170                                 iter++;
171                                 attribListString << "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, "
172                                                                  << eglResetNotificationStrategyToString(*iter) << ", ";
173                                 iter++;
174                                 break;
175
176                         case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
177                                 iter++;
178                                 attribListString << "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, "
179                                                                  << eglResetNotificationStrategyToString(*iter) << ", ";
180                                 iter++;
181                                 break;
182
183                         case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
184                                 iter++;
185                                 attribListString << "EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, ";
186
187                                 if (*iter == EGL_FALSE || *iter == EGL_TRUE)
188                                         attribListString << (*iter ? "EGL_TRUE" : "EGL_FALSE") << ", ";
189                                 else
190                                         attribListString << (*iter) << ", ";
191                                 iter++;
192                                 break;
193
194                         default:
195                                 DE_FATAL("Unsupported attribute");
196                 }
197         }
198
199         attribListString << "EGL_NONE";
200         eglTestCtx.getTestContext().getLog() << TestLog::Message
201                                                                                  << "EGL attrib list: { " << attribListString.str() << " }\n\n"
202                                                                                  << TestLog::EndMessage;
203 }
204
205 class RobustnessTestCase: public TestCase
206 {
207 public:
208         class Params
209         {
210         public:
211                                                         Params                                  (void) {};
212
213                                                         Params                                  (const string&                          name,
214                                                                                                          const string&                          description,
215                                                                                                          const RobustAccessType&        robustAccessType,
216                                                                                                          const ContextResetType&        contextResetType,
217                                                                                                          const FixedFunctionType&       fixedFunctionType);
218
219                                                         Params                                  (const string&                          name,
220                                                                                                          const string&                          description,
221                                                                                                          const ContextResetType&        contextResetType,
222                                                                                                          const ShaderType&                      shaderType);
223
224                                                         Params                                  (const string&                          name,
225                                                                                                          const string&                          description,
226                                                                                                          const RobustAccessType&        robustAccessType,
227                                                                                                          const ContextResetType&        contextResetType,
228                                                                                                          const ShaderType&                      shaderType,
229                                                                                                          const ResourceType&            resourceType,
230                                                                                                          const ReadWriteType&           readWriteType);
231
232                 const string&                           getName                                 (void) const { return m_name;                           }
233                 const string&                           getDescription                  (void) const { return m_description;            }
234                 const ContextResetType&         getContextResetType             (void) const { return m_contextResetType;       }
235                 const ShaderType&                       getShaderType                   (void) const { return m_shaderType;                     }
236                 const ResourceType&                     getResourceType                 (void) const { return m_resourceType;           }
237                 const ReadWriteType&            getReadWriteType                (void) const { return m_readWriteType;          }
238                 const FixedFunctionType&        getFixedFunctionType    (void) const { return m_fixedFunctionType;      }
239                 const RobustAccessType&         getRobustAccessType             (void) const { return m_robustAccessType;       }
240
241         private:
242                 string                          m_name;
243                 string                          m_description;
244                 RobustAccessType        m_robustAccessType;
245                 ContextResetType        m_contextResetType;
246                 ShaderType                      m_shaderType;
247                 ResourceType            m_resourceType;
248                 ReadWriteType           m_readWriteType;
249                 FixedFunctionType       m_fixedFunctionType;
250         };
251
252                         RobustnessTestCase                      (EglTestContext& eglTestCtx, const char* name, const char* description);
253                         RobustnessTestCase                      (EglTestContext& eglTestCtx, const char* name, const char* description, Params params);
254                         ~RobustnessTestCase                     (void);
255
256         void    checkRequiredEGLExtensions      (const EGLint* attribList);
257
258 protected:
259         Params                                  m_params;
260         EGLDisplay                              m_eglDisplay;
261         EGLConfig                               m_eglConfig;
262         EGLSurface                              m_eglSurface;
263
264 private:
265         void                                    init                                    (void);
266         void                                    deinit                                  (void);
267         void                                    initEGLSurface                  (void);
268         EGLConfig                               getEGLConfig                    (void);
269
270         eglu::NativeWindow*             m_window;
271 };
272
273 RobustnessTestCase::Params::Params (const string&                               name,
274                                                                         const string&                           description,
275                                                                         const RobustAccessType&         robustAccessType,
276                                                                         const ContextResetType&         contextResetType,
277                                                                         const FixedFunctionType&        fixedFunctionType)
278         : m_name                                (name)
279         , m_description                 (description)
280         , m_robustAccessType    (robustAccessType)
281         , m_contextResetType    (contextResetType)
282         , m_fixedFunctionType   (fixedFunctionType)
283 {
284 }
285
286 RobustnessTestCase::Params::Params (const string&                               name,
287                                                                         const string&                           description,
288                                                                         const ContextResetType&         contextResetType,
289                                                                         const ShaderType&                       shaderType)
290         : m_name                                (name)
291         , m_description                 (description)
292         , m_contextResetType    (contextResetType)
293         , m_shaderType                  (shaderType)
294 {
295 }
296
297 RobustnessTestCase::Params::Params (const string&                               name,
298                                                                         const string&                           description,
299                                                                         const RobustAccessType&         robustAccessType,
300                                                                         const ContextResetType&         contextResetType,
301                                                                         const ShaderType&                       shaderType,
302                                                                         const ResourceType&                     resourceType,
303                                                                         const ReadWriteType&            readWriteType)
304         : m_name                                (name)
305         , m_description                 (description)
306         , m_robustAccessType    (robustAccessType)
307         , m_contextResetType    (contextResetType)
308         , m_shaderType                  (shaderType)
309         , m_resourceType                (resourceType)
310         , m_readWriteType               (readWriteType)
311 {
312 }
313
314 RobustnessTestCase::RobustnessTestCase (EglTestContext& eglTestCtx, const char* name, const char* description)
315         : TestCase                      (eglTestCtx, name, description)
316         , m_eglDisplay          (EGL_NO_DISPLAY)
317         , m_eglConfig           (0)
318         , m_eglSurface          (EGL_NO_SURFACE)
319         , m_window                      (DE_NULL)
320 {
321 }
322
323 RobustnessTestCase::RobustnessTestCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
324         : TestCase                      (eglTestCtx, name, description)
325         , m_params                      (params)
326         , m_eglDisplay          (EGL_NO_DISPLAY)
327         , m_eglConfig           (0)
328         , m_eglSurface          (EGL_NO_SURFACE)
329         , m_window                      (DE_NULL)
330 {
331 }
332
333 RobustnessTestCase::~RobustnessTestCase (void)
334 {
335         deinit();
336 }
337
338 void RobustnessTestCase::init (void)
339 {
340         m_eglDisplay    = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
341         m_eglConfig             = getEGLConfig();
342
343         initEGLSurface();
344 }
345
346 void RobustnessTestCase::deinit (void)
347 {
348         const Library& egl = m_eglTestCtx.getLibrary();
349
350         if (m_eglSurface != EGL_NO_SURFACE)
351         {
352                 egl.destroySurface(m_eglDisplay, m_eglSurface);
353                 m_eglSurface = EGL_NO_SURFACE;
354         }
355         if (m_eglDisplay != EGL_NO_DISPLAY)
356         {
357                 egl.terminate(m_eglDisplay);
358                 m_eglDisplay = EGL_NO_DISPLAY;
359         }
360
361         delete m_window;
362         m_window = DE_NULL;
363 }
364
365 EGLConfig RobustnessTestCase::getEGLConfig (void)
366 {
367         eglu::FilterList filters;
368         filters << isWindow << getRenderableFilter(EGL_OPENGL_ES3_BIT);
369         return eglu::chooseSingleConfig(m_eglTestCtx.getLibrary(), m_eglDisplay, filters);
370 }
371
372 void RobustnessTestCase::initEGLSurface (void)
373 {
374         EGLU_CHECK_CALL(m_eglTestCtx.getLibrary(), bindAPI(EGL_OPENGL_ES_API));
375
376         const eglu::NativeWindowFactory& factory =      eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
377
378         const eglu::WindowParams        windowParams    =       eglu::WindowParams(256, 256, eglu::parseWindowVisibility(m_testCtx.getCommandLine()));
379         m_window                                                                        =       factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, m_eglConfig, DE_NULL, windowParams);
380         m_eglSurface                                                            =       eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, m_eglConfig, DE_NULL);
381 }
382
383 glu::ApiType paramsToApiType (const RobustnessTestCase::Params& params)
384 {
385         EGLint                          minorVersion    = 0;
386         if (params.getShaderType()               == SHADERTYPE_COMPUTE  ||
387                 params.getResourceType()         == RESOURCETYPE_SSBO   ||
388                 params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB)
389         {
390                 minorVersion = 1;
391         }
392
393         return glu::ApiType::es(3, minorVersion);
394 }
395
396 void RobustnessTestCase::checkRequiredEGLExtensions (const EGLint* attribList)
397 {
398         set<string>             requiredExtensions;
399         vector<string>  extensions                      = eglu::getDisplayExtensions(m_eglTestCtx.getLibrary(), m_eglDisplay);
400
401         {
402                 const EGLint* iter = attribList;
403
404                 while ((*iter) != EGL_NONE)
405                 {
406                         switch (*iter)
407                         {
408                                 case EGL_CONTEXT_MAJOR_VERSION_KHR: iter++;
409                                         iter++;
410                                         break;
411
412                                 case EGL_CONTEXT_MINOR_VERSION_KHR:
413                                         iter++;
414                                         requiredExtensions.insert("EGL_KHR_create_context");
415                                         iter++;
416                                         break;
417
418                                 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
419                                 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
420                                         iter++;
421                                         requiredExtensions.insert("EGL_EXT_create_context_robustness");
422                                         iter++;
423                                         break;
424
425                                 default:
426                                         DE_ASSERT(DE_FALSE);
427                         }
428                 }
429         }
430
431         for (std::set<string>::const_iterator reqExt = requiredExtensions.begin(); reqExt != requiredExtensions.end(); ++reqExt)
432         {
433                 if (!de::contains(extensions.begin(), extensions.end(), *reqExt))
434                 {
435                         const char* const extension = reqExt->c_str();
436                         requireEGLExtension(m_eglTestCtx.getLibrary(), m_eglDisplay, extension);
437                 }
438         }
439 }
440
441 void checkRequiredGLSupport (const glw::Functions& gl, glu::ApiType requiredApi)
442 {
443         if (!glu::hasExtension(gl, requiredApi, "GL_KHR_robustness") && !glu::hasExtension(gl, requiredApi, "GL_EXT_robustness"))
444         {
445                 TCU_THROW(NotSupportedError, (string("GL_KHR_robustness and GL_EXT_robustness") + " not supported").c_str());
446         }
447         else
448         {
449                 int realMinorVersion = 0;
450                 gl.getIntegerv(GL_MINOR_VERSION, &realMinorVersion);
451                 GLU_EXPECT_NO_ERROR(gl.getError(), "Get minor version failed");
452
453                 if (realMinorVersion < requiredApi.getMinorVersion())
454                         TCU_THROW(NotSupportedError, "Test case requires GLES 3.1");
455         }
456 }
457
458 void checkGLSupportForParams (const glw::Functions& gl, const RobustnessTestCase::Params& params)
459 {
460         int minorVersion = 0;
461         if (params.getShaderType()                == SHADERTYPE_COMPUTE ||
462                 params.getResourceType()          == RESOURCETYPE_SSBO  ||
463                 params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB)
464         {
465                 minorVersion = 1;
466         }
467         checkRequiredGLSupport(gl, glu::ApiType::es(3, minorVersion));
468 }
469
470 class RenderingContext
471 {
472 public:
473                                                         RenderingContext                                        (const EglTestContext&  eglTestCtx,
474                                                                                                                                  const EGLint*                  attribList,
475                                                                                                                                  const EGLConfig&               config,
476                                                                                                                                  const EGLDisplay&              display,
477                                                                                                                                  const EGLContext&              sharedContext);
478                                                         ~RenderingContext                                       (void);
479
480         void                                    initGLFunctions                                         (glw::Functions* gl, const glu::ApiType apiType);
481         void                                    makeCurrent                                                     (const EGLSurface& surface);
482         EGLContext                              getContext                                                      (void);
483
484 private:
485         const EglTestContext&   m_eglTestCtx;
486         const EGLint*                   m_attribList;
487         const EGLConfig&                m_config;
488         const EGLDisplay&               m_display;
489         const Library&                  m_egl;
490
491         EGLContext                              m_context;
492
493         void                                    createContext                                           (const EGLConfig& sharedConfig);
494         void                                    destroyContext                                          (void);
495
496                                                         RenderingContext                                        (const RenderingContext&);
497         RenderingContext&               operator=                                                       (const RenderingContext&);
498 };
499
500 RenderingContext::RenderingContext (const EglTestContext&        eglTestCtx,
501                                                                         const EGLint*                    attribList,
502                                                                         const EGLConfig&                 config,
503                                                                         const EGLDisplay&                display,
504                                                                         const EGLContext&                sharedContext)
505         : m_eglTestCtx          (eglTestCtx)
506         , m_attribList          (attribList)
507         , m_config                      (config)
508         , m_display                     (display)
509         , m_egl                         (eglTestCtx.getLibrary())
510         , m_context                     (EGL_NO_CONTEXT)
511 {
512         logAttribList(eglTestCtx, m_attribList);
513         createContext(sharedContext);
514 }
515
516 RenderingContext::~RenderingContext (void)
517 {
518         destroyContext();
519 }
520
521 void RenderingContext::createContext (const EGLConfig& sharedContext)
522 {
523         m_context = m_egl.createContext(m_display, m_config, sharedContext, m_attribList);
524         EGLU_CHECK_MSG(m_egl, "eglCreateContext()");
525 }
526
527 void RenderingContext::destroyContext (void)
528 {
529         EGLU_CHECK_CALL(m_eglTestCtx.getLibrary(), makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
530
531         if (m_context != EGL_NO_CONTEXT)
532                 m_egl.destroyContext(m_display, m_context);
533 }
534
535 void RenderingContext::makeCurrent (const EGLSurface& surface)
536 {
537         EGLU_CHECK_CALL(m_egl, makeCurrent(m_display, surface, surface, m_context));
538 }
539
540 void RenderingContext::initGLFunctions (glw::Functions *gl, const glu::ApiType apiType)
541 {
542         // \todo [2017-03-23 pyry] Current version has 2 somewhat ugly hacks:
543         //
544         // 1) Core functions are loaded twice. We need glGetString(i) to query supported
545         //    extensions to determine if we need to load EXT or KHR-suffixed robustness
546         //    functions. This could be fixed by exposing glw::FunctionLoader in EglTestContext
547         //    for example.
548         //
549         // 2) We assume that calling code will check for KHR_robustness or EXT_robustness
550         //    support after calling initGLFunctions(). We could move the check here.
551
552         m_eglTestCtx.initGLFunctions(gl, apiType);
553
554         {
555                 const char* const       robustnessExt   = glu::hasExtension(*gl, apiType, "GL_KHR_robustness") ? "GL_KHR_robustness" : "GL_EXT_robustness";
556                 const char* const       extensions[]    = { robustnessExt };
557
558                 m_eglTestCtx.initGLFunctions(gl, apiType, DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
559         }
560 }
561
562 EGLContext RenderingContext::getContext (void)
563 {
564         return m_context;
565 }
566
567 class ContextReset
568 {
569 public:
570                                                 ContextReset                            (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType);
571                                                 ContextReset                            (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType);
572                                                 ContextReset                            (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType);
573
574         virtual                         ~ContextReset                           (void) {};
575
576         virtual void            setup                                           (void) = 0;
577         virtual void            draw                                            (void) = 0;
578         virtual void            teardown                                        (void) = 0;
579
580         void                            finish                                          (void);
581         void                            createSyncObject                        (void);
582         glw::GLint                      getSyncStatus                           (void);
583
584         void                            beginQuery                                      (void);
585         void                            endQuery                                        (void);
586         glw::GLint                      getError                                        (void);
587         glw::GLint                      getGraphicsResetStatus          (void);
588         glw::GLuint                     getQueryAvailability            (void);
589
590         glw::GLsync                     getSyncObject                           (void) const { return m_sync; }
591         glw::GLuint                     getQueryID                                      (void) const { return m_queryID; }
592
593         glw::Functions&         m_gl;
594         tcu::TestLog&           m_log;
595         ShaderType                      m_shaderType;
596         ResourceType            m_resourceType;
597         ReadWriteType           m_readWriteType;
598         FixedFunctionType       m_fixedFunctionType;
599
600 private:
601                                                 ContextReset                            (const ContextReset&);
602         ContextReset&           operator=                                       (const ContextReset&);
603
604         glw::GLuint                     m_queryID;
605         glw::GLsync                     m_sync;
606 };
607
608 ContextReset::ContextReset (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType)
609         : m_gl                                  (gl)
610         , m_log                                 (log)
611         , m_fixedFunctionType   (fixedFunctionType)
612 {
613 }
614
615 ContextReset::ContextReset (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType)
616         : m_gl                          (gl)
617         , m_log                         (log)
618         , m_shaderType          (shaderType)
619         , m_resourceType        (resourceType)
620         , m_readWriteType       (readWriteType)
621 {
622 }
623
624 ContextReset::ContextReset (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType)
625         : m_gl                  (gl)
626         , m_log                 (log)
627         , m_shaderType  (shaderType)
628 {
629 }
630
631 void ContextReset::finish (void)
632 {
633         GLU_CHECK_GLW_CALL(m_gl, finish());
634 }
635
636 void ContextReset::createSyncObject (void)
637 {
638         m_sync = m_gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
639         GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFenceSync()");
640 }
641
642 glw::GLint ContextReset::getError (void)
643 {
644         glw::GLint error;
645         error = m_gl.getError();
646
647         return error;
648 }
649
650 glw::GLint ContextReset::getGraphicsResetStatus (void)
651 {
652         glw::GLint resetStatus;
653         resetStatus = m_gl.getGraphicsResetStatus();
654
655         return resetStatus;
656 }
657
658 glw::GLint ContextReset::getSyncStatus (void)
659 {
660         glw::GLint syncStatus;
661         m_gl.getSynciv(m_sync, GL_SYNC_STATUS, sizeof(glw::GLint), NULL, &syncStatus);
662
663         return syncStatus;
664 }
665
666 void ContextReset::beginQuery (void)
667 {
668         GLU_CHECK_GLW_CALL(m_gl, genQueries(1, &m_queryID));
669         GLU_CHECK_GLW_CALL(m_gl, beginQuery(GL_ANY_SAMPLES_PASSED, m_queryID));
670 }
671
672 void ContextReset::endQuery (void)
673 {
674         GLU_CHECK_GLW_CALL(m_gl, endQuery(GL_ANY_SAMPLES_PASSED));
675 }
676
677 glw::GLuint ContextReset::getQueryAvailability (void)
678 {
679         glw::GLuint queryReady = GL_FALSE;
680         m_gl.getQueryObjectuiv(m_queryID, GL_QUERY_RESULT_AVAILABLE, &queryReady);
681
682         return queryReady;
683 }
684
685 class InfiniteLoop : public ContextReset
686 {
687 public:
688                                                 InfiniteLoop                    (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType);
689                                                 ~InfiniteLoop                   (void);
690
691         virtual void            setup                                   (void);
692         virtual void            draw                                    (void);
693         virtual void            teardown                                (void);
694
695 private:
696         glu::ProgramSources genComputeSource            (void);
697         glu::ProgramSources genNonComputeSource         (void);
698         glu::ProgramSources     genSources                              (void);
699
700         glw::GLuint                     m_outputBuffer;
701         glw::GLuint                     m_coordinatesBuffer;
702         glw::GLint                      m_coordLocation;
703 };
704
705 InfiniteLoop::InfiniteLoop (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType)
706         : ContextReset(gl, log, shaderType)
707         , m_outputBuffer                (0)
708         , m_coordinatesBuffer   (0)
709         , m_coordLocation               (0)
710 {
711 }
712
713 InfiniteLoop::~InfiniteLoop (void)
714 {
715         try
716         {
717                 // Reset GL_CONTEXT_LOST error before destroying resources
718                 m_gl.getGraphicsResetStatus();
719                 teardown();
720         }
721         catch (...)
722         {
723                 // Ignore GL errors from teardown()
724         }
725 }
726
727 glu::ProgramSources InfiniteLoop::genSources(void)
728 {
729         if (m_shaderType == SHADERTYPE_COMPUTE)
730                 return genComputeSource();
731         else
732                 return genNonComputeSource();
733 }
734
735 glu::ProgramSources InfiniteLoop::genComputeSource(void)
736 {
737         const char* const computeSource =
738                 "#version 310 es\n"
739                 "layout(local_size_x = 1, local_size_y = 1) in;\n"
740                 "uniform highp int u_iterCount;\n"
741                 "writeonly buffer Output { highp int b_output_int; };\n"
742                 "void main ()\n"
743                 "{\n"
744                 "       for (highp int i = 0; i < u_iterCount || u_iterCount < 0; ++i)\n"
745                 "               b_output_int = u_iterCount;\n"
746                 "}\n";
747
748         return glu::ProgramSources() << glu::ComputeSource(computeSource);
749 }
750
751 glu::ProgramSources InfiniteLoop::genNonComputeSource (void)
752 {
753         const bool isVertCase                   = m_shaderType == SHADERTYPE_VERT;
754         const bool isFragCase                   = m_shaderType == SHADERTYPE_FRAG;
755         const bool isVertAndFragment    = m_shaderType == SHADERTYPE_VERT_AND_FRAG;
756
757         std::ostringstream vert, frag;
758
759         vert << "#version 300 es\n"
760                  << "in highp vec2 a_position;\n";
761
762         frag << "#version 300 es\n";
763
764         vert << "uniform highp int u_iterCount;\n";
765         if (isFragCase || isVertAndFragment)
766         {
767                 vert << "flat out highp int v_iterCount;\n";
768                 frag << "flat in highp int v_iterCount;\n";
769         }
770
771         if (isVertCase || isVertAndFragment)
772         {
773                 vert << "out mediump vec4 v_color;\n";
774                 frag << "in mediump vec4 v_color;\n";
775         }
776
777         frag << "out mediump vec4 o_color;\n";
778
779         vert << "\nvoid main (void)\n{\n"
780                  << "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
781                  << "   gl_PointSize = 1.0;\n";
782
783         if (isFragCase || isVertAndFragment)
784                 vert << "       v_iterCount = u_iterCount;\n";
785
786         frag << "\nvoid main (void)\n{\n";
787
788         const std::string       iterCount       = (isVertCase ? "u_iterCount" : "v_iterCount");
789         const std::string       loopHeader      = "     for (highp int i = 0; i < " + iterCount + " || " + iterCount + " < 0; ++i)\n";
790         const char* const       body            = "color = cos(sin(color*1.25)*0.8);";
791
792         if (isVertAndFragment)
793         {
794                 vert << "       mediump vec4 color = " << "a_position.xyxy" << ";\n";
795                 vert << loopHeader << "         " << body << "\n";
796
797                 frag << "       mediump vec4 color = " << "gl_FragCoord" << ";\n";
798                 frag << loopHeader << "         " << body << "\n";
799         }
800         else
801         {
802                 std::ostringstream&     op                      = isVertCase ? vert : frag;
803                 op << " mediump vec4 color = " << (isVertCase ? "a_position.xyxy" : "gl_FragCoord") << ";\n";
804                 op << loopHeader << "           " << body << "\n";
805         }
806
807         if (isVertCase || isVertAndFragment)
808         {
809                 vert << "       v_color = color;\n";
810                 frag << "       o_color = v_color;\n";
811         }
812         else
813                 frag << "       o_color = color;\n";
814
815         vert << "}\n";
816         frag << "}\n";
817
818         return glu::ProgramSources() << glu::VertexSource(vert.str()) << glu::FragmentSource(frag.str());
819 }
820
821 void InfiniteLoop::setup (void)
822 {
823         glu::ShaderProgram program (m_gl, genSources());
824         m_log << program;
825
826         if (!program.isOk())
827                 TCU_FAIL("Failed to compile shader program");
828
829         GLU_CHECK_GLW_CALL(m_gl, useProgram(program.getProgram()));
830
831         if (m_shaderType == SHADERTYPE_COMPUTE)
832         {
833                 // Output buffer setup
834                 m_outputBuffer = 0;
835                 GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_outputBuffer));
836                 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_SHADER_STORAGE_BUFFER, m_outputBuffer));
837                 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int), DE_NULL, GL_DYNAMIC_DRAW));
838                 GLU_CHECK_GLW_CALL(m_gl, bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_outputBuffer));
839         }
840         else
841         {
842                 const glw::GLfloat coords[] =
843                 {
844                         -1.0f, -1.0f,
845                         +1.0f, -1.0f,
846                         +1.0f, +1.0f,
847                         -1.0f, +1.0f
848                 };
849
850                 m_coordLocation = m_gl.getAttribLocation(program.getProgram(), "a_position");
851                 GLU_CHECK_GLW_MSG(m_gl, "glGetAttribLocation()");
852                 TCU_CHECK(m_coordLocation != (glw::GLint)-1);
853
854                 // Load the vertex data
855                 m_coordinatesBuffer = 0;
856                 GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
857                 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
858                 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
859                 GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(m_coordLocation));
860                 GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(m_coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
861         }
862
863         glw::GLint iterCountLocation = m_gl.getUniformLocation(program.getProgram(), "u_iterCount");
864         GLU_CHECK_GLW_MSG(m_gl, "glGetUniformLocation()");
865         TCU_CHECK(iterCountLocation != (glw::GLint)-1);
866
867         // Set the iteration count (infinite)
868         glw::GLint iterCount = -1;
869         GLU_CHECK_GLW_CALL(m_gl, uniform1i(iterCountLocation, iterCount));
870 }
871
872 void InfiniteLoop::draw (void)
873 {
874         if (m_shaderType == SHADERTYPE_COMPUTE)
875                 m_gl.dispatchCompute(1, 1, 1);
876         else
877         {
878                 const glw::GLushort indices[] = { 0, 1, 2, 2, 3, 0 };
879                 m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
880         }
881 }
882
883 void InfiniteLoop::teardown (void)
884 {
885         if (m_shaderType != SHADERTYPE_COMPUTE)
886         {
887                 if (m_coordLocation)
888                 {
889                         GLU_CHECK_GLW_CALL(m_gl, disableVertexAttribArray(m_coordLocation));
890                         m_coordLocation = 0;
891                 }
892         }
893
894         if (m_outputBuffer)
895         {
896                 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_outputBuffer));
897                 m_outputBuffer = 0;
898         }
899
900         if (m_coordinatesBuffer)
901         {
902                 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
903                 m_coordinatesBuffer = 0;
904         }
905
906         GLU_CHECK_GLW_CALL(m_gl, useProgram(0));
907 }
908
909 class FixedFunctionOOB : public ContextReset
910 {
911 public:
912                                                         FixedFunctionOOB                        (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType);
913                                                         ~FixedFunctionOOB                       (void);
914
915         struct TestConfig
916         {
917                 int textureWidth;
918                 int textureHeight;
919         };
920
921         virtual void                    setup                                           (void);
922         virtual void                    draw                                            (void);
923         virtual void                    teardown                                        (void);
924
925 private:
926         glu::ProgramSources             genSources                                      (void);
927         glw::GLuint                             m_coordinatesBuffer;
928         glw::GLint                              m_coordLocation;
929 };
930
931 FixedFunctionOOB::FixedFunctionOOB (glw::Functions& gl, tcu::TestLog& log, FixedFunctionType fixedFunctionType)
932         : ContextReset(gl, log, fixedFunctionType)
933         , m_coordinatesBuffer   (0)
934         , m_coordLocation               (0)
935 {
936 }
937
938 FixedFunctionOOB::~FixedFunctionOOB (void)
939 {
940         try
941         {
942                 // Reset GL_CONTEXT_LOST error before destroying resources
943                 m_gl.getGraphicsResetStatus();
944                 teardown();
945         }
946         catch (...)
947         {
948                 // Ignore GL errors from teardown()
949         }
950 }
951
952 glu::ProgramSources FixedFunctionOOB::genSources (void)
953 {
954         const char* const vert =
955                 "#version 300 es\n"
956                 "in highp vec4 a_position;\n"
957                 "void main (void)\n"
958                 "{\n"
959                 "       gl_Position = a_position;\n"
960                 "}\n";
961
962         const char* const frag =
963                 "#version 300 es\n"
964                 "layout(location = 0) out highp vec4 fragColor;\n"
965                 "void main (void)\n"
966                 "{\n"
967                 "       fragColor = vec4(1.0f);\n"
968                 "}\n";
969
970         return glu::ProgramSources() << glu::VertexSource(vert) << glu::FragmentSource(frag);
971 }
972
973 void FixedFunctionOOB::setup (void)
974 {
975         glu::ShaderProgram program(m_gl, genSources());
976
977         m_log << program;
978
979         if (!program.isOk())
980                 TCU_FAIL("Failed to compile shader program");
981
982         GLU_CHECK_GLW_CALL(m_gl, useProgram(program.getProgram()));
983
984         const glw::GLfloat coords[] =
985         {
986                 -1.0f, -1.0f,
987                  1.0f, -1.0f,
988                  1.0f,  1.0f,
989                 -1.0f,  1.0f
990         };
991
992         m_coordLocation = m_gl.getAttribLocation(program.getProgram(), "a_position");
993         GLU_CHECK_GLW_MSG(m_gl, "glGetAttribLocation()");
994         TCU_CHECK(m_coordLocation != (glw::GLint)-1);
995
996         // Load the vertex data
997         m_coordinatesBuffer = 0;
998         GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
999         GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
1000         GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
1001         GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(m_coordLocation));
1002         GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(m_coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
1003 }
1004
1005 void FixedFunctionOOB::draw (void)
1006 {
1007         const glw::GLint bad_indices[] = {0, 10, 100, 1000, 10000, 100000};
1008
1009         if (m_fixedFunctionType == FIXEDFUNCTIONTYPE_INDICES)
1010                 m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, bad_indices);
1011         else if (m_fixedFunctionType == FIXEDFUNCTIONTYPE_VERTICES)
1012                 m_gl.drawArrays(GL_TRIANGLES, 0, 1000);
1013         else
1014                 DE_FATAL("Unknown fixed function type");
1015 }
1016
1017 void FixedFunctionOOB::teardown (void)
1018 {
1019         if (m_coordLocation)
1020         {
1021                 GLU_CHECK_GLW_CALL(m_gl, disableVertexAttribArray(m_coordLocation));
1022                 m_coordLocation = 0;
1023         }
1024
1025         if (m_coordinatesBuffer)
1026         {
1027                 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
1028                 m_coordinatesBuffer = 0;
1029         }
1030
1031         GLU_CHECK_GLW_CALL(m_gl, useProgram(0));
1032 }
1033
1034 class ShadersOOB : public ContextReset
1035 {
1036 public:
1037                                                                 ShadersOOB                                      (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType);
1038                                                                 ~ShadersOOB                                     (void);
1039
1040         virtual void                            setup                                           (void);
1041         virtual void                            draw                                            (void);
1042         virtual void                            teardown                                        (void);
1043
1044 private:
1045         static const int                        s_numBindings                           = 3;
1046
1047         glw::GLuint                                     m_coordinatesBuffer;
1048         glw::GLint                                      m_coordLocation;
1049
1050         bool                                            m_isUBO;
1051         bool                                            m_isRead;
1052         bool                                            m_isLocalArray;
1053         std::vector<glw::GLuint>        m_buffers;
1054
1055         std::string                                     genVertexShader                         (const std::string& shaderDecl, const std::string& shaderBody);
1056         std::string                                     genFragmentShader                       (const std::string& shaderDecl, const std::string& shaderBody);
1057         std::string                                     genComputeShader                        (const std::string& shaderDecl, const std::string& shaderBody);
1058
1059         glu::ProgramSources                     genNonComputeSource                     (void);
1060         glu::ProgramSources                     genComputeSource                        (void);
1061         glu::ProgramSources                     genSources                                      (void);
1062 };
1063
1064 ShadersOOB::ShadersOOB (glw::Functions& gl, tcu::TestLog& log, ShaderType shaderType, ResourceType resourceType, ReadWriteType readWriteType)
1065         : ContextReset(gl, log, shaderType, resourceType, readWriteType)
1066         , m_coordinatesBuffer   (0)
1067         , m_coordLocation               (0)
1068         , m_buffers                             (s_numBindings, 0)
1069 {
1070         m_isUBO                 = (m_resourceType == RESOURCETYPE_UBO);
1071         m_isLocalArray  = (m_resourceType == RESOURCETYPE_LOCAL_ARRAY);
1072         m_isRead                = (m_readWriteType == READWRITETYPE_READ);
1073 }
1074
1075 ShadersOOB::~ShadersOOB (void)
1076 {
1077         try
1078         {
1079                 // Reset GL_CONTEXT_LOST error before destroying resources
1080                 m_gl.getGraphicsResetStatus();
1081                 teardown();
1082         }
1083         catch (...)
1084         {
1085                 // Ignore GL errors from teardown()
1086         }
1087 }
1088
1089 std::string ShadersOOB::genVertexShader (const std::string& shaderDecl, const std::string& shaderBody)
1090 {
1091         static const char* const s_simpleVertexShaderSource     =
1092                 "#version 310 es\n"
1093                 "in highp vec4 a_position;\n"
1094                 "void main (void)\n"
1095                 "{\n"
1096                 "       gl_Position = a_position;\n"
1097                 "}\n";
1098
1099         switch (m_shaderType)
1100         {
1101                 case SHADERTYPE_VERT:
1102                 case SHADERTYPE_VERT_AND_FRAG:
1103                 {
1104                         std::ostringstream vertexShaderSource;
1105                         vertexShaderSource      <<      "#version 310 es\n"
1106                                                                 <<      "in highp vec4 a_position;\n"
1107                                                                 <<      "out highp vec4 v_color;\n"
1108                                                                 <<      shaderDecl << "\n"
1109                                                                 <<      "void main (void)\n"
1110                                                                 <<      "{\n"
1111                                                                 <<      "       highp vec4 color;\n"
1112                                                                 <<      shaderBody << "\n"
1113                                                                 <<      "       v_color = color;\n"
1114                                                                 <<      "       gl_Position = a_position;\n"
1115                                                                 <<      "}\n";
1116
1117                         return vertexShaderSource.str();
1118                 }
1119
1120                 case SHADERTYPE_FRAG:
1121                         return s_simpleVertexShaderSource;
1122
1123                 default:
1124                         DE_FATAL("Unknown shader type");
1125                         return "";
1126         }
1127 }
1128
1129 std::string ShadersOOB::genFragmentShader (const std::string& shaderDecl, const std::string& shaderBody)
1130 {
1131         static const char* const s_simpleFragmentShaderSource =
1132                 "#version 310 es\n"
1133                 "in highp vec4 v_color;\n"
1134                 "layout(location = 0) out highp vec4 fragColor;\n"
1135                 "void main (void)\n"
1136                 "{\n"
1137                 "       fragColor = v_color;\n"
1138                 "}\n";
1139
1140         switch (m_shaderType)
1141         {
1142                 case SHADERTYPE_VERT:
1143                         return s_simpleFragmentShaderSource;
1144
1145                 case SHADERTYPE_FRAG:
1146                 {
1147                         std::ostringstream fragmentShaderSource;
1148                         fragmentShaderSource    <<      "#version 310 es\n"
1149                                                                         <<      "layout(location = 0) out highp vec4 fragColor;\n"
1150                                                                         <<      shaderDecl << "\n"
1151                                                                         <<      "void main (void)\n"
1152                                                                         <<      "{\n"
1153                                                                         <<      "       highp vec4 color = vec4(0.0f);\n"
1154                                                                         <<      shaderBody << "\n"
1155                                                                         <<      "       fragColor = color;\n"
1156                                                                         <<      "}\n";
1157
1158                         return fragmentShaderSource.str();
1159                 }
1160                 case SHADERTYPE_VERT_AND_FRAG:
1161                 {
1162                         std::ostringstream fragmentShaderSource;
1163                         fragmentShaderSource    <<      "#version 310 es\n"
1164                                                                         <<      "in highp vec4 v_color;\n"
1165                                                                         <<      "layout(location = 0) out highp vec4 fragColor;\n"
1166                                                                         <<      shaderDecl << "\n"
1167                                                                         <<      "void main (void)\n"
1168                                                                         <<      "{\n"
1169                                                                         <<      "       highp vec4 color = vec4(0.0f);\n"
1170                                                                         <<      shaderBody << "\n"
1171                                                                         <<      "       fragColor = color;\n"
1172                                                                         <<      "}\n";
1173
1174                         return fragmentShaderSource.str();
1175                 }
1176
1177                 default:
1178                         DE_FATAL("Unknown shader type");
1179                         return "";
1180         }
1181 }
1182
1183 std::string ShadersOOB::genComputeShader (const std::string& shaderDecl, const std::string& shaderBody)
1184 {
1185         std::ostringstream computeShaderSource;
1186
1187         computeShaderSource             <<      "#version 310 es\n"
1188                                                         <<      "layout(local_size_x = 1, local_size_y = 1) in;\n"
1189                                                         <<      "\n"
1190                                                         <<      "layout(binding = 0) buffer Output {\n"
1191                                                         <<      "       highp vec4 values;\n"
1192                                                         <<      "} sb_out;\n"
1193                                                         <<      "\n"
1194                                                         <<      shaderDecl
1195                                                         <<      "void main ()\n"
1196                                                         <<      "{\n"
1197                                                         <<      shaderBody
1198                                                         <<      "}\n";
1199
1200         return computeShaderSource.str();
1201 }
1202
1203 glu::ProgramSources ShadersOOB::genNonComputeSource (void)
1204 {
1205         std::ostringstream              shaderDecl;
1206         std::ostringstream              shaderBody;
1207
1208         shaderDecl << "uniform highp int u_index;\n";
1209
1210         if (m_isLocalArray)
1211         {
1212                 const char* const readWriteStatement = (m_isRead)
1213                                                                                          ? "    color.x = color_out[u_index];\n"
1214                                                                                          : "    color[u_index] = color_out[0];\n";
1215
1216                 shaderBody      << "    highp float color_out[4] = float[4](0.25f, 0.5f, 0.75f, 1.0f);\n"
1217                                         << readWriteStatement;
1218         }
1219         else
1220         {
1221                 const std::string resName = (m_isUBO) ? "ub_in" : "sb_in";
1222
1223                 shaderDecl << "layout(std140, binding = 0) " << ((m_isUBO) ? "uniform" : "buffer") << " Block\n"
1224                         << "{\n"
1225                         << "    highp float color_out[4];\n"
1226                         << "} " << resName << "[" << s_numBindings << "];\n";
1227
1228                 const std::string readWriteStatement = (m_isRead)
1229                                                                                          ? "    color.x = " + resName + "[0].color_out[u_index];\n"
1230                                                                                          : "    color[u_index] = " + resName + "[0].color_out[0];\n";
1231
1232                 shaderBody << readWriteStatement;
1233         }
1234
1235         return glu::ProgramSources() << glu::VertexSource(genVertexShader(shaderDecl.str(), shaderBody.str()))
1236                                                                  << glu::FragmentSource(genFragmentShader(shaderDecl.str(), shaderBody.str()));
1237 }
1238
1239 glu::ProgramSources ShadersOOB::genComputeSource (void)
1240 {
1241         std::ostringstream              shaderDecl;
1242         std::ostringstream              shaderBody;
1243
1244         shaderDecl << "uniform highp int u_index;\n";
1245
1246         shaderBody      << "    uvec3 size = gl_NumWorkGroups * gl_WorkGroupSize;\n"
1247                                 << "    uint groupNdx = size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;\n";
1248
1249         if (m_isLocalArray)
1250         {
1251                 const char* const readWriteStatement = (m_isRead)
1252                                                                                          ? "    sb_out.values.x = values[u_index];\n"
1253                                                                                          : "    sb_out.values[u_index] = values.x;\n";
1254
1255                 shaderBody      << "    highp vec4 values = vec4(1.0f, 0.0f, 3.0f, 2.0f) * float(groupNdx);\n"
1256                                         << readWriteStatement;
1257         }
1258         else
1259         {
1260                 const std::string resName = (m_isUBO) ? "ub_in" : "sb_in";
1261
1262                 shaderDecl      << "layout(std140, binding = 1) " << ((m_isUBO) ? "uniform" : "buffer") << " Input\n"
1263                                         << "{\n"
1264                                         << "    highp vec4 values;\n"
1265                                         << "} " << resName << "[" << s_numBindings << "];\n";
1266
1267                 std::string readWriteStatement = (m_isRead)
1268                                                                            ? "  sb_out.values.x = " + resName + "[0].values[u_index] * float(groupNdx);\n"
1269                                                                            : "  sb_out.values[u_index] = " + resName + "[0].values.x * float(groupNdx);\n";
1270
1271                 shaderBody << readWriteStatement;
1272         }
1273
1274         return glu::ProgramSources() << glu::ComputeSource(genComputeShader(shaderDecl.str(), shaderBody.str()));
1275 }
1276
1277 glu::ProgramSources ShadersOOB::genSources (void)
1278 {
1279         if (m_shaderType == SHADERTYPE_COMPUTE)
1280                 return genComputeSource();
1281         else
1282                 return genNonComputeSource();
1283 }
1284
1285 void ShadersOOB::setup (void)
1286 {
1287         if (!m_isUBO && !m_isLocalArray && (m_shaderType != SHADERTYPE_COMPUTE))
1288         {
1289                 // Check implementation limits for shader SSBO
1290                 int shaderStorageBlockSupported = -1;
1291                 const bool isVertex = (m_shaderType == SHADERTYPE_VERT || m_shaderType == SHADERTYPE_VERT_AND_FRAG) ? true : false;
1292                 string shaderTypeStr = isVertex ? "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS" : "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS";
1293
1294                 GLU_CHECK_GLW_CALL(m_gl, getIntegerv(isVertex ? GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS : GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &shaderStorageBlockSupported));
1295
1296                 if (shaderStorageBlockSupported < (int)m_buffers.size())
1297                         TCU_THROW(NotSupportedError, ("Test requires " + shaderTypeStr + " >= " + de::toString((int)m_buffers.size()) + ", got " + de::toString(shaderStorageBlockSupported)).c_str());
1298         }
1299
1300         glu::ShaderProgram program(m_gl, genSources());
1301
1302         m_log << program;
1303
1304         if (!program.isOk())
1305                 TCU_FAIL("Failed to compile shader program");
1306
1307         GLU_CHECK_GLW_CALL(m_gl, useProgram(program.getProgram()));
1308
1309         const glw::GLint indexLocation = m_gl.getUniformLocation(program.getProgram(), "u_index");
1310         GLU_CHECK_GLW_MSG(m_gl, "glGetUniformLocation()");
1311         TCU_CHECK(indexLocation != (glw::GLint)-1);
1312
1313         const glw::GLint index = -1;
1314         GLU_CHECK_GLW_CALL(m_gl, uniform1i(indexLocation, index));
1315
1316         if (m_shaderType != SHADERTYPE_COMPUTE)
1317         {
1318                 const glw::GLfloat coords[] =
1319                 {
1320                         -1.0f, -1.0f,
1321                         +1.0f, -1.0f,
1322                         +1.0f, +1.0f,
1323                         -1.0f, +1.0f
1324                 };
1325
1326                 // Setup vertices position
1327                 m_coordLocation = m_gl.getAttribLocation(program.getProgram(), "a_position");
1328                 GLU_CHECK_GLW_MSG(m_gl, "glGetAttribLocation()");
1329                 TCU_CHECK(m_coordLocation != (glw::GLint)-1);
1330
1331                 // Load the vertex data
1332                 m_coordinatesBuffer = 0;
1333                 GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
1334                 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
1335                 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
1336                 GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(m_coordLocation));
1337                 GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(m_coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
1338         }
1339
1340         // Create dummy data for filling buffer objects
1341         const std::vector<tcu::Vec4> refValues(s_numBindings, tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f));
1342
1343         if (m_isLocalArray && m_shaderType == SHADERTYPE_COMPUTE)
1344         {
1345                 // Setup output buffer
1346                 GLU_CHECK_GLW_CALL(m_gl, genBuffers((glw::GLsizei)1u, &m_buffers[0]));
1347
1348                 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffers[0]));
1349                 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(tcu::Vec4), &(refValues[0]), GL_STATIC_DRAW));
1350                 GLU_CHECK_GLW_CALL(m_gl, bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffers[0]));
1351         }
1352         else if (!m_isLocalArray)
1353         {
1354                 // Set up interface block of buffer bindings
1355                 GLU_CHECK_GLW_CALL(m_gl, genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]));
1356
1357                 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1358                 {
1359                         const glw::GLenum resType       = m_isUBO && (m_shaderType != SHADERTYPE_COMPUTE || bufNdx != 0)
1360                                                                                 ? GL_UNIFORM_BUFFER
1361                                                                                 : GL_SHADER_STORAGE_BUFFER;
1362
1363                         GLU_CHECK_GLW_CALL(m_gl, bindBuffer(resType, m_buffers[bufNdx]));
1364                         GLU_CHECK_GLW_CALL(m_gl, bufferData(resType, sizeof(tcu::Vec4), &(refValues[bufNdx]), GL_STATIC_DRAW));
1365                         GLU_CHECK_GLW_CALL(m_gl, bindBufferBase(resType, bufNdx, m_buffers[bufNdx]));
1366                 }
1367         }
1368 }
1369
1370 void ShadersOOB::draw (void)
1371 {
1372         if (m_shaderType == SHADERTYPE_COMPUTE)
1373                 m_gl.dispatchCompute(1, 1, 1);
1374         else
1375         {
1376                 const glw::GLuint indices[] = {0, 1, 2, 2, 3, 0};
1377                 m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);
1378         }
1379 }
1380
1381 void ShadersOOB::teardown (void)
1382 {
1383         if (m_shaderType != SHADERTYPE_COMPUTE)
1384         {
1385                 if (m_coordLocation)
1386                 {
1387                         GLU_CHECK_GLW_CALL(m_gl, disableVertexAttribArray(m_coordLocation));
1388                         m_coordLocation = 0;
1389                 }
1390         }
1391
1392         if (m_coordinatesBuffer)
1393         {
1394                 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
1395                 m_coordinatesBuffer = 0;
1396         }
1397
1398         if (!m_isLocalArray)
1399         {
1400                 if (!m_buffers.empty())
1401                 {
1402                         GLU_CHECK_GLW_CALL(m_gl, deleteBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]));
1403                         m_buffers.clear();
1404                 }
1405         }
1406
1407         GLU_CHECK_GLW_CALL(m_gl, useProgram(0));
1408 }
1409
1410 class QueryRobustAccessCase : public RobustnessTestCase
1411 {
1412 public:
1413         QueryRobustAccessCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1414                 : RobustnessTestCase (eglTestCtx, name, description) {}
1415
1416         TestCase::IterateResult iterate         (void)
1417         {
1418                 TestLog&        log             = m_testCtx.getLog();
1419
1420                 log << tcu::TestLog::Message
1421                         << "Check that after successfully creating a robust context the robust access query returned by glBooleanv() equals GL_TRUE\n\n"
1422                         << tcu::TestLog::EndMessage;
1423
1424                 const EGLint attribList[] =
1425                 {
1426                         EGL_CONTEXT_CLIENT_VERSION, 3,
1427                         EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1428                         EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1429                         EGL_NONE
1430                 };
1431
1432                 checkRequiredEGLExtensions(attribList);
1433
1434                 RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1435                 context.makeCurrent(m_eglSurface);
1436
1437                 glw::Functions gl;
1438                 {
1439                         const glu::ApiType apiType(3, 0, glu::PROFILE_ES);
1440                         context.initGLFunctions(&gl, apiType);
1441                         checkRequiredGLSupport(gl, apiType);
1442                 }
1443
1444                 deUint8 robustAccessGL;
1445                 gl.getBooleanv(GL_CONTEXT_ROBUST_ACCESS_EXT, &robustAccessGL);
1446                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv()");
1447
1448                 if (robustAccessGL != GL_TRUE)
1449                 {
1450                         log << TestLog::Message
1451                                 << "Invalid GL_CONTEXT_ROBUST_ACCESS returned by glGetBooleanv(). Got '" << robustAccessGL << "' expected GL_TRUE."
1452                                 << TestLog::EndMessage;
1453
1454                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1455                         return STOP;
1456                 }
1457
1458                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1459                 return STOP;
1460         }
1461 };
1462
1463 class NoResetNotificationCase : public RobustnessTestCase
1464 {
1465 public:
1466         NoResetNotificationCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1467                 : RobustnessTestCase (eglTestCtx, name, description) {}
1468
1469         TestCase::IterateResult iterate         (void)
1470         {
1471                 TestLog&        log             = m_testCtx.getLog();
1472
1473                 log << tcu::TestLog::Message
1474                         << "Check the reset notification strategy returned by glGetIntegerv() equals GL_NO_RESET_NOTIFICATION\n\n"
1475                         << tcu::TestLog::EndMessage;
1476
1477                 const EGLint attribList[] =
1478                 {
1479                         EGL_CONTEXT_CLIENT_VERSION, 3,
1480                         EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1481                         EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1482                         EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION,
1483                         EGL_NONE
1484                 };
1485
1486                 checkRequiredEGLExtensions(attribList);
1487
1488                 RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1489                 context.makeCurrent(m_eglSurface);
1490
1491                 glw::Functions gl;
1492                 {
1493                         const glu::ApiType apiType(3, 0, glu::PROFILE_ES);
1494                         context.initGLFunctions(&gl, apiType);
1495                         checkRequiredGLSupport(gl, apiType);
1496                 }
1497
1498                 deUint8 robustAccessGL;
1499                 gl.getBooleanv(GL_CONTEXT_ROBUST_ACCESS_EXT, &robustAccessGL);
1500                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv()");
1501
1502                 glw::GLint reset = 0;
1503                 gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset);
1504                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
1505
1506                 if (reset != GL_NO_RESET_NOTIFICATION)
1507                 {
1508                         log     << tcu::TestLog::Message
1509                                 << "Test failed! glGetIntegerv() returned wrong value. [" << glu::getErrorStr(reset) << ", expected " << glu::getErrorStr(GL_NO_RESET_NOTIFICATION) << "]"
1510                                 << tcu::TestLog::EndMessage;
1511
1512                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1513                         return STOP;
1514                 }
1515
1516                 GLU_CHECK_GLW_CALL(gl, getGraphicsResetStatus());
1517
1518                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1519                 return STOP;
1520         }
1521 };
1522
1523 class LoseContextOnResetCase : public RobustnessTestCase
1524 {
1525 public:
1526         LoseContextOnResetCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1527                 : RobustnessTestCase(eglTestCtx, name, description) {}
1528
1529         TestCase::IterateResult iterate         (void)
1530         {
1531                 TestLog&        log             = m_testCtx.getLog();
1532
1533                 log << tcu::TestLog::Message
1534                         << "Check the reset notification strategy returned by glGetIntegerv() equals GL_LOSE_CONTEXT_ON_RESET\n\n"
1535                         << tcu::TestLog::EndMessage;
1536
1537                 const EGLint attribList[] =
1538                 {
1539                         EGL_CONTEXT_CLIENT_VERSION, 3,
1540                         EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1541                         EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1542                         EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
1543                         EGL_NONE
1544                 };
1545
1546                 checkRequiredEGLExtensions(attribList);
1547
1548                 RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1549                 context.makeCurrent(m_eglSurface);
1550
1551                 glw::Functions gl;
1552                 {
1553                         const glu::ApiType apiType(3, 0, glu::PROFILE_ES);
1554                         context.initGLFunctions(&gl, apiType);
1555                         checkRequiredGLSupport(gl, apiType);
1556                 }
1557                 glw::GLint reset = 0;
1558                 gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset);
1559                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
1560
1561                 if (reset != GL_LOSE_CONTEXT_ON_RESET)
1562                 {
1563                         log     << tcu::TestLog::Message
1564                                 << "Test failed! glGetIntegerv() returned wrong value. [" << reset << ", expected " << glu::getErrorStr(GL_LOSE_CONTEXT_ON_RESET) << "]"
1565                                 << tcu::TestLog::EndMessage;
1566
1567                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1568                         return STOP;
1569                 }
1570
1571                 log << tcu::TestLog::Message
1572                         << "Check the graphics reset status returned by glGetGraphicsResetStatus() "
1573                         << "equals GL_NO_ERROR\n"
1574                         << tcu::TestLog::EndMessage;
1575
1576                 GLU_CHECK_GLW_CALL(gl, getGraphicsResetStatus());
1577
1578                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1579                 return STOP;
1580         }
1581 };
1582
1583 de::SharedPtr<ContextReset> contextResetFactory (const RobustnessTestCase::Params params, glw::Functions& gl, tcu::TestLog& log)
1584 {
1585         if (params.getContextResetType() == CONTEXTRESETTYPE_INFINITE_LOOP)
1586                 return de::SharedPtr<ContextReset>(new InfiniteLoop(gl, log, params.getShaderType()));
1587
1588         if (params.getContextResetType() == CONTEXTRESETTYPE_FIXED_FUNC_OOB)
1589                 return de::SharedPtr<ContextReset>(new FixedFunctionOOB(gl, log, params.getFixedFunctionType()));
1590
1591         if (params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB)
1592                 return de::SharedPtr<ContextReset>(new ShadersOOB(gl, log, params.getShaderType(), params.getResourceType(), params.getReadWriteType()));
1593         else
1594         {
1595                 DE_FATAL("Unknown context reset type");
1596                 return de::SharedPtr<ContextReset>(DE_NULL);
1597         }
1598 }
1599
1600 class ContextResetCase : public RobustnessTestCase
1601 {
1602
1603 public:
1604                                                         ContextResetCase                (EglTestContext& eglTestCtx, const char* name, const char* description, Params params);
1605         virtual                                 ~ContextResetCase               (void) {};
1606
1607         virtual void                    provokeReset                    (de::SharedPtr<ContextReset>& contextReset) = 0;
1608         virtual void                    waitForReset                    (de::SharedPtr<ContextReset>& contextReset) = 0;
1609         virtual void                    passAndLog                              (de::SharedPtr<ContextReset>& contextReset) = 0;
1610
1611         TestCase::IterateResult iterate                                 (void);
1612         void                                    execute                                 (glw::Functions& gl);
1613
1614 private:
1615                                                 ContextResetCase                        (const ContextResetCase&);
1616         ContextResetCase&       operator=                                       (const ContextResetCase&);
1617 };
1618
1619 ContextResetCase::ContextResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
1620         : RobustnessTestCase (eglTestCtx, name, description, params) {}
1621
1622 TestCase::IterateResult ContextResetCase::iterate (void)
1623 {
1624         glw::Functions  gl;
1625
1626         const EGLint attribList[] =
1627         {
1628                 EGL_CONTEXT_CLIENT_VERSION, 3,
1629                 EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1630                 EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, (m_params.getRobustAccessType() == ROBUSTACCESS_TRUE) ? EGL_TRUE : EGL_FALSE,
1631                 EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
1632                 EGL_NONE
1633         };
1634
1635         checkRequiredEGLExtensions(attribList);
1636
1637         RenderingContext context(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1638         context.makeCurrent(m_eglSurface);
1639
1640         {
1641                 const glu::ApiType apiType = paramsToApiType(m_params);
1642                 context.initGLFunctions(&gl, apiType);
1643                 checkGLSupportForParams(gl, m_params);
1644         }
1645
1646         execute(gl);
1647
1648         return STOP;
1649 }
1650
1651 void ContextResetCase::execute (glw::Functions& gl)
1652 {
1653         de::SharedPtr<ContextReset> contextReset                                        = contextResetFactory(m_params, gl, m_testCtx.getLog());
1654         glw::GLboolean                          isContextRobust                                 = GL_FALSE;
1655
1656         GLU_CHECK_GLW_CALL(gl, getBooleanv(GL_CONTEXT_ROBUST_ACCESS_EXT, &isContextRobust));
1657         provokeReset(contextReset);
1658
1659         if (m_params.getContextResetType() == CONTEXTRESETTYPE_INFINITE_LOOP)
1660         {
1661                 try
1662                 {
1663                         waitForReset(contextReset);
1664
1665                         const glw::GLenum       status  = gl.getGraphicsResetStatus();
1666
1667                         if (status == GL_NO_ERROR)
1668                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Context was NOT lost");
1669                         else
1670                         {
1671                                 m_testCtx.getLog() << tcu::TestLog::Message << "glGetGraphicsResetStatus() returned " << glu::getGraphicsResetStatusStr(status) << tcu::TestLog::EndMessage;
1672                                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Context was lost");
1673                         }
1674                 }
1675                 catch (const glu::Error& error)
1676                 {
1677                         if (error.getError() == GL_CONTEXT_LOST)
1678                                 passAndLog(contextReset);
1679                         else
1680                         {
1681                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1682
1683                                 m_testCtx.getLog()      << tcu::TestLog::Message
1684                                                                         << "Warning: glGetError() returned wrong value [" << error.what() << ", expected " << glu::getErrorStr(GL_CONTEXT_LOST) << "]"
1685                                                                         << tcu::TestLog::EndMessage;
1686                         }
1687                 }
1688         }
1689         else if (m_params.getContextResetType() == CONTEXTRESETTYPE_SHADER_OOB || m_params.getContextResetType() == CONTEXTRESETTYPE_FIXED_FUNC_OOB)
1690         {
1691                 try
1692                 {
1693                         waitForReset(contextReset);
1694                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Context was NOT lost. Test skipped");
1695                 }
1696                 catch (const glu::Error& error)
1697                 {
1698                         if (error.getError() == GL_CONTEXT_LOST)
1699                         {
1700                                 if (isContextRobust)
1701                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "No context reset should of occurred GL_CONTEXT_ROBUST_ACCESS == TRUE");
1702                                 else
1703                                         passAndLog(contextReset);
1704                         }
1705                         else if (isContextRobust)
1706                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unknown error.");
1707                         else
1708                         {
1709                                 m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Warning: glGetError() returned wrong value. Expected GL_CONTEXT_LOST");
1710
1711                                 m_testCtx.getLog()      << tcu::TestLog::Message
1712                                                                         << "Warning: glGetError() returned wrong value [" << error.what() << ", expected " << glu::getErrorStr(GL_CONTEXT_LOST) << "]"
1713                                                                         << tcu::TestLog::EndMessage;
1714                         }
1715                 }
1716         }
1717         else
1718                 DE_FATAL("Unknown context reset type");
1719 }
1720
1721 class BasicResetCase : public ContextResetCase
1722 {
1723 public:
1724
1725         BasicResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
1726                 : ContextResetCase (eglTestCtx, name, description, params) {}
1727
1728         virtual void provokeReset (de::SharedPtr<ContextReset>& contextReset)
1729         {
1730                 m_testCtx.getLog()      << tcu::TestLog::Message
1731                                                         << "Check the graphics reset status returned by glGetGraphicsResetStatus() equals "
1732                                                         << "GL_GUILTY_CONTEXT_RESET after a context reset\n\n"
1733                                                         << tcu::TestLog::EndMessage;
1734
1735                 contextReset->setup();
1736                 contextReset->draw();
1737         }
1738
1739         virtual void waitForReset (de::SharedPtr<ContextReset>& contextReset)
1740         {
1741                 contextReset->teardown();
1742                 contextReset->finish();
1743         }
1744
1745         virtual void passAndLog (de::SharedPtr<ContextReset>& contextReset)
1746         {
1747                 const glw::GLint status = contextReset->getGraphicsResetStatus();
1748
1749                 if (status == GL_NO_ERROR)
1750                 {
1751                         m_testCtx.getLog()      << tcu::TestLog::Message
1752                                                                 << "Test failed! glGetGraphicsResetStatus() returned wrong value [" << glu::getGraphicsResetStatusStr(status) << ", expected " << glu::getGraphicsResetStatusStr(GL_GUILTY_CONTEXT_RESET) << "]"
1753                                                                 << tcu::TestLog::EndMessage;
1754
1755                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1756                 }
1757                 else
1758                 {
1759                         if (contextReset->getError() != GL_NO_ERROR)
1760                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Error flag not reset after calling getGraphicsResetStatus()");
1761                         else
1762                                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1763                 }
1764         }
1765 };
1766
1767 class SyncObjectResetCase : public ContextResetCase
1768 {
1769 public:
1770         SyncObjectResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
1771                 : ContextResetCase (eglTestCtx, name, description, params) {}
1772
1773         virtual void provokeReset (de::SharedPtr<ContextReset>& contextReset)
1774         {
1775                 m_testCtx.getLog()      << tcu::TestLog::Message
1776                                                         << "Check the status of a sync object after a context reset returned by glGetSynciv() equals GL_SIGNALED\n\n"
1777                                                         << tcu::TestLog::EndMessage;
1778
1779                 contextReset->setup();
1780                 contextReset->draw();
1781         }
1782
1783         virtual void waitForReset (de::SharedPtr<ContextReset>& contextReset)
1784         {
1785                 contextReset->createSyncObject();
1786                 contextReset->teardown();
1787                 contextReset->finish();
1788         }
1789
1790         virtual void passAndLog (de::SharedPtr<ContextReset>& contextReset)
1791         {
1792                 const glw::GLint status = contextReset->getSyncStatus();
1793                 if (status != GL_SIGNALED)
1794                 {
1795                         m_testCtx.getLog()      << tcu::TestLog::Message
1796                                                                 << "Test failed! glGetSynciv() returned wrong value [" << glu::getErrorStr(status) << ", expected " << glu::getErrorStr(GL_SIGNALED) << "]"
1797                                                                 << tcu::TestLog::EndMessage;
1798
1799                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1800                 }
1801                 else
1802                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1803         }
1804 };
1805
1806 class QueryObjectResetCase : public ContextResetCase
1807 {
1808 public:
1809         QueryObjectResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
1810                 : ContextResetCase (eglTestCtx, name, description, params) {}
1811
1812         virtual void provokeReset (de::SharedPtr<ContextReset>& contextReset)
1813         {
1814                 m_testCtx.getLog()      << tcu::TestLog::Message
1815                                                         << "Check the status of a query object after a context reset returned by glGetQueryObjectuiv() equals GL_TRUE\n\n"
1816                                                         << tcu::TestLog::EndMessage;
1817
1818                 contextReset->setup();
1819                 contextReset->beginQuery();
1820                 contextReset->draw();
1821         }
1822
1823         virtual void waitForReset (de::SharedPtr<ContextReset>& contextReset)
1824         {
1825                 contextReset->endQuery();
1826                 contextReset->teardown();
1827                 contextReset->finish();
1828         }
1829
1830         virtual void passAndLog (de::SharedPtr<ContextReset>& contextReset)
1831         {
1832                 const glw::GLuint queryReady = contextReset->getQueryAvailability();
1833                 if (queryReady != GL_TRUE)
1834                 {
1835                         m_testCtx.getLog()      << tcu::TestLog::Message
1836                                                                 << "Test failed! glGetQueryObjectuiv() returned wrong value [" << glu::getErrorStr(queryReady) << ", expected " << glu::getErrorStr(GL_TRUE) << "]"
1837                                                                 << tcu::TestLog::EndMessage;
1838
1839                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1840                 }
1841                 else
1842                 {
1843                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1844                 }
1845         }
1846 };
1847
1848 class InvalidShareContextCase : public RobustnessTestCase
1849 {
1850 public:
1851         InvalidShareContextCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1852                 : RobustnessTestCase (eglTestCtx, name, description) {}
1853
1854         TestCase::IterateResult iterate (void)
1855         {
1856                 TestLog&                log             =       m_testCtx.getLog();
1857                 const Library&  egl             =       m_eglTestCtx.getLibrary();
1858                 bool                    isOk    =       true;
1859
1860                 log << tcu::TestLog::Message
1861                         << "EGL_BAD_MATCH is generated if reset notification strategies do not match when creating shared contexts\n\n"
1862                         << tcu::TestLog::EndMessage;
1863
1864                 const EGLint attribListA[] =
1865                 {
1866                         EGL_CONTEXT_CLIENT_VERSION, 3,
1867                         EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1868                         EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1869                         EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION,
1870                         EGL_NONE
1871                 };
1872
1873                 const EGLint attribListB[] =
1874                 {
1875                         EGL_CONTEXT_CLIENT_VERSION, 3,
1876                         EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1877                         EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1878                         EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
1879                         EGL_NONE
1880                 };
1881
1882                 checkRequiredEGLExtensions(attribListA);
1883
1884                 log << tcu::TestLog::Message << "Create context A (share_context = EGL_NO_CONTEXT)" << tcu::TestLog::EndMessage;
1885                 RenderingContext contextA(m_eglTestCtx, attribListA, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1886
1887                 log << tcu::TestLog::Message << "Create context B (share_context = context A)" << tcu::TestLog::EndMessage;
1888                 logAttribList(m_eglTestCtx, attribListB);
1889
1890                 EGLContext contextB = egl.createContext(m_eglDisplay, m_eglConfig, contextA.getContext(), attribListB);
1891
1892                 const EGLenum error = egl.getError();
1893                 if (error != EGL_BAD_MATCH)
1894                 {
1895                         log << TestLog::Message
1896                                 << "Test failed! eglCreateContext() returned with error [" << eglu::getErrorStr(error) << ", expected " << eglu::getErrorStr(EGL_BAD_MATCH) << "]"
1897                                 << TestLog::EndMessage;
1898
1899                         isOk = false;
1900                 }
1901
1902                 if (contextB != EGL_NO_CONTEXT)
1903                         egl.destroyContext(m_eglDisplay, contextB);
1904
1905                 if (isOk)
1906                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1907                 else
1908                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1909
1910                 return STOP;
1911         }
1912 };
1913
1914 class InvalidNotificationEnumCase : public RobustnessTestCase
1915 {
1916 public:
1917         InvalidNotificationEnumCase (EglTestContext& eglTestCtx, const char* name, const char* description)
1918                 : RobustnessTestCase (eglTestCtx, name, description) {}
1919
1920         TestCase::IterateResult iterate (void)
1921         {
1922                 TestLog&                log             =       m_testCtx.getLog();
1923                 const Library&  egl             =       m_eglTestCtx.getLibrary();
1924                 bool                    isOk    =       true;
1925
1926                 log << tcu::TestLog::Message
1927                         << "EGL_BAD_ATTRIBUTE is generated if EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR is used with EGL versions <= 1.4\n\n"
1928                         << tcu::TestLog::EndMessage;
1929
1930                 const EGLint attribList[] =
1931                 {
1932                         EGL_CONTEXT_CLIENT_VERSION, 3,
1933                         EGL_CONTEXT_MINOR_VERSION_KHR, 1,
1934                         EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, EGL_NO_RESET_NOTIFICATION,
1935                         EGL_NONE
1936                 };
1937
1938                 if (eglu::getVersion(egl, m_eglDisplay) >= eglu::Version(1, 5))
1939                 {
1940                         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test requires EGL version to be under 1.5");
1941                         return STOP;
1942                 }
1943
1944                 logAttribList(m_eglTestCtx, attribList);
1945                 EGLContext context = egl.createContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, attribList);
1946
1947                 const EGLenum error = egl.getError();
1948                 if (error != EGL_BAD_ATTRIBUTE)
1949                 {
1950                         log << TestLog::Message
1951                                 << "Test failed! eglCreateContext() returned with error [" << eglu::getErrorStr(error) << ", expected " << eglu::getErrorStr(EGL_BAD_ATTRIBUTE) << "]"
1952                                 << TestLog::EndMessage;
1953
1954                         isOk = false;
1955                 }
1956
1957                 if (context != EGL_NO_CONTEXT)
1958                         egl.destroyContext(m_eglDisplay, context);
1959
1960                 if (isOk)
1961                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1962                 else
1963                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1964
1965                 return STOP;
1966         }
1967 };
1968
1969 class SharedContextResetCase : public RobustnessTestCase
1970 {
1971 public:
1972         SharedContextResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
1973                 : RobustnessTestCase (eglTestCtx, name, description, params) {}
1974
1975         TestCase::IterateResult iterate (void)
1976         {
1977                 TestLog&        log             = m_testCtx.getLog();
1978
1979                 log << tcu::TestLog::Message
1980                         << "A reset in one context will result in a reset in all other contexts in its share group\n\n"
1981                         << tcu::TestLog::EndMessage;
1982
1983                 // Create two share contexts with the same reset notification strategies
1984                 const EGLint attribListShared[] =
1985                 {
1986                         EGL_CONTEXT_CLIENT_VERSION, 3,
1987                         EGL_CONTEXT_MINOR_VERSION_KHR, 0,
1988                         EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
1989                         EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
1990                         EGL_NONE
1991                 };
1992
1993                 checkRequiredEGLExtensions(attribListShared);
1994
1995                 log << tcu::TestLog::Message << "Create context A (share_context = EGL_NO_CONTEXT)" << tcu::TestLog::EndMessage;
1996                 RenderingContext contextA(m_eglTestCtx, attribListShared, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
1997
1998                 log << tcu::TestLog::Message << "Create context B (share_context = context A)" << tcu::TestLog::EndMessage;
1999                 RenderingContext contextB(m_eglTestCtx, attribListShared, m_eglConfig, m_eglDisplay, contextA.getContext());
2000
2001                 contextA.makeCurrent(m_eglSurface);
2002
2003                 glw::Functions gl;
2004                 contextA.initGLFunctions(&gl, paramsToApiType(m_params));
2005                 checkGLSupportForParams(gl, m_params);
2006
2007                 DE_ASSERT(m_params.getContextResetType() == CONTEXTRESETTYPE_INFINITE_LOOP);
2008                 de::UniquePtr<ContextReset> contextReset(new InfiniteLoop(gl, log, m_params.getShaderType()));
2009
2010                 contextReset->setup();
2011                 contextReset->draw();
2012
2013                 try
2014                 {
2015                         contextReset->teardown();
2016                         contextReset->finish();
2017                 }
2018                 catch (const glu::Error& error)
2019                 {
2020                         if (error.getError() == GL_CONTEXT_LOST)
2021                         {
2022                                 contextB.makeCurrent(m_eglSurface);
2023
2024                                 gl.getString(GL_VERSION); // arbitrary gl call
2025
2026                                 if (gl.getError() != GL_CONTEXT_LOST)
2027                                 {
2028                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Test failed! glGetError() returned wrong value. Expected GL_CONTEXT_LOST in context B");
2029                                         return STOP;
2030                                 }
2031                         }
2032                         else
2033                         {
2034                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Test failed! glGetError() returned wrong value. Expected GL_CONTEXT_LOST in context A");
2035                                 return STOP;
2036                         }
2037                 }
2038
2039                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2040                 return STOP;
2041         }
2042 };
2043
2044 class InvalidContextCase : public RobustnessTestCase
2045 {
2046 public:
2047         InvalidContextCase (EglTestContext& eglTestCtx, const char* name, const char* description)
2048                 : RobustnessTestCase (eglTestCtx, name, description) {}
2049
2050         TestCase::IterateResult iterate (void)
2051         {
2052                 const Library&  egl             = m_eglTestCtx.getLibrary();
2053                 TestLog&                log             = m_testCtx.getLog();
2054                 bool                    isOk    = true;
2055
2056                 log << tcu::TestLog::Message
2057                         << "EGL_BAD_ATTRIBUTE is generated if EXT_create_context_robustness is NOT supported but EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT is specified\n\n"
2058                         << tcu::TestLog::EndMessage;
2059
2060                 const EGLint attribList[] =
2061                 {
2062                         EGL_CONTEXT_CLIENT_VERSION, 3,
2063                         EGL_CONTEXT_MINOR_VERSION_KHR, 0,
2064                         EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
2065                         EGL_NONE
2066                 };
2067
2068                 if (eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_create_context_robustness"))
2069                 {
2070                         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test requires EGL_EXT_create_context_robustness to be unsupported");
2071                         return STOP;
2072                 }
2073
2074                 logAttribList(m_eglTestCtx, attribList);
2075                 EGLContext context = egl.createContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, attribList);
2076
2077                 const EGLenum error = egl.getError();
2078                 if (error != EGL_BAD_ATTRIBUTE)
2079                 {
2080                         log << TestLog::Message
2081                                 << "Test failed! eglCreateContext() returned with error [" << eglu::getErrorStr(error) << ", expected " << eglu::getErrorStr(EGL_BAD_ATTRIBUTE) << "]"
2082                                 << TestLog::EndMessage;
2083
2084                         isOk = false;
2085                 }
2086
2087                 if (context != EGL_NO_CONTEXT)
2088                         egl.destroyContext(m_eglDisplay, context);
2089
2090                 if (isOk)
2091                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2092                 else
2093                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2094
2095                 return STOP;
2096         }
2097 };
2098
2099 class RecoverFromResetCase : public RobustnessTestCase
2100 {
2101 public:
2102         RecoverFromResetCase (EglTestContext& eglTestCtx, const char* name, const char* description, Params params)
2103                 : RobustnessTestCase (eglTestCtx, name, description,  params) {}
2104
2105         TestCase::IterateResult iterate (void)
2106         {
2107                 TestLog&        log             = m_testCtx.getLog();
2108
2109                 log << tcu::TestLog::Message
2110                         << "Provoke a context reset and wait for glGetGraphicsResetStatus() to return NO_ERROR_KHR.\n"
2111                         << "Destroy the old context and successfully create a new context.\n\n"
2112                         << tcu::TestLog::EndMessage;
2113
2114                 const EGLint attribList[] =
2115                 {
2116                         EGL_CONTEXT_CLIENT_VERSION, 3,
2117                         EGL_CONTEXT_MINOR_VERSION_KHR, 0,
2118                         EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE,
2119                         EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET,
2120                         EGL_NONE
2121                 };
2122
2123                 checkRequiredEGLExtensions(attribList);
2124
2125                 log << tcu::TestLog::Message << "Create context A" << tcu::TestLog::EndMessage;
2126                 RenderingContext contextA(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
2127                 contextA.makeCurrent(m_eglSurface);
2128
2129                 glw::Functions gl;
2130                 contextA.initGLFunctions(&gl, paramsToApiType(m_params));
2131                 checkGLSupportForParams(gl, m_params);
2132
2133                 DE_ASSERT(m_params.getContextResetType() == CONTEXTRESETTYPE_INFINITE_LOOP);
2134                 de::UniquePtr<ContextReset> contextReset(new InfiniteLoop(gl, log, m_params.getShaderType()));
2135
2136                 contextReset->setup();
2137                 contextReset->draw();
2138
2139                 try
2140                 {
2141                         contextReset->teardown();
2142                         contextReset->finish();
2143                 }
2144                 catch (const glu::Error& error)
2145                 {
2146                         if (error.getError() == GL_CONTEXT_LOST)
2147                         {
2148                                 const glw::GLint status = gl.getGraphicsResetStatus();
2149                                 if (status == GL_NO_ERROR)
2150                                 {
2151                                         log << tcu::TestLog::Message
2152                                                 << "Test failed! glGetGraphicsResetStatus() returned wrong value [" << glu::getErrorStr(status) << ", expected " << glu::getErrorStr(GL_GUILTY_CONTEXT_RESET) << "]"
2153                                                 << tcu::TestLog::EndMessage;
2154
2155                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2156                                         return STOP;
2157                                 }
2158
2159                                 const int       sleepTimeMs             = 1000;                         // (1 second)
2160                                 int                     timeout                 = sleepTimeMs * 10; // (10 seconds)
2161                                 int                     reset_status    = -1;
2162
2163                                 // wait for context to reset
2164                                 while ((reset_status = gl.getGraphicsResetStatus() != GL_NO_ERROR) && timeout > 0)
2165                                 {
2166                                         deSleep(sleepTimeMs);
2167                                         timeout -= sleepTimeMs;
2168                                 }
2169
2170                                 if (reset_status != GL_NO_ERROR)
2171                                 {
2172                                         log     << tcu::TestLog::Message
2173                                                 << "Test failed! Context did not reset. glGetGraphicsResetStatus() returned wrong value [" << glu::getErrorStr(reset_status) << ", expected " << glu::getErrorStr(GL_NO_ERROR) << "]"
2174                                                 << tcu::TestLog::EndMessage;
2175
2176                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2177                                         return STOP;
2178                                 }
2179                         }
2180                         else
2181                         {
2182                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Test failed! glGetError() returned wrong value. Expected GL_CONTEXT_LOST in context A");
2183                                 return STOP;
2184                         }
2185                 }
2186
2187                 try
2188                 {
2189                         log << tcu::TestLog::Message << "Create context B" << tcu::TestLog::EndMessage;
2190                         RenderingContext contextB(m_eglTestCtx, attribList, m_eglConfig, m_eglDisplay, EGL_NO_CONTEXT);
2191                 }
2192                 catch (const glu::Error&)
2193                 {
2194                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Test failed! Could not create new context. glGetError() returned wrong value. Expected GL_NO_ERROR");
2195                         return STOP;
2196                 }
2197
2198                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2199                 return STOP;
2200         }
2201 };
2202
2203 } // anonymous
2204
2205 // Note: Tests limited to openGLES 3.1 contexts only
2206 TestCaseGroup* createRobustnessTests (EglTestContext& eglTestCtx)
2207 {
2208         de::MovePtr<TestCaseGroup> group (new TestCaseGroup(eglTestCtx, "robustness", "KHR_robustness tests"));
2209
2210         tcu::TestCaseGroup* const contextCreationTestGroup                      = new TestCaseGroup(eglTestCtx, "create_context",                                               "Test valid context_creation attributes");
2211         tcu::TestCaseGroup* const contextResetTestGroup                         = new TestCaseGroup(eglTestCtx, "reset_context",                                                "Test context resets scenarios");
2212         tcu::TestCaseGroup* const negativeContextTestGroup                      = new TestCaseGroup(eglTestCtx, "negative_context",                                             "Test invalid context creation attributes");
2213
2214         tcu::TestCaseGroup* const shadersTestGroup                                      = new TestCaseGroup(eglTestCtx, "shaders",                                                              "Shader specific context reset tests");
2215         tcu::TestCaseGroup* const fixedFunctionTestGroup                        = new TestCaseGroup(eglTestCtx, "fixed_function_pipeline",                              "Fixed function pipeline context reset tests with robust context");
2216         tcu::TestCaseGroup* const fixedFunctionNonRobustTestGroup       = new TestCaseGroup(eglTestCtx, "fixed_function_pipeline_non_robust",   "Fixed function pipeline context reset tests with non-robust context");
2217
2218         tcu::TestCaseGroup* const infiniteLoopTestGroup                         = new TestCaseGroup(eglTestCtx, "infinite_loop",                                                "Infinite loop scenarios");
2219         tcu::TestCaseGroup* const outOfBoundsTestGroup                          = new TestCaseGroup(eglTestCtx, "out_of_bounds",                                                "Out of bounds access scenarios with robust context");
2220
2221         tcu::TestCaseGroup* const outOfBoundsNonRobustTestGroup         = new TestCaseGroup(eglTestCtx, "out_of_bounds_non_robust",                             "Out of bounds access scenarios with non-robust context");
2222
2223         const string resetScenarioDescription   = "query error states and reset notifications";
2224         const string syncScenarioDescription    = "query sync status with getSynciv()";
2225         const string queryScenarioDescription   = "check availability of query result with getQueryObjectiv()";
2226         const string sharedScenarioDescription  = "check reset notification is propagated to shared context";
2227         const string recoverScenarioDescription = "delete the old context and create a new one";
2228
2229         // infinite loop test cases
2230         {
2231                 tcu::TestCaseGroup* const infiniteLoopResetTestGroup    = new TestCaseGroup(eglTestCtx, "reset_status",                         "Tests that query the reset status after a context reset has occurred");
2232                 tcu::TestCaseGroup* const infiniteLoopSyncTestGroup             = new TestCaseGroup(eglTestCtx, "sync_status",                          "Tests that query the sync status after a context reset has occurred");
2233                 tcu::TestCaseGroup* const infiniteLoopQueryTestGroup    = new TestCaseGroup(eglTestCtx, "query_status",                         "Tests that query the state of a query object after a context reset has occurred");
2234                 tcu::TestCaseGroup* const infiniteLoopSharedTestGroup   = new TestCaseGroup(eglTestCtx, "shared_context_status",        "Tests that query the state of a shared context after a reset has occurred");
2235                 tcu::TestCaseGroup* const infiniteLoopRecoverTestGroup  = new TestCaseGroup(eglTestCtx, "recover_from_reset",           "Tests that attempt to create a new context after a context has occurred");
2236
2237                 static const RobustnessTestCase::Params s_infiniteLoopCases[] =
2238                 {
2239                         RobustnessTestCase::Params("vertex",                            "Provoke a context reset in vertex shader and ",                                CONTEXTRESETTYPE_INFINITE_LOOP, SHADERTYPE_VERT),
2240                         RobustnessTestCase::Params("fragment",                          "Provoke a context reset in fragment shader and ",                              CONTEXTRESETTYPE_INFINITE_LOOP, SHADERTYPE_FRAG),
2241                         RobustnessTestCase::Params("vertex_and_fragment",       "Provoke a context reset in vertex and fragment shader and ",   CONTEXTRESETTYPE_INFINITE_LOOP, SHADERTYPE_VERT_AND_FRAG),
2242                         RobustnessTestCase::Params("compute",                           "Provoke a context reset in compute shader and ",                               CONTEXTRESETTYPE_INFINITE_LOOP, SHADERTYPE_COMPUTE),
2243                 };
2244
2245                 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_infiniteLoopCases); ++testNdx)
2246                 {
2247                         const RobustnessTestCase::Params& test = s_infiniteLoopCases[testNdx];
2248                         infiniteLoopResetTestGroup->addChild    (new BasicResetCase                             (eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2249                         infiniteLoopSyncTestGroup->addChild             (new SyncObjectResetCase                (eglTestCtx, test.getName().c_str(), (test.getDescription() + syncScenarioDescription).c_str(), test));
2250                         infiniteLoopQueryTestGroup->addChild    (new QueryObjectResetCase               (eglTestCtx, test.getName().c_str(), (test.getDescription() + queryScenarioDescription).c_str(), test));
2251                         infiniteLoopSharedTestGroup->addChild   (new SharedContextResetCase             (eglTestCtx, test.getName().c_str(), (test.getDescription() + sharedScenarioDescription).c_str(), test));
2252                         infiniteLoopRecoverTestGroup->addChild  (new RecoverFromResetCase               (eglTestCtx, test.getName().c_str(), (test.getDescription() + recoverScenarioDescription).c_str(), test));
2253                 }
2254
2255                 infiniteLoopTestGroup->addChild(infiniteLoopResetTestGroup);
2256                 infiniteLoopTestGroup->addChild(infiniteLoopSyncTestGroup);
2257                 infiniteLoopTestGroup->addChild(infiniteLoopQueryTestGroup);
2258                 infiniteLoopTestGroup->addChild(infiniteLoopSharedTestGroup);
2259                 infiniteLoopTestGroup->addChild(infiniteLoopRecoverTestGroup);
2260         }
2261
2262         // out-of-bounds test cases
2263         {
2264                 // robust context
2265                 tcu::TestCaseGroup* const uboReadArrayResetTestGroup    = new TestCaseGroup(eglTestCtx, "uniform_block",                "Uniform Block Accesses");
2266                 tcu::TestCaseGroup* const uboWriteArrayResetTestGroup   = new TestCaseGroup(eglTestCtx, "uniform_block",                "Uniform Block Accesses");
2267                 tcu::TestCaseGroup* const ssboWriteArrayResetTestGroup  = new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
2268                 tcu::TestCaseGroup* const ssboReadArrayResetTestGroup   = new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
2269                 tcu::TestCaseGroup* const localWriteArrayResetTestGroup = new TestCaseGroup(eglTestCtx, "local_array",                  "Local array accesses");
2270                 tcu::TestCaseGroup* const localReadArrayResetTestGroup  = new TestCaseGroup(eglTestCtx, "local_array",                  "Local array accesses");
2271
2272                 // non-robust context (internal use only)
2273                 tcu::TestCaseGroup* const uboReadArrayResetNonRobustTestGroup           = new TestCaseGroup(eglTestCtx, "uniform_block",                "Uniform Block Accesses");
2274                 tcu::TestCaseGroup* const uboWriteArrayResetNonRobustTestGroup          = new TestCaseGroup(eglTestCtx, "uniform_block",                "Uniform Block Accesses");
2275                 tcu::TestCaseGroup* const ssboWriteArrayResetNonRobustTestGroup         = new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
2276                 tcu::TestCaseGroup* const ssboReadArrayResetNonRobustTestGroup          = new TestCaseGroup(eglTestCtx, "shader_storage_block", "Shader Storage Block accesses");
2277                 tcu::TestCaseGroup* const localWriteArrayResetNonRobustTestGroup        = new TestCaseGroup(eglTestCtx, "local_array",                  "Local array accesses");
2278                 tcu::TestCaseGroup* const localReadArrayResetNonRobustTestGroup         = new TestCaseGroup(eglTestCtx, "local_array",                  "Local array accesses");
2279
2280                 static const RobustnessTestCase::Params s_outOfBoundReadCases[] =
2281                 {
2282                         // ubo read only
2283                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                        RESOURCETYPE_UBO, READWRITETYPE_READ),
2284                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                        RESOURCETYPE_UBO, READWRITETYPE_READ),
2285                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,       RESOURCETYPE_UBO, READWRITETYPE_READ),
2286                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,                     RESOURCETYPE_UBO, READWRITETYPE_READ),
2287
2288                         // ssbo read only
2289                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                        RESOURCETYPE_SSBO, READWRITETYPE_READ),
2290                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                        RESOURCETYPE_SSBO, READWRITETYPE_READ),
2291                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,       RESOURCETYPE_SSBO, READWRITETYPE_READ),
2292                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,                     RESOURCETYPE_SSBO, READWRITETYPE_READ),
2293
2294                         // local array read only
2295                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                        RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
2296                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                        RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
2297                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,       RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
2298                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,                     RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
2299
2300                         // ubo read only (non-robust)
2301                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                       RESOURCETYPE_UBO, READWRITETYPE_READ),
2302                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                       RESOURCETYPE_UBO, READWRITETYPE_READ),
2303                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,      RESOURCETYPE_UBO, READWRITETYPE_READ),
2304                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,            RESOURCETYPE_UBO, READWRITETYPE_READ),
2305
2306                         // ssbo read only (non-robust)
2307                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                       RESOURCETYPE_SSBO, READWRITETYPE_READ),
2308                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                       RESOURCETYPE_SSBO, READWRITETYPE_READ),
2309                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,      RESOURCETYPE_SSBO, READWRITETYPE_READ),
2310                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,            RESOURCETYPE_SSBO, READWRITETYPE_READ),
2311
2312                         // local array read only (non-robust)
2313                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                       RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
2314                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                       RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
2315                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,      RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
2316                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,            RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_READ),
2317                 };
2318
2319                 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_outOfBoundReadCases); ++testNdx)
2320                 {
2321                         const RobustnessTestCase::Params& test = s_outOfBoundReadCases[testNdx];
2322
2323                         if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
2324                                 uboReadArrayResetTestGroup->addChild                            (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2325
2326                         if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
2327                                 uboReadArrayResetNonRobustTestGroup->addChild           (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2328
2329                         if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
2330                                 ssboReadArrayResetTestGroup->addChild                           (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2331
2332                         if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
2333                                 ssboReadArrayResetNonRobustTestGroup->addChild          (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2334
2335                         if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
2336                                 localReadArrayResetTestGroup->addChild                          (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2337
2338                         if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
2339                                 localReadArrayResetNonRobustTestGroup->addChild         (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2340                 }
2341
2342                 static const RobustnessTestCase::Params s_outOfBoundWriteCases[] =
2343                 {
2344                         // ubo write only
2345                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                        RESOURCETYPE_UBO, READWRITETYPE_WRITE),
2346                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                        RESOURCETYPE_UBO, READWRITETYPE_WRITE),
2347                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,       RESOURCETYPE_UBO, READWRITETYPE_WRITE),
2348                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,                     RESOURCETYPE_UBO, READWRITETYPE_WRITE),
2349
2350                         // ssbo write only
2351                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                        RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
2352                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                        RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
2353                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,       RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
2354                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,                     RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
2355
2356                         // local array write only
2357                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                        RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
2358                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                        RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
2359                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,       RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
2360                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,                     RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
2361
2362                         // ubo write only (non-robust)
2363                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                       RESOURCETYPE_UBO, READWRITETYPE_WRITE),
2364                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                       RESOURCETYPE_UBO, READWRITETYPE_WRITE),
2365                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,      RESOURCETYPE_UBO, READWRITETYPE_WRITE),
2366                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,            RESOURCETYPE_UBO, READWRITETYPE_WRITE),
2367
2368                         // ssbo write only (non-robust)
2369                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                       RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
2370                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                       RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
2371                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,      RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
2372                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,            RESOURCETYPE_SSBO, READWRITETYPE_WRITE),
2373
2374                         // local array write only (non-robust)
2375                         RobustnessTestCase::Params ("vertex",                           "Provoke a context reset in vertex shader and ",                                ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT,                       RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
2376                         RobustnessTestCase::Params ("fragment",                         "Provoke a context reset in fragment shader and ",                              ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_FRAG,                       RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
2377                         RobustnessTestCase::Params ("vertex_and_fragment",      "Provoke a context reset in vertex and fragment shader and ",   ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_VERT_AND_FRAG,      RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
2378                         RobustnessTestCase::Params ("compute",                          "Provoke a context reset in compute shader and ",                               ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_SHADER_OOB, SHADERTYPE_COMPUTE,            RESOURCETYPE_LOCAL_ARRAY, READWRITETYPE_WRITE),
2379                 };
2380
2381                 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_outOfBoundWriteCases); ++testNdx)
2382                 {
2383                         const RobustnessTestCase::Params& test = s_outOfBoundWriteCases[testNdx];
2384
2385                                 if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
2386                                         uboWriteArrayResetTestGroup->addChild                           (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2387
2388                                 if (test.getResourceType() == RESOURCETYPE_UBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
2389                                         uboWriteArrayResetNonRobustTestGroup->addChild          (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2390
2391                                 if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
2392                                         ssboWriteArrayResetTestGroup->addChild                          (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2393
2394                                 if (test.getResourceType() == RESOURCETYPE_SSBO && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
2395                                         ssboWriteArrayResetNonRobustTestGroup->addChild         (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2396
2397                                 if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_TRUE)
2398                                         localWriteArrayResetTestGroup->addChild                         (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2399
2400                                 if (test.getResourceType() == RESOURCETYPE_LOCAL_ARRAY && test.getRobustAccessType() == ROBUSTACCESS_FALSE)
2401                                         localWriteArrayResetNonRobustTestGroup->addChild        (new BasicResetCase(eglTestCtx, test.getName().c_str(), (test.getDescription() + resetScenarioDescription).c_str(), test));
2402                 }
2403
2404                 // robust Context
2405                 tcu::TestCaseGroup* const outOfBoundsResetReadAccessTestGroup   = new TestCaseGroup(eglTestCtx, "reads",        "Out of bounds read accesses");
2406                 tcu::TestCaseGroup* const outOfBoundsResetWriteAccessTestGroup  = new TestCaseGroup(eglTestCtx, "writes",       "Out of bounds write accesses");
2407
2408                 outOfBoundsResetReadAccessTestGroup->addChild(uboReadArrayResetTestGroup);
2409                 outOfBoundsResetReadAccessTestGroup->addChild(ssboReadArrayResetTestGroup);
2410                 outOfBoundsResetReadAccessTestGroup->addChild(localReadArrayResetTestGroup);
2411
2412                 outOfBoundsResetWriteAccessTestGroup->addChild(uboWriteArrayResetTestGroup);
2413                 outOfBoundsResetWriteAccessTestGroup->addChild(ssboWriteArrayResetTestGroup);
2414                 outOfBoundsResetWriteAccessTestGroup->addChild(localWriteArrayResetTestGroup);
2415
2416                 tcu::TestCaseGroup* const outOfBoundsResetTestGroup             = new TestCaseGroup(eglTestCtx, "reset_status", "Tests that query the reset status after a context reset has occurred");
2417
2418                 outOfBoundsResetTestGroup->addChild(outOfBoundsResetReadAccessTestGroup);
2419                 outOfBoundsResetTestGroup->addChild(outOfBoundsResetWriteAccessTestGroup);
2420
2421                 outOfBoundsTestGroup->addChild(outOfBoundsResetTestGroup);
2422
2423                 // non-robust Context (internal use only)
2424                 tcu::TestCaseGroup* const outOfBoundsResetReadAccessNonRobustTestGroup  = new TestCaseGroup(eglTestCtx, "reads",        "Out of bounds read accesses");
2425                 tcu::TestCaseGroup* const outOfBoundsResetWriteAccessNonRobustTestGroup = new TestCaseGroup(eglTestCtx, "writes",       "Out of bounds write accesses");
2426
2427                 outOfBoundsResetReadAccessNonRobustTestGroup->addChild(uboReadArrayResetNonRobustTestGroup);
2428                 outOfBoundsResetReadAccessNonRobustTestGroup->addChild(ssboReadArrayResetNonRobustTestGroup);
2429                 outOfBoundsResetReadAccessNonRobustTestGroup->addChild(localReadArrayResetNonRobustTestGroup);
2430
2431                 outOfBoundsResetWriteAccessNonRobustTestGroup->addChild(uboWriteArrayResetNonRobustTestGroup);
2432                 outOfBoundsResetWriteAccessNonRobustTestGroup->addChild(ssboWriteArrayResetNonRobustTestGroup);
2433                 outOfBoundsResetWriteAccessNonRobustTestGroup->addChild(localWriteArrayResetNonRobustTestGroup);
2434
2435                 tcu::TestCaseGroup* const outOfBoundsResetNonRobustTestGroup            = new TestCaseGroup(eglTestCtx, "reset_status", "Tests that query the reset status after a context reset has occurred");
2436
2437                 outOfBoundsResetNonRobustTestGroup->addChild(outOfBoundsResetReadAccessNonRobustTestGroup);
2438                 outOfBoundsResetNonRobustTestGroup->addChild(outOfBoundsResetWriteAccessNonRobustTestGroup);
2439
2440                 outOfBoundsNonRobustTestGroup->addChild(outOfBoundsResetNonRobustTestGroup);
2441         }
2442
2443         // fixed function test cases
2444         {
2445                 // robust context
2446                 tcu::TestCaseGroup* const fixedFunctionResetStatusTestGroup                             = new TestCaseGroup(eglTestCtx, "reset_status", "Tests that query the reset status after a context reset has occurred");
2447
2448                 // non-robust context (internal use only)
2449                 tcu::TestCaseGroup* const fixedFunctionResetStatusNonRobustTestGroup    = new TestCaseGroup(eglTestCtx, "reset_status", "Tests that query the reset status after a context reset has occurred");
2450
2451                 static const RobustnessTestCase::Params s_fixedFunctionPipelineCases[] =
2452                 {
2453                         RobustnessTestCase::Params( "index_buffer_out_of_bounds",       "Provoke context reset and query error states and reset notifications", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_INDICES),
2454                         RobustnessTestCase::Params( "vertex_buffer_out_of_bounds",      "Provoke context reset and query error states and reset notifications", ROBUSTACCESS_TRUE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_VERTICES),
2455
2456                         RobustnessTestCase::Params( "index_buffer_out_of_bounds",       "Provoke context reset and query error states and reset notifications", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_INDICES),
2457                         RobustnessTestCase::Params( "vertex_buffer_out_of_bounds",      "Provoke context reset and query error states and reset notifications", ROBUSTACCESS_FALSE, CONTEXTRESETTYPE_FIXED_FUNC_OOB, FIXEDFUNCTIONTYPE_VERTICES),
2458                 };
2459
2460                 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_fixedFunctionPipelineCases); ++testNdx)
2461                 {
2462                         const RobustnessTestCase::Params& test = s_fixedFunctionPipelineCases[testNdx];
2463                         if (test.getRobustAccessType() == ROBUSTACCESS_TRUE)
2464                                 fixedFunctionResetStatusTestGroup->addChild(new BasicResetCase(eglTestCtx, test.getName().c_str(), test.getDescription().c_str(), test));
2465                         else
2466                                 fixedFunctionResetStatusNonRobustTestGroup->addChild(new BasicResetCase(eglTestCtx, test.getName().c_str(), test.getDescription().c_str(), test));
2467                 }
2468
2469                 fixedFunctionTestGroup->addChild(fixedFunctionResetStatusTestGroup);
2470                 fixedFunctionNonRobustTestGroup->addChild(fixedFunctionResetStatusNonRobustTestGroup);
2471         }
2472
2473         // context creation query cases
2474         {
2475                 contextCreationTestGroup->addChild(new QueryRobustAccessCase    (eglTestCtx, "query_robust_access",             "Query robust access after successfully creating a robust context"));
2476                 contextCreationTestGroup->addChild(new NoResetNotificationCase  (eglTestCtx, "no_reset_notification",   "Query reset notification strategy after specifying GL_NO_RESET_NOTIFICATION"));
2477                 contextCreationTestGroup->addChild(new LoseContextOnResetCase   (eglTestCtx, "lose_context_on_reset",   "Query reset notification strategy after specifying GL_LOSE_CONTEXT_ON_RESET"));
2478         }
2479
2480         // invalid context creation cases
2481         {
2482                 negativeContextTestGroup->addChild(new InvalidContextCase                       (eglTestCtx, "invalid_robust_context_creation",                 "Create a non-robust context but specify a reset notification strategy"));
2483                 negativeContextTestGroup->addChild(new InvalidShareContextCase          (eglTestCtx, "invalid_robust_shared_context_creation",  "Create a context share group with conflicting reset notification strategies"));
2484                 negativeContextTestGroup->addChild(new InvalidNotificationEnumCase      (eglTestCtx, "invalid_notification_strategy_enum",              "Create a robust context using EGL 1.5 only enum with EGL versions <= 1.4" ));
2485         }
2486
2487         shadersTestGroup->addChild(infiniteLoopTestGroup);
2488         shadersTestGroup->addChild(outOfBoundsTestGroup);
2489         shadersTestGroup->addChild(outOfBoundsNonRobustTestGroup);
2490
2491         contextResetTestGroup->addChild(shadersTestGroup);
2492         contextResetTestGroup->addChild(fixedFunctionTestGroup);
2493         contextResetTestGroup->addChild(fixedFunctionNonRobustTestGroup);
2494
2495         group->addChild(contextCreationTestGroup);
2496         group->addChild(contextResetTestGroup);
2497         group->addChild(negativeContextTestGroup);
2498
2499         return group.release();
2500 }
2501
2502 } // egl
2503 } // deqp