• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "glcShaderMultisampleInterpolationTests.hpp"
25 #include "deMath.h"
26 #include "deRandom.hpp"
27 #include "deStringUtil.hpp"
28 #include "gluContextInfo.hpp"
29 #include "gluDrawUtil.hpp"
30 #include "gluPixelTransfer.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "glw.h"
33 #include "glwFunctions.hpp"
34 #include "tcuCommandLine.hpp"
35 #include "tcuStringTemplate.hpp"
36 #include "tcuSurface.hpp"
37 #include "tcuTestLog.hpp"
38 
39 namespace tcu
40 {
operator <(tcu::Vec4 const & k1,tcu::Vec4 const & k2)41 static bool operator<(tcu::Vec4 const& k1, tcu::Vec4 const& k2)
42 {
43 	if (k1.y() < k2.y())
44 	{
45 		return true;
46 	}
47 	else if (k1.y() == k2.y())
48 	{
49 		return k1.x() < k2.x();
50 	}
51 	else
52 	{
53 		return false;
54 	}
55 }
56 }
57 
58 namespace deqp
59 {
60 
61 using tcu::TestLog;
62 using std::string;
63 using std::vector;
64 
specializeVersion(std::string const & source,glu::GLSLVersion version,std::string const & sampler="",std::string const & outType="",std::string const & qualifier="",std::string const & assignment="",std::string const & condition="")65 static std::string specializeVersion(std::string const& source, glu::GLSLVersion version,
66 									 std::string const& sampler = "", std::string const& outType = "",
67 									 std::string const& qualifier = "", std::string const& assignment = "",
68 									 std::string const& condition = "")
69 {
70 	DE_ASSERT(version == glu::GLSL_VERSION_310_ES || version >= glu::GLSL_VERSION_440);
71 	std::map<std::string, std::string> args;
72 	args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(version);
73 	args["SAMPLER"]		 = sampler;
74 	args["OUT_TYPE"]	 = outType;
75 	args["QUALIFIER"]	= qualifier;
76 	args["ASSIGNMENT"]   = assignment;
77 	args["CONDITION"]	= condition;
78 	if (version == glu::GLSL_VERSION_310_ES)
79 	{
80 		args["OES_SMI_EN"] = "#extension GL_OES_shader_multisample_interpolation : enable\n";
81 		args["OES_SMI_RQ"] = "#extension GL_OES_shader_multisample_interpolation : require\n";
82 		args["OES_SMI_CH"] = "#if !GL_OES_shader_multisample_interpolation\n"
83 							 "    this is broken\n"
84 							 "#endif\n";
85 		args["OES_SV_EN"] = "#extension GL_OES_sample_variables : enable\n";
86 	}
87 	else
88 	{
89 		args["OES_SMI_EN"] = "";
90 		args["OES_SMI_RQ"] = "";
91 		args["OES_SMI_CH"] = "";
92 		args["OES_SV_EN"]  = "";
93 	}
94 	return tcu::StringTemplate(source.c_str()).specialize(args);
95 }
96 
97 class ShaderMultisampleInterpolationApiCase : public TestCase
98 {
99 public:
100 	ShaderMultisampleInterpolationApiCase(Context& context, const char* name, const char* description,
101 										  glu::GLSLVersion glslVersion);
102 	~ShaderMultisampleInterpolationApiCase();
103 
104 	IterateResult iterate();
105 
106 protected:
107 	glu::GLSLVersion m_glslVersion;
108 };
109 
ShaderMultisampleInterpolationApiCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)110 ShaderMultisampleInterpolationApiCase::ShaderMultisampleInterpolationApiCase(Context& context, const char* name,
111 																			 const char*	  description,
112 																			 glu::GLSLVersion glslVersion)
113 	: TestCase(context, name, description), m_glslVersion(glslVersion)
114 {
115 	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_440);
116 }
117 
~ShaderMultisampleInterpolationApiCase()118 ShaderMultisampleInterpolationApiCase::~ShaderMultisampleInterpolationApiCase()
119 {
120 }
121 
iterate()122 ShaderMultisampleInterpolationApiCase::IterateResult ShaderMultisampleInterpolationApiCase::iterate()
123 {
124 	TestLog&			  log  = m_testCtx.getLog();
125 	const glw::Functions& gl   = m_context.getRenderContext().getFunctions();
126 	bool				  isOk = true;
127 
128 	if (m_glslVersion == glu::GLSL_VERSION_310_ES &&
129 		!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
130 	{
131 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_OES_shader_multisample_interpolation");
132 		return STOP;
133 	}
134 
135 	static char const* vss = "${VERSION_DECL}\n"
136 							 "${OES_SMI_RQ}"
137 							 "in highp vec4 a_position;\n"
138 							 "in highp vec4 a_color;\n"
139 							 "sample out highp vec4 v_color;\n"
140 							 "void main()\n"
141 							 "{\n"
142 							 "    gl_Position = a_position;\n"
143 							 "}\n";
144 
145 	{
146 		static char const* fss = "${VERSION_DECL}\n"
147 								 "${OES_SMI_RQ}"
148 								 "sample in highp vec4 v_color;\n"
149 								 "out highp vec4 o_color;\n"
150 								 "void main()\n"
151 								 "{\n"
152 								 "    o_color = v_color;\n"
153 								 "}\n";
154 
155 		glu::ShaderProgram program(m_context.getRenderContext(),
156 								   glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(),
157 														   specializeVersion(fss, m_glslVersion).c_str()));
158 		log << program;
159 		if (!program.isOk())
160 		{
161 			TCU_FAIL("Compile failed");
162 		}
163 	}
164 
165 	{
166 		static char const* fss = "${VERSION_DECL}\n"
167 								 "${OES_SMI_EN}"
168 								 "sample in highp vec4 v_color;\n"
169 								 "out highp vec4 o_color;\n"
170 								 "void main()\n"
171 								 "{\n"
172 								 "${OES_SMI_CH}"
173 								 "    o_color = v_color;\n"
174 								 "}\n";
175 
176 		glu::ShaderProgram program(m_context.getRenderContext(),
177 								   glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(),
178 														   specializeVersion(fss, m_glslVersion).c_str()));
179 		log << program;
180 		if (!program.isOk())
181 		{
182 			TCU_FAIL("Compile failed");
183 		}
184 	}
185 
186 	GLfloat minFragmentInterpolationOffset = 0.0f;
187 	gl.getFloatv(GL_MIN_FRAGMENT_INTERPOLATION_OFFSET, &minFragmentInterpolationOffset);
188 	if (minFragmentInterpolationOffset > -0.5f)
189 	{
190 		isOk = false;
191 	}
192 
193 	GLint fragmentInterpolationOffsetBits = 0;
194 	gl.getIntegerv(GL_FRAGMENT_INTERPOLATION_OFFSET_BITS, &fragmentInterpolationOffsetBits);
195 	if (fragmentInterpolationOffsetBits < 4)
196 	{
197 		isOk = false;
198 	}
199 	GLfloat ULP = 1.0f / powf(2, static_cast<float>(fragmentInterpolationOffsetBits));
200 
201 	GLfloat maxFragmentInterpolationOffset = 0.0f;
202 	gl.getFloatv(GL_MAX_FRAGMENT_INTERPOLATION_OFFSET, &maxFragmentInterpolationOffset);
203 	if (maxFragmentInterpolationOffset < 0.5f - ULP)
204 	{
205 		isOk = false;
206 	}
207 
208 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
209 	return STOP;
210 }
211 
212 class ShaderMultisampleInterpolationBaseCase : public TestCase
213 {
214 public:
215 	ShaderMultisampleInterpolationBaseCase(Context& context, const char* name, const char* description,
216 										   glu::GLSLVersion glslVersion, char const* qualifier, char const* assignment,
217 										   char const* condition, bool unique, GLenum internalFormat,
218 										   tcu::TextureFormat const& texFormat, const char* m_sampler,
219 										   const char* m_outType, GLfloat min, GLfloat max, GLint samples);
220 	~ShaderMultisampleInterpolationBaseCase();
221 
222 	IterateResult iterate();
223 
224 protected:
225 	glu::GLSLVersion   m_glslVersion;
226 	std::string		   m_qualifier;
227 	std::string		   m_assignment;
228 	std::string		   m_condition;
229 	bool			   m_unique;
230 	GLenum			   m_internalFormat;
231 	tcu::TextureFormat m_texFormat;
232 	std::string		   m_sampler;
233 	std::string		   m_outType;
234 	GLfloat			   m_min;
235 	GLfloat			   m_max;
236 	GLint			   m_samples;
237 
238 	enum
239 	{
240 		WIDTH  = 8,
241 		HEIGHT = 8,
242 	};
243 
244 	int countUniquePixels(tcu::ConstPixelBufferAccess const& pixels);
245 	int countUniquePixels(const std::vector<tcu::Vec4>& pixels);
246 };
247 
ShaderMultisampleInterpolationBaseCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion,char const * qualifier,char const * assignment,char const * condition,bool unique,GLenum internalFormat,tcu::TextureFormat const & texFormat,const char * sampler,const char * outType,GLfloat min,GLfloat max,GLint samples)248 ShaderMultisampleInterpolationBaseCase::ShaderMultisampleInterpolationBaseCase(
249 	Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion, char const* qualifier,
250 	char const* assignment, char const* condition, bool unique, GLenum internalFormat,
251 	tcu::TextureFormat const& texFormat, const char* sampler, const char* outType, GLfloat min, GLfloat max,
252 	GLint samples)
253 	: TestCase(context, name, description)
254 	, m_glslVersion(glslVersion)
255 	, m_qualifier(qualifier)
256 	, m_assignment(assignment)
257 	, m_condition(condition)
258 	, m_unique(unique)
259 	, m_internalFormat(internalFormat)
260 	, m_texFormat(texFormat)
261 	, m_sampler(sampler)
262 	, m_outType(outType)
263 	, m_min(min)
264 	, m_max(max)
265 	, m_samples(samples)
266 {
267 	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_440);
268 }
269 
~ShaderMultisampleInterpolationBaseCase()270 ShaderMultisampleInterpolationBaseCase::~ShaderMultisampleInterpolationBaseCase()
271 {
272 }
273 
iterate()274 ShaderMultisampleInterpolationBaseCase::IterateResult ShaderMultisampleInterpolationBaseCase::iterate()
275 {
276 	TestLog&			  log			  = m_testCtx.getLog();
277 	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
278 	bool				  isOk			  = true;
279 	bool				  supportsRgba32f = false;
280 
281 	if (m_glslVersion == glu::GLSL_VERSION_310_ES &&
282 		!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
283 	{
284 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_OES_shader_multisample_interpolation");
285 		return STOP;
286 	}
287 
288 	supportsRgba32f = isContextTypeGLCore(m_context.getRenderContext().getType()) ?
289 						  true :
290 						  (m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_float") ||
291 						   m_context.getContextInfo().isExtensionSupported("GL_ARB_color_buffer_float"));
292 
293 	if (m_internalFormat == GL_RGBA32F && !supportsRgba32f)
294 	{
295 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Internalformat rgba32f not supported");
296 		return STOP;
297 	}
298 
299 	GLint maxSamples;
300 	if (((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA)) ||
301 		((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RG)) ||
302 		((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::R)) ||
303 		((m_texFormat.type == tcu::TextureFormat::HALF_FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA)))
304 	{
305 		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, m_internalFormat, GL_SAMPLES, 1, &maxSamples);
306 		if (m_samples > maxSamples)
307 		{
308 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
309 									"Test sample count greater than samples that the format supports");
310 			return STOP;
311 		}
312 	}
313 	else if (m_texFormat.type == tcu::TextureFormat::SIGNED_INT8 ||
314 			 m_texFormat.type == tcu::TextureFormat::UNSIGNED_INT8)
315 	{
316 		gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &maxSamples);
317 		if (m_samples > maxSamples)
318 		{
319 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test sample count greater than MAX_INTEGER_SAMPLES");
320 			return STOP;
321 		}
322 	}
323 	else
324 	{
325 		gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
326 		if (m_samples > maxSamples)
327 		{
328 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test sample count greater than MAX_SAMPLES");
329 			return STOP;
330 		}
331 	}
332 
333 	// Create a multisample texture, or a regular texture if samples is zero.
334 	GLuint tex;
335 	gl.genTextures(1, &tex);
336 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
337 	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, m_internalFormat, WIDTH, HEIGHT, GL_FALSE);
338 
339 	// Create a framebuffer with the texture attached.
340 	GLuint fboMs;
341 	gl.genFramebuffers(1, &fboMs);
342 	gl.bindFramebuffer(GL_FRAMEBUFFER, fboMs);
343 	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
344 	gl.viewport(0, 0, WIDTH, HEIGHT);
345 
346 	static deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 };
347 
348 	{
349 		// Draw with one of the fragment input qualifiers and with one of the
350 		// interpolate functions. Cross-check the result in the shader and
351 		// output the final interpolated value.
352 
353 		static char const* vss = "${VERSION_DECL}\n"
354 								 "${OES_SMI_RQ}"
355 								 "layout(location = 0) in highp vec2 a_position;\n"
356 								 "layout(location = 1) in highp vec4 a_color;\n"
357 								 "out highp vec4 v_colorBase;\n"
358 								 "${QUALIFIER} out highp vec4 v_color;\n"
359 								 "void main()\n"
360 								 "{\n"
361 								 "    v_colorBase = a_color;\n"
362 								 "    v_color = a_color;\n"
363 								 "    gl_Position = vec4(a_position, 0.0, 1.0);\n"
364 								 "}\n";
365 
366 		static char const* fss = "${VERSION_DECL}\n"
367 								 "${OES_SMI_RQ}"
368 								 "${OES_SV_EN}"
369 								 "in highp vec4 v_colorBase;\n"
370 								 "${QUALIFIER} in highp vec4 v_color;\n"
371 								 "layout(location = 0) out highp ${OUT_TYPE} o_color;\n"
372 								 "void main()\n"
373 								 "{\n"
374 								 "    highp vec4 temp = ${ASSIGNMENT};\n"
375 								 "    bool condition = ${CONDITION};\n"
376 								 "    o_color = ${OUT_TYPE}(temp.x, temp.y, condition, 1);\n"
377 								 "}\n";
378 
379 		glu::ShaderProgram program(
380 			m_context.getRenderContext(),
381 			glu::makeVtxFragSources(
382 				specializeVersion(vss, m_glslVersion, m_sampler, m_outType, m_qualifier, m_assignment, m_condition)
383 					.c_str(),
384 				specializeVersion(fss, m_glslVersion, m_sampler, m_outType, m_qualifier, m_assignment, m_condition)
385 					.c_str()));
386 		log << program;
387 		if (!program.isOk())
388 		{
389 			TCU_FAIL("Compile failed");
390 		}
391 
392 		static float const position[] = {
393 			-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
394 		};
395 
396 		const float color[] = {
397 			m_min, m_min, 0.0f, 1.0f, m_min, m_max, 0.0f, 1.0f, m_max, m_min, 0.0f, 1.0f, m_max, m_max, 0.0f, 1.0f,
398 		};
399 
400 		gl.useProgram(program.getProgram());
401 
402 		glu::VertexArrayBinding vertexArrays[] = {
403 			glu::va::Float("a_position", 2, 4, 0, &position[0]), glu::va::Float("a_color", 4, 4, 0, &color[0]),
404 		};
405 		glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
406 				  &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
407 
408 		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
409 	}
410 
411 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
412 	gl.deleteFramebuffers(1, &fboMs);
413 
414 	GLsizei width = WIDTH * m_samples;
415 
416 	GLuint rbo;
417 	gl.genRenderbuffers(1, &rbo);
418 	gl.bindRenderbuffer(GL_RENDERBUFFER, rbo);
419 	gl.renderbufferStorage(GL_RENDERBUFFER, m_internalFormat, width, HEIGHT);
420 
421 	GLuint fbo;
422 	gl.genFramebuffers(1, &fbo);
423 	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
424 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
425 	gl.viewport(0, 0, width, HEIGHT);
426 
427 	{
428 		// Resolve the mutli-sample texture into a render-buffer sized such that
429 		// the width can hold all samples of a pixel.
430 
431 		static char const* vss = "${VERSION_DECL}\n"
432 								 "in highp vec2 a_position;\n"
433 								 "void main(void)\n"
434 								 "{\n"
435 								 "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
436 								 "}\n";
437 
438 		static char const* fss = "${VERSION_DECL}\n"
439 								 "uniform highp ${SAMPLER}MS u_texMS;\n"
440 								 "uniform int u_samples;\n"
441 								 "layout(location = 0) out highp ${OUT_TYPE} o_color;\n"
442 								 "void main(void)\n"
443 								 "{\n"
444 								 "    ivec2 coord = ivec2(int(gl_FragCoord.x) / u_samples, gl_FragCoord.y);\n"
445 								 "    int sampleId = int(gl_FragCoord.x) % u_samples;\n"
446 								 "    o_color = texelFetch(u_texMS, coord, sampleId);\n"
447 								 "}\n";
448 
449 		glu::ShaderProgram program(
450 			m_context.getRenderContext(),
451 			glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion, m_sampler, m_outType).c_str(),
452 									specializeVersion(fss, m_glslVersion, m_sampler, m_outType).c_str()));
453 		log << program;
454 		if (!program.isOk())
455 		{
456 			TCU_FAIL("Compile failed");
457 		}
458 
459 		static float const position[] = {
460 			-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
461 		};
462 
463 		gl.useProgram(program.getProgram());
464 		gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_samples"), m_samples);
465 		gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_texMS"), 0);
466 
467 		glu::VertexArrayBinding vertexArrays[] = {
468 			glu::va::Float("a_position", 2, 4, 0, &position[0]),
469 		};
470 		glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
471 				  &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
472 
473 		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
474 	}
475 
476 	// Verify the results.
477 	tcu::TextureLevel	  results(m_texFormat, width, HEIGHT);
478 	tcu::PixelBufferAccess pixels = results.getAccess();
479 	std::vector<tcu::Vec4> result(pixels.getHeight() * pixels.getWidth());
480 	int					   uniquePixels;
481 
482 	if (pixels.getFormat().type == tcu::TextureFormat::SIGNED_INT8)
483 	{
484 		std::vector<GLint> data(pixels.getHeight() * pixels.getWidth() * 4);
485 		gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_INT, &data[0]);
486 		for (unsigned int i = 0; i < data.size(); i += 4)
487 		{
488 			result[i / 4] =
489 				tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]);
490 		}
491 		uniquePixels = countUniquePixels(result);
492 	}
493 	else if (pixels.getFormat().type == tcu::TextureFormat::UNSIGNED_INT8)
494 	{
495 		std::vector<GLuint> data(pixels.getHeight() * pixels.getWidth() * 4);
496 		gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data[0]);
497 		for (unsigned int i = 0; i < data.size(); i += 4)
498 		{
499 			result[i / 4] =
500 				tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]);
501 		}
502 		uniquePixels = countUniquePixels(result);
503 	}
504 	else
505 	{
506 		glu::readPixels(m_context.getRenderContext(), 0, 0, pixels);
507 		uniquePixels = countUniquePixels(pixels);
508 	}
509 
510 	int expectedUnique = WIDTH * HEIGHT * ((m_unique) ? m_samples : 1);
511 	if (uniquePixels < expectedUnique)
512 	{
513 		// There are duplicate pixel values meaning interpolation didn't work as expected.
514 		isOk = false;
515 	}
516 	for (int y = 0; y < pixels.getHeight(); ++y)
517 	{
518 		for (int x = 0; x < pixels.getWidth(); ++x)
519 		{
520 			tcu::Vec4 pixel;
521 			if (pixels.getFormat().type == tcu::TextureFormat::SIGNED_INT8 ||
522 				pixels.getFormat().type == tcu::TextureFormat::UNSIGNED_INT8)
523 			{
524 				pixel = result[y * WIDTH + x];
525 			}
526 			else
527 			{
528 				pixel = pixels.getPixel(x, y);
529 			}
530 			if (pixel.z() != 1)
531 			{
532 				// The ${CONDITION} check in the shader failed.
533 				isOk = false;
534 			}
535 		}
536 	}
537 
538 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
539 	gl.deleteFramebuffers(1, &fbo);
540 
541 	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
542 	gl.deleteRenderbuffers(1, &rbo);
543 
544 	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
545 	gl.deleteTextures(1, &tex);
546 
547 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
548 	return STOP;
549 }
550 
countUniquePixels(tcu::ConstPixelBufferAccess const & pixels)551 int ShaderMultisampleInterpolationBaseCase::countUniquePixels(tcu::ConstPixelBufferAccess const& pixels)
552 {
553 	std::set<tcu::Vec4> uniquePixels;
554 
555 	for (int y = 0; y < pixels.getHeight(); ++y)
556 	{
557 		for (int x = 0; x < pixels.getWidth(); ++x)
558 		{
559 			uniquePixels.insert(pixels.getPixel(x, y));
560 		}
561 	}
562 
563 	return (int)uniquePixels.size();
564 }
565 
countUniquePixels(const std::vector<tcu::Vec4> & pixels)566 int ShaderMultisampleInterpolationBaseCase::countUniquePixels(const std::vector<tcu::Vec4>& pixels)
567 {
568 	std::set<tcu::Vec4> uniquePixels;
569 
570 	for (unsigned int i = 0; i < pixels.size(); ++i)
571 	{
572 		uniquePixels.insert(pixels[i]);
573 	}
574 
575 	return (int)uniquePixels.size();
576 }
577 
ShaderMultisampleInterpolationTests(Context & context,glu::GLSLVersion glslVersion)578 ShaderMultisampleInterpolationTests::ShaderMultisampleInterpolationTests(Context& context, glu::GLSLVersion glslVersion)
579 	: TestCaseGroup(context, "shader_multisample_interpolation", "Shader Multisample Interpolation tests")
580 	, m_glslVersion(glslVersion)
581 {
582 }
583 
~ShaderMultisampleInterpolationTests()584 ShaderMultisampleInterpolationTests::~ShaderMultisampleInterpolationTests()
585 {
586 }
587 
init()588 void ShaderMultisampleInterpolationTests::init()
589 {
590 	struct Sample
591 	{
592 		char const* name;
593 		GLint		samples;
594 	} samples[] = {
595 		{ "samples_1", 1 }, { "samples_2", 2 }, { "samples_4", 4 },
596 	};
597 
598 	// shader_multisample_interpolation.api
599 	tcu::TestCaseGroup* apiGroup = new tcu::TestCaseGroup(m_testCtx, "api", "API verification");
600 	apiGroup->addChild(new ShaderMultisampleInterpolationApiCase(m_context, "api", "API verification", m_glslVersion));
601 	addChild(apiGroup);
602 
603 	struct Case
604 	{
605 		char const* name;
606 		char const* qualifier;
607 		char const* assignment;
608 		char const* condition;
609 		bool		unique;
610 	} cases[] = {
611 		{ "base", "", "v_color", "true", false },
612 		{ "sample", "sample", "v_color", "true", true },
613 		{ "centroid", "centroid", "v_color", "true", false },
614 		{ "interpolate_at_sample", "", "interpolateAtSample(v_colorBase, gl_SampleID)", "true", true },
615 		{ "interpolate_at_sample_check", "sample", "interpolateAtSample(v_colorBase, gl_SampleID)", "temp == v_color",
616 		  true },
617 		{ "interpolate_at_centroid", "", "interpolateAtCentroid(v_colorBase)", "true", false },
618 		{ "interpolate_at_centroid_check", "centroid", "interpolateAtCentroid(v_colorBase)", "temp == v_color", false },
619 		{ "interpolate_at_offset", "", "interpolateAtOffset(v_colorBase, gl_SamplePosition - 0.5)", "true", true },
620 		{ "interpolate_at_offset_check", "sample", "interpolateAtOffset(v_colorBase, gl_SamplePosition - 0.5)",
621 		  "temp == v_color", true },
622 	};
623 
624 	// shader_multisample_interpolation.render
625 	tcu::TestCaseGroup* renderGroup = new tcu::TestCaseGroup(m_testCtx, "render", "Rendering tests");
626 	addChild(renderGroup);
627 	for (int caseId = 0; caseId < DE_LENGTH_OF_ARRAY(cases); ++caseId)
628 	{
629 		tcu::TestCaseGroup* group = new tcu::TestCaseGroup(m_testCtx, cases[caseId].name, "");
630 		renderGroup->addChild(group);
631 		struct Format
632 		{
633 			char const*		   name;
634 			GLenum			   internalFormat;
635 			tcu::TextureFormat textureFormat;
636 			char const*		   sampler;
637 			char const*		   outType;
638 			GLfloat			   min;
639 			GLfloat			   max;
640 		} formats[] = {
641 			{ "rgba8", GL_RGBA8, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
642 			  "sampler2D", "vec4", 0.0f, 1.0f },
643 			{ "rgba8i", GL_RGBA8I, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8),
644 			  "isampler2D", "ivec4", -128.0f, 127.0f },
645 			{ "rgba8ui", GL_RGBA8UI, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8),
646 			  "usampler2D", "uvec4", 0.0f, 255.0f },
647 			{ "rgba32f", GL_RGBA32F, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT),
648 			  "sampler2D", "vec4", 0.0f, 1.0f },
649 		};
650 		for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); ++format)
651 		{
652 			tcu::TestCaseGroup* formatGroup = new tcu::TestCaseGroup(m_testCtx, formats[format].name, "");
653 			group->addChild(formatGroup);
654 
655 			for (int sample = 0; sample < DE_LENGTH_OF_ARRAY(samples); ++sample)
656 			{
657 				formatGroup->addChild(new ShaderMultisampleInterpolationBaseCase(
658 					m_context, samples[sample].name, "", m_glslVersion, cases[caseId].qualifier,
659 					cases[caseId].assignment, cases[caseId].condition, cases[caseId].unique,
660 					formats[format].internalFormat, formats[format].textureFormat, formats[format].sampler,
661 					formats[format].outType, formats[format].min, formats[format].max, samples[sample].samples));
662 			}
663 		}
664 	}
665 }
666 
667 } // glcts
668