1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 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 Multisample interpolation tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fShaderMultisampleInterpolationTests.hpp"
25 #include "es31fMultisampleShaderRenderCase.hpp"
26 #include "tcuTestLog.hpp"
27 #include "tcuRGBA.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "tcuRenderTarget.hpp"
31 #include "gluContextInfo.hpp"
32 #include "gluShaderProgram.hpp"
33 #include "gluRenderContext.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36 #include "deArrayUtil.hpp"
37 #include "deStringUtil.hpp"
38 #include "deMath.h"
39 
40 #include <map>
41 
42 namespace deqp
43 {
44 namespace gles31
45 {
46 namespace Functional
47 {
48 namespace
49 {
50 
specializeShader(const std::string & shaderSource,const glu::ContextType & contextType)51 static std::string specializeShader(const std::string& shaderSource, const glu::ContextType& contextType)
52 {
53 	const bool supportsES32 = glu::contextSupports(contextType, glu::ApiType::es(3, 2));
54 
55 	std::map<std::string, std::string> args;
56 	args["GLSL_VERSION_DECL"]							= glu::getGLSLVersionDeclaration(glu::getContextTypeGLSLVersion(contextType));
57 	args["GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION"]	= supportsES32 ? "" : "#extension GL_OES_shader_multisample_interpolation : require\n";
58 	args["GLSL_EXT_SAMPLE_VARIABLES"]					= supportsES32 ? "" : "#extension GL_OES_sample_variables : require\n";
59 
60 	return tcu::StringTemplate(shaderSource).specialize(args);
61 }
62 
verifyGreenImage(const tcu::Surface & image,tcu::TestLog & log)63 static bool verifyGreenImage (const tcu::Surface& image, tcu::TestLog& log)
64 {
65 	bool error = false;
66 
67 	log << tcu::TestLog::Message << "Verifying result image, expecting green." << tcu::TestLog::EndMessage;
68 
69 	// all pixels must be green
70 
71 	for (int y = 0; y < image.getHeight(); ++y)
72 	for (int x = 0; x < image.getWidth(); ++x)
73 	{
74 		const tcu::RGBA color			= image.getPixel(x, y);
75 		const int		greenThreshold	= 8;
76 
77 		if (color.getRed() > 0 || color.getGreen() < 255-greenThreshold || color.getBlue() > 0)
78 			error = true;
79 	}
80 
81 	if (error)
82 		log	<< tcu::TestLog::Image("ResultImage", "Result Image", image.getAccess())
83 			<< tcu::TestLog::Message
84 			<< "Image verification failed."
85 			<< tcu::TestLog::EndMessage;
86 	else
87 		log	<< tcu::TestLog::Image("ResultImage", "Result Image", image.getAccess())
88 			<< tcu::TestLog::Message
89 			<< "Image verification passed."
90 			<< tcu::TestLog::EndMessage;
91 
92 	return !error;
93 }
94 
95 class MultisampleShadeCountRenderCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
96 {
97 public:
98 						MultisampleShadeCountRenderCase		(Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
99 	virtual				~MultisampleShadeCountRenderCase	(void);
100 
101 	void				init								(void);
102 
103 private:
104 	enum
105 	{
106 		RENDER_SIZE = 128
107 	};
108 
109 	virtual std::string	getIterationDescription				(int iteration) const;
110 	bool				verifyImage							(const tcu::Surface& resultImage);
111 };
112 
MultisampleShadeCountRenderCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target)113 MultisampleShadeCountRenderCase::MultisampleShadeCountRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
114 	: MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, RENDER_SIZE, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_PER_ITERATION_SHADER)
115 {
116 	m_numIterations = -1; // must be set by deriving class
117 }
118 
~MultisampleShadeCountRenderCase(void)119 MultisampleShadeCountRenderCase::~MultisampleShadeCountRenderCase (void)
120 {
121 }
122 
init(void)123 void MultisampleShadeCountRenderCase::init (void)
124 {
125 	// requirements
126 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation") && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
127 		TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
128 
129 	MultisampleShaderRenderUtil::MultisampleRenderCase::init();
130 }
131 
getIterationDescription(int iteration) const132 std::string	MultisampleShadeCountRenderCase::getIterationDescription (int iteration) const
133 {
134 	// must be overriden
135 	DE_UNREF(iteration);
136 	DE_ASSERT(false);
137 	return "";
138 }
139 
verifyImage(const tcu::Surface & resultImage)140 bool MultisampleShadeCountRenderCase::verifyImage (const tcu::Surface& resultImage)
141 {
142 	const bool				isSingleSampleTarget	= (m_renderTarget != TARGET_DEFAULT && m_numRequestedSamples == 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1);
143 	const int				numShadesRequired		= (isSingleSampleTarget) ? (2) : (m_numTargetSamples + 1);
144 	const int				rareThreshold			= 100;
145 	int						rareCount				= 0;
146 	std::map<deUint32, int>	shadeFrequency;
147 
148 	m_testCtx.getLog()
149 		<< tcu::TestLog::Image("ResultImage", "Result Image", resultImage.getAccess())
150 		<< tcu::TestLog::Message
151 		<< "Verifying image has (at least) " << numShadesRequired << " different shades.\n"
152 		<< "Excluding pixels with no full coverage (pixels on the shared edge of the triangle pair)."
153 		<< tcu::TestLog::EndMessage;
154 
155 	for (int y = 0; y < RENDER_SIZE; ++y)
156 	for (int x = 0; x < RENDER_SIZE; ++x)
157 	{
158 		const tcu::RGBA	color	= resultImage.getPixel(x, y);
159 		const deUint32	packed	= ((deUint32)color.getRed()) + ((deUint32)color.getGreen() << 8) + ((deUint32)color.getGreen() << 16);
160 
161 		// on the triangle edge, skip
162 		if (x == y)
163 			continue;
164 
165 		if (shadeFrequency.find(packed) == shadeFrequency.end())
166 			shadeFrequency[packed] = 1;
167 		else
168 			shadeFrequency[packed] = shadeFrequency[packed] + 1;
169 	}
170 
171 	for (std::map<deUint32, int>::const_iterator it = shadeFrequency.begin(); it != shadeFrequency.end(); ++it)
172 		if (it->second < rareThreshold)
173 			rareCount++;
174 
175 	m_testCtx.getLog()
176 		<< tcu::TestLog::Message
177 		<< "Found " << (int)shadeFrequency.size() << " different shades.\n"
178 		<< "\tRare (less than " << rareThreshold << " pixels): " << rareCount << "\n"
179 		<< "\tCommon: " << (int)shadeFrequency.size() - rareCount << "\n"
180 		<< tcu::TestLog::EndMessage;
181 
182 	if ((int)shadeFrequency.size() < numShadesRequired)
183 	{
184 		m_testCtx.getLog() << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage;
185 		return false;
186 	}
187 	return true;
188 }
189 
190 class SampleQualifierRenderCase : public MultisampleShadeCountRenderCase
191 {
192 public:
193 				SampleQualifierRenderCase	(Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
194 				~SampleQualifierRenderCase	(void);
195 
196 	void		init						(void);
197 
198 private:
199 	std::string	genVertexSource				(int numTargetSamples) const;
200 	std::string	genFragmentSource			(int numTargetSamples) const;
201 	std::string	getIterationDescription		(int iteration) const;
202 };
203 
SampleQualifierRenderCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target)204 SampleQualifierRenderCase::SampleQualifierRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
205 	: MultisampleShadeCountRenderCase(context, name, description, numSamples, target)
206 {
207 	m_numIterations = 6; // float, vec2, .3, .4, array, struct
208 }
209 
~SampleQualifierRenderCase(void)210 SampleQualifierRenderCase::~SampleQualifierRenderCase (void)
211 {
212 }
213 
init(void)214 void SampleQualifierRenderCase::init (void)
215 {
216 	const bool isSingleSampleTarget = (m_renderTarget != TARGET_DEFAULT && m_numRequestedSamples == 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1);
217 
218 	// test purpose and expectations
219 	if (isSingleSampleTarget)
220 	{
221 		m_testCtx.getLog()
222 			<< tcu::TestLog::Message
223 			<< "Verifying that a sample-qualified varying is given different values for different samples.\n"
224 			<< "	Render high-frequency function, map result to black/white.\n"
225 			<< "	=> Resulting image image should contain both black and white pixels.\n"
226 			<< tcu::TestLog::EndMessage;
227 	}
228 	else
229 	{
230 		m_testCtx.getLog()
231 			<< tcu::TestLog::Message
232 			<< "Verifying that a sample-qualified varying is given different values for different samples.\n"
233 			<< "	Render high-frequency function, map result to black/white.\n"
234 			<< "	=> Resulting image should contain n+1 shades of gray, n = sample count.\n"
235 			<< tcu::TestLog::EndMessage;
236 	}
237 
238 	MultisampleShadeCountRenderCase::init();
239 }
240 
genVertexSource(int numTargetSamples) const241 std::string	SampleQualifierRenderCase::genVertexSource (int numTargetSamples) const
242 {
243 	DE_UNREF(numTargetSamples);
244 
245 	std::ostringstream buf;
246 
247 	buf <<	"${GLSL_VERSION_DECL}\n"
248 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
249 			"in highp vec4 a_position;\n";
250 
251 	if (m_iteration == 0)
252 		buf << "sample out highp float v_input;\n";
253 	else if (m_iteration == 1)
254 		buf << "sample out highp vec2 v_input;\n";
255 	else if (m_iteration == 2)
256 		buf << "sample out highp vec3 v_input;\n";
257 	else if (m_iteration == 3)
258 		buf << "sample out highp vec4 v_input;\n";
259 	else if (m_iteration == 4)
260 		buf << "sample out highp float[2] v_input;\n";
261 	else if (m_iteration == 5)
262 		buf << "struct VaryingStruct { highp float a; highp float b; };\n"
263 			   "sample out VaryingStruct v_input;\n";
264 	else
265 		DE_ASSERT(false);
266 
267 	buf <<	"void main (void)\n"
268 			"{\n"
269 			"	gl_Position = a_position;\n";
270 
271 	if (m_iteration == 0)
272 		buf << "	v_input = a_position.x + exp(a_position.y) + step(0.9, a_position.x)*step(a_position.y, -0.9)*8.0;\n";
273 	else if (m_iteration == 1)
274 		buf << "	v_input = a_position.xy;\n";
275 	else if (m_iteration == 2)
276 		buf << "	v_input = vec3(a_position.xy, a_position.x * 2.0 - a_position.y);\n";
277 	else if (m_iteration == 3)
278 		buf << "	v_input = vec4(a_position.xy, a_position.x * 2.0 - a_position.y, a_position.x*a_position.y);\n";
279 	else if (m_iteration == 4)
280 		buf << "	v_input[0] = a_position.x;\n"
281 			   "	v_input[1] = a_position.y;\n";
282 	else if (m_iteration == 5)
283 		buf << "	v_input.a = a_position.x;\n"
284 			   "	v_input.b = a_position.y;\n";
285 	else
286 		DE_ASSERT(false);
287 
288 	buf <<	"}";
289 
290 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
291 }
292 
genFragmentSource(int numTargetSamples) const293 std::string	SampleQualifierRenderCase::genFragmentSource (int numTargetSamples) const
294 {
295 	DE_UNREF(numTargetSamples);
296 
297 	std::ostringstream buf;
298 
299 	buf <<	"${GLSL_VERSION_DECL}\n"
300 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}";
301 
302 	if (m_iteration == 0)
303 		buf << "sample in highp float v_input;\n";
304 	else if (m_iteration == 1)
305 		buf << "sample in highp vec2 v_input;\n";
306 	else if (m_iteration == 2)
307 		buf << "sample in highp vec3 v_input;\n";
308 	else if (m_iteration == 3)
309 		buf << "sample in highp vec4 v_input;\n";
310 	else if (m_iteration == 4)
311 		buf << "sample in highp float[2] v_input;\n";
312 	else if (m_iteration == 5)
313 		buf << "struct VaryingStruct { highp float a; highp float b; };\n"
314 			   "sample in VaryingStruct v_input;\n";
315 	else
316 		DE_ASSERT(false);
317 
318 	buf <<	"layout(location = 0) out mediump vec4 fragColor;\n"
319 			"void main (void)\n"
320 			"{\n";
321 
322 	if (m_iteration == 0)
323 		buf << "	highp float field = exp(v_input) + v_input*v_input;\n";
324 	else if (m_iteration == 1)
325 		buf << "	highp float field = dot(v_input.xy, v_input.xy) + dot(21.0 * v_input.xx, sin(3.1 * v_input.xy));\n";
326 	else if (m_iteration == 2)
327 		buf << "	highp float field = dot(v_input.xy, v_input.xy) + dot(21.0 * v_input.zx, sin(3.1 * v_input.zy));\n";
328 	else if (m_iteration == 3)
329 		buf << "	highp float field = dot(v_input.xy, v_input.zw) + dot(21.0 * v_input.zy, sin(3.1 * v_input.zw));\n";
330 	else if (m_iteration == 4)
331 		buf << "	highp float field = dot(vec2(v_input[0], v_input[1]), vec2(v_input[0], v_input[1])) + dot(21.0 * vec2(v_input[0]), sin(3.1 * vec2(v_input[0], v_input[1])));\n";
332 	else if (m_iteration == 5)
333 		buf << "	highp float field = dot(vec2(v_input.a, v_input.b), vec2(v_input.a, v_input.b)) + dot(21.0 * vec2(v_input.a), sin(3.1 * vec2(v_input.a, v_input.b)));\n";
334 	else
335 		DE_ASSERT(false);
336 
337 	buf <<	"	fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
338 			"\n"
339 			"	if (fract(field) > 0.5)\n"
340 			"		fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
341 			"}";
342 
343 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
344 }
345 
getIterationDescription(int iteration) const346 std::string	SampleQualifierRenderCase::getIterationDescription (int iteration) const
347 {
348 	if (iteration == 0)
349 		return "Test with float varying";
350 	else if (iteration == 1)
351 		return "Test with vec2 varying";
352 	else if (iteration == 2)
353 		return "Test with vec3 varying";
354 	else if (iteration == 3)
355 		return "Test with vec4 varying";
356 	else if (iteration == 4)
357 		return "Test with array varying";
358 	else if (iteration == 5)
359 		return "Test with struct varying";
360 
361 	DE_ASSERT(false);
362 	return "";
363 }
364 
365 class InterpolateAtSampleRenderCase : public MultisampleShadeCountRenderCase
366 {
367 public:
368 	enum IndexingMode
369 	{
370 		INDEXING_STATIC,
371 		INDEXING_DYNAMIC,
372 
373 		INDEXING_LAST
374 	};
375 						InterpolateAtSampleRenderCase	(Context& context, const char* name, const char* description, int numSamples, RenderTarget target, IndexingMode mode);
376 						~InterpolateAtSampleRenderCase	(void);
377 
378 	void				init							(void);
379 	void				preDraw							(void);
380 
381 private:
382 	std::string			genVertexSource					(int numTargetSamples) const;
383 	std::string			genFragmentSource				(int numTargetSamples) const;
384 	std::string			getIterationDescription			(int iteration) const;
385 
386 	const IndexingMode	m_indexMode;
387 };
388 
InterpolateAtSampleRenderCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target,IndexingMode mode)389 InterpolateAtSampleRenderCase::InterpolateAtSampleRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, IndexingMode mode)
390 	: MultisampleShadeCountRenderCase	(context, name, description, numSamples, target)
391 	, m_indexMode						(mode)
392 {
393 	DE_ASSERT(mode < INDEXING_LAST);
394 
395 	m_numIterations = 5; // float, vec2, .3, .4, array
396 }
397 
~InterpolateAtSampleRenderCase(void)398 InterpolateAtSampleRenderCase::~InterpolateAtSampleRenderCase (void)
399 {
400 }
401 
init(void)402 void InterpolateAtSampleRenderCase::init (void)
403 {
404 	const bool isSingleSampleTarget = (m_renderTarget != TARGET_DEFAULT && m_numRequestedSamples == 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1);
405 
406 	// test purpose and expectations
407 	if (isSingleSampleTarget)
408 	{
409 		m_testCtx.getLog()
410 			<< tcu::TestLog::Message
411 			<< "Verifying that a interpolateAtSample returns different values for different samples.\n"
412 			<< "	Render high-frequency function, map result to black/white.\n"
413 			<< "	=> Resulting image image should contain both black and white pixels.\n"
414 			<< tcu::TestLog::EndMessage;
415 	}
416 	else
417 	{
418 		m_testCtx.getLog()
419 			<< tcu::TestLog::Message
420 			<< "Verifying that a interpolateAtSample returns different values for different samples.\n"
421 			<< "	Render high-frequency function, map result to black/white.\n"
422 			<< "	=> Resulting image should contain n+1 shades of gray, n = sample count.\n"
423 			<< tcu::TestLog::EndMessage;
424 	}
425 
426 	MultisampleShadeCountRenderCase::init();
427 }
428 
preDraw(void)429 void InterpolateAtSampleRenderCase::preDraw (void)
430 {
431 	if (m_indexMode == INDEXING_DYNAMIC)
432 	{
433 		const deInt32			range		= m_numTargetSamples;
434 		const deInt32			offset		= 1;
435 		const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
436 		const deInt32			offsetLoc	= gl.getUniformLocation(m_program->getProgram(), "u_offset");
437 		const deInt32			rangeLoc	= gl.getUniformLocation(m_program->getProgram(), "u_range");
438 
439 		if (offsetLoc == -1)
440 			throw tcu::TestError("Location of u_offset was -1");
441 		if (rangeLoc == -1)
442 			throw tcu::TestError("Location of u_range was -1");
443 
444 		gl.uniform1i(offsetLoc, 0);
445 		gl.uniform1i(rangeLoc, m_numTargetSamples);
446 		GLU_EXPECT_NO_ERROR(gl.getError(), "set uniforms");
447 
448 		m_testCtx.getLog()
449 			<< tcu::TestLog::Message
450 			<< "Set u_offset = " << offset << "\n"
451 			<< "Set u_range = " << range
452 			<< tcu::TestLog::EndMessage;
453 	}
454 }
455 
genVertexSource(int numTargetSamples) const456 std::string InterpolateAtSampleRenderCase::genVertexSource (int numTargetSamples) const
457 {
458 	DE_UNREF(numTargetSamples);
459 
460 	std::ostringstream buf;
461 
462 	buf <<	"${GLSL_VERSION_DECL}\n"
463 			"in highp vec4 a_position;\n";
464 
465 	if (m_iteration == 0)
466 		buf << "out highp float v_input;\n";
467 	else if (m_iteration == 1)
468 		buf << "out highp vec2 v_input;\n";
469 	else if (m_iteration == 2)
470 		buf << "out highp vec3 v_input;\n";
471 	else if (m_iteration == 3)
472 		buf << "out highp vec4 v_input;\n";
473 	else if (m_iteration == 4)
474 		buf << "out highp vec2[2] v_input;\n";
475 	else
476 		DE_ASSERT(false);
477 
478 	buf <<	"void main (void)\n"
479 			"{\n"
480 			"	gl_Position = a_position;\n";
481 
482 	if (m_iteration == 0)
483 		buf << "	v_input = a_position.x + exp(a_position.y) + step(0.9, a_position.x)*step(a_position.y, -0.9)*8.0;\n";
484 	else if (m_iteration == 1)
485 		buf << "	v_input = a_position.xy;\n";
486 	else if (m_iteration == 2)
487 		buf << "	v_input = vec3(a_position.xy, a_position.x * 2.0 - a_position.y);\n";
488 	else if (m_iteration == 3)
489 		buf << "	v_input = vec4(a_position.xy, a_position.x * 2.0 - a_position.y, a_position.x*a_position.y);\n";
490 	else if (m_iteration == 4)
491 		buf << "	v_input[0] = a_position.yx + vec2(0.5, 0.5);\n"
492 			   "	v_input[1] = a_position.xy;\n";
493 	else
494 		DE_ASSERT(false);
495 
496 	buf <<	"}";
497 
498 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
499 }
500 
genFragmentSource(int numTargetSamples) const501 std::string InterpolateAtSampleRenderCase::genFragmentSource (int numTargetSamples) const
502 {
503 	std::ostringstream buf;
504 
505 	buf <<	"${GLSL_VERSION_DECL}\n"
506 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}";
507 
508 	if (m_iteration == 0)
509 		buf << "in highp float v_input;\n";
510 	else if (m_iteration == 1)
511 		buf << "in highp vec2 v_input;\n";
512 	else if (m_iteration == 2)
513 		buf << "in highp vec3 v_input;\n";
514 	else if (m_iteration == 3)
515 		buf << "in highp vec4 v_input;\n";
516 	else if (m_iteration == 4)
517 		buf << "in highp vec2[2] v_input;\n";
518 	else
519 		DE_ASSERT(false);
520 
521 	buf << "layout(location = 0) out mediump vec4 fragColor;\n";
522 
523 	if (m_indexMode == INDEXING_DYNAMIC)
524 		buf <<	"uniform highp int u_offset;\n"
525 				"uniform highp int u_range;\n";
526 
527 	buf <<	"void main (void)\n"
528 			"{\n"
529 			"	mediump int coverage = 0;\n"
530 			"\n";
531 
532 	if (m_indexMode == INDEXING_STATIC)
533 	{
534 		for (int ndx = 0; ndx < numTargetSamples; ++ndx)
535 		{
536 			if (m_iteration == 0)
537 				buf <<	"	highp float sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n";
538 			else if (m_iteration == 1)
539 				buf <<	"	highp vec2 sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n";
540 			else if (m_iteration == 2)
541 				buf <<	"	highp vec3 sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n";
542 			else if (m_iteration == 3)
543 				buf <<	"	highp vec4 sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n";
544 			else if (m_iteration == 4)
545 				buf <<	"	highp vec2 sampleInput" << ndx << " = interpolateAtSample(v_input[1], " << ndx << ");\n";
546 			else
547 				DE_ASSERT(false);
548 		}
549 		buf <<	"\n";
550 
551 		for (int ndx = 0; ndx < numTargetSamples; ++ndx)
552 		{
553 			if (m_iteration == 0)
554 				buf << "	highp float field" << ndx << " = exp(sampleInput" << ndx << ") + sampleInput" << ndx << "*sampleInput" << ndx << ";\n";
555 			else if (m_iteration == 1 || m_iteration == 4)
556 				buf << "	highp float field" << ndx << " = dot(sampleInput" << ndx << ", sampleInput" << ndx << ") + dot(21.0 * sampleInput" << ndx << ".xx, sin(3.1 * sampleInput" << ndx << "));\n";
557 			else if (m_iteration == 2)
558 				buf << "	highp float field" << ndx << " = dot(sampleInput" << ndx << ".xy, sampleInput" << ndx << ".xy) + dot(21.0 * sampleInput" << ndx << ".zx, sin(3.1 * sampleInput" << ndx << ".zy));\n";
559 			else if (m_iteration == 3)
560 				buf << "	highp float field" << ndx << " = dot(sampleInput" << ndx << ".xy, sampleInput" << ndx << ".zw) + dot(21.0 * sampleInput" << ndx << ".zy, sin(3.1 * sampleInput" << ndx << ".zw));\n";
561 			else
562 				DE_ASSERT(false);
563 		}
564 		buf <<	"\n";
565 
566 		for (int ndx = 0; ndx < numTargetSamples; ++ndx)
567 			buf <<	"	if (fract(field" << ndx << ") <= 0.5)\n"
568 					"		++coverage;\n";
569 	}
570 	else if (m_indexMode == INDEXING_DYNAMIC)
571 	{
572 		buf <<	"	for (int ndx = 0; ndx < " << numTargetSamples << "; ++ndx)\n"
573 				"	{\n";
574 
575 		if (m_iteration == 0)
576 			buf <<	"		highp float sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n";
577 		else if (m_iteration == 1)
578 			buf <<	"		highp vec2 sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n";
579 		else if (m_iteration == 2)
580 			buf <<	"		highp vec3 sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n";
581 		else if (m_iteration == 3)
582 			buf <<	"		highp vec4 sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n";
583 		else if (m_iteration == 4)
584 			buf <<	"		highp vec2 sampleInput = interpolateAtSample(v_input[1], (u_offset + ndx) % u_range);\n";
585 		else
586 			DE_ASSERT(false);
587 
588 		if (m_iteration == 0)
589 			buf << "		highp float field = exp(sampleInput) + sampleInput*sampleInput;\n";
590 		else if (m_iteration == 1 || m_iteration == 4)
591 			buf << "		highp float field = dot(sampleInput, sampleInput) + dot(21.0 * sampleInput.xx, sin(3.1 * sampleInput));\n";
592 		else if (m_iteration == 2)
593 			buf << "		highp float field = dot(sampleInput.xy, sampleInput.xy) + dot(21.0 * sampleInput.zx, sin(3.1 * sampleInput.zy));\n";
594 		else if (m_iteration == 3)
595 			buf << "		highp float field = dot(sampleInput.xy, sampleInput.zw) + dot(21.0 * sampleInput.zy, sin(3.1 * sampleInput.zw));\n";
596 		else
597 			DE_ASSERT(false);
598 
599 		buf <<	"		if (fract(field) <= 0.5)\n"
600 				"			++coverage;\n"
601 				"	}\n";
602 	}
603 
604 	buf <<	"	fragColor = vec4(vec3(float(coverage) / float(" << numTargetSamples << ")), 1.0);\n"
605 			"}";
606 
607 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
608 }
609 
getIterationDescription(int iteration) const610 std::string InterpolateAtSampleRenderCase::getIterationDescription (int iteration) const
611 {
612 	if (iteration == 0)
613 		return "Test with float varying";
614 	else if (iteration < 4)
615 		return "Test with vec" + de::toString(iteration+1) + " varying";
616 	else if (iteration == 4)
617 		return "Test with array varying";
618 
619 	DE_ASSERT(false);
620 	return "";
621 }
622 
623 class SingleSampleInterpolateAtSampleCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
624 {
625 public:
626 	enum SampleCase
627 	{
628 		SAMPLE_0 = 0,
629 		SAMPLE_N,
630 
631 		SAMPLE_LAST
632 	};
633 
634 						SingleSampleInterpolateAtSampleCase		(Context& context, const char* name, const char* description, int numSamples, RenderTarget target, SampleCase sampleCase);
635 	virtual				~SingleSampleInterpolateAtSampleCase	(void);
636 
637 	void				init									(void);
638 
639 private:
640 	enum
641 	{
642 		RENDER_SIZE = 32
643 	};
644 
645 	std::string			genVertexSource							(int numTargetSamples) const;
646 	std::string			genFragmentSource						(int numTargetSamples) const;
647 	bool				verifyImage								(const tcu::Surface& resultImage);
648 
649 	const SampleCase	m_sampleCase;
650 };
651 
SingleSampleInterpolateAtSampleCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target,SampleCase sampleCase)652 SingleSampleInterpolateAtSampleCase::SingleSampleInterpolateAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, SampleCase sampleCase)
653 	: MultisampleShaderRenderUtil::MultisampleRenderCase	(context, name, description, numSamples, target, RENDER_SIZE)
654 	, m_sampleCase											(sampleCase)
655 {
656 	DE_ASSERT(numSamples == 0);
657 	DE_ASSERT(sampleCase < SAMPLE_LAST);
658 }
659 
~SingleSampleInterpolateAtSampleCase(void)660 SingleSampleInterpolateAtSampleCase::~SingleSampleInterpolateAtSampleCase (void)
661 {
662 }
663 
init(void)664 void SingleSampleInterpolateAtSampleCase::init (void)
665 {
666 	// requirements
667 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation") && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
668 		TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
669 	if (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1)
670 		TCU_THROW(NotSupportedError, "Non-multisample framebuffer required");
671 
672 	// test purpose and expectations
673 	m_testCtx.getLog()
674 		<< tcu::TestLog::Message
675 		<< "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n"
676 		<< "	Interpolate varying containing screen space location.\n"
677 		<< "	=> fract(screen space location) should be (about) (0.5, 0.5)\n"
678 		<< tcu::TestLog::EndMessage;
679 
680 	MultisampleShaderRenderUtil::MultisampleRenderCase::init();
681 }
682 
genVertexSource(int numTargetSamples) const683 std::string SingleSampleInterpolateAtSampleCase::genVertexSource (int numTargetSamples) const
684 {
685 	DE_UNREF(numTargetSamples);
686 
687 	std::ostringstream buf;
688 
689 	buf <<	"${GLSL_VERSION_DECL}\n"
690 			"in highp vec4 a_position;\n"
691 			"out highp vec2 v_position;\n"
692 			"void main (void)\n"
693 			"{\n"
694 			"	gl_Position = a_position;\n"
695 			"	v_position = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n"
696 			"}\n";
697 
698 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
699 }
700 
genFragmentSource(int numTargetSamples) const701 std::string SingleSampleInterpolateAtSampleCase::genFragmentSource (int numTargetSamples) const
702 {
703 	DE_UNREF(numTargetSamples);
704 
705 	std::ostringstream buf;
706 
707 	buf <<	"${GLSL_VERSION_DECL}\n"
708 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
709 			"in highp vec2 v_position;\n"
710 			"layout(location = 0) out mediump vec4 fragColor;\n"
711 			"void main (void)\n"
712 			"{\n"
713 			"	const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n"; // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE)
714 
715 	if (m_sampleCase == SAMPLE_0)
716 	{
717 		buf <<	"	highp vec2 samplePosition = interpolateAtSample(v_position, 0);\n"
718 				"	highp vec2 positionInsideAPixel = fract(samplePosition);\n"
719 				"\n"
720 				"	if (abs(positionInsideAPixel.x - 0.5) <= threshold && abs(positionInsideAPixel.y - 0.5) <= threshold)\n"
721 				"		fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
722 				"	else\n"
723 				"		fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
724 				"}\n";
725 	}
726 	else if (m_sampleCase == SAMPLE_N)
727 	{
728 		buf <<	"	bool allOk = true;\n"
729 				"	for (int sampleNdx = 159; sampleNdx < 163; ++sampleNdx)\n"
730 				"	{\n"
731 				"		highp vec2 samplePosition = interpolateAtSample(v_position, sampleNdx);\n"
732 				"		highp vec2 positionInsideAPixel = fract(samplePosition);\n"
733 				"		if (abs(positionInsideAPixel.x - 0.5) > threshold || abs(positionInsideAPixel.y - 0.5) > threshold)\n"
734 				"			allOk = false;\n"
735 				"	}\n"
736 				"\n"
737 				"	if (allOk)\n"
738 				"		fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
739 				"	else\n"
740 				"		fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
741 				"}\n";
742 	}
743 	else
744 		DE_ASSERT(false);
745 
746 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
747 }
748 
verifyImage(const tcu::Surface & resultImage)749 bool SingleSampleInterpolateAtSampleCase::verifyImage (const tcu::Surface& resultImage)
750 {
751 	return verifyGreenImage(resultImage, m_testCtx.getLog());
752 }
753 
754 class CentroidRenderCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
755 {
756 public:
757 									CentroidRenderCase	(Context& context, const char* name, const char* description, int numSamples, RenderTarget target, int renderSize);
758 	virtual							~CentroidRenderCase	(void);
759 
760 	void							init				(void);
761 
762 private:
763 	void							setupRenderData		(void);
764 };
765 
CentroidRenderCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target,int renderSize)766 CentroidRenderCase::CentroidRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, int renderSize)
767 	: MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, renderSize)
768 {
769 }
770 
~CentroidRenderCase(void)771 CentroidRenderCase::~CentroidRenderCase (void)
772 {
773 }
774 
init(void)775 void CentroidRenderCase::init (void)
776 {
777 	// requirements
778 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation") && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
779 		TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
780 
781 	MultisampleShaderRenderUtil::MultisampleRenderCase::init();
782 }
783 
setupRenderData(void)784 void CentroidRenderCase::setupRenderData (void)
785 {
786 	const int				numTriangles	= 200;
787 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
788 	std::vector<tcu::Vec4>	data			(numTriangles * 3 * 3);
789 
790 	m_renderMode = GL_TRIANGLES;
791 	m_renderCount = numTriangles * 3;
792 	m_renderSceneDescription = "triangle fan of narrow triangles";
793 
794 	m_renderAttribs["a_position"].offset = 0;
795 	m_renderAttribs["a_position"].stride = (int)sizeof(float[4]) * 3;
796 	m_renderAttribs["a_barycentricsA"].offset = (int)sizeof(float[4]);
797 	m_renderAttribs["a_barycentricsA"].stride = (int)sizeof(float[4]) * 3;
798 	m_renderAttribs["a_barycentricsB"].offset = (int)sizeof(float[4]) * 2;
799 	m_renderAttribs["a_barycentricsB"].stride = (int)sizeof(float[4]) * 3;
800 
801 	for (int triangleNdx = 0; triangleNdx < numTriangles; ++triangleNdx)
802 	{
803 		const float angle		= ((float)triangleNdx) / (float)numTriangles * 2.0f * DE_PI;
804 		const float nextAngle	= ((float)triangleNdx + 1.0f) / (float)numTriangles * 2.0f * DE_PI;
805 
806 		data[(triangleNdx * 3 + 0) * 3 + 0] = tcu::Vec4(0.2f, -0.3f, 0.0f, 1.0f);
807 		data[(triangleNdx * 3 + 0) * 3 + 1] = tcu::Vec4(1.0f,  0.0f, 0.0f, 0.0f);
808 		data[(triangleNdx * 3 + 0) * 3 + 2] = tcu::Vec4(1.0f,  0.0f, 0.0f, 0.0f);
809 
810 		data[(triangleNdx * 3 + 1) * 3 + 0] = tcu::Vec4(2.0f * deFloatCos(angle), 2.0f * deFloatSin(angle), 0.0f, 1.0f);
811 		data[(triangleNdx * 3 + 1) * 3 + 1] = tcu::Vec4(0.0f,  1.0f, 0.0f, 0.0f);
812 		data[(triangleNdx * 3 + 1) * 3 + 2] = tcu::Vec4(0.0f,  1.0f, 0.0f, 0.0f);
813 
814 		data[(triangleNdx * 3 + 2) * 3 + 0] = tcu::Vec4(2.0f * deFloatCos(nextAngle), 2.0f * deFloatSin(nextAngle), 0.0f, 1.0f);
815 		data[(triangleNdx * 3 + 2) * 3 + 1] = tcu::Vec4(0.0f,  0.0f, 1.0f, 0.0f);
816 		data[(triangleNdx * 3 + 2) * 3 + 2] = tcu::Vec4(0.0f,  0.0f, 1.0f, 0.0f);
817 	}
818 
819 	gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer);
820 	gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(data.size() * sizeof(tcu::Vec4)), data[0].getPtr(), GL_STATIC_DRAW);
821 }
822 
823 class CentroidQualifierAtSampleCase : public CentroidRenderCase
824 {
825 public:
826 									CentroidQualifierAtSampleCase	(Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
827 	virtual							~CentroidQualifierAtSampleCase	(void);
828 
829 	void							init						(void);
830 
831 private:
832 	enum
833 	{
834 		RENDER_SIZE = 128
835 	};
836 
837 	std::string						genVertexSource				(int numTargetSamples) const;
838 	std::string						genFragmentSource			(int numTargetSamples) const;
839 	bool							verifyImage					(const tcu::Surface& resultImage);
840 };
841 
CentroidQualifierAtSampleCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target)842 CentroidQualifierAtSampleCase::CentroidQualifierAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
843 	: CentroidRenderCase(context, name, description, numSamples, target, RENDER_SIZE)
844 {
845 }
846 
~CentroidQualifierAtSampleCase(void)847 CentroidQualifierAtSampleCase::~CentroidQualifierAtSampleCase (void)
848 {
849 }
850 
init(void)851 void CentroidQualifierAtSampleCase::init (void)
852 {
853 	// test purpose and expectations
854 	m_testCtx.getLog()
855 		<< tcu::TestLog::Message
856 		<< "Verifying that interpolateAtSample ignores the centroid-qualifier.\n"
857 		<< "	Draw a fan of narrow triangles (large number of pixels on the edges).\n"
858 		<< "	Set varyings 'barycentricsA' and 'barycentricsB' to contain barycentric coordinates.\n"
859 		<< "	Add centroid-qualifier for barycentricsB.\n"
860 		<< "	=> interpolateAtSample(barycentricsB, N) ~= interpolateAtSample(barycentricsA, N)\n"
861 		<< tcu::TestLog::EndMessage;
862 
863 	CentroidRenderCase::init();
864 }
865 
genVertexSource(int numTargetSamples) const866 std::string CentroidQualifierAtSampleCase::genVertexSource (int numTargetSamples) const
867 {
868 	DE_UNREF(numTargetSamples);
869 
870 	std::ostringstream buf;
871 
872 	buf <<	"${GLSL_VERSION_DECL}\n"
873 			"in highp vec4 a_position;\n"
874 			"in highp vec4 a_barycentricsA;\n"
875 			"in highp vec4 a_barycentricsB;\n"
876 			"out highp vec3 v_barycentricsA;\n"
877 			"centroid out highp vec3 v_barycentricsB;\n"
878 			"void main (void)\n"
879 			"{\n"
880 			"	gl_Position = a_position;\n"
881 			"	v_barycentricsA = a_barycentricsA.xyz;\n"
882 			"	v_barycentricsB = a_barycentricsB.xyz;\n"
883 			"}\n";
884 
885 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
886 }
887 
genFragmentSource(int numTargetSamples) const888 std::string CentroidQualifierAtSampleCase::genFragmentSource (int numTargetSamples) const
889 {
890 	DE_UNREF(numTargetSamples);
891 
892 	std::ostringstream buf;
893 
894 	buf <<	"${GLSL_VERSION_DECL}\n"
895 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
896 			"in highp vec3 v_barycentricsA;\n"
897 			"centroid in highp vec3 v_barycentricsB;\n"
898 			"layout(location = 0) out mediump vec4 fragColor;\n"
899 			"void main (void)\n"
900 			"{\n"
901 			"	const highp float threshold = 0.0005;\n"
902 			"	bool allOk = true;\n"
903 			"\n"
904 			"	for (int sampleNdx = 0; sampleNdx < " << numTargetSamples << "; ++sampleNdx)\n"
905 			"	{\n"
906 			"		highp vec3 sampleA = interpolateAtSample(v_barycentricsA, sampleNdx);\n"
907 			"		highp vec3 sampleB = interpolateAtSample(v_barycentricsB, sampleNdx);\n"
908 			"		bool valuesEqual = all(lessThan(abs(sampleA - sampleB), vec3(threshold)));\n"
909 			"		if (!valuesEqual)\n"
910 			"			allOk = false;\n"
911 			"	}\n"
912 			"\n"
913 			"	if (allOk)\n"
914 			"		fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
915 			"	else\n"
916 			"		fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
917 			"}\n";
918 
919 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
920 }
921 
verifyImage(const tcu::Surface & resultImage)922 bool CentroidQualifierAtSampleCase::verifyImage (const tcu::Surface& resultImage)
923 {
924 	return verifyGreenImage(resultImage, m_testCtx.getLog());
925 }
926 
927 class InterpolateAtSampleIDCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
928 {
929 public:
930 						InterpolateAtSampleIDCase	(Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
931 	virtual				~InterpolateAtSampleIDCase	(void);
932 
933 	void				init						(void);
934 private:
935 	enum
936 	{
937 		RENDER_SIZE = 32
938 	};
939 
940 	std::string			genVertexSource				(int numTargetSamples) const;
941 	std::string			genFragmentSource			(int numTargetSamples) const;
942 	bool				verifyImage					(const tcu::Surface& resultImage);
943 };
944 
InterpolateAtSampleIDCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target)945 InterpolateAtSampleIDCase::InterpolateAtSampleIDCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
946 	: MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, RENDER_SIZE)
947 {
948 }
949 
~InterpolateAtSampleIDCase(void)950 InterpolateAtSampleIDCase::~InterpolateAtSampleIDCase (void)
951 {
952 }
953 
init(void)954 void InterpolateAtSampleIDCase::init (void)
955 {
956 	// requirements
957 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation") && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
958 		TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
959 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_sample_variables") && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
960 		TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_variables extension");
961 
962 	// test purpose and expectations
963 	m_testCtx.getLog()
964 		<< tcu::TestLog::Message
965 		<< "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
966 		<< "	Interpolate varying containing screen space location.\n"
967 		<< "	=> interpolateAtSample(varying, sampleID) = varying"
968 		<< tcu::TestLog::EndMessage;
969 
970 	MultisampleShaderRenderUtil::MultisampleRenderCase::init();
971 }
972 
genVertexSource(int numTargetSamples) const973 std::string InterpolateAtSampleIDCase::genVertexSource (int numTargetSamples) const
974 {
975 	DE_UNREF(numTargetSamples);
976 
977 	std::ostringstream buf;
978 
979 	buf <<	"${GLSL_VERSION_DECL}\n"
980 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
981 			"in highp vec4 a_position;\n"
982 			"sample out highp vec2 v_screenPosition;\n"
983 			"void main (void)\n"
984 			"{\n"
985 			"	gl_Position = a_position;\n"
986 			"	v_screenPosition = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n"
987 			"}\n";
988 
989 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
990 }
991 
genFragmentSource(int numTargetSamples) const992 std::string InterpolateAtSampleIDCase::genFragmentSource (int numTargetSamples) const
993 {
994 	DE_UNREF(numTargetSamples);
995 
996 	std::ostringstream buf;
997 
998 	buf <<	"${GLSL_VERSION_DECL}\n"
999 			"${GLSL_EXT_SAMPLE_VARIABLES}"
1000 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1001 			"sample in highp vec2 v_screenPosition;\n"
1002 			"layout(location = 0) out mediump vec4 fragColor;\n"
1003 			"void main (void)\n"
1004 			"{\n"
1005 			"	const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE)
1006 			"\n"
1007 			"	highp vec2 offsetValue = interpolateAtSample(v_screenPosition, gl_SampleID);\n"
1008 			"	highp vec2 refValue = v_screenPosition;\n"
1009 			"\n"
1010 			"	bool valuesEqual = all(lessThan(abs(offsetValue - refValue), vec2(threshold)));\n"
1011 			"	if (valuesEqual)\n"
1012 			"		fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1013 			"	else\n"
1014 			"		fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1015 			"}\n";
1016 
1017 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
1018 }
1019 
verifyImage(const tcu::Surface & resultImage)1020 bool InterpolateAtSampleIDCase::verifyImage (const tcu::Surface& resultImage)
1021 {
1022 	return verifyGreenImage(resultImage, m_testCtx.getLog());
1023 }
1024 
1025 class InterpolateAtCentroidCase : public CentroidRenderCase
1026 {
1027 public:
1028 	enum TestType
1029 	{
1030 		TEST_CONSISTENCY = 0,
1031 		TEST_ARRAY_ELEMENT,
1032 
1033 		TEST_LAST
1034 	};
1035 
1036 									InterpolateAtCentroidCase	(Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType type);
1037 	virtual							~InterpolateAtCentroidCase	(void);
1038 
1039 	void							init						(void);
1040 
1041 private:
1042 	enum
1043 	{
1044 		RENDER_SIZE = 128
1045 	};
1046 
1047 	std::string						genVertexSource				(int numTargetSamples) const;
1048 	std::string						genFragmentSource			(int numTargetSamples) const;
1049 	bool							verifyImage					(const tcu::Surface& resultImage);
1050 
1051 	const TestType					m_type;
1052 };
1053 
InterpolateAtCentroidCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target,TestType type)1054 InterpolateAtCentroidCase::InterpolateAtCentroidCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType type)
1055 	: CentroidRenderCase	(context, name, description, numSamples, target, RENDER_SIZE)
1056 	, m_type				(type)
1057 {
1058 }
1059 
~InterpolateAtCentroidCase(void)1060 InterpolateAtCentroidCase::~InterpolateAtCentroidCase (void)
1061 {
1062 }
1063 
init(void)1064 void InterpolateAtCentroidCase::init (void)
1065 {
1066 	// test purpose and expectations
1067 	if (m_type == TEST_CONSISTENCY)
1068 	{
1069 		m_testCtx.getLog()
1070 			<< tcu::TestLog::Message
1071 			<< "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid-qualified varying.\n"
1072 			<< "	Draw a fan of narrow triangles (large number of pixels on the edges).\n"
1073 			<< "	Set varyings 'barycentricsA' and 'barycentricsB' to contain barycentric coordinates.\n"
1074 			<< "	Add centroid-qualifier for barycentricsB.\n"
1075 			<< "	=> interpolateAtCentroid(barycentricsA) ~= barycentricsB\n"
1076 			<< tcu::TestLog::EndMessage;
1077 	}
1078 	else if (m_type == TEST_ARRAY_ELEMENT)
1079 	{
1080 		m_testCtx.getLog()
1081 			<< tcu::TestLog::Message
1082 			<< "Testing interpolateAtCentroid with element of array as an argument."
1083 			<< tcu::TestLog::EndMessage;
1084 	}
1085 	else
1086 		DE_ASSERT(false);
1087 
1088 	CentroidRenderCase::init();
1089 }
1090 
genVertexSource(int numTargetSamples) const1091 std::string InterpolateAtCentroidCase::genVertexSource (int numTargetSamples) const
1092 {
1093 	DE_UNREF(numTargetSamples);
1094 
1095 	std::ostringstream buf;
1096 
1097 	if (m_type == TEST_CONSISTENCY)
1098 		buf <<	"${GLSL_VERSION_DECL}\n"
1099 				"in highp vec4 a_position;\n"
1100 				"in highp vec4 a_barycentricsA;\n"
1101 				"in highp vec4 a_barycentricsB;\n"
1102 				"out highp vec3 v_barycentricsA;\n"
1103 				"centroid out highp vec3 v_barycentricsB;\n"
1104 				"void main (void)\n"
1105 				"{\n"
1106 				"	gl_Position = a_position;\n"
1107 				"	v_barycentricsA = a_barycentricsA.xyz;\n"
1108 				"	v_barycentricsB = a_barycentricsB.xyz;\n"
1109 				"}\n";
1110 	else if (m_type == TEST_ARRAY_ELEMENT)
1111 		buf <<	"${GLSL_VERSION_DECL}\n"
1112 				"in highp vec4 a_position;\n"
1113 				"in highp vec4 a_barycentricsA;\n"
1114 				"in highp vec4 a_barycentricsB;\n"
1115 				"out highp vec3[2] v_barycentrics;\n"
1116 				"void main (void)\n"
1117 				"{\n"
1118 				"	gl_Position = a_position;\n"
1119 				"	v_barycentrics[0] = a_barycentricsA.xyz;\n"
1120 				"	v_barycentrics[1] = a_barycentricsB.xyz;\n"
1121 				"}\n";
1122 	else
1123 		DE_ASSERT(false);
1124 
1125 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
1126 }
1127 
genFragmentSource(int numTargetSamples) const1128 std::string InterpolateAtCentroidCase::genFragmentSource (int numTargetSamples) const
1129 {
1130 	DE_UNREF(numTargetSamples);
1131 
1132 	std::ostringstream buf;
1133 
1134 	if (m_type == TEST_CONSISTENCY)
1135 		buf <<	"${GLSL_VERSION_DECL}\n"
1136 				"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1137 				"in highp vec3 v_barycentricsA;\n"
1138 				"centroid in highp vec3 v_barycentricsB;\n"
1139 				"layout(location = 0) out highp vec4 fragColor;\n"
1140 				"void main (void)\n"
1141 				"{\n"
1142 				"	const highp float threshold = 0.0005;\n"
1143 				"\n"
1144 				"	highp vec3 centroidASampled = interpolateAtCentroid(v_barycentricsA);\n"
1145 				"	bool valuesEqual = all(lessThan(abs(centroidASampled - v_barycentricsB), vec3(threshold)));\n"
1146 				"	bool centroidAIsInvalid = any(greaterThan(centroidASampled, vec3(1.0))) ||\n"
1147 				"	                          any(lessThan(centroidASampled, vec3(0.0)));\n"
1148 				"	bool centroidBIsInvalid = any(greaterThan(v_barycentricsB, vec3(1.0))) ||\n"
1149 				"	                          any(lessThan(v_barycentricsB, vec3(0.0)));\n"
1150 				"\n"
1151 				"	if (valuesEqual && !centroidAIsInvalid && !centroidBIsInvalid)\n"
1152 				"		fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1153 				"	else if (centroidAIsInvalid || centroidBIsInvalid)\n"
1154 				"		fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1155 				"	else\n"
1156 				"		fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1157 				"}\n";
1158 	else if (m_type == TEST_ARRAY_ELEMENT)
1159 		buf <<	"${GLSL_VERSION_DECL}\n"
1160 				"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1161 				"in highp vec3[2] v_barycentrics;\n"
1162 				"layout(location = 0) out mediump vec4 fragColor;\n"
1163 				"void main (void)\n"
1164 				"{\n"
1165 				"	const highp float threshold = 0.0005;\n"
1166 				"\n"
1167 				"	highp vec3 centroidInterpolated = interpolateAtCentroid(v_barycentrics[1]);\n"
1168 				"	bool centroidIsInvalid = any(greaterThan(centroidInterpolated, vec3(1.0))) ||\n"
1169 				"	                         any(lessThan(centroidInterpolated, vec3(0.0)));\n"
1170 				"\n"
1171 				"	if (!centroidIsInvalid)\n"
1172 				"		fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1173 				"	else\n"
1174 				"		fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1175 				"}\n";
1176 	else
1177 		DE_ASSERT(false);
1178 
1179 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
1180 }
1181 
verifyImage(const tcu::Surface & resultImage)1182 bool InterpolateAtCentroidCase::verifyImage (const tcu::Surface& resultImage)
1183 {
1184 	return verifyGreenImage(resultImage, m_testCtx.getLog());
1185 }
1186 
1187 class InterpolateAtOffsetCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
1188 {
1189 public:
1190 	enum TestType
1191 	{
1192 		TEST_QUALIFIER_NONE = 0,
1193 		TEST_QUALIFIER_CENTROID,
1194 		TEST_QUALIFIER_SAMPLE,
1195 		TEST_ARRAY_ELEMENT,
1196 
1197 		TEST_LAST
1198 	};
1199 						InterpolateAtOffsetCase		(Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType testType);
1200 	virtual				~InterpolateAtOffsetCase	(void);
1201 
1202 	void				init						(void);
1203 private:
1204 	enum
1205 	{
1206 		RENDER_SIZE = 32
1207 	};
1208 
1209 	std::string			genVertexSource				(int numTargetSamples) const;
1210 	std::string			genFragmentSource			(int numTargetSamples) const;
1211 	bool				verifyImage					(const tcu::Surface& resultImage);
1212 
1213 	const TestType		m_testType;
1214 };
1215 
InterpolateAtOffsetCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target,TestType testType)1216 InterpolateAtOffsetCase::InterpolateAtOffsetCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType testType)
1217 	: MultisampleShaderRenderUtil::MultisampleRenderCase	(context, name, description, numSamples, target, RENDER_SIZE)
1218 	, m_testType											(testType)
1219 {
1220 	DE_ASSERT(testType < TEST_LAST);
1221 }
1222 
~InterpolateAtOffsetCase(void)1223 InterpolateAtOffsetCase::~InterpolateAtOffsetCase (void)
1224 {
1225 }
1226 
init(void)1227 void InterpolateAtOffsetCase::init (void)
1228 {
1229 	// requirements
1230 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation") && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
1231 		TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
1232 
1233 	// test purpose and expectations
1234 	m_testCtx.getLog()
1235 		<< tcu::TestLog::Message
1236 		<< "Verifying that interpolateAtOffset returns correct values.\n"
1237 		<< "	Interpolate varying containing screen space location.\n"
1238 		<< "	=> interpolateAtOffset(varying, offset) should be \"varying value at the pixel center\" + offset"
1239 		<< tcu::TestLog::EndMessage;
1240 
1241 	MultisampleShaderRenderUtil::MultisampleRenderCase::init();
1242 }
1243 
genVertexSource(int numTargetSamples) const1244 std::string InterpolateAtOffsetCase::genVertexSource (int numTargetSamples) const
1245 {
1246 	DE_UNREF(numTargetSamples);
1247 
1248 	std::ostringstream buf;
1249 	buf << "${GLSL_VERSION_DECL}\n"
1250 		<< "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1251 		<< "in highp vec4 a_position;\n";
1252 
1253 	if (m_testType == TEST_QUALIFIER_NONE || m_testType == TEST_QUALIFIER_CENTROID || m_testType == TEST_QUALIFIER_SAMPLE)
1254 	{
1255 		const char* const qualifier = (m_testType == TEST_QUALIFIER_CENTROID) ? ("centroid ") : (m_testType == TEST_QUALIFIER_SAMPLE) ? ("sample ") : ("");
1256 		buf << qualifier << "out highp vec2 v_screenPosition;\n"
1257 			<< qualifier << "out highp vec2 v_offset;\n";
1258 	}
1259 	else if (m_testType == TEST_ARRAY_ELEMENT)
1260 	{
1261 		buf << "out highp vec2[2] v_screenPosition;\n"
1262 			<< "out highp vec2 v_offset;\n";
1263 	}
1264 	else
1265 		DE_ASSERT(false);
1266 
1267 	buf	<< "void main (void)\n"
1268 		<< "{\n"
1269 		<< "	gl_Position = a_position;\n";
1270 
1271 	if (m_testType != TEST_ARRAY_ELEMENT)
1272 		buf	<< "	v_screenPosition = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n";
1273 	else
1274 		buf	<< "	v_screenPosition[0] = a_position.xy; // not used\n"
1275 				"	v_screenPosition[1] = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n";
1276 
1277 	buf	<< "	v_offset = a_position.xy * 0.5f;\n"
1278 		<< "}\n";
1279 
1280 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
1281 }
1282 
genFragmentSource(int numTargetSamples) const1283 std::string InterpolateAtOffsetCase::genFragmentSource (int numTargetSamples) const
1284 {
1285 	DE_UNREF(numTargetSamples);
1286 
1287 	const char* const	arrayIndexing = (m_testType == TEST_ARRAY_ELEMENT) ? ("[1]") : ("");
1288 	std::ostringstream	buf;
1289 
1290 	buf <<	"${GLSL_VERSION_DECL}\n"
1291 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}";
1292 
1293 	if (m_testType == TEST_QUALIFIER_NONE || m_testType == TEST_QUALIFIER_CENTROID || m_testType == TEST_QUALIFIER_SAMPLE)
1294 	{
1295 		const char* const qualifier = (m_testType == TEST_QUALIFIER_CENTROID) ? ("centroid ") : (m_testType == TEST_QUALIFIER_SAMPLE) ? ("sample ") : ("");
1296 		buf	<< qualifier << "in highp vec2 v_screenPosition;\n"
1297 			<< qualifier << "in highp vec2 v_offset;\n";
1298 	}
1299 	else if (m_testType == TEST_ARRAY_ELEMENT)
1300 	{
1301 		buf << "in highp vec2[2] v_screenPosition;\n"
1302 			<< "in highp vec2 v_offset;\n";
1303 	}
1304 	else
1305 		DE_ASSERT(false);
1306 
1307 	buf	<<	"layout(location = 0) out mediump vec4 fragColor;\n"
1308 			"void main (void)\n"
1309 			"{\n"
1310 			"	const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE)
1311 			"\n"
1312 			"	highp vec2 pixelCenter = floor(v_screenPosition" << arrayIndexing << ") + vec2(0.5, 0.5);\n"
1313 			"	highp vec2 offsetValue = interpolateAtOffset(v_screenPosition" << arrayIndexing << ", v_offset);\n"
1314 			"	highp vec2 refValue = pixelCenter + v_offset;\n"
1315 			"\n"
1316 			"	bool valuesEqual = all(lessThan(abs(offsetValue - refValue), vec2(threshold)));\n"
1317 			"	if (valuesEqual)\n"
1318 			"		fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1319 			"	else\n"
1320 			"		fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1321 			"}\n";
1322 
1323 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
1324 }
1325 
verifyImage(const tcu::Surface & resultImage)1326 bool InterpolateAtOffsetCase::verifyImage (const tcu::Surface& resultImage)
1327 {
1328 	return verifyGreenImage(resultImage, m_testCtx.getLog());
1329 }
1330 
1331 class InterpolateAtSamplePositionCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
1332 {
1333 public:
1334 						InterpolateAtSamplePositionCase		(Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
1335 	virtual				~InterpolateAtSamplePositionCase	(void);
1336 
1337 	void				init								(void);
1338 private:
1339 	enum
1340 	{
1341 		RENDER_SIZE = 32
1342 	};
1343 
1344 	std::string			genVertexSource						(int numTargetSamples) const;
1345 	std::string			genFragmentSource					(int numTargetSamples) const;
1346 	bool				verifyImage							(const tcu::Surface& resultImage);
1347 };
1348 
InterpolateAtSamplePositionCase(Context & context,const char * name,const char * description,int numSamples,RenderTarget target)1349 InterpolateAtSamplePositionCase::InterpolateAtSamplePositionCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
1350 	: MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, RENDER_SIZE)
1351 {
1352 }
1353 
~InterpolateAtSamplePositionCase(void)1354 InterpolateAtSamplePositionCase::~InterpolateAtSamplePositionCase (void)
1355 {
1356 }
1357 
init(void)1358 void InterpolateAtSamplePositionCase::init (void)
1359 {
1360 	// requirements
1361 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation") && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
1362 		TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
1363 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_sample_variables") && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
1364 		TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_variables extension");
1365 
1366 	// test purpose and expectations
1367 	m_testCtx.getLog()
1368 		<< tcu::TestLog::Message
1369 		<< "Verifying that interpolateAtOffset with the offset of current sample position returns consistent values.\n"
1370 		<< "	Interpolate varying containing screen space location.\n"
1371 		<< "	=> interpolateAtOffset(varying, currentOffset) = varying"
1372 		<< tcu::TestLog::EndMessage;
1373 
1374 	MultisampleShaderRenderUtil::MultisampleRenderCase::init();
1375 }
1376 
genVertexSource(int numTargetSamples) const1377 std::string InterpolateAtSamplePositionCase::genVertexSource (int numTargetSamples) const
1378 {
1379 	DE_UNREF(numTargetSamples);
1380 
1381 	std::ostringstream buf;
1382 
1383 	buf <<	"${GLSL_VERSION_DECL}\n"
1384 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1385 			"in highp vec4 a_position;\n"
1386 			"sample out highp vec2 v_screenPosition;\n"
1387 			"void main (void)\n"
1388 			"{\n"
1389 			"	gl_Position = a_position;\n"
1390 			"	v_screenPosition = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n"
1391 			"}\n";
1392 
1393 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
1394 }
1395 
genFragmentSource(int numTargetSamples) const1396 std::string InterpolateAtSamplePositionCase::genFragmentSource (int numTargetSamples) const
1397 {
1398 	DE_UNREF(numTargetSamples);
1399 
1400 	std::ostringstream buf;
1401 
1402 	buf <<	"${GLSL_VERSION_DECL}\n"
1403 			"${GLSL_EXT_SAMPLE_VARIABLES}"
1404 			"${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1405 			"sample in highp vec2 v_screenPosition;\n"
1406 			"layout(location = 0) out mediump vec4 fragColor;\n"
1407 			"void main (void)\n"
1408 			"{\n"
1409 			"	const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE)
1410 			"\n"
1411 			"	highp vec2 offset = gl_SamplePosition - vec2(0.5, 0.5);\n"
1412 			"	highp vec2 offsetValue = interpolateAtOffset(v_screenPosition, offset);\n"
1413 			"	highp vec2 refValue = v_screenPosition;\n"
1414 			"\n"
1415 			"	bool valuesEqual = all(lessThan(abs(offsetValue - refValue), vec2(threshold)));\n"
1416 			"	if (valuesEqual)\n"
1417 			"		fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1418 			"	else\n"
1419 			"		fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1420 			"}\n";
1421 
1422 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
1423 }
1424 
verifyImage(const tcu::Surface & resultImage)1425 bool InterpolateAtSamplePositionCase::verifyImage (const tcu::Surface& resultImage)
1426 {
1427 	return verifyGreenImage(resultImage, m_testCtx.getLog());
1428 }
1429 
1430 class NegativeCompileInterpolationCase : public TestCase
1431 {
1432 public:
1433 	enum CaseType
1434 	{
1435 		CASE_VEC4_IDENTITY_SWIZZLE = 0,
1436 		CASE_VEC4_CROP_SWIZZLE,
1437 		CASE_VEC4_MIXED_SWIZZLE,
1438 		CASE_INTERPOLATE_IVEC4,
1439 		CASE_INTERPOLATE_UVEC4,
1440 		CASE_INTERPOLATE_ARRAY,
1441 		CASE_INTERPOLATE_STRUCT,
1442 		CASE_INTERPOLATE_STRUCT_MEMBER,
1443 		CASE_INTERPOLATE_LOCAL,
1444 		CASE_INTERPOLATE_GLOBAL,
1445 		CASE_INTERPOLATE_CONSTANT,
1446 
1447 		CASE_LAST
1448 	};
1449 	enum InterpolatorType
1450 	{
1451 		INTERPOLATE_AT_SAMPLE = 0,
1452 		INTERPOLATE_AT_CENTROID,
1453 		INTERPOLATE_AT_OFFSET,
1454 
1455 		INTERPOLATE_LAST
1456 	};
1457 
1458 							NegativeCompileInterpolationCase	(Context& context, const char* name, const char* description, CaseType caseType, InterpolatorType interpolator);
1459 
1460 private:
1461 	void					init								(void);
1462 	IterateResult			iterate								(void);
1463 
1464 	std::string				genShaderSource						(void) const;
1465 
1466 	const CaseType			m_caseType;
1467 	const InterpolatorType	m_interpolation;
1468 };
1469 
NegativeCompileInterpolationCase(Context & context,const char * name,const char * description,CaseType caseType,InterpolatorType interpolator)1470 NegativeCompileInterpolationCase::NegativeCompileInterpolationCase (Context& context, const char* name, const char* description, CaseType caseType, InterpolatorType interpolator)
1471 	: TestCase			(context, name, description)
1472 	, m_caseType		(caseType)
1473 	, m_interpolation	(interpolator)
1474 {
1475 	DE_ASSERT(m_caseType < CASE_LAST);
1476 	DE_ASSERT(m_interpolation < INTERPOLATE_LAST);
1477 }
1478 
init(void)1479 void NegativeCompileInterpolationCase::init (void)
1480 {
1481 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation") && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
1482 		TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
1483 
1484 	m_testCtx.getLog() << tcu::TestLog::Message << "Trying to compile illegal shader, expecting compile to fail." << tcu::TestLog::EndMessage;
1485 }
1486 
iterate(void)1487 NegativeCompileInterpolationCase::IterateResult NegativeCompileInterpolationCase::iterate (void)
1488 {
1489 	const std::string	source			= genShaderSource();
1490 	glu::Shader			shader			(m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT);
1491 	const char* const	sourceStrPtr	= source.c_str();
1492 
1493 	m_testCtx.getLog()	<< tcu::TestLog::Message
1494 						<< "Fragment shader source:"
1495 						<< tcu::TestLog::EndMessage
1496 						<< tcu::TestLog::KernelSource(source);
1497 
1498 	shader.setSources(1, &sourceStrPtr, DE_NULL);
1499 	shader.compile();
1500 
1501 	m_testCtx.getLog()	<< tcu::TestLog::Message
1502 						<< "Info log:"
1503 						<< tcu::TestLog::EndMessage
1504 						<< tcu::TestLog::KernelSource(shader.getInfoLog());
1505 
1506 	if (shader.getCompileStatus())
1507 	{
1508 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Illegal shader compiled successfully." << tcu::TestLog::EndMessage;
1509 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected compile status");
1510 	}
1511 	else
1512 	{
1513 		m_testCtx.getLog() << tcu::TestLog::Message << "Compile failed as expected." << tcu::TestLog::EndMessage;
1514 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1515 	}
1516 	return STOP;
1517 }
1518 
genShaderSource(void) const1519 std::string NegativeCompileInterpolationCase::genShaderSource (void) const
1520 {
1521 	std::ostringstream	buf;
1522 	std::string			interpolation;
1523 	const char*			interpolationTemplate;
1524 	const char*			description;
1525 	const char*			globalDeclarations		= "";
1526 	const char*			localDeclarations		= "";
1527 	const char*			interpolationTarget		= "";
1528 	const char*			postSelector			= "";
1529 
1530 	switch (m_caseType)
1531 	{
1532 		case CASE_VEC4_IDENTITY_SWIZZLE:
1533 			globalDeclarations	= "in highp vec4 v_var;\n";
1534 			interpolationTarget	= "v_var.xyzw";
1535 			description			= "component selection is illegal";
1536 			break;
1537 
1538 		case CASE_VEC4_CROP_SWIZZLE:
1539 			globalDeclarations	= "in highp vec4 v_var;\n";
1540 			interpolationTarget	= "v_var.xy";
1541 			postSelector		= ".x";
1542 			description			= "component selection is illegal";
1543 			break;
1544 
1545 		case CASE_VEC4_MIXED_SWIZZLE:
1546 			globalDeclarations	= "in highp vec4 v_var;\n";
1547 			interpolationTarget	= "v_var.yzxw";
1548 			description			= "component selection is illegal";
1549 			break;
1550 
1551 		case CASE_INTERPOLATE_IVEC4:
1552 			globalDeclarations	= "flat in highp ivec4 v_var;\n";
1553 			interpolationTarget	= "v_var";
1554 			description			= "no overload for ivec";
1555 			break;
1556 
1557 		case CASE_INTERPOLATE_UVEC4:
1558 			globalDeclarations	= "flat in highp uvec4 v_var;\n";
1559 			interpolationTarget	= "v_var";
1560 			description			= "no overload for uvec";
1561 			break;
1562 
1563 		case CASE_INTERPOLATE_ARRAY:
1564 			globalDeclarations	= "in highp float v_var[2];\n";
1565 			interpolationTarget	= "v_var";
1566 			postSelector		= "[1]";
1567 			description			= "no overload for arrays";
1568 			break;
1569 
1570 		case CASE_INTERPOLATE_STRUCT:
1571 		case CASE_INTERPOLATE_STRUCT_MEMBER:
1572 			globalDeclarations	=	"struct S\n"
1573 									"{\n"
1574 									"	highp float a;\n"
1575 									"	highp float b;\n"
1576 									"};\n"
1577 									"in S v_var;\n";
1578 
1579 			interpolationTarget	= (m_caseType == CASE_INTERPOLATE_STRUCT) ? ("v_var")						: ("v_var.a");
1580 			postSelector		= (m_caseType == CASE_INTERPOLATE_STRUCT) ? (".a")							: ("");
1581 			description			= (m_caseType == CASE_INTERPOLATE_STRUCT) ? ("no overload for this type")	: ("<interpolant> is not an input variable (just a member of)");
1582 			break;
1583 
1584 		case CASE_INTERPOLATE_LOCAL:
1585 			localDeclarations	= "	highp vec4 local_var = gl_FragCoord;\n";
1586 			interpolationTarget	= "local_var";
1587 			description			= "<interpolant> is not an input variable";
1588 			break;
1589 
1590 		case CASE_INTERPOLATE_GLOBAL:
1591 			globalDeclarations	= "highp vec4 global_var;\n";
1592 			localDeclarations	= "	global_var = gl_FragCoord;\n";
1593 			interpolationTarget	= "global_var";
1594 			description			= "<interpolant> is not an input variable";
1595 			break;
1596 
1597 		case CASE_INTERPOLATE_CONSTANT:
1598 			globalDeclarations	= "const highp vec4 const_var = vec4(0.2);\n";
1599 			interpolationTarget	= "const_var";
1600 			description			= "<interpolant> is not an input variable";
1601 			break;
1602 
1603 		default:
1604 			DE_ASSERT(false);
1605 			return "";
1606 	}
1607 
1608 	switch (m_interpolation)
1609 	{
1610 		case INTERPOLATE_AT_SAMPLE:
1611 			interpolationTemplate = "interpolateAtSample(${TARGET}, 0)${POST_SELECTOR}";
1612 			break;
1613 
1614 		case INTERPOLATE_AT_CENTROID:
1615 			interpolationTemplate = "interpolateAtCentroid(${TARGET})${POST_SELECTOR}";
1616 			break;
1617 
1618 		case INTERPOLATE_AT_OFFSET:
1619 			interpolationTemplate = "interpolateAtOffset(${TARGET}, vec2(0.2, 0.2))${POST_SELECTOR}";
1620 			break;
1621 
1622 		default:
1623 			DE_ASSERT(false);
1624 			return "";
1625 	}
1626 
1627 	{
1628 		std::map<std::string, std::string> args;
1629 		args["TARGET"] = interpolationTarget;
1630 		args["POST_SELECTOR"] = postSelector;
1631 
1632 		interpolation = tcu::StringTemplate(interpolationTemplate).specialize(args);
1633 	}
1634 
1635 	buf <<	glu::getGLSLVersionDeclaration(glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType())) << "\n"
1636 		<< "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1637 		<<	globalDeclarations
1638 		<<	"layout(location = 0) out mediump vec4 fragColor;\n"
1639 			"void main (void)\n"
1640 			"{\n"
1641 		<<	localDeclarations
1642 		<<	"	fragColor = vec4(" << interpolation << "); // " << description << "\n"
1643 			"}\n";
1644 
1645 	return specializeShader(buf.str(), m_context.getRenderContext().getType());
1646 }
1647 
1648 } // anonymous
1649 
ShaderMultisampleInterpolationTests(Context & context)1650 ShaderMultisampleInterpolationTests::ShaderMultisampleInterpolationTests (Context& context)
1651 	: TestCaseGroup(context, "multisample_interpolation", "Test multisample interpolation")
1652 {
1653 }
1654 
~ShaderMultisampleInterpolationTests(void)1655 ShaderMultisampleInterpolationTests::~ShaderMultisampleInterpolationTests (void)
1656 {
1657 }
1658 
init(void)1659 void ShaderMultisampleInterpolationTests::init (void)
1660 {
1661 	using namespace MultisampleShaderRenderUtil;
1662 
1663 	static const struct RenderTarget
1664 	{
1665 		const char*							name;
1666 		const char*							desc;
1667 		int									numSamples;
1668 		MultisampleRenderCase::RenderTarget	target;
1669 	} targets[] =
1670 	{
1671 		{ "default_framebuffer",		"Test with default framebuffer",	0,	MultisampleRenderCase::TARGET_DEFAULT		},
1672 		{ "singlesample_texture",		"Test with singlesample texture",	0,	MultisampleRenderCase::TARGET_TEXTURE		},
1673 		{ "multisample_texture_1",		"Test with multisample texture",	1,	MultisampleRenderCase::TARGET_TEXTURE		},
1674 		{ "multisample_texture_2",		"Test with multisample texture",	2,	MultisampleRenderCase::TARGET_TEXTURE		},
1675 		{ "multisample_texture_4",		"Test with multisample texture",	4,	MultisampleRenderCase::TARGET_TEXTURE		},
1676 		{ "multisample_texture_8",		"Test with multisample texture",	8,	MultisampleRenderCase::TARGET_TEXTURE		},
1677 		{ "multisample_texture_16",		"Test with multisample texture",	16,	MultisampleRenderCase::TARGET_TEXTURE		},
1678 		{ "singlesample_rbo",			"Test with singlesample rbo",		0,	MultisampleRenderCase::TARGET_RENDERBUFFER	},
1679 		{ "multisample_rbo_1",			"Test with multisample rbo",		1,	MultisampleRenderCase::TARGET_RENDERBUFFER	},
1680 		{ "multisample_rbo_2",			"Test with multisample rbo",		2,	MultisampleRenderCase::TARGET_RENDERBUFFER	},
1681 		{ "multisample_rbo_4",			"Test with multisample rbo",		4,	MultisampleRenderCase::TARGET_RENDERBUFFER	},
1682 		{ "multisample_rbo_8",			"Test with multisample rbo",		8,	MultisampleRenderCase::TARGET_RENDERBUFFER	},
1683 		{ "multisample_rbo_16",			"Test with multisample rbo",		16,	MultisampleRenderCase::TARGET_RENDERBUFFER	},
1684 	};
1685 
1686 	static const struct
1687 	{
1688 		const char*									name;
1689 		const char*									description;
1690 		NegativeCompileInterpolationCase::CaseType	caseType;
1691 	} negativeCompileCases[] =
1692 	{
1693 		{ "vec4_identity_swizzle",		"use identity swizzle",				NegativeCompileInterpolationCase::CASE_VEC4_IDENTITY_SWIZZLE		},
1694 		{ "vec4_crop_swizzle",			"use cropped identity swizzle",		NegativeCompileInterpolationCase::CASE_VEC4_CROP_SWIZZLE			},
1695 		{ "vec4_mixed_swizzle",			"use swizzle",						NegativeCompileInterpolationCase::CASE_VEC4_MIXED_SWIZZLE			},
1696 		{ "interpolate_ivec4",			"interpolate integer variable",		NegativeCompileInterpolationCase::CASE_INTERPOLATE_IVEC4			},
1697 		{ "interpolate_uvec4",			"interpolate integer variable",		NegativeCompileInterpolationCase::CASE_INTERPOLATE_UVEC4			},
1698 		{ "interpolate_array",			"interpolate whole array",			NegativeCompileInterpolationCase::CASE_INTERPOLATE_ARRAY			},
1699 		{ "interpolate_struct",			"interpolate whole struct",			NegativeCompileInterpolationCase::CASE_INTERPOLATE_STRUCT			},
1700 		{ "interpolate_struct_member",	"interpolate struct member",		NegativeCompileInterpolationCase::CASE_INTERPOLATE_STRUCT_MEMBER	},
1701 		{ "interpolate_local",			"interpolate local variable",		NegativeCompileInterpolationCase::CASE_INTERPOLATE_LOCAL			},
1702 		{ "interpolate_global",			"interpolate global variable",		NegativeCompileInterpolationCase::CASE_INTERPOLATE_GLOBAL			},
1703 		{ "interpolate_constant",		"interpolate constant variable",	NegativeCompileInterpolationCase::CASE_INTERPOLATE_CONSTANT			},
1704 	};
1705 
1706 	// .sample_qualifier
1707 	{
1708 		tcu::TestCaseGroup* const sampleQualifierGroup = new tcu::TestCaseGroup(m_testCtx, "sample_qualifier", "Test sample qualifier");
1709 		addChild(sampleQualifierGroup);
1710 
1711 		for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1712 			sampleQualifierGroup->addChild(new SampleQualifierRenderCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
1713 	}
1714 
1715 	// .interpolate_at_sample
1716 	{
1717 		tcu::TestCaseGroup* const interpolateAtSampleGroup = new tcu::TestCaseGroup(m_testCtx, "interpolate_at_sample", "Test interpolateAtSample");
1718 		addChild(interpolateAtSampleGroup);
1719 
1720 		// .static_sample_number
1721 		{
1722 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "static_sample_number", "Test interpolateAtSample sample number");
1723 			interpolateAtSampleGroup->addChild(group);
1724 
1725 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1726 				group->addChild(new InterpolateAtSampleRenderCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtSampleRenderCase::INDEXING_STATIC));
1727 		}
1728 
1729 		// .dynamic_sample_number
1730 		{
1731 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "dynamic_sample_number", "Test interpolateAtSample sample number");
1732 			interpolateAtSampleGroup->addChild(group);
1733 
1734 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1735 				group->addChild(new InterpolateAtSampleRenderCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtSampleRenderCase::INDEXING_DYNAMIC));
1736 		}
1737 
1738 		// .non_multisample_buffer
1739 		{
1740 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "non_multisample_buffer", "Test interpolateAtSample with non-multisample buffers");
1741 			interpolateAtSampleGroup->addChild(group);
1742 
1743 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1744 				if (targets[targetNdx].numSamples == 0)
1745 					group->addChild(new SingleSampleInterpolateAtSampleCase(m_context, std::string("sample_0_").append(targets[targetNdx].name).c_str(), targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SingleSampleInterpolateAtSampleCase::SAMPLE_0));
1746 
1747 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1748 				if (targets[targetNdx].numSamples == 0)
1749 					group->addChild(new SingleSampleInterpolateAtSampleCase(m_context, std::string("sample_n_").append(targets[targetNdx].name).c_str(), targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SingleSampleInterpolateAtSampleCase::SAMPLE_N));
1750 		}
1751 
1752 		// .centroid_qualifier
1753 		{
1754 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "centroid_qualified", "Test interpolateAtSample with centroid qualified varying");
1755 			interpolateAtSampleGroup->addChild(group);
1756 
1757 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1758 				group->addChild(new CentroidQualifierAtSampleCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
1759 		}
1760 
1761 		// .at_sample_id
1762 		{
1763 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "at_sample_id", "Test interpolateAtSample at current sample id");
1764 			interpolateAtSampleGroup->addChild(group);
1765 
1766 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1767 				group->addChild(new InterpolateAtSampleIDCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
1768 		}
1769 
1770 		// .negative
1771 		{
1772 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "negative", "interpolateAtSample negative tests");
1773 			interpolateAtSampleGroup->addChild(group);
1774 
1775 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(negativeCompileCases); ++ndx)
1776 				group->addChild(new NegativeCompileInterpolationCase(m_context,
1777 																	 negativeCompileCases[ndx].name,
1778 																	 negativeCompileCases[ndx].description,
1779 																	 negativeCompileCases[ndx].caseType,
1780 																	 NegativeCompileInterpolationCase::INTERPOLATE_AT_SAMPLE));
1781 		}
1782 	}
1783 
1784 	// .interpolate_at_centroid
1785 	{
1786 		tcu::TestCaseGroup* const methodGroup = new tcu::TestCaseGroup(m_testCtx, "interpolate_at_centroid", "Test interpolateAtCentroid");
1787 		addChild(methodGroup);
1788 
1789 		// .consistency
1790 		{
1791 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "consistency", "Test interpolateAtCentroid return value is consistent to centroid qualified value");
1792 			methodGroup->addChild(group);
1793 
1794 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1795 				group->addChild(new InterpolateAtCentroidCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtCentroidCase::TEST_CONSISTENCY));
1796 		}
1797 
1798 		// .array_element
1799 		{
1800 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "array_element", "Test interpolateAtCentroid with array element");
1801 			methodGroup->addChild(group);
1802 
1803 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1804 				group->addChild(new InterpolateAtCentroidCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtCentroidCase::TEST_ARRAY_ELEMENT));
1805 		}
1806 
1807 		// .negative
1808 		{
1809 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "negative", "interpolateAtCentroid negative tests");
1810 			methodGroup->addChild(group);
1811 
1812 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(negativeCompileCases); ++ndx)
1813 				group->addChild(new NegativeCompileInterpolationCase(m_context,
1814 																	 negativeCompileCases[ndx].name,
1815 																	 negativeCompileCases[ndx].description,
1816 																	 negativeCompileCases[ndx].caseType,
1817 																	 NegativeCompileInterpolationCase::INTERPOLATE_AT_CENTROID));
1818 		}
1819 	}
1820 
1821 	// .interpolate_at_offset
1822 	{
1823 		static const struct TestConfig
1824 		{
1825 			const char*							name;
1826 			InterpolateAtOffsetCase::TestType	type;
1827 		} configs[] =
1828 		{
1829 			{ "no_qualifiers",		InterpolateAtOffsetCase::TEST_QUALIFIER_NONE		},
1830 			{ "centroid_qualifier",	InterpolateAtOffsetCase::TEST_QUALIFIER_CENTROID	},
1831 			{ "sample_qualifier",	InterpolateAtOffsetCase::TEST_QUALIFIER_SAMPLE		},
1832 		};
1833 
1834 		tcu::TestCaseGroup* const methodGroup = new tcu::TestCaseGroup(m_testCtx, "interpolate_at_offset", "Test interpolateAtOffset");
1835 		addChild(methodGroup);
1836 
1837 		// .no_qualifiers
1838 		// .centroid_qualifier
1839 		// .sample_qualifier
1840 		for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(configs); ++configNdx)
1841 		{
1842 			tcu::TestCaseGroup* const qualifierGroup = new tcu::TestCaseGroup(m_testCtx, configs[configNdx].name, "Test interpolateAtOffset with qualified/non-qualified varying");
1843 			methodGroup->addChild(qualifierGroup);
1844 
1845 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1846 				qualifierGroup->addChild(new InterpolateAtOffsetCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, configs[configNdx].type));
1847 		}
1848 
1849 		// .at_sample_position
1850 		{
1851 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "at_sample_position", "Test interpolateAtOffset at sample position");
1852 			methodGroup->addChild(group);
1853 
1854 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1855 				group->addChild(new InterpolateAtSamplePositionCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
1856 		}
1857 
1858 		// .array_element
1859 		{
1860 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "array_element", "Test interpolateAtOffset with array element");
1861 			methodGroup->addChild(group);
1862 
1863 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1864 				group->addChild(new InterpolateAtOffsetCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtOffsetCase::TEST_ARRAY_ELEMENT));
1865 		}
1866 
1867 		// .negative
1868 		{
1869 			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "negative", "interpolateAtOffset negative tests");
1870 			methodGroup->addChild(group);
1871 
1872 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(negativeCompileCases); ++ndx)
1873 				group->addChild(new NegativeCompileInterpolationCase(m_context,
1874 																	 negativeCompileCases[ndx].name,
1875 																	 negativeCompileCases[ndx].description,
1876 																	 negativeCompileCases[ndx].caseType,
1877 																	 NegativeCompileInterpolationCase::INTERPOLATE_AT_OFFSET));
1878 		}
1879 	}
1880 }
1881 
1882 } // Functional
1883 } // gles31
1884 } // deqp
1885