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
28#include "tcuFloat.hpp"
29#include "deUniquePtr.hpp"
30#include "vkDefs.hpp"
31#include "vktShaderRender.hpp"
32#include "gluShaderUtil.hpp"
33#include "tcuImageCompare.hpp"
34#include "tcuStringTemplate.hpp"
35#include "tcuTextureUtil.hpp"
36#include "tcuTestLog.hpp"
37#include "vktDrawUtil.hpp"
38#include "vkImageUtil.hpp"
39#include "vkTypeUtil.hpp"
40#include "vkMemUtil.hpp"
41#include "vkCmdUtil.hpp"
42
43#include "deMath.h"
44#include "deRandom.hpp"
45
46#include <map>
47
48using namespace std;
49using namespace tcu;
50using namespace vk;
51using namespace de;
52
53namespace vkt
54{
55using namespace drawutil;
56
57namespace sr
58{
59
60namespace
61{
62
63enum
64{
65	FRONTFACE_RENDERWIDTH			= 16,
66	FRONTFACE_RENDERHEIGHT			= 16
67};
68
69class FrontFacingVertexShader : public rr::VertexShader
70{
71public:
72	FrontFacingVertexShader (void)
73		: rr::VertexShader(1, 0)
74	{
75		m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
76	}
77
78	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
79	{
80		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
81		{
82			packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
83																	 packets[packetNdx]->instanceNdx,
84																	 packets[packetNdx]->vertexNdx);
85		}
86	}
87};
88
89class FrontFacingFragmentShader : public rr::FragmentShader
90{
91public:
92	FrontFacingFragmentShader (void)
93		: rr::FragmentShader(0, 1)
94	{
95		m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
96	}
97
98	void shadeFragments (rr::FragmentPacket* , const int numPackets, const rr::FragmentShadingContext& context) const
99	{
100		tcu::Vec4 color;
101		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
102		{
103			for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
104			{
105				if (context.visibleFace == rr::FACETYPE_FRONT)
106					color = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
107				else
108					color = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
109				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
110			}
111		}
112	}
113};
114
115class BuiltinGlFrontFacingCaseInstance : public ShaderRenderCaseInstance
116{
117public:
118					BuiltinGlFrontFacingCaseInstance	(Context& context, VkPrimitiveTopology topology);
119
120	TestStatus		iterate								(void);
121private:
122	const VkPrimitiveTopology							m_topology;
123};
124
125BuiltinGlFrontFacingCaseInstance::BuiltinGlFrontFacingCaseInstance (Context& context, VkPrimitiveTopology topology)
126	: ShaderRenderCaseInstance	(context)
127	, m_topology				(topology)
128{
129}
130
131
132TestStatus BuiltinGlFrontFacingCaseInstance::iterate (void)
133{
134	TestLog&							log				= m_context.getTestContext().getLog();
135	std::vector<Vec4>					vertices;
136	std::vector<VulkanShader>			shaders;
137	std::shared_ptr<rr::VertexShader>	vertexShader	= std::make_shared<FrontFacingVertexShader>();
138	std::shared_ptr<rr::FragmentShader>	fragmentShader	= std::make_shared<FrontFacingFragmentShader>();
139	std::string							testDesc;
140
141	vertices.push_back(Vec4( -0.75f,	-0.75f,	0.0f,	1.0f));
142	vertices.push_back(Vec4(  0.0f,		-0.75f,	0.0f,	1.0f));
143	vertices.push_back(Vec4( -0.37f,	0.75f,	0.0f,	1.0f));
144	vertices.push_back(Vec4(  0.37f,	0.75f,	0.0f,	1.0f));
145	vertices.push_back(Vec4(  0.75f,	-0.75f,	0.0f,	1.0f));
146	vertices.push_back(Vec4(  0.0f,		-0.75f,	0.0f,	1.0f));
147
148	shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert")));
149	shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag")));
150
151	testDesc = "gl_FrontFacing " + getPrimitiveTopologyShortName(m_topology) + " ";
152
153	FrameBufferState			frameBufferState	(FRONTFACE_RENDERWIDTH, FRONTFACE_RENDERHEIGHT);
154	PipelineState				pipelineState		(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
155	DrawCallData				drawCallData		(m_topology, vertices);
156	VulkanProgram				vulkanProgram		(shaders);
157	VulkanDrawContext			dc					(m_context, frameBufferState);
158	dc.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
159	dc.draw();
160
161	ReferenceDrawContext		refDrawContext(frameBufferState);
162	refDrawContext.registerDrawObject(pipelineState, vertexShader, fragmentShader, drawCallData);
163	refDrawContext.draw();
164
165	log << TestLog::Image( "reference",
166							"reference",
167							tcu::ConstPixelBufferAccess(tcu::TextureFormat(
168									refDrawContext.getColorPixels().getFormat()),
169									refDrawContext.getColorPixels().getWidth(),
170									refDrawContext.getColorPixels().getHeight(),
171									1,
172									refDrawContext.getColorPixels().getDataPtr()));
173
174	log << TestLog::Image(	"result",
175							"result",
176							tcu::ConstPixelBufferAccess(tcu::TextureFormat(
177									dc.getColorPixels().getFormat()),
178									dc.getColorPixels().getWidth(),
179									dc.getColorPixels().getHeight(),
180									1,
181									dc.getColorPixels().getDataPtr()));
182
183	if (tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
184												  "ComparisonResult",
185												  "Image comparison result",
186												  refDrawContext.getColorPixels(),
187												  dc.getColorPixels(),
188												  UVec4(0u),
189												  IVec3(1,1,0),
190												  false,
191												  tcu::COMPARE_LOG_RESULT))
192	{
193		testDesc += "passed";
194		return tcu::TestStatus::pass(testDesc.c_str());
195	}
196	else
197	{
198		testDesc += "failed";
199		return tcu::TestStatus::fail(testDesc.c_str());
200	}
201}
202
203class BuiltinGlFrontFacingCase : public TestCase
204{
205public:
206								BuiltinGlFrontFacingCase	(TestContext& testCtx, VkPrimitiveTopology topology, const char* name);
207	virtual						~BuiltinGlFrontFacingCase	(void);
208
209	void						initPrograms				(SourceCollections& dst) const;
210	void						checkSupport				(Context& context) const;
211	TestInstance*				createInstance				(Context& context) const;
212
213private:
214								BuiltinGlFrontFacingCase	(const BuiltinGlFrontFacingCase&);	// not allowed!
215	BuiltinGlFrontFacingCase&	operator=					(const BuiltinGlFrontFacingCase&);	// not allowed!
216
217	const VkPrimitiveTopology	m_topology;
218};
219
220BuiltinGlFrontFacingCase::BuiltinGlFrontFacingCase (TestContext& testCtx, VkPrimitiveTopology topology, const char* name)
221	: TestCase					(testCtx, name)
222	, m_topology				(topology)
223{
224}
225
226BuiltinGlFrontFacingCase::~BuiltinGlFrontFacingCase (void)
227{
228}
229
230void BuiltinGlFrontFacingCase::initPrograms (SourceCollections& programCollection) const
231{
232	{
233		std::ostringstream vertexSource;
234		vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
235			<< "\n"
236			<< "layout(location = 0) in highp vec4 position;\n"
237			<< "void main()\n"
238			<< "{\n"
239			<< "gl_Position = position;\n"
240			<< "gl_PointSize = 1.0;\n"
241			<< "}\n";
242		programCollection.glslSources.add("vert") << glu::VertexSource(vertexSource.str());
243	}
244
245	{
246		std::ostringstream fragmentSource;
247		fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
248			<< "\n"
249			<< "layout(location = 0) out mediump vec4 color;\n"
250			<< "void main()\n"
251			<< "{\n"
252			<< "if (gl_FrontFacing)\n"
253			<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
254			<< "else\n"
255			<< "	color = vec4(0.0, 1.0, 0.0, 1.0);\n"
256			<< "}\n";
257		programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentSource.str());
258	}
259}
260
261void BuiltinGlFrontFacingCase::checkSupport (Context& context) const
262{
263#ifndef CTS_USES_VULKANSC
264	if (m_topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
265		context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
266		!context.getPortabilitySubsetFeatures().triangleFans)
267	{
268		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
269	}
270#else
271	DE_UNREF(context);
272#endif // CTS_USES_VULKANSC
273}
274
275TestInstance* BuiltinGlFrontFacingCase::createInstance (Context& context) const
276{
277	return new BuiltinGlFrontFacingCaseInstance(context, m_topology);
278}
279
280class BuiltinFragDepthCaseInstance : public TestInstance
281{
282public:
283	enum
284	{
285		RENDERWIDTH		= 16,
286		RENDERHEIGHT	= 16
287	};
288					BuiltinFragDepthCaseInstance		(Context& context, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable, float defaultDepth, bool depthClampEnable, const VkSampleCountFlagBits samples);
289	TestStatus		iterate								(void);
290
291	bool			validateDepthBuffer					(const tcu::ConstPixelBufferAccess& validationBuffer, const tcu::ConstPixelBufferAccess& markerBuffer, const float tolerance) const;
292private:
293	const VkPrimitiveTopology		m_topology;
294	const VkFormat					m_format;
295	const bool						m_largeDepthEnable;
296	const float						m_defaultDepthValue;
297	const bool						m_depthClampEnable;
298	const VkSampleCountFlagBits		m_samples;
299	const tcu::UVec2				m_renderSize;
300	const float						m_largeDepthBase;
301};
302
303BuiltinFragDepthCaseInstance::BuiltinFragDepthCaseInstance (Context& context, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable, float defaultDepth, bool depthClampEnable, const VkSampleCountFlagBits samples)
304	: TestInstance			(context)
305	, m_topology			(topology)
306	, m_format				(format)
307	, m_largeDepthEnable	(largeDepthEnable)
308	, m_defaultDepthValue	(defaultDepth)
309	, m_depthClampEnable	(depthClampEnable)
310	, m_samples				(samples)
311	, m_renderSize			(RENDERWIDTH, RENDERHEIGHT)
312	, m_largeDepthBase		(20.0f)
313{
314	const InstanceInterface&	vki					= m_context.getInstanceInterface();
315	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();
316
317	try
318	{
319		VkImageFormatProperties		imageFormatProperties;
320		VkFormatProperties			formatProperties;
321
322		if (m_context.getDeviceFeatures().fragmentStoresAndAtomics == VK_FALSE)
323			throw tcu::NotSupportedError("fragmentStoresAndAtomics not supported");
324
325		if (m_context.getDeviceFeatures().sampleRateShading == VK_FALSE)
326			throw tcu::NotSupportedError("sampleRateShading not supported");
327
328		imageFormatProperties = getPhysicalDeviceImageFormatProperties(vki, physicalDevice, m_format, VK_IMAGE_TYPE_2D,
329				VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, (VkImageCreateFlags)0);
330
331		if ((imageFormatProperties.sampleCounts & m_samples) == 0)
332			throw tcu::NotSupportedError("Image format and sample count not supported");
333
334		formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, VK_FORMAT_R8G8B8A8_UINT);
335
336		if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
337			throw tcu::NotSupportedError("MarkerImage format not supported as storage image");
338
339		if (m_largeDepthEnable && !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_EXT_depth_range_unrestricted"))
340			throw tcu::NotSupportedError("large_depth test variants require the VK_EXT_depth_range_unrestricted extension");
341
342		if (m_context.getDeviceFeatures().depthClamp == VK_FALSE && m_depthClampEnable)
343			throw tcu::NotSupportedError("Depthclamp is not supported.");
344	}
345	catch (const vk::Error& e)
346	{
347		if (e.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
348			throw tcu::NotSupportedError("Image format not supported");
349		else
350			throw;
351
352	}
353}
354
355TestStatus BuiltinFragDepthCaseInstance::iterate (void)
356{
357	const VkDevice					device				= m_context.getDevice();
358	const DeviceInterface&			vk					= m_context.getDeviceInterface();
359	const VkQueue					queue				= m_context.getUniversalQueue();
360	Allocator&						allocator			= m_context.getDefaultAllocator();
361	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
362	TestLog&						log					= m_context.getTestContext().getLog();
363	const deUint32					scale				= 4;										// To account for std140 stride
364	const VkDeviceSize				pixelCount			= m_renderSize.x() * m_renderSize.y();
365	std::string						testDesc;
366	Move<VkImage>					depthResolveImage;
367	Move<VkImageView>				depthResolveImageView;
368	MovePtr<Allocation>				depthResolveAllocation;
369	Move<VkImage>					depthImage;
370	Move<VkImageView>				depthImageView;
371	MovePtr<Allocation>				depthImageAllocation;
372	Move<VkBuffer>					controlBuffer;
373	MovePtr<Allocation>				controlBufferAllocation;
374	Move<VkImage>					markerImage;
375	Move<VkImageView>				markerImageView;
376	MovePtr<Allocation>				markerImageAllocation;
377	Move<VkBuffer>					markerBuffer;
378	MovePtr<Allocation>				markerBufferAllocation;
379	Move<VkBuffer>					validationBuffer;
380	MovePtr<Allocation>				validationAlloc;
381	MovePtr<Allocation>				depthInitAllocation;
382	Move<VkCommandPool>				cmdPool;
383	Move<VkCommandBuffer>			transferCmdBuffer;
384	Move<VkSampler>					depthSampler;
385
386	// Create Buffer/Image for validation
387	{
388		VkFormat	resolvedBufferFormat = VK_FORMAT_R32_SFLOAT;
389		const VkBufferCreateInfo validationBufferCreateInfo =
390		{
391			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,										// VkStructureType		sType
392			DE_NULL,																	// const void*			pNext
393			(VkBufferCreateFlags)0,														// VkBufferCreateFlags	flags
394			m_samples * pixelCount * getPixelSize(mapVkFormat(resolvedBufferFormat)),	// VkDeviceSize			size
395			VK_BUFFER_USAGE_TRANSFER_DST_BIT,											// VkBufferUsageFlags	usage
396			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode
397			0u,																			// uint32_t				queueFamilyIndexCount,
398			DE_NULL																		// const uint32_t*		pQueueFamilyIndices
399		};
400
401		validationBuffer = createBuffer(vk, device, &validationBufferCreateInfo);
402		validationAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *validationBuffer), MemoryRequirement::HostVisible);
403		VK_CHECK(vk.bindBufferMemory(device, *validationBuffer, validationAlloc->getMemory(), validationAlloc->getOffset()));
404
405		const VkImageCreateInfo depthResolveImageCreateInfo =
406		{
407			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,								// VkStructureType			sType
408			DE_NULL,															// const void*				pNext
409			(VkImageCreateFlags)0,												// VkImageCreateFlags		flags
410			VK_IMAGE_TYPE_2D,													// VkIMageType				imageType
411			resolvedBufferFormat,												// VkFormat					format
412			makeExtent3D(m_samples * m_renderSize.x(), m_renderSize.y(), 1u),	// VkExtent3D				extent
413			1u,																	// uint32_t					mipLevels
414			1u,																	// uint32_t					arrayLayers
415			VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagsBits	samples
416			VK_IMAGE_TILING_OPTIMAL,											// VkImageTiling			tiling
417			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |									// VkImageUsageFlags		usage
418			VK_IMAGE_USAGE_STORAGE_BIT |
419			VK_IMAGE_USAGE_TRANSFER_DST_BIT,
420			VK_SHARING_MODE_EXCLUSIVE,											// VkSharingMode			sharingMode
421			0u,																	// uint32_t					queueFamilyIndexCount
422			DE_NULL,															// const uint32_t			pQueueFamilyIndices
423			VK_IMAGE_LAYOUT_UNDEFINED											// VkImageLayout			initialLayout
424		};
425
426		depthResolveImage = createImage(vk, device, &depthResolveImageCreateInfo, DE_NULL);
427		depthResolveAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *depthResolveImage), MemoryRequirement::Any);
428		VK_CHECK(vk.bindImageMemory(device, *depthResolveImage, depthResolveAllocation->getMemory(), depthResolveAllocation->getOffset()));
429
430		const VkImageViewCreateInfo depthResolveImageViewCreateInfo =
431		{
432			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,								// VkStructureType			sType
433			DE_NULL,																// const void*				pNext
434			(VkImageViewCreateFlags)0,												// VkImageViewCreateFlags	flags
435			*depthResolveImage,														// VkImage					image
436			VK_IMAGE_VIEW_TYPE_2D,													// VkImageViewType			type
437			resolvedBufferFormat,													// VkFormat					format
438			makeComponentMappingRGBA(),												// VkComponentMapping		componentMapping
439			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)	// VkImageSUbresourceRange	subresourceRange
440		};
441
442		depthResolveImageView = createImageView(vk, device, &depthResolveImageViewCreateInfo, DE_NULL);
443	}
444
445	// Marker Buffer
446	{
447		const VkDeviceSize	size			= m_samples * m_renderSize.x() * m_renderSize.y() * getPixelSize(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT));
448
449		const VkBufferCreateInfo markerBufferCreateInfo =
450		{
451			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,			// VkStructureType			sType
452			DE_NULL,										// const void*				pNext
453			(VkBufferCreateFlags)0,							// VkBufferCreateFlags		flags
454			size,											// VkDeviceSize				size
455			VK_BUFFER_USAGE_TRANSFER_DST_BIT,				// VkBufferUsageFlags		usage
456			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode
457			0u,												// uint32_t					queueFamilyIndexCount
458			DE_NULL											// const uint32_t*			pQueueFamilyIndices
459		};
460
461		markerBuffer = createBuffer(vk, device, &markerBufferCreateInfo, DE_NULL);
462		markerBufferAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *markerBuffer), MemoryRequirement::HostVisible);
463		VK_CHECK(vk.bindBufferMemory(device, *markerBuffer, markerBufferAllocation->getMemory(), markerBufferAllocation->getOffset()));
464
465		const VkImageCreateInfo markerImageCreateInfo =
466		{
467			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType
468			DE_NULL,														// const void*				pNext
469			(VkImageCreateFlags)0,											// VkImageCreateFlags		flags
470			VK_IMAGE_TYPE_2D,												// VkImageType				imageType
471			VK_FORMAT_R8G8B8A8_UINT,										// VkFormat					format
472			makeExtent3D(m_samples * m_renderSize.x(), m_renderSize.y(), 1),// VkExtent3D				extent
473			1u,																// uint32_t					mipLevels
474			1u,																// uint32_t					arrayLayers
475			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagsBit	smaples
476			VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling
477			VK_IMAGE_USAGE_STORAGE_BIT |									// VkImageUsageFlags		usage
478			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
479			VK_IMAGE_USAGE_TRANSFER_DST_BIT,
480			VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharing
481			0u,																// uint32_t					queueFamilyIndexCount
482			DE_NULL,														// const uint32_t*			pQueueFamilyIndices
483			VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout
484		};
485
486		markerImage = createImage(vk, device, &markerImageCreateInfo, DE_NULL);
487		markerImageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *markerImage), MemoryRequirement::Any);
488		VK_CHECK(vk.bindImageMemory(device, *markerImage, markerImageAllocation->getMemory(), markerImageAllocation->getOffset()));
489
490		const VkImageViewCreateInfo markerViewCreateInfo =
491		{
492			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,				// VkStructureType			sType
493			DE_NULL,												// const void*				pNext
494			(VkImageViewCreateFlags)0,								// VkImageViewCreateFlags	flags
495			*markerImage,											// VkImage					image
496			VK_IMAGE_VIEW_TYPE_2D,									// VkImageViewType			viewType
497			VK_FORMAT_R8G8B8A8_UINT,								// VkFormat					format
498			makeComponentMappingRGBA(),								// VkComponentMapping		components
499			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)
500		};
501
502		markerImageView = createImageView(vk, device, &markerViewCreateInfo, DE_NULL);
503	}
504
505	// Control Buffer
506	{
507		const VkBufferCreateInfo controlBufferCreateInfo =
508		{
509			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,					// VkStructureType		sType
510			DE_NULL,												// const void*			pNext
511			(VkBufferCreateFlags)0,									// VkBufferCreateFlags	flags
512			pixelCount * sizeof(float)* scale,						// VkDeviceSize			size
513			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,						// VkBufferUsageFlags	usage
514			VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode		sharingMode
515			0u,														// deUint32				queueFamilyIndexCount
516
517			DE_NULL													// pQueueFamilyIndices
518		};
519
520		controlBuffer = createBuffer(vk, device, &controlBufferCreateInfo, DE_NULL);
521		controlBufferAllocation = allocator.allocate( getBufferMemoryRequirements(vk, device, *controlBuffer), MemoryRequirement::HostVisible);
522		VK_CHECK(vk.bindBufferMemory(device, *controlBuffer, controlBufferAllocation->getMemory(), controlBufferAllocation->getOffset()));
523
524		{
525			float* bufferData = (float*)(controlBufferAllocation->getHostPtr());
526			float sign = m_depthClampEnable ? -1.0f : 1.0f;
527			for (deUint32 ndx = 0; ndx < m_renderSize.x() * m_renderSize.y(); ndx++)
528			{
529				bufferData[ndx * scale] = (float)ndx / 256.0f * sign;
530				if (m_largeDepthEnable)
531					bufferData[ndx * scale] += m_largeDepthBase;
532			}
533
534			const VkMappedMemoryRange range =
535			{
536				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
537				DE_NULL,
538				controlBufferAllocation->getMemory(),
539				0u,
540				VK_WHOLE_SIZE
541			};
542
543			VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &range));
544		}
545	}
546
547	// Depth Buffer
548	{
549		VkImageSubresourceRange depthSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
550		const VkImageCreateInfo depthImageCreateInfo	=
551		{
552			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType
553			DE_NULL,												// const void*				pNext
554			(VkImageCreateFlags)0,									// VkImageCreateFlags		flags
555			VK_IMAGE_TYPE_2D,										// VkImageType				imageType
556			m_format,												// VkFormat					format
557			makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u),	// VkExtent3D				extent
558			1u,														// uint32_t					mipLevels
559			1u,														// uint32_t					arrayLayers
560			m_samples,												// VkSampleCountFlagsBits	samples
561			VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling
562			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
563			VK_IMAGE_USAGE_TRANSFER_DST_BIT |
564			VK_IMAGE_USAGE_SAMPLED_BIT      |
565			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,			// VkImageUsageFlags		usage
566			VK_SHARING_MODE_EXCLUSIVE,								// VkShaderingMode			sharingMode
567			0u,														// uint32_t					queueFamilyIndexCount
568			DE_NULL,												// const uint32_t*			pQueueFamilyIndices
569			VK_IMAGE_LAYOUT_UNDEFINED								// VkImageLayout			initialLayout
570		};
571
572		depthImage = createImage(vk, device, &depthImageCreateInfo, DE_NULL);
573		depthImageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *depthImage), MemoryRequirement::Any);
574		VK_CHECK(vk.bindImageMemory(device, *depthImage, depthImageAllocation->getMemory(), depthImageAllocation->getOffset()));
575
576		const VkImageViewCreateInfo imageViewParams =
577		{
578			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
579			DE_NULL,										// const void*				pNext;
580			(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
581			*depthImage,									// VkImage					image;
582			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
583			m_format,										// VkFormat					format;
584			makeComponentMappingRGBA(),						// VkComponentMapping		components;
585			depthSubresourceRange,							// VkImageSubresourceRange	subresourceRange;
586		};
587		depthImageView = createImageView(vk, device, &imageViewParams);
588
589		const VkSamplerCreateInfo depthSamplerCreateInfo =
590		{
591			VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// VkStructureType			sType
592			DE_NULL,										// const void*				pNext
593			(VkSamplerCreateFlags)0,						// VkSamplerCreateFlags		flags
594			VK_FILTER_NEAREST,								// VkFilter					minFilter
595			VK_FILTER_NEAREST,								// VkFilter					magFilter
596			VK_SAMPLER_MIPMAP_MODE_NEAREST,					// VkSamplerMipMapMode		mipMapMode
597			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressModeU
598			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressModeV
599			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressmodeW
600			0.0f,											// float					mipLodBias
601			VK_FALSE,										// VkBool32					anisotropyEnable
602			0.0f,											// float					maxAnisotropy
603			VK_FALSE,										// VkBool32					compareEnable
604			VK_COMPARE_OP_NEVER,							// VkCompareOp				compareOp
605			0.0f,											// float					minLod
606			0.0f,											// float					maxLod
607			VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,		// VkBorderColor			borderColor
608			VK_FALSE										// VkBool32					unnormalizedCoordinates
609		};
610
611		depthSampler = createSampler(vk, device, &depthSamplerCreateInfo, DE_NULL);
612	}
613
614	// Command Pool
615	{
616		const VkCommandPoolCreateInfo cmdPoolCreateInfo =
617		{
618			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType
619			DE_NULL,											// const void*				pNext
620			VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags
621			queueFamilyIndex									// uint32_t					queueFamilyIndex
622		};
623
624		cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
625	}
626
627	// Command buffer for data transfers
628	{
629		const VkCommandBufferAllocateInfo cmdBufferAllocInfo =
630		{
631			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType		sType,
632			DE_NULL,										// const void*			pNext
633			*cmdPool,										// VkCommandPool		commandPool
634			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel	level
635			1u												// uint32_t				bufferCount
636		};
637
638		transferCmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocInfo);
639	}
640
641	// Initialize Marker Buffer
642	{
643		const VkImageMemoryBarrier imageBarrier[] =
644		{
645			{
646				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
647				DE_NULL,										// const void*			pNext
648				0,												// VkAccessMask			srcAccessMask
649				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessMask			dstAccessMask
650				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout		oldLayout
651				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout		newLayout
652				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
653				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
654				*markerImage,									// VkImage				image
655				{
656					VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
657					0u,										// uint32_t				baseMipLevel
658					1u,										// uint32_t				mipLevels
659					0u,										// uint32_t				baseArray
660					1u										// uint32_t				arraySize
661				}
662			},
663		};
664
665		const VkImageMemoryBarrier imagePostBarrier[] =
666		{
667			{
668				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
669				DE_NULL,										// const void*			pNext
670				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlagBits		srcAccessMask
671				VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlagBits		dstAccessMask
672				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout		oldLayout
673				VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout		newLayout
674				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
675				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
676				*markerImage,									// VkImage				image
677				{
678					VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
679					0u,										// uint32_t				baseMipLevel
680					1u,										// uint32_t				mipLevels
681					0u,										// uint32_t				baseArray
682					1u										// uint32_t				arraySize
683				}
684			},
685		};
686
687		beginCommandBuffer(vk, *transferCmdBuffer);
688		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
689				(VkDependencyFlags)0,
690				0, (const VkMemoryBarrier*)DE_NULL,
691				0, (const VkBufferMemoryBarrier*)DE_NULL,
692				DE_LENGTH_OF_ARRAY(imageBarrier), imageBarrier);
693
694		const VkClearValue				colorClearValue	= makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 0.0f));
695		const VkImageSubresourceRange	colorClearRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
696
697		vk.cmdClearColorImage(*transferCmdBuffer, *markerImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &colorClearValue.color, 1u, &colorClearRange);
698
699		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
700				(VkDependencyFlags)0,
701				0, (const VkMemoryBarrier*)DE_NULL,
702				0, (const VkBufferMemoryBarrier*)DE_NULL,
703				DE_LENGTH_OF_ARRAY(imagePostBarrier), imagePostBarrier);
704
705		endCommandBuffer(vk, *transferCmdBuffer);
706
707		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
708		m_context.resetCommandPoolForVKSC(device, *cmdPool);
709	}
710
711
712	// Perform Draw
713	{
714		std::vector<Vec4>				vertices;
715		std::vector<VulkanShader>		shaders;
716		Move<VkDescriptorSetLayout>		descriptorSetLayout;
717		Move<VkDescriptorPool>			descriptorPool;
718		Move<VkDescriptorSet>			descriptorSet;
719
720		// Descriptors
721		{
722			DescriptorSetLayoutBuilder	layoutBuilder;
723			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
724			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
725			descriptorSetLayout = layoutBuilder.build(vk, device);
726			descriptorPool = DescriptorPoolBuilder()
727					.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
728					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
729					.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
730
731			const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
732			{
733				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
734				DE_NULL,
735				*descriptorPool,
736				1u,
737				&descriptorSetLayout.get()
738			};
739
740			descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
741
742			const VkDescriptorBufferInfo bufferInfo =
743			{
744				*controlBuffer,
745				0u,
746				VK_WHOLE_SIZE
747			};
748
749			const VkDescriptorImageInfo imageInfo =
750			{
751				(VkSampler)DE_NULL,
752				*markerImageView,
753				VK_IMAGE_LAYOUT_GENERAL
754			};
755
756			DescriptorSetUpdateBuilder()
757				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfo)
758				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
759				.update(vk, device);
760		}
761
762		vertices.push_back(Vec4( -0.70f,	0.5f,	0.0f,	1.0f));
763		vertices.push_back(Vec4(  0.45f,	-0.75f,	0.0f,	1.0f));
764		vertices.push_back(Vec4(  0.78f,	0.0f,	0.0f,	1.0f));
765		vertices.push_back(Vec4( -0.1f,		0.6f,	0.0f,	1.0f));
766
767		shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVert")));
768		shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFrag")));
769
770		FrameBufferState			frameBufferState(m_renderSize.x(), m_renderSize.y());
771		PipelineState				pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
772		DrawCallData				drawCallData(m_topology, vertices);
773		VulkanProgram				vulkanProgram(shaders);
774
775		frameBufferState.depthFormat		= m_format;
776		frameBufferState.numSamples			= m_samples;
777		frameBufferState.depthImageView		= *depthImageView;
778		pipelineState.depthClampEnable		= m_depthClampEnable;
779		pipelineState.compareOp				= rr::TESTFUNC_ALWAYS;
780		pipelineState.depthTestEnable		= true;
781		pipelineState.depthWriteEnable		= true;
782		pipelineState.sampleShadingEnable	= true;
783		vulkanProgram.descriptorSetLayout	= *descriptorSetLayout;
784		vulkanProgram.descriptorSet			= *descriptorSet;
785
786		VulkanDrawContext			vulkanDrawContext(m_context, frameBufferState);
787		vulkanDrawContext.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
788		vulkanDrawContext.draw();
789
790		log << TestLog::Image(	"resultColor",
791								"Result Color Buffer",
792								tcu::ConstPixelBufferAccess(tcu::TextureFormat(
793										vulkanDrawContext.getColorPixels().getFormat()),
794										vulkanDrawContext.getColorPixels().getWidth(),
795										vulkanDrawContext.getColorPixels().getHeight(),
796										1,
797										vulkanDrawContext.getColorPixels().getDataPtr()));
798	}
799
800	// Barrier to transition between first and second pass
801	{
802		const VkImageMemoryBarrier imageBarrier[] =
803		{
804			{
805				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType		sType
806				DE_NULL,													// const void*			pNext
807				VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,				// VkAccessFlags		srcAccessMask
808				VK_ACCESS_SHADER_READ_BIT,									// VkAccessFlags		dstAccessMask
809				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,			// VkImageLayout		oldLayout
810				VK_IMAGE_LAYOUT_GENERAL,									// VkImageLayout		newLayout
811				0u,															// deUint32				srcQueueFamilyIndex
812				0u,															// deUint32				dstQueueFamilyIndex
813				*depthImage,												// VkImage				image
814				{
815					VK_IMAGE_ASPECT_DEPTH_BIT,						// VkImageAspectFlags		aspectMask
816					0u,												// deUint32					baseMipLevel
817					1u,												// deUint32					levelCount
818					0u,												// deUint32					baseArrayLayer
819					1u												// deUint32					layerCount
820				}
821			},
822			{
823				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType		sType
824				DE_NULL,													// const void*			pNext
825				0u,															// VkAccessFlags		srcAccessMask
826				VK_ACCESS_HOST_READ_BIT,									// VkAccessFlags		dstAccessMask
827				VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout		oldLayout
828				VK_IMAGE_LAYOUT_GENERAL,									// VkImageLayout		newLayout
829				0u,															// deUint32				srcQueueFamilyIndex
830				0u,															// deUint32				dstQueueFamilyIndex
831				*depthResolveImage,											// VkImage				image
832				{
833					VK_IMAGE_ASPECT_COLOR_BIT,						// VkImageAspectFlags		aspectMask
834					0u,												// deUint32					baseMipLevel
835					1u,												// deUint32					levelCount
836					0u,												// deUint32					baseArrayLayer
837					1u,												// deUint32					layerCount
838
839				}
840			}
841		};
842
843		beginCommandBuffer(vk, *transferCmdBuffer);
844		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_HOST_BIT,
845				(VkDependencyFlags)0,
846				0, (const VkMemoryBarrier*)DE_NULL,
847				0, (const VkBufferMemoryBarrier*)DE_NULL,
848				DE_LENGTH_OF_ARRAY(imageBarrier), imageBarrier);
849		endCommandBuffer(vk, *transferCmdBuffer);
850
851		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
852		m_context.resetCommandPoolForVKSC(device, *cmdPool);
853	}
854
855	// Resolve Depth Buffer
856	{
857		std::vector<Vec4>				vertices;
858		std::vector<VulkanShader>		shaders;
859		Move<VkDescriptorSetLayout>		descriptorSetLayout;
860		Move<VkDescriptorPool>			descriptorPool;
861		Move<VkDescriptorSet>			descriptorSet;
862
863		// Descriptors
864		{
865			DescriptorSetLayoutBuilder	layoutBuilder;
866			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
867			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
868			descriptorSetLayout = layoutBuilder.build(vk, device);
869			descriptorPool = DescriptorPoolBuilder()
870					.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
871					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
872					.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
873
874			const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
875			{
876				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
877				DE_NULL,
878				*descriptorPool,
879				1u,
880				&descriptorSetLayout.get()
881			};
882
883			descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
884
885			const VkDescriptorImageInfo depthImageInfo =
886			{
887				*depthSampler,
888				*depthImageView,
889				VK_IMAGE_LAYOUT_GENERAL
890			};
891
892			const VkDescriptorImageInfo imageInfo =
893			{
894				(VkSampler)DE_NULL,
895				*depthResolveImageView,
896				VK_IMAGE_LAYOUT_GENERAL
897			};
898
899			DescriptorSetUpdateBuilder()
900				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &depthImageInfo)
901				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
902				.update(vk, device);
903		}
904
905		vertices.push_back(Vec4( -1.0f,	-1.0f,	0.0f,	1.0f));
906		vertices.push_back(Vec4( -1.0f,	 1.0f,	0.0f,	1.0f));
907		vertices.push_back(Vec4(  1.0f,	-1.0f,	0.0f,	1.0f));
908		vertices.push_back(Vec4(  1.0f,	 1.0f,	0.0f,	1.0f));
909
910		shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVertPass2")));
911		shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFragPass2")));
912
913		FrameBufferState			frameBufferState(m_renderSize.x(), m_renderSize.y());
914		PipelineState				pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
915		DrawCallData				drawCallData(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, vertices);
916		VulkanProgram				vulkanProgram(shaders);
917
918		frameBufferState.numSamples				= m_samples;
919		pipelineState.sampleShadingEnable		= true;
920		vulkanProgram.descriptorSetLayout		= *descriptorSetLayout;
921		vulkanProgram.descriptorSet				= *descriptorSet;
922
923		VulkanDrawContext		vulkanDrawContext(m_context, frameBufferState);
924		vulkanDrawContext.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
925		vulkanDrawContext.draw();
926	}
927
928	// Transfer marker buffer
929	{
930		beginCommandBuffer(vk, *transferCmdBuffer);
931		copyImageToBuffer(vk, *transferCmdBuffer, *markerImage, *markerBuffer, tcu::IVec2(m_renderSize.x() * m_samples, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
932		endCommandBuffer(vk, *transferCmdBuffer);
933
934		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
935		m_context.resetCommandPoolForVKSC(device, *cmdPool);
936	}
937
938	// Verify depth buffer
939	{
940		bool status;
941
942		beginCommandBuffer(vk, *transferCmdBuffer, 0u);
943		copyImageToBuffer(vk, *transferCmdBuffer, *depthResolveImage, *validationBuffer, tcu::IVec2(m_renderSize.x() * m_samples, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
944		endCommandBuffer(vk, *transferCmdBuffer);
945
946		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
947		m_context.resetCommandPoolForVKSC(device, *cmdPool);
948
949		invalidateMappedMemoryRange(vk, device, validationAlloc->getMemory(), validationAlloc->getOffset(), VK_WHOLE_SIZE);
950		invalidateMappedMemoryRange(vk, device, markerBufferAllocation->getMemory(), markerBufferAllocation->getOffset(), VK_WHOLE_SIZE);
951
952		tcu::ConstPixelBufferAccess resultPixelBuffer(mapVkFormat(VK_FORMAT_R32_SFLOAT), m_renderSize.x() * m_samples, m_renderSize.y(), 1u, validationAlloc->getHostPtr());
953		tcu::ConstPixelBufferAccess markerPixelBuffer(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), m_renderSize.x() * m_samples, m_renderSize.y(), 1u, markerBufferAllocation->getHostPtr());
954		status = validateDepthBuffer(resultPixelBuffer, markerPixelBuffer, 0.001f);
955		testDesc = "gl_FragDepth " + getPrimitiveTopologyShortName(m_topology) + " ";
956		if (status)
957		{
958			testDesc += "passed";
959			return tcu::TestStatus::pass(testDesc.c_str());
960		}
961		else
962		{
963			log << TestLog::Image("resultDepth", "Result Depth Buffer", resultPixelBuffer);
964			testDesc += "failed";
965			return tcu::TestStatus::fail(testDesc.c_str());
966		}
967	}
968}
969
970bool BuiltinFragDepthCaseInstance::validateDepthBuffer (const tcu::ConstPixelBufferAccess& validationBuffer, const tcu::ConstPixelBufferAccess& markerBuffer, const float tolerance) const
971{
972	TestLog& log = m_context.getTestContext().getLog();
973
974	for (deUint32 rowNdx = 0; rowNdx < m_renderSize.y(); rowNdx++)
975	{
976		for (deUint32 colNdx = 0; colNdx < m_renderSize.x(); colNdx++)
977		{
978			const float multiplier		= m_depthClampEnable ? 0.0f : 1.0f;
979			float expectedValue	= (float)(rowNdx * m_renderSize.x() + colNdx)/256.0f * multiplier;
980
981			if (m_largeDepthEnable)
982				expectedValue += m_largeDepthBase;
983
984			for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)m_samples; sampleNdx++)
985			{
986				const float	actualValue		= validationBuffer.getPixel(sampleNdx + m_samples * colNdx, rowNdx).x();
987				const float	markerValue		= markerBuffer.getPixel(sampleNdx + m_samples * colNdx, rowNdx).x();
988
989				if (markerValue != 0)
990				{
991					if (de::abs(expectedValue - actualValue) > tolerance)
992					{
993						log << TestLog::Message << "Mismatch at pixel (" << colNdx << "," << rowNdx << "," << sampleNdx << "): expected " << expectedValue << " but got " << actualValue << TestLog::EndMessage;
994						return false;
995					}
996				}
997				else
998				{
999					if (de::abs(actualValue - m_defaultDepthValue) > tolerance)
1000					{
1001						log << TestLog::Message << "Mismatch at pixel (" << colNdx << "," << rowNdx << "," << sampleNdx << "): expected " << expectedValue << " but got " << actualValue << TestLog::EndMessage;
1002						return false;
1003					}
1004				}
1005			}
1006		}
1007	}
1008
1009	return true;
1010}
1011
1012class BuiltinFragCoordMsaaCaseInstance : public TestInstance
1013{
1014public:
1015	enum
1016	{
1017		RENDERWIDTH		= 16,
1018		RENDERHEIGHT	= 16
1019	};
1020				BuiltinFragCoordMsaaCaseInstance	(Context& context, VkSampleCountFlagBits sampleCount, bool sampleShading, std::vector<uint32_t> sampleMaskArray, bool useEnable);
1021	TestStatus	iterate								(void);
1022private:
1023	bool		validateSampleLocations				(const ConstPixelBufferAccess& sampleLocationBuffer) const;
1024
1025	const tcu::UVec2				m_renderSize;
1026	const VkSampleCountFlagBits		m_sampleCount;
1027	const bool						m_sampleShading;
1028	const std::vector<uint32_t>		m_sampleMaskArray;
1029	const bool						m_useEnable;
1030};
1031
1032BuiltinFragCoordMsaaCaseInstance::BuiltinFragCoordMsaaCaseInstance (Context& context, VkSampleCountFlagBits sampleCount, bool sampleShading, std::vector<uint32_t> sampleMaskArray, bool useEnable)
1033	: TestInstance		(context)
1034	, m_renderSize		(RENDERWIDTH, RENDERHEIGHT)
1035	, m_sampleCount		(sampleCount)
1036	, m_sampleShading	(sampleShading)
1037	, m_sampleMaskArray	(sampleMaskArray)
1038	, m_useEnable		(useEnable)
1039{
1040	const InstanceInterface&	vki					= m_context.getInstanceInterface();
1041	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();
1042
1043	if (!context.getDeviceFeatures().sampleRateShading)
1044		TCU_THROW(NotSupportedError, "sampleRateShading not supported");
1045
1046	try
1047	{
1048		VkImageFormatProperties		imageFormatProperties;
1049		VkFormatProperties			formatProperties;
1050
1051		if (m_context.getDeviceFeatures().fragmentStoresAndAtomics == VK_FALSE)
1052			throw tcu::NotSupportedError("fragmentStoresAndAtomics not supported");
1053
1054		if (m_context.getDeviceFeatures().sampleRateShading == VK_FALSE)
1055			throw tcu::NotSupportedError("sampleRateShading not supported");
1056
1057		imageFormatProperties = getPhysicalDeviceImageFormatProperties(vki, physicalDevice, VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_TYPE_2D,
1058				VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, (VkImageCreateFlags)0);
1059
1060		if ((imageFormatProperties.sampleCounts & m_sampleCount) == 0)
1061			throw tcu::NotSupportedError("Image format and sample count not supported");
1062
1063		formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, VK_FORMAT_R32G32B32A32_SFLOAT);
1064
1065		if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
1066			throw tcu::NotSupportedError("Output format not supported as storage image");
1067	}
1068	catch (const vk::Error& e)
1069	{
1070		if (e.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
1071			throw tcu::NotSupportedError("Image format not supported");
1072		else
1073			throw;
1074
1075	}
1076}
1077
1078TestStatus BuiltinFragCoordMsaaCaseInstance::iterate (void)
1079{
1080	const VkDevice					device				= m_context.getDevice();
1081	const DeviceInterface&			vk					= m_context.getDeviceInterface();
1082	const VkQueue					queue				= m_context.getUniversalQueue();
1083	Allocator&						allocator			= m_context.getDefaultAllocator();
1084	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1085	TestLog&						log					= m_context.getTestContext().getLog();
1086	Move<VkImage>					outputImage;
1087	Move<VkImageView>				outputImageView;
1088	MovePtr<Allocation>				outputImageAllocation;
1089	Move<VkDescriptorSetLayout>		descriptorSetLayout;
1090	Move<VkDescriptorPool>			descriptorPool;
1091	Move<VkDescriptorSet>			descriptorSet;
1092	Move<VkBuffer>					sampleLocationBuffer;
1093	MovePtr<Allocation>				sampleLocationBufferAllocation;
1094	Move<VkCommandPool>				cmdPool;
1095	Move<VkCommandBuffer>			transferCmdBuffer;
1096
1097	// Coordinate result image
1098	{
1099		const VkImageCreateInfo outputImageCreateInfo =
1100		{
1101			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType
1102			DE_NULL,												// const void*				pNext
1103			(VkImageCreateFlags)0,									// VkImageCreateFlags		flags
1104			VK_IMAGE_TYPE_2D,										// VkImageType				imageType
1105			VK_FORMAT_R32G32B32A32_SFLOAT,							// VkFormat					format
1106			makeExtent3D(m_sampleCount * m_renderSize.x(), m_renderSize.y(), 1u),	// VkExtent3D				extent3d
1107			1u,														// uint32_t					mipLevels
1108			1u,														// uint32_t					arrayLayers
1109			VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples
1110			VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling
1111			VK_IMAGE_USAGE_STORAGE_BIT |							// VkImageUsageFlags		usage
1112			VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1113			VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode
1114			0u,														// uint32_t					queueFamilyIndexCount
1115			DE_NULL,												// const uint32_t*			pQueueFamilyIndices
1116			VK_IMAGE_LAYOUT_UNDEFINED								// VkImageLayout			initialLayout
1117		};
1118
1119		outputImage = createImage(vk, device, &outputImageCreateInfo, DE_NULL);
1120		outputImageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *outputImage), MemoryRequirement::Any);
1121		vk.bindImageMemory(device, *outputImage, outputImageAllocation->getMemory(), outputImageAllocation->getOffset());
1122
1123		VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1124		const VkImageViewCreateInfo outputImageViewCreateInfo =
1125		{
1126			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,				// VkStructureType			sType
1127			DE_NULL,												// const void*				pNext
1128			(VkImageViewCreateFlags)0,								// VkImageViewCreateFlags	flags
1129			*outputImage,											// VkImage					image
1130			VK_IMAGE_VIEW_TYPE_2D,									// VkImageViewType			viewType
1131			VK_FORMAT_R32G32B32A32_SFLOAT,							// VkFormat					format,
1132			makeComponentMappingRGBA(),								// VkComponentMapping		components
1133			imageSubresourceRange									// VkImageSubresourceRange	imageSubresourceRange
1134		};
1135
1136		outputImageView = createImageView(vk, device, &outputImageViewCreateInfo);
1137	}
1138
1139	// Validation buffer
1140	{
1141		VkDeviceSize  pixelSize = getPixelSize(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT));
1142		const VkBufferCreateInfo sampleLocationBufferCreateInfo =
1143		{
1144			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,				// VkStructureType		sType
1145			DE_NULL,											// const void*			pNext
1146			(VkBufferCreateFlags)0,								// VkBufferCreateFlags	flags
1147			m_sampleCount * m_renderSize.x() * m_renderSize.y() * pixelSize,	// VkDeviceSize			size
1148			VK_BUFFER_USAGE_TRANSFER_DST_BIT,					// VkBufferUsageFlags	usage
1149			VK_SHARING_MODE_EXCLUSIVE,							// VkSharingMode		mode
1150			0u,													// uint32_t				queueFamilyIndexCount
1151			DE_NULL												// const uint32_t*		pQueueFamilyIndices
1152		};
1153
1154		sampleLocationBuffer = createBuffer(vk, device, &sampleLocationBufferCreateInfo, DE_NULL);
1155		sampleLocationBufferAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *sampleLocationBuffer), MemoryRequirement::HostVisible);
1156		vk.bindBufferMemory(device, *sampleLocationBuffer, sampleLocationBufferAllocation->getMemory(), sampleLocationBufferAllocation->getOffset());
1157	}
1158
1159	// Descriptors
1160	{
1161		DescriptorSetLayoutBuilder		layoutBuilder;
1162		layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
1163		descriptorSetLayout = layoutBuilder.build(vk, device);
1164		descriptorPool = DescriptorPoolBuilder()
1165			.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1166			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1167
1168		const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
1169		{
1170			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1171			DE_NULL,
1172			*descriptorPool,
1173			1u,
1174			&*descriptorSetLayout
1175		};
1176
1177		descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
1178
1179		const VkDescriptorImageInfo imageInfo =
1180		{
1181			(VkSampler)DE_NULL,
1182			*outputImageView,
1183			VK_IMAGE_LAYOUT_GENERAL
1184		};
1185
1186		DescriptorSetUpdateBuilder()
1187			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
1188			.update(vk, device);
1189	}
1190
1191	// Command Pool
1192	{
1193		const VkCommandPoolCreateInfo cmdPoolCreateInfo =
1194		{
1195			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType
1196			DE_NULL,											// const void*				pNext
1197			VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags
1198			queueFamilyIndex									// uint32_t					queueFamilyIndex
1199		};
1200
1201		cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
1202	}
1203
1204	// Command buffer for data transfers
1205	{
1206		const VkCommandBufferAllocateInfo cmdBufferAllocInfo =
1207		{
1208			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType		sType,
1209			DE_NULL,										// const void*			pNext
1210			*cmdPool,										// VkCommandPool		commandPool
1211			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel	level
1212			1u												// uint32_t				bufferCount
1213		};
1214
1215		transferCmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocInfo);
1216	}
1217
1218	// Transition the output image to LAYOUT_GENERAL
1219	{
1220		const VkImageMemoryBarrier barrier =
1221		{
1222			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType		sType
1223			DE_NULL,									// const void*			pNext
1224			0u,											// VkAccessFlags		srcAccessMask
1225			VK_ACCESS_SHADER_WRITE_BIT,					// VkAccessFlags		dstAccessMask
1226			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout		oldLayout
1227			VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout		newLayout
1228			VK_QUEUE_FAMILY_IGNORED,					// uint32_t				srcQueueFamilyIndex
1229			VK_QUEUE_FAMILY_IGNORED,					// uint32_t				dstQueueFamilyIndex
1230			*outputImage,								// VkImage				image
1231			{
1232				VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspectFlags	aspectMask
1233				0u,									// uint32_t				baseMipLevel
1234				1u,									// uint32_t				mipLevels
1235				0u,									// uint32_t				baseArray
1236				1u									// uint32_t				arraySize
1237			}
1238		};
1239
1240		beginCommandBuffer(vk, *transferCmdBuffer);
1241		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1242				(VkDependencyFlags)0,
1243				0, (const VkMemoryBarrier*)DE_NULL,
1244				0, (const VkBufferMemoryBarrier*)DE_NULL,
1245				1, &barrier);
1246
1247		endCommandBuffer(vk, *transferCmdBuffer);
1248
1249		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
1250		m_context.resetCommandPoolForVKSC(device, *cmdPool);
1251	}
1252
1253	// Perform draw
1254	{
1255		std::vector<Vec4>				vertices;
1256		std::vector<VulkanShader>		shaders;
1257
1258		vertices.push_back(Vec4( -1.0f,	-1.0f,	0.0f,	1.0f));
1259		vertices.push_back(Vec4( -1.0f,	 1.0f,	0.0f,	1.0f));
1260		vertices.push_back(Vec4(  1.0f,	-1.0f,	0.0f,	1.0f));
1261		vertices.push_back(Vec4(  1.0f,	 1.0f,	0.0f,	1.0f));
1262
1263		shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragCoordMsaaVert")));
1264		shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragCoordMsaaFrag")));
1265
1266		FrameBufferState			frameBufferState(m_renderSize.x(), m_renderSize.y());
1267		PipelineState				pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1268		DrawCallData				drawCallData(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, vertices);
1269		VulkanProgram				vulkanProgram(shaders);
1270
1271		frameBufferState.numSamples				= m_sampleCount;
1272		pipelineState.sampleShadingEnable		= m_useEnable; // When m_useEnable is false, we rely on the gl_SampleID input to enable sample shading
1273		pipelineState.sampleMasks				= m_sampleMaskArray;
1274		vulkanProgram.descriptorSetLayout		= *descriptorSetLayout;
1275		vulkanProgram.descriptorSet				= *descriptorSet;
1276
1277		VulkanDrawContext			vulkanDrawContext(m_context, frameBufferState);
1278		vulkanDrawContext.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
1279		vulkanDrawContext.draw();
1280
1281		log << TestLog::Image(	"result",
1282								"result",
1283								tcu::ConstPixelBufferAccess(tcu::TextureFormat(
1284										vulkanDrawContext.getColorPixels().getFormat()),
1285										vulkanDrawContext.getColorPixels().getWidth(),
1286										vulkanDrawContext.getColorPixels().getHeight(),
1287										1,
1288										vulkanDrawContext.getColorPixels().getDataPtr()));
1289	}
1290
1291	// Transfer location image to buffer
1292	{
1293		beginCommandBuffer(vk, *transferCmdBuffer);
1294		copyImageToBuffer(vk, *transferCmdBuffer, *outputImage, *sampleLocationBuffer, tcu::IVec2(m_renderSize.x() * m_sampleCount, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
1295		endCommandBuffer(vk, *transferCmdBuffer);
1296
1297		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
1298		m_context.resetCommandPoolForVKSC(device, *cmdPool);
1299
1300		invalidateAlloc(vk, device, *sampleLocationBufferAllocation);
1301	}
1302
1303	// Validate result
1304	{
1305		bool status;
1306
1307		ConstPixelBufferAccess sampleLocationPixelBuffer(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT), m_sampleCount * m_renderSize.x(),
1308				m_renderSize.y(), 1u, sampleLocationBufferAllocation->getHostPtr());
1309
1310		status = validateSampleLocations(sampleLocationPixelBuffer);
1311		if (status)
1312			return TestStatus::pass("FragCoordMsaa passed");
1313		else
1314			return TestStatus::fail("FragCoordMsaa failed");
1315	}
1316}
1317
1318static bool pixelOffsetCompare (const Vec2& a, const Vec2& b)
1319{
1320	return a.x() < b.x();
1321}
1322
1323bool BuiltinFragCoordMsaaCaseInstance::validateSampleLocations (const ConstPixelBufferAccess& sampleLocationBuffer) const
1324{
1325	const InstanceInterface&	vki					= m_context.getInstanceInterface();
1326	TestLog&					log					= m_context.getTestContext().getLog();
1327	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();
1328	deUint32					logSampleCount		= deLog2Floor32(m_sampleCount);
1329	VkPhysicalDeviceProperties	physicalDeviceProperties;
1330
1331	static const Vec2 sampleCount1Bit[] =
1332	{
1333		Vec2(0.5f, 0.5f)
1334	};
1335
1336	static const Vec2 sampleCount2Bit[] =
1337	{
1338		Vec2(0.25f, 0.25f), Vec2(0.75f, 0.75f)
1339	};
1340
1341	static const Vec2 sampleCount4Bit[] =
1342	{
1343		Vec2(0.375f, 0.125f), Vec2(0.875f, 0.375f), Vec2(0.125f, 0.625f), Vec2(0.625f, 0.875f)
1344	};
1345
1346	static const Vec2 sampleCount8Bit[] =
1347	{
1348		Vec2(0.5625f, 0.3125f), Vec2(0.4375f, 0.6875f), Vec2(0.8125f,0.5625f), Vec2(0.3125f, 0.1875f),
1349		Vec2(0.1875f, 0.8125f), Vec2(0.0625f, 0.4375f), Vec2(0.6875f,0.9375f), Vec2(0.9375f, 0.0625f)
1350	};
1351
1352	static const Vec2 sampleCount16Bit[] =
1353	{
1354		Vec2(0.5625f, 0.5625f), Vec2(0.4375f, 0.3125f), Vec2(0.3125f,0.6250f), Vec2(0.7500f, 0.4375f),
1355		Vec2(0.1875f, 0.3750f), Vec2(0.6250f, 0.8125f), Vec2(0.8125f,0.6875f), Vec2(0.6875f, 0.1875f),
1356		Vec2(0.3750f, 0.8750f), Vec2(0.5000f, 0.0625f), Vec2(0.2500f,0.1250f), Vec2(0.1250f, 0.7500f),
1357		Vec2(0.0000f, 0.5000f), Vec2(0.9375f, 0.2500f), Vec2(0.8750f,0.9375f), Vec2(0.0625f, 0.0000f)
1358	};
1359
1360	static const Vec2* standardSampleLocationTable[] =
1361	{
1362		sampleCount1Bit,
1363		sampleCount2Bit,
1364		sampleCount4Bit,
1365		sampleCount8Bit,
1366		sampleCount16Bit
1367	};
1368
1369	vki.getPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
1370
1371	for (deInt32 rowNdx = 0; rowNdx < (deInt32)m_renderSize.y(); rowNdx++)
1372	{
1373		for (deInt32 colNdx = 0; colNdx < (deInt32)m_renderSize.x(); colNdx++)
1374		{
1375			// Check standard sample locations
1376			if (m_sampleShading == true)
1377			{
1378				std::vector<Vec2> locations;
1379
1380				for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)m_sampleCount; sampleNdx++)
1381				{
1382					const UVec2 pixelAddress	= UVec2(sampleNdx + m_sampleCount * colNdx, rowNdx);
1383					const Vec4  pixelData		= sampleLocationBuffer.getPixel(pixelAddress.x(), pixelAddress.y());
1384
1385					if (pixelData.z() != 0.0f)
1386					{
1387						log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx << "): has unexpected .z component, expected: 0.0, got: " << pixelData.z() << TestLog::EndMessage;
1388						return false;
1389					}
1390
1391					if (pixelData.w() != 1.0f)
1392					{
1393						log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx << "): has unexpected .w component, expected: 1.0, got: " << pixelData.w() << TestLog::EndMessage;
1394						return false;
1395					}
1396
1397					locations.push_back(Vec2(pixelData.x(), pixelData.y()));
1398				}
1399				std::sort(locations.begin(), locations.end(), pixelOffsetCompare);
1400				for (std::vector<Vec2>::const_iterator sampleIt = locations.begin(); sampleIt != locations.end(); sampleIt++)
1401				{
1402					IVec2	sampleFloor(deFloorFloatToInt32((*sampleIt).x()), deFloorFloatToInt32((*sampleIt).y()));
1403					IVec2	sampleCeil(deCeilFloatToInt32((*sampleIt).x()), deCeilFloatToInt32((*sampleIt).y()));
1404
1405					if ((sampleFloor.x() < colNdx) || (sampleCeil.x() > colNdx + 1) || (sampleFloor.y() < rowNdx) || (sampleCeil.y() > rowNdx + 1))
1406					{
1407						log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx << "): " << *sampleIt << TestLog::EndMessage;
1408						return false;
1409					}
1410				}
1411
1412				std::vector<Vec2>::iterator last = std::unique(locations.begin(), locations.end());
1413				if (last != locations.end())
1414				{
1415					log << TestLog::Message << "Fail: Sample locations contains non-unique entry" << TestLog::EndMessage;
1416					return false;
1417				}
1418
1419				if (logSampleCount < DE_LENGTH_OF_ARRAY(standardSampleLocationTable))
1420				{
1421					if (physicalDeviceProperties.limits.standardSampleLocations)
1422					{
1423						for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)m_sampleCount; sampleNdx++)
1424						{
1425							if (!de::contains(locations.begin(), locations.end(), standardSampleLocationTable[logSampleCount][sampleNdx] + Vec2(float(colNdx), float(rowNdx))))
1426							{
1427								log << TestLog::Message << "Didn't match sample locations " << standardSampleLocationTable[logSampleCount][sampleNdx] << TestLog::EndMessage;
1428								return false;
1429							}
1430						}
1431					}
1432				}
1433			}
1434			else
1435			{
1436				// Check the sample location is at the pixel center when sample shading is disabled.
1437				const Vec4 pixelData = sampleLocationBuffer.getPixel(colNdx, rowNdx);
1438
1439				if (pixelData.z() != 0.0f)
1440				{
1441					log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx << "): has unexpected .z component, expected: 0.0, got: " << pixelData.z() << TestLog::EndMessage;
1442					return false;
1443				}
1444
1445				if (pixelData.w() != 1.0f)
1446				{
1447					log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx << "): has unexpected .w component, expected: 1.0, got: " << pixelData.w() << TestLog::EndMessage;
1448					return false;
1449				}
1450
1451				if (!(deFloatFrac(pixelData.x()) == 0.5f && deFloatFrac(pixelData.y()) == 0.5f))
1452				{
1453					log << TestLog::Message << "Didn't match sample locations (" << pixelData.x() << ", " << pixelData.y() << "): " << Vec2(float(colNdx) + 0.5f, float(rowNdx) + 0.5f) << TestLog::EndMessage;
1454					return false;
1455				}
1456			}
1457		}
1458	}
1459
1460	return true;
1461}
1462
1463class BuiltinFragCoordMsaaTestCase : public TestCase
1464{
1465public:
1466					BuiltinFragCoordMsaaTestCase	(TestContext& testCtx, const char* name, VkSampleCountFlagBits sampleCount, bool sampleShading, std::vector<uint32_t> sampleMaskArray, bool useCentroid, bool useEnable);
1467	virtual			~BuiltinFragCoordMsaaTestCase	(void);
1468	void			initPrograms					(SourceCollections& sourceCollections) const;
1469	TestInstance*	createInstance					(Context& context) const;
1470private:
1471	const VkSampleCountFlagBits		m_sampleCount;
1472	const bool						m_sampleShading;	// Enable or disable Sample Shading.
1473	const std::vector<uint32_t>		m_sampleMaskArray;
1474	const bool						m_useCentroid;		// Use Centroid interpolation decoration.
1475	const bool						m_useEnable;
1476};
1477
1478BuiltinFragCoordMsaaTestCase::BuiltinFragCoordMsaaTestCase (TestContext& testCtx, const char* name, VkSampleCountFlagBits sampleCount, bool sampleShading, std::vector<uint32_t> sampleMaskArray, bool useCentroid, bool useEnable)
1479	: TestCase			(testCtx, name)
1480	, m_sampleCount		(sampleCount)
1481	, m_sampleShading	(sampleShading)
1482	, m_sampleMaskArray	(sampleMaskArray)
1483	, m_useCentroid		(useCentroid)
1484	, m_useEnable		(useEnable)
1485{
1486}
1487
1488BuiltinFragCoordMsaaTestCase::~BuiltinFragCoordMsaaTestCase (void)
1489{
1490}
1491
1492void BuiltinFragCoordMsaaTestCase::initPrograms (SourceCollections& programCollection) const
1493{
1494	{
1495		std::ostringstream vertexSource;
1496		vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1497			<< "\n"
1498			<< "layout (location = 0) in vec4 position;\n"
1499			<< "void main()\n"
1500			<< "{\n"
1501			<< "	gl_Position = position;\n"
1502			<< "}\n";
1503		programCollection.glslSources.add("FragCoordMsaaVert") << glu::VertexSource(vertexSource.str());
1504	}
1505
1506	if(m_sampleShading == true)
1507	{
1508		std::ostringstream fragmentSource;
1509		fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1510			<< "\n"
1511			<< "layout(location = 0) out mediump vec4 color;\n"
1512			<< "layout (set = 0, binding = 0, rgba32f) writeonly uniform image2D storageImage;\n"
1513			<< "void main()\n"
1514			<< "{\n"
1515			<< "	const int sampleNdx = int(gl_SampleID);\n"
1516			<< "	ivec2 imageCoord = ivec2(sampleNdx + int(gl_FragCoord.x) * " << m_sampleCount << ", int(gl_FragCoord.y));\n"
1517			<< "	imageStore(storageImage, imageCoord, gl_FragCoord);\n"
1518			<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1519			<< "}\n";
1520		programCollection.glslSources.add("FragCoordMsaaFrag") << glu::FragmentSource(fragmentSource.str());
1521	}
1522	else
1523	{
1524		if (m_useCentroid == false)
1525		{
1526			std::ostringstream src;
1527
1528			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1529				<< "\n"
1530				<< "layout (location = 0) out mediump vec4 color;\n"
1531				<< "layout (set = 0, binding = 0, rgba32f) writeonly uniform image2D storageImage;\n"
1532				<< "void main()\n"
1533				<< "{\n"
1534				<< "	ivec2 imageCoord = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y));\n"
1535				<< "	imageStore(storageImage, imageCoord, gl_FragCoord);\n"
1536				<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1537				<< "}\n";
1538
1539			programCollection.glslSources.add("FragCoordMsaaFrag") << glu::FragmentSource(src.str());
1540		}
1541		else
1542		{
1543			// This SPIR-V shader is identical to GLSL shader above but with the exception of that added cendroid decoration line.
1544			std::ostringstream src;
1545			src << "; SPIR - V\n"
1546				<< "; Version: 1.0\n"
1547				<< "; Generator: Khronos Glslang Reference Front End; 10\n"
1548				<< "; Bound: 36\n"
1549				<< "; Schema: 0\n"
1550				<< "OpCapability Shader\n"
1551				<< "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1552				<< "OpMemoryModel Logical GLSL450\n"
1553				<< "OpEntryPoint Fragment %main \"main\" %gl_FragCoord %color\n"
1554				<< "OpExecutionMode %main OriginUpperLeft\n"
1555				<< "OpSource GLSL 450\n"
1556				<< "OpName %main \"main\"\n"
1557				<< "OpName %imageCoord \"imageCoord\"\n"
1558				<< "OpName %gl_FragCoord \"gl_FragCoord\"\n"
1559				<< "OpName %storageImage \"storageImage\"\n"
1560				<< "OpName %color \"color\"\n"
1561				<< "OpDecorate %gl_FragCoord BuiltIn FragCoord\n"
1562				<< "OpDecorate %gl_FragCoord Centroid\n"
1563				<< "OpDecorate %storageImage DescriptorSet 0\n"
1564				<< "OpDecorate %storageImage Binding 0\n"
1565				<< "OpDecorate %storageImage NonReadable\n"
1566				<< "OpDecorate %color RelaxedPrecision\n"
1567				<< "OpDecorate %color Location 0\n"
1568				<< "%void = OpTypeVoid\n"
1569				<< "%3 = OpTypeFunction %void\n"
1570				<< "%int = OpTypeInt 32 1\n"
1571				<< "%v2int = OpTypeVector %int 2\n"
1572				<< "%_ptr_Function_v2int = OpTypePointer Function %v2int\n"
1573				<< "%float = OpTypeFloat 32\n"
1574				<< "%v4float = OpTypeVector %float 4\n"
1575				<< "%_ptr_Input_v4float = OpTypePointer Input %v4float\n"
1576				<< "%gl_FragCoord = OpVariable %_ptr_Input_v4float Input\n"
1577				<< "%uint = OpTypeInt 32 0\n"
1578				<< "%uint_0 = OpConstant %uint 0\n"
1579				<< "%_ptr_Input_float = OpTypePointer Input %float\n"
1580				<< "%uint_1 = OpConstant %uint 1\n"
1581				<< "%25 = OpTypeImage %float 2D 0 0 0 2 Rgba32f\n"
1582				<< "%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25\n"
1583				<< "%storageImage = OpVariable %_ptr_UniformConstant_25 UniformConstant\n"
1584				<< "%_ptr_Output_v4float = OpTypePointer Output %v4float\n"
1585				<< "%color = OpVariable %_ptr_Output_v4float Output\n"
1586				<< "%float_1 = OpConstant %float 1\n"
1587				<< "%float_0 = OpConstant %float 0\n"
1588				<< "%35 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1\n"
1589				<< "%main = OpFunction %void None %3\n"
1590				<< "%5 = OpLabel\n"
1591				<< "%imageCoord = OpVariable %_ptr_Function_v2int Function\n"
1592				<< "%17 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_0\n"
1593				<< "%18 = OpLoad %float %17\n"
1594				<< "%19 = OpConvertFToS %int %18\n"
1595				<< "%21 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_1\n"
1596				<< "%22 = OpLoad %float %21\n"
1597				<< "%23 = OpConvertFToS %int %22\n"
1598				<< "%24 = OpCompositeConstruct %v2int %19 %23\n"
1599				<< "OpStore %imageCoord %24\n"
1600				<< "%28 = OpLoad %25 %storageImage\n"
1601				<< "%29 = OpLoad %v2int %imageCoord\n"
1602				<< "%30 = OpLoad %v4float %gl_FragCoord\n"
1603				<< "OpImageWrite %28 %29 %30\n"
1604				<< "OpStore %color %35\n"
1605				<< "OpReturn\n"
1606				<< "OpFunctionEnd\n";
1607
1608			programCollection.spirvAsmSources.add("FragCoordMsaaFrag") << src.str();
1609		}
1610	}
1611}
1612
1613TestInstance* BuiltinFragCoordMsaaTestCase::createInstance (Context& context) const
1614{
1615	return new BuiltinFragCoordMsaaCaseInstance(context, m_sampleCount, m_sampleShading, m_sampleMaskArray, m_useEnable);
1616}
1617
1618class BuiltinFragDepthCase : public TestCase
1619{
1620public:
1621					BuiltinFragDepthCase		(TestContext& testCtx, const char* name, VkPrimitiveTopology topology,  VkFormat format, bool largeDepthEnable, bool depthClampEnable, const VkSampleCountFlagBits samples);
1622	virtual			~BuiltinFragDepthCase		(void);
1623
1624	void			initPrograms				(SourceCollections& dst) const;
1625	TestInstance*	createInstance				(Context& context) const;
1626
1627private:
1628	const VkPrimitiveTopology		m_topology;
1629	const VkFormat					m_format;
1630	const bool						m_largeDepthEnable;
1631	const float						m_defaultDepth;
1632	const bool						m_depthClampEnable;
1633	const VkSampleCountFlagBits		m_samples;
1634};
1635
1636BuiltinFragDepthCase::BuiltinFragDepthCase (TestContext& testCtx, const char* name, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable, bool depthClampEnable, const VkSampleCountFlagBits  samples)
1637	: TestCase				(testCtx, name)
1638	, m_topology			(topology)
1639	, m_format				(format)
1640	, m_largeDepthEnable	(largeDepthEnable)
1641	, m_defaultDepth		(0.0f)
1642	, m_depthClampEnable	(depthClampEnable)
1643	, m_samples				(samples)
1644{
1645}
1646
1647BuiltinFragDepthCase::~BuiltinFragDepthCase(void)
1648{
1649}
1650
1651void BuiltinFragDepthCase::initPrograms (SourceCollections& programCollection) const
1652{
1653	// Vertex
1654	{
1655		// Pass 1
1656		{
1657			std::ostringstream vertexSource;
1658			vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1659				<< "\n"
1660				<<  "layout (location = 0) in vec4 position;\n"
1661				<< "void main()\n"
1662				<< "{\n"
1663				<< "	gl_Position = position;\n"
1664				<< "	gl_PointSize = 1.0;\n"
1665				<< "}\n";
1666			programCollection.glslSources.add("FragDepthVert") << glu::VertexSource(vertexSource.str());
1667		}
1668
1669		// Pass 2
1670		{
1671			std::ostringstream vertexSource;
1672			vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1673				<< "\n"
1674				<<  "layout (location = 0) in vec4 position;\n"
1675				<<  "layout (location = 1) out vec2 texCoord;\n"
1676				<< "void main()\n"
1677				<< "{\n"
1678				<< "	gl_Position = position;\n"
1679				<< "	gl_PointSize = 1.0;\n"
1680				<< "	texCoord = position.xy/2 + vec2(0.5);\n"
1681				<< "}\n";
1682			programCollection.glslSources.add("FragDepthVertPass2") << glu::VertexSource(vertexSource.str());
1683		}
1684	}
1685
1686	// Fragment
1687	{
1688		// Pass 1
1689		{
1690			std::ostringstream	fragmentSource;
1691			fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1692				<< "\n"
1693				<< "layout(location = 0) out mediump vec4 color;\n"
1694				<< "layout (std140, set = 0, binding = 0) uniform control_buffer_t\n"
1695				<< "{\n"
1696				<< "	float data[256];\n"
1697				<< "} control_buffer;\n"
1698				<< "layout (set = 0, binding = 1, rgba8ui) writeonly uniform uimage2D storageImage;\n"
1699				<< "float controlDepthValue;\n"
1700				<< "void recheck(float controlDepthValue)\n"
1701				<< "{\n"
1702				<< "	if (gl_FragDepth != controlDepthValue)\n"
1703				<< "		gl_FragDepth = 1.0;\n"
1704				<< "}\n"
1705				<< "void main()\n"
1706				<< "{\n"
1707				<< "	const int numSamples = " << m_samples << ";\n"
1708				<< "	if (int(gl_FragCoord.x) == " << BuiltinFragDepthCaseInstance::RENDERWIDTH/4 << ")\n"
1709				<< "		discard;\n"
1710				<< "	highp int index =int(gl_FragCoord.y) * " << BuiltinFragDepthCaseInstance::RENDERHEIGHT << " + int(gl_FragCoord.x);\n"
1711				<< "	controlDepthValue = control_buffer.data[index];\n"
1712				<< "	gl_FragDepth = controlDepthValue;\n"
1713				<< "	const int sampleNdx = int(gl_SampleID);\n"
1714				<< "	ivec2 imageCoord = ivec2(sampleNdx + int(gl_FragCoord.x) * " << m_samples << ", int(gl_FragCoord.y));\n"
1715				<< "	imageStore(storageImage, imageCoord, uvec4(1));\n"
1716				<< "	recheck(controlDepthValue);\n"
1717				<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1718				<< "}\n";
1719			programCollection.glslSources.add("FragDepthFrag") << glu::FragmentSource(fragmentSource.str());
1720		}
1721
1722		// Pass 2
1723		{
1724			const char* multisampleDecoration = m_samples != VK_SAMPLE_COUNT_1_BIT ? "MS" : "";
1725			std::ostringstream fragmentSource;
1726			fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1727				<< "\n"
1728				<< "layout (location = 0) out mediump vec4 color;\n"
1729				<< "layout (location = 1) in vec2 texCoord;\n"
1730				<< "layout (binding = 0, set = 0) uniform sampler2D" << multisampleDecoration << " u_depthTex;\n"
1731				<< "layout (binding = 1, set = 0, r32f) writeonly uniform image2D u_outImage;\n"
1732				<< "void main (void)\n"
1733				<< "{\n"
1734				<< "	const int numSamples = " << m_samples << ";\n"
1735				<< "	const int sampleNdx = int(gl_SampleID);\n"
1736				<< "	ivec2 renderSize = ivec2(" << BuiltinFragDepthCaseInstance::RENDERWIDTH << "," << BuiltinFragDepthCaseInstance::RENDERHEIGHT << ");\n"
1737				<< "	ivec2 imageCoord = ivec2(int(texCoord.x * renderSize.x), int(texCoord.y * renderSize.y));\n"
1738				<< "	vec4 depthVal = texelFetch(u_depthTex, imageCoord, sampleNdx);\n"
1739				<< "	imageStore(u_outImage, ivec2(sampleNdx + int(texCoord.x * renderSize.x) * numSamples, int(texCoord.y * renderSize.y)), depthVal);\n"
1740				<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1741				<< "}\n";
1742			programCollection.glslSources.add("FragDepthFragPass2") << glu::FragmentSource(fragmentSource.str());
1743		}
1744	}
1745}
1746
1747TestInstance* BuiltinFragDepthCase::createInstance (Context& context) const
1748{
1749	return new BuiltinFragDepthCaseInstance(context, m_topology, m_format, m_largeDepthEnable, m_defaultDepth, m_depthClampEnable, m_samples);
1750}
1751
1752class BuiltinGlFragCoordXYZCaseInstance : public ShaderRenderCaseInstance
1753{
1754public:
1755					BuiltinGlFragCoordXYZCaseInstance	(Context& context);
1756
1757	TestStatus		iterate								(void);
1758	virtual void	setupDefaultInputs					(void);
1759};
1760
1761BuiltinGlFragCoordXYZCaseInstance::BuiltinGlFragCoordXYZCaseInstance (Context& context)
1762	: ShaderRenderCaseInstance	(context)
1763{
1764	m_colorFormat = VK_FORMAT_R16G16B16A16_UNORM;
1765}
1766
1767TestStatus BuiltinGlFragCoordXYZCaseInstance::iterate (void)
1768{
1769	const UVec2		viewportSize	= getViewportSize();
1770	const int		width			= viewportSize.x();
1771	const int		height			= viewportSize.y();
1772	const tcu::Vec3	scale			(1.0f / float(width), 1.0f / float(height), 1.0f);
1773	const float		precision		= 0.00001f;
1774	const deUint16	indices[6]		=
1775	{
1776		2, 1, 3,
1777		0, 1, 2,
1778	};
1779
1780	setup();
1781	addUniform(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, scale);
1782
1783	render(4, 2, indices);
1784
1785	// Reference image
1786	for (int y = 0; y < height; y++)
1787	{
1788		for (int x = 0; x < width; x++)
1789		{
1790			const float	xf			= (float(x) + .5f) / float(width);
1791			const float	yf			= (float(height - y - 1) + .5f) / float(height);
1792			const float	z			= (xf + yf) / 2.0f;
1793			const Vec3	fragCoord	(float(x) + .5f, float(y) + .5f, z);
1794			const Vec3	scaledFC	= fragCoord*scale;
1795			const Vec4	color		(scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);
1796			const Vec4	resultColor	= getResultImage().getAccess().getPixel(x, y);
1797
1798			if (de::abs(color.x() - resultColor.x()) > precision ||
1799				de::abs(color.y() - resultColor.y()) > precision ||
1800				de::abs(color.z() - resultColor.z()) > precision)
1801			return TestStatus::fail("Image mismatch");
1802		}
1803	}
1804
1805	return TestStatus::pass("Result image matches reference");
1806}
1807
1808void BuiltinGlFragCoordXYZCaseInstance::setupDefaultInputs (void)
1809{
1810	const float		vertices[]		=
1811	{
1812		-1.0f,  1.0f,  0.0f, 1.0f,
1813		-1.0f, -1.0f,  0.5f, 1.0f,
1814		 1.0f,  1.0f,  0.5f, 1.0f,
1815		 1.0f, -1.0f,  1.0f, 1.0f,
1816	};
1817
1818	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
1819}
1820
1821class BuiltinGlFragCoordXYZCase : public TestCase
1822{
1823public:
1824								BuiltinGlFragCoordXYZCase	(TestContext& testCtx, const string& name);
1825	virtual						~BuiltinGlFragCoordXYZCase	(void);
1826
1827	void						initPrograms				(SourceCollections& dst) const;
1828	TestInstance*				createInstance				(Context& context) const;
1829
1830private:
1831								BuiltinGlFragCoordXYZCase	(const BuiltinGlFragCoordXYZCase&);	// not allowed!
1832	BuiltinGlFragCoordXYZCase&	operator=					(const BuiltinGlFragCoordXYZCase&);	// not allowed!
1833};
1834
1835BuiltinGlFragCoordXYZCase::BuiltinGlFragCoordXYZCase (TestContext& testCtx, const string& name)
1836	: TestCase(testCtx, name)
1837{
1838}
1839
1840BuiltinGlFragCoordXYZCase::~BuiltinGlFragCoordXYZCase (void)
1841{
1842}
1843
1844void BuiltinGlFragCoordXYZCase::initPrograms (SourceCollections& dst) const
1845{
1846	dst.glslSources.add("vert") << glu::VertexSource(
1847		"#version 310 es\n"
1848		"layout(location = 0) in highp vec4 a_position;\n"
1849		"void main (void)\n"
1850		"{\n"
1851		"       gl_Position = a_position;\n"
1852		"}\n");
1853
1854	dst.glslSources.add("frag") << glu::FragmentSource(
1855		"#version 310 es\n"
1856		"layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
1857		"layout(location = 0) out highp vec4 o_color;\n"
1858		"void main (void)\n"
1859		"{\n"
1860		"       o_color = vec4(gl_FragCoord.xyz * u_scale, 1.0);\n"
1861		"}\n");
1862}
1863
1864TestInstance* BuiltinGlFragCoordXYZCase::createInstance (Context& context) const
1865{
1866	return new BuiltinGlFragCoordXYZCaseInstance(context);
1867}
1868
1869inline float projectedTriInterpolate (const Vec3& s, const Vec3& w, float nx, float ny)
1870{
1871	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]);
1872}
1873
1874class BuiltinGlFragCoordWCaseInstance : public ShaderRenderCaseInstance
1875{
1876public:
1877					BuiltinGlFragCoordWCaseInstance	(Context& context);
1878
1879	TestStatus		iterate							(void);
1880	virtual void	setupDefaultInputs				(void);
1881
1882private:
1883
1884	const Vec4		m_w;
1885
1886};
1887
1888BuiltinGlFragCoordWCaseInstance::BuiltinGlFragCoordWCaseInstance (Context& context)
1889	: ShaderRenderCaseInstance	(context)
1890	, m_w						(1.7f, 2.0f, 1.2f, 1.0f)
1891{
1892	m_colorFormat = VK_FORMAT_R16G16B16A16_UNORM;
1893}
1894
1895TestStatus BuiltinGlFragCoordWCaseInstance::iterate (void)
1896{
1897	const UVec2		viewportSize	= getViewportSize();
1898	const int		width			= viewportSize.x();
1899	const int		height			= viewportSize.y();
1900	const float		precision		= 0.00001f;
1901	const deUint16	indices[6]		=
1902	{
1903		2, 1, 3,
1904		0, 1, 2,
1905	};
1906
1907	setup();
1908	render(4, 2, indices);
1909
1910	// Reference image
1911	for (int y = 0; y < height; y++)
1912	{
1913		for (int x = 0; x < width; x++)
1914		{
1915			const float	xf			= (float(x) + .5f) / float(width);
1916			const float	yf			= (float(height - y - 1) +.5f) / float(height);
1917			const float	oow			= ((xf + yf) < 1.0f)
1918										? projectedTriInterpolate(Vec3(m_w[0], m_w[1], m_w[2]), Vec3(m_w[0], m_w[1], m_w[2]), xf, yf)
1919										: 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);
1920			const Vec4	color		(0.0f, oow - 1.0f, 0.0f, 1.0f);
1921			const Vec4	resultColor	= getResultImage().getAccess().getPixel(x, y);
1922
1923			if (de::abs(color.x() - resultColor.x()) > precision ||
1924				de::abs(color.y() - resultColor.y()) > precision ||
1925				de::abs(color.z() - resultColor.z()) > precision)
1926			return TestStatus::fail("Image mismatch");
1927		}
1928	}
1929
1930	return TestStatus::pass("Result image matches reference");
1931}
1932
1933void BuiltinGlFragCoordWCaseInstance::setupDefaultInputs (void)
1934{
1935	const float vertices[] =
1936	{
1937		-m_w[0],  m_w[0], 0.0f, m_w[0],
1938		-m_w[1], -m_w[1], 0.0f, m_w[1],
1939		 m_w[2],  m_w[2], 0.0f, m_w[2],
1940		 m_w[3], -m_w[3], 0.0f, m_w[3]
1941	};
1942
1943	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
1944}
1945
1946class BuiltinGlFragCoordWCase : public TestCase
1947{
1948public:
1949								BuiltinGlFragCoordWCase		(TestContext& testCtx, const string& name);
1950	virtual						~BuiltinGlFragCoordWCase	(void);
1951
1952	void						initPrograms				(SourceCollections& dst) const;
1953	TestInstance*				createInstance				(Context& context) const;
1954
1955private:
1956								BuiltinGlFragCoordWCase		(const BuiltinGlFragCoordWCase&);	// not allowed!
1957	BuiltinGlFragCoordWCase&	operator=					(const BuiltinGlFragCoordWCase&);	// not allowed!
1958};
1959
1960BuiltinGlFragCoordWCase::BuiltinGlFragCoordWCase (TestContext& testCtx, const string& name)
1961	: TestCase(testCtx, name)
1962{
1963}
1964
1965BuiltinGlFragCoordWCase::~BuiltinGlFragCoordWCase (void)
1966{
1967}
1968
1969void BuiltinGlFragCoordWCase::initPrograms (SourceCollections& dst) const
1970{
1971	dst.glslSources.add("vert") << glu::VertexSource(
1972		"#version 310 es\n"
1973		"layout(location = 0) in highp vec4 a_position;\n"
1974		"void main (void)\n"
1975		"{\n"
1976		"       gl_Position = a_position;\n"
1977		"}\n");
1978
1979	dst.glslSources.add("frag") << glu::FragmentSource(
1980		"#version 310 es\n"
1981		"layout(location = 0) out highp vec4 o_color;\n"
1982		"void main (void)\n"
1983		"{\n"
1984		"       o_color = vec4(0.0, 1.0 / gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
1985		"}\n");
1986}
1987
1988TestInstance* BuiltinGlFragCoordWCase::createInstance (Context& context) const
1989{
1990	return new BuiltinGlFragCoordWCaseInstance(context);
1991}
1992
1993enum
1994{
1995	POINTCOORD_VARIANT_DEFAULT,
1996	POINTCOORD_VARIANT_UNIFORM_VERTEX,
1997	POINTCOORD_VARIANT_UNIFORM_FRAGMENT
1998};
1999
2000
2001class BuiltinGlPointCoordCaseInstance : public ShaderRenderCaseInstance
2002{
2003public:
2004					BuiltinGlPointCoordCaseInstance	(Context& context, int testVariant);
2005
2006	TestStatus		iterate								(void);
2007	virtual void	setupDefaultInputs					(void);
2008private:
2009	int				variant;
2010};
2011
2012BuiltinGlPointCoordCaseInstance::BuiltinGlPointCoordCaseInstance (Context& context, int testVariant)
2013	: ShaderRenderCaseInstance	(context),
2014	  variant(testVariant)
2015{
2016}
2017
2018TestStatus BuiltinGlPointCoordCaseInstance::iterate (void)
2019{
2020	const UVec2				viewportSize	= getViewportSize();
2021	const int				width			= viewportSize.x();
2022	const int				height			= viewportSize.y();
2023	const float				threshold		= 0.02f;
2024	const int				numPoints		= 16;
2025	vector<Vec3>			coords			(numPoints);
2026	de::Random				rnd				(0x145fa);
2027	Surface					resImage		(width, height);
2028	Surface					refImage		(width, height);
2029	bool					compareOk		= false;
2030	const tcu::Vec3			scale(1.0f / float(width), 1.0f / float(height), 1.0f);
2031
2032	// Compute coordinates.
2033	{
2034		const VkPhysicalDeviceLimits&	limits					= m_context.getDeviceProperties().limits;
2035		const float						minPointSize			= limits.pointSizeRange[0];
2036		const float						maxPointSize			= limits.pointSizeRange[1];
2037		const int						pointSizeDeltaMultiples	= de::max(1, deCeilFloatToInt32((maxPointSize - minPointSize) / limits.pointSizeGranularity));
2038
2039		TCU_CHECK(minPointSize <= maxPointSize);
2040
2041		for (vector<Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
2042		{
2043			coord->x() = rnd.getFloat(-0.9f, 0.9f);
2044			coord->y() = rnd.getFloat(-0.9f, 0.9f);
2045			coord->z() = de::min(maxPointSize, minPointSize + float(rnd.getInt(0, pointSizeDeltaMultiples)) * limits.pointSizeGranularity);
2046		}
2047	}
2048
2049	setup();
2050
2051	if (variant == POINTCOORD_VARIANT_UNIFORM_VERTEX || variant == POINTCOORD_VARIANT_UNIFORM_FRAGMENT)
2052		addUniform(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, scale);
2053
2054	addAttribute(0u, VK_FORMAT_R32G32B32_SFLOAT, deUint32(sizeof(Vec3)), numPoints, &coords[0]);
2055	render(numPoints, 0, DE_NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
2056	copy(resImage.getAccess(), getResultImage().getAccess());
2057
2058	// Draw reference
2059	clear(refImage.getAccess(), m_clearColor);
2060
2061	for (vector<Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
2062	{
2063		float x = pointIter->x();
2064		float y = pointIter->y();
2065		if (variant == POINTCOORD_VARIANT_UNIFORM_VERTEX)
2066		{
2067			x *= scale.m_data[0];
2068			y *= scale.m_data[1];
2069		}
2070		const float	centerX	= float(width) *(x*0.5f + 0.5f);
2071		const float	centerY	= float(height)*(y*0.5f + 0.5f);
2072		const float	size	= pointIter->z();
2073		const int	x0		= deRoundFloatToInt32(centerX - size*0.5f);
2074		const int	y0		= deRoundFloatToInt32(centerY - size*0.5f);
2075		const int	x1		= deRoundFloatToInt32(centerX + size*0.5f);
2076		const int	y1		= deRoundFloatToInt32(centerY + size*0.5f);
2077		const int	w		= x1-x0;
2078		const int	h		= y1-y0;
2079
2080		for (int yo = 0; yo < h; yo++)
2081		{
2082			for (int xo = 0; xo < w; xo++)
2083			{
2084				const int		dx		= x0+xo;
2085				const int		dy		= y0+yo;
2086				const float		fragX	= float(dx) + 0.5f;
2087				const float		fragY	= float(dy) + 0.5f;
2088				const float		s		= 0.5f + (fragX - centerX) / size;
2089				const float		t		= 0.5f + (fragY - centerY) / size;
2090				Vec4			color	(s, t, 0.0f, 1.0f);
2091
2092				if (variant == POINTCOORD_VARIANT_UNIFORM_FRAGMENT)
2093				{
2094					color.m_data[0] *= scale.m_data[0];
2095					color.m_data[1] *= scale.m_data[1];
2096					color.m_data[2] *= scale.m_data[2];
2097				}
2098
2099				if (de::inBounds(dx, 0, refImage.getWidth()) && de::inBounds(dy, 0, refImage.getHeight()))
2100					refImage.setPixel(dx, dy, RGBA(color));
2101			}
2102		}
2103	}
2104
2105	compareOk = fuzzyCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
2106
2107	if (compareOk)
2108		return TestStatus::pass("Result image matches reference");
2109	else
2110		return TestStatus::fail("Image mismatch");
2111}
2112
2113void BuiltinGlPointCoordCaseInstance::setupDefaultInputs (void)
2114{
2115}
2116
2117class BuiltinGlPointCoordCase : public TestCase
2118{
2119public:
2120								BuiltinGlPointCoordCase	(TestContext& testCtx, const string& name, int testVariant);
2121	virtual						~BuiltinGlPointCoordCase	(void);
2122
2123	void						initPrograms				(SourceCollections& dst) const;
2124	TestInstance*				createInstance				(Context& context) const;
2125
2126private:
2127	int							variant;
2128								BuiltinGlPointCoordCase	(const BuiltinGlPointCoordCase&);	// not allowed!
2129	BuiltinGlPointCoordCase&	operator=					(const BuiltinGlPointCoordCase&);	// not allowed!
2130};
2131
2132BuiltinGlPointCoordCase::BuiltinGlPointCoordCase (TestContext& testCtx, const string& name, int testVariant)
2133	: TestCase(testCtx, name),
2134	  variant(testVariant)
2135{
2136}
2137
2138BuiltinGlPointCoordCase::~BuiltinGlPointCoordCase (void)
2139{
2140}
2141
2142void BuiltinGlPointCoordCase::initPrograms (SourceCollections& dst) const
2143{
2144	switch (variant)
2145	{
2146	case POINTCOORD_VARIANT_UNIFORM_FRAGMENT:
2147		dst.glslSources.add("vert") << glu::VertexSource(
2148			"#version 310 es\n"
2149			"layout(location = 0) in highp vec3 a_position;\n"
2150			"void main (void)\n"
2151			"{\n"
2152			"    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
2153			"    gl_PointSize = a_position.z;\n"
2154			"}\n");
2155
2156		dst.glslSources.add("frag") << glu::FragmentSource(
2157			"#version 310 es\n"
2158			"layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
2159			"layout(location = 0) out lowp vec4 o_color;\n"
2160			"void main (void)\n"
2161			"{\n"
2162			"    o_color = vec4(gl_PointCoord, 0.0, 1.0) * vec4(u_scale, 1.0);\n"
2163			"}\n");
2164		break;
2165	case POINTCOORD_VARIANT_UNIFORM_VERTEX:
2166		dst.glslSources.add("vert") << glu::VertexSource(
2167			"#version 310 es\n"
2168			"layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
2169			"layout(location = 0) in highp vec3 a_position;\n"
2170			"void main (void)\n"
2171			"{\n"
2172			"    gl_Position = vec4(a_position.xy, 0.0, 1.0) * vec4(u_scale, 1.0);\n"
2173			"    gl_PointSize = a_position.z;\n"
2174			"}\n");
2175
2176		dst.glslSources.add("frag") << glu::FragmentSource(
2177			"#version 310 es\n"
2178			"layout(location = 0) out lowp vec4 o_color;\n"
2179			"void main (void)\n"
2180			"{\n"
2181			"    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
2182			"}\n");
2183		break;
2184	default: // POINTCOORD_VARIANT_DEFAULT
2185		dst.glslSources.add("vert") << glu::VertexSource(
2186			"#version 310 es\n"
2187			"layout(location = 0) in highp vec3 a_position;\n"
2188			"void main (void)\n"
2189			"{\n"
2190			"    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
2191			"    gl_PointSize = a_position.z;\n"
2192			"}\n");
2193
2194		dst.glslSources.add("frag") << glu::FragmentSource(
2195			"#version 310 es\n"
2196			"layout(location = 0) out lowp vec4 o_color;\n"
2197			"void main (void)\n"
2198			"{\n"
2199			"    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
2200			"}\n");
2201	}
2202}
2203
2204TestInstance* BuiltinGlPointCoordCase::createInstance (Context& context) const
2205{
2206	return new BuiltinGlPointCoordCaseInstance(context, variant);
2207}
2208
2209enum ShaderInputTypeBits
2210{
2211	SHADER_INPUT_BUILTIN_BIT	= 0x01,
2212	SHADER_INPUT_VARYING_BIT	= 0x02,
2213	SHADER_INPUT_CONSTANT_BIT	= 0x04
2214};
2215
2216typedef deUint16 ShaderInputTypes;
2217
2218string shaderInputTypeToString (ShaderInputTypes type)
2219{
2220	string typeString = "input";
2221
2222	if (type == 0)
2223		return "input_none";
2224
2225	if (type & SHADER_INPUT_BUILTIN_BIT)
2226		typeString += "_builtin";
2227
2228	if (type & SHADER_INPUT_VARYING_BIT)
2229		typeString += "_varying";
2230
2231	if (type & SHADER_INPUT_CONSTANT_BIT)
2232		typeString += "_constant";
2233
2234	return typeString;
2235}
2236
2237class BuiltinInputVariationsCaseInstance : public ShaderRenderCaseInstance
2238{
2239public:
2240							BuiltinInputVariationsCaseInstance	(Context& context, const ShaderInputTypes shaderInputTypes);
2241
2242	TestStatus				iterate								(void);
2243	virtual void			setupDefaultInputs					(void);
2244	virtual void			updatePushConstants					(vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout);
2245
2246private:
2247	const ShaderInputTypes	m_shaderInputTypes;
2248	const Vec4				m_constantColor;
2249};
2250
2251BuiltinInputVariationsCaseInstance::BuiltinInputVariationsCaseInstance (Context& context, const ShaderInputTypes shaderInputTypes)
2252	: ShaderRenderCaseInstance	(context)
2253	, m_shaderInputTypes		(shaderInputTypes)
2254	, m_constantColor			(0.1f, 0.05f, 0.2f, 0.0f)
2255{
2256}
2257
2258TestStatus BuiltinInputVariationsCaseInstance::iterate (void)
2259{
2260	const UVec2					viewportSize	= getViewportSize();
2261	const int					width			= viewportSize.x();
2262	const int					height			= viewportSize.y();
2263	const tcu::RGBA				threshold		(2, 2, 2, 2);
2264	Surface						resImage		(width, height);
2265	Surface						refImage		(width, height);
2266	bool						compareOk		= false;
2267	const VkPushConstantRange	pcRanges		=
2268	{
2269		VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags	stageFlags;
2270		0u,								// deUint32				offset;
2271		sizeof(Vec4)					// deUint32				size;
2272	};
2273	const deUint16				indices[12]		=
2274	{
2275		0, 4, 1,
2276		0, 5, 4,
2277		1, 2, 3,
2278		1, 3, 4
2279	};
2280
2281	setup();
2282
2283	if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
2284		setPushConstantRanges(1, &pcRanges);
2285
2286	render(6, 4, indices);
2287	copy(resImage.getAccess(), getResultImage().getAccess());
2288
2289	// Reference image
2290	for (int y = 0; y < refImage.getHeight(); y++)
2291	{
2292		for (int x = 0; x < refImage.getWidth(); x++)
2293		{
2294			Vec4 color (0.1f, 0.2f, 0.3f, 1.0f);
2295
2296			if (((m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT) && (x < refImage.getWidth() / 2)) ||
2297				!(m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT))
2298			{
2299				if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
2300				{
2301					const float xf = (float(x)+.5f) / float(refImage.getWidth());
2302					color += Vec4(0.6f * (1 - xf), 0.6f * xf, 0.0f, 0.0f);
2303				}
2304				else
2305					color += Vec4(0.3f, 0.2f, 0.1f, 0.0f);
2306			}
2307
2308			if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
2309				color += m_constantColor;
2310
2311			refImage.setPixel(x, y, RGBA(color));
2312		}
2313	}
2314
2315	compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
2316
2317	if (compareOk)
2318		return TestStatus::pass("Result image matches reference");
2319	else
2320		return TestStatus::fail("Image mismatch");
2321}
2322
2323void BuiltinInputVariationsCaseInstance::setupDefaultInputs (void)
2324{
2325	const float vertices[] =
2326	{
2327		-1.0f, -1.0f, 0.0f, 1.0f,
2328		 0.0f, -1.0f, 0.0f, 1.0f,
2329		 1.0f, -1.0f, 0.0f, 1.0f,
2330		 1.0f,  1.0f, 0.0f, 1.0f,
2331		 0.0f,  1.0f, 0.0f, 1.0f,
2332		-1.0f,  1.0f, 0.0f, 1.0f
2333	};
2334
2335	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, vertices);
2336
2337	if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
2338	{
2339		const float colors[] =
2340		{
2341			 0.6f,  0.0f, 0.0f, 1.0f,
2342			 0.3f,  0.3f, 0.0f, 1.0f,
2343			 0.0f,  0.6f, 0.0f, 1.0f,
2344			 0.0f,  0.6f, 0.0f, 1.0f,
2345			 0.3f,  0.3f, 0.0f, 1.0f,
2346			 0.6f,  0.0f, 0.0f, 1.0f
2347		};
2348		addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, colors);
2349	}
2350}
2351
2352void BuiltinInputVariationsCaseInstance::updatePushConstants (vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout)
2353{
2354	if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
2355	{
2356		const DeviceInterface& vk = m_context.getDeviceInterface();
2357		vk.cmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(Vec4), &m_constantColor);
2358	}
2359}
2360
2361class BuiltinInputVariationsCase : public TestCase
2362{
2363public:
2364								BuiltinInputVariationsCase	(TestContext& testCtx, const string& name, const ShaderInputTypes shaderInputTypes);
2365	virtual						~BuiltinInputVariationsCase	(void);
2366
2367	void						initPrograms				(SourceCollections& dst) const;
2368	TestInstance*				createInstance				(Context& context) const;
2369
2370private:
2371								BuiltinInputVariationsCase	(const BuiltinInputVariationsCase&);	// not allowed!
2372	BuiltinInputVariationsCase&	operator=					(const BuiltinInputVariationsCase&);	// not allowed!
2373	const ShaderInputTypes		m_shaderInputTypes;
2374};
2375
2376BuiltinInputVariationsCase::BuiltinInputVariationsCase (TestContext& testCtx, const string& name, ShaderInputTypes shaderInputTypes)
2377	: TestCase				(testCtx, name)
2378	, m_shaderInputTypes	(shaderInputTypes)
2379{
2380}
2381
2382BuiltinInputVariationsCase::~BuiltinInputVariationsCase (void)
2383{
2384}
2385
2386void BuiltinInputVariationsCase::initPrograms (SourceCollections& dst) const
2387{
2388	map<string, string>			vertexParams;
2389	map<string, string>			fragmentParams;
2390	const tcu::StringTemplate	vertexCodeTemplate		(
2391		"#version 450\n"
2392		"layout(location = 0) in highp vec4 a_position;\n"
2393		"out gl_PerVertex {\n"
2394		"	vec4 gl_Position;\n"
2395		"};\n"
2396		"${VARYING_DECL}"
2397		"void main (void)\n"
2398		"{\n"
2399		"    gl_Position = a_position;\n"
2400		"    ${VARYING_USAGE}"
2401		"}\n");
2402
2403	const tcu::StringTemplate	fragmentCodeTemplate	(
2404		"#version 450\n"
2405		"${VARYING_DECL}"
2406		"${CONSTANT_DECL}"
2407		"layout(location = 0) out highp vec4 o_color;\n"
2408		"void main (void)\n"
2409		"{\n"
2410		"    o_color = vec4(0.1, 0.2, 0.3, 1.0);\n"
2411		"    ${BUILTIN_USAGE}"
2412		"    ${VARYING_USAGE}"
2413		"    ${CONSTANT_USAGE}"
2414		"}\n");
2415
2416	vertexParams["VARYING_DECL"]		=
2417		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "layout(location = 1) in highp vec4 a_color;\n"
2418														  "layout(location = 0) out highp vec4 v_color;\n"
2419														: "";
2420
2421	vertexParams["VARYING_USAGE"]		=
2422		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "v_color = a_color;\n"
2423														: "";
2424
2425	fragmentParams["VARYING_DECL"]		=
2426		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "layout(location = 0) in highp vec4 a_color;\n"
2427														: "";
2428
2429	fragmentParams["CONSTANT_DECL"]		=
2430		m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT	? "layout(push_constant) uniform PCBlock {\n"
2431														  "  vec4 color;\n"
2432														  "} pc;\n"
2433														: "";
2434
2435	fragmentParams["BUILTIN_USAGE"]		=
2436		m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT	? "if (gl_FrontFacing)\n"
2437														: "";
2438
2439	fragmentParams["VARYING_USAGE"]		=
2440		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "o_color += vec4(a_color.xyz, 0.0);\n"
2441														: "o_color += vec4(0.3, 0.2, 0.1, 0.0);\n";
2442
2443
2444	fragmentParams["CONSTANT_USAGE"]	=
2445		m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT	? "o_color += pc.color;\n"
2446														: "";
2447
2448	dst.glslSources.add("vert") << glu::VertexSource(vertexCodeTemplate.specialize(vertexParams));
2449	dst.glslSources.add("frag") << glu::FragmentSource(fragmentCodeTemplate.specialize(fragmentParams));
2450}
2451
2452TestInstance* BuiltinInputVariationsCase::createInstance (Context& context) const
2453{
2454	return new BuiltinInputVariationsCaseInstance(context, m_shaderInputTypes);
2455}
2456
2457} // anonymous
2458
2459TestCaseGroup* createBuiltinVarTests (TestContext& testCtx)
2460{
2461	de::MovePtr<TestCaseGroup> builtinGroup			(new TestCaseGroup(testCtx, "builtin_var", "Shader builtin variable tests."));
2462	de::MovePtr<TestCaseGroup> simpleGroup			(new TestCaseGroup(testCtx, "simple", "Simple cases."));
2463	de::MovePtr<TestCaseGroup> inputVariationsGroup	(new TestCaseGroup(testCtx, "input_variations", "Input type variation tests."));
2464	de::MovePtr<TestCaseGroup> frontFacingGroup		(new TestCaseGroup(testCtx, "frontfacing", "Test gl_Frontfacing keyword."));
2465	de::MovePtr<TestCaseGroup> fragDepthGroup		(new TestCaseGroup(testCtx, "fragdepth", "Test gl_FragDepth keyword."));
2466	de::MovePtr<TestCaseGroup> fragCoordMsaaGroup	(new TestCaseGroup(testCtx, "fragcoord_msaa", "Test interation between gl_FragCoord and msaa"));
2467	de::MovePtr<TestCaseGroup> fragCoordMsaaInputGroup	(new TestCaseGroup(testCtx, "fragcoord_msaa_input", "Test interation between gl_FragCoord and msaa"));
2468
2469	// FragCoord xyz test
2470	simpleGroup->addChild(new BuiltinGlFragCoordXYZCase(testCtx, "fragcoord_xyz"));
2471	// FragCoord w test
2472	simpleGroup->addChild(new BuiltinGlFragCoordWCase(testCtx, "fragcoord_w"));
2473	// PointCoord test
2474	simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord", POINTCOORD_VARIANT_DEFAULT));
2475	// PointCoord test with fragment uniform
2476	simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord_uniform_frag", POINTCOORD_VARIANT_UNIFORM_FRAGMENT));
2477	// PointCoord test with vertex uniform
2478	simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord_uniform_vert", POINTCOORD_VARIANT_UNIFORM_VERTEX));
2479
2480	// FragCoord_msaa
2481	{
2482		static const struct FragCoordMsaaCaseList
2483		{
2484			const char*				name;
2485			VkSampleCountFlagBits	sampleCount;
2486		} fragCoordMsaaCaseList[] =
2487		{
2488			{ "1_bit",	VK_SAMPLE_COUNT_1_BIT },
2489			{ "2_bit",	VK_SAMPLE_COUNT_2_BIT },
2490			{ "4_bit",	VK_SAMPLE_COUNT_4_BIT },
2491			{ "8_bit",	VK_SAMPLE_COUNT_8_BIT },
2492			{ "16_bit",	VK_SAMPLE_COUNT_16_BIT },
2493			{ "32_bit",	VK_SAMPLE_COUNT_32_BIT },
2494			{ "64_bit",	VK_SAMPLE_COUNT_64_BIT },
2495		};
2496
2497		// Standard sample tests
2498		std::vector<uint32_t> sampleMaskArray;
2499
2500		for (deUint32 caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(fragCoordMsaaCaseList); caseNdx++)
2501		{
2502			fragCoordMsaaGroup->addChild(new BuiltinFragCoordMsaaTestCase(testCtx, fragCoordMsaaCaseList[caseNdx].name, fragCoordMsaaCaseList[caseNdx].sampleCount, true, sampleMaskArray, false, true));
2503			fragCoordMsaaInputGroup->addChild(new BuiltinFragCoordMsaaTestCase(testCtx, fragCoordMsaaCaseList[caseNdx].name, fragCoordMsaaCaseList[caseNdx].sampleCount, true, sampleMaskArray, false, false));
2504		}
2505
2506		sampleMaskArray.push_back(1u);
2507
2508		// No sample shading tests
2509		for (deUint32 caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(fragCoordMsaaCaseList); caseNdx++)
2510		{
2511			fragCoordMsaaInputGroup->addChild(new BuiltinFragCoordMsaaTestCase(testCtx, (std::string(fragCoordMsaaCaseList[caseNdx].name) + "_no_sample_shading").c_str(), fragCoordMsaaCaseList[caseNdx].sampleCount, false, sampleMaskArray, false, false));
2512		}
2513
2514		// No sample shading tests with centroid interpolation decoration
2515		for (deUint32 caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(fragCoordMsaaCaseList); caseNdx++)
2516		{
2517			fragCoordMsaaInputGroup->addChild(new BuiltinFragCoordMsaaTestCase(testCtx, (std::string(fragCoordMsaaCaseList[caseNdx].name) + "_no_sample_shading_centroid_interpolation").c_str(), fragCoordMsaaCaseList[caseNdx].sampleCount, false, sampleMaskArray, true, false));
2518		}
2519	}
2520
2521	// gl_FrontFacing tests
2522	{
2523		static const struct PrimitiveTable
2524		{
2525			const char*				name;
2526			VkPrimitiveTopology		primitive;
2527		} frontfacingCases[] =
2528		{
2529			// Test that points are frontfacing
2530			{ "point_list",							VK_PRIMITIVE_TOPOLOGY_POINT_LIST },
2531			// Test that lines are frontfacing
2532			{ "line_list",							VK_PRIMITIVE_TOPOLOGY_LINE_LIST },
2533			// Test that triangles can be frontfacing or backfacing
2534			{ "triangle_list",						VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST },
2535			// Test that traiangle strips can be front or back facing
2536			{ "triangle_strip",						VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP },
2537			// Test that triangle fans can be front or back facing
2538			{ "triangle_fan",						VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN },
2539		};
2540
2541		for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(frontfacingCases); ndx++)
2542			frontFacingGroup->addChild(new BuiltinGlFrontFacingCase(testCtx, frontfacingCases[ndx].primitive, frontfacingCases[ndx].name));
2543	}
2544
2545	// gl_FragDepth
2546	{
2547		static const struct PrimitiveTopologyTable
2548		{
2549			std::string			name;
2550			VkPrimitiveTopology	prim;
2551		} primitiveTopologyTable[] =
2552		{
2553			// test that points respect gl_fragdepth
2554			{ "point_list", VK_PRIMITIVE_TOPOLOGY_POINT_LIST },
2555			// test taht lines respect gl_fragdepth
2556			{ "line_list", VK_PRIMITIVE_TOPOLOGY_LINE_LIST },
2557			// test that triangles respect gl_fragdepth
2558			{ "triangle_list", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP },
2559		};
2560
2561		static const struct TestCaseTable
2562		{
2563			VkFormat				format;
2564			std::string				name;
2565			bool					largeDepthEnable;
2566			bool					depthClampEnable;
2567			VkSampleCountFlagBits	samples;
2568		} testCaseTable[] =
2569		{
2570			{ VK_FORMAT_D16_UNORM,				"d16_unorm_no_depth_clamp",				false,	false,	VK_SAMPLE_COUNT_1_BIT },
2571			{ VK_FORMAT_X8_D24_UNORM_PACK32,	"x8_d24_unorm_pack32_no_depth_clamp",	false,	false,	VK_SAMPLE_COUNT_1_BIT },
2572			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_no_depth_clamp",			false,	false,	VK_SAMPLE_COUNT_1_BIT },
2573			{ VK_FORMAT_D16_UNORM_S8_UINT,		"d16_unorm_s8_uint_no_depth_clamp",		false,	false,	VK_SAMPLE_COUNT_1_BIT },
2574			{ VK_FORMAT_D24_UNORM_S8_UINT,		"d24_unorm_s8_uint_no_depth_clamp",		false,	false,	VK_SAMPLE_COUNT_1_BIT },
2575			{ VK_FORMAT_D32_SFLOAT_S8_UINT,		"d32_sfloat_s8_uint_no_depth_clamp",	false,	false,	VK_SAMPLE_COUNT_1_BIT },
2576			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_large_depth",				true,	false,	VK_SAMPLE_COUNT_1_BIT },
2577			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat",							false,	true,	VK_SAMPLE_COUNT_1_BIT },
2578			{ VK_FORMAT_D32_SFLOAT_S8_UINT,		"d32_sfloat_s8_uint",					false,	true,	VK_SAMPLE_COUNT_1_BIT },
2579			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_2",				false,	false,	VK_SAMPLE_COUNT_2_BIT },
2580			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_4",				false,	false,	VK_SAMPLE_COUNT_4_BIT },
2581			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_8",				false,	false,	VK_SAMPLE_COUNT_8_BIT },
2582			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_16",			false,	false,	VK_SAMPLE_COUNT_16_BIT },
2583			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_32",			false,	false,	VK_SAMPLE_COUNT_32_BIT },
2584			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_64",			false,	false,	VK_SAMPLE_COUNT_64_BIT },
2585		};
2586
2587		for (deUint32 primNdx = 0;  primNdx < DE_LENGTH_OF_ARRAY(primitiveTopologyTable); primNdx++)
2588		{
2589			for (deUint32 caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCaseTable); caseNdx++)
2590				fragDepthGroup->addChild(new BuiltinFragDepthCase(testCtx, (primitiveTopologyTable[primNdx].name+"_" + testCaseTable[caseNdx].name).c_str(),
2591							primitiveTopologyTable[primNdx].prim, testCaseTable[caseNdx].format, testCaseTable[caseNdx].largeDepthEnable, testCaseTable[caseNdx].depthClampEnable, testCaseTable[caseNdx].samples));
2592
2593		}
2594	}
2595
2596	builtinGroup->addChild(frontFacingGroup.release());
2597	builtinGroup->addChild(fragDepthGroup.release());
2598	builtinGroup->addChild(fragCoordMsaaGroup.release());
2599	builtinGroup->addChild(fragCoordMsaaInputGroup.release());
2600	builtinGroup->addChild(simpleGroup.release());
2601
2602	for (deUint16 shaderType = 0; shaderType <= (SHADER_INPUT_BUILTIN_BIT | SHADER_INPUT_VARYING_BIT | SHADER_INPUT_CONSTANT_BIT); ++shaderType)
2603	{
2604		inputVariationsGroup->addChild(new BuiltinInputVariationsCase(testCtx, shaderInputTypeToString(shaderType), shaderType));
2605	}
2606
2607	builtinGroup->addChild(inputVariationsGroup.release());
2608	return builtinGroup.release();
2609}
2610
2611} // sr
2612} // vkt
2613