• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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