Home | History | Annotate | Download | only in fragment_ops
      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 
     48 namespace vkt
     49 {
     50 namespace FragmentOperations
     51 {
     52 namespace
     53 {
     54 using namespace vk;
     55 using de::UniquePtr;
     56 
     57 //! Basic 2D image.
     58 inline 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 
     81 void 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 
    109 Move<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 
    193 Move<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 
    215 Move<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 
    410 VkBufferImageCopy 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 
    424 void 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 
    447 VkImageAspectFlags 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 
    459 bool 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 
    466 VkFormat 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 
    477 enum 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 
    485 class EarlyFragmentTest : public TestCase
    486 {
    487 public:
    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 
    495 private:
    496 	const deUint32		m_flags;
    497 };
    498 
    499 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
    500 	: TestCase	(testCtx, name, "")
    501 	, m_flags	(flags)
    502 {
    503 }
    504 
    505 void 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 
    549 class EarlyFragmentTestInstance : public TestInstance
    550 {
    551 public:
    552 							EarlyFragmentTestInstance (Context& context, const deUint32 flags);
    553 
    554 	tcu::TestStatus			iterate					  (void);
    555 
    556 private:
    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 
    569 EarlyFragmentTestInstance::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 
    579 tcu::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 
    798 TestInstance* 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 
    815 tcu::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