Home | History | Annotate | Download | only in renderpass
      1 /*-------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2017 Google Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Tests for render pass multisample resolve
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "vktRenderPassMultisampleResolveTests.hpp"
     25 
     26 #include "vktTestCaseUtil.hpp"
     27 #include "vktTestGroupUtil.hpp"
     28 
     29 #include "vkDefs.hpp"
     30 #include "vkDeviceUtil.hpp"
     31 #include "vkImageUtil.hpp"
     32 #include "vkMemUtil.hpp"
     33 #include "vkPlatform.hpp"
     34 #include "vkPrograms.hpp"
     35 #include "vkQueryUtil.hpp"
     36 #include "vkRef.hpp"
     37 #include "vkRefUtil.hpp"
     38 #include "vkTypeUtil.hpp"
     39 
     40 #include "tcuFloat.hpp"
     41 #include "tcuImageCompare.hpp"
     42 #include "tcuFormatUtil.hpp"
     43 #include "tcuMaybe.hpp"
     44 #include "tcuResultCollector.hpp"
     45 #include "tcuTestLog.hpp"
     46 #include "tcuTextureUtil.hpp"
     47 #include "tcuVectorUtil.hpp"
     48 
     49 #include "deUniquePtr.hpp"
     50 #include "deSharedPtr.hpp"
     51 
     52 using namespace vk;
     53 
     54 using tcu::BVec4;
     55 using tcu::IVec2;
     56 using tcu::IVec4;
     57 using tcu::UVec2;
     58 using tcu::UVec4;
     59 using tcu::Vec2;
     60 using tcu::Vec4;
     61 
     62 using tcu::Maybe;
     63 using tcu::just;
     64 using tcu::nothing;
     65 
     66 using tcu::ConstPixelBufferAccess;
     67 using tcu::PixelBufferAccess;
     68 
     69 using tcu::TestLog;
     70 
     71 using std::pair;
     72 using std::string;
     73 using std::vector;
     74 
     75 typedef de::SharedPtr<vk::Unique<VkImage> >		VkImageSp;
     76 typedef de::SharedPtr<vk::Unique<VkImageView> >	VkImageViewSp;
     77 typedef de::SharedPtr<vk::Unique<VkBuffer> >	VkBufferSp;
     78 typedef de::SharedPtr<vk::Unique<VkPipeline> >	VkPipelineSp;
     79 
     80 namespace vkt
     81 {
     82 namespace
     83 {
     84 enum
     85 {
     86 	MAX_COLOR_ATTACHMENT_COUNT = 4u
     87 };
     88 
     89 template<typename T>
     90 de::SharedPtr<T> safeSharedPtr (T* ptr)
     91 {
     92 	try
     93 	{
     94 		return de::SharedPtr<T>(ptr);
     95 	}
     96 	catch (...)
     97 	{
     98 		delete ptr;
     99 		throw;
    100 	}
    101 }
    102 
    103 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
    104 {
    105 	VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
    106 }
    107 
    108 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
    109 {
    110 	VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
    111 }
    112 
    113 de::MovePtr<Allocation> createBufferMemory (const DeviceInterface&	vk,
    114 											VkDevice				device,
    115 											Allocator&				allocator,
    116 											VkBuffer				buffer)
    117 {
    118 	de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
    119 	bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset());
    120 	return allocation;
    121 }
    122 
    123 de::MovePtr<Allocation> createImageMemory (const DeviceInterface&	vk,
    124 										   VkDevice					device,
    125 										   Allocator&				allocator,
    126 										   VkImage					image)
    127 {
    128 	de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any));
    129 	bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
    130 	return allocation;
    131 }
    132 
    133 Move<VkImage> createImage (const DeviceInterface&	vk,
    134 						   VkDevice					device,
    135 						   VkImageCreateFlags		flags,
    136 						   VkImageType				imageType,
    137 						   VkFormat					format,
    138 						   VkExtent3D				extent,
    139 						   deUint32					mipLevels,
    140 						   deUint32					arrayLayers,
    141 						   VkSampleCountFlagBits	samples,
    142 						   VkImageTiling			tiling,
    143 						   VkImageUsageFlags		usage,
    144 						   VkSharingMode			sharingMode,
    145 						   deUint32					queueFamilyCount,
    146 						   const deUint32*			pQueueFamilyIndices,
    147 						   VkImageLayout			initialLayout)
    148 {
    149 	const VkImageCreateInfo pCreateInfo =
    150 	{
    151 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
    152 		DE_NULL,
    153 		flags,
    154 		imageType,
    155 		format,
    156 		extent,
    157 		mipLevels,
    158 		arrayLayers,
    159 		samples,
    160 		tiling,
    161 		usage,
    162 		sharingMode,
    163 		queueFamilyCount,
    164 		pQueueFamilyIndices,
    165 		initialLayout
    166 	};
    167 	return createImage(vk, device, &pCreateInfo);
    168 }
    169 
    170 Move<VkImageView> createImageView (const DeviceInterface&	vk,
    171 								   VkDevice					device,
    172 								   VkImageViewCreateFlags	flags,
    173 								   VkImage					image,
    174 								   VkImageViewType			viewType,
    175 								   VkFormat					format,
    176 								   VkComponentMapping		components,
    177 								   VkImageSubresourceRange	subresourceRange)
    178 {
    179 	const VkImageViewCreateInfo pCreateInfo =
    180 	{
    181 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
    182 		DE_NULL,
    183 		flags,
    184 		image,
    185 		viewType,
    186 		format,
    187 		components,
    188 		subresourceRange,
    189 	};
    190 	return createImageView(vk, device, &pCreateInfo);
    191 }
    192 
    193 Move<VkImage> createImage (const InstanceInterface&	vki,
    194 						   VkPhysicalDevice			physicalDevice,
    195 						   const DeviceInterface&	vkd,
    196 						   VkDevice					device,
    197 						   VkFormat					vkFormat,
    198 						   VkSampleCountFlagBits	sampleCountBit,
    199 						   VkImageUsageFlags		usage,
    200 						   deUint32					width,
    201 						   deUint32					height)
    202 {
    203 	try
    204 	{
    205 		const tcu::TextureFormat		format					(mapVkFormat(vkFormat));
    206 		const VkImageType				imageType				(VK_IMAGE_TYPE_2D);
    207 		const VkImageTiling				imageTiling				(VK_IMAGE_TILING_OPTIMAL);
    208 		const VkFormatProperties		formatProperties		(getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat));
    209 		const VkImageFormatProperties	imageFormatProperties	(getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u));
    210 		const VkExtent3D				imageExtent				=
    211 		{
    212 			width,
    213 			height,
    214 			1u
    215 		};
    216 
    217 		if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
    218 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
    219 			TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
    220 
    221 		if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
    222 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
    223 			TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
    224 
    225 		if (imageFormatProperties.maxExtent.width < imageExtent.width
    226 			|| imageFormatProperties.maxExtent.height < imageExtent.height
    227 			|| ((imageFormatProperties.sampleCounts & sampleCountBit) == 0))
    228 		{
    229 			TCU_THROW(NotSupportedError, "Image type not supported");
    230 		}
    231 
    232 		return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, 1u, sampleCountBit, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED);
    233 	}
    234 	catch (const vk::Error& error)
    235 	{
    236 		if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
    237 			TCU_THROW(NotSupportedError, "Image format not supported");
    238 
    239 		throw;
    240 	}
    241 }
    242 
    243 Move<VkImageView> createImageView (const DeviceInterface&	vkd,
    244 								   VkDevice					device,
    245 								   VkImage					image,
    246 								   VkFormat					format,
    247 								   VkImageAspectFlags		aspect)
    248 {
    249 	const VkImageSubresourceRange	range =
    250 	{
    251 		aspect,
    252 		0u,
    253 		1u,
    254 		0u,
    255 		1u
    256 	};
    257 
    258 	return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
    259 }
    260 
    261 VkDeviceSize getPixelSize (VkFormat vkFormat)
    262 {
    263 	const tcu::TextureFormat	format	(mapVkFormat(vkFormat));
    264 
    265 	return format.getPixelSize();
    266 }
    267 
    268 Move<VkBuffer> createBuffer (const DeviceInterface&		vkd,
    269 							 VkDevice					device,
    270 							 VkFormat					format,
    271 							 deUint32					width,
    272 							 deUint32					height)
    273 {
    274 	const VkBufferUsageFlags	bufferUsage			(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
    275 	const VkDeviceSize			pixelSize			(getPixelSize(format));
    276 	const VkBufferCreateInfo	createInfo			=
    277 	{
    278 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
    279 		DE_NULL,
    280 		0u,
    281 
    282 		width * height * pixelSize,
    283 		bufferUsage,
    284 
    285 		VK_SHARING_MODE_EXCLUSIVE,
    286 		0u,
    287 		DE_NULL
    288 	};
    289 	return createBuffer(vkd, device, &createInfo);
    290 }
    291 
    292 VkSampleCountFlagBits sampleCountBitFromSampleCount (deUint32 count)
    293 {
    294 	switch (count)
    295 	{
    296 		case 1:  return VK_SAMPLE_COUNT_1_BIT;
    297 		case 2:  return VK_SAMPLE_COUNT_2_BIT;
    298 		case 4:  return VK_SAMPLE_COUNT_4_BIT;
    299 		case 8:  return VK_SAMPLE_COUNT_8_BIT;
    300 		case 16: return VK_SAMPLE_COUNT_16_BIT;
    301 		case 32: return VK_SAMPLE_COUNT_32_BIT;
    302 		case 64: return VK_SAMPLE_COUNT_64_BIT;
    303 
    304 		default:
    305 			DE_FATAL("Invalid sample count");
    306 			return (VkSampleCountFlagBits)0x0;
    307 	}
    308 }
    309 
    310 std::vector<VkImageSp> createMultisampleImages (const InstanceInterface&	vki,
    311 												VkPhysicalDevice			physicalDevice,
    312 												const DeviceInterface&		vkd,
    313 												VkDevice					device,
    314 												VkFormat					format,
    315 												deUint32					sampleCount,
    316 												deUint32					width,
    317 												deUint32					height)
    318 {
    319 	std::vector<VkImageSp> images (MAX_COLOR_ATTACHMENT_COUNT);
    320 
    321 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
    322 		images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromSampleCount(sampleCount), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height)));
    323 
    324 	return images;
    325 }
    326 
    327 std::vector<VkImageSp> createSingleSampleImages (const InstanceInterface&	vki,
    328 												 VkPhysicalDevice			physicalDevice,
    329 												 const DeviceInterface&		vkd,
    330 												 VkDevice					device,
    331 												 VkFormat					format,
    332 												 deUint32					width,
    333 												 deUint32					height)
    334 {
    335 	std::vector<VkImageSp> images (MAX_COLOR_ATTACHMENT_COUNT);
    336 
    337 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
    338 		images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, width, height)));
    339 
    340 	return images;
    341 }
    342 
    343 std::vector<de::SharedPtr<Allocation> > createImageMemory (const DeviceInterface&		vkd,
    344 														   VkDevice						device,
    345 														   Allocator&					allocator,
    346 														   const std::vector<VkImageSp>	images)
    347 {
    348 	std::vector<de::SharedPtr<Allocation> > memory (images.size());
    349 
    350 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
    351 		memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release());
    352 
    353 	return memory;
    354 }
    355 
    356 std::vector<VkImageViewSp> createImageViews (const DeviceInterface&			vkd,
    357 											 VkDevice						device,
    358 											 const std::vector<VkImageSp>&	images,
    359 											 VkFormat						format,
    360 											 VkImageAspectFlagBits			aspect)
    361 {
    362 	std::vector<VkImageViewSp> views (images.size());
    363 
    364 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
    365 		views[imageNdx] = safeSharedPtr(new Unique<VkImageView>(createImageView(vkd, device, **images[imageNdx], format, aspect)));
    366 
    367 	return views;
    368 }
    369 
    370 std::vector<VkBufferSp> createBuffers (const DeviceInterface&	vkd,
    371 									   VkDevice					device,
    372 									   VkFormat					format,
    373 									   deUint32					width,
    374 									   deUint32					height)
    375 {
    376 	std::vector<VkBufferSp> buffers (MAX_COLOR_ATTACHMENT_COUNT);
    377 
    378 	for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
    379 		buffers[bufferNdx] = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vkd, device, format, width, height)));
    380 
    381 	return buffers;
    382 }
    383 
    384 std::vector<de::SharedPtr<Allocation> > createBufferMemory (const DeviceInterface&			vkd,
    385 															VkDevice						device,
    386 															Allocator&						allocator,
    387 															const std::vector<VkBufferSp>	buffers)
    388 {
    389 	std::vector<de::SharedPtr<Allocation> > memory (buffers.size());
    390 
    391 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
    392 		memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release());
    393 
    394 	return memory;
    395 }
    396 
    397 Move<VkRenderPass> createRenderPass (const DeviceInterface&	vkd,
    398 									 VkDevice				device,
    399 									 VkFormat				format,
    400 									 deUint32				sampleCount)
    401 {
    402 	const VkSampleCountFlagBits				samples						(sampleCountBitFromSampleCount(sampleCount));
    403 	std::vector<VkAttachmentDescription>	attachments;
    404 	std::vector<VkAttachmentReference>		colorAttachmentRefs;
    405 	std::vector<VkAttachmentReference>		resolveAttachmentRefs;
    406 
    407 	for (size_t attachmentNdx = 0; attachmentNdx < 4; attachmentNdx++)
    408 	{
    409 		{
    410 			const VkAttachmentDescription multisampleAttachment =
    411 			{
    412 				0u,
    413 
    414 				format,
    415 				samples,
    416 
    417 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    418 				VK_ATTACHMENT_STORE_OP_DONT_CARE,
    419 
    420 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    421 				VK_ATTACHMENT_STORE_OP_DONT_CARE,
    422 
    423 				VK_IMAGE_LAYOUT_UNDEFINED,
    424 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
    425 			};
    426 			const VkAttachmentReference attachmentRef =
    427 			{
    428 				(deUint32)attachments.size(),
    429 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
    430 			};
    431 			colorAttachmentRefs.push_back(attachmentRef);
    432 			attachments.push_back(multisampleAttachment);
    433 		}
    434 		{
    435 			const VkAttachmentDescription singlesampleAttachment =
    436 			{
    437 				0u,
    438 
    439 				format,
    440 				VK_SAMPLE_COUNT_1_BIT,
    441 
    442 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    443 				VK_ATTACHMENT_STORE_OP_STORE,
    444 
    445 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    446 				VK_ATTACHMENT_STORE_OP_DONT_CARE,
    447 
    448 				VK_IMAGE_LAYOUT_UNDEFINED,
    449 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
    450 			};
    451 			const VkAttachmentReference attachmentRef =
    452 			{
    453 				(deUint32)attachments.size(),
    454 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
    455 			};
    456 			resolveAttachmentRefs.push_back(attachmentRef);
    457 			attachments.push_back(singlesampleAttachment);
    458 		}
    459 	}
    460 
    461 	DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
    462 	DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
    463 
    464 	{
    465 		const VkSubpassDescription	subpass =
    466 		{
    467 			(VkSubpassDescriptionFlags)0,
    468 			VK_PIPELINE_BIND_POINT_GRAPHICS,
    469 
    470 			0u,
    471 			DE_NULL,
    472 
    473 			(deUint32)colorAttachmentRefs.size(),
    474 			&colorAttachmentRefs[0],
    475 			&resolveAttachmentRefs[0],
    476 
    477 			DE_NULL,
    478 			0u,
    479 			DE_NULL
    480 		};
    481 		const VkRenderPassCreateInfo	createInfo	=
    482 		{
    483 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
    484 			DE_NULL,
    485 			(VkRenderPassCreateFlags)0u,
    486 
    487 			(deUint32)attachments.size(),
    488 			&attachments[0],
    489 
    490 			1u,
    491 			&subpass,
    492 
    493 			0u,
    494 			DE_NULL
    495 		};
    496 
    497 		return createRenderPass(vkd, device, &createInfo);
    498 	}
    499 }
    500 
    501 Move<VkFramebuffer> createFramebuffer (const DeviceInterface&			vkd,
    502 									   VkDevice							device,
    503 									   VkRenderPass						renderPass,
    504 									   const std::vector<VkImageViewSp>&	multisampleImageViews,
    505 									   const std::vector<VkImageViewSp>&	singlesampleImageViews,
    506 									   deUint32							width,
    507 									   deUint32							height)
    508 {
    509 	std::vector<VkImageView> attachments;
    510 
    511 	attachments.reserve(multisampleImageViews.size() + singlesampleImageViews.size());
    512 
    513 	DE_ASSERT(multisampleImageViews.size() == singlesampleImageViews.size());
    514 
    515 	for (size_t ndx = 0; ndx < multisampleImageViews.size(); ndx++)
    516 	{
    517 		attachments.push_back(**multisampleImageViews[ndx]);
    518 		attachments.push_back(**singlesampleImageViews[ndx]);
    519 	}
    520 
    521 	const VkFramebufferCreateInfo createInfo =
    522 	{
    523 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
    524 		DE_NULL,
    525 		0u,
    526 
    527 		renderPass,
    528 		(deUint32)attachments.size(),
    529 		&attachments[0],
    530 
    531 		width,
    532 		height,
    533 		1u
    534 	};
    535 
    536 	return createFramebuffer(vkd, device, &createInfo);
    537 }
    538 
    539 Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface&	vkd,
    540 												   VkDevice					device)
    541 {
    542 	const VkPushConstantRange			pushConstant			=
    543 	{
    544 		VK_SHADER_STAGE_FRAGMENT_BIT,
    545 		0u,
    546 		4u
    547 	};
    548 	const VkPipelineLayoutCreateInfo	createInfo	=
    549 	{
    550 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
    551 		DE_NULL,
    552 		(vk::VkPipelineLayoutCreateFlags)0,
    553 
    554 		0u,
    555 		DE_NULL,
    556 
    557 		1u,
    558 		&pushConstant
    559 	};
    560 
    561 	return createPipelineLayout(vkd, device, &createInfo);
    562 }
    563 
    564 Move<VkPipeline> createRenderPipeline (const DeviceInterface&							vkd,
    565 									   VkDevice											device,
    566 									   VkRenderPass										renderPass,
    567 									   VkPipelineLayout									pipelineLayout,
    568 									   const vk::ProgramCollection<vk::ProgramBinary>&	binaryCollection,
    569 									   deUint32											width,
    570 									   deUint32											height,
    571 									   deUint32											sampleCount)
    572 {
    573 	const Unique<VkShaderModule>	vertexShaderModule			(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
    574 	const Unique<VkShaderModule>	fragmentShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
    575 	const VkSpecializationInfo		emptyShaderSpecializations	=
    576 	{
    577 		0u,
    578 		DE_NULL,
    579 
    580 		0u,
    581 		DE_NULL
    582 	};
    583 	// Disable blending
    584 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
    585 	{
    586 		VK_FALSE,
    587 		VK_BLEND_FACTOR_SRC_ALPHA,
    588 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
    589 		VK_BLEND_OP_ADD,
    590 		VK_BLEND_FACTOR_ONE,
    591 		VK_BLEND_FACTOR_ONE,
    592 		VK_BLEND_OP_ADD,
    593 		VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
    594 	};
    595 	const VkPipelineColorBlendAttachmentState attachmentBlendStates[] =
    596 	{
    597 		attachmentBlendState,
    598 		attachmentBlendState,
    599 		attachmentBlendState,
    600 		attachmentBlendState,
    601 	};
    602 	const VkPipelineShaderStageCreateInfo shaderStages[2] =
    603 	{
    604 		{
    605 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
    606 			DE_NULL,
    607 			(VkPipelineShaderStageCreateFlags)0u,
    608 			VK_SHADER_STAGE_VERTEX_BIT,
    609 			*vertexShaderModule,
    610 			"main",
    611 			&emptyShaderSpecializations
    612 		},
    613 		{
    614 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
    615 			DE_NULL,
    616 			(VkPipelineShaderStageCreateFlags)0u,
    617 			VK_SHADER_STAGE_FRAGMENT_BIT,
    618 			*fragmentShaderModule,
    619 			"main",
    620 			&emptyShaderSpecializations
    621 		}
    622 	};
    623 	const VkPipelineVertexInputStateCreateInfo vertexInputState =
    624 	{
    625 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
    626 		DE_NULL,
    627 		(VkPipelineVertexInputStateCreateFlags)0u,
    628 
    629 		0u,
    630 		DE_NULL,
    631 
    632 		0u,
    633 		DE_NULL
    634 	};
    635 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
    636 	{
    637 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
    638 		DE_NULL,
    639 
    640 		(VkPipelineInputAssemblyStateCreateFlags)0u,
    641 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
    642 		VK_FALSE
    643 	};
    644 	const VkViewport viewport =
    645 	{
    646 		0.0f,  0.0f,
    647 		(float)width, (float)height,
    648 
    649 		0.0f, 1.0f
    650 	};
    651 	const VkRect2D scissor =
    652 	{
    653 		{ 0u, 0u },
    654 		{ width, height }
    655 	};
    656 	const VkPipelineViewportStateCreateInfo viewportState =
    657 	{
    658 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
    659 		DE_NULL,
    660 		(VkPipelineViewportStateCreateFlags)0u,
    661 
    662 		1u,
    663 		&viewport,
    664 
    665 		1u,
    666 		&scissor
    667 	};
    668 	const VkPipelineRasterizationStateCreateInfo rasterState =
    669 	{
    670 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
    671 		DE_NULL,
    672 		(VkPipelineRasterizationStateCreateFlags)0u,
    673 		VK_TRUE,
    674 		VK_FALSE,
    675 		VK_POLYGON_MODE_FILL,
    676 		VK_CULL_MODE_NONE,
    677 		VK_FRONT_FACE_COUNTER_CLOCKWISE,
    678 		VK_FALSE,
    679 		0.0f,
    680 		0.0f,
    681 		0.0f,
    682 		1.0f
    683 	};
    684 	const VkPipelineMultisampleStateCreateInfo multisampleState =
    685 	{
    686 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
    687 		DE_NULL,
    688 		(VkPipelineMultisampleStateCreateFlags)0u,
    689 
    690 		sampleCountBitFromSampleCount(sampleCount),
    691 		VK_FALSE,
    692 		0.0f,
    693 		DE_NULL,
    694 		VK_FALSE,
    695 		VK_FALSE,
    696 	};
    697 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
    698 	{
    699 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
    700 		DE_NULL,
    701 		(VkPipelineDepthStencilStateCreateFlags)0u,
    702 
    703 		VK_FALSE,
    704 		VK_TRUE,
    705 		VK_COMPARE_OP_ALWAYS,
    706 		VK_FALSE,
    707 		VK_TRUE,
    708 		{
    709 			VK_STENCIL_OP_KEEP,
    710 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
    711 			VK_STENCIL_OP_KEEP,
    712 			VK_COMPARE_OP_ALWAYS,
    713 			~0u,
    714 			~0u,
    715 			0xFFu / (sampleCount + 1)
    716 		},
    717 		{
    718 			VK_STENCIL_OP_KEEP,
    719 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
    720 			VK_STENCIL_OP_KEEP,
    721 			VK_COMPARE_OP_ALWAYS,
    722 			~0u,
    723 			~0u,
    724 			0xFFu / (sampleCount + 1)
    725 		},
    726 
    727 		0.0f,
    728 		1.0f
    729 	};
    730 	const VkPipelineColorBlendStateCreateInfo blendState =
    731 	{
    732 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
    733 		DE_NULL,
    734 		(VkPipelineColorBlendStateCreateFlags)0u,
    735 
    736 		VK_FALSE,
    737 		VK_LOGIC_OP_COPY,
    738 		DE_LENGTH_OF_ARRAY(attachmentBlendStates),
    739 		attachmentBlendStates,
    740 		{ 0.0f, 0.0f, 0.0f, 0.0f }
    741 	};
    742 	const VkGraphicsPipelineCreateInfo createInfo =
    743 	{
    744 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
    745 		DE_NULL,
    746 		(VkPipelineCreateFlags)0u,
    747 
    748 		2,
    749 		shaderStages,
    750 
    751 		&vertexInputState,
    752 		&inputAssemblyState,
    753 		DE_NULL,
    754 		&viewportState,
    755 		&rasterState,
    756 		&multisampleState,
    757 		&depthStencilState,
    758 		&blendState,
    759 		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,
    760 		pipelineLayout,
    761 
    762 		renderPass,
    763 		0u,
    764 		DE_NULL,
    765 		0u
    766 	};
    767 
    768 	return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
    769 }
    770 
    771 struct TestConfig
    772 {
    773 				TestConfig		(VkFormat	format_,
    774 								 deUint32	sampleCount_)
    775 		: format		(format_)
    776 		, sampleCount	(sampleCount_)
    777 	{
    778 	}
    779 
    780 	VkFormat	format;
    781 	deUint32	sampleCount;
    782 };
    783 
    784 class MultisampleRenderPassTestInstance : public TestInstance
    785 {
    786 public:
    787 													MultisampleRenderPassTestInstance	(Context& context, TestConfig config);
    788 													~MultisampleRenderPassTestInstance	(void);
    789 
    790 	tcu::TestStatus									iterate								(void);
    791 
    792 private:
    793 	void											submit								(void);
    794 	void											verify								(void);
    795 
    796 	const VkFormat									m_format;
    797 	const deUint32									m_sampleCount;
    798 	const deUint32									m_width;
    799 	const deUint32									m_height;
    800 
    801 	const std::vector<VkImageSp>					m_multisampleImages;
    802 	const std::vector<de::SharedPtr<Allocation> >	m_multisampleImageMemory;
    803 	const std::vector<VkImageViewSp>				m_multisampleImageViews;
    804 
    805 	const std::vector<VkImageSp>					m_singlesampleImages;
    806 	const std::vector<de::SharedPtr<Allocation> >	m_singlesampleImageMemory;
    807 	const std::vector<VkImageViewSp>				m_singlesampleImageViews;
    808 
    809 	const Unique<VkRenderPass>						m_renderPass;
    810 	const Unique<VkFramebuffer>						m_framebuffer;
    811 
    812 	const Unique<VkPipelineLayout>					m_renderPipelineLayout;
    813 	const Unique<VkPipeline>						m_renderPipeline;
    814 
    815 	const std::vector<VkBufferSp>					m_buffers;
    816 	const std::vector<de::SharedPtr<Allocation> >	m_bufferMemory;
    817 
    818 	const Unique<VkCommandPool>						m_commandPool;
    819 	tcu::TextureLevel								m_sum;
    820 	deUint32										m_sampleMask;
    821 	tcu::ResultCollector							m_resultCollector;
    822 };
    823 
    824 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
    825 	: TestInstance				(context)
    826 	, m_format					(config.format)
    827 	, m_sampleCount				(config.sampleCount)
    828 	, m_width					(32u)
    829 	, m_height					(32u)
    830 
    831 	, m_multisampleImages		(createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_format, m_sampleCount, m_width, m_height))
    832 	, m_multisampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_multisampleImages))
    833 	, m_multisampleImageViews	(createImageViews(context.getDeviceInterface(), context.getDevice(), m_multisampleImages, m_format, VK_IMAGE_ASPECT_COLOR_BIT))
    834 
    835 	, m_singlesampleImages		(createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_format, m_width, m_height))
    836 	, m_singlesampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_singlesampleImages))
    837 	, m_singlesampleImageViews	(createImageViews(context.getDeviceInterface(), context.getDevice(), m_singlesampleImages, m_format, VK_IMAGE_ASPECT_COLOR_BIT))
    838 
    839 	, m_renderPass				(createRenderPass(context.getDeviceInterface(), context.getDevice(), m_format, m_sampleCount))
    840 	, m_framebuffer				(createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, m_multisampleImageViews, m_singlesampleImageViews, m_width, m_height))
    841 
    842 	, m_renderPipelineLayout	(createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
    843 	, m_renderPipeline			(createRenderPipeline(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
    844 
    845 	, m_buffers					(createBuffers(context.getDeviceInterface(), context.getDevice(), m_format, m_width, m_height))
    846 	, m_bufferMemory			(createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_buffers))
    847 
    848 	, m_commandPool				(createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
    849 	, m_sum						(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height)
    850 	, m_sampleMask				(0x0u)
    851 {
    852 	tcu::clear(m_sum.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
    853 }
    854 
    855 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
    856 {
    857 }
    858 
    859 void MultisampleRenderPassTestInstance::submit (void)
    860 {
    861 	const DeviceInterface&			vkd				(m_context.getDeviceInterface());
    862 	const VkDevice					device			(m_context.getDevice());
    863 	const Unique<VkCommandBuffer>	commandBuffer	(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
    864 
    865 	{
    866 		const VkCommandBufferBeginInfo beginInfo =
    867 		{
    868 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
    869 			DE_NULL,
    870 
    871 			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
    872 			DE_NULL
    873 		};
    874 
    875 		VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
    876 	}
    877 
    878 	{
    879 		const VkRenderPassBeginInfo beginInfo =
    880 		{
    881 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
    882 			DE_NULL,
    883 
    884 			*m_renderPass,
    885 			*m_framebuffer,
    886 
    887 			{
    888 				{ 0u, 0u },
    889 				{ m_width, m_height }
    890 			},
    891 
    892 			0u,
    893 			DE_NULL
    894 		};
    895 		vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
    896 	}
    897 
    898 	// Memory barriers between previous copies and rendering
    899 	{
    900 		std::vector<VkImageMemoryBarrier> barriers;
    901 
    902 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
    903 		{
    904 			const VkImageMemoryBarrier barrier =
    905 			{
    906 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
    907 				DE_NULL,
    908 
    909 				VK_ACCESS_TRANSFER_READ_BIT,
    910 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
    911 
    912 				VK_IMAGE_LAYOUT_UNDEFINED,
    913 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
    914 
    915 				VK_QUEUE_FAMILY_IGNORED,
    916 				VK_QUEUE_FAMILY_IGNORED,
    917 
    918 				**m_singlesampleImages[dstNdx],
    919 				{
    920 					VK_IMAGE_ASPECT_COLOR_BIT,
    921 					0u,
    922 					1u,
    923 					0u,
    924 					1u
    925 				}
    926 			};
    927 
    928 			barriers.push_back(barrier);
    929 		}
    930 
    931 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
    932 	}
    933 
    934 	// Clear everything to black
    935 	{
    936 		const tcu::TextureFormat			format			(mapVkFormat(m_format));
    937 		const tcu::TextureChannelClass		channelClass	(tcu::getTextureChannelClass(format.type));
    938 		VkClearValue						value;
    939 
    940 		switch (channelClass)
    941 		{
    942 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    943 				value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
    944 				break;
    945 
    946 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    947 				value = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
    948 				break;
    949 
    950 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    951 				value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
    952 				break;
    953 
    954 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    955 				value = makeClearValueColorI32(-128, -128, -128, -128);
    956 				break;
    957 
    958 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    959 				value = makeClearValueColorU32(0u, 0u, 0u, 0u);
    960 				break;
    961 
    962 			default:
    963 				DE_FATAL("Unknown channel class");
    964 		}
    965 		const VkClearAttachment				colors[]		=
    966 		{
    967 			{
    968 				VK_IMAGE_ASPECT_COLOR_BIT,
    969 				0u,
    970 				value
    971 			},
    972 			{
    973 				VK_IMAGE_ASPECT_COLOR_BIT,
    974 				1u,
    975 				value
    976 			},
    977 			{
    978 				VK_IMAGE_ASPECT_COLOR_BIT,
    979 				2u,
    980 				value
    981 			},
    982 			{
    983 				VK_IMAGE_ASPECT_COLOR_BIT,
    984 				3u,
    985 				value
    986 			}
    987 		};
    988 		const VkClearRect rect =
    989 		{
    990 			{
    991 				{ 0u, 0u },
    992 				{ m_width, m_height }
    993 			},
    994 			0u,
    995 			1u,
    996 		};
    997 		vkd.cmdClearAttachments(*commandBuffer, DE_LENGTH_OF_ARRAY(colors), colors, 1u, &rect);
    998 	}
    999 
   1000 	// Render black samples
   1001 	{
   1002 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
   1003 		vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(m_sampleMask), &m_sampleMask);
   1004 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
   1005 	}
   1006 
   1007 	vkd.cmdEndRenderPass(*commandBuffer);
   1008 
   1009 	// Memory barriers between rendering and copies
   1010 	{
   1011 		std::vector<VkImageMemoryBarrier> barriers;
   1012 
   1013 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
   1014 		{
   1015 			const VkImageMemoryBarrier barrier =
   1016 			{
   1017 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
   1018 				DE_NULL,
   1019 
   1020 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
   1021 				VK_ACCESS_TRANSFER_READ_BIT,
   1022 
   1023 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1024 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1025 
   1026 				VK_QUEUE_FAMILY_IGNORED,
   1027 				VK_QUEUE_FAMILY_IGNORED,
   1028 
   1029 				**m_singlesampleImages[dstNdx],
   1030 				{
   1031 					VK_IMAGE_ASPECT_COLOR_BIT,
   1032 					0u,
   1033 					1u,
   1034 					0u,
   1035 					1u
   1036 				}
   1037 			};
   1038 
   1039 			barriers.push_back(barrier);
   1040 		}
   1041 
   1042 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
   1043 	}
   1044 
   1045 	// Copy image memory to buffers
   1046 	for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
   1047 	{
   1048 		const VkBufferImageCopy region =
   1049 		{
   1050 			0u,
   1051 			0u,
   1052 			0u,
   1053 			{
   1054 				VK_IMAGE_ASPECT_COLOR_BIT,
   1055 				0u,
   1056 				0u,
   1057 				1u,
   1058 			},
   1059 			{ 0u, 0u, 0u },
   1060 			{ m_width, m_height, 1u }
   1061 		};
   1062 
   1063 		vkd.cmdCopyImageToBuffer(*commandBuffer, **m_singlesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_buffers[dstNdx], 1u, &region);
   1064 	}
   1065 
   1066 	// Memory barriers between copies and host access
   1067 	{
   1068 		std::vector<VkBufferMemoryBarrier> barriers;
   1069 
   1070 		for (size_t dstNdx = 0; dstNdx < m_buffers.size(); dstNdx++)
   1071 		{
   1072 			const VkBufferMemoryBarrier barrier =
   1073 			{
   1074 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
   1075 				DE_NULL,
   1076 
   1077 				VK_ACCESS_TRANSFER_WRITE_BIT,
   1078 				VK_ACCESS_HOST_READ_BIT,
   1079 
   1080 				VK_QUEUE_FAMILY_IGNORED,
   1081 				VK_QUEUE_FAMILY_IGNORED,
   1082 
   1083 				**m_buffers[dstNdx],
   1084 				0u,
   1085 				VK_WHOLE_SIZE
   1086 			};
   1087 
   1088 			barriers.push_back(barrier);
   1089 		}
   1090 
   1091 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0], 0u, DE_NULL);
   1092 	}
   1093 
   1094 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
   1095 
   1096 	{
   1097 		const VkSubmitInfo submitInfo =
   1098 		{
   1099 			VK_STRUCTURE_TYPE_SUBMIT_INFO,
   1100 			DE_NULL,
   1101 
   1102 			0u,
   1103 			DE_NULL,
   1104 			DE_NULL,
   1105 
   1106 			1u,
   1107 			&*commandBuffer,
   1108 
   1109 			0u,
   1110 			DE_NULL
   1111 		};
   1112 
   1113 		VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u));
   1114 
   1115 		VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue()));
   1116 	}
   1117 }
   1118 
   1119 void MultisampleRenderPassTestInstance::verify (void)
   1120 {
   1121 	const Vec4							errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
   1122 	const Vec4							okColor			(0.0f, 0.0f, 0.0f, 1.0f);
   1123 	const tcu::TextureFormat			format			(mapVkFormat(m_format));
   1124 	const tcu::TextureChannelClass		channelClass	(tcu::getTextureChannelClass(format.type));
   1125 	const void* const					ptrs[]			=
   1126 	{
   1127 		m_bufferMemory[0]->getHostPtr(),
   1128 		m_bufferMemory[1]->getHostPtr(),
   1129 		m_bufferMemory[2]->getHostPtr(),
   1130 		m_bufferMemory[3]->getHostPtr()
   1131 	};
   1132 	const tcu::ConstPixelBufferAccess	accesses[]		=
   1133 	{
   1134 		tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[0]),
   1135 		tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[1]),
   1136 		tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[2]),
   1137 		tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[3])
   1138 	};
   1139 	tcu::TextureLevel					errorMask		(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height);
   1140 	tcu::TestLog&						log				(m_context.getTestContext().getLog());
   1141 
   1142 	switch (channelClass)
   1143 	{
   1144 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1145 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1146 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1147 		{
   1148 			const int	componentCount	(tcu::getNumUsedChannels(format.order));
   1149 			bool		isOk			= true;
   1150 			float		clearValue;
   1151 			float		renderValue;
   1152 
   1153 			switch (channelClass)
   1154 			{
   1155 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1156 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1157 					clearValue  = -1.0f;
   1158 					renderValue = 1.0f;
   1159 					break;
   1160 
   1161 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1162 					clearValue  = 0.0f;
   1163 					renderValue = 1.0f;
   1164 					break;
   1165 
   1166 				default:
   1167 					clearValue  = 0.0f;
   1168 					renderValue = 0.0f;
   1169 					DE_FATAL("Unknown channel class");
   1170 			}
   1171 
   1172 			for (deUint32 y = 0; y < m_height; y++)
   1173 			for (deUint32 x = 0; x < m_width; x++)
   1174 			{
   1175 				// Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
   1176 				const Vec4	firstColor	(accesses[0].getPixel(x, y));
   1177 				const Vec4	refColor	(m_sampleMask == 0x0u
   1178 										? Vec4(clearValue,
   1179 												componentCount > 1 ? clearValue : 0.0f,
   1180 												componentCount > 2 ? clearValue : 0.0f,
   1181 												componentCount > 3 ? clearValue : 1.0f)
   1182 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
   1183 										? Vec4(renderValue,
   1184 												componentCount > 1 ? renderValue : 0.0f,
   1185 												componentCount > 2 ? renderValue : 0.0f,
   1186 												componentCount > 3 ? renderValue : 1.0f)
   1187 										: firstColor);
   1188 
   1189 				errorMask.getAccess().setPixel(okColor, x, y);
   1190 
   1191 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
   1192 				{
   1193 					const Vec4 color (accesses[attachmentNdx].getPixel(x, y));
   1194 
   1195 					if (refColor != color)
   1196 					{
   1197 						isOk = false;
   1198 						errorMask.getAccess().setPixel(errorColor, x, y);
   1199 						break;
   1200 					}
   1201 				}
   1202 
   1203 				{
   1204 					const Vec4 old = m_sum.getAccess().getPixel(x, y);
   1205 
   1206 					m_sum.getAccess().setPixel(old + firstColor, x, y);
   1207 				}
   1208 			}
   1209 
   1210 			if (!isOk)
   1211 			{
   1212 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
   1213 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
   1214 
   1215 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
   1216 				{
   1217 					const std::string	name	("Attachment" + de::toString(attachmentNdx));
   1218 					m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), accesses[attachmentNdx]);
   1219 				}
   1220 
   1221 				m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
   1222 
   1223 				if (m_sampleMask == 0x0u)
   1224 				{
   1225 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
   1226 					m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
   1227 				}
   1228 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
   1229 				{
   1230 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
   1231 					m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
   1232 				}
   1233 				else
   1234 				{
   1235 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve is inconsistent between attachments" << tcu::TestLog::EndMessage;
   1236 					m_resultCollector.fail("Resolve is inconsistent between attachments");
   1237 				}
   1238 			}
   1239 			break;
   1240 		}
   1241 
   1242 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1243 		{
   1244 			const int		componentCount			(tcu::getNumUsedChannels(format.order));
   1245 			const UVec4		bitDepth				(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1246 			const UVec4		renderValue				(tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
   1247 																  UVec4(0u, 0u, 0u, 1u),
   1248 																  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
   1249 			const UVec4		clearValue				(tcu::select(UVec4(0u),
   1250 																 UVec4(0u, 0u, 0u, 1u),
   1251 																 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
   1252 			bool			unexpectedValues		= false;
   1253 			bool			inconsistentComponents	= false;
   1254 			bool			inconsistentAttachments	= false;
   1255 
   1256 			for (deUint32 y = 0; y < m_height; y++)
   1257 			for (deUint32 x = 0; x < m_width; x++)
   1258 			{
   1259 				// Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
   1260 				const UVec4 refColor	(m_sampleMask == 0x0u
   1261 										? clearValue
   1262 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
   1263 										? renderValue
   1264 										: accesses[0].getPixelUint(x, y));
   1265 
   1266 				errorMask.getAccess().setPixel(okColor, x, y);
   1267 
   1268 				// If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
   1269 				if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
   1270 				{
   1271 					// Each component must be resolved same way
   1272 					const BVec4		isRenderValue	(refColor == renderValue);
   1273 					const BVec4		isClearValue	(refColor == clearValue);
   1274 
   1275 					unexpectedValues		= tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true));
   1276 					inconsistentComponents	= !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true)));
   1277 
   1278 					if (unexpectedValues || inconsistentComponents)
   1279 						errorMask.getAccess().setPixel(errorColor, x, y);
   1280 				}
   1281 
   1282 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
   1283 				{
   1284 					const UVec4 color (accesses[attachmentNdx].getPixelUint(x, y));
   1285 
   1286 					if (refColor != color)
   1287 					{
   1288 						inconsistentAttachments = true;
   1289 						errorMask.getAccess().setPixel(errorColor, x, y);
   1290 						break;
   1291 					}
   1292 				}
   1293 			}
   1294 
   1295 			if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
   1296 			{
   1297 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
   1298 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
   1299 
   1300 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
   1301 				{
   1302 					const std::string	name	("Attachment" + de::toString(attachmentNdx));
   1303 					m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), accesses[attachmentNdx]);
   1304 				}
   1305 
   1306 				m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
   1307 
   1308 				if (m_sampleMask == 0x0u)
   1309 				{
   1310 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
   1311 					m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
   1312 				}
   1313 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
   1314 				{
   1315 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
   1316 					m_resultCollector.fail("Full sample mask didn't produce correct pixels");
   1317 				}
   1318 				else
   1319 				{
   1320 					if (unexpectedValues)
   1321 					{
   1322 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
   1323 						m_resultCollector.fail("Resolve produced unexpected values");
   1324 					}
   1325 
   1326 					if (inconsistentComponents)
   1327 					{
   1328 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
   1329 						m_resultCollector.fail("Different components of attachment were resolved to different values.");
   1330 					}
   1331 
   1332 					if (inconsistentAttachments)
   1333 					{
   1334 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
   1335 						m_resultCollector.fail("Different attachments were resolved to different values.");
   1336 					}
   1337 				}
   1338 			}
   1339 			break;
   1340 		}
   1341 
   1342 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1343 		{
   1344 			const int		componentCount			(tcu::getNumUsedChannels(format.order));
   1345 			const IVec4		bitDepth				(tcu::getTextureFormatBitDepth(format));
   1346 			const IVec4		renderValue				(tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
   1347 																  IVec4(0, 0, 0, 1),
   1348 																  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
   1349 			const IVec4		clearValue				(tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))),
   1350 																 IVec4(0, 0, 0, 1),
   1351 																 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
   1352 			bool			unexpectedValues		= false;
   1353 			bool			inconsistentComponents	= false;
   1354 			bool			inconsistentAttachments	= false;
   1355 
   1356 			for (deUint32 y = 0; y < m_height; y++)
   1357 			for (deUint32 x = 0; x < m_width; x++)
   1358 			{
   1359 				// Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
   1360 				const IVec4 refColor	(m_sampleMask == 0x0u
   1361 										? clearValue
   1362 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
   1363 										? renderValue
   1364 										: accesses[0].getPixelInt(x, y));
   1365 
   1366 				errorMask.getAccess().setPixel(okColor, x, y);
   1367 
   1368 				// If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
   1369 				if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
   1370 				{
   1371 					// Each component must be resolved same way
   1372 					const BVec4		isRenderValue	(refColor == renderValue);
   1373 					const BVec4		isClearValue	(refColor == clearValue);
   1374 
   1375 					unexpectedValues		= tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true));
   1376 					inconsistentComponents	= !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true)));
   1377 
   1378 					if (unexpectedValues || inconsistentComponents)
   1379 						errorMask.getAccess().setPixel(errorColor, x, y);
   1380 				}
   1381 			}
   1382 
   1383 			if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
   1384 			{
   1385 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
   1386 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
   1387 
   1388 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
   1389 				{
   1390 					const std::string	name	("Attachment" + de::toString(attachmentNdx));
   1391 					m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), accesses[attachmentNdx]);
   1392 				}
   1393 
   1394 				m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
   1395 
   1396 				if (m_sampleMask == 0x0u)
   1397 				{
   1398 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
   1399 					m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
   1400 				}
   1401 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
   1402 				{
   1403 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
   1404 					m_resultCollector.fail("Full sample mask didn't produce correct pixels");
   1405 				}
   1406 				else
   1407 				{
   1408 					if (unexpectedValues)
   1409 					{
   1410 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
   1411 						m_resultCollector.fail("Resolve produced unexpected values");
   1412 					}
   1413 
   1414 					if (inconsistentComponents)
   1415 					{
   1416 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
   1417 						m_resultCollector.fail("Different components of attachment were resolved to different values.");
   1418 					}
   1419 
   1420 					if (inconsistentAttachments)
   1421 					{
   1422 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
   1423 						m_resultCollector.fail("Different attachments were resolved to different values.");
   1424 					}
   1425 				}
   1426 			}
   1427 			break;
   1428 		}
   1429 
   1430 		default:
   1431 			DE_FATAL("Unknown channel class");
   1432 	}
   1433 }
   1434 
   1435 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
   1436 {
   1437 	if (m_sampleMask == 0u)
   1438 	{
   1439 		const tcu::TextureFormat		format			(mapVkFormat(m_format));
   1440 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
   1441 		tcu::TestLog&					log				(m_context.getTestContext().getLog());
   1442 
   1443 		switch (channelClass)
   1444 		{
   1445 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1446 				log << TestLog::Message << "Clearing target to zero and rendering 255 pixels with every possible sample mask" << TestLog::EndMessage;
   1447 				break;
   1448 
   1449 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1450 				log << TestLog::Message << "Clearing target to -128 and rendering 127 pixels with every possible sample mask" << TestLog::EndMessage;
   1451 				break;
   1452 
   1453 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1454 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1455 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1456 				log << TestLog::Message << "Clearing target to black and rendering white pixels with every possible sample mask" << TestLog::EndMessage;
   1457 				break;
   1458 
   1459 			default:
   1460 				DE_FATAL("Unknown channel class");
   1461 		}
   1462 	}
   1463 
   1464 	submit();
   1465 	verify();
   1466 
   1467 	if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
   1468 	{
   1469 		const tcu::TextureFormat		format			(mapVkFormat(m_format));
   1470 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
   1471 		tcu::TestLog&					log				(m_context.getTestContext().getLog());
   1472 
   1473 		if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
   1474 				|| channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
   1475 				|| channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
   1476 		{
   1477 			const float			threshold		= 0.05f;
   1478 			const int			componentCount	(tcu::getNumUsedChannels(format.order));
   1479 			const Vec4			errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
   1480 			const Vec4			okColor			(0.0f, 0.0f, 0.0f, 1.0f);
   1481 			tcu::TextureLevel	errorMask		(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height);
   1482 			bool				isOk			= true;
   1483 			Vec4				maxDiff			(0.0f);
   1484 			Vec4				expectedAverage;
   1485 
   1486 			switch (channelClass)
   1487 			{
   1488 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1489 				{
   1490 					expectedAverage = Vec4(0.5f, componentCount > 1 ? 0.5f : 0.0f, componentCount > 2 ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
   1491 					break;
   1492 				}
   1493 
   1494 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1495 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1496 				{
   1497 					expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
   1498 					break;
   1499 				}
   1500 
   1501 				default:
   1502 					DE_FATAL("Unknown channel class");
   1503 			}
   1504 
   1505 			for (deUint32 y = 0; y < m_height; y++)
   1506 			for (deUint32 x = 0; x < m_width; x++)
   1507 			{
   1508 				const Vec4	sum		(m_sum.getAccess().getPixel(x, y));
   1509 				const Vec4	average	(sum / Vec4((float)(0x1u << m_sampleCount)));
   1510 				const Vec4	diff	(tcu::abs(average - expectedAverage));
   1511 
   1512 				m_sum.getAccess().setPixel(average, x, y);
   1513 				errorMask.getAccess().setPixel(okColor, x, y);
   1514 
   1515 				if (diff[0] > threshold
   1516 						|| diff[1] > threshold
   1517 						|| diff[2] > threshold
   1518 						|| diff[3] > threshold)
   1519 				{
   1520 					isOk	= false;
   1521 					maxDiff	= tcu::max(maxDiff, diff);
   1522 					errorMask.getAccess().setPixel(errorColor, x, y);
   1523 				}
   1524 			}
   1525 
   1526 			log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0", m_sum);
   1527 
   1528 			if (!isOk)
   1529 			{
   1530 				m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
   1531 
   1532 				log << TestLog::Message << "Average resolved values differ from expected average values by more than " << threshold << " max per component diff " << maxDiff << TestLog::EndMessage;
   1533 			}
   1534 		}
   1535 
   1536 		return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
   1537 	}
   1538 	else
   1539 	{
   1540 		m_sampleMask++;
   1541 		return tcu::TestStatus::incomplete();
   1542 	}
   1543 }
   1544 
   1545 struct Programs
   1546 {
   1547 	void init (vk::SourceCollections& dst, TestConfig config) const
   1548 	{
   1549 		const tcu::TextureFormat		format			(mapVkFormat(config.format));
   1550 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
   1551 
   1552 		dst.glslSources.add("quad-vert") << glu::VertexSource(
   1553 			"#version 450\n"
   1554 			"out gl_PerVertex {\n"
   1555 			"\tvec4 gl_Position;\n"
   1556 			"};\n"
   1557 			"highp float;\n"
   1558 			"void main (void) {\n"
   1559 			"\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
   1560 			"\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
   1561 			"}\n");
   1562 
   1563 		switch (channelClass)
   1564 		{
   1565 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1566 				dst.glslSources.add("quad-frag") << glu::FragmentSource(
   1567 					"#version 450\n"
   1568 					"layout(push_constant) uniform PushConstant {\n"
   1569 					"\thighp uint sampleMask;\n"
   1570 					"} pushConstants;\n"
   1571 					"layout(location = 0) out highp uvec4 o_color0;\n"
   1572 					"layout(location = 1) out highp uvec4 o_color1;\n"
   1573 					"layout(location = 2) out highp uvec4 o_color2;\n"
   1574 					"layout(location = 3) out highp uvec4 o_color3;\n"
   1575 					"void main (void)\n"
   1576 					"{\n"
   1577 					"\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
   1578 					"\to_color0 = uvec4(255);\n"
   1579 					"\to_color1 = uvec4(255);\n"
   1580 					"\to_color2 = uvec4(255);\n"
   1581 					"\to_color3 = uvec4(255);\n"
   1582 					"}\n");
   1583 				break;
   1584 
   1585 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1586 				dst.glslSources.add("quad-frag") << glu::FragmentSource(
   1587 					"#version 450\n"
   1588 					"layout(push_constant) uniform PushConstant {\n"
   1589 					"\thighp uint sampleMask;\n"
   1590 					"} pushConstants;\n"
   1591 					"layout(location = 0) out highp ivec4 o_color0;\n"
   1592 					"layout(location = 1) out highp ivec4 o_color1;\n"
   1593 					"layout(location = 2) out highp ivec4 o_color2;\n"
   1594 					"layout(location = 3) out highp ivec4 o_color3;\n"
   1595 					"void main (void)\n"
   1596 					"{\n"
   1597 					"\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
   1598 					"\to_color0 = ivec4(127);\n"
   1599 					"\to_color1 = ivec4(127);\n"
   1600 					"\to_color2 = ivec4(127);\n"
   1601 					"\to_color3 = ivec4(127);\n"
   1602 					"}\n");
   1603 				break;
   1604 
   1605 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1606 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1607 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1608 				dst.glslSources.add("quad-frag") << glu::FragmentSource(
   1609 					"#version 450\n"
   1610 					"layout(push_constant) uniform PushConstant {\n"
   1611 					"\thighp uint sampleMask;\n"
   1612 					"} pushConstants;\n"
   1613 					"layout(location = 0) out highp vec4 o_color0;\n"
   1614 					"layout(location = 1) out highp vec4 o_color1;\n"
   1615 					"layout(location = 2) out highp vec4 o_color2;\n"
   1616 					"layout(location = 3) out highp vec4 o_color3;\n"
   1617 					"void main (void)\n"
   1618 					"{\n"
   1619 					"\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
   1620 					"\to_color0 = vec4(1.0);\n"
   1621 					"\to_color1 = vec4(1.0);\n"
   1622 					"\to_color2 = vec4(1.0);\n"
   1623 					"\to_color3 = vec4(1.0);\n"
   1624 					"}\n");
   1625 				break;
   1626 
   1627 			default:
   1628 				DE_FATAL("Unknown channel class");
   1629 		}
   1630 	}
   1631 };
   1632 
   1633 std::string formatToName (VkFormat format)
   1634 {
   1635 	const std::string	formatStr	= de::toString(format);
   1636 	const std::string	prefix		= "VK_FORMAT_";
   1637 
   1638 	DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
   1639 
   1640 	return de::toLower(formatStr.substr(prefix.length()));
   1641 }
   1642 
   1643 void initTests (tcu::TestCaseGroup* group)
   1644 {
   1645 	static const VkFormat	formats[]	=
   1646 	{
   1647 		VK_FORMAT_R5G6B5_UNORM_PACK16,
   1648 		VK_FORMAT_R8_UNORM,
   1649 		VK_FORMAT_R8_SNORM,
   1650 		VK_FORMAT_R8_UINT,
   1651 		VK_FORMAT_R8_SINT,
   1652 		VK_FORMAT_R8G8_UNORM,
   1653 		VK_FORMAT_R8G8_SNORM,
   1654 		VK_FORMAT_R8G8_UINT,
   1655 		VK_FORMAT_R8G8_SINT,
   1656 		VK_FORMAT_R8G8B8A8_UNORM,
   1657 		VK_FORMAT_R8G8B8A8_SNORM,
   1658 		VK_FORMAT_R8G8B8A8_UINT,
   1659 		VK_FORMAT_R8G8B8A8_SINT,
   1660 		VK_FORMAT_R8G8B8A8_SRGB,
   1661 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
   1662 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
   1663 		VK_FORMAT_A8B8G8R8_UINT_PACK32,
   1664 		VK_FORMAT_A8B8G8R8_SINT_PACK32,
   1665 		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
   1666 		VK_FORMAT_B8G8R8A8_UNORM,
   1667 		VK_FORMAT_B8G8R8A8_SRGB,
   1668 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
   1669 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
   1670 		VK_FORMAT_A2B10G10R10_UINT_PACK32,
   1671 		VK_FORMAT_R16_UNORM,
   1672 		VK_FORMAT_R16_SNORM,
   1673 		VK_FORMAT_R16_UINT,
   1674 		VK_FORMAT_R16_SINT,
   1675 		VK_FORMAT_R16_SFLOAT,
   1676 		VK_FORMAT_R16G16_UNORM,
   1677 		VK_FORMAT_R16G16_SNORM,
   1678 		VK_FORMAT_R16G16_UINT,
   1679 		VK_FORMAT_R16G16_SINT,
   1680 		VK_FORMAT_R16G16_SFLOAT,
   1681 		VK_FORMAT_R16G16B16A16_UNORM,
   1682 		VK_FORMAT_R16G16B16A16_SNORM,
   1683 		VK_FORMAT_R16G16B16A16_UINT,
   1684 		VK_FORMAT_R16G16B16A16_SINT,
   1685 		VK_FORMAT_R16G16B16A16_SFLOAT,
   1686 		VK_FORMAT_R32_UINT,
   1687 		VK_FORMAT_R32_SINT,
   1688 		VK_FORMAT_R32_SFLOAT,
   1689 		VK_FORMAT_R32G32_UINT,
   1690 		VK_FORMAT_R32G32_SINT,
   1691 		VK_FORMAT_R32G32_SFLOAT,
   1692 		VK_FORMAT_R32G32B32A32_UINT,
   1693 		VK_FORMAT_R32G32B32A32_SINT,
   1694 		VK_FORMAT_R32G32B32A32_SFLOAT,
   1695 	};
   1696 	const deUint32			sampleCounts[] =
   1697 	{
   1698 		2u, 4u, 8u
   1699 	};
   1700 	tcu::TestContext&		testCtx		(group->getTestContext());
   1701 
   1702 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
   1703 	{
   1704 		const VkFormat					format		(formats[formatNdx]);
   1705 		const std::string				formatName	(formatToName(format));
   1706 		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
   1707 
   1708 		for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
   1709 		{
   1710 			const deUint32		sampleCount	(sampleCounts[sampleCountNdx]);
   1711 			const std::string	testName	("samples_" + de::toString(sampleCount));
   1712 
   1713 			formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount)));
   1714 		}
   1715 
   1716 		group->addChild(formatGroup.release());
   1717 	}
   1718 }
   1719 
   1720 } // anonymous
   1721 
   1722 tcu::TestCaseGroup* createRenderPassMultisampleResolveTests (tcu::TestContext& testCtx)
   1723 {
   1724 	return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests);
   1725 }
   1726 
   1727 } // vkt
   1728