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 "vktFragmentOperationsEarlyFragmentTests.hpp"
26#include "vktFragmentOperationsMakeUtil.hpp"
27#include "vktTestCaseUtil.hpp"
28
29#include "vkDefs.hpp"
30#include "vkRef.hpp"
31#include "vkRefUtil.hpp"
32#include "vkPlatform.hpp"
33#include "vkPrograms.hpp"
34#include "vkMemUtil.hpp"
35#include "vkBuilderUtil.hpp"
36#include "vkStrUtil.hpp"
37#include "vkTypeUtil.hpp"
38#include "vkQueryUtil.hpp"
39#include "vkImageUtil.hpp"
40
41#include "tcuTestLog.hpp"
42
43#include "deUniquePtr.hpp"
44#include "deStringUtil.hpp"
45
46#include <string>
47
48namespace vkt
49{
50namespace FragmentOperations
51{
52namespace
53{
54using namespace vk;
55using de::UniquePtr;
56
57//! Basic 2D image.
58inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
59{
60	const VkImageCreateInfo imageParams =
61	{
62		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType;
63		DE_NULL,												// const void*				pNext;
64		(VkImageCreateFlags)0,									// VkImageCreateFlags		flags;
65		VK_IMAGE_TYPE_2D,										// VkImageType				imageType;
66		format,													// VkFormat					format;
67		makeExtent3D(size.x(), size.y(), 1),					// VkExtent3D				extent;
68		1u,														// deUint32					mipLevels;
69		1u,														// deUint32					arrayLayers;
70		VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples;
71		VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling;
72		usage,													// VkImageUsageFlags		usage;
73		VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode;
74		0u,														// deUint32					queueFamilyIndexCount;
75		DE_NULL,												// const deUint32*			pQueueFamilyIndices;
76		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			initialLayout;
77	};
78	return imageParams;
79}
80
81void beginRenderPass (const DeviceInterface&	vk,
82					  const VkCommandBuffer		commandBuffer,
83					  const VkRenderPass		renderPass,
84					  const VkFramebuffer		framebuffer,
85					  const VkRect2D&			renderArea,
86					  const tcu::Vec4&			clearColor,
87					  const float				clearDepth,
88					  const deUint32			clearStencil)
89{
90	const VkClearValue clearValues[] =
91	{
92		makeClearValueColor(clearColor),						// attachment 0
93		makeClearValueDepthStencil(clearDepth, clearStencil),	// attachment 1
94	};
95
96	const VkRenderPassBeginInfo renderPassBeginInfo = {
97		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
98		DE_NULL,										// const void*             pNext;
99		renderPass,										// VkRenderPass            renderPass;
100		framebuffer,									// VkFramebuffer           framebuffer;
101		renderArea,										// VkRect2D                renderArea;
102		DE_LENGTH_OF_ARRAY(clearValues),				// uint32_t                clearValueCount;
103		clearValues,									// const VkClearValue*     pClearValues;
104	};
105
106	vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
107}
108
109Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
110								   const VkDevice			device,
111								   const VkFormat			colorFormat,
112								   const bool				useDepthStencilAttachment,
113								   const VkFormat			depthStencilFormat)
114{
115	const VkAttachmentDescription attachments[] =
116	{
117		// color
118		{
119			(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
120			colorFormat,										// VkFormat							format;
121			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
122			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
123			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
124			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
125			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
126			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
127			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
128		},
129		// depth/stencil
130		{
131			(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
132			depthStencilFormat,									// VkFormat							format;
133			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
134			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
135			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
136			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				stencilLoadOp;
137			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				stencilStoreOp;
138			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout;
139			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout					finalLayout;
140		}
141	};
142
143	const VkAttachmentReference unusedAttachmentReference =
144	{
145		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
146		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
147	};
148
149	const VkAttachmentReference colorAttachmentReference =
150	{
151		0u,													// deUint32			attachment;
152		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
153	};
154
155	const VkAttachmentReference depthStencilAttachmentReference =
156	{
157		1u,													// deUint32			attachment;
158		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
159	};
160
161	const VkAttachmentReference* pDepthStencilAttachment = (useDepthStencilAttachment ? &depthStencilAttachmentReference : &unusedAttachmentReference);
162
163	const VkSubpassDescription subpassDescription =
164	{
165		0u,													// VkSubpassDescriptionFlags		flags;
166		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
167		0u,													// deUint32							inputAttachmentCount;
168		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
169		1u,													// deUint32							colorAttachmentCount;
170		&colorAttachmentReference,							// const VkAttachmentReference*		pColorAttachments;
171		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
172		pDepthStencilAttachment,							// const VkAttachmentReference*		pDepthStencilAttachment;
173		0u,													// deUint32							preserveAttachmentCount;
174		DE_NULL												// const deUint32*					pPreserveAttachments;
175	};
176
177	const VkRenderPassCreateInfo renderPassInfo =
178	{
179		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
180		DE_NULL,											// const void*						pNext;
181		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
182		(useDepthStencilAttachment ? 2u : 1u),				// deUint32							attachmentCount;
183		attachments,										// const VkAttachmentDescription*	pAttachments;
184		1u,													// deUint32							subpassCount;
185		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
186		0u,													// deUint32							dependencyCount;
187		DE_NULL												// const VkSubpassDependency*		pDependencies;
188	};
189
190	return createRenderPass(vk, device, &renderPassInfo);
191}
192
193Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
194									 const VkDevice				device,
195									 const VkRenderPass			renderPass,
196									 const deUint32				attachmentCount,
197									 const VkImageView*			pAttachments,
198									 const tcu::IVec2			size)
199{
200	const VkFramebufferCreateInfo framebufferInfo = {
201		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
202		DE_NULL,										// const void*                                 pNext;
203		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
204		renderPass,										// VkRenderPass                                renderPass;
205		attachmentCount,								// uint32_t                                    attachmentCount;
206		pAttachments,									// const VkImageView*                          pAttachments;
207		static_cast<deUint32>(size.x()),				// uint32_t                                    width;
208		static_cast<deUint32>(size.y()),				// uint32_t                                    height;
209		1u,												// uint32_t                                    layers;
210	};
211
212	return createFramebuffer(vk, device, &framebufferInfo);
213}
214
215Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&	vk,
216									   const VkDevice			device,
217									   const VkPipelineLayout	pipelineLayout,
218									   const VkRenderPass		renderPass,
219									   const VkShaderModule		vertexModule,
220									   const VkShaderModule		fragmentModule,
221									   const tcu::IVec2&		renderSize,
222									   const bool				enableDepthTest,
223									   const bool				enableStencilTest)
224{
225	const VkVertexInputBindingDescription vertexInputBindingDescription =
226	{
227		0u,								// uint32_t				binding;
228		sizeof(tcu::Vec4),				// uint32_t				stride;		// Vertex is a 4-element vector XYZW, position only
229		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
230	};
231
232	const VkVertexInputAttributeDescription vertexInputAttributeDescription =
233	{
234		0u,									// uint32_t			location;
235		0u,									// uint32_t			binding;
236		VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
237		0u,									// uint32_t			offset;
238	};
239
240	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
241	{
242		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType;
243		DE_NULL,													// const void*                                 pNext;
244		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags       flags;
245		1u,															// uint32_t                                    vertexBindingDescriptionCount;
246		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
247		1u,															// uint32_t                                    vertexAttributeDescriptionCount;
248		&vertexInputAttributeDescription,							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
249	};
250
251	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
252	{
253		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
254		DE_NULL,														// const void*                                 pNext;
255		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
256		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology                         topology;
257		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
258	};
259
260	const VkViewport viewport = makeViewport(
261		0.0f, 0.0f,
262		static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
263		0.0f, 1.0f);
264
265	const VkRect2D scissor = {
266		makeOffset2D(0, 0),
267		makeExtent2D(renderSize.x(), renderSize.y()),
268	};
269
270	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
271	{
272		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
273		DE_NULL,												// const void*                                 pNext;
274		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
275		1u,														// uint32_t                                    viewportCount;
276		&viewport,												// const VkViewport*                           pViewports;
277		1u,														// uint32_t                                    scissorCount;
278		&scissor,												// const VkRect2D*                             pScissors;
279	};
280
281	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
282	{
283		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
284		DE_NULL,														// const void*                              pNext;
285		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
286		VK_FALSE,														// VkBool32                                 depthClampEnable;
287		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
288		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
289		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
290		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
291		VK_FALSE,														// VkBool32									depthBiasEnable;
292		0.0f,															// float									depthBiasConstantFactor;
293		0.0f,															// float									depthBiasClamp;
294		0.0f,															// float									depthBiasSlopeFactor;
295		1.0f,															// float									lineWidth;
296	};
297
298	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
299	{
300		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
301		DE_NULL,													// const void*								pNext;
302		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
303		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
304		VK_FALSE,													// VkBool32									sampleShadingEnable;
305		0.0f,														// float									minSampleShading;
306		DE_NULL,													// const VkSampleMask*						pSampleMask;
307		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
308		VK_FALSE													// VkBool32									alphaToOneEnable;
309	};
310
311	const VkStencilOpState stencilOpState = makeStencilOpState(
312		VK_STENCIL_OP_KEEP,		// stencil fail
313		VK_STENCIL_OP_KEEP,		// depth & stencil pass
314		VK_STENCIL_OP_KEEP,		// depth only fail
315		VK_COMPARE_OP_EQUAL,	// compare op
316		1u,						// compare mask
317		1u,						// write mask
318		1u);					// reference
319
320	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
321	{
322		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
323		DE_NULL,													// const void*								pNext;
324		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
325		enableDepthTest,											// VkBool32									depthTestEnable;
326		VK_TRUE,													// VkBool32									depthWriteEnable;
327		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
328		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
329		enableStencilTest,											// VkBool32									stencilTestEnable;
330		stencilOpState,												// VkStencilOpState							front;
331		stencilOpState,												// VkStencilOpState							back;
332		0.0f,														// float									minDepthBounds;
333		1.0f,														// float									maxDepthBounds;
334	};
335
336	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
337	// Number of blend attachments must equal the number of color attachments.
338	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
339	{
340		VK_FALSE,							// VkBool32					blendEnable;
341		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcColorBlendFactor;
342		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstColorBlendFactor;
343		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
344		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcAlphaBlendFactor;
345		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstAlphaBlendFactor;
346		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
347		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
348	};
349
350	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
351	{
352		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
353		DE_NULL,													// const void*									pNext;
354		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
355		VK_FALSE,													// VkBool32										logicOpEnable;
356		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
357		1u,															// deUint32										attachmentCount;
358		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
359		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
360	};
361
362	const VkPipelineShaderStageCreateInfo pShaderStages[] =
363	{
364		{
365			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
366			DE_NULL,												// const void*							pNext;
367			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
368			VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage;
369			vertexModule,											// VkShaderModule						module;
370			"main",													// const char*							pName;
371			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
372		},
373		{
374			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
375			DE_NULL,												// const void*							pNext;
376			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
377			VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits				stage;
378			fragmentModule,											// VkShaderModule						module;
379			"main",													// const char*							pName;
380			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
381		}
382	};
383
384	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
385	{
386		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
387		DE_NULL,											// const void*										pNext;
388		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
389		DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
390		pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
391		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
392		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
393		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
394		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
395		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
396		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
397		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
398		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
399		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
400		pipelineLayout,										// VkPipelineLayout									layout;
401		renderPass,											// VkRenderPass										renderPass;
402		0u,													// deUint32											subpass;
403		DE_NULL,											// VkPipeline										basePipelineHandle;
404		0,													// deInt32											basePipelineIndex;
405	};
406
407	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
408}
409
410VkBufferImageCopy makeBufferImageCopy (const VkImageAspectFlags aspectFlags, const tcu::IVec2& renderSize)
411{
412	const VkBufferImageCopy copyParams =
413	{
414		0ull,															//	VkDeviceSize				bufferOffset;
415		0u,																//	deUint32					bufferRowLength;
416		0u,																//	deUint32					bufferImageHeight;
417		makeImageSubresourceLayers(aspectFlags, 0u, 0u, 1u),			//	VkImageSubresourceLayers	imageSubresource;
418		makeOffset3D(0, 0, 0),											//	VkOffset3D					imageOffset;
419		makeExtent3D(renderSize.x(), renderSize.y(), 1u),				//	VkExtent3D					imageExtent;
420	};
421	return copyParams;
422}
423
424void commandClearStencilAttachment (const DeviceInterface&	vk,
425									const VkCommandBuffer	commandBuffer,
426									const VkOffset2D&		offset,
427									const VkExtent2D&		extent,
428									const deUint32			clearValue)
429{
430	const VkClearAttachment stencilAttachment =
431	{
432		VK_IMAGE_ASPECT_STENCIL_BIT,					// VkImageAspectFlags    aspectMask;
433		0u,												// uint32_t              colorAttachment;
434		makeClearValueDepthStencil(0.0f, clearValue),	// VkClearValue          clearValue;
435	};
436
437	const VkClearRect rect =
438	{
439		{ offset, extent },		// VkRect2D    rect;
440		0u,						// uint32_t    baseArrayLayer;
441		1u,						// uint32_t    layerCount;
442	};
443
444	vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
445}
446
447VkImageAspectFlags getImageAspectFlags (const VkFormat format)
448{
449	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
450
451	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
452	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
453	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
454
455	DE_ASSERT(false);
456	return 0u;
457}
458
459bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
460{
461	VkFormatProperties formatProps;
462	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
463	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
464}
465
466VkFormat pickSupportedDepthStencilFormat (const InstanceInterface&	instanceInterface,
467										  const VkPhysicalDevice	device,
468										  const deUint32			numFormats,
469										  const VkFormat*			pFormats)
470{
471	for (deUint32 i = 0; i < numFormats; ++i)
472		if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
473			return pFormats[i];
474	return VK_FORMAT_UNDEFINED;
475}
476
477enum Flags
478{
479	FLAG_TEST_DEPTH							= 1u << 0,
480	FLAG_TEST_STENCIL						= 1u << 1,
481	FLAG_DONT_USE_TEST_ATTACHMENT			= 1u << 2,
482	FLAG_DONT_USE_EARLY_FRAGMENT_TESTS		= 1u << 3,
483};
484
485class EarlyFragmentTest : public TestCase
486{
487public:
488						EarlyFragmentTest	(tcu::TestContext&		testCtx,
489											 const std::string		name,
490											 const deUint32			flags);
491
492	void				initPrograms		(SourceCollections&		programCollection) const;
493	TestInstance*		createInstance		(Context&				context) const;
494
495private:
496	const deUint32		m_flags;
497};
498
499EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
500	: TestCase	(testCtx, name, "")
501	, m_flags	(flags)
502{
503}
504
505void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
506{
507	// Vertex
508	{
509		std::ostringstream src;
510		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
511			<< "\n"
512			<< "layout(location = 0) in highp vec4 position;\n"
513			<< "\n"
514			<< "out gl_PerVertex {\n"
515			<< "   vec4 gl_Position;\n"
516			<< "};\n"
517			<< "\n"
518			<< "void main (void)\n"
519			<< "{\n"
520			<< "    gl_Position = position;\n"
521			<< "}\n";
522
523		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
524	}
525
526	// Fragment
527	{
528		const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
529		std::ostringstream src;
530		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
531			<< "\n"
532			<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
533			<< "layout(location = 0) out highp vec4 fragColor;\n"
534			<< "\n"
535			<< "layout(binding = 0) coherent buffer Output {\n"
536			<< "    uint result;\n"
537			<< "} sb_out;\n"
538			<< "\n"
539			<< "void main (void)\n"
540			<< "{\n"
541			<< "    atomicAdd(sb_out.result, 1u);\n"
542			<< "	fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
543			<< "}\n";
544
545		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
546	}
547}
548
549class EarlyFragmentTestInstance : public TestInstance
550{
551public:
552							EarlyFragmentTestInstance (Context& context, const deUint32 flags);
553
554	tcu::TestStatus			iterate					  (void);
555
556private:
557	enum TestMode
558	{
559		MODE_INVALID,
560		MODE_DEPTH,
561		MODE_STENCIL,
562	};
563
564	const TestMode			m_testMode;
565	const bool				m_useTestAttachment;
566	const bool				m_useEarlyTests;
567};
568
569EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
570	: TestInstance			(context)
571	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
572							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
573	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
574	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
575{
576	DE_ASSERT(m_testMode != MODE_INVALID);
577}
578
579tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
580{
581	const DeviceInterface&		vk					= m_context.getDeviceInterface();
582	const InstanceInterface&	vki					= m_context.getInstanceInterface();
583	const VkDevice				device				= m_context.getDevice();
584	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
585	const VkQueue				queue				= m_context.getUniversalQueue();
586	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
587	Allocator&					allocator			= m_context.getDefaultAllocator();
588
589	// Color attachment
590
591	const tcu::IVec2				renderSize			= tcu::IVec2(32, 32);
592	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
593	const VkImageSubresourceRange	colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
594	const Unique<VkImage>			colorImage			(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
595	const UniquePtr<Allocation>		colorImageAlloc		(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
596	const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
597
598	// Test attachment (depth or stencil)
599	static const VkFormat stencilFormats[] =
600	{
601		// One of the following formats must be supported, as per spec requirement.
602		VK_FORMAT_S8_UINT,
603		VK_FORMAT_D16_UNORM_S8_UINT,
604		VK_FORMAT_D24_UNORM_S8_UINT,
605		VK_FORMAT_D32_SFLOAT_S8_UINT,
606	};
607
608	const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
609															: VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
610	if (testFormat == VK_FORMAT_UNDEFINED)
611		return tcu::TestStatus::fail("Required depth/stencil format not supported");
612
613	if (m_useTestAttachment)
614		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
615
616	const VkImageSubresourceRange	testSubresourceRange	= makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
617	const Unique<VkImage>			testImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
618	const UniquePtr<Allocation>		testImageAlloc			(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
619	const Unique<VkImageView>		testImageView			(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
620	const VkImageView				attachmentImages[]		= { *colorImageView, *testImageView };
621	const deUint32					numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
622
623	// Vertex buffer
624
625	const deUint32					numVertices				= 6;
626	const VkDeviceSize				vertexBufferSizeBytes	= sizeof(tcu::Vec4) * numVertices;
627	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)));
628	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
629
630	{
631		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
632
633		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
634		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
635		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
636
637		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
638		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
639		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
640
641		flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSizeBytes);
642		// No barrier needed, flushed memory is automatically visible
643	}
644
645	// Result buffer
646
647	const VkDeviceSize				resultBufferSizeBytes	= sizeof(deUint32);
648	const Unique<VkBuffer>			resultBuffer			(makeBuffer(vk, device, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)));
649	const UniquePtr<Allocation>		resultBufferAlloc		(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
650
651	{
652		deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
653
654		*pData = 0;
655		flushMappedMemoryRange(vk, device, resultBufferAlloc->getMemory(), resultBufferAlloc->getOffset(), resultBufferSizeBytes);
656	}
657
658	// Render result buffer (to retrieve color attachment contents)
659
660	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
661	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
662	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
663
664	// Descriptors
665
666	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
667		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
668		.build(vk, device));
669
670	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
671		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
672		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
673
674	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
675	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
676
677	DescriptorSetUpdateBuilder()
678		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
679		.update(vk, device);
680
681	// Pipeline
682
683	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
684	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
685	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
686	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize));
687	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
688	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
689												  (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
690	const Unique<VkCommandPool>		cmdPool		  (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
691	const Unique<VkCommandBuffer>	cmdBuffer	  (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
692
693	// Draw commands
694
695	{
696		const VkRect2D renderArea = {
697			makeOffset2D(0, 0),
698			makeExtent2D(renderSize.x(), renderSize.y()),
699		};
700		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
701		const VkDeviceSize vertexBufferOffset = 0ull;
702
703		beginCommandBuffer(vk, *cmdBuffer);
704
705		{
706			const VkImageMemoryBarrier barriers[] = {
707				makeImageMemoryBarrier(
708					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
709					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
710					*colorImage, colorSubresourceRange),
711				makeImageMemoryBarrier(
712					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
713					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
714					*testImage, testSubresourceRange),
715			};
716
717			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
718				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
719		}
720
721		// Will clear the attachments with specified depth and stencil values.
722		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
723
724		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
725		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
726		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
727
728		// Mask half of the attachment image with value that will pass the stencil test.
729		if (m_useTestAttachment && m_testMode == MODE_STENCIL)
730			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
731
732		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
733		vk.cmdEndRenderPass(*cmdBuffer);
734
735		{
736			const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
737				VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSizeBytes);
738
739			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
740				0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
741
742			const VkImageMemoryBarrier preCopyColorImageBarrier = makeImageMemoryBarrier(
743				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
744				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
745				*colorImage, colorSubresourceRange);
746
747			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
748				0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyColorImageBarrier);
749
750			const VkBufferImageCopy copyRegion = makeBufferImageCopy(VK_IMAGE_ASPECT_COLOR_BIT, renderSize);
751			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &copyRegion);
752
753			const VkBufferMemoryBarrier postCopyColorBufferBarrier = makeBufferMemoryBarrier(
754				VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
755
756			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
757				0u, DE_NULL, 1u, &postCopyColorBufferBarrier, 0u, DE_NULL);
758		}
759
760		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
761		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
762	}
763
764	// Log result image
765	{
766		invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSizeBytes);
767
768		const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
769
770		tcu::TestLog& log = m_context.getTestContext().getLog();
771		log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
772	}
773
774	// Verify results
775	{
776		invalidateMappedMemoryRange(vk, device, resultBufferAlloc->getMemory(), resultBufferAlloc->getOffset(), resultBufferSizeBytes);
777
778		const int  actualCounter	   = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
779		const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
780		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
781		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
782		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
783		const int  expectedMax		   = expectedCounter + tolerance;
784
785		tcu::TestLog& log = m_context.getTestContext().getLog();
786		log << tcu::TestLog::Message << "Expected value"
787			<< (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
788			<< tcu::TestLog::EndMessage;
789		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
790
791		if (expectedMin <= actualCounter && actualCounter <= expectedMax)
792			return tcu::TestStatus::pass("Success");
793		else
794			return tcu::TestStatus::fail("Value out of range");
795	}
796}
797
798TestInstance* EarlyFragmentTest::createInstance (Context& context) const
799{
800	// Check required features
801	{
802		VkPhysicalDeviceFeatures features;
803		context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
804
805		// SSBO writes in fragment shader
806		if (!features.fragmentStoresAndAtomics)
807			throw tcu::NotSupportedError("Missing required feature: fragmentStoresAndAtomics");
808	}
809
810	return new EarlyFragmentTestInstance(context, m_flags);
811}
812
813} // anonymous ns
814
815tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
816{
817	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
818
819	static const struct
820	{
821		std::string caseName;
822		deUint32	flags;
823	} cases[] =
824	{
825		{ "no_early_fragment_tests_depth",					FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
826		{ "no_early_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
827		{ "early_fragment_tests_depth",						FLAG_TEST_DEPTH																			},
828		{ "early_fragment_tests_stencil",					FLAG_TEST_STENCIL																		},
829		{ "no_early_fragment_tests_depth_no_attachment",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
830		{ "no_early_fragment_tests_stencil_no_attachment",	FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
831		{ "early_fragment_tests_depth_no_attachment",		FLAG_TEST_DEPTH   |										 FLAG_DONT_USE_TEST_ATTACHMENT  },
832		{ "early_fragment_tests_stencil_no_attachment",		FLAG_TEST_STENCIL |										 FLAG_DONT_USE_TEST_ATTACHMENT	},
833	};
834
835	for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
836		testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
837
838	return testGroup.release();
839}
840
841} // FragmentOperations
842} // vkt
843