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