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