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