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 Blend Tests
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktPipelineBlendTests.hpp"
     26 #include "vktPipelineClearUtil.hpp"
     27 #include "vktPipelineImageUtil.hpp"
     28 #include "vktPipelineVertexUtil.hpp"
     29 #include "vktPipelineUniqueRandomIterator.hpp"
     30 #include "vktPipelineReferenceRenderer.hpp"
     31 #include "vktTestCase.hpp"
     32 #include "vkImageUtil.hpp"
     33 #include "vkMemUtil.hpp"
     34 #include "vkPlatform.hpp"
     35 #include "vkPrograms.hpp"
     36 #include "vkQueryUtil.hpp"
     37 #include "vkRef.hpp"
     38 #include "vkRefUtil.hpp"
     39 #include "tcuImageCompare.hpp"
     40 #include "tcuPlatform.hpp"
     41 #include "tcuTextureUtil.hpp"
     42 #include "deRandom.hpp"
     43 #include "deStringUtil.hpp"
     44 #include "deUniquePtr.hpp"
     45 #include <cstring>
     46 #include <set>
     47 #include <sstream>
     48 #include <vector>
     49 
     50 namespace vkt
     51 {
     52 namespace pipeline
     53 {
     54 
     55 using namespace vk;
     56 
     57 namespace
     58 {
     59 
     60 bool isSupportedBlendFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
     61 {
     62 	VkFormatProperties formatProps;
     63 
     64 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
     65 
     66 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) &&
     67 		   (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT);
     68 }
     69 
     70 class BlendStateUniqueRandomIterator : public UniqueRandomIterator<VkPipelineColorBlendAttachmentState>
     71 {
     72 public:
     73 											BlendStateUniqueRandomIterator		(deUint32 numberOfCombinations, int seed);
     74 	virtual									~BlendStateUniqueRandomIterator		(void) {}
     75 	VkPipelineColorBlendAttachmentState		getIndexedValue	(deUint32 index);
     76 
     77 private:
     78 	const static VkBlendFactor				m_blendFactors[];
     79 	const static VkBlendOp					m_blendOps[];
     80 
     81 	// Pre-calculated constants
     82 	const static deUint32					m_blendFactorsLength;
     83 	const static deUint32					m_blendFactorsLength2;
     84 	const static deUint32					m_blendFactorsLength3;
     85 	const static deUint32					m_blendFactorsLength4;
     86 	const static deUint32					m_blendOpsLength;
     87 
     88 	// Total number of cross-combinations of (srcBlendColor x destBlendColor x blendOpColor x srcBlendAlpha x destBlendAlpha x blendOpAlpha)
     89 	const static deUint32					m_totalBlendStates;
     90 };
     91 
     92 class BlendTest : public vkt::TestCase
     93 {
     94 public:
     95 	enum
     96 	{
     97 		QUAD_COUNT = 4
     98 	};
     99 
    100 	const static VkColorComponentFlags	s_colorWriteMasks[QUAD_COUNT];
    101 	const static tcu::Vec4				s_blendConst;
    102 
    103 										BlendTest				(tcu::TestContext&							testContext,
    104 																 const std::string&							name,
    105 																 const std::string&							description,
    106 																 const VkFormat								colorFormat,
    107 																 const VkPipelineColorBlendAttachmentState	blendStates[QUAD_COUNT]);
    108 	virtual								~BlendTest				(void);
    109 	virtual void						initPrograms			(SourceCollections& sourceCollections) const;
    110 	virtual TestInstance*				createInstance			(Context& context) const;
    111 
    112 private:
    113 	const VkFormat						m_colorFormat;
    114 	VkPipelineColorBlendAttachmentState	m_blendStates[QUAD_COUNT];
    115 };
    116 
    117 class BlendTestInstance : public vkt::TestInstance
    118 {
    119 public:
    120 										BlendTestInstance		(Context& context, const VkFormat colorFormat, const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT]);
    121 	virtual								~BlendTestInstance		(void);
    122 	virtual tcu::TestStatus				iterate					(void);
    123 
    124 private:
    125 	static float						getNormChannelThreshold	(const tcu::TextureFormat& format, int numBits);
    126 	static tcu::Vec4					getFormatThreshold		(const tcu::TextureFormat& format);
    127 	tcu::TestStatus						verifyImage				(void);
    128 
    129 	VkPipelineColorBlendAttachmentState	m_blendStates[BlendTest::QUAD_COUNT];
    130 
    131 	const tcu::UVec2					m_renderSize;
    132 	const VkFormat						m_colorFormat;
    133 
    134 	VkImageCreateInfo					m_colorImageCreateInfo;
    135 	Move<VkImage>						m_colorImage;
    136 	de::MovePtr<Allocation>				m_colorImageAlloc;
    137 	Move<VkImageView>					m_colorAttachmentView;
    138 	Move<VkRenderPass>					m_renderPass;
    139 	Move<VkFramebuffer>					m_framebuffer;
    140 
    141 	Move<VkShaderModule>				m_vertexShaderModule;
    142 	Move<VkShaderModule>				m_fragmentShaderModule;
    143 
    144 	Move<VkBuffer>						m_vertexBuffer;
    145 	std::vector<Vertex4RGBA>			m_vertices;
    146 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
    147 
    148 	Move<VkPipelineLayout>				m_pipelineLayout;
    149 	Move<VkPipeline>					m_graphicsPipelines[BlendTest::QUAD_COUNT];
    150 
    151 	Move<VkCommandPool>					m_cmdPool;
    152 	Move<VkCommandBuffer>				m_cmdBuffer;
    153 
    154 	Move<VkFence>						m_fence;
    155 };
    156 
    157 
    158 // BlendStateUniqueRandomIterator
    159 
    160 const VkBlendFactor BlendStateUniqueRandomIterator::m_blendFactors[] =
    161 {
    162 	VK_BLEND_FACTOR_ZERO,
    163 	VK_BLEND_FACTOR_ONE,
    164 	VK_BLEND_FACTOR_SRC_COLOR,
    165 	VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
    166 	VK_BLEND_FACTOR_DST_COLOR,
    167 	VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
    168 	VK_BLEND_FACTOR_SRC_ALPHA,
    169 	VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
    170 	VK_BLEND_FACTOR_DST_ALPHA,
    171 	VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
    172 	VK_BLEND_FACTOR_CONSTANT_COLOR,
    173 	VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
    174 	VK_BLEND_FACTOR_CONSTANT_ALPHA,
    175 	VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
    176 	VK_BLEND_FACTOR_SRC_ALPHA_SATURATE
    177 };
    178 
    179 const VkBlendOp BlendStateUniqueRandomIterator::m_blendOps[] =
    180 {
    181 	VK_BLEND_OP_ADD,
    182 	VK_BLEND_OP_SUBTRACT,
    183 	VK_BLEND_OP_REVERSE_SUBTRACT,
    184 	VK_BLEND_OP_MIN,
    185 	VK_BLEND_OP_MAX
    186 };
    187 
    188 const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength		= DE_LENGTH_OF_ARRAY(m_blendFactors);
    189 const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength2	= m_blendFactorsLength * m_blendFactorsLength;
    190 const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength3	= m_blendFactorsLength2 * m_blendFactorsLength;
    191 const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength4	= m_blendFactorsLength3 * m_blendFactorsLength;
    192 const deUint32 BlendStateUniqueRandomIterator::m_blendOpsLength			= DE_LENGTH_OF_ARRAY(m_blendOps);
    193 const deUint32 BlendStateUniqueRandomIterator::m_totalBlendStates		= m_blendFactorsLength4 * m_blendOpsLength * m_blendOpsLength;
    194 
    195 
    196 BlendStateUniqueRandomIterator::BlendStateUniqueRandomIterator (deUint32 numberOfCombinations, int seed)
    197 	: UniqueRandomIterator<VkPipelineColorBlendAttachmentState>(numberOfCombinations, m_totalBlendStates, seed)
    198 {
    199 }
    200 
    201 VkPipelineColorBlendAttachmentState BlendStateUniqueRandomIterator::getIndexedValue (deUint32 index)
    202 {
    203 	const deUint32		blendOpAlphaIndex			= index / (m_blendFactorsLength4 * m_blendOpsLength);
    204 	const deUint32		blendOpAlphaSeqIndex		= blendOpAlphaIndex * (m_blendFactorsLength4 * m_blendOpsLength);
    205 
    206 	const deUint32		destBlendAlphaIndex			= (index - blendOpAlphaSeqIndex) / (m_blendFactorsLength3 * m_blendOpsLength);
    207 	const deUint32		destBlendAlphaSeqIndex		= destBlendAlphaIndex * (m_blendFactorsLength3 * m_blendOpsLength);
    208 
    209 	const deUint32		srcBlendAlphaIndex			= (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex) / (m_blendFactorsLength2 * m_blendOpsLength);
    210 	const deUint32		srcBlendAlphaSeqIndex		= srcBlendAlphaIndex * (m_blendFactorsLength2 * m_blendOpsLength);
    211 
    212 	const deUint32		blendOpColorIndex			= (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex) / m_blendFactorsLength2;
    213 	const deUint32		blendOpColorSeqIndex		= blendOpColorIndex * m_blendFactorsLength2;
    214 
    215 	const deUint32		destBlendColorIndex			= (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex) / m_blendFactorsLength;
    216 	const deUint32		destBlendColorSeqIndex		= destBlendColorIndex * m_blendFactorsLength;
    217 
    218 	const deUint32		srcBlendColorIndex			= index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex - destBlendColorSeqIndex;
    219 
    220 	const VkPipelineColorBlendAttachmentState blendAttachmentState =
    221 	{
    222 		true,														// VkBool32					blendEnable;
    223 		m_blendFactors[srcBlendColorIndex],							// VkBlendFactor			srcColorBlendFactor;
    224 		m_blendFactors[destBlendColorIndex],						// VkBlendFactor			dstColorBlendFactor;
    225 		m_blendOps[blendOpColorIndex],								// VkBlendOp				colorBlendOp;
    226 		m_blendFactors[srcBlendAlphaIndex],							// VkBlendFactor			srcAlphaBlendFactor;
    227 		m_blendFactors[destBlendAlphaIndex],						// VkBlendFactor			dstAlphaBlendFactor;
    228 		m_blendOps[blendOpAlphaIndex],								// VkBlendOp				alphaBlendOp;
    229 		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
    230 			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
    231 	};
    232 
    233 	return blendAttachmentState;
    234 }
    235 
    236 
    237 // BlendTest
    238 
    239 const VkColorComponentFlags BlendTest::s_colorWriteMasks[BlendTest::QUAD_COUNT] = { VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT,	// Pair of channels: R & G
    240 																					VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT,	// Pair of channels: G & B
    241 																					VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,	// Pair of channels: B & A
    242 																					VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT };	// All channels
    243 
    244 const tcu::Vec4 BlendTest::s_blendConst = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f);
    245 
    246 BlendTest::BlendTest (tcu::TestContext&								testContext,
    247 					  const std::string&							name,
    248 					  const std::string&							description,
    249 					  const VkFormat								colorFormat,
    250 					  const VkPipelineColorBlendAttachmentState		blendStates[QUAD_COUNT])
    251 	: vkt::TestCase	(testContext, name, description)
    252 	, m_colorFormat(colorFormat)
    253 {
    254 	deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * QUAD_COUNT);
    255 }
    256 
    257 BlendTest::~BlendTest (void)
    258 {
    259 }
    260 
    261 TestInstance* BlendTest::createInstance(Context& context) const
    262 {
    263 	return new BlendTestInstance(context, m_colorFormat, m_blendStates);
    264 }
    265 
    266 void BlendTest::initPrograms (SourceCollections& sourceCollections) const
    267 {
    268 	std::ostringstream fragmentSource;
    269 
    270 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
    271 		"#version 310 es\n"
    272 		"layout(location = 0) in highp vec4 position;\n"
    273 		"layout(location = 1) in highp vec4 color;\n"
    274 		"layout(location = 0) out highp vec4 vtxColor;\n"
    275 		"void main (void)\n"
    276 		"{\n"
    277 		"	gl_Position = position;\n"
    278 		"	vtxColor = color;\n"
    279 		"}\n");
    280 
    281 	fragmentSource << "#version 310 es\n"
    282 		"layout(location = 0) in highp vec4 vtxColor;\n"
    283 		"layout(location = 0) out highp vec4 fragColor;\n"
    284 		"void main (void)\n"
    285 		"{\n"
    286 		"	fragColor = vtxColor;\n"
    287 		"}\n";
    288 
    289 	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
    290 }
    291 
    292 
    293 // BlendTestInstance
    294 
    295 BlendTestInstance::BlendTestInstance (Context&									context,
    296 									  const VkFormat							colorFormat,
    297 									  const VkPipelineColorBlendAttachmentState	blendStates[BlendTest::QUAD_COUNT])
    298 	: vkt::TestInstance	(context)
    299 	, m_renderSize		(32, 32)
    300 	, m_colorFormat		(colorFormat)
    301 {
    302 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
    303 	const VkDevice				vkDevice			= m_context.getDevice();
    304 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
    305 	SimpleAllocator				memAlloc			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
    306 
    307 	// Copy depth operators
    308 	deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * BlendTest::QUAD_COUNT);
    309 
    310 	// Create color image
    311 	{
    312 		if (!isSupportedBlendFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_colorFormat))
    313 			throw tcu::NotSupportedError(std::string("Unsupported color blending format: ") + getFormatName(m_colorFormat));
    314 
    315 		const VkImageCreateInfo	colorImageParams =
    316 		{
    317 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
    318 			DE_NULL,																	// const void*				pNext;
    319 			0u,																			// VkImageCreateFlags		flags;
    320 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
    321 			m_colorFormat,																// VkFormat					format;
    322 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
    323 			1u,																			// deUint32					mipLevels;
    324 			1u,																			// deUint32					arrayLayers;
    325 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
    326 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
    327 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
    328 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
    329 			1u,																			// deUint32					queueFamilyIndexCount;
    330 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
    331 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
    332 		};
    333 
    334 		m_colorImageCreateInfo	= colorImageParams;
    335 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
    336 
    337 		// Allocate and bind color image memory
    338 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
    339 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
    340 	}
    341 
    342 	// Create color attachment view
    343 	{
    344 		const VkImageViewCreateInfo colorAttachmentViewParams =
    345 		{
    346 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
    347 			DE_NULL,											// const void*				pNext;
    348 			0u,													// VkImageViewCreateFlags	flags;
    349 			*m_colorImage,										// VkImage					image;
    350 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
    351 			m_colorFormat,										// VkFormat					format;
    352 			{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
    353 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
    354 		};
    355 
    356 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
    357 	}
    358 
    359 	// Create render pass
    360 	{
    361 		const VkAttachmentDescription colorAttachmentDescription =
    362 		{
    363 			0u,													// VkAttachmentDescriptionFlags		flags;
    364 			m_colorFormat,										// VkFormat							format;
    365 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
    366 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
    367 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
    368 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
    369 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
    370 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
    371 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
    372 		};
    373 
    374 		const VkAttachmentReference colorAttachmentReference =
    375 		{
    376 			0u,													// deUint32			attachment;
    377 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
    378 		};
    379 
    380 		const VkSubpassDescription subpassDescription =
    381 		{
    382 			0u,													// VkSubpassDescriptionFlag		flags;
    383 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
    384 			0u,													// deUint32						inputAttachmentCount;
    385 			DE_NULL,											// const VkAttachmentReference*	pInputAttachments;
    386 			1u,													// deUint32						colorAttachmentCount;
    387 			&colorAttachmentReference,							// const VkAttachmentReference*	pColorAttachments;
    388 			DE_NULL,											// const VkAttachmentReference*	pResolveAttachments;
    389 			DE_NULL,											// const VkAttachmentReference*	pDepthStencilAttachment;
    390 			0u,													// deUint32						preserveAttachmentCount;
    391 			DE_NULL												// const VkAttachmentReference*	pPreserveAttachments;
    392 		};
    393 
    394 		const VkRenderPassCreateInfo renderPassParams =
    395 		{
    396 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
    397 			DE_NULL,											// const void*						pNext;
    398 			0u,													// VkRenderPassCreateFlags			flags;
    399 			1u,													// deUint32							attachmentCount;
    400 			&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
    401 			1u,													// deUint32							subpassCount;
    402 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
    403 			0u,													// deUint32							dependencyCount;
    404 			DE_NULL												// const VkSubpassDependency*		pDependencies;
    405 		};
    406 
    407 		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
    408 	}
    409 
    410 	// Create framebuffer
    411 	{
    412 		const VkFramebufferCreateInfo framebufferParams =
    413 		{
    414 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
    415 			DE_NULL,											// const void*				pNext;
    416 			0u,													// VkFramebufferCreateFlags	flags;
    417 			*m_renderPass,										// VkRenderPass				renderPass;
    418 			1u,													// deUint32					attachmentCount;
    419 			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
    420 			(deUint32)m_renderSize.x(),							// deUint32					width;
    421 			(deUint32)m_renderSize.y(),							// deUint32					height;
    422 			1u													// deUint32					layers;
    423 		};
    424 
    425 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
    426 	}
    427 
    428 	// Create pipeline layout
    429 	{
    430 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
    431 		{
    432 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
    433 			DE_NULL,											// const void*						pNext;
    434 			0u,													// VkPipelineLayoutCreateFlags		flags;
    435 			0u,													// deUint32							setLayoutCount;
    436 			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
    437 			0u,													// deUint32							pushConstantRangeCount;
    438 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
    439 		};
    440 
    441 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
    442 	}
    443 
    444 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
    445 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
    446 
    447 	// Create pipeline
    448 	{
    449 		const VkPipelineShaderStageCreateInfo shaderStages[2] =
    450 		{
    451 			{
    452 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
    453 				DE_NULL,												// const void*						pNext;
    454 				0u,														// VkPipelineShaderStageCreateFlags	flags;
    455 				VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits			stage;
    456 				*m_vertexShaderModule,									// VkShaderModule					module;
    457 				"main",													// const char*						pName;
    458 				DE_NULL													// const VkSpecializationInfo*		pSpecializationInfo;
    459 			},
    460 			{
    461 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
    462 				DE_NULL,												// const void*						pNext;
    463 				0u,														// VkPipelineShaderStageCreateFlags	flags;
    464 				VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits			stage;
    465 				*m_fragmentShaderModule,								// VkShaderModule					module;
    466 				"main",													// const char*						pName;
    467 				DE_NULL													// const VkSpecializationInfo*		pSpecializationInfo;
    468 			}
    469 		};
    470 
    471 		const VkVertexInputBindingDescription vertexInputBindingDescription =
    472 		{
    473 			0u,									// deUint32					binding;
    474 			sizeof(Vertex4RGBA),				// deUint32					strideInBytes;
    475 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
    476 		};
    477 
    478 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
    479 		{
    480 			{
    481 				0u,								// deUint32	location;
    482 				0u,								// deUint32	binding;
    483 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
    484 				0u								// deUint32	offset;
    485 			},
    486 			{
    487 				1u,								// deUint32	location;
    488 				0u,								// deUint32	binding;
    489 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
    490 				(deUint32)(sizeof(float) * 4),	// deUint32	offset;
    491 			}
    492 		};
    493 
    494 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
    495 		{
    496 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
    497 			DE_NULL,														// const void*								pNext;
    498 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
    499 			1u,																// deUint32									vertexBindingDescriptionCount;
    500 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
    501 			2u,																// deUint32									vertexAttributeDescriptionCount;
    502 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
    503 		};
    504 
    505 		const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
    506 		{
    507 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
    508 			DE_NULL,														// const void*								pNext;
    509 			0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
    510 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
    511 			false															// VkBool32									primitiveRestartEnable;
    512 		};
    513 
    514 		const VkViewport viewport =
    515 		{
    516 			0.0f,						// float	x;
    517 			0.0f,						// float	y;
    518 			(float)m_renderSize.x(),	// float	width;
    519 			(float)m_renderSize.y(),	// float	height;
    520 			0.0f,						// float	minDepth;
    521 			1.0f						// float	maxDepth;
    522 		};
    523 
    524 		const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
    525 
    526 		const VkPipelineViewportStateCreateInfo viewportStateParams =
    527 		{
    528 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
    529 			DE_NULL,														// const void*							pNext;
    530 			0u,																// VkPipelineViewportStateCreateFlags	flags;
    531 			1u,																// deUint32								viewportCount;
    532 			&viewport,														// const VkViewport*					pViewports;
    533 			1u,																// deUint32								scissorCount;
    534 			&scissor														// const VkRect2D*						pScissors;
    535 		};
    536 
    537 		const VkPipelineRasterizationStateCreateInfo rasterStateParams =
    538 		{
    539 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
    540 			DE_NULL,														// const void*								pNext;
    541 			0u,																// VkPipelineRasterizationStateCreateFlags	flags;
    542 			false,															// VkBool32									depthClampEnable;
    543 			false,															// VkBool32									rasterizerDiscardEnable;
    544 			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
    545 			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
    546 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
    547 			false,															// VkBool32									depthBiasEnable;
    548 			0.0f,															// float									depthBiasConstantFactor;
    549 			0.0f,															// float									depthBiasClamp;
    550 			0.0f,															// float									depthBiasSlopeFactor;
    551 			1.0f															// float									lineWidth;
    552 		};
    553 
    554 		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
    555 		{
    556 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
    557 			DE_NULL,													// const void*								pNext;
    558 			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
    559 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
    560 			false,														// VkBool32									sampleShadingEnable;
    561 			0.0f,														// float									minSampleShading;
    562 			DE_NULL,													// const VkSampleMask*						pSampleMask;
    563 			false,														// VkBool32									alphaToCoverageEnable;
    564 			false														// VkBool32									alphaToOneEnable;
    565 		};
    566 
    567 		const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
    568 		{
    569 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
    570 			DE_NULL,													// const void*								pNext;
    571 			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
    572 			false,														// VkBool32									depthTestEnable;
    573 			false,														// VkBool32									depthWriteEnable;
    574 			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
    575 			false,														// VkBool32									depthBoundsTestEnable;
    576 			false,														// VkBool32									stencilTestEnable;
    577 			// VkStencilOpState	front;
    578 			{
    579 				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
    580 				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
    581 				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
    582 				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
    583 				0u,						// deUint32		compareMask;
    584 				0u,						// deUint32		writeMask;
    585 				0u						// deUint32		reference;
    586 			},
    587 			// VkStencilOpState	back;
    588 			{
    589 				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
    590 				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
    591 				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
    592 				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
    593 				0u,						// deUint32		compareMask;
    594 				0u,						// deUint32		writeMask;
    595 				0u						// deUint32		reference;
    596 			},
    597 			0.0f,														// float			minDepthBounds;
    598 			1.0f														// float			maxDepthBounds;
    599 		};
    600 
    601 		// The color blend attachment will be set up before creating the graphics pipeline.
    602 		VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
    603 		{
    604 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
    605 			DE_NULL,													// const void*									pNext;
    606 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
    607 			false,														// VkBool32										logicOpEnable;
    608 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
    609 			0u,															// deUint32										attachmentCount;
    610 			DE_NULL,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
    611 			{															// float										blendConstants[4];
    612 				BlendTest::s_blendConst.x(),
    613 				BlendTest::s_blendConst.y(),
    614 				BlendTest::s_blendConst.z(),
    615 				BlendTest::s_blendConst.w()
    616 			}
    617 		};
    618 
    619 		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
    620 		{
    621 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
    622 			DE_NULL,											// const void*										pNext;
    623 			0u,													// VkPipelineCreateFlags							flags;
    624 			2u,													// deUint32											stageCount;
    625 			shaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
    626 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
    627 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
    628 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
    629 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
    630 			&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
    631 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
    632 			&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
    633 			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
    634 			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
    635 			*m_pipelineLayout,									// VkPipelineLayout									layout;
    636 			*m_renderPass,										// VkRenderPass										renderPass;
    637 			0u,													// deUint32											subpass;
    638 			0u,													// VkPipeline										basePipelineHandle;
    639 			0u													// deInt32											basePipelineIndex;
    640 		};
    641 
    642 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
    643 		{
    644 			colorBlendStateParams.attachmentCount	= 1u;
    645 			colorBlendStateParams.pAttachments		= &m_blendStates[quadNdx];
    646 			m_graphicsPipelines[quadNdx]			= createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
    647 		}
    648 	}
    649 
    650 	// Create vertex buffer
    651 	{
    652 		const VkBufferCreateInfo vertexBufferParams =
    653 		{
    654 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    655 			DE_NULL,									// const void*			pNext;
    656 			0u,											// VkBufferCreateFlags	flags;
    657 			1024u,										// VkDeviceSize			size;
    658 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    659 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    660 			1u,											// deUint32				queueFamilyIndexCount;
    661 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    662 		};
    663 
    664 		m_vertices			= createOverlappingQuads();
    665 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
    666 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
    667 
    668 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
    669 
    670 		// Adjust vertex colors
    671 		if (!isFloatFormat(m_colorFormat))
    672 		{
    673 			const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(mapVkFormat(m_colorFormat));
    674 			for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
    675 				m_vertices[vertexNdx].color = (m_vertices[vertexNdx].color - formatInfo.lookupBias) / formatInfo.lookupScale;
    676 		}
    677 
    678 		// Upload vertex data
    679 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
    680 
    681 		const VkMappedMemoryRange flushRange =
    682 		{
    683 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// VkStructureType	sType;
    684 			DE_NULL,								// const void*		pNext;
    685 			m_vertexBufferAlloc->getMemory(),		// VkDeviceMemory	memory;
    686 			m_vertexBufferAlloc->getOffset(),		// VkDeviceSize		offset;
    687 			vertexBufferParams.size					// VkDeviceSize		size;
    688 		};
    689 
    690 		vk.flushMappedMemoryRanges(vkDevice, 1, &flushRange);
    691 	}
    692 
    693 	// Create command pool
    694 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
    695 
    696 	// Create command buffer
    697 	{
    698 		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
    699 		{
    700 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
    701 			DE_NULL,										// const void*						pNext;
    702 			0u,												// VkCommandBufferUsageFlags		flags;
    703 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
    704 		};
    705 
    706 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
    707 
    708 		const VkRenderPassBeginInfo renderPassBeginInfo =
    709 		{
    710 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
    711 			DE_NULL,												// const void*			pNext;
    712 			*m_renderPass,											// VkRenderPass			renderPass;
    713 			*m_framebuffer,											// VkFramebuffer		framebuffer;
    714 			{ { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
    715 			1,														// deUint32				clearValueCount;
    716 			&attachmentClearValue									// const VkClearValue*	pClearValues;
    717 		};
    718 
    719 		// Color image layout transition
    720 		const VkImageMemoryBarrier imageLayoutBarrier =
    721 		{
    722 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
    723 			DE_NULL,																// const void*                pNext;
    724 			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
    725 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									// VkAccessFlags              dstAccessMask;
    726 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
    727 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout              newLayout;
    728 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
    729 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
    730 			*m_colorImage,															// VkImage                    image;
    731 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }							// VkImageSubresourceRange    subresourceRange;
    732 		};
    733 
    734 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
    735 
    736 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
    737 
    738 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
    739 			0u, DE_NULL, 0u, DE_NULL, 1u, &imageLayoutBarrier);
    740 
    741 		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
    742 
    743 		const VkDeviceSize quadOffset = (m_vertices.size() / BlendTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
    744 
    745 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
    746 		{
    747 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
    748 
    749 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
    750 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
    751 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / BlendTest::QUAD_COUNT), 1, 0, 0);
    752 		}
    753 
    754 		vk.cmdEndRenderPass(*m_cmdBuffer);
    755 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
    756 	}
    757 
    758 	// Create fence
    759 	m_fence = createFence(vk, vkDevice);
    760 }
    761 
    762 BlendTestInstance::~BlendTestInstance (void)
    763 {
    764 }
    765 
    766 tcu::TestStatus BlendTestInstance::iterate (void)
    767 {
    768 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
    769 	const VkDevice				vkDevice	= m_context.getDevice();
    770 	const VkQueue				queue		= m_context.getUniversalQueue();
    771 	const VkSubmitInfo			submitInfo	=
    772 	{
    773 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    774 		DE_NULL,						// const void*				pNext;
    775 		0u,								// deUint32					waitSemaphoreCount;
    776 		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
    777 		(const VkPipelineStageFlags*)DE_NULL,
    778 		1u,								// deUint32					commandBufferCount;
    779 		&m_cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
    780 		0u,								// deUint32					signalSemaphoreCount;
    781 		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
    782 	};
    783 
    784 	VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
    785 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
    786 	VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
    787 
    788 	return verifyImage();
    789 }
    790 
    791 float BlendTestInstance::getNormChannelThreshold (const tcu::TextureFormat& format, int numBits)
    792 {
    793 	switch (tcu::getTextureChannelClass(format.type))
    794 	{
    795 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:	return BlendTest::QUAD_COUNT / static_cast<float>((1 << numBits) - 1);
    796 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:	return BlendTest::QUAD_COUNT / static_cast<float>((1 << (numBits - 1)) - 1);
    797 		default:
    798 			break;
    799 	}
    800 
    801 	DE_ASSERT(false);
    802 	return 0.0f;
    803 }
    804 
    805 tcu::Vec4 BlendTestInstance::getFormatThreshold (const tcu::TextureFormat& format)
    806 {
    807 	using tcu::Vec4;
    808 	using tcu::TextureFormat;
    809 
    810 	Vec4 threshold(0.01f);
    811 
    812 	switch (format.type)
    813 	{
    814 		case TextureFormat::UNORM_BYTE_44:
    815 			threshold = Vec4(getNormChannelThreshold(format, 4), getNormChannelThreshold(format, 4), 1.0f, 1.0f);
    816 			break;
    817 
    818 		case TextureFormat::UNORM_SHORT_565:
    819 			threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 6), getNormChannelThreshold(format, 5), 1.0f);
    820 			break;
    821 
    822 		case TextureFormat::UNORM_SHORT_555:
    823 			threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 1.0f);
    824 			break;
    825 
    826 		case TextureFormat::UNORM_SHORT_4444:
    827 			threshold = Vec4(getNormChannelThreshold(format, 4));
    828 			break;
    829 
    830 		case TextureFormat::UNORM_SHORT_5551:
    831 			threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 0.1f);
    832 			break;
    833 
    834 		case TextureFormat::UNORM_INT_1010102_REV:
    835 		case TextureFormat::SNORM_INT_1010102_REV:
    836 			threshold = Vec4(getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), 0.34f);
    837 			break;
    838 
    839 		case TextureFormat::UNORM_INT8:
    840 		case TextureFormat::SNORM_INT8:
    841 			threshold = Vec4(getNormChannelThreshold(format, 8));
    842 			break;
    843 
    844 		case TextureFormat::UNORM_INT16:
    845 		case TextureFormat::SNORM_INT16:
    846 			threshold = Vec4(getNormChannelThreshold(format, 16));
    847 			break;
    848 
    849 		case TextureFormat::UNORM_INT32:
    850 		case TextureFormat::SNORM_INT32:
    851 			threshold = Vec4(getNormChannelThreshold(format, 32));
    852 			break;
    853 
    854 		case TextureFormat::HALF_FLOAT:
    855 			threshold = Vec4(0.005f);
    856 			break;
    857 
    858 		case TextureFormat::FLOAT:
    859 			threshold = Vec4(0.00001f);
    860 			break;
    861 
    862 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
    863 			threshold = Vec4(0.02f, 0.02f, 0.0625f, 1.0f);
    864 			break;
    865 
    866 		case TextureFormat::UNSIGNED_INT_999_E5_REV:
    867 			threshold = Vec4(0.05f, 0.05f, 0.05f, 1.0f);
    868 			break;
    869 
    870 		default:
    871 			DE_ASSERT(false);
    872 	}
    873 
    874 	// Return value matching the channel order specified by the format
    875 	if (format.order == tcu::TextureFormat::BGR || format.order == tcu::TextureFormat::BGRA)
    876 		return threshold.swizzle(2, 1, 0, 3);
    877 	else
    878 		return threshold;
    879 }
    880 
    881 tcu::TestStatus BlendTestInstance::verifyImage (void)
    882 {
    883 	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
    884 	const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat(); // Undefined depth/stencil format
    885 	const ColorVertexShader		vertexShader;
    886 	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
    887 	const rr::Program			program			(&vertexShader, &fragmentShader);
    888 	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
    889 	bool						compareOk		= false;
    890 
    891 	// Render reference image
    892 	{
    893 		for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
    894 		{
    895 			const VkPipelineColorBlendAttachmentState& blendState = m_blendStates[quadNdx];
    896 
    897 			// Set blend state
    898 			rr::RenderState renderState					(refRenderer.getViewportState());
    899 			renderState.fragOps.blendMode				= rr::BLENDMODE_STANDARD;
    900 			renderState.fragOps.blendRGBState.srcFunc	= mapVkBlendFactor(blendState.srcColorBlendFactor);
    901 			renderState.fragOps.blendRGBState.dstFunc	= mapVkBlendFactor(blendState.dstColorBlendFactor);
    902 			renderState.fragOps.blendRGBState.equation	= mapVkBlendOp(blendState.colorBlendOp);
    903 			renderState.fragOps.blendAState.srcFunc		= mapVkBlendFactor(blendState.srcAlphaBlendFactor);
    904 			renderState.fragOps.blendAState.dstFunc		= mapVkBlendFactor(blendState.dstAlphaBlendFactor);
    905 			renderState.fragOps.blendAState.equation	= mapVkBlendOp(blendState.alphaBlendOp);
    906 			renderState.fragOps.blendColor				= BlendTest::s_blendConst;
    907 			renderState.fragOps.colorMask				= mapVkColorComponentFlags(BlendTest::s_colorWriteMasks[quadNdx]);
    908 
    909 			refRenderer.draw(renderState,
    910 							 rr::PRIMITIVETYPE_TRIANGLES,
    911 							 std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
    912 													  m_vertices.begin() + (quadNdx + 1) * 6));
    913 		}
    914 	}
    915 
    916 
    917 	// Compare result with reference image
    918 	{
    919 		const DeviceInterface&				vk							= m_context.getDeviceInterface();
    920 		const VkDevice						vkDevice					= m_context.getDevice();
    921 		const VkQueue						queue						= m_context.getUniversalQueue();
    922 		const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
    923 		SimpleAllocator						allocator					(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
    924 		de::UniquePtr<tcu::TextureLevel>	result						(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
    925 		const tcu::Vec4						threshold					(getFormatThreshold(tcuColorFormat));
    926 
    927 		compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
    928 											   "FloatImageCompare",
    929 											   "Image comparison",
    930 											   refRenderer.getAccess(),
    931 											   result->getAccess(),
    932 											   threshold,
    933 											   tcu::COMPARE_LOG_RESULT);
    934 	}
    935 
    936 	if (compareOk)
    937 		return tcu::TestStatus::pass("Result image matches reference");
    938 	else
    939 		return tcu::TestStatus::fail("Image mismatch");
    940 }
    941 
    942 } // anonymous
    943 
    944 std::string getBlendStateName (const VkPipelineColorBlendAttachmentState& blendState)
    945 {
    946 	const char* shortBlendFactorNames[] =
    947 	{
    948 		"z",		// VK_BLEND_ZERO
    949 		"o",		// VK_BLEND_ONE
    950 		"sc",		// VK_BLEND_SRC_COLOR
    951 		"1msc",		// VK_BLEND_ONE_MINUS_SRC_COLOR
    952 		"dc",		// VK_BLEND_DEST_COLOR
    953 		"1mdc",		// VK_BLEND_ONE_MINUS_DEST_COLOR
    954 		"sa",		// VK_BLEND_SRC_ALPHA
    955 		"1msa",		// VK_BLEND_ONE_MINUS_SRC_ALPHA
    956 		"da",		// VK_BLEND_DEST_ALPHA
    957 		"1mda",		// VK_BLEND_ONE_MINUS_DEST_ALPHA
    958 		"cc",		// VK_BLEND_CONSTANT_COLOR
    959 		"1mcc",		// VK_BLEND_ONE_MINUS_CONSTANT_COLOR
    960 		"ca",		// VK_BLEND_CONSTANT_ALPHA
    961 		"1mca",		// VK_BLEND_ONE_MINUS_CONSTANT_ALPHA
    962 		"sas"		// VK_BLEND_SRC_ALPHA_SATURATE
    963 	};
    964 
    965 	const char* blendOpNames[] =
    966 	{
    967 		"add",		// VK_BLEND_OP_ADD
    968 		"sub",		// VK_BLEND_OP_SUBTRACT
    969 		"rsub",		// VK_BLEND_OP_REVERSE_SUBTRACT
    970 		"min",		// VK_BLEND_OP_MIN
    971 		"max",		// VK_BLEND_OP_MAX
    972 	};
    973 
    974 	std::ostringstream shortName;
    975 
    976 	shortName << "color_" << shortBlendFactorNames[blendState.srcColorBlendFactor] << "_" << shortBlendFactorNames[blendState.dstColorBlendFactor] << "_" << blendOpNames[blendState.colorBlendOp];
    977 	shortName << "_alpha_" << shortBlendFactorNames[blendState.srcAlphaBlendFactor] << "_" << shortBlendFactorNames[blendState.dstAlphaBlendFactor] << "_" << blendOpNames[blendState.alphaBlendOp];
    978 
    979 	return shortName.str();
    980 }
    981 
    982 std::string getBlendStateSetName (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])
    983 {
    984 	std::ostringstream name;
    985 
    986 	for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
    987 	{
    988 		name << getBlendStateName(blendStates[quadNdx]);
    989 
    990 		if (quadNdx < BlendTest::QUAD_COUNT - 1)
    991 			name << "-";
    992 	}
    993 
    994 	return name.str();
    995 }
    996 
    997 std::string getBlendStateSetDescription (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT])
    998 {
    999 	std::ostringstream description;
   1000 
   1001 	description << "Draws " << BlendTest::QUAD_COUNT << " quads with the following blend states:\n";
   1002 
   1003 	for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
   1004 		description << blendStates[quadNdx] << "\n";
   1005 
   1006 	return description.str();
   1007 }
   1008 
   1009 std::string getFormatCaseName (VkFormat format)
   1010 {
   1011 	const std::string fullName = getFormatName(format);
   1012 
   1013 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
   1014 
   1015 	return de::toLower(fullName.substr(10));
   1016 }
   1017 
   1018 tcu::TestCaseGroup* createBlendTests (tcu::TestContext& testCtx)
   1019 {
   1020 	const deUint32 blendStatesPerFormat = 100 * BlendTest::QUAD_COUNT;
   1021 
   1022 	// Formats that are dEQP-compatible, non-integer and uncompressed
   1023 	const VkFormat blendFormats[] =
   1024 	{
   1025 		VK_FORMAT_R4G4_UNORM_PACK8,
   1026 		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
   1027 		VK_FORMAT_R5G6B5_UNORM_PACK16,
   1028 		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
   1029 		VK_FORMAT_R8_UNORM,
   1030 		VK_FORMAT_R8_SNORM,
   1031 		VK_FORMAT_R8_SRGB,
   1032 		VK_FORMAT_R8G8_UNORM,
   1033 		VK_FORMAT_R8G8_SNORM,
   1034 		VK_FORMAT_R8G8_SRGB,
   1035 		VK_FORMAT_R8G8B8_UNORM,
   1036 		VK_FORMAT_R8G8B8_SNORM,
   1037 		VK_FORMAT_R8G8B8_SRGB,
   1038 		VK_FORMAT_R8G8B8A8_UNORM,
   1039 		VK_FORMAT_R8G8B8A8_SNORM,
   1040 		VK_FORMAT_R8G8B8A8_SRGB,
   1041 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
   1042 		VK_FORMAT_R16_UNORM,
   1043 		VK_FORMAT_R16_SNORM,
   1044 		VK_FORMAT_R16_SFLOAT,
   1045 		VK_FORMAT_R16G16_UNORM,
   1046 		VK_FORMAT_R16G16_SNORM,
   1047 		VK_FORMAT_R16G16_SFLOAT,
   1048 		VK_FORMAT_R16G16B16_UNORM,
   1049 		VK_FORMAT_R16G16B16_SNORM,
   1050 		VK_FORMAT_R16G16B16_SFLOAT,
   1051 		VK_FORMAT_R16G16B16A16_UNORM,
   1052 		VK_FORMAT_R16G16B16A16_SNORM,
   1053 		VK_FORMAT_R16G16B16A16_SFLOAT,
   1054 		VK_FORMAT_R32_SFLOAT,
   1055 		VK_FORMAT_R32G32_SFLOAT,
   1056 		VK_FORMAT_R32G32B32_SFLOAT,
   1057 		VK_FORMAT_R32G32B32A32_SFLOAT,
   1058 		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
   1059 		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
   1060 		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
   1061 		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
   1062 	};
   1063 
   1064 	de::MovePtr<tcu::TestCaseGroup>		blendTests		(new tcu::TestCaseGroup(testCtx, "blend", "Blend tests"));
   1065 	de::MovePtr<tcu::TestCaseGroup>		formatTests		(new tcu::TestCaseGroup(testCtx, "format", "Uses different blend formats"));
   1066 	BlendStateUniqueRandomIterator		blendStateItr	(blendStatesPerFormat, 123);
   1067 
   1068 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(blendFormats); formatNdx++)
   1069 	{
   1070 		const VkFormat					format			= blendFormats[formatNdx];
   1071 		de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
   1072 																				getFormatCaseName(format).c_str(),
   1073 																				(std::string("Uses format ") + getFormatName(format)).c_str()));
   1074 		de::MovePtr<tcu::TestCaseGroup>	blendStateTests;
   1075 		{
   1076 			std::ostringstream blendStateDescription;
   1077 			blendStateDescription << "Combines blend factors, operators and channel write masks. The constant color used in all tests is " << BlendTest::s_blendConst;
   1078 			blendStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", blendStateDescription.str().c_str()));
   1079 		}
   1080 
   1081 		blendStateItr.reset();
   1082 
   1083 		while (blendStateItr.hasNext())
   1084 		{
   1085 			VkPipelineColorBlendAttachmentState quadBlendConfigs[BlendTest::QUAD_COUNT];
   1086 
   1087 			for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++)
   1088 			{
   1089 				quadBlendConfigs[quadNdx]					= blendStateItr.next();
   1090 				quadBlendConfigs[quadNdx].colorWriteMask	= BlendTest::s_colorWriteMasks[quadNdx];
   1091 			}
   1092 
   1093 			blendStateTests->addChild(new BlendTest(testCtx,
   1094 													getBlendStateSetName(quadBlendConfigs),
   1095 													getBlendStateSetDescription(quadBlendConfigs),
   1096 													format,
   1097 													quadBlendConfigs));
   1098 		}
   1099 		formatTest->addChild(blendStateTests.release());
   1100 		formatTests->addChild(formatTest.release());
   1101 	}
   1102 	blendTests->addChild(formatTests.release());
   1103 
   1104 	return blendTests.release();
   1105 }
   1106 
   1107 } // pipeline
   1108 } // vkt
   1109