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 #include "vkBarrierUtil.hpp"
     41 #include "vkCmdUtil.hpp"
     42 #include "vkObjUtil.hpp"
     43 
     44 #include "tcuTestLog.hpp"
     45 
     46 #include "deUniquePtr.hpp"
     47 #include "deStringUtil.hpp"
     48 
     49 #include <string>
     50 
     51 namespace vkt
     52 {
     53 namespace FragmentOperations
     54 {
     55 namespace
     56 {
     57 using namespace vk;
     58 using de::UniquePtr;
     59 
     60 //! Basic 2D image.
     61 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
     62 {
     63 	const VkImageCreateInfo imageParams =
     64 	{
     65 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType;
     66 		DE_NULL,												// const void*				pNext;
     67 		(VkImageCreateFlags)0,									// VkImageCreateFlags		flags;
     68 		VK_IMAGE_TYPE_2D,										// VkImageType				imageType;
     69 		format,													// VkFormat					format;
     70 		makeExtent3D(size.x(), size.y(), 1),					// VkExtent3D				extent;
     71 		1u,														// deUint32					mipLevels;
     72 		1u,														// deUint32					arrayLayers;
     73 		VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples;
     74 		VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling;
     75 		usage,													// VkImageUsageFlags		usage;
     76 		VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode;
     77 		0u,														// deUint32					queueFamilyIndexCount;
     78 		DE_NULL,												// const deUint32*			pQueueFamilyIndices;
     79 		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			initialLayout;
     80 	};
     81 	return imageParams;
     82 }
     83 
     84 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
     85 								   const VkDevice			device,
     86 								   const VkFormat			colorFormat,
     87 								   const bool				useDepthStencilAttachment,
     88 								   const VkFormat			depthStencilFormat)
     89 {
     90 	return makeRenderPass(vk, device, colorFormat, useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
     91 }
     92 
     93 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
     94 									 const VkDevice				device,
     95 									 const VkRenderPass			renderPass,
     96 									 const deUint32				attachmentCount,
     97 									 const VkImageView*			pAttachments,
     98 									 const tcu::IVec2			size)
     99 {
    100 	const VkFramebufferCreateInfo framebufferInfo = {
    101 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
    102 		DE_NULL,										// const void*                                 pNext;
    103 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
    104 		renderPass,										// VkRenderPass                                renderPass;
    105 		attachmentCount,								// uint32_t                                    attachmentCount;
    106 		pAttachments,									// const VkImageView*                          pAttachments;
    107 		static_cast<deUint32>(size.x()),				// uint32_t                                    width;
    108 		static_cast<deUint32>(size.y()),				// uint32_t                                    height;
    109 		1u,												// uint32_t                                    layers;
    110 	};
    111 
    112 	return createFramebuffer(vk, device, &framebufferInfo);
    113 }
    114 
    115 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&	vk,
    116 									   const VkDevice			device,
    117 									   const VkPipelineLayout	pipelineLayout,
    118 									   const VkRenderPass		renderPass,
    119 									   const VkShaderModule		vertexModule,
    120 									   const VkShaderModule		fragmentModule,
    121 									   const tcu::IVec2&		renderSize,
    122 									   const bool				enableDepthTest,
    123 									   const bool				enableStencilTest)
    124 {
    125 	const std::vector<VkViewport>			viewports					(1, makeViewport(renderSize));
    126 	const std::vector<VkRect2D>				scissors					(1, makeRect2D(renderSize));
    127 
    128 	const VkStencilOpState					stencilOpState				= makeStencilOpState(
    129 		VK_STENCIL_OP_KEEP,		// stencil fail
    130 		VK_STENCIL_OP_KEEP,		// depth & stencil pass
    131 		VK_STENCIL_OP_KEEP,		// depth only fail
    132 		VK_COMPARE_OP_EQUAL,	// compare op
    133 		1u,						// compare mask
    134 		1u,						// write mask
    135 		1u);					// reference
    136 
    137 	VkPipelineDepthStencilStateCreateInfo	depthStencilStateCreateInfo	=
    138 	{
    139 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType                          sType
    140 		DE_NULL,													// const void*                              pNext
    141 		0u,															// VkPipelineDepthStencilStateCreateFlags   flags
    142 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthTestEnable
    143 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthWriteEnable
    144 		VK_COMPARE_OP_LESS,											// VkCompareOp                              depthCompareOp
    145 		VK_FALSE,													// VkBool32                                 depthBoundsTestEnable
    146 		enableStencilTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 stencilTestEnable
    147 		stencilOpState,												// VkStencilOpState                         front
    148 		stencilOpState,												// VkStencilOpState                         back
    149 		0.0f,														// float                                    minDepthBounds
    150 		1.0f														// float                                    maxDepthBounds
    151 	};
    152 
    153 	return vk::makeGraphicsPipeline(vk,										// const DeviceInterface&                        vk
    154 									device,									// const VkDevice                                device
    155 									pipelineLayout,							// const VkPipelineLayout                        pipelineLayout
    156 									vertexModule,							// const VkShaderModule                          vertexShaderModule
    157 									DE_NULL,								// const VkShaderModule                          tessellationControlModule
    158 									DE_NULL,								// const VkShaderModule                          tessellationEvalModule
    159 									DE_NULL,								// const VkShaderModule                          geometryShaderModule
    160 									fragmentModule,							// const VkShaderModule                          fragmentShaderModule
    161 									renderPass,								// const VkRenderPass                            renderPass
    162 									viewports,								// const std::vector<VkViewport>&                viewports
    163 									scissors,								// const std::vector<VkRect2D>&                  scissors
    164 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
    165 									0u,										// const deUint32                                subpass
    166 									0u,										// const deUint32                                patchControlPoints
    167 									DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
    168 									DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
    169 									DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
    170 									&depthStencilStateCreateInfo);			// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
    171 }
    172 
    173 void commandClearStencilAttachment (const DeviceInterface&	vk,
    174 									const VkCommandBuffer	commandBuffer,
    175 									const VkOffset2D&		offset,
    176 									const VkExtent2D&		extent,
    177 									const deUint32			clearValue)
    178 {
    179 	const VkClearAttachment stencilAttachment =
    180 	{
    181 		VK_IMAGE_ASPECT_STENCIL_BIT,					// VkImageAspectFlags    aspectMask;
    182 		0u,												// uint32_t              colorAttachment;
    183 		makeClearValueDepthStencil(0.0f, clearValue),	// VkClearValue          clearValue;
    184 	};
    185 
    186 	const VkClearRect rect =
    187 	{
    188 		{ offset, extent },		// VkRect2D    rect;
    189 		0u,						// uint32_t    baseArrayLayer;
    190 		1u,						// uint32_t    layerCount;
    191 	};
    192 
    193 	vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
    194 }
    195 
    196 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
    197 {
    198 	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
    199 
    200 	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
    201 	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
    202 	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
    203 
    204 	DE_ASSERT(false);
    205 	return 0u;
    206 }
    207 
    208 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
    209 {
    210 	VkFormatProperties formatProps;
    211 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
    212 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
    213 }
    214 
    215 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface&	instanceInterface,
    216 										  const VkPhysicalDevice	device,
    217 										  const deUint32			numFormats,
    218 										  const VkFormat*			pFormats)
    219 {
    220 	for (deUint32 i = 0; i < numFormats; ++i)
    221 		if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
    222 			return pFormats[i];
    223 	return VK_FORMAT_UNDEFINED;
    224 }
    225 
    226 enum Flags
    227 {
    228 	FLAG_TEST_DEPTH							= 1u << 0,
    229 	FLAG_TEST_STENCIL						= 1u << 1,
    230 	FLAG_DONT_USE_TEST_ATTACHMENT			= 1u << 2,
    231 	FLAG_DONT_USE_EARLY_FRAGMENT_TESTS		= 1u << 3,
    232 };
    233 
    234 class EarlyFragmentTest : public TestCase
    235 {
    236 public:
    237 						EarlyFragmentTest	(tcu::TestContext&		testCtx,
    238 											 const std::string		name,
    239 											 const deUint32			flags);
    240 
    241 	void				initPrograms		(SourceCollections&		programCollection) const;
    242 	TestInstance*		createInstance		(Context&				context) const;
    243 
    244 private:
    245 	const deUint32		m_flags;
    246 };
    247 
    248 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
    249 	: TestCase	(testCtx, name, "")
    250 	, m_flags	(flags)
    251 {
    252 }
    253 
    254 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
    255 {
    256 	// Vertex
    257 	{
    258 		std::ostringstream src;
    259 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
    260 			<< "\n"
    261 			<< "layout(location = 0) in highp vec4 position;\n"
    262 			<< "\n"
    263 			<< "out gl_PerVertex {\n"
    264 			<< "   vec4 gl_Position;\n"
    265 			<< "};\n"
    266 			<< "\n"
    267 			<< "void main (void)\n"
    268 			<< "{\n"
    269 			<< "    gl_Position = position;\n"
    270 			<< "}\n";
    271 
    272 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
    273 	}
    274 
    275 	// Fragment
    276 	{
    277 		const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
    278 		std::ostringstream src;
    279 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
    280 			<< "\n"
    281 			<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
    282 			<< "layout(location = 0) out highp vec4 fragColor;\n"
    283 			<< "\n"
    284 			<< "layout(binding = 0) coherent buffer Output {\n"
    285 			<< "    uint result;\n"
    286 			<< "} sb_out;\n"
    287 			<< "\n"
    288 			<< "void main (void)\n"
    289 			<< "{\n"
    290 			<< "    atomicAdd(sb_out.result, 1u);\n"
    291 			<< "	fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
    292 			<< "}\n";
    293 
    294 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
    295 	}
    296 }
    297 
    298 class EarlyFragmentTestInstance : public TestInstance
    299 {
    300 public:
    301 							EarlyFragmentTestInstance (Context& context, const deUint32 flags);
    302 
    303 	tcu::TestStatus			iterate					  (void);
    304 
    305 private:
    306 	enum TestMode
    307 	{
    308 		MODE_INVALID,
    309 		MODE_DEPTH,
    310 		MODE_STENCIL,
    311 	};
    312 
    313 	const TestMode			m_testMode;
    314 	const bool				m_useTestAttachment;
    315 	const bool				m_useEarlyTests;
    316 };
    317 
    318 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
    319 	: TestInstance			(context)
    320 	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
    321 							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
    322 	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
    323 	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
    324 {
    325 	DE_ASSERT(m_testMode != MODE_INVALID);
    326 }
    327 
    328 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
    329 {
    330 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
    331 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
    332 	const VkDevice				device				= m_context.getDevice();
    333 	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
    334 	const VkQueue				queue				= m_context.getUniversalQueue();
    335 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
    336 	Allocator&					allocator			= m_context.getDefaultAllocator();
    337 
    338 	// Color attachment
    339 
    340 	const tcu::IVec2				renderSize			= tcu::IVec2(32, 32);
    341 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
    342 	const VkImageSubresourceRange	colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
    343 	const Unique<VkImage>			colorImage			(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
    344 	const UniquePtr<Allocation>		colorImageAlloc		(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
    345 	const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
    346 
    347 	// Test attachment (depth or stencil)
    348 	static const VkFormat stencilFormats[] =
    349 	{
    350 		// One of the following formats must be supported, as per spec requirement.
    351 		VK_FORMAT_S8_UINT,
    352 		VK_FORMAT_D16_UNORM_S8_UINT,
    353 		VK_FORMAT_D24_UNORM_S8_UINT,
    354 		VK_FORMAT_D32_SFLOAT_S8_UINT,
    355 	};
    356 
    357 	const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
    358 															: VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
    359 	if (testFormat == VK_FORMAT_UNDEFINED)
    360 		return tcu::TestStatus::fail("Required depth/stencil format not supported");
    361 
    362 	if (m_useTestAttachment)
    363 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
    364 
    365 	const VkImageSubresourceRange	testSubresourceRange	= makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
    366 	const Unique<VkImage>			testImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
    367 	const UniquePtr<Allocation>		testImageAlloc			(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
    368 	const Unique<VkImageView>		testImageView			(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
    369 	const VkImageView				attachmentImages[]		= { *colorImageView, *testImageView };
    370 	const deUint32					numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
    371 
    372 	// Vertex buffer
    373 
    374 	const deUint32					numVertices				= 6;
    375 	const VkDeviceSize				vertexBufferSizeBytes	= sizeof(tcu::Vec4) * numVertices;
    376 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)));
    377 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
    378 
    379 	{
    380 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
    381 
    382 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
    383 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
    384 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
    385 
    386 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
    387 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
    388 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
    389 
    390 		flushAlloc(vk, device, *vertexBufferAlloc);
    391 		// No barrier needed, flushed memory is automatically visible
    392 	}
    393 
    394 	// Result buffer
    395 
    396 	const VkDeviceSize				resultBufferSizeBytes	= sizeof(deUint32);
    397 	const Unique<VkBuffer>			resultBuffer			(makeBuffer(vk, device, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)));
    398 	const UniquePtr<Allocation>		resultBufferAlloc		(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
    399 
    400 	{
    401 		deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
    402 
    403 		*pData = 0;
    404 		flushAlloc(vk, device, *resultBufferAlloc);
    405 	}
    406 
    407 	// Render result buffer (to retrieve color attachment contents)
    408 
    409 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
    410 	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
    411 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
    412 
    413 	// Descriptors
    414 
    415 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
    416 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
    417 		.build(vk, device));
    418 
    419 	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
    420 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
    421 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
    422 
    423 	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
    424 	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
    425 
    426 	DescriptorSetUpdateBuilder()
    427 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
    428 		.update(vk, device);
    429 
    430 	// Pipeline
    431 
    432 	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
    433 	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
    434 	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
    435 	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize));
    436 	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
    437 	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
    438 												  (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
    439 	const Unique<VkCommandPool>		cmdPool		  (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
    440 	const Unique<VkCommandBuffer>	cmdBuffer	  (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
    441 
    442 	// Draw commands
    443 
    444 	{
    445 		const VkRect2D renderArea = {
    446 			makeOffset2D(0, 0),
    447 			makeExtent2D(renderSize.x(), renderSize.y()),
    448 		};
    449 		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
    450 		const VkDeviceSize vertexBufferOffset = 0ull;
    451 
    452 		beginCommandBuffer(vk, *cmdBuffer);
    453 
    454 		{
    455 			const VkImageMemoryBarrier barriers[] = {
    456 				makeImageMemoryBarrier(
    457 					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
    458 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    459 					*colorImage, colorSubresourceRange),
    460 				makeImageMemoryBarrier(
    461 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
    462 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
    463 					*testImage, testSubresourceRange),
    464 			};
    465 
    466 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
    467 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
    468 		}
    469 
    470 		// Will clear the attachments with specified depth and stencil values.
    471 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
    472 
    473 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
    474 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
    475 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
    476 
    477 		// Mask half of the attachment image with value that will pass the stencil test.
    478 		if (m_useTestAttachment && m_testMode == MODE_STENCIL)
    479 			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
    480 
    481 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
    482 		endRenderPass(vk, *cmdBuffer);
    483 
    484 		copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_SHADER_WRITE_BIT);
    485 
    486 		endCommandBuffer(vk, *cmdBuffer);
    487 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
    488 	}
    489 
    490 	// Log result image
    491 	{
    492 		invalidateAlloc(vk, device, *colorBufferAlloc);
    493 
    494 		const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
    495 
    496 		tcu::TestLog& log = m_context.getTestContext().getLog();
    497 		log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
    498 	}
    499 
    500 	// Verify results
    501 	{
    502 		invalidateAlloc(vk, device, *resultBufferAlloc);
    503 
    504 		const int  actualCounter	   = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
    505 		const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
    506 		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
    507 		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
    508 		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
    509 		const int  expectedMax		   = expectedCounter + tolerance;
    510 
    511 		tcu::TestLog& log = m_context.getTestContext().getLog();
    512 		log << tcu::TestLog::Message << "Expected value"
    513 			<< (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
    514 			<< tcu::TestLog::EndMessage;
    515 		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
    516 
    517 		if (expectedMin <= actualCounter && actualCounter <= expectedMax)
    518 			return tcu::TestStatus::pass("Success");
    519 		else
    520 			return tcu::TestStatus::fail("Value out of range");
    521 	}
    522 }
    523 
    524 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
    525 {
    526 	// Check required features
    527 	{
    528 		VkPhysicalDeviceFeatures features;
    529 		context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
    530 
    531 		// SSBO writes in fragment shader
    532 		if (!features.fragmentStoresAndAtomics)
    533 			throw tcu::NotSupportedError("Missing required feature: fragmentStoresAndAtomics");
    534 	}
    535 
    536 	return new EarlyFragmentTestInstance(context, m_flags);
    537 }
    538 
    539 } // anonymous ns
    540 
    541 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
    542 {
    543 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
    544 
    545 	static const struct
    546 	{
    547 		std::string caseName;
    548 		deUint32	flags;
    549 	} cases[] =
    550 	{
    551 		{ "no_early_fragment_tests_depth",					FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
    552 		{ "no_early_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
    553 		{ "early_fragment_tests_depth",						FLAG_TEST_DEPTH																			},
    554 		{ "early_fragment_tests_stencil",					FLAG_TEST_STENCIL																		},
    555 		{ "no_early_fragment_tests_depth_no_attachment",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
    556 		{ "no_early_fragment_tests_stencil_no_attachment",	FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
    557 		{ "early_fragment_tests_depth_no_attachment",		FLAG_TEST_DEPTH   |										 FLAG_DONT_USE_TEST_ATTACHMENT	},
    558 		{ "early_fragment_tests_stencil_no_attachment",		FLAG_TEST_STENCIL |										 FLAG_DONT_USE_TEST_ATTACHMENT	},
    559 	};
    560 
    561 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
    562 		testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
    563 
    564 	return testGroup.release();
    565 }
    566 
    567 } // FragmentOperations
    568 } // vkt
    569