• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Sample shading tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fSampleShadingTests.hpp"
25 #include "es31fMultisampleShaderRenderCase.hpp"
26 #include "tcuRenderTarget.hpp"
27 #include "tcuSurface.hpp"
28 #include "glsStateQueryUtil.hpp"
29 #include "gluCallLogWrapper.hpp"
30 #include "gluContextInfo.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "gluRenderContext.hpp"
33 #include "gluPixelTransfer.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36 #include "deStringUtil.hpp"
37 #include "deRandom.hpp"
38 
39 #include <map>
40 
41 namespace deqp
42 {
43 namespace gles31
44 {
45 namespace Functional
46 {
47 namespace
48 {
49 
50 using namespace gls::StateQueryUtil;
51 
52 class SampleShadingStateCase : public TestCase
53 {
54 public:
55 						SampleShadingStateCase	(Context& ctx, const char* name, const char* desc, QueryType);
56 
57 	void				init					(void);
58 	IterateResult		iterate					(void);
59 
60 private:
61 	const QueryType		m_verifier;
62 };
63 
SampleShadingStateCase(Context & ctx,const char * name,const char * desc,QueryType type)64 SampleShadingStateCase::SampleShadingStateCase (Context& ctx, const char* name, const char* desc, QueryType type)
65 	: TestCase		(ctx, name, desc)
66 	, m_verifier	(type)
67 {
68 }
69 
init(void)70 void SampleShadingStateCase::init (void)
71 {
72 	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
73 		throw tcu::NotSupportedError("Test requires GL_OES_sample_shading extension or a context version 3.2 or higher.");
74 }
75 
iterate(void)76 SampleShadingStateCase::IterateResult SampleShadingStateCase::iterate (void)
77 {
78 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
79 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
80 	gl.enableLogging(true);
81 
82 	// initial
83 	{
84 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying initial value" << tcu::TestLog::EndMessage;
85 		verifyStateBoolean(result, gl, GL_SAMPLE_SHADING, false, m_verifier);
86 	}
87 
88 	// true and false too
89 	{
90 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying random values" << tcu::TestLog::EndMessage;
91 
92 		gl.glEnable(GL_SAMPLE_SHADING);
93 		verifyStateBoolean(result, gl, GL_SAMPLE_SHADING, true, m_verifier);
94 
95 		gl.glDisable(GL_SAMPLE_SHADING);
96 		verifyStateBoolean(result, gl, GL_SAMPLE_SHADING, false, m_verifier);
97 	}
98 
99 	result.setTestContextResult(m_testCtx);
100 	return STOP;
101 }
102 
103 class MinSampleShadingValueCase : public TestCase
104 {
105 public:
106 						MinSampleShadingValueCase	(Context& ctx, const char* name, const char* desc, QueryType);
107 
108 	void				init						(void);
109 	IterateResult		iterate						(void);
110 
111 private:
112 	const QueryType		m_verifier;
113 };
114 
MinSampleShadingValueCase(Context & ctx,const char * name,const char * desc,QueryType type)115 MinSampleShadingValueCase::MinSampleShadingValueCase (Context& ctx, const char* name, const char* desc, QueryType type)
116 	: TestCase		(ctx, name, desc)
117 	, m_verifier	(type)
118 {
119 }
120 
init(void)121 void MinSampleShadingValueCase::init (void)
122 {
123 	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
124 		throw tcu::NotSupportedError("Test requires GL_OES_sample_shading extension or a context version 3.2 or higher.");
125 }
126 
iterate(void)127 MinSampleShadingValueCase::IterateResult MinSampleShadingValueCase::iterate (void)
128 {
129 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
130 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
131 
132 	gl.enableLogging(true);
133 
134 	// initial
135 	{
136 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying initial value" << tcu::TestLog::EndMessage;
137 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, m_verifier);
138 	}
139 
140 	// special values
141 	{
142 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying special values" << tcu::TestLog::EndMessage;
143 
144 		gl.glMinSampleShading(0.0f);
145 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, m_verifier);
146 
147 		gl.glMinSampleShading(1.0f);
148 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, m_verifier);
149 
150 		gl.glMinSampleShading(0.5f);
151 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.5, m_verifier);
152 	}
153 
154 	// random values
155 	{
156 		const int	numRandomTests	= 10;
157 		de::Random	rnd				(0xde123);
158 
159 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying random values" << tcu::TestLog::EndMessage;
160 
161 		for (int randNdx = 0; randNdx < numRandomTests; ++randNdx)
162 		{
163 			const float value = rnd.getFloat();
164 
165 			gl.glMinSampleShading(value);
166 			verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, value, m_verifier);
167 		}
168 	}
169 
170 	result.setTestContextResult(m_testCtx);
171 	return STOP;
172 }
173 
174 class MinSampleShadingValueClampingCase : public TestCase
175 {
176 public:
177 						MinSampleShadingValueClampingCase	(Context& ctx, const char* name, const char* desc);
178 
179 	void				init								(void);
180 	IterateResult		iterate								(void);
181 };
182 
MinSampleShadingValueClampingCase(Context & ctx,const char * name,const char * desc)183 MinSampleShadingValueClampingCase::MinSampleShadingValueClampingCase (Context& ctx, const char* name, const char* desc)
184 	: TestCase(ctx, name, desc)
185 {
186 }
187 
init(void)188 void MinSampleShadingValueClampingCase::init (void)
189 {
190 	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
191 		throw tcu::NotSupportedError("Test requires GL_OES_sample_shading extension or a context version 3.2 or higher.");
192 }
193 
iterate(void)194 MinSampleShadingValueClampingCase::IterateResult MinSampleShadingValueClampingCase::iterate (void)
195 {
196 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
197 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
198 	gl.enableLogging(true);
199 
200 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
201 
202 	// special values
203 	{
204 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying clamped values. Value is clamped when specified." << tcu::TestLog::EndMessage;
205 
206 		gl.glMinSampleShading(-0.5f);
207 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, QUERY_FLOAT);
208 
209 		gl.glMinSampleShading(-1.0f);
210 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, QUERY_FLOAT);
211 
212 		gl.glMinSampleShading(-1.5f);
213 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, QUERY_FLOAT);
214 
215 		gl.glMinSampleShading(1.5f);
216 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, QUERY_FLOAT);
217 
218 		gl.glMinSampleShading(2.0f);
219 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, QUERY_FLOAT);
220 
221 		gl.glMinSampleShading(2.5f);
222 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, QUERY_FLOAT);
223 	}
224 
225 	result.setTestContextResult(m_testCtx);
226 	return STOP;
227 }
228 
229 class SampleShadingRenderingCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
230 {
231 public:
232 	enum TestType
233 	{
234 		TEST_DISCARD = 0,
235 		TEST_COLOR,
236 
237 		TEST_LAST
238 	};
239 						SampleShadingRenderingCase	(Context& ctx, const char* name, const char* desc, RenderTarget target, int numSamples, TestType type);
240 						~SampleShadingRenderingCase	(void);
241 
242 	void				init						(void);
243 private:
244 	void				setShadingValue				(int sampleCount);
245 
246 	void				preDraw						(void);
247 	void				postDraw					(void);
248 	std::string			getIterationDescription		(int iteration) const;
249 
250 	bool				verifyImage					(const tcu::Surface& resultImage);
251 
252 	std::string			genFragmentSource			(int numSamples) const;
253 
254 	enum
255 	{
256 		RENDER_SIZE = 128
257 	};
258 
259 	const TestType		m_type;
260 };
261 
SampleShadingRenderingCase(Context & ctx,const char * name,const char * desc,RenderTarget target,int numSamples,TestType type)262 SampleShadingRenderingCase::SampleShadingRenderingCase (Context& ctx, const char* name, const char* desc, RenderTarget target, int numSamples, TestType type)
263 	: MultisampleShaderRenderUtil::MultisampleRenderCase	(ctx, name, desc, numSamples, target, RENDER_SIZE)
264 	, m_type												(type)
265 {
266 	DE_ASSERT(type < TEST_LAST);
267 }
268 
~SampleShadingRenderingCase(void)269 SampleShadingRenderingCase::~SampleShadingRenderingCase (void)
270 {
271 	deinit();
272 }
273 
init(void)274 void SampleShadingRenderingCase::init (void)
275 {
276 	// requirements
277 
278 	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
279 		throw tcu::NotSupportedError("Test requires GL_OES_sample_shading extension or a context version 3.2 or higher.");
280 	if (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1)
281 		throw tcu::NotSupportedError("Multisampled default framebuffer required");
282 
283 	// test purpose and expectations
284 	m_testCtx.getLog()
285 		<< tcu::TestLog::Message
286 		<< "Verifying that a varying is given at least N different values for different samples within a single pixel.\n"
287 		<< "	Render high-frequency function, map result to black/white. Modify N with glMinSampleShading().\n"
288 		<< "	=> Resulting image should contain N+1 shades of gray.\n"
289 		<< tcu::TestLog::EndMessage;
290 
291 	// setup resources
292 
293 	MultisampleShaderRenderUtil::MultisampleRenderCase::init();
294 
295 	// set iterations
296 
297 	m_numIterations = m_numTargetSamples + 1;
298 }
299 
setShadingValue(int sampleCount)300 void SampleShadingRenderingCase::setShadingValue (int sampleCount)
301 {
302 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
303 
304 	if (sampleCount == 0)
305 	{
306 		gl.disable(GL_SAMPLE_SHADING);
307 		gl.minSampleShading(1.0f);
308 		GLU_EXPECT_NO_ERROR(gl.getError(), "set ratio");
309 	}
310 	else
311 	{
312 		// Minimum number of samples is max(ceil(<mss> * <samples>),1). Decrease mss with epsilon to prevent
313 		// ceiling to a too large sample count.
314 		const float epsilon	= 0.25f / (float)m_numTargetSamples;
315 		const float ratio	= ((float)sampleCount / (float)m_numTargetSamples) - epsilon;
316 
317 		gl.enable(GL_SAMPLE_SHADING);
318 		gl.minSampleShading(ratio);
319 		GLU_EXPECT_NO_ERROR(gl.getError(), "set ratio");
320 
321 		m_testCtx.getLog()
322 			<< tcu::TestLog::Message
323 			<< "Setting MIN_SAMPLE_SHADING_VALUE = " << ratio << "\n"
324 			<< "Requested sample count: shadingValue * numSamples = " << ratio << " * " << m_numTargetSamples << " = " << (ratio * (float)m_numTargetSamples) << "\n"
325 			<< "Minimum sample count: ceil(shadingValue * numSamples) = ceil(" << (ratio * (float)m_numTargetSamples) << ") = " << sampleCount
326 			<< tcu::TestLog::EndMessage;
327 
328 		// can't fail with reasonable values of numSamples
329 		DE_ASSERT(deFloatCeil(ratio * (float)m_numTargetSamples) == float(sampleCount));
330 	}
331 }
332 
preDraw(void)333 void SampleShadingRenderingCase::preDraw (void)
334 {
335 	setShadingValue(m_iteration);
336 }
337 
postDraw(void)338 void SampleShadingRenderingCase::postDraw (void)
339 {
340 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
341 
342 	gl.disable(GL_SAMPLE_SHADING);
343 	gl.minSampleShading(1.0f);
344 }
345 
getIterationDescription(int iteration) const346 std::string	SampleShadingRenderingCase::getIterationDescription (int iteration) const
347 {
348 	if (iteration == 0)
349 		return "Disabled SAMPLE_SHADING";
350 	else
351 		return "Samples per pixel: " + de::toString(iteration);
352 }
353 
verifyImage(const tcu::Surface & resultImage)354 bool SampleShadingRenderingCase::verifyImage (const tcu::Surface& resultImage)
355 {
356 	const int				numShadesRequired	= (m_iteration == 0) ? (2) : (m_iteration + 1);
357 	const int				rareThreshold		= 100;
358 	int						rareCount			= 0;
359 	std::map<deUint32, int>	shadeFrequency;
360 
361 	// we should now have n+1 different shades of white, n = num samples
362 
363 	m_testCtx.getLog()
364 		<< tcu::TestLog::Image("ResultImage", "Result Image", resultImage.getAccess())
365 		<< tcu::TestLog::Message
366 		<< "Verifying image has (at least) " << numShadesRequired << " different shades.\n"
367 		<< "Excluding pixels with no full coverage (pixels on the shared edge of the triangle pair)."
368 		<< tcu::TestLog::EndMessage;
369 
370 	for (int y = 0; y < RENDER_SIZE; ++y)
371 	for (int x = 0; x < RENDER_SIZE; ++x)
372 	{
373 		const tcu::RGBA	color	= resultImage.getPixel(x, y);
374 		const deUint32	packed	= ((deUint32)color.getRed()) + ((deUint32)color.getGreen() << 8) + ((deUint32)color.getGreen() << 16);
375 
376 		// on the triangle edge, skip
377 		if (x == y)
378 			continue;
379 
380 		if (shadeFrequency.find(packed) == shadeFrequency.end())
381 			shadeFrequency[packed] = 1;
382 		else
383 			shadeFrequency[packed] = shadeFrequency[packed] + 1;
384 	}
385 
386 	for (std::map<deUint32, int>::const_iterator it = shadeFrequency.begin(); it != shadeFrequency.end(); ++it)
387 		if (it->second < rareThreshold)
388 			rareCount++;
389 
390 	m_testCtx.getLog()
391 		<< tcu::TestLog::Message
392 		<< "Found " << (int)shadeFrequency.size() << " different shades.\n"
393 		<< "\tRare (less than " << rareThreshold << " pixels): " << rareCount << "\n"
394 		<< "\tCommon: " << (int)shadeFrequency.size() - rareCount << "\n"
395 		<< tcu::TestLog::EndMessage;
396 
397 	if ((int)shadeFrequency.size() < numShadesRequired)
398 	{
399 		m_testCtx.getLog() << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage;
400 		return false;
401 	}
402 	return true;
403 }
404 
genFragmentSource(int numSamples) const405 std::string SampleShadingRenderingCase::genFragmentSource (int numSamples) const
406 {
407 	DE_UNREF(numSamples);
408 	const glu::GLSLVersion	version	= contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2))
409 									? glu::GLSL_VERSION_320_ES
410 									: glu::GLSL_VERSION_310_ES;
411 	std::ostringstream		buf;
412 
413 	buf <<	glu::getGLSLVersionDeclaration(version) << "\n"
414 			"in highp vec4 v_position;\n"
415 			"layout(location = 0) out mediump vec4 fragColor;\n"
416 			"void main (void)\n"
417 			"{\n"
418 			"	highp float field = dot(v_position.xy, v_position.xy) + dot(21.0 * v_position.xx, sin(3.1 * v_position.xy));\n"
419 			"	fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
420 			"\n"
421 			"	if (fract(field) > 0.5)\n";
422 
423 	if (m_type == TEST_DISCARD)
424 		buf <<	"		discard;\n";
425 	else if (m_type == TEST_COLOR)
426 		buf <<	"		fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n";
427 	else
428 		DE_ASSERT(false);
429 
430 	buf <<	"}";
431 
432 	return buf.str();
433 }
434 
435 } // anonymous
436 
SampleShadingTests(Context & context)437 SampleShadingTests::SampleShadingTests (Context& context)
438 	: TestCaseGroup(context, "sample_shading", "Test sample shading")
439 {
440 }
441 
~SampleShadingTests(void)442 SampleShadingTests::~SampleShadingTests (void)
443 {
444 }
445 
init(void)446 void SampleShadingTests::init (void)
447 {
448 	tcu::TestCaseGroup* const stateQueryGroup = new tcu::TestCaseGroup(m_testCtx, "state_query", "State query tests.");
449 	tcu::TestCaseGroup* const minSamplesGroup = new tcu::TestCaseGroup(m_testCtx, "min_sample_shading", "Min sample shading tests.");
450 
451 	addChild(stateQueryGroup);
452 	addChild(minSamplesGroup);
453 
454 	// .state query
455 	{
456 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_is_enabled",				"test SAMPLE_SHADING",						QUERY_ISENABLED));
457 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_boolean",				"test SAMPLE_SHADING",						QUERY_BOOLEAN));
458 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_integer",				"test SAMPLE_SHADING",						QUERY_INTEGER));
459 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_float",					"test SAMPLE_SHADING",						QUERY_FLOAT));
460 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_integer64",				"test SAMPLE_SHADING",						QUERY_INTEGER64));
461 		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_boolean",		"test MIN_SAMPLE_SHADING_VALUE",			QUERY_BOOLEAN));
462 		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_integer",		"test MIN_SAMPLE_SHADING_VALUE",			QUERY_INTEGER));
463 		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_float",		"test MIN_SAMPLE_SHADING_VALUE",			QUERY_FLOAT));
464 		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_integer64",	"test MIN_SAMPLE_SHADING_VALUE",			QUERY_INTEGER64));
465 		stateQueryGroup->addChild(new MinSampleShadingValueClampingCase	(m_context, "min_sample_shading_value_clamping",		"test MIN_SAMPLE_SHADING_VALUE clamping"));
466 	}
467 
468 	// .min_sample_count
469 	{
470 		static const struct Target
471 		{
472 			SampleShadingRenderingCase::RenderTarget	target;
473 			int											numSamples;
474 			const char*									name;
475 		} targets[] =
476 		{
477 			{ SampleShadingRenderingCase::TARGET_DEFAULT,			0,	"default_framebuffer"					},
478 			{ SampleShadingRenderingCase::TARGET_TEXTURE,			2,	"multisample_texture_samples_2"			},
479 			{ SampleShadingRenderingCase::TARGET_TEXTURE,			4,	"multisample_texture_samples_4"			},
480 			{ SampleShadingRenderingCase::TARGET_TEXTURE,			8,	"multisample_texture_samples_8"			},
481 			{ SampleShadingRenderingCase::TARGET_TEXTURE,			16,	"multisample_texture_samples_16"		},
482 			{ SampleShadingRenderingCase::TARGET_RENDERBUFFER,		2,	"multisample_renderbuffer_samples_2"	},
483 			{ SampleShadingRenderingCase::TARGET_RENDERBUFFER,		4,	"multisample_renderbuffer_samples_4"	},
484 			{ SampleShadingRenderingCase::TARGET_RENDERBUFFER,		8,	"multisample_renderbuffer_samples_8"	},
485 			{ SampleShadingRenderingCase::TARGET_RENDERBUFFER,		16,	"multisample_renderbuffer_samples_16"	},
486 		};
487 
488 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(targets); ++ndx)
489 		{
490 			minSamplesGroup->addChild(new SampleShadingRenderingCase(m_context, (std::string(targets[ndx].name) + "_color").c_str(),	"Test multiple samples per pixel with color",	targets[ndx].target, targets[ndx].numSamples, SampleShadingRenderingCase::TEST_COLOR));
491 			minSamplesGroup->addChild(new SampleShadingRenderingCase(m_context, (std::string(targets[ndx].name) + "_discard").c_str(),	"Test multiple samples per pixel with",			targets[ndx].target, targets[ndx].numSamples, SampleShadingRenderingCase::TEST_DISCARD));
492 		}
493 	}
494 }
495 
496 } // Functional
497 } // gles31
498 } // deqp
499