1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 * Copyright (c) 2015 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Early fragment tests
23 *//*--------------------------------------------------------------------*/
24
25#include "vktPipelineEarlyFragmentTests.hpp"
26#include "vktTestCaseUtil.hpp"
27
28#include "vkDefs.hpp"
29#include "vkRef.hpp"
30#include "vkRefUtil.hpp"
31#include "vkPlatform.hpp"
32#include "vkPrograms.hpp"
33#include "vkMemUtil.hpp"
34#include "vkBuilderUtil.hpp"
35#include "vkStrUtil.hpp"
36#include "vkTypeUtil.hpp"
37#include "vkQueryUtil.hpp"
38#include "vkImageUtil.hpp"
39
40#include "deUniquePtr.hpp"
41#include "deStringUtil.hpp"
42
43#include <string>
44
45using namespace vk;
46
47namespace vkt
48{
49namespace pipeline
50{
51namespace
52{
53
54// \note Some utility functions are general, but others are custom tailored to this test.
55
56class Buffer
57{
58public:
59									Buffer			(const DeviceInterface&		vk,
60													 const VkDevice				device,
61													 Allocator&					allocator,
62													 const VkBufferCreateInfo&	bufferCreateInfo,
63													 const MemoryRequirement	memoryRequirement)
64
65										: m_buffer		(createBuffer(vk, device, &bufferCreateInfo))
66										, m_allocation	(allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement))
67									{
68										VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset()));
69									}
70
71	const VkBuffer&					get				(void) const { return *m_buffer; }
72	const VkBuffer&					operator*		(void) const { return get(); }
73	Allocation&						getAllocation	(void) const { return *m_allocation; }
74
75private:
76	const Unique<VkBuffer>			m_buffer;
77	const de::UniquePtr<Allocation>	m_allocation;
78
79	// "deleted"
80									Buffer			(const Buffer&);
81	Buffer&							operator=		(const Buffer&);
82};
83
84class Image
85{
86public:
87									Image			(const DeviceInterface&		vk,
88													 const VkDevice				device,
89													 Allocator&					allocator,
90													 const VkImageCreateInfo&	imageCreateInfo,
91													 const MemoryRequirement	memoryRequirement)
92
93										: m_image		(createImage(vk, device, &imageCreateInfo))
94										, m_allocation	(allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement))
95									{
96										VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset()));
97									}
98
99	const VkImage&					get				(void) const { return *m_image; }
100	const VkImage&					operator*		(void) const { return get(); }
101	Allocation&						getAllocation	(void) const { return *m_allocation; }
102
103private:
104	const Unique<VkImage>			m_image;
105	const de::UniquePtr<Allocation>	m_allocation;
106
107	// "deleted"
108									Image			(const Image&);
109	Image&							operator=		(const Image&);
110};
111
112Move<VkImageView> makeImageView (const DeviceInterface&			vk,
113								 const VkDevice					vkDevice,
114								 const VkImage					image,
115								 const VkImageViewType			imageViewType,
116								 const VkFormat					format,
117								 const VkImageSubresourceRange	subresourceRange)
118{
119	const VkImageViewCreateInfo imageViewParams =
120	{
121		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
122		DE_NULL,										// const void*				pNext;
123		(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
124		image,											// VkImage					image;
125		imageViewType,									// VkImageViewType			viewType;
126		format,											// VkFormat					format;
127		makeComponentMappingRGBA(),						// VkComponentMapping		components;
128		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
129	};
130	return createImageView(vk, vkDevice, &imageViewParams);
131}
132
133VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
134										 const VkBufferUsageFlags	usage)
135{
136	const VkBufferCreateInfo bufferCreateInfo =
137	{
138		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
139		DE_NULL,								// const void*			pNext;
140		(VkBufferCreateFlags)0,					// VkBufferCreateFlags	flags;
141		bufferSize,								// VkDeviceSize			size;
142		usage,									// VkBufferUsageFlags	usage;
143		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
144		0u,										// deUint32				queueFamilyIndexCount;
145		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
146	};
147	return bufferCreateInfo;
148}
149
150Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&			vk,
151										 const VkDevice					device,
152										 const VkDescriptorPool			descriptorPool,
153										 const VkDescriptorSetLayout	setLayout)
154{
155	const VkDescriptorSetAllocateInfo allocateParams =
156	{
157		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
158		DE_NULL,											// const void*					pNext;
159		descriptorPool,										// VkDescriptorPool				descriptorPool;
160		1u,													// deUint32						setLayoutCount;
161		&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
162	};
163	return allocateDescriptorSet(vk, device, &allocateParams);
164}
165
166Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
167										   const VkDevice				device,
168										   const VkDescriptorSetLayout	descriptorSetLayout)
169{
170	const VkPipelineLayoutCreateInfo pipelineLayoutParams =
171	{
172		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
173		DE_NULL,											// const void*						pNext;
174		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags		flags;
175		1u,													// deUint32							setLayoutCount;
176		&descriptorSetLayout,								// const VkDescriptorSetLayout*		pSetLayouts;
177		0u,													// deUint32							pushConstantRangeCount;
178		DE_NULL,											// const VkPushConstantRange*		pPushConstantRanges;
179	};
180	return createPipelineLayout(vk, device, &pipelineLayoutParams);
181}
182
183Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
184{
185	const VkCommandPoolCreateInfo commandPoolParams =
186	{
187		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType;
188		DE_NULL,											// const void*				pNext;
189		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags;
190		queueFamilyIndex,									// deUint32					queueFamilyIndex;
191	};
192	return createCommandPool(vk, device, &commandPoolParams);
193}
194
195Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
196{
197	const VkCommandBufferAllocateInfo bufferAllocateParams =
198	{
199		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType			sType;
200		DE_NULL,											// const void*				pNext;
201		commandPool,										// VkCommandPool			commandPool;
202		VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel		level;
203		1u,													// deUint32					bufferCount;
204	};
205	return allocateCommandBuffer(vk, device, &bufferAllocateParams);
206}
207
208void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
209{
210	const VkCommandBufferBeginInfo commandBufBeginParams =
211	{
212		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
213		DE_NULL,										// const void*						pNext;
214		(VkCommandBufferUsageFlags)0,					// VkCommandBufferUsageFlags		flags;
215		DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
216	};
217	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &commandBufBeginParams));
218}
219
220void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
221{
222	VK_CHECK(vk.endCommandBuffer(commandBuffer));
223}
224
225void submitCommandsAndWait (const DeviceInterface&	vk,
226							const VkDevice			device,
227							const VkQueue			queue,
228							const VkCommandBuffer	commandBuffer)
229{
230	const VkFenceCreateInfo	fenceParams =
231	{
232		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
233		DE_NULL,								// const void*			pNext;
234		(VkFenceCreateFlags)0,					// VkFenceCreateFlags	flags;
235	};
236	const Unique<VkFence> fence(createFence(vk, device, &fenceParams));
237
238	const VkSubmitInfo submitInfo =
239	{
240		VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType			sType;
241		DE_NULL,							// const void*				pNext;
242		0u,									// deUint32					waitSemaphoreCount;
243		DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
244		DE_NULL,							// const VkPipelineStageFlags*    pWaitDstStageMask;
245		1u,									// deUint32					commandBufferCount;
246		&commandBuffer,						// const VkCommandBuffer*	pCommandBuffers;
247		0u,									// deUint32					signalSemaphoreCount;
248		DE_NULL,							// const VkSemaphore*		pSignalSemaphores;
249	};
250
251	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
252	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
253}
254
255VkImageMemoryBarrier makeImageMemoryBarrier	(const VkAccessFlags			srcAccessMask,
256											 const VkAccessFlags			dstAccessMask,
257											 const VkImageLayout			oldLayout,
258											 const VkImageLayout			newLayout,
259											 const VkImage					image,
260											 const VkImageSubresourceRange	subresourceRange)
261{
262	const VkImageMemoryBarrier barrier =
263	{
264		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
265		DE_NULL,										// const void*				pNext;
266		srcAccessMask,									// VkAccessFlags			outputMask;
267		dstAccessMask,									// VkAccessFlags			inputMask;
268		oldLayout,										// VkImageLayout			oldLayout;
269		newLayout,										// VkImageLayout			newLayout;
270		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
271		VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
272		image,											// VkImage					image;
273		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
274	};
275	return barrier;
276}
277
278VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags	srcAccessMask,
279											   const VkAccessFlags	dstAccessMask,
280											   const VkBuffer		buffer,
281											   const VkDeviceSize	offset,
282											   const VkDeviceSize	bufferSizeBytes)
283{
284	const VkBufferMemoryBarrier barrier =
285	{
286		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
287		DE_NULL,									// const void*		pNext;
288		srcAccessMask,								// VkAccessFlags	srcAccessMask;
289		dstAccessMask,								// VkAccessFlags	dstAccessMask;
290		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
291		VK_QUEUE_FAMILY_IGNORED,					// deUint32			destQueueFamilyIndex;
292		buffer,										// VkBuffer			buffer;
293		offset,										// VkDeviceSize		offset;
294		bufferSizeBytes,							// VkDeviceSize		size;
295	};
296	return barrier;
297}
298
299//! Basic 2D image.
300inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
301{
302	const VkImageCreateInfo imageParams =
303	{
304		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType;
305		DE_NULL,												// const void*				pNext;
306		(VkImageCreateFlags)0,									// VkImageCreateFlags		flags;
307		VK_IMAGE_TYPE_2D,										// VkImageType				imageType;
308		format,													// VkFormat					format;
309		makeExtent3D(size.x(), size.y(), 1),					// VkExtent3D				extent;
310		1u,														// deUint32					mipLevels;
311		1u,														// deUint32					arrayLayers;
312		VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples;
313		VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling;
314		usage,													// VkImageUsageFlags		usage;
315		VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode;
316		0u,														// deUint32					queueFamilyIndexCount;
317		DE_NULL,												// const deUint32*			pQueueFamilyIndices;
318		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			initialLayout;
319	};
320	return imageParams;
321}
322
323void beginRenderPass (const DeviceInterface&	vk,
324					  const VkCommandBuffer		commandBuffer,
325					  const VkRenderPass		renderPass,
326					  const VkFramebuffer		framebuffer,
327					  const VkRect2D&			renderArea,
328					  const tcu::Vec4&			clearColor,
329					  const float				clearDepth,
330					  const deUint32			clearStencil)
331{
332	const VkClearValue clearValues[] =
333	{
334		makeClearValueColor(clearColor),						// attachment 0
335		makeClearValueDepthStencil(clearDepth, clearStencil),	// attachment 1
336	};
337
338	const VkRenderPassBeginInfo renderPassBeginInfo = {
339		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
340		DE_NULL,										// const void*             pNext;
341		renderPass,										// VkRenderPass            renderPass;
342		framebuffer,									// VkFramebuffer           framebuffer;
343		renderArea,										// VkRect2D                renderArea;
344		DE_LENGTH_OF_ARRAY(clearValues),				// uint32_t                clearValueCount;
345		clearValues,									// const VkClearValue*     pClearValues;
346	};
347
348	vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
349}
350
351void endRenderPass (const DeviceInterface&	vk,
352					const VkCommandBuffer	commandBuffer)
353{
354	vk.cmdEndRenderPass(commandBuffer);
355}
356
357Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
358								   const VkDevice			device,
359								   const VkFormat			colorFormat,
360								   const bool				useDepthStencilAttachment,
361								   const VkFormat			depthStencilFormat)
362{
363	const VkAttachmentDescription attachments[] =
364	{
365		// color
366		{
367			(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
368			colorFormat,										// VkFormat							format;
369			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
370			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
371			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
372			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
373			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
374			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
375			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
376		},
377		// depth/stencil
378		{
379			(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
380			depthStencilFormat,									// VkFormat							format;
381			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
382			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
383			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
384			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				stencilLoadOp;
385			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				stencilStoreOp;
386			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout;
387			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout					finalLayout;
388		}
389	};
390
391	const VkAttachmentReference unusedAttachmentReference =
392	{
393		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
394		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
395	};
396
397	const VkAttachmentReference colorAttachmentReference =
398	{
399		0u,													// deUint32			attachment;
400		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
401	};
402
403	const VkAttachmentReference depthStencilAttachmentReference =
404	{
405		1u,													// deUint32			attachment;
406		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
407	};
408
409	const VkAttachmentReference* pDepthStencilAttachment = (useDepthStencilAttachment ? &depthStencilAttachmentReference : &unusedAttachmentReference);
410
411	const VkSubpassDescription subpassDescription =
412	{
413		0u,													// VkSubpassDescriptionFlags		flags;
414		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
415		0u,													// deUint32							inputAttachmentCount;
416		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
417		1u,													// deUint32							colorAttachmentCount;
418		&colorAttachmentReference,							// const VkAttachmentReference*		pColorAttachments;
419		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
420		pDepthStencilAttachment,							// const VkAttachmentReference*		pDepthStencilAttachment;
421		0u,													// deUint32							preserveAttachmentCount;
422		DE_NULL												// const deUint32*					pPreserveAttachments;
423	};
424
425	const VkRenderPassCreateInfo renderPassInfo =
426	{
427		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
428		DE_NULL,											// const void*						pNext;
429		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
430		(useDepthStencilAttachment ? 2u : 1u),				// deUint32							attachmentCount;
431		attachments,										// const VkAttachmentDescription*	pAttachments;
432		1u,													// deUint32							subpassCount;
433		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
434		0u,													// deUint32							dependencyCount;
435		DE_NULL												// const VkSubpassDependency*		pDependencies;
436	};
437
438	return createRenderPass(vk, device, &renderPassInfo);
439}
440
441Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
442									 const VkDevice				device,
443									 const VkRenderPass			renderPass,
444									 const deUint32				attachmentCount,
445									 const VkImageView*			pAttachments,
446									 const tcu::IVec2			size)
447{
448	const VkFramebufferCreateInfo framebufferInfo = {
449		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
450		DE_NULL,										// const void*                                 pNext;
451		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
452		renderPass,										// VkRenderPass                                renderPass;
453		attachmentCount,								// uint32_t                                    attachmentCount;
454		pAttachments,									// const VkImageView*                          pAttachments;
455		static_cast<deUint32>(size.x()),				// uint32_t                                    width;
456		static_cast<deUint32>(size.y()),				// uint32_t                                    height;
457		1u,												// uint32_t                                    layers;
458	};
459
460	return createFramebuffer(vk, device, &framebufferInfo);
461}
462
463Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&	vk,
464									   const VkDevice			device,
465									   const VkPipelineLayout	pipelineLayout,
466									   const VkRenderPass		renderPass,
467									   const VkShaderModule		vertexModule,
468									   const VkShaderModule		fragmentModule,
469									   const tcu::IVec2&		renderSize,
470									   const bool				enableDepthTest,
471									   const bool				enableStencilTest)
472{
473	const VkVertexInputBindingDescription vertexInputBindingDescription =
474	{
475		0u,								// uint32_t				binding;
476		sizeof(tcu::Vec4),				// uint32_t				stride;		// Vertex is a 4-element vector XYZW, position only
477		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
478	};
479
480	const VkVertexInputAttributeDescription vertexInputAttributeDescription =
481	{
482		0u,									// uint32_t			location;
483		0u,									// uint32_t			binding;
484		VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
485		0u,									// uint32_t			offset;
486	};
487
488	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
489	{
490		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType;
491		DE_NULL,													// const void*                                 pNext;
492		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags       flags;
493		1u,															// uint32_t                                    vertexBindingDescriptionCount;
494		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
495		1u,															// uint32_t                                    vertexAttributeDescriptionCount;
496		&vertexInputAttributeDescription,							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
497	};
498
499	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
500	{
501		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
502		DE_NULL,														// const void*                                 pNext;
503		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
504		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology                         topology;
505		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
506	};
507
508	const VkViewport viewport = makeViewport(
509		0.0f, 0.0f,
510		static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
511		0.0f, 1.0f);
512
513	const VkRect2D scissor = {
514		makeOffset2D(0, 0),
515		makeExtent2D(renderSize.x(), renderSize.y()),
516	};
517
518	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
519	{
520		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
521		DE_NULL,												// const void*                                 pNext;
522		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
523		1u,														// uint32_t                                    viewportCount;
524		&viewport,												// const VkViewport*                           pViewports;
525		1u,														// uint32_t                                    scissorCount;
526		&scissor,												// const VkRect2D*                             pScissors;
527	};
528
529	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
530	{
531		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
532		DE_NULL,														// const void*                              pNext;
533		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
534		VK_FALSE,														// VkBool32                                 depthClampEnable;
535		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
536		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
537		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
538		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
539		VK_FALSE,														// VkBool32									depthBiasEnable;
540		0.0f,															// float									depthBiasConstantFactor;
541		0.0f,															// float									depthBiasClamp;
542		0.0f,															// float									depthBiasSlopeFactor;
543		1.0f,															// float									lineWidth;
544	};
545
546	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
547	{
548		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
549		DE_NULL,													// const void*								pNext;
550		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
551		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
552		VK_FALSE,													// VkBool32									sampleShadingEnable;
553		0.0f,														// float									minSampleShading;
554		DE_NULL,													// const VkSampleMask*						pSampleMask;
555		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
556		VK_FALSE													// VkBool32									alphaToOneEnable;
557	};
558
559	const VkStencilOpState stencilOpState = makeStencilOpState(
560		VK_STENCIL_OP_KEEP,		// stencil fail
561		VK_STENCIL_OP_KEEP,		// depth & stencil pass
562		VK_STENCIL_OP_KEEP,		// depth only fail
563		VK_COMPARE_OP_EQUAL,	// compare op
564		1u,						// compare mask
565		1u,						// write mask
566		1u);					// reference
567
568	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
569	{
570		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
571		DE_NULL,													// const void*								pNext;
572		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
573		enableDepthTest,											// VkBool32									depthTestEnable;
574		VK_TRUE,													// VkBool32									depthWriteEnable;
575		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
576		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
577		enableStencilTest,											// VkBool32									stencilTestEnable;
578		stencilOpState,												// VkStencilOpState							front;
579		stencilOpState,												// VkStencilOpState							back;
580		0.0f,														// float									minDepthBounds;
581		1.0f,														// float									maxDepthBounds;
582	};
583
584	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
585	// Number of blend attachments must equal the number of color attachments.
586	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
587	{
588		VK_FALSE,							// VkBool32					blendEnable;
589		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcColorBlendFactor;
590		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstColorBlendFactor;
591		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
592		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcAlphaBlendFactor;
593		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstAlphaBlendFactor;
594		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
595		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
596	};
597
598	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
599	{
600		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
601		DE_NULL,													// const void*									pNext;
602		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
603		VK_FALSE,													// VkBool32										logicOpEnable;
604		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
605		1u,															// deUint32										attachmentCount;
606		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
607		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
608	};
609
610	const VkPipelineShaderStageCreateInfo pShaderStages[] =
611	{
612		{
613			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
614			DE_NULL,												// const void*							pNext;
615			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
616			VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage;
617			vertexModule,											// VkShaderModule						module;
618			"main",													// const char*							pName;
619			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
620		},
621		{
622			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
623			DE_NULL,												// const void*							pNext;
624			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
625			VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits				stage;
626			fragmentModule,											// VkShaderModule						module;
627			"main",													// const char*							pName;
628			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
629		}
630	};
631
632	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
633	{
634		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
635		DE_NULL,											// const void*										pNext;
636		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
637		DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
638		pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
639		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
640		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
641		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
642		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
643		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
644		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
645		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
646		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
647		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
648		pipelineLayout,										// VkPipelineLayout									layout;
649		renderPass,											// VkRenderPass										renderPass;
650		0u,													// deUint32											subpass;
651		DE_NULL,											// VkPipeline										basePipelineHandle;
652		0,													// deInt32											basePipelineIndex;
653	};
654
655	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
656}
657
658VkBufferImageCopy makeBufferImageCopy (const VkImageAspectFlags aspectFlags, const tcu::IVec2& renderSize)
659{
660	const VkBufferImageCopy copyParams =
661	{
662		0ull,															//	VkDeviceSize				bufferOffset;
663		0u,																//	deUint32					bufferRowLength;
664		0u,																//	deUint32					bufferImageHeight;
665		makeImageSubresourceLayers(aspectFlags, 0u, 0u, 1u),			//	VkImageSubresourceLayers	imageSubresource;
666		makeOffset3D(0, 0, 0),											//	VkOffset3D					imageOffset;
667		makeExtent3D(renderSize.x(), renderSize.y(), 1u),				//	VkExtent3D					imageExtent;
668	};
669	return copyParams;
670}
671
672void commandClearStencilAttachment (const DeviceInterface&	vk,
673									const VkCommandBuffer	commandBuffer,
674									const VkOffset2D&		offset,
675									const VkExtent2D&		extent,
676									const deUint32			clearValue)
677{
678	const VkClearAttachment stencilAttachment =
679	{
680		VK_IMAGE_ASPECT_STENCIL_BIT,					// VkImageAspectFlags    aspectMask;
681		0u,												// uint32_t              colorAttachment;
682		makeClearValueDepthStencil(0.0f, clearValue),	// VkClearValue          clearValue;
683	};
684
685	const VkClearRect rect =
686	{
687		{ offset, extent },		// VkRect2D    rect;
688		0u,						// uint32_t    baseArrayLayer;
689		1u,						// uint32_t    layerCount;
690	};
691
692	vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
693}
694
695VkImageAspectFlags getImageAspectFlags (const VkFormat format)
696{
697	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
698
699	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
700	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
701	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
702
703	DE_ASSERT(false);
704	return 0u;
705}
706
707bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
708{
709	VkFormatProperties formatProps;
710	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
711	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
712}
713
714VkFormat pickSupportedDepthStencilFormat (const InstanceInterface&	instanceInterface,
715										  const VkPhysicalDevice	device,
716										  const deUint32			numFormats,
717										  const VkFormat*			pFormats)
718{
719	for (deUint32 i = 0; i < numFormats; ++i)
720		if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
721			return pFormats[i];
722	return VK_FORMAT_UNDEFINED;
723}
724
725enum Flags
726{
727	FLAG_TEST_DEPTH							= 1u << 0,
728	FLAG_TEST_STENCIL						= 1u << 1,
729	FLAG_DONT_USE_TEST_ATTACHMENT			= 1u << 2,
730	FLAG_DONT_USE_EARLY_FRAGMENT_TESTS		= 1u << 3,
731};
732
733class EarlyFragmentTest : public TestCase
734{
735public:
736						EarlyFragmentTest	(tcu::TestContext&		testCtx,
737											 const std::string		name,
738											 const deUint32			flags);
739
740	void				initPrograms		(SourceCollections&		programCollection) const;
741	TestInstance*		createInstance		(Context&				context) const;
742
743private:
744	const deUint32		m_flags;
745};
746
747EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
748	: TestCase	(testCtx, name, "")
749	, m_flags	(flags)
750{
751}
752
753void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
754{
755	// Vertex
756	{
757		std::ostringstream src;
758		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
759			<< "\n"
760			<< "layout(location = 0) in highp vec4 position;\n"
761			<< "\n"
762			<< "void main (void)\n"
763			<< "{\n"
764			<< "    gl_Position = position;\n"
765			<< "}\n";
766
767		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
768	}
769
770	// Fragment
771	{
772		const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
773		std::ostringstream src;
774		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
775			<< "\n"
776			<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
777			<< "layout(location = 0) out highp vec4 fragColor;\n"
778			<< "\n"
779			<< "layout(binding = 0) coherent buffer Output {\n"
780			<< "    uint result;\n"
781			<< "} sb_out;\n"
782			<< "\n"
783			<< "void main (void)\n"
784			<< "{\n"
785			<< "    atomicAdd(sb_out.result, 1u);\n"
786			<< "	fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
787			<< "}\n";
788
789		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
790	}
791}
792
793class EarlyFragmentTestInstance : public TestInstance
794{
795public:
796							EarlyFragmentTestInstance (Context& context, const deUint32 flags);
797
798	tcu::TestStatus			iterate					  (void);
799
800private:
801	enum TestMode
802	{
803		MODE_INVALID,
804		MODE_DEPTH,
805		MODE_STENCIL,
806	};
807
808	const TestMode			m_testMode;
809	const bool				m_useTestAttachment;
810	const bool				m_useEarlyTests;
811};
812
813EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
814	: TestInstance			(context)
815	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
816							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
817	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
818	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
819{
820	DE_ASSERT(m_testMode != MODE_INVALID);
821}
822
823tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
824{
825	const DeviceInterface&		vk					= m_context.getDeviceInterface();
826	const InstanceInterface&	vki					= m_context.getInstanceInterface();
827	const VkDevice				device				= m_context.getDevice();
828	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
829	const VkQueue				queue				= m_context.getUniversalQueue();
830	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
831	Allocator&					allocator			= m_context.getDefaultAllocator();
832
833	// Color attachment
834
835	const tcu::IVec2			  renderSize			= tcu::IVec2(32, 32);
836	const VkFormat				  colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
837	const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
838	const Image					  colorImage			(vk, device, allocator, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::Any);
839	const Unique<VkImageView>	  colorImageView		(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
840
841	// Test attachment (depth or stencil)
842	static const VkFormat stencilFormats[] =
843	{
844		// One of the following formats must be supported, as per spec requirement.
845		VK_FORMAT_S8_UINT,
846		VK_FORMAT_D16_UNORM_S8_UINT,
847		VK_FORMAT_D24_UNORM_S8_UINT,
848		VK_FORMAT_D32_SFLOAT_S8_UINT,
849	};
850
851	const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
852															: VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
853	if (testFormat == VK_FORMAT_UNDEFINED)
854		return tcu::TestStatus::fail("Required depth/stencil format not supported");
855
856	if (m_useTestAttachment)
857		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
858
859	const VkImageSubresourceRange testSubresourceRange	  = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
860	const Image					  testImage				  (vk, device, allocator, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT), MemoryRequirement::Any);
861	const Unique<VkImageView>	  testImageView			  (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
862	const VkImageView			  attachmentImages[]	  = { *colorImageView, *testImageView };
863	const deUint32				  numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
864
865	// Vertex buffer
866
867	const deUint32	   numVertices			 = 6;
868	const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
869	const Buffer	   vertexBuffer			 (vk, device, allocator, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
870
871	{
872		const Allocation& alloc = vertexBuffer.getAllocation();
873		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(alloc.getHostPtr());
874
875		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
876		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
877		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
878
879		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
880		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
881		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
882
883		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), vertexBufferSizeBytes);
884		// No barrier needed, flushed memory is automatically visible
885	}
886
887	// Result buffer
888
889	const VkDeviceSize resultBufferSizeBytes = sizeof(deUint32);
890	const Buffer resultBuffer(vk, device, allocator, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
891
892	{
893		const Allocation& alloc = resultBuffer.getAllocation();
894		deUint32* const pData = static_cast<deUint32*>(alloc.getHostPtr());
895
896		*pData = 0;
897		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
898	}
899
900	// Render result buffer (to retrieve color attachment contents)
901
902	const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
903	const Buffer	   colorBuffer			(vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
904
905	// Descriptors
906
907	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
908		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
909		.build(vk, device));
910
911	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
912		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
913		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
914
915	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
916	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
917
918	DescriptorSetUpdateBuilder()
919		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
920		.update(vk, device);
921
922	// Pipeline
923
924	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
925	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
926	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
927	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize));
928	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
929	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
930												  (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
931	const Unique<VkCommandPool>		cmdPool		  (makeCommandPool(vk, device, queueFamilyIndex));
932	const Unique<VkCommandBuffer>	cmdBuffer	  (makeCommandBuffer(vk, device, *cmdPool));
933
934	// Draw commands
935
936	{
937		const VkRect2D renderArea = {
938			makeOffset2D(0, 0),
939			makeExtent2D(renderSize.x(), renderSize.y()),
940		};
941		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
942		const VkDeviceSize vertexBufferOffset = 0ull;
943
944		beginCommandBuffer(vk, *cmdBuffer);
945
946		{
947			const VkImageMemoryBarrier barriers[] = {
948				makeImageMemoryBarrier(
949					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
950					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
951					*colorImage, colorSubresourceRange),
952				makeImageMemoryBarrier(
953					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
954					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
955					*testImage, testSubresourceRange),
956			};
957
958			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
959				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
960		}
961
962		// Will clear the attachments with specified depth and stencil values.
963		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
964
965		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
966		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
967		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
968
969		// Mask half of the attachment image with value that will pass the stencil test.
970		if (m_useTestAttachment && m_testMode == MODE_STENCIL)
971			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
972
973		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
974		endRenderPass(vk, *cmdBuffer);
975
976		{
977			const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
978				VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSizeBytes);
979
980			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
981				0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
982
983			const VkImageMemoryBarrier preCopyColorImageBarrier = makeImageMemoryBarrier(
984				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
985				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
986				*colorImage, colorSubresourceRange);
987
988			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
989				0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyColorImageBarrier);
990
991			const VkBufferImageCopy copyRegion = makeBufferImageCopy(VK_IMAGE_ASPECT_COLOR_BIT, renderSize);
992			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &copyRegion);
993
994			const VkBufferMemoryBarrier postCopyColorBufferBarrier = makeBufferMemoryBarrier(
995				VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
996
997			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
998				0u, DE_NULL, 1u, &postCopyColorBufferBarrier, 0u, DE_NULL);
999		}
1000
1001		endCommandBuffer(vk, *cmdBuffer);
1002		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1003	}
1004
1005	// Log result image
1006	{
1007		const Allocation& alloc = colorBuffer.getAllocation();
1008		invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), colorBufferSizeBytes);
1009
1010		const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, alloc.getHostPtr());
1011
1012		tcu::TestLog& log = m_context.getTestContext().getLog();
1013		log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
1014	}
1015
1016	// Verify results
1017	{
1018		const Allocation& alloc = resultBuffer.getAllocation();
1019		invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
1020
1021		const int  actualCounter	   = *static_cast<deInt32*>(alloc.getHostPtr());
1022		const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
1023		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
1024		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
1025		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
1026		const int  expectedMax		   = expectedCounter + tolerance;
1027
1028		tcu::TestLog& log = m_context.getTestContext().getLog();
1029		log << tcu::TestLog::Message << "Expected value"
1030			<< (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
1031			<< tcu::TestLog::EndMessage;
1032		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
1033
1034		if (expectedMin <= actualCounter && actualCounter <= expectedMax)
1035			return tcu::TestStatus::pass("Success");
1036		else
1037			return tcu::TestStatus::fail("Value out of range");
1038	}
1039}
1040
1041TestInstance* EarlyFragmentTest::createInstance (Context& context) const
1042{
1043	// Check required features
1044	{
1045		VkPhysicalDeviceFeatures features;
1046		context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
1047
1048		// SSBO writes in fragment shader
1049		if (!features.fragmentStoresAndAtomics)
1050			throw tcu::NotSupportedError("Missing required feature: fragmentStoresAndAtomics");
1051	}
1052
1053	return new EarlyFragmentTestInstance(context, m_flags);
1054}
1055
1056} // anonymous ns
1057
1058tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
1059{
1060	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
1061
1062	static const struct
1063	{
1064		std::string caseName;
1065		deUint32	flags;
1066	} cases[] =
1067	{
1068		{ "no_early_fragment_tests_depth",					FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
1069		{ "no_early_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
1070		{ "early_fragment_tests_depth",						FLAG_TEST_DEPTH																			},
1071		{ "early_fragment_tests_stencil",					FLAG_TEST_STENCIL																		},
1072		{ "no_early_fragment_tests_depth_no_attachment",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
1073		{ "no_early_fragment_tests_stencil_no_attachment",	FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
1074		{ "early_fragment_tests_depth_no_attachment",		FLAG_TEST_DEPTH   |										 FLAG_DONT_USE_TEST_ATTACHMENT  },
1075		{ "early_fragment_tests_stencil_no_attachment",		FLAG_TEST_STENCIL |										 FLAG_DONT_USE_TEST_ATTACHMENT	},
1076	};
1077
1078	for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1079		testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
1080
1081	return testGroup.release();
1082}
1083
1084} // pipeline
1085} // vkt
1086