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 
45 using namespace vk;
46 
47 namespace vkt
48 {
49 namespace pipeline
50 {
51 namespace
52 {
53 
54 // \note Some utility functions are general, but others are custom tailored to this test.
55 
56 class Buffer
57 {
58 public:
Buffer(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkBufferCreateInfo & bufferCreateInfo,const MemoryRequirement memoryRequirement)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 
get(void) const71 	const VkBuffer&					get				(void) const { return *m_buffer; }
operator *(void) const72 	const VkBuffer&					operator*		(void) const { return get(); }
getAllocation(void) const73 	Allocation&						getAllocation	(void) const { return *m_allocation; }
74 
75 private:
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 
84 class Image
85 {
86 public:
Image(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkImageCreateInfo & imageCreateInfo,const MemoryRequirement memoryRequirement)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 
get(void) const99 	const VkImage&					get				(void) const { return *m_image; }
operator *(void) const100 	const VkImage&					operator*		(void) const { return get(); }
getAllocation(void) const101 	Allocation&						getAllocation	(void) const { return *m_allocation; }
102 
103 private:
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 
makeImageView(const DeviceInterface & vk,const VkDevice vkDevice,const VkImage image,const VkImageViewType imageViewType,const VkFormat format,const VkImageSubresourceRange subresourceRange)112 Move<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 
makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)133 VkBufferCreateInfo 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 
makeDescriptorSet(const DeviceInterface & vk,const VkDevice device,const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout setLayout)150 Move<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 
makePipelineLayout(const DeviceInterface & vk,const VkDevice device,const VkDescriptorSetLayout descriptorSetLayout)166 Move<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 
makeCommandPool(const DeviceInterface & vk,const VkDevice device,const deUint32 queueFamilyIndex)183 Move<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 
makeCommandBuffer(const DeviceInterface & vk,const VkDevice device,const VkCommandPool commandPool)195 Move<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 
beginCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)208 void 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 
endCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)220 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
221 {
222 	VK_CHECK(vk.endCommandBuffer(commandBuffer));
223 }
224 
submitCommandsAndWait(const DeviceInterface & vk,const VkDevice device,const VkQueue queue,const VkCommandBuffer commandBuffer)225 void 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 
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkImage image,const VkImageSubresourceRange subresourceRange)255 VkImageMemoryBarrier 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 
makeBufferMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkBuffer buffer,const VkDeviceSize offset,const VkDeviceSize bufferSizeBytes)278 VkBufferMemoryBarrier 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.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)300 inline 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 
beginRenderPass(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRenderPass renderPass,const VkFramebuffer framebuffer,const VkRect2D & renderArea,const tcu::Vec4 & clearColor,const float clearDepth,const deUint32 clearStencil)323 void 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 
endRenderPass(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)351 void endRenderPass (const DeviceInterface&	vk,
352 					const VkCommandBuffer	commandBuffer)
353 {
354 	vk.cmdEndRenderPass(commandBuffer);
355 }
356 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)357 Move<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 
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const deUint32 attachmentCount,const VkImageView * pAttachments,const tcu::IVec2 size)441 Move<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 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableDepthTest,const bool enableStencilTest)463 Move<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 
makeBufferImageCopy(const VkImageAspectFlags aspectFlags,const tcu::IVec2 & renderSize)658 VkBufferImageCopy 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 
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)672 void 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 
getImageAspectFlags(const VkFormat format)695 VkImageAspectFlags 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 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)707 bool 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 
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const deUint32 numFormats,const VkFormat * pFormats)714 VkFormat 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 
725 enum 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 
733 class EarlyFragmentTest : public TestCase
734 {
735 public:
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 
743 private:
744 	const deUint32		m_flags;
745 };
746 
EarlyFragmentTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags)747 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
748 	: TestCase	(testCtx, name, "")
749 	, m_flags	(flags)
750 {
751 }
752 
initPrograms(SourceCollections & programCollection) const753 void 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 
793 class EarlyFragmentTestInstance : public TestInstance
794 {
795 public:
796 							EarlyFragmentTestInstance (Context& context, const deUint32 flags);
797 
798 	tcu::TestStatus			iterate					  (void);
799 
800 private:
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 
EarlyFragmentTestInstance(Context & context,const deUint32 flags)813 EarlyFragmentTestInstance::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 
iterate(void)823 tcu::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 
createInstance(Context & context) const1041 TestInstance* 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 
createEarlyFragmentTests(tcu::TestContext & testCtx)1058 tcu::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