Home | History | Annotate | Download | only in pipeline
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 The Khronos Group Inc.
      6  * Copyright (c) 2015 Imagination Technologies Ltd.
      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 Stencil Tests
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktPipelineStencilTests.hpp"
     26 #include "vktPipelineClearUtil.hpp"
     27 #include "vktPipelineImageUtil.hpp"
     28 #include "vktPipelineVertexUtil.hpp"
     29 #include "vktPipelineReferenceRenderer.hpp"
     30 #include "vktPipelineUniqueRandomIterator.hpp"
     31 #include "vktTestCase.hpp"
     32 #include "vkImageUtil.hpp"
     33 #include "vkMemUtil.hpp"
     34 #include "vkPrograms.hpp"
     35 #include "vkQueryUtil.hpp"
     36 #include "vkRef.hpp"
     37 #include "vkRefUtil.hpp"
     38 #include "vkTypeUtil.hpp"
     39 #include "tcuImageCompare.hpp"
     40 #include "deMemory.h"
     41 #include "deRandom.hpp"
     42 #include "deStringUtil.hpp"
     43 #include "deUniquePtr.hpp"
     44 
     45 #include <algorithm>
     46 #include <sstream>
     47 #include <vector>
     48 
     49 namespace vkt
     50 {
     51 namespace pipeline
     52 {
     53 
     54 using namespace vk;
     55 
     56 namespace
     57 {
     58 
     59 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
     60 {
     61 	VkFormatProperties formatProps;
     62 
     63 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
     64 
     65 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
     66 }
     67 
     68 class StencilOpStateUniqueRandomIterator : public UniqueRandomIterator<VkStencilOpState>
     69 {
     70 public:
     71 								StencilOpStateUniqueRandomIterator	(int seed);
     72 	virtual						~StencilOpStateUniqueRandomIterator	(void) {}
     73 	virtual VkStencilOpState	getIndexedValue (deUint32 index);
     74 
     75 private:
     76 	const static VkStencilOp	m_stencilOps[];
     77 	const static VkCompareOp	m_compareOps[];
     78 
     79 	// Pre-calculated constants
     80 	const static deUint32		m_stencilOpsLength;
     81 	const static deUint32		m_stencilOpsLength2;
     82 	const static deUint32		m_stencilOpsLength3;
     83 	const static deUint32		m_compareOpsLength;
     84 
     85 	// Total number of cross-combinations of (stencilFailOp x stencilPassOp x stencilDepthFailOp x stencilCompareOp)
     86 	const static deUint32		m_totalStencilOpStates;
     87 };
     88 
     89 
     90 class StencilTest : public vkt::TestCase
     91 {
     92 public:
     93 	enum
     94 	{
     95 		QUAD_COUNT = 4
     96 	};
     97 
     98 	struct StencilStateConfig
     99 	{
    100 		deUint32	frontReadMask;
    101 		deUint32	frontWriteMask;
    102 		deUint32	frontRef;
    103 
    104 		deUint32	backReadMask;
    105 		deUint32	backWriteMask;
    106 		deUint32	backRef;
    107 	};
    108 
    109 	const static StencilStateConfig			s_stencilStateConfigs[QUAD_COUNT];
    110 	const static float						s_quadDepths[QUAD_COUNT];
    111 
    112 
    113 											StencilTest				(tcu::TestContext&			testContext,
    114 																	 const std::string&			name,
    115 																	 const std::string&			description,
    116 																	 VkFormat					stencilFormat,
    117 																	 const VkStencilOpState&	stencilOpStateFront,
    118 																	 const VkStencilOpState&	stencilOpStateBack);
    119 	virtual									~StencilTest			(void);
    120 	virtual void							initPrograms			(SourceCollections& sourceCollections) const;
    121 	virtual TestInstance*					createInstance			(Context& context) const;
    122 
    123 private:
    124 	VkFormat								m_stencilFormat;
    125 	const VkStencilOpState					m_stencilOpStateFront;
    126 	const VkStencilOpState					m_stencilOpStateBack;
    127 };
    128 
    129 class StencilTestInstance : public vkt::TestInstance
    130 {
    131 public:
    132 										StencilTestInstance		(Context&					context,
    133 																 VkFormat					stencilFormat,
    134 																 const VkStencilOpState&	stencilOpStatesFront,
    135 																 const VkStencilOpState&	stencilOpStatesBack);
    136 	virtual								~StencilTestInstance	(void);
    137 	virtual tcu::TestStatus				iterate					(void);
    138 
    139 private:
    140 	tcu::TestStatus						verifyImage				(void);
    141 
    142 	VkStencilOpState					m_stencilOpStateFront;
    143 	VkStencilOpState					m_stencilOpStateBack;
    144 	const tcu::UVec2					m_renderSize;
    145 	const VkFormat						m_colorFormat;
    146 	const VkFormat						m_stencilFormat;
    147 	VkImageSubresourceRange				m_stencilImageSubresourceRange;
    148 
    149 	VkImageCreateInfo					m_colorImageCreateInfo;
    150 	Move<VkImage>						m_colorImage;
    151 	de::MovePtr<Allocation>				m_colorImageAlloc;
    152 	Move<VkImage>						m_stencilImage;
    153 	de::MovePtr<Allocation>				m_stencilImageAlloc;
    154 	Move<VkImageView>					m_colorAttachmentView;
    155 	Move<VkImageView>					m_stencilAttachmentView;
    156 	Move<VkRenderPass>					m_renderPass;
    157 	Move<VkFramebuffer>					m_framebuffer;
    158 
    159 	Move<VkShaderModule>				m_vertexShaderModule;
    160 	Move<VkShaderModule>				m_fragmentShaderModule;
    161 
    162 	Move<VkBuffer>						m_vertexBuffer;
    163 	std::vector<Vertex4RGBA>			m_vertices;
    164 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
    165 
    166 	Move<VkPipelineLayout>				m_pipelineLayout;
    167 	Move<VkPipeline>					m_graphicsPipelines[StencilTest::QUAD_COUNT];
    168 
    169 	Move<VkCommandPool>					m_cmdPool;
    170 	Move<VkCommandBuffer>				m_cmdBuffer;
    171 
    172 	Move<VkFence>						m_fence;
    173 };
    174 
    175 
    176 // StencilOpStateUniqueRandomIterator
    177 
    178 const VkStencilOp StencilOpStateUniqueRandomIterator::m_stencilOps[] =
    179 {
    180 	VK_STENCIL_OP_KEEP,
    181 	VK_STENCIL_OP_ZERO,
    182 	VK_STENCIL_OP_REPLACE,
    183 	VK_STENCIL_OP_INCREMENT_AND_CLAMP,
    184 	VK_STENCIL_OP_DECREMENT_AND_CLAMP,
    185 	VK_STENCIL_OP_INVERT,
    186 	VK_STENCIL_OP_INCREMENT_AND_WRAP,
    187 	VK_STENCIL_OP_DECREMENT_AND_WRAP
    188 };
    189 
    190 const VkCompareOp StencilOpStateUniqueRandomIterator::m_compareOps[] =
    191 {
    192 	VK_COMPARE_OP_NEVER,
    193 	VK_COMPARE_OP_LESS,
    194 	VK_COMPARE_OP_EQUAL,
    195 	VK_COMPARE_OP_LESS_OR_EQUAL,
    196 	VK_COMPARE_OP_GREATER,
    197 	VK_COMPARE_OP_NOT_EQUAL,
    198 	VK_COMPARE_OP_GREATER_OR_EQUAL,
    199 	VK_COMPARE_OP_ALWAYS
    200 };
    201 
    202 const deUint32 StencilOpStateUniqueRandomIterator::m_stencilOpsLength		= DE_LENGTH_OF_ARRAY(m_stencilOps);
    203 const deUint32 StencilOpStateUniqueRandomIterator::m_stencilOpsLength2		= m_stencilOpsLength * m_stencilOpsLength;
    204 const deUint32 StencilOpStateUniqueRandomIterator::m_stencilOpsLength3		= m_stencilOpsLength2 * m_stencilOpsLength;
    205 const deUint32 StencilOpStateUniqueRandomIterator::m_compareOpsLength		= DE_LENGTH_OF_ARRAY(m_compareOps);
    206 const deUint32 StencilOpStateUniqueRandomIterator::m_totalStencilOpStates	= m_stencilOpsLength3 * m_compareOpsLength;
    207 
    208 StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator (int seed)
    209 	: UniqueRandomIterator<VkStencilOpState>(m_totalStencilOpStates, m_totalStencilOpStates, seed)
    210 {
    211 }
    212 
    213 VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue (deUint32 index)
    214 {
    215 	const deUint32 stencilCompareOpIndex = index / m_stencilOpsLength3;
    216 	const deUint32 stencilCompareOpSeqIndex = stencilCompareOpIndex * m_stencilOpsLength3;
    217 
    218 	const deUint32 stencilDepthFailOpIndex = (index - stencilCompareOpSeqIndex) / m_stencilOpsLength2;
    219 	const deUint32 stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * m_stencilOpsLength2;
    220 
    221 	const deUint32 stencilPassOpIndex = (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / m_stencilOpsLength;
    222 	const deUint32 stencilPassOpSeqIndex = stencilPassOpIndex * m_stencilOpsLength;
    223 
    224 	const deUint32 stencilFailOpIndex = index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
    225 
    226 	const VkStencilOpState stencilOpState =
    227 	{
    228 		m_stencilOps[stencilFailOpIndex],		// VkStencilOp	failOp;
    229 		m_stencilOps[stencilPassOpIndex],		// VkStencilOp	passOp;
    230 		m_stencilOps[stencilDepthFailOpIndex],	// VkStencilOp	depthFailOp;
    231 		m_compareOps[stencilCompareOpIndex],	// VkCompareOp	compareOp;
    232 		0x0,									// deUint32		compareMask;
    233 		0x0,									// deUint32		writeMask;
    234 		0x0										// deUint32		reference;
    235 	};
    236 
    237 	return stencilOpState;
    238 }
    239 
    240 
    241 // StencilTest
    242 
    243 const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] =
    244 {
    245 	//	frontReadMask	frontWriteMask		frontRef		backReadMask	backWriteMask	backRef
    246 	{	0xFF,			0xFF,				0xAB,			0xF0,			0xFF,			0xFF	},
    247 	{	0xFF,			0xF0,				0xCD,			0xF0,			0xF0,			0xEF	},
    248 	{	0xF0,			0x0F,				0xEF,			0xFF,			0x0F,			0xCD	},
    249 	{	0xF0,			0x01,				0xFF,			0xFF,			0x01,			0xAB	}
    250 };
    251 
    252 const float StencilTest::s_quadDepths[QUAD_COUNT] =
    253 {
    254 	0.1f,
    255 	0.0f,
    256 	0.3f,
    257 	0.2f
    258 };
    259 
    260 StencilTest::StencilTest (tcu::TestContext&			testContext,
    261 						  const std::string&		name,
    262 						  const std::string&		description,
    263 						  VkFormat					stencilFormat,
    264 						  const VkStencilOpState&	stencilOpStateFront,
    265 						  const VkStencilOpState&	stencilOpStateBack)
    266 	: vkt::TestCase			(testContext, name, description)
    267 	, m_stencilFormat		(stencilFormat)
    268 	, m_stencilOpStateFront	(stencilOpStateFront)
    269 	, m_stencilOpStateBack	(stencilOpStateBack)
    270 {
    271 }
    272 
    273 StencilTest::~StencilTest (void)
    274 {
    275 }
    276 
    277 TestInstance* StencilTest::createInstance (Context& context) const
    278 {
    279 	return new StencilTestInstance(context, m_stencilFormat, m_stencilOpStateFront, m_stencilOpStateBack);
    280 }
    281 
    282 void StencilTest::initPrograms (SourceCollections& sourceCollections) const
    283 {
    284 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
    285 		"#version 310 es\n"
    286 		"layout(location = 0) in vec4 position;\n"
    287 		"layout(location = 1) in vec4 color;\n"
    288 		"layout(location = 0) out highp vec4 vtxColor;\n"
    289 		"void main (void)\n"
    290 		"{\n"
    291 		"	gl_Position = position;\n"
    292 		"	vtxColor = color;\n"
    293 		"}\n");
    294 
    295 	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
    296 		"#version 310 es\n"
    297 		"layout(location = 0) in highp vec4 vtxColor;\n"
    298 		"layout(location = 0) out highp vec4 fragColor;\n"
    299 		"void main (void)\n"
    300 		"{\n"
    301 		"	fragColor = vtxColor;\n"
    302 		"}\n");
    303 }
    304 
    305 
    306 // StencilTestInstance
    307 
    308 StencilTestInstance::StencilTestInstance (Context&					context,
    309 										  VkFormat					stencilFormat,
    310 										  const VkStencilOpState&	stencilOpStateFront,
    311 										  const VkStencilOpState&	stencilOpStateBack)
    312 	: vkt::TestInstance		(context)
    313 	, m_stencilOpStateFront	(stencilOpStateFront)
    314 	, m_stencilOpStateBack	(stencilOpStateBack)
    315 	, m_renderSize			(32, 32)
    316 	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
    317 	, m_stencilFormat		(stencilFormat)
    318 {
    319 	const DeviceInterface&		vk						= context.getDeviceInterface();
    320 	const VkDevice				vkDevice				= context.getDevice();
    321 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
    322 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
    323 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
    324 
    325 	// Create color image
    326 	{
    327 		const VkImageCreateInfo colorImageParams =
    328 		{
    329 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
    330 			DE_NULL,																	// const void*				pNext;
    331 			0u,																			// VkImageCreateFlags		flags;
    332 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
    333 			m_colorFormat,																// VkFormat					format;
    334 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
    335 			1u,																			// deUint32					mipLevels;
    336 			1u,																			// deUint32					arrayLayers;
    337 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
    338 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
    339 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
    340 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
    341 			1u,																			// deUint32					queueFamilyIndexCount;
    342 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
    343 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
    344 		};
    345 
    346 		m_colorImageCreateInfo	= colorImageParams;
    347 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
    348 
    349 		// Allocate and bind color image memory
    350 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
    351 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
    352 	}
    353 
    354 	// Create stencil image
    355 	{
    356 		// Check format support
    357 		if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_stencilFormat))
    358 			throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") + getFormatName(m_stencilFormat));
    359 
    360 		const VkImageCreateInfo stencilImageParams =
    361 		{
    362 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
    363 			DE_NULL,										// const void*				pNext;
    364 			0u,												// VkImageCreateFlags		flags;
    365 			VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
    366 			m_stencilFormat,								// VkFormat					format;
    367 			{ m_renderSize.x(), m_renderSize.y(), 1u },		// VkExtent3D				extent;
    368 			1u,												// deUint32					mipLevels;
    369 			1u,												// deUint32					arrayLayers;
    370 			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
    371 			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
    372 			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,	// VkImageUsageFlags		usage;
    373 			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
    374 			1u,												// deUint32					queueFamilyIndexCount;
    375 			&queueFamilyIndex,								// const deUint32*			pQueueFamilyIndices;
    376 			VK_IMAGE_LAYOUT_UNDEFINED						// VkImageLayout			initialLayout;
    377 		};
    378 
    379 		m_stencilImage = createImage(vk, vkDevice, &stencilImageParams);
    380 
    381 		// Allocate and bind stencil image memory
    382 		m_stencilImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_stencilImage), MemoryRequirement::Any);
    383 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_stencilImage, m_stencilImageAlloc->getMemory(), m_stencilImageAlloc->getOffset()));
    384 
    385 		const VkImageAspectFlags aspect = (mapVkFormat(m_stencilFormat).order == tcu::TextureFormat::DS ? VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT
    386 																										: VK_IMAGE_ASPECT_STENCIL_BIT);
    387 		m_stencilImageSubresourceRange  = makeImageSubresourceRange(aspect, 0u, stencilImageParams.mipLevels, 0u, stencilImageParams.arrayLayers);
    388 	}
    389 
    390 	// Create color attachment view
    391 	{
    392 		const VkImageViewCreateInfo colorAttachmentViewParams =
    393 		{
    394 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
    395 			DE_NULL,											// const void*				pNext;
    396 			0u,													// VkImageViewCreateFlags	flags;
    397 			*m_colorImage,										// VkImage					image;
    398 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
    399 			m_colorFormat,										// VkFormat					format;
    400 			componentMappingRGBA,								// VkComponentMapping		components;
    401 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
    402 		};
    403 
    404 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
    405 	}
    406 
    407 	// Create stencil attachment view
    408 	{
    409 		const VkImageViewCreateInfo stencilAttachmentViewParams =
    410 		{
    411 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
    412 			DE_NULL,											// const void*				pNext;
    413 			0u,													// VkImageViewCreateFlags	flags;
    414 			*m_stencilImage,									// VkImage					image;
    415 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
    416 			m_stencilFormat,									// VkFormat					format;
    417 			componentMappingRGBA,								// VkComponentMapping		components;
    418 			m_stencilImageSubresourceRange,						// VkImageSubresourceRange	subresourceRange;
    419 		};
    420 
    421 		m_stencilAttachmentView = createImageView(vk, vkDevice, &stencilAttachmentViewParams);
    422 	}
    423 
    424 	// Create render pass
    425 	{
    426 		const VkAttachmentDescription colorAttachmentDescription =
    427 		{
    428 			0u,													// VkAttachmentDescriptionFlags	flags;
    429 			m_colorFormat,										// VkFormat						format;
    430 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits		samples;
    431 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp			loadOp;
    432 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp			storeOp;
    433 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp			stencilLoadOp;
    434 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp			stencilStoreOp;
    435 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				initialLayout;
    436 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				finalLayout;
    437 		};
    438 
    439 		const VkAttachmentDescription stencilAttachmentDescription =
    440 		{
    441 			0u,													// VkAttachmentDescriptionFlags	flags;
    442 			m_stencilFormat,									// VkFormat						format;
    443 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits		samples;
    444 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp			loadOp;
    445 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp			storeOp;
    446 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp			stencilLoadOp;
    447 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp			stencilStoreOp;
    448 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout				initialLayout;
    449 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout				finalLayout;
    450 		};
    451 
    452 		const VkAttachmentDescription attachments[2] =
    453 		{
    454 			colorAttachmentDescription,
    455 			stencilAttachmentDescription
    456 		};
    457 
    458 		const VkAttachmentReference colorAttachmentReference =
    459 		{
    460 			0u,													// deUint32			attachment;
    461 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
    462 		};
    463 
    464 		const VkAttachmentReference stencilAttachmentReference =
    465 		{
    466 			1u,													// deUint32			attachment;
    467 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
    468 		};
    469 
    470 		const VkSubpassDescription subpassDescription =
    471 		{
    472 			0u,													// VkSubpassDescriptionFlags	flags;
    473 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
    474 			0u,													// deUint32						inputAttachmentCount;
    475 			DE_NULL,											// const VkAttachmentReference*	pInputAttachments;
    476 			1u,													// deUint32						colorAttachmentCount;
    477 			&colorAttachmentReference,							// const VkAttachmentReference*	pColorAttachments;
    478 			DE_NULL,											// const VkAttachmentReference*	pResolveAttachments;
    479 			&stencilAttachmentReference,						// const VkAttachmentReference*	pDepthStencilAttachment;
    480 			0u,													// deUint32						preserveAttachmentCount;
    481 			DE_NULL												// const VkAttachmentReference*	pPreserveAttachments;
    482 		};
    483 
    484 		const VkRenderPassCreateInfo renderPassParams =
    485 		{
    486 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
    487 			DE_NULL,											// const void*						pNext;
    488 			0u,													// VkRenderPassCreateFlags			flags;
    489 			2u,													// deUint32							attachmentCount;
    490 			attachments,										// const VkAttachmentDescription*	pAttachments;
    491 			1u,													// deUint32							subpassCount;
    492 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
    493 			0u,													// deUint32							dependencyCount;
    494 			DE_NULL												// const VkSubpassDependency*		pDependencies;
    495 		};
    496 
    497 		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
    498 	}
    499 
    500 	// Create framebuffer
    501 	{
    502 		const VkImageView attachmentBindInfos[2] = { *m_colorAttachmentView, *m_stencilAttachmentView };
    503 
    504 		const VkFramebufferCreateInfo framebufferParams =
    505 		{
    506 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
    507 			DE_NULL,											// const void*				pNext;
    508 			0u,													// VkFramebufferCreateFlags	flags;
    509 			*m_renderPass,										// VkRenderPass				renderPass;
    510 			2u,													// deUint32					attachmentCount;
    511 			attachmentBindInfos,								// const VkImageView*		pAttachments;
    512 			(deUint32)m_renderSize.x(),							// deUint32					width;
    513 			(deUint32)m_renderSize.y(),							// deUint32					height;
    514 			1u													// deUint32					layers;
    515 		};
    516 
    517 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
    518 	}
    519 
    520 	// Create pipeline layout
    521 	{
    522 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
    523 		{
    524 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
    525 			DE_NULL,											// const void*					pNext;
    526 			0u,													// VkPipelineLayoutCreateFlags	flags;
    527 			0u,													// deUint32						setLayoutCount;
    528 			DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
    529 			0u,													// deUint32						pushConstantRangeCount;
    530 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
    531 		};
    532 
    533 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
    534 	}
    535 
    536 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
    537 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
    538 
    539 	// Create pipeline
    540 	{
    541 		const VkPipelineShaderStageCreateInfo shaderStages[2] =
    542 		{
    543 			{
    544 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    545 				DE_NULL,													// const void*							pNext;
    546 				0u,															// VkPipelineShaderStageCreateFlags		flags;
    547 				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
    548 				*m_vertexShaderModule,										// VkShaderModule						module;
    549 				"main",														// const char*							pName;
    550 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
    551 			},
    552 			{
    553 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    554 				DE_NULL,													// const void*							pNext;
    555 				0u,															// VkPipelineShaderStageCreateFlags		flags;
    556 				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
    557 				*m_fragmentShaderModule,									// VkShaderModule						module;
    558 				"main",														// const char*							pName;
    559 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
    560 			}
    561 		};
    562 
    563 		const VkVertexInputBindingDescription vertexInputBindingDescription =
    564 		{
    565 			0u,										// deUint32					binding;
    566 			sizeof(Vertex4RGBA),					// deUint32					strideInBytes;
    567 			VK_VERTEX_INPUT_RATE_VERTEX				// VkVertexInputStepRate	inputRate;
    568 		};
    569 
    570 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
    571 		{
    572 			{
    573 				0u,									// deUint32	location;
    574 				0u,									// deUint32	binding;
    575 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
    576 				0u									// deUint32	offsetInBytes;
    577 			},
    578 			{
    579 				1u,									// deUint32	location;
    580 				0u,									// deUint32	binding;
    581 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
    582 				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offsetInBytes;
    583 			}
    584 		};
    585 
    586 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
    587 		{
    588 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
    589 			DE_NULL,														// const void*								pNext;
    590 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
    591 			1u,																// deUint32									vertexBindingDescriptionCount;
    592 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
    593 			2u,																// deUint32									vertexAttributeDescriptionCount;
    594 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
    595 		};
    596 
    597 		const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
    598 		{
    599 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
    600 			DE_NULL,														// const void*								pNext;
    601 			0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
    602 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
    603 			false															// VkBool32									primitiveRestartEnable;
    604 		};
    605 
    606 		const VkViewport viewport =
    607 		{
    608 			0.0f,						// float	x;
    609 			0.0f,						// float	y;
    610 			(float)m_renderSize.x(),	// float	width;
    611 			(float)m_renderSize.y(),	// float	height;
    612 			0.0f,						// float	minDepth;
    613 			1.0f						// float	maxDepth;
    614 		};
    615 
    616 		const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
    617 
    618 		const VkPipelineViewportStateCreateInfo viewportStateParams =
    619 		{
    620 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
    621 			DE_NULL,														// const void*							pNext;
    622 			0u,																// VkPipelineViewportStateCreateFlags	flags;
    623 			1u,																// deUint32								viewportCount;
    624 			&viewport,														// const VkViewport*					pViewports;
    625 			1u,																// deUint32								scissorCount;
    626 			&scissor,														// const VkRect2D*						pScissors;
    627 		};
    628 
    629 		const VkPipelineRasterizationStateCreateInfo rasterStateParams =
    630 		{
    631 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
    632 			DE_NULL,														// const void*								pNext;
    633 			0u,																// VkPipelineRasterizationStateCreateFlags	flags;
    634 			false,															// VkBool32									depthClampEnable;
    635 			false,															// VkBool32									rasterizerDiscardEnable;
    636 			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
    637 			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
    638 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
    639 			false,															// VkBool32									depthBiasEnable;
    640 			0.0f,															// float									depthBiasConstantFactor;
    641 			0.0f,															// float									depthBiasClamp;
    642 			0.0f,															// float									depthBiasSlopeFactor;
    643 			1.0f															// float									lineWidth;
    644 		};
    645 
    646 		const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
    647 		{
    648 			false,															// VkBool32					blendEnable;
    649 			VK_BLEND_FACTOR_ONE,											// VkBlendFactor			srcColorBlendFactor;
    650 			VK_BLEND_FACTOR_ZERO,											// VkBlendFactor			dstColorBlendFactor;
    651 			VK_BLEND_OP_ADD,												// VkBlendOp				colorBlendOp;
    652 			VK_BLEND_FACTOR_ONE,											// VKBLENDFACTOR			SRCALPHABLENDFACTOR;
    653 			VK_BLEND_FACTOR_ZERO,											// VkBlendFactor			dstAlphaBlendFactor;
    654 			VK_BLEND_OP_ADD,												// VkBlendOp				alphaBlendOp;
    655 			VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |			// VkColorComponentFlags	colorWriteMask;
    656 				VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
    657 		};
    658 
    659 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
    660 		{
    661 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
    662 			DE_NULL,													// const void*									pNext;
    663 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
    664 			false,														// VkBool32										logicOpEnable;
    665 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
    666 			1u,															// deUint32										attachmentCount;
    667 			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
    668 			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
    669 		};
    670 
    671 		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
    672 		{
    673 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
    674 			DE_NULL,													// const void*								pNext;
    675 			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
    676 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
    677 			false,														// VkBool32									sampleShadingEnable;
    678 			0.0f,														// float									minSampleShading;
    679 			DE_NULL,													// const VkSampleMask*						pSampleMask;
    680 			false,														// VkBool32									alphaToCoverageEnable;
    681 			false														// VkBool32									alphaToOneEnable;
    682 		};
    683 
    684 		const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
    685 
    686 		VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
    687 		{
    688 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
    689 			DE_NULL,													// const void*								pNext;
    690 			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
    691 			isDepthEnabled,												// VkBool32									depthTestEnable;
    692 			isDepthEnabled,												// VkBool32									depthWriteEnable;
    693 			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
    694 			false,														// VkBool32									depthBoundsTestEnable;
    695 			true,														// VkBool32									stencilTestEnable;
    696 			m_stencilOpStateFront,										// VkStencilOpState							front;
    697 			m_stencilOpStateBack,										// VkStencilOpState							back;
    698 			0.0f,														// float									minDepthBounds;
    699 			1.0f														// float									maxDepthBounds;
    700 		};
    701 
    702 		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
    703 		{
    704 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
    705 			DE_NULL,											// const void*										pNext;
    706 			0u,													// VkPipelineCreateFlags							flags;
    707 			2u,													// deUint32											stageCount;
    708 			shaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
    709 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
    710 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
    711 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
    712 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
    713 			&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
    714 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
    715 			&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
    716 			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
    717 			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
    718 			*m_pipelineLayout,									// VkPipelineLayout									layout;
    719 			*m_renderPass,										// VkRenderPass										renderPass;
    720 			0u,													// deUint32											subpass;
    721 			0u,													// VkPipeline										basePipelineHandle;
    722 			0u													// deInt32											basePipelineIndex;
    723 		};
    724 
    725 		// Setup different stencil masks and refs in each quad
    726 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
    727 		{
    728 			const StencilTest::StencilStateConfig&	config	= StencilTest::s_stencilStateConfigs[quadNdx];
    729 			VkStencilOpState&						front	= depthStencilStateParams.front;
    730 			VkStencilOpState&						back	= depthStencilStateParams.back;
    731 
    732 			front.compareMask	= config.frontReadMask;
    733 			front.writeMask		= config.frontWriteMask;
    734 			front.reference		= config.frontRef;
    735 
    736 			back.compareMask	= config.backReadMask;
    737 			back.writeMask		= config.backWriteMask;
    738 			back.reference		= config.backRef;
    739 
    740 			m_graphicsPipelines[quadNdx] = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
    741 		}
    742 	}
    743 
    744 
    745 	// Create vertex buffer
    746 	{
    747 		const VkBufferCreateInfo vertexBufferParams =
    748 		{
    749 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    750 			DE_NULL,									// const void*			pNext;
    751 			0u,											// VkBufferCreateFlags	flags;
    752 			1024u,										// VkDeviceSize			size;
    753 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    754 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    755 			1u,											// deUint32				queueFamilyIndexCount;
    756 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    757 		};
    758 
    759 		m_vertices			= createOverlappingQuads();
    760 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
    761 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
    762 
    763 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
    764 
    765 		// Adjust depths
    766 		for (int quadNdx = 0; quadNdx < 4; quadNdx++)
    767 			for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
    768 				m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
    769 
    770 		// Load vertices into vertex buffer
    771 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
    772 
    773 		const VkMappedMemoryRange flushRange =
    774 		{
    775 				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// VkStructureType	sType;
    776 				DE_NULL,								// const void*		pNext;
    777 				m_vertexBufferAlloc->getMemory(),		// VkDeviceMemory	memory;
    778 				m_vertexBufferAlloc->getOffset(),		// VkDeviceSize		offset;
    779 				vertexBufferParams.size					// VkDeviceSize		size;
    780 		};
    781 
    782 		vk.flushMappedMemoryRanges(vkDevice, 1, &flushRange);
    783 	}
    784 
    785 	// Create command pool
    786 	{
    787 		const VkCommandPoolCreateInfo cmdPoolParams =
    788 		{
    789 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType			sType;
    790 			DE_NULL,										// const void*				pNext;
    791 			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags	flags;
    792 			queueFamilyIndex,								// deUint32					queueFamilyIndex;
    793 		};
    794 
    795 		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
    796 	}
    797 
    798 	// Create command buffer
    799 	{
    800 		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
    801 		{
    802 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType		sType;
    803 			DE_NULL,										// const void*			pNext;
    804 			*m_cmdPool,										// VkCommandPool		commandPool;
    805 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel	level;
    806 			1u												// deUint32				bufferCount;
    807 		};
    808 
    809 		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
    810 		{
    811 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
    812 			DE_NULL,										// const void*						pNext;
    813 			0u,												// VkCommandBufferUsageFlags		flags;
    814 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
    815 		};
    816 
    817 		const VkClearValue attachmentClearValues[2] =
    818 		{
    819 			defaultClearValue(m_colorFormat),
    820 			defaultClearValue(m_stencilFormat)
    821 		};
    822 
    823 		const VkRenderPassBeginInfo renderPassBeginInfo =
    824 		{
    825 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
    826 			DE_NULL,												// const void*			pNext;
    827 			*m_renderPass,											// VkRenderPass			renderPass;
    828 			*m_framebuffer,											// VkFramebuffer		framebuffer;
    829 			{ { 0, 0 } , { m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
    830 			2,														// deUint32				clearValueCount;
    831 			attachmentClearValues									// const VkClearValue*	pClearValues;
    832 		};
    833 
    834 		const VkImageMemoryBarrier imageLayoutBarriers[] =
    835 		{
    836 			// color image layout transition
    837 			{
    838 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
    839 				DE_NULL,																// const void*                pNext;
    840 				(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
    841 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									// VkAccessFlags              dstAccessMask;
    842 				VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
    843 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout              newLayout;
    844 				VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
    845 				VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
    846 				*m_colorImage,															// VkImage                    image;
    847 				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }							// VkImageSubresourceRange    subresourceRange;
    848 			},
    849 			// stencil image layout transition
    850 			{
    851 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
    852 				DE_NULL,																// const void*                pNext;
    853 				(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
    854 				VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,							// VkAccessFlags              dstAccessMask;
    855 				VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
    856 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,						// VkImageLayout              newLayout;
    857 				VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
    858 				VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
    859 				*m_stencilImage,														// VkImage                    image;
    860 				m_stencilImageSubresourceRange,											// VkImageSubresourceRange    subresourceRange;
    861 			},
    862 		};
    863 
    864 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
    865 
    866 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
    867 
    868 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
    869 			0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageLayoutBarriers), imageLayoutBarriers);
    870 
    871 		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
    872 
    873 		const VkDeviceSize		quadOffset		= (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
    874 
    875 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
    876 		{
    877 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
    878 
    879 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
    880 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
    881 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
    882 		}
    883 
    884 		vk.cmdEndRenderPass(*m_cmdBuffer);
    885 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
    886 	}
    887 
    888 	// Create fence
    889 	{
    890 		const VkFenceCreateInfo fenceParams =
    891 		{
    892 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
    893 			DE_NULL,								// const void*			pNext;
    894 			0u										// VkFenceCreateFlags	flags;
    895 		};
    896 
    897 		m_fence = createFence(vk, vkDevice, &fenceParams);
    898 	}
    899 }
    900 
    901 StencilTestInstance::~StencilTestInstance (void)
    902 {
    903 }
    904 
    905 tcu::TestStatus StencilTestInstance::iterate (void)
    906 {
    907 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
    908 	const VkDevice				vkDevice	= m_context.getDevice();
    909 	const VkQueue				queue		= m_context.getUniversalQueue();
    910 	const VkSubmitInfo			submitInfo	=
    911 	{
    912 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    913 		DE_NULL,						// const void*				pNext;
    914 		0u,								// deUint32					waitSemaphoreCount;
    915 		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
    916 		(const VkPipelineStageFlags*)DE_NULL,
    917 		1u,								// deUint32					commandBufferCount;
    918 		&m_cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
    919 		0u,								// deUint32					signalSemaphoreCount;
    920 		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
    921 	};
    922 
    923 	VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
    924 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
    925 	VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
    926 
    927 	return verifyImage();
    928 }
    929 
    930 tcu::TestStatus StencilTestInstance::verifyImage (void)
    931 {
    932 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(m_colorFormat);
    933 	const tcu::TextureFormat	tcuStencilFormat	= mapVkFormat(m_stencilFormat);
    934 	const ColorVertexShader		vertexShader;
    935 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuStencilFormat);
    936 	const rr::Program			program				(&vertexShader, &fragmentShader);
    937 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
    938 	bool						compareOk			= false;
    939 
    940 	// Render reference image
    941 	{
    942 		// Set depth state
    943 		rr::RenderState renderState(refRenderer.getViewportState());
    944 
    945 		renderState.fragOps.depthTestEnabled	= true;
    946 		renderState.fragOps.depthFunc			= mapVkCompareOp(VK_COMPARE_OP_LESS);
    947 		renderState.fragOps.stencilTestEnabled	= true;
    948 
    949 		rr::StencilState& refStencilFront	= renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
    950 		rr::StencilState& refStencilBack	= renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
    951 
    952 		refStencilFront.sFail		= mapVkStencilOp(m_stencilOpStateFront.failOp);
    953 		refStencilFront.dpFail		= mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
    954 		refStencilFront.dpPass		= mapVkStencilOp(m_stencilOpStateFront.passOp);
    955 		refStencilFront.func		= mapVkCompareOp(m_stencilOpStateFront.compareOp);
    956 
    957 		refStencilBack.sFail		= mapVkStencilOp(m_stencilOpStateBack.failOp);
    958 		refStencilBack.dpFail		= mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
    959 		refStencilBack.dpPass		= mapVkStencilOp(m_stencilOpStateBack.passOp);
    960 		refStencilBack.func			= mapVkCompareOp(m_stencilOpStateBack.compareOp);
    961 
    962 		// Reverse winding of vertices, as Vulkan screen coordinates start at upper left
    963 		std::vector<Vertex4RGBA> cwVertices(m_vertices);
    964 		for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
    965 		{
    966 			const Vertex4RGBA cwVertex1	= cwVertices[vertexNdx + 1];
    967 
    968 			cwVertices[vertexNdx + 1]	= cwVertices[vertexNdx + 2];
    969 			cwVertices[vertexNdx + 2]	= cwVertex1;
    970 		}
    971 
    972 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
    973 		{
    974 			refStencilFront.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
    975 			refStencilFront.compMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
    976 			refStencilFront.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
    977 
    978 			refStencilBack.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
    979 			refStencilBack.compMask		= StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
    980 			refStencilBack.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
    981 
    982 			refRenderer.draw(renderState,
    983 							 rr::PRIMITIVETYPE_TRIANGLES,
    984 							 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6,
    985 													  cwVertices.begin() + (quadNdx + 1) * 6));
    986 		}
    987 	}
    988 
    989 	// Compare result with reference image
    990 	{
    991 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
    992 		const VkDevice						vkDevice			= m_context.getDevice();
    993 		const VkQueue						queue				= m_context.getUniversalQueue();
    994 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
    995 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
    996 		de::UniquePtr<tcu::TextureLevel>	result				(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
    997 
    998 		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
    999 															  "IntImageCompare",
   1000 															  "Image comparison",
   1001 															  refRenderer.getAccess(),
   1002 															  result->getAccess(),
   1003 															  tcu::UVec4(2, 2, 2, 2),
   1004 															  tcu::IVec3(1, 1, 0),
   1005 															  true,
   1006 															  tcu::COMPARE_LOG_RESULT);
   1007 	}
   1008 
   1009 	if (compareOk)
   1010 		return tcu::TestStatus::pass("Result image matches reference");
   1011 	else
   1012 		return tcu::TestStatus::fail("Image mismatch");
   1013 }
   1014 
   1015 
   1016 // Utilities for test names
   1017 
   1018 std::string getShortName (VkCompareOp compareOp)
   1019 {
   1020 	const std::string  fullName = getCompareOpName(compareOp);
   1021 
   1022 	DE_ASSERT(de::beginsWith(fullName, "VK_COMPARE_OP_"));
   1023 
   1024 	return de::toLower(fullName.substr(14));
   1025 }
   1026 
   1027 const char* getShortName (VkStencilOp stencilOp)
   1028 {
   1029 	switch (stencilOp)
   1030 	{
   1031 		case VK_STENCIL_OP_KEEP:					return "keep";
   1032 		case VK_STENCIL_OP_ZERO:					return "zero";
   1033 		case VK_STENCIL_OP_REPLACE:					return "repl";
   1034 		case VK_STENCIL_OP_INCREMENT_AND_CLAMP:		return "incc";
   1035 		case VK_STENCIL_OP_DECREMENT_AND_CLAMP:		return "decc";
   1036 		case VK_STENCIL_OP_INVERT:					return "inv";
   1037 		case VK_STENCIL_OP_INCREMENT_AND_WRAP:		return "wrap";
   1038 		case VK_STENCIL_OP_DECREMENT_AND_WRAP:		return "decw";
   1039 
   1040 		default:
   1041 			DE_FATAL("Invalid VkStencilOpState value");
   1042 	}
   1043 	return DE_NULL;
   1044 }
   1045 
   1046 std::string getStencilName(const VkStencilOpState& stencilOpState)
   1047 {
   1048 	std::ostringstream name;
   1049 
   1050 	name << "fail_" << getShortName(stencilOpState.failOp)
   1051 		 << "_pass_" << getShortName(stencilOpState.passOp)
   1052 		 << "_dfail_" << getShortName(stencilOpState.depthFailOp)
   1053 		 << "_comp_" << getShortName(stencilOpState.compareOp);
   1054 
   1055 	return name.str();
   1056 }
   1057 
   1058 std::string getStencilStateSetName(const VkStencilOpState& stencilOpStateFront,
   1059 								   const VkStencilOpState& stencilOpStateBack)
   1060 {
   1061 	std::ostringstream name;
   1062 
   1063 	name << "front_" << getStencilName(stencilOpStateFront)
   1064 		 << "_back_" << getStencilName(stencilOpStateBack);
   1065 
   1066 	return name.str();
   1067 }
   1068 
   1069 std::string getStencilStateSetDescription(const VkStencilOpState& stencilOpStateFront,
   1070 										  const VkStencilOpState& stencilOpStateBack)
   1071 {
   1072 	std::ostringstream desc;
   1073 
   1074 	desc << "\nFront faces:\n" << stencilOpStateFront;
   1075 	desc << "Back faces:\n" << stencilOpStateBack;
   1076 
   1077 	return desc.str();
   1078 }
   1079 
   1080 std::string getFormatCaseName (VkFormat format)
   1081 {
   1082 	const std::string fullName = getFormatName(format);
   1083 
   1084 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
   1085 
   1086 	return de::toLower(fullName.substr(10));
   1087 }
   1088 
   1089 } // anonymous
   1090 
   1091 tcu::TestCaseGroup* createStencilTests (tcu::TestContext& testCtx)
   1092 {
   1093 	const VkFormat stencilFormats[] =
   1094 	{
   1095 		VK_FORMAT_S8_UINT,
   1096 		VK_FORMAT_D16_UNORM_S8_UINT,
   1097 		VK_FORMAT_D24_UNORM_S8_UINT,
   1098 		VK_FORMAT_D32_SFLOAT_S8_UINT
   1099 	};
   1100 
   1101 	de::MovePtr<tcu::TestCaseGroup>		stencilTests	(new tcu::TestCaseGroup(testCtx, "stencil", "Stencil tests"));
   1102 	de::MovePtr<tcu::TestCaseGroup>		formatTests		(new tcu::TestCaseGroup(testCtx, "format", "Uses different stencil formats"));
   1103 	StencilOpStateUniqueRandomIterator	stencilOpItr	(123);
   1104 
   1105 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
   1106 	{
   1107 		const VkFormat					stencilFormat	= stencilFormats[formatNdx];
   1108 		de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
   1109 																				getFormatCaseName(stencilFormat).c_str(),
   1110 																				(std::string("Uses format ") + getFormatName(stencilFormat)).c_str()));
   1111 
   1112 		de::MovePtr<tcu::TestCaseGroup>	stencilStateTests;
   1113 		{
   1114 			std::ostringstream desc;
   1115 			desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
   1116 			for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
   1117 			{
   1118 				const StencilTest::StencilStateConfig& stencilConfig = StencilTest::s_stencilStateConfigs[quadNdx];
   1119 
   1120 				desc << "(" << quadNdx << ") "
   1121 					 << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
   1122 					 << "frontReadMask = " << stencilConfig.frontReadMask << ", "
   1123 					 << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
   1124 					 << "frontRef = " << stencilConfig.frontRef << ", "
   1125 					 << "backReadMask = " << stencilConfig.backReadMask << ", "
   1126 					 << "backWriteMask = " << stencilConfig.backWriteMask << ", "
   1127 					 << "backRef = " << stencilConfig.backRef;
   1128 			}
   1129 
   1130 			stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", desc.str().c_str()));
   1131 		}
   1132 
   1133 		stencilOpItr.reset();
   1134 
   1135 		VkStencilOpState		prevStencilState	= stencilOpItr.next();
   1136 		const VkStencilOpState	firstStencilState	= prevStencilState;
   1137 
   1138 		while (stencilOpItr.hasNext())
   1139 		{
   1140 			const VkStencilOpState stencilState = stencilOpItr.next();
   1141 
   1142 			// Use current stencil state in front fraces and previous state in back faces
   1143 			stencilStateTests->addChild(new StencilTest(testCtx,
   1144 														getStencilStateSetName(stencilState, prevStencilState),
   1145 														getStencilStateSetDescription(stencilState, prevStencilState),
   1146 														stencilFormat,
   1147 														stencilState,
   1148 														prevStencilState));
   1149 
   1150 			prevStencilState = stencilState;
   1151 		}
   1152 
   1153 		// Use first stencil state with last stencil state. This would make the test suite cover all states in front and back faces.
   1154 		stencilStateTests->addChild(new StencilTest(testCtx,
   1155 													getStencilStateSetName(firstStencilState, prevStencilState),
   1156 													getStencilStateSetDescription(firstStencilState, prevStencilState),
   1157 													stencilFormat,
   1158 													firstStencilState,
   1159 													prevStencilState));
   1160 
   1161 		formatTest->addChild(stencilStateTests.release());
   1162 		formatTests->addChild(formatTest.release());
   1163 	}
   1164 	stencilTests->addChild(formatTests.release());
   1165 
   1166 	return stencilTests.release();
   1167 }
   1168 
   1169 } // pipeline
   1170 } // vkt
   1171