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