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