• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Shader builtin variable tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktShaderRenderBuiltinVarTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "gluShaderUtil.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuStringTemplate.hpp"
31 #include "tcuTextureUtil.hpp"
32 
33 #include "deMath.h"
34 #include "deRandom.hpp"
35 
36 #include <map>
37 
38 using namespace std;
39 using namespace tcu;
40 using namespace vk;
41 
42 namespace vkt
43 {
44 namespace sr
45 {
46 
47 namespace
48 {
49 
50 class BuiltinGlFrontFacingCaseInstance : public ShaderRenderCaseInstance
51 {
52 public:
53 					BuiltinGlFrontFacingCaseInstance	(Context& context);
54 
55 	TestStatus		iterate								(void);
56 	virtual void	setupDefaultInputs					(void);
57 };
58 
BuiltinGlFrontFacingCaseInstance(Context & context)59 BuiltinGlFrontFacingCaseInstance::BuiltinGlFrontFacingCaseInstance (Context& context)
60 	: ShaderRenderCaseInstance	(context)
61 {
62 }
63 
iterate(void)64 TestStatus BuiltinGlFrontFacingCaseInstance::iterate (void)
65 {
66 	const UVec2		viewportSize	= getViewportSize();
67 	const int		width			= viewportSize.x();
68 	const int		height			= viewportSize.y();
69 	const RGBA		threshold		(2, 2, 2, 2);
70 	Surface			resImage		(width, height);
71 	Surface			refImage		(width, height);
72 	bool			compareOk		= false;
73 	const deUint16	indices[12]		=
74 	{
75 		0, 4, 1,
76 		0, 5, 4,
77 		1, 2, 3,
78 		1, 3, 4
79 	};
80 
81 	setup();
82 	render(6, 4, indices);
83 	copy(resImage.getAccess(), getResultImage().getAccess());
84 
85 	for (int y = 0; y < refImage.getHeight(); y++)
86 	{
87 		for (int x = 0; x < refImage.getWidth()/2; x++)
88 			refImage.setPixel(x, y, RGBA::green());
89 
90 		for (int x = refImage.getWidth()/2; x < refImage.getWidth(); x++)
91 			refImage.setPixel(x, y, RGBA::blue());
92 	}
93 
94 	compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
95 
96 	if (compareOk)
97 		return TestStatus::pass("Result image matches reference");
98 	else
99 		return TestStatus::fail("Image mismatch");
100 }
101 
setupDefaultInputs(void)102 void BuiltinGlFrontFacingCaseInstance::setupDefaultInputs (void)
103 {
104 	const float vertices[] =
105 	{
106 		-1.0f, -1.0f, 0.0f, 1.0f,
107 		 0.0f, -1.0f, 0.0f, 1.0f,
108 		 1.0f, -1.0f, 0.0f, 1.0f,
109 		 1.0f,  1.0f, 0.0f, 1.0f,
110 		 0.0f,  1.0f, 0.0f, 1.0f,
111 		-1.0f,  1.0f, 0.0f, 1.0f
112 	};
113 
114 	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, vertices);
115 }
116 
117 class BuiltinGlFrontFacingCase : public TestCase
118 {
119 public:
120 								BuiltinGlFrontFacingCase	(TestContext& testCtx, const string& name, const string& description);
121 	virtual						~BuiltinGlFrontFacingCase	(void);
122 
123 	void						initPrograms				(SourceCollections& dst) const;
124 	TestInstance*				createInstance				(Context& context) const;
125 
126 private:
127 								BuiltinGlFrontFacingCase	(const BuiltinGlFrontFacingCase&);	// not allowed!
128 	BuiltinGlFrontFacingCase&	operator=					(const BuiltinGlFrontFacingCase&);	// not allowed!
129 };
130 
BuiltinGlFrontFacingCase(TestContext & testCtx,const string & name,const string & description)131 BuiltinGlFrontFacingCase::BuiltinGlFrontFacingCase (TestContext& testCtx, const string& name, const string& description)
132 	: TestCase(testCtx, name, description)
133 {
134 }
135 
~BuiltinGlFrontFacingCase(void)136 BuiltinGlFrontFacingCase::~BuiltinGlFrontFacingCase (void)
137 {
138 }
139 
initPrograms(SourceCollections & dst) const140 void BuiltinGlFrontFacingCase::initPrograms (SourceCollections& dst) const
141 {
142 	dst.glslSources.add("vert") << glu::VertexSource(
143 		"#version 310 es\n"
144 		"layout(location = 0) in highp vec4 a_position;\n"
145 		"void main (void)\n"
146 		"{\n"
147 		"       gl_Position = a_position;\n"
148 		"}\n");
149 
150 	dst.glslSources.add("frag") << glu::FragmentSource(
151 		"#version 310 es\n"
152 		"layout(location = 0) out lowp vec4 o_color;\n"
153 		"void main (void)\n"
154 		"{\n"
155 		"       if (gl_FrontFacing)\n"
156 		"               o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
157 		"       else\n"
158 		"               o_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
159 		"}\n");
160 }
161 
createInstance(Context & context) const162 TestInstance* BuiltinGlFrontFacingCase::createInstance (Context& context) const
163 {
164 	return new BuiltinGlFrontFacingCaseInstance(context);
165 }
166 
167 class BuiltinGlFragCoordXYZCaseInstance : public ShaderRenderCaseInstance
168 {
169 public:
170 					BuiltinGlFragCoordXYZCaseInstance	(Context& context);
171 
172 	TestStatus		iterate								(void);
173 	virtual void	setupDefaultInputs					(void);
174 };
175 
BuiltinGlFragCoordXYZCaseInstance(Context & context)176 BuiltinGlFragCoordXYZCaseInstance::BuiltinGlFragCoordXYZCaseInstance (Context& context)
177 	: ShaderRenderCaseInstance	(context)
178 {
179 }
180 
iterate(void)181 TestStatus BuiltinGlFragCoordXYZCaseInstance::iterate (void)
182 {
183 	const UVec2		viewportSize	= getViewportSize();
184 	const int		width			= viewportSize.x();
185 	const int		height			= viewportSize.y();
186 	const tcu::Vec3	scale			(1.f / float(width), 1.f / float(height), 1.0f);
187 	const tcu::RGBA	threshold		(2, 2, 2, 2);
188 	Surface			resImage		(width, height);
189 	Surface			refImage		(width, height);
190 	bool			compareOk		= false;
191 	const deUint16	indices[6]		=
192 	{
193 		2, 1, 3,
194 		0, 1, 2,
195 	};
196 
197 	setup();
198 	addUniform(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, scale);
199 
200 	render(4, 2, indices);
201 	copy(resImage.getAccess(), getResultImage().getAccess());
202 
203 	// Reference image
204 	for (int y = 0; y < refImage.getHeight(); y++)
205 	{
206 		for (int x = 0; x < refImage.getWidth(); x++)
207 		{
208 			const float	xf			= (float(x)+.5f) / float(refImage.getWidth());
209 			const float	yf			= (float(refImage.getHeight()-y-1)+.5f) / float(refImage.getHeight());
210 			const float	z			= (xf + yf) / 2.0f;
211 			const Vec3	fragCoord	(float(x)+.5f, float(y)+.5f, z);
212 			const Vec3	scaledFC	= fragCoord*scale;
213 			const Vec4	color		(scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);
214 
215 			refImage.setPixel(x, y, RGBA(color));
216 		}
217 	}
218 
219 	compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
220 
221 	if (compareOk)
222 		return TestStatus::pass("Result image matches reference");
223 	else
224 		return TestStatus::fail("Image mismatch");
225 }
226 
setupDefaultInputs(void)227 void BuiltinGlFragCoordXYZCaseInstance::setupDefaultInputs (void)
228 {
229 	const float		vertices[]		=
230 	{
231 		-1.0f,  1.0f,  0.0f, 1.0f,
232 		-1.0f, -1.0f,  0.5f, 1.0f,
233 		 1.0f,  1.0f,  0.5f, 1.0f,
234 		 1.0f, -1.0f,  1.0f, 1.0f,
235 	};
236 
237 	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
238 }
239 
240 class BuiltinGlFragCoordXYZCase : public TestCase
241 {
242 public:
243 								BuiltinGlFragCoordXYZCase	(TestContext& testCtx, const string& name, const string& description);
244 	virtual						~BuiltinGlFragCoordXYZCase	(void);
245 
246 	void						initPrograms				(SourceCollections& dst) const;
247 	TestInstance*				createInstance				(Context& context) const;
248 
249 private:
250 								BuiltinGlFragCoordXYZCase	(const BuiltinGlFragCoordXYZCase&);	// not allowed!
251 	BuiltinGlFragCoordXYZCase&	operator=					(const BuiltinGlFragCoordXYZCase&);	// not allowed!
252 };
253 
BuiltinGlFragCoordXYZCase(TestContext & testCtx,const string & name,const string & description)254 BuiltinGlFragCoordXYZCase::BuiltinGlFragCoordXYZCase (TestContext& testCtx, const string& name, const string& description)
255 	: TestCase(testCtx, name, description)
256 {
257 }
258 
~BuiltinGlFragCoordXYZCase(void)259 BuiltinGlFragCoordXYZCase::~BuiltinGlFragCoordXYZCase (void)
260 {
261 }
262 
initPrograms(SourceCollections & dst) const263 void BuiltinGlFragCoordXYZCase::initPrograms (SourceCollections& dst) const
264 {
265 	dst.glslSources.add("vert") << glu::VertexSource(
266 		"#version 310 es\n"
267 		"layout(location = 0) in highp vec4 a_position;\n"
268 		"void main (void)\n"
269 		"{\n"
270 		"       gl_Position = a_position;\n"
271 		"}\n");
272 
273 	dst.glslSources.add("frag") << glu::FragmentSource(
274 		"#version 310 es\n"
275 		"layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
276 		"layout(location = 0) out highp vec4 o_color;\n"
277 		"void main (void)\n"
278 		"{\n"
279 		"       o_color = vec4(gl_FragCoord.xyz * u_scale, 1.0);\n"
280 		"}\n");
281 }
282 
createInstance(Context & context) const283 TestInstance* BuiltinGlFragCoordXYZCase::createInstance (Context& context) const
284 {
285 	return new BuiltinGlFragCoordXYZCaseInstance(context);
286 }
287 
projectedTriInterpolate(const Vec3 & s,const Vec3 & w,float nx,float ny)288 inline float projectedTriInterpolate (const Vec3& s, const Vec3& w, float nx, float ny)
289 {
290 	return (s[0]*(1.0f-nx-ny)/w[0] + s[1]*ny/w[1] + s[2]*nx/w[2]) / ((1.0f-nx-ny)/w[0] + ny/w[1] + nx/w[2]);
291 }
292 
293 class BuiltinGlFragCoordWCaseInstance : public ShaderRenderCaseInstance
294 {
295 public:
296 					BuiltinGlFragCoordWCaseInstance	(Context& context);
297 
298 	TestStatus		iterate							(void);
299 	virtual void	setupDefaultInputs				(void);
300 
301 private:
302 
303 	const Vec4		m_w;
304 
305 };
306 
BuiltinGlFragCoordWCaseInstance(Context & context)307 BuiltinGlFragCoordWCaseInstance::BuiltinGlFragCoordWCaseInstance (Context& context)
308 	: ShaderRenderCaseInstance	(context)
309 	, m_w						(1.7f, 2.0f, 1.2f, 1.0f)
310 {
311 }
312 
iterate(void)313 TestStatus BuiltinGlFragCoordWCaseInstance::iterate (void)
314 {
315 	const UVec2		viewportSize	= getViewportSize();
316 	const int		width			= viewportSize.x();
317 	const int		height			= viewportSize.y();
318 	const tcu::RGBA	threshold		(2, 2, 2, 2);
319 	Surface			resImage		(width, height);
320 	Surface			refImage		(width, height);
321 	bool			compareOk		= false;
322 	const deUint16	indices[6]		=
323 	{
324 		2, 1, 3,
325 		0, 1, 2,
326 	};
327 
328 	setup();
329 	render(4, 2, indices);
330 	copy(resImage.getAccess(), getResultImage().getAccess());
331 
332 	// Reference image
333 	for (int y = 0; y < refImage.getHeight(); y++)
334 	{
335 		for (int x = 0; x < refImage.getWidth(); x++)
336 		{
337 			const float	xf			= (float(x)+.5f) / float(refImage.getWidth());
338 			const float	yf			= (float(refImage.getHeight()-y-1)+.5f) / float(refImage.getHeight());
339 			const float	oow			= ((xf + yf) < 1.0f)
340 										? projectedTriInterpolate(Vec3(m_w[0], m_w[1], m_w[2]), Vec3(m_w[0], m_w[1], m_w[2]), xf, yf)
341 										: projectedTriInterpolate(Vec3(m_w[3], m_w[2], m_w[1]), Vec3(m_w[3], m_w[2], m_w[1]), 1.0f-xf, 1.0f-yf);
342 			const Vec4	color		(0.0f, oow - 1.0f, 0.0f, 1.0f);
343 
344 			refImage.setPixel(x, y, RGBA(color));
345 		}
346 	}
347 
348 	compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
349 
350 	if (compareOk)
351 		return TestStatus::pass("Result image matches reference");
352 	else
353 		return TestStatus::fail("Image mismatch");
354 }
355 
setupDefaultInputs(void)356 void BuiltinGlFragCoordWCaseInstance::setupDefaultInputs (void)
357 {
358 	const float vertices[] =
359 	{
360 		-m_w[0],  m_w[0], 0.0f, m_w[0],
361 		-m_w[1], -m_w[1], 0.0f, m_w[1],
362 		 m_w[2],  m_w[2], 0.0f, m_w[2],
363 		 m_w[3], -m_w[3], 0.0f, m_w[3]
364 	};
365 
366 	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
367 }
368 
369 class BuiltinGlFragCoordWCase : public TestCase
370 {
371 public:
372 								BuiltinGlFragCoordWCase		(TestContext& testCtx, const string& name, const string& description);
373 	virtual						~BuiltinGlFragCoordWCase	(void);
374 
375 	void						initPrograms				(SourceCollections& dst) const;
376 	TestInstance*				createInstance				(Context& context) const;
377 
378 private:
379 								BuiltinGlFragCoordWCase		(const BuiltinGlFragCoordWCase&);	// not allowed!
380 	BuiltinGlFragCoordWCase&	operator=					(const BuiltinGlFragCoordWCase&);	// not allowed!
381 };
382 
BuiltinGlFragCoordWCase(TestContext & testCtx,const string & name,const string & description)383 BuiltinGlFragCoordWCase::BuiltinGlFragCoordWCase (TestContext& testCtx, const string& name, const string& description)
384 	: TestCase(testCtx, name, description)
385 {
386 }
387 
~BuiltinGlFragCoordWCase(void)388 BuiltinGlFragCoordWCase::~BuiltinGlFragCoordWCase (void)
389 {
390 }
391 
initPrograms(SourceCollections & dst) const392 void BuiltinGlFragCoordWCase::initPrograms (SourceCollections& dst) const
393 {
394 	dst.glslSources.add("vert") << glu::VertexSource(
395 		"#version 310 es\n"
396 		"layout(location = 0) in highp vec4 a_position;\n"
397 		"void main (void)\n"
398 		"{\n"
399 		"       gl_Position = a_position;\n"
400 		"}\n");
401 
402 	dst.glslSources.add("frag") << glu::FragmentSource(
403 		"#version 310 es\n"
404 		"layout(location = 0) out highp vec4 o_color;\n"
405 		"void main (void)\n"
406 		"{\n"
407 		"       o_color = vec4(0.0, 1.0 / gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
408 		"}\n");
409 }
410 
createInstance(Context & context) const411 TestInstance* BuiltinGlFragCoordWCase::createInstance (Context& context) const
412 {
413 	return new BuiltinGlFragCoordWCaseInstance(context);
414 }
415 
416 class BuiltinGlPointCoordCaseInstance : public ShaderRenderCaseInstance
417 {
418 public:
419 					BuiltinGlPointCoordCaseInstance	(Context& context);
420 
421 	TestStatus		iterate								(void);
422 	virtual void	setupDefaultInputs					(void);
423 };
424 
BuiltinGlPointCoordCaseInstance(Context & context)425 BuiltinGlPointCoordCaseInstance::BuiltinGlPointCoordCaseInstance (Context& context)
426 	: ShaderRenderCaseInstance	(context)
427 {
428 }
429 
iterate(void)430 TestStatus BuiltinGlPointCoordCaseInstance::iterate (void)
431 {
432 	const UVec2				viewportSize	= getViewportSize();
433 	const int				width			= viewportSize.x();
434 	const int				height			= viewportSize.y();
435 	const float				threshold		= 0.02f;
436 	const int				numPoints		= 16;
437 	vector<Vec3>			coords			(numPoints);
438 	de::Random				rnd				(0x145fa);
439 	Surface					resImage		(width, height);
440 	Surface					refImage		(width, height);
441 	bool					compareOk		= false;
442 
443 	// Compute coordinates.
444 	{
445 		const VkPhysicalDeviceLimits&	limits					= m_context.getDeviceProperties().limits;
446 		const float						minPointSize			= limits.pointSizeRange[0];
447 		const float						maxPointSize			= limits.pointSizeRange[1];
448 		const int						pointSizeDeltaMultiples	= de::max(1, deCeilFloatToInt32((maxPointSize - minPointSize) / limits.pointSizeGranularity));
449 
450 		TCU_CHECK(minPointSize <= maxPointSize);
451 
452 		for (vector<Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
453 		{
454 			coord->x() = rnd.getFloat(-0.9f, 0.9f);
455 			coord->y() = rnd.getFloat(-0.9f, 0.9f);
456 			coord->z() = de::min(maxPointSize, minPointSize + float(rnd.getInt(0, pointSizeDeltaMultiples)) * limits.pointSizeGranularity);
457 		}
458 	}
459 
460 	setup();
461 	addAttribute(0u, VK_FORMAT_R32G32B32_SFLOAT, deUint32(sizeof(Vec3)), numPoints, &coords[0]);
462 	render(numPoints, 0, DE_NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
463 	copy(resImage.getAccess(), getResultImage().getAccess());
464 
465 	// Draw reference
466 	clear(refImage.getAccess(), m_clearColor);
467 
468 	for (vector<Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
469 	{
470 		const float	centerX	= float(width) *(pointIter->x()*0.5f + 0.5f);
471 		const float	centerY	= float(height)*(pointIter->y()*0.5f + 0.5f);
472 		const float	size	= pointIter->z();
473 		const int	x0		= deRoundFloatToInt32(centerX - size*0.5f);
474 		const int	y0		= deRoundFloatToInt32(centerY - size*0.5f);
475 		const int	x1		= deRoundFloatToInt32(centerX + size*0.5f);
476 		const int	y1		= deRoundFloatToInt32(centerY + size*0.5f);
477 		const int	w		= x1-x0;
478 		const int	h		= y1-y0;
479 
480 		for (int yo = 0; yo < h; yo++)
481 		{
482 			for (int xo = 0; xo < w; xo++)
483 			{
484 				const int		dx		= x0+xo;
485 				const int		dy		= y0+yo;
486 				const float		fragX	= float(dx) + 0.5f;
487 				const float		fragY	= float(dy) + 0.5f;
488 				const float		s		= 0.5f + (fragX - centerX) / size;
489 				const float		t		= 0.5f + (fragY - centerY) / size;
490 				const Vec4		color	(s, t, 0.0f, 1.0f);
491 
492 				if (de::inBounds(dx, 0, refImage.getWidth()) && de::inBounds(dy, 0, refImage.getHeight()))
493 					refImage.setPixel(dx, dy, RGBA(color));
494 			}
495 		}
496 	}
497 
498 	compareOk = fuzzyCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
499 
500 	if (compareOk)
501 		return TestStatus::pass("Result image matches reference");
502 	else
503 		return TestStatus::fail("Image mismatch");
504 }
505 
setupDefaultInputs(void)506 void BuiltinGlPointCoordCaseInstance::setupDefaultInputs (void)
507 {
508 }
509 
510 class BuiltinGlPointCoordCase : public TestCase
511 {
512 public:
513 								BuiltinGlPointCoordCase	(TestContext& testCtx, const string& name, const string& description);
514 	virtual						~BuiltinGlPointCoordCase	(void);
515 
516 	void						initPrograms				(SourceCollections& dst) const;
517 	TestInstance*				createInstance				(Context& context) const;
518 
519 private:
520 								BuiltinGlPointCoordCase	(const BuiltinGlPointCoordCase&);	// not allowed!
521 	BuiltinGlPointCoordCase&	operator=					(const BuiltinGlPointCoordCase&);	// not allowed!
522 };
523 
BuiltinGlPointCoordCase(TestContext & testCtx,const string & name,const string & description)524 BuiltinGlPointCoordCase::BuiltinGlPointCoordCase (TestContext& testCtx, const string& name, const string& description)
525 	: TestCase(testCtx, name, description)
526 {
527 }
528 
~BuiltinGlPointCoordCase(void)529 BuiltinGlPointCoordCase::~BuiltinGlPointCoordCase (void)
530 {
531 }
532 
initPrograms(SourceCollections & dst) const533 void BuiltinGlPointCoordCase::initPrograms (SourceCollections& dst) const
534 {
535 	dst.glslSources.add("vert") << glu::VertexSource(
536 		"#version 310 es\n"
537 		"layout(location = 0) in highp vec3 a_position;\n"
538 		"void main (void)\n"
539 		"{\n"
540 		"    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
541 		"    gl_PointSize = a_position.z;\n"
542 		"}\n");
543 
544 	dst.glslSources.add("frag") << glu::FragmentSource(
545 		"#version 310 es\n"
546 		"layout(location = 0) out lowp vec4 o_color;\n"
547 		"void main (void)\n"
548 		"{\n"
549 		"    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
550 		"}\n");
551 }
552 
createInstance(Context & context) const553 TestInstance* BuiltinGlPointCoordCase::createInstance (Context& context) const
554 {
555 	return new BuiltinGlPointCoordCaseInstance(context);
556 }
557 
558 enum ShaderInputTypeBits
559 {
560 	SHADER_INPUT_BUILTIN_BIT	= 0x01,
561 	SHADER_INPUT_VARYING_BIT	= 0x02,
562 	SHADER_INPUT_CONSTANT_BIT	= 0x04
563 };
564 
565 typedef deUint16 ShaderInputTypes;
566 
shaderInputTypeToString(ShaderInputTypes type)567 string shaderInputTypeToString (ShaderInputTypes type)
568 {
569 	string typeString = "input";
570 
571 	if (type == 0)
572 		return "input_none";
573 
574 	if (type & SHADER_INPUT_BUILTIN_BIT)
575 		typeString += "_builtin";
576 
577 	if (type & SHADER_INPUT_VARYING_BIT)
578 		typeString += "_varying";
579 
580 	if (type & SHADER_INPUT_CONSTANT_BIT)
581 		typeString += "_constant";
582 
583 	return typeString;
584 }
585 
586 class BuiltinInputVariationsCaseInstance : public ShaderRenderCaseInstance
587 {
588 public:
589 							BuiltinInputVariationsCaseInstance	(Context& context, const ShaderInputTypes shaderInputTypes);
590 
591 	TestStatus				iterate								(void);
592 	virtual void			setupDefaultInputs					(void);
593 	virtual void			updatePushConstants					(vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout);
594 
595 private:
596 	const ShaderInputTypes	m_shaderInputTypes;
597 	const Vec4				m_constantColor;
598 };
599 
BuiltinInputVariationsCaseInstance(Context & context,const ShaderInputTypes shaderInputTypes)600 BuiltinInputVariationsCaseInstance::BuiltinInputVariationsCaseInstance (Context& context, const ShaderInputTypes shaderInputTypes)
601 	: ShaderRenderCaseInstance	(context)
602 	, m_shaderInputTypes		(shaderInputTypes)
603 	, m_constantColor			(0.1f, 0.05f, 0.2f, 0.0f)
604 {
605 }
606 
iterate(void)607 TestStatus BuiltinInputVariationsCaseInstance::iterate (void)
608 {
609 	const UVec2					viewportSize	= getViewportSize();
610 	const int					width			= viewportSize.x();
611 	const int					height			= viewportSize.y();
612 	const tcu::RGBA				threshold		(2, 2, 2, 2);
613 	Surface						resImage		(width, height);
614 	Surface						refImage		(width, height);
615 	bool						compareOk		= false;
616 	const VkPushConstantRange	pcRanges		=
617 	{
618 		VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags	stageFlags;
619 		0u,								// deUint32				offset;
620 		sizeof(Vec4)					// deUint32				size;
621 	};
622 	const deUint16				indices[12]		=
623 	{
624 		0, 4, 1,
625 		0, 5, 4,
626 		1, 2, 3,
627 		1, 3, 4
628 	};
629 
630 	setup();
631 
632 	if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
633 		setPushConstantRanges(1, &pcRanges);
634 
635 	render(6, 4, indices);
636 	copy(resImage.getAccess(), getResultImage().getAccess());
637 
638 	// Reference image
639 	for (int y = 0; y < refImage.getHeight(); y++)
640 	{
641 		for (int x = 0; x < refImage.getWidth(); x++)
642 		{
643 			Vec4 color (0.1f, 0.2f, 0.3f, 1.0f);
644 
645 			if (((m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT) && (x < refImage.getWidth() / 2)) ||
646 				!(m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT))
647 			{
648 				if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
649 				{
650 					const float xf = (float(x)+.5f) / float(refImage.getWidth());
651 					color += Vec4(0.6f * (1 - xf), 0.6f * xf, 0.0f, 0.0f);
652 				}
653 				else
654 					color += Vec4(0.3f, 0.2f, 0.1f, 0.0f);
655 			}
656 
657 			if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
658 				color += m_constantColor;
659 
660 			refImage.setPixel(x, y, RGBA(color));
661 		}
662 	}
663 
664 	compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
665 
666 	if (compareOk)
667 		return TestStatus::pass("Result image matches reference");
668 	else
669 		return TestStatus::fail("Image mismatch");
670 }
671 
setupDefaultInputs(void)672 void BuiltinInputVariationsCaseInstance::setupDefaultInputs (void)
673 {
674 	const float vertices[] =
675 	{
676 		-1.0f, -1.0f, 0.0f, 1.0f,
677 		 0.0f, -1.0f, 0.0f, 1.0f,
678 		 1.0f, -1.0f, 0.0f, 1.0f,
679 		 1.0f,  1.0f, 0.0f, 1.0f,
680 		 0.0f,  1.0f, 0.0f, 1.0f,
681 		-1.0f,  1.0f, 0.0f, 1.0f
682 	};
683 
684 	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, vertices);
685 
686 	if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
687 	{
688 		const float colors[] =
689 		{
690 			 0.6f,  0.0f, 0.0f, 1.0f,
691 			 0.3f,  0.3f, 0.0f, 1.0f,
692 			 0.0f,  0.6f, 0.0f, 1.0f,
693 			 0.0f,  0.6f, 0.0f, 1.0f,
694 			 0.3f,  0.3f, 0.0f, 1.0f,
695 			 0.6f,  0.0f, 0.0f, 1.0f
696 		};
697 		addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, colors);
698 	}
699 }
700 
updatePushConstants(vk::VkCommandBuffer commandBuffer,vk::VkPipelineLayout pipelineLayout)701 void BuiltinInputVariationsCaseInstance::updatePushConstants (vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout)
702 {
703 	if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
704 	{
705 		const DeviceInterface& vk = m_context.getDeviceInterface();
706 		vk.cmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(Vec4), &m_constantColor);
707 	}
708 }
709 
710 class BuiltinInputVariationsCase : public TestCase
711 {
712 public:
713 								BuiltinInputVariationsCase	(TestContext& testCtx, const string& name, const string& description, const ShaderInputTypes shaderInputTypes);
714 	virtual						~BuiltinInputVariationsCase	(void);
715 
716 	void						initPrograms				(SourceCollections& dst) const;
717 	TestInstance*				createInstance				(Context& context) const;
718 
719 private:
720 								BuiltinInputVariationsCase	(const BuiltinInputVariationsCase&);	// not allowed!
721 	BuiltinInputVariationsCase&	operator=					(const BuiltinInputVariationsCase&);	// not allowed!
722 	const ShaderInputTypes		m_shaderInputTypes;
723 };
724 
BuiltinInputVariationsCase(TestContext & testCtx,const string & name,const string & description,ShaderInputTypes shaderInputTypes)725 BuiltinInputVariationsCase::BuiltinInputVariationsCase (TestContext& testCtx, const string& name, const string& description, ShaderInputTypes shaderInputTypes)
726 	: TestCase				(testCtx, name, description)
727 	, m_shaderInputTypes	(shaderInputTypes)
728 {
729 }
730 
~BuiltinInputVariationsCase(void)731 BuiltinInputVariationsCase::~BuiltinInputVariationsCase (void)
732 {
733 }
734 
initPrograms(SourceCollections & dst) const735 void BuiltinInputVariationsCase::initPrograms (SourceCollections& dst) const
736 {
737 	map<string, string>			vertexParams;
738 	map<string, string>			fragmentParams;
739 	const tcu::StringTemplate	vertexCodeTemplate		(
740 		"#version 450\n"
741 		"layout(location = 0) in highp vec4 a_position;\n"
742 		"out gl_PerVertex {\n"
743 		"	vec4 gl_Position;\n"
744 		"};\n"
745 		"${VARYING_DECL}"
746 		"void main (void)\n"
747 		"{\n"
748 		"    gl_Position = a_position;\n"
749 		"    ${VARYING_USAGE}"
750 		"}\n");
751 
752 	const tcu::StringTemplate	fragmentCodeTemplate	(
753 		"#version 450\n"
754 		"${VARYING_DECL}"
755 		"${CONSTANT_DECL}"
756 		"layout(location = 0) out highp vec4 o_color;\n"
757 		"void main (void)\n"
758 		"{\n"
759 		"    o_color = vec4(0.1, 0.2, 0.3, 1.0);\n"
760 		"    ${BUILTIN_USAGE}"
761 		"    ${VARYING_USAGE}"
762 		"    ${CONSTANT_USAGE}"
763 		"}\n");
764 
765 	vertexParams["VARYING_DECL"]		=
766 		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "layout(location = 1) in highp vec4 a_color;\n"
767 														  "layout(location = 0) out highp vec4 v_color;\n"
768 														: "";
769 
770 	vertexParams["VARYING_USAGE"]		=
771 		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "v_color = a_color;\n"
772 														: "";
773 
774 	fragmentParams["VARYING_DECL"]		=
775 		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "layout(location = 0) in highp vec4 a_color;\n"
776 														: "";
777 
778 	fragmentParams["CONSTANT_DECL"]		=
779 		m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT	? "layout(push_constant) uniform PCBlock {\n"
780 														  "  vec4 color;\n"
781 														  "} pc;\n"
782 														: "";
783 
784 	fragmentParams["BUILTIN_USAGE"]		=
785 		m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT	? "if (gl_FrontFacing)\n"
786 														: "";
787 
788 	fragmentParams["VARYING_USAGE"]		=
789 		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "o_color += vec4(a_color.xyz, 0.0);\n"
790 														: "o_color += vec4(0.3, 0.2, 0.1, 0.0);\n";
791 
792 
793 	fragmentParams["CONSTANT_USAGE"]	=
794 		m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT	? "o_color += pc.color;\n"
795 														: "";
796 
797 	dst.glslSources.add("vert") << glu::VertexSource(vertexCodeTemplate.specialize(vertexParams));
798 	dst.glslSources.add("frag") << glu::FragmentSource(fragmentCodeTemplate.specialize(fragmentParams));
799 }
800 
createInstance(Context & context) const801 TestInstance* BuiltinInputVariationsCase::createInstance (Context& context) const
802 {
803 	return new BuiltinInputVariationsCaseInstance(context, m_shaderInputTypes);
804 }
805 
806 } // anonymous
807 
createBuiltinVarTests(TestContext & testCtx)808 TestCaseGroup* createBuiltinVarTests (TestContext& testCtx)
809 {
810 	de::MovePtr<TestCaseGroup> builtinGroup			(new TestCaseGroup(testCtx, "builtin_var", "Shader builtin variable tests."));
811 	de::MovePtr<TestCaseGroup> simpleGroup			(new TestCaseGroup(testCtx, "simple", "Simple cases."));
812 	de::MovePtr<TestCaseGroup> inputVariationsGroup	(new TestCaseGroup(testCtx, "input_variations", "Input type variation tests."));
813 
814 	simpleGroup->addChild(new BuiltinGlFrontFacingCase(testCtx, "frontfacing", "FrontFacing test"));
815 	simpleGroup->addChild(new BuiltinGlFragCoordXYZCase(testCtx, "fragcoord_xyz", "FragCoord xyz test"));
816 	simpleGroup->addChild(new BuiltinGlFragCoordWCase(testCtx, "fragcoord_w", "FragCoord w test"));
817 	simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord", "PointCoord test"));
818 
819 	builtinGroup->addChild(simpleGroup.release());
820 
821 	for (deUint16 shaderType = 0; shaderType <= (SHADER_INPUT_BUILTIN_BIT | SHADER_INPUT_VARYING_BIT | SHADER_INPUT_CONSTANT_BIT); ++shaderType)
822 	{
823 		inputVariationsGroup->addChild(new BuiltinInputVariationsCase(testCtx, shaderInputTypeToString(shaderType), "Input variation test", shaderType));
824 	}
825 
826 	builtinGroup->addChild(inputVariationsGroup.release());
827 	return builtinGroup.release();
828 }
829 
830 } // sr
831 } // vkt
832