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 passses with multisample attachments
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "vktRenderPassMultisampleTests.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 VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat)
    104 {
    105 	const tcu::TextureFormat	format		(mapVkFormat(vkFormat));
    106 	const bool					hasDepth	(tcu::hasDepthComponent(format.order));
    107 	const bool					hasStencil	(tcu::hasStencilComponent(format.order));
    108 
    109 	if (hasDepth || hasStencil)
    110 	{
    111 		return (hasDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : (VkImageAspectFlagBits)0u)
    112 				| (hasStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : (VkImageAspectFlagBits)0u);
    113 	}
    114 	else
    115 		return VK_IMAGE_ASPECT_COLOR_BIT;
    116 }
    117 
    118 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
    119 {
    120 	VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
    121 }
    122 
    123 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
    124 {
    125 	VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
    126 }
    127 
    128 de::MovePtr<Allocation> createBufferMemory (const DeviceInterface&	vk,
    129 											VkDevice				device,
    130 											Allocator&				allocator,
    131 											VkBuffer				buffer)
    132 {
    133 	de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
    134 	bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset());
    135 	return allocation;
    136 }
    137 
    138 de::MovePtr<Allocation> createImageMemory (const DeviceInterface&	vk,
    139 										   VkDevice					device,
    140 										   Allocator&				allocator,
    141 										   VkImage					image)
    142 {
    143 	de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any));
    144 	bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
    145 	return allocation;
    146 }
    147 
    148 Move<VkImage> createImage (const DeviceInterface&	vk,
    149 						   VkDevice					device,
    150 						   VkImageCreateFlags		flags,
    151 						   VkImageType				imageType,
    152 						   VkFormat					format,
    153 						   VkExtent3D				extent,
    154 						   deUint32					mipLevels,
    155 						   deUint32					arrayLayers,
    156 						   VkSampleCountFlagBits	samples,
    157 						   VkImageTiling			tiling,
    158 						   VkImageUsageFlags		usage,
    159 						   VkSharingMode			sharingMode,
    160 						   deUint32					queueFamilyCount,
    161 						   const deUint32*			pQueueFamilyIndices,
    162 						   VkImageLayout			initialLayout)
    163 {
    164 	const VkImageCreateInfo pCreateInfo =
    165 	{
    166 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
    167 		DE_NULL,
    168 		flags,
    169 		imageType,
    170 		format,
    171 		extent,
    172 		mipLevels,
    173 		arrayLayers,
    174 		samples,
    175 		tiling,
    176 		usage,
    177 		sharingMode,
    178 		queueFamilyCount,
    179 		pQueueFamilyIndices,
    180 		initialLayout
    181 	};
    182 	return createImage(vk, device, &pCreateInfo);
    183 }
    184 
    185 Move<VkImageView> createImageView (const DeviceInterface&	vk,
    186 								   VkDevice					device,
    187 								   VkImageViewCreateFlags	flags,
    188 								   VkImage					image,
    189 								   VkImageViewType			viewType,
    190 								   VkFormat					format,
    191 								   VkComponentMapping		components,
    192 								   VkImageSubresourceRange	subresourceRange)
    193 {
    194 	const VkImageViewCreateInfo pCreateInfo =
    195 	{
    196 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
    197 		DE_NULL,
    198 		flags,
    199 		image,
    200 		viewType,
    201 		format,
    202 		components,
    203 		subresourceRange,
    204 	};
    205 	return createImageView(vk, device, &pCreateInfo);
    206 }
    207 
    208 Move<VkImage> createImage (const InstanceInterface&	vki,
    209 						   VkPhysicalDevice			physicalDevice,
    210 						   const DeviceInterface&	vkd,
    211 						   VkDevice					device,
    212 						   VkFormat					vkFormat,
    213 						   VkSampleCountFlagBits	sampleCountBit,
    214 						   VkImageUsageFlags		usage,
    215 						   deUint32					width,
    216 						   deUint32					height)
    217 {
    218 	try
    219 	{
    220 		const tcu::TextureFormat		format					(mapVkFormat(vkFormat));
    221 		const VkImageType				imageType				(VK_IMAGE_TYPE_2D);
    222 		const VkImageTiling				imageTiling				(VK_IMAGE_TILING_OPTIMAL);
    223 		const VkFormatProperties		formatProperties		(getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat));
    224 		const VkImageFormatProperties	imageFormatProperties	(getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u));
    225 		const VkExtent3D				imageExtent				=
    226 		{
    227 			width,
    228 			height,
    229 			1u
    230 		};
    231 
    232 		if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
    233 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
    234 			TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
    235 
    236 		if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
    237 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
    238 			TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
    239 
    240 		if (imageFormatProperties.maxExtent.width < imageExtent.width
    241 			|| imageFormatProperties.maxExtent.height < imageExtent.height
    242 			|| ((imageFormatProperties.sampleCounts & sampleCountBit) == 0))
    243 		{
    244 			TCU_THROW(NotSupportedError, "Image type not supported");
    245 		}
    246 
    247 		return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, 1u, sampleCountBit, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED);
    248 	}
    249 	catch (const vk::Error& error)
    250 	{
    251 		if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
    252 			TCU_THROW(NotSupportedError, "Image format not supported");
    253 
    254 		throw;
    255 	}
    256 }
    257 
    258 Move<VkImageView> createImageAttachmentView (const DeviceInterface&	vkd,
    259 											 VkDevice				device,
    260 											 VkImage				image,
    261 											 VkFormat				format,
    262 											 VkImageAspectFlags		aspect)
    263 {
    264 	const VkImageSubresourceRange	range =
    265 	{
    266 		aspect,
    267 		0u,
    268 		1u,
    269 		0u,
    270 		1u
    271 	};
    272 
    273 	return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
    274 }
    275 
    276 Move<VkImageView> createSrcPrimaryInputImageView (const DeviceInterface&	vkd,
    277 												  VkDevice					device,
    278 												  VkImage					image,
    279 												  VkFormat					format,
    280 												  VkImageAspectFlags		aspect)
    281 {
    282 	const VkImageSubresourceRange	range =
    283 	{
    284 		aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)
    285 			? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT
    286 			: aspect,
    287 		0u,
    288 		1u,
    289 		0u,
    290 		1u
    291 	};
    292 
    293 	return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
    294 }
    295 
    296 Move<VkImageView> createSrcSecondaryInputImageView (const DeviceInterface&	vkd,
    297 													VkDevice				device,
    298 													VkImage					image,
    299 													VkFormat				format,
    300 													VkImageAspectFlags		aspect)
    301 {
    302 	if (aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT))
    303 	{
    304 		const VkImageSubresourceRange	range =
    305 		{
    306 			VK_IMAGE_ASPECT_STENCIL_BIT,
    307 			0u,
    308 			1u,
    309 			0u,
    310 			1u
    311 		};
    312 
    313 		return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
    314 	}
    315 	else
    316 		return Move<VkImageView>();
    317 }
    318 
    319 VkDeviceSize getPixelSize (VkFormat vkFormat)
    320 {
    321 	const tcu::TextureFormat	format	(mapVkFormat(vkFormat));
    322 
    323 	return format.getPixelSize();
    324 }
    325 
    326 Move<VkBuffer> createBuffer (const DeviceInterface&		vkd,
    327 							 VkDevice					device,
    328 							 VkFormat					format,
    329 							 deUint32					width,
    330 							 deUint32					height)
    331 {
    332 	const VkBufferUsageFlags	bufferUsage			(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
    333 	const VkDeviceSize			pixelSize			(getPixelSize(format));
    334 	const VkBufferCreateInfo	createInfo			=
    335 	{
    336 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
    337 		DE_NULL,
    338 		0u,
    339 
    340 		width * height * pixelSize,
    341 		bufferUsage,
    342 
    343 		VK_SHARING_MODE_EXCLUSIVE,
    344 		0u,
    345 		DE_NULL
    346 	};
    347 	return createBuffer(vkd, device, &createInfo);
    348 }
    349 
    350 VkSampleCountFlagBits sampleCountBitFromomSampleCount (deUint32 count)
    351 {
    352 	switch (count)
    353 	{
    354 		case 1:  return VK_SAMPLE_COUNT_1_BIT;
    355 		case 2:  return VK_SAMPLE_COUNT_2_BIT;
    356 		case 4:  return VK_SAMPLE_COUNT_4_BIT;
    357 		case 8:  return VK_SAMPLE_COUNT_8_BIT;
    358 		case 16: return VK_SAMPLE_COUNT_16_BIT;
    359 		case 32: return VK_SAMPLE_COUNT_32_BIT;
    360 		case 64: return VK_SAMPLE_COUNT_64_BIT;
    361 
    362 		default:
    363 			DE_FATAL("Invalid sample count");
    364 			return (VkSampleCountFlagBits)(0x1u << count);
    365 	}
    366 }
    367 
    368 std::vector<VkImageSp> createMultisampleImages (const InstanceInterface&	vki,
    369 												VkPhysicalDevice			physicalDevice,
    370 												const DeviceInterface&		vkd,
    371 												VkDevice					device,
    372 												VkFormat					format,
    373 												deUint32					sampleCount,
    374 												deUint32					width,
    375 												deUint32					height)
    376 {
    377 	std::vector<VkImageSp> images (sampleCount);
    378 
    379 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
    380 		images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromomSampleCount(sampleCount), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height)));
    381 
    382 	return images;
    383 }
    384 
    385 std::vector<VkImageSp> createSingleSampleImages (const InstanceInterface&	vki,
    386 												 VkPhysicalDevice			physicalDevice,
    387 												 const DeviceInterface&		vkd,
    388 												 VkDevice					device,
    389 												 VkFormat					format,
    390 												 deUint32					sampleCount,
    391 												 deUint32					width,
    392 												 deUint32					height)
    393 {
    394 	std::vector<VkImageSp> images (sampleCount);
    395 
    396 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
    397 		images[imageNdx] = safeSharedPtr(new vk::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)));
    398 
    399 	return images;
    400 }
    401 
    402 std::vector<de::SharedPtr<Allocation> > createImageMemory (const DeviceInterface&		vkd,
    403 														   VkDevice						device,
    404 														   Allocator&					allocator,
    405 														   const std::vector<VkImageSp>	images)
    406 {
    407 	std::vector<de::SharedPtr<Allocation> > memory (images.size());
    408 
    409 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
    410 		memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release());
    411 
    412 	return memory;
    413 }
    414 
    415 std::vector<VkImageViewSp> createImageAttachmentViews (const DeviceInterface&			vkd,
    416 													   VkDevice							device,
    417 													   const std::vector<VkImageSp>&	images,
    418 													   VkFormat							format,
    419 													   VkImageAspectFlagBits			aspect)
    420 {
    421 	std::vector<VkImageViewSp> views (images.size());
    422 
    423 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
    424 		views[imageNdx] = safeSharedPtr(new vk::Unique<VkImageView>(createImageAttachmentView(vkd, device, **images[imageNdx], format, aspect)));
    425 
    426 	return views;
    427 }
    428 
    429 std::vector<VkBufferSp> createBuffers (const DeviceInterface&	vkd,
    430 									   VkDevice					device,
    431 									   VkFormat					format,
    432 									   deUint32					sampleCount,
    433 									   deUint32					width,
    434 									   deUint32					height)
    435 {
    436 	std::vector<VkBufferSp> buffers (sampleCount);
    437 
    438 	for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
    439 		buffers[bufferNdx] = safeSharedPtr(new vk::Unique<VkBuffer>(createBuffer(vkd, device, format, width, height)));
    440 
    441 	return buffers;
    442 }
    443 
    444 std::vector<de::SharedPtr<Allocation> > createBufferMemory (const DeviceInterface&			vkd,
    445 															VkDevice						device,
    446 															Allocator&						allocator,
    447 															const std::vector<VkBufferSp>	buffers)
    448 {
    449 	std::vector<de::SharedPtr<Allocation> > memory (buffers.size());
    450 
    451 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
    452 		memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release());
    453 
    454 	return memory;
    455 }
    456 
    457 Move<VkRenderPass> createRenderPass (const DeviceInterface&	vkd,
    458 									 VkDevice				device,
    459 									 VkFormat				srcFormat,
    460 									 VkFormat				dstFormat,
    461 									 deUint32				sampleCount)
    462 {
    463 	const VkSampleCountFlagBits				samples						(sampleCountBitFromomSampleCount(sampleCount));
    464 	const deUint32							splitSubpassCount			(deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT));
    465 	const tcu::TextureFormat				format						(mapVkFormat(srcFormat));
    466 	const bool								isDepthStencilFormat		(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order));
    467 	vector<VkSubpassDescription>			subpasses;
    468 	vector<vector<VkAttachmentReference> >	dstAttachmentRefs			(splitSubpassCount);
    469 	vector<vector<VkAttachmentReference> >	dstResolveAttachmentRefs	(splitSubpassCount);
    470 	vector<VkAttachmentDescription>			attachments;
    471 	vector<VkSubpassDependency>				dependencies;
    472 	const VkAttachmentReference				srcAttachmentRef =
    473 	{
    474 		0u,
    475 		isDepthStencilFormat
    476 			? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
    477 			: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
    478 	};
    479 	const VkAttachmentReference				srcAttachmentInputRef =
    480 	{
    481 		0u,
    482 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
    483 	};
    484 
    485 	{
    486 		const VkAttachmentDescription srcAttachment =
    487 		{
    488 			0u,
    489 
    490 			srcFormat,
    491 			samples,
    492 
    493 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    494 			VK_ATTACHMENT_STORE_OP_DONT_CARE,
    495 
    496 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    497 			VK_ATTACHMENT_STORE_OP_DONT_CARE,
    498 
    499 			VK_IMAGE_LAYOUT_UNDEFINED,
    500 			VK_IMAGE_LAYOUT_GENERAL
    501 		};
    502 
    503 		attachments.push_back(srcAttachment);
    504 	}
    505 
    506 	for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
    507 	{
    508 		for (deUint32 sampleNdx = 0; sampleNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount  - splitSubpassIndex * MAX_COLOR_ATTACHMENT_COUNT); sampleNdx++)
    509 		{
    510 			// Multisample color attachment
    511 			{
    512 				const VkAttachmentDescription dstAttachment =
    513 				{
    514 					0u,
    515 
    516 					dstFormat,
    517 					samples,
    518 
    519 					VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    520 					VK_ATTACHMENT_STORE_OP_DONT_CARE,
    521 
    522 					VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    523 					VK_ATTACHMENT_STORE_OP_DONT_CARE,
    524 
    525 					VK_IMAGE_LAYOUT_UNDEFINED,
    526 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
    527 				};
    528 				const VkAttachmentReference dstAttachmentRef =
    529 				{
    530 					(deUint32)attachments.size(),
    531 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
    532 				};
    533 
    534 				attachments.push_back(dstAttachment);
    535 				dstAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
    536 			}
    537 			// Resolve attachment
    538 			{
    539 				const VkAttachmentDescription dstAttachment =
    540 				{
    541 					0u,
    542 
    543 					dstFormat,
    544 					VK_SAMPLE_COUNT_1_BIT,
    545 
    546 					VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    547 					VK_ATTACHMENT_STORE_OP_STORE,
    548 
    549 					VK_ATTACHMENT_LOAD_OP_DONT_CARE,
    550 					VK_ATTACHMENT_STORE_OP_STORE,
    551 
    552 					VK_IMAGE_LAYOUT_UNDEFINED,
    553 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
    554 				};
    555 				const VkAttachmentReference dstAttachmentRef =
    556 				{
    557 					(deUint32)attachments.size(),
    558 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
    559 				};
    560 
    561 				attachments.push_back(dstAttachment);
    562 				dstResolveAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
    563 			}
    564 		}
    565 	}
    566 
    567 	{
    568 		{
    569 			const VkSubpassDescription	subpass =
    570 			{
    571 				(VkSubpassDescriptionFlags)0,
    572 				VK_PIPELINE_BIND_POINT_GRAPHICS,
    573 
    574 				0u,
    575 				DE_NULL,
    576 
    577 				isDepthStencilFormat ? 0u : 1u,
    578 				isDepthStencilFormat ? DE_NULL : &srcAttachmentRef,
    579 				DE_NULL,
    580 
    581 				isDepthStencilFormat ? &srcAttachmentRef : DE_NULL,
    582 				0u,
    583 				DE_NULL
    584 			};
    585 
    586 			subpasses.push_back(subpass);
    587 		}
    588 
    589 		for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
    590 		{
    591 			{
    592 				const VkSubpassDescription	subpass =
    593 				{
    594 					(VkSubpassDescriptionFlags)0,
    595 					VK_PIPELINE_BIND_POINT_GRAPHICS,
    596 
    597 					1u,
    598 					&srcAttachmentInputRef,
    599 
    600 					(deUint32)dstAttachmentRefs[splitSubpassIndex].size(),
    601 					&dstAttachmentRefs[splitSubpassIndex][0],
    602 					&dstResolveAttachmentRefs[splitSubpassIndex][0],
    603 
    604 					DE_NULL,
    605 					0u,
    606 					DE_NULL
    607 				};
    608 				subpasses.push_back(subpass);
    609 			}
    610 			{
    611 				const VkSubpassDependency		dependency	=
    612 				{
    613 					0u, splitSubpassIndex + 1,
    614 					VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
    615 					VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
    616 
    617 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
    618 					VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
    619 
    620 					VK_DEPENDENCY_BY_REGION_BIT
    621 				};
    622 
    623 				dependencies.push_back(dependency);
    624 			}
    625 		};
    626 		const VkRenderPassCreateInfo	createInfo	=
    627 		{
    628 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
    629 			DE_NULL,
    630 			(VkRenderPassCreateFlags)0u,
    631 
    632 			(deUint32)attachments.size(),
    633 			&attachments[0],
    634 
    635 			(deUint32)subpasses.size(),
    636 			&subpasses[0],
    637 
    638 			(deUint32)dependencies.size(),
    639 			&dependencies[0]
    640 		};
    641 
    642 		return createRenderPass(vkd, device, &createInfo);
    643 	}
    644 }
    645 
    646 Move<VkFramebuffer> createFramebuffer (const DeviceInterface&				vkd,
    647 									   VkDevice								device,
    648 									   VkRenderPass							renderPass,
    649 									   VkImageView							srcImageView,
    650 									   const std::vector<VkImageViewSp>&	dstMultisampleImageViews,
    651 									   const std::vector<VkImageViewSp>&	dstSinglesampleImageViews,
    652 									   deUint32								width,
    653 									   deUint32								height)
    654 {
    655 	std::vector<VkImageView> attachments;
    656 
    657 	attachments.reserve(dstMultisampleImageViews.size() + dstSinglesampleImageViews.size() + 1u);
    658 
    659 	attachments.push_back(srcImageView);
    660 
    661 	DE_ASSERT(dstMultisampleImageViews.size() == dstSinglesampleImageViews.size());
    662 
    663 	for (size_t ndx = 0; ndx < dstMultisampleImageViews.size(); ndx++)
    664 	{
    665 		attachments.push_back(**dstMultisampleImageViews[ndx]);
    666 		attachments.push_back(**dstSinglesampleImageViews[ndx]);
    667 	}
    668 
    669 	const VkFramebufferCreateInfo createInfo =
    670 	{
    671 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
    672 		DE_NULL,
    673 		0u,
    674 
    675 		renderPass,
    676 		(deUint32)attachments.size(),
    677 		&attachments[0],
    678 
    679 		width,
    680 		height,
    681 		1u
    682 	};
    683 
    684 	return createFramebuffer(vkd, device, &createInfo);
    685 }
    686 
    687 Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface&	vkd,
    688 												   VkDevice					device)
    689 {
    690 	const VkPushConstantRange			pushConstant			=
    691 	{
    692 		VK_SHADER_STAGE_FRAGMENT_BIT,
    693 		0u,
    694 		4u
    695 	};
    696 	const VkPipelineLayoutCreateInfo	createInfo	=
    697 	{
    698 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
    699 		DE_NULL,
    700 		(vk::VkPipelineLayoutCreateFlags)0,
    701 
    702 		0u,
    703 		DE_NULL,
    704 
    705 		1u,
    706 		&pushConstant
    707 	};
    708 
    709 	return createPipelineLayout(vkd, device, &createInfo);
    710 }
    711 
    712 Move<VkPipeline> createRenderPipeline (const DeviceInterface&		vkd,
    713 									   VkDevice						device,
    714 									   VkFormat						srcFormat,
    715 									   VkRenderPass					renderPass,
    716 									   VkPipelineLayout				pipelineLayout,
    717 									   const vk::BinaryCollection&	binaryCollection,
    718 									   deUint32						width,
    719 									   deUint32						height,
    720 									   deUint32						sampleCount)
    721 {
    722 	const tcu::TextureFormat		format						(mapVkFormat(srcFormat));
    723 	const bool						isDepthStencilFormat		(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order));
    724 
    725 	const Unique<VkShaderModule>	vertexShaderModule			(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
    726 	const Unique<VkShaderModule>	fragmentShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
    727 	const VkSpecializationInfo		emptyShaderSpecializations	=
    728 	{
    729 		0u,
    730 		DE_NULL,
    731 
    732 		0u,
    733 		DE_NULL
    734 	};
    735 	// Disable blending
    736 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
    737 	{
    738 		VK_FALSE,
    739 		VK_BLEND_FACTOR_SRC_ALPHA,
    740 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
    741 		VK_BLEND_OP_ADD,
    742 		VK_BLEND_FACTOR_ONE,
    743 		VK_BLEND_FACTOR_ONE,
    744 		VK_BLEND_OP_ADD,
    745 		VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
    746 	};
    747 	const VkPipelineShaderStageCreateInfo shaderStages[2] =
    748 	{
    749 		{
    750 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
    751 			DE_NULL,
    752 			(VkPipelineShaderStageCreateFlags)0u,
    753 			VK_SHADER_STAGE_VERTEX_BIT,
    754 			*vertexShaderModule,
    755 			"main",
    756 			&emptyShaderSpecializations
    757 		},
    758 		{
    759 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
    760 			DE_NULL,
    761 			(VkPipelineShaderStageCreateFlags)0u,
    762 			VK_SHADER_STAGE_FRAGMENT_BIT,
    763 			*fragmentShaderModule,
    764 			"main",
    765 			&emptyShaderSpecializations
    766 		}
    767 	};
    768 	const VkPipelineVertexInputStateCreateInfo vertexInputState =
    769 	{
    770 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
    771 		DE_NULL,
    772 		(VkPipelineVertexInputStateCreateFlags)0u,
    773 
    774 		0u,
    775 		DE_NULL,
    776 
    777 		0u,
    778 		DE_NULL
    779 	};
    780 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
    781 	{
    782 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
    783 		DE_NULL,
    784 
    785 		(VkPipelineInputAssemblyStateCreateFlags)0u,
    786 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
    787 		VK_FALSE
    788 	};
    789 	const VkViewport viewport =
    790 	{
    791 		0.0f,  0.0f,
    792 		(float)width, (float)height,
    793 
    794 		0.0f, 1.0f
    795 	};
    796 	const VkRect2D scissor =
    797 	{
    798 		{ 0u, 0u },
    799 		{ width, height }
    800 	};
    801 	const VkPipelineViewportStateCreateInfo viewportState =
    802 	{
    803 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
    804 		DE_NULL,
    805 		(VkPipelineViewportStateCreateFlags)0u,
    806 
    807 		1u,
    808 		&viewport,
    809 
    810 		1u,
    811 		&scissor
    812 	};
    813 	const VkPipelineRasterizationStateCreateInfo rasterState =
    814 	{
    815 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
    816 		DE_NULL,
    817 		(VkPipelineRasterizationStateCreateFlags)0u,
    818 		VK_TRUE,
    819 		VK_FALSE,
    820 		VK_POLYGON_MODE_FILL,
    821 		VK_CULL_MODE_NONE,
    822 		VK_FRONT_FACE_COUNTER_CLOCKWISE,
    823 		VK_FALSE,
    824 		0.0f,
    825 		0.0f,
    826 		0.0f,
    827 		1.0f
    828 	};
    829 	const VkPipelineMultisampleStateCreateInfo multisampleState =
    830 	{
    831 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
    832 		DE_NULL,
    833 		(VkPipelineMultisampleStateCreateFlags)0u,
    834 
    835 		sampleCountBitFromomSampleCount(sampleCount),
    836 		VK_FALSE,
    837 		0.0f,
    838 		DE_NULL,
    839 		VK_FALSE,
    840 		VK_FALSE,
    841 	};
    842 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
    843 	{
    844 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
    845 		DE_NULL,
    846 		(VkPipelineDepthStencilStateCreateFlags)0u,
    847 
    848 		VK_TRUE,
    849 		VK_TRUE,
    850 		VK_COMPARE_OP_ALWAYS,
    851 		VK_FALSE,
    852 		VK_TRUE,
    853 		{
    854 			VK_STENCIL_OP_KEEP,
    855 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
    856 			VK_STENCIL_OP_KEEP,
    857 			VK_COMPARE_OP_ALWAYS,
    858 			~0u,
    859 			~0u,
    860 			0xFFu / (sampleCount + 1)
    861 		},
    862 		{
    863 			VK_STENCIL_OP_KEEP,
    864 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
    865 			VK_STENCIL_OP_KEEP,
    866 			VK_COMPARE_OP_ALWAYS,
    867 			~0u,
    868 			~0u,
    869 			0xFFu / (sampleCount + 1)
    870 		},
    871 
    872 		0.0f,
    873 		1.0f
    874 	};
    875 	const VkPipelineColorBlendStateCreateInfo blendState =
    876 	{
    877 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
    878 		DE_NULL,
    879 		(VkPipelineColorBlendStateCreateFlags)0u,
    880 
    881 		VK_FALSE,
    882 		VK_LOGIC_OP_COPY,
    883 		(isDepthStencilFormat ? 0u : 1u),
    884 		(isDepthStencilFormat ? DE_NULL : &attachmentBlendState),
    885 		{ 0.0f, 0.0f, 0.0f, 0.0f }
    886 	};
    887 	const VkGraphicsPipelineCreateInfo createInfo =
    888 	{
    889 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
    890 		DE_NULL,
    891 		(VkPipelineCreateFlags)0u,
    892 
    893 		2,
    894 		shaderStages,
    895 
    896 		&vertexInputState,
    897 		&inputAssemblyState,
    898 		DE_NULL,
    899 		&viewportState,
    900 		&rasterState,
    901 		&multisampleState,
    902 		&depthStencilState,
    903 		&blendState,
    904 		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,
    905 		pipelineLayout,
    906 
    907 		renderPass,
    908 		0u,
    909 		DE_NULL,
    910 		0u
    911 	};
    912 
    913 	return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
    914 }
    915 
    916 Move<VkDescriptorSetLayout> createSplitDescriptorSetLayout (const DeviceInterface&	vkd,
    917 															VkDevice				device,
    918 															VkFormat				vkFormat)
    919 {
    920 	const tcu::TextureFormat				format		(mapVkFormat(vkFormat));
    921 	const bool								hasDepth	(tcu::hasDepthComponent(format.order));
    922 	const bool								hasStencil	(tcu::hasStencilComponent(format.order));
    923 	const VkDescriptorSetLayoutBinding		bindings[]	=
    924 	{
    925 		{
    926 			0u,
    927 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
    928 			1u,
    929 			VK_SHADER_STAGE_FRAGMENT_BIT,
    930 			DE_NULL
    931 		},
    932 		{
    933 			1u,
    934 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
    935 			1u,
    936 			VK_SHADER_STAGE_FRAGMENT_BIT,
    937 			DE_NULL
    938 		}
    939 	};
    940 	const VkDescriptorSetLayoutCreateInfo	createInfo	=
    941 	{
    942 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
    943 		DE_NULL,
    944 		0u,
    945 
    946 		hasDepth && hasStencil ? 2u : 1u,
    947 		bindings
    948 	};
    949 
    950 	return createDescriptorSetLayout(vkd, device, &createInfo);
    951 }
    952 
    953 Move<VkPipelineLayout> createSplitPipelineLayout (const DeviceInterface&	vkd,
    954 												  VkDevice					device,
    955 												  VkDescriptorSetLayout		descriptorSetLayout)
    956 {
    957 	const VkPushConstantRange			pushConstant			=
    958 	{
    959 		VK_SHADER_STAGE_FRAGMENT_BIT,
    960 		0u,
    961 		4u
    962 	};
    963 	const VkPipelineLayoutCreateInfo	createInfo	=
    964 	{
    965 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
    966 		DE_NULL,
    967 		(vk::VkPipelineLayoutCreateFlags)0,
    968 
    969 		1u,
    970 		&descriptorSetLayout,
    971 
    972 		1u,
    973 		&pushConstant
    974 	};
    975 
    976 	return createPipelineLayout(vkd, device, &createInfo);
    977 }
    978 
    979 Move<VkPipeline> createSplitPipeline (const DeviceInterface&		vkd,
    980 									  VkDevice						device,
    981 									  VkRenderPass					renderPass,
    982 									  deUint32						subpassIndex,
    983 									  VkPipelineLayout				pipelineLayout,
    984 									  const vk::BinaryCollection&	binaryCollection,
    985 									  deUint32						width,
    986 									  deUint32						height,
    987 									  deUint32						sampleCount)
    988 {
    989 	const Unique<VkShaderModule>	vertexShaderModule			(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
    990 	const Unique<VkShaderModule>	fragmentShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-split-frag"), 0u));
    991 	const VkSpecializationInfo		emptyShaderSpecializations	=
    992 	{
    993 		0u,
    994 		DE_NULL,
    995 
    996 		0u,
    997 		DE_NULL
    998 	};
    999 	// Disable blending
   1000 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
   1001 	{
   1002 		VK_FALSE,
   1003 		VK_BLEND_FACTOR_SRC_ALPHA,
   1004 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
   1005 		VK_BLEND_OP_ADD,
   1006 		VK_BLEND_FACTOR_ONE,
   1007 		VK_BLEND_FACTOR_ONE,
   1008 		VK_BLEND_OP_ADD,
   1009 		VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
   1010 	};
   1011 	const std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates (de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount), attachmentBlendState);
   1012 	const VkPipelineShaderStageCreateInfo shaderStages[2] =
   1013 	{
   1014 		{
   1015 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
   1016 			DE_NULL,
   1017 			(VkPipelineShaderStageCreateFlags)0u,
   1018 			VK_SHADER_STAGE_VERTEX_BIT,
   1019 			*vertexShaderModule,
   1020 			"main",
   1021 			&emptyShaderSpecializations
   1022 		},
   1023 		{
   1024 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
   1025 			DE_NULL,
   1026 			(VkPipelineShaderStageCreateFlags)0u,
   1027 			VK_SHADER_STAGE_FRAGMENT_BIT,
   1028 			*fragmentShaderModule,
   1029 			"main",
   1030 			&emptyShaderSpecializations
   1031 		}
   1032 	};
   1033 	const VkPipelineVertexInputStateCreateInfo vertexInputState =
   1034 	{
   1035 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
   1036 		DE_NULL,
   1037 		(VkPipelineVertexInputStateCreateFlags)0u,
   1038 
   1039 		0u,
   1040 		DE_NULL,
   1041 
   1042 		0u,
   1043 		DE_NULL
   1044 	};
   1045 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
   1046 	{
   1047 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
   1048 		DE_NULL,
   1049 
   1050 		(VkPipelineInputAssemblyStateCreateFlags)0u,
   1051 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
   1052 		VK_FALSE
   1053 	};
   1054 	const VkViewport viewport =
   1055 	{
   1056 		0.0f,  0.0f,
   1057 		(float)width, (float)height,
   1058 
   1059 		0.0f, 1.0f
   1060 	};
   1061 	const VkRect2D scissor =
   1062 	{
   1063 		{ 0u, 0u },
   1064 		{ width, height }
   1065 	};
   1066 	const VkPipelineViewportStateCreateInfo viewportState =
   1067 	{
   1068 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
   1069 		DE_NULL,
   1070 		(VkPipelineViewportStateCreateFlags)0u,
   1071 
   1072 		1u,
   1073 		&viewport,
   1074 
   1075 		1u,
   1076 		&scissor
   1077 	};
   1078 	const VkPipelineRasterizationStateCreateInfo rasterState =
   1079 	{
   1080 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
   1081 		DE_NULL,
   1082 		(VkPipelineRasterizationStateCreateFlags)0u,
   1083 		VK_TRUE,
   1084 		VK_FALSE,
   1085 		VK_POLYGON_MODE_FILL,
   1086 		VK_CULL_MODE_NONE,
   1087 		VK_FRONT_FACE_COUNTER_CLOCKWISE,
   1088 		VK_FALSE,
   1089 		0.0f,
   1090 		0.0f,
   1091 		0.0f,
   1092 		1.0f
   1093 	};
   1094 	const VkPipelineMultisampleStateCreateInfo multisampleState =
   1095 	{
   1096 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
   1097 		DE_NULL,
   1098 		(VkPipelineMultisampleStateCreateFlags)0u,
   1099 
   1100 		sampleCountBitFromomSampleCount(sampleCount),
   1101 		VK_FALSE,
   1102 		0.0f,
   1103 		DE_NULL,
   1104 		VK_FALSE,
   1105 		VK_FALSE,
   1106 	};
   1107 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
   1108 	{
   1109 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
   1110 		DE_NULL,
   1111 		(VkPipelineDepthStencilStateCreateFlags)0u,
   1112 
   1113 		VK_FALSE,
   1114 		VK_FALSE,
   1115 		VK_COMPARE_OP_ALWAYS,
   1116 		VK_FALSE,
   1117 		VK_FALSE,
   1118 		{
   1119 			VK_STENCIL_OP_REPLACE,
   1120 			VK_STENCIL_OP_REPLACE,
   1121 			VK_STENCIL_OP_REPLACE,
   1122 			VK_COMPARE_OP_ALWAYS,
   1123 			~0u,
   1124 			~0u,
   1125 			0x0u
   1126 		},
   1127 		{
   1128 			VK_STENCIL_OP_REPLACE,
   1129 			VK_STENCIL_OP_REPLACE,
   1130 			VK_STENCIL_OP_REPLACE,
   1131 			VK_COMPARE_OP_ALWAYS,
   1132 			~0u,
   1133 			~0u,
   1134 			0x0u
   1135 		},
   1136 
   1137 		0.0f,
   1138 		1.0f
   1139 	};
   1140 	const VkPipelineColorBlendStateCreateInfo blendState =
   1141 	{
   1142 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
   1143 		DE_NULL,
   1144 		(VkPipelineColorBlendStateCreateFlags)0u,
   1145 
   1146 		VK_FALSE,
   1147 		VK_LOGIC_OP_COPY,
   1148 
   1149 		(deUint32)attachmentBlendStates.size(),
   1150 		&attachmentBlendStates[0],
   1151 
   1152 		{ 0.0f, 0.0f, 0.0f, 0.0f }
   1153 	};
   1154 	const VkGraphicsPipelineCreateInfo createInfo =
   1155 	{
   1156 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
   1157 		DE_NULL,
   1158 		(VkPipelineCreateFlags)0u,
   1159 
   1160 		2,
   1161 		shaderStages,
   1162 
   1163 		&vertexInputState,
   1164 		&inputAssemblyState,
   1165 		DE_NULL,
   1166 		&viewportState,
   1167 		&rasterState,
   1168 		&multisampleState,
   1169 		&depthStencilState,
   1170 		&blendState,
   1171 		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,
   1172 		pipelineLayout,
   1173 
   1174 		renderPass,
   1175 		subpassIndex,
   1176 		DE_NULL,
   1177 		0u
   1178 	};
   1179 
   1180 	return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
   1181 }
   1182 
   1183 vector<VkPipelineSp> createSplitPipelines (const DeviceInterface&		vkd,
   1184 										 VkDevice						device,
   1185 										 VkRenderPass					renderPass,
   1186 										 VkPipelineLayout				pipelineLayout,
   1187 										 const vk::BinaryCollection&	binaryCollection,
   1188 										 deUint32						width,
   1189 										 deUint32						height,
   1190 										 deUint32						sampleCount)
   1191 {
   1192 	std::vector<VkPipelineSp> pipelines (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT), (VkPipelineSp)0u);
   1193 
   1194 	for (size_t ndx = 0; ndx < pipelines.size(); ndx++)
   1195 		pipelines[ndx] = safeSharedPtr(new Unique<VkPipeline>(createSplitPipeline(vkd, device, renderPass, (deUint32)(ndx + 1), pipelineLayout, binaryCollection, width, height, sampleCount)));
   1196 
   1197 	return pipelines;
   1198 }
   1199 
   1200 Move<VkDescriptorPool> createSplitDescriptorPool (const DeviceInterface&	vkd,
   1201 												  VkDevice					device)
   1202 {
   1203 	const VkDescriptorPoolSize			size		=
   1204 	{
   1205 		VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2u
   1206 	};
   1207 	const VkDescriptorPoolCreateInfo	createInfo	=
   1208 	{
   1209 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
   1210 		DE_NULL,
   1211 		VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
   1212 
   1213 
   1214 		2u,
   1215 		1u,
   1216 		&size
   1217 	};
   1218 
   1219 	return createDescriptorPool(vkd, device, &createInfo);
   1220 }
   1221 
   1222 Move<VkDescriptorSet> createSplitDescriptorSet (const DeviceInterface&	vkd,
   1223 												VkDevice				device,
   1224 												VkDescriptorPool		pool,
   1225 												VkDescriptorSetLayout	layout,
   1226 												VkImageView				primaryImageView,
   1227 												VkImageView				secondaryImageView)
   1228 {
   1229 	const VkDescriptorSetAllocateInfo	allocateInfo	=
   1230 	{
   1231 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   1232 		DE_NULL,
   1233 
   1234 		pool,
   1235 		1u,
   1236 		&layout
   1237 	};
   1238 	Move<VkDescriptorSet> set (allocateDescriptorSet(vkd, device, &allocateInfo));
   1239 
   1240 	{
   1241 		const VkDescriptorImageInfo	imageInfos[]	=
   1242 		{
   1243 			{
   1244 				(VkSampler)0u,
   1245 				primaryImageView,
   1246 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
   1247 			},
   1248 			{
   1249 				(VkSampler)0u,
   1250 				secondaryImageView,
   1251 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
   1252 			}
   1253 		};
   1254 		const VkWriteDescriptorSet	writes[]	=
   1255 		{
   1256 			{
   1257 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
   1258 				DE_NULL,
   1259 
   1260 				*set,
   1261 				0u,
   1262 				0u,
   1263 				1u,
   1264 				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
   1265 				&imageInfos[0],
   1266 				DE_NULL,
   1267 				DE_NULL
   1268 			},
   1269 			{
   1270 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
   1271 				DE_NULL,
   1272 
   1273 				*set,
   1274 				1u,
   1275 				0u,
   1276 				1u,
   1277 				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
   1278 				&imageInfos[1],
   1279 				DE_NULL,
   1280 				DE_NULL
   1281 			}
   1282 		};
   1283 		const deUint32	count	= secondaryImageView != (VkImageView)0
   1284 								? 2u
   1285 								: 1u;
   1286 
   1287 		vkd.updateDescriptorSets(device, count, writes, 0u, DE_NULL);
   1288 	}
   1289 	return set;
   1290 }
   1291 
   1292 struct TestConfig
   1293 {
   1294 				TestConfig		(VkFormat	format_,
   1295 								 deUint32	sampleCount_)
   1296 		: format		(format_)
   1297 		, sampleCount	(sampleCount_)
   1298 	{
   1299 	}
   1300 
   1301 	VkFormat	format;
   1302 	deUint32	sampleCount;
   1303 };
   1304 
   1305 VkImageUsageFlags getSrcImageUsage (VkFormat vkFormat)
   1306 {
   1307 	const tcu::TextureFormat	format		(mapVkFormat(vkFormat));
   1308 	const bool					hasDepth	(tcu::hasDepthComponent(format.order));
   1309 	const bool					hasStencil	(tcu::hasStencilComponent(format.order));
   1310 
   1311 	if (hasDepth || hasStencil)
   1312 		return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
   1313 	else
   1314 		return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
   1315 }
   1316 
   1317 VkFormat getDstFormat (VkFormat vkFormat)
   1318 {
   1319 	const tcu::TextureFormat	format		(mapVkFormat(vkFormat));
   1320 	const bool					hasDepth	(tcu::hasDepthComponent(format.order));
   1321 	const bool					hasStencil	(tcu::hasStencilComponent(format.order));
   1322 
   1323 	if (hasDepth && hasStencil)
   1324 		return VK_FORMAT_R32G32_SFLOAT;
   1325 	else if (hasDepth || hasStencil)
   1326 		return VK_FORMAT_R32_SFLOAT;
   1327 	else
   1328 		return vkFormat;
   1329 }
   1330 
   1331 
   1332 class MultisampleRenderPassTestInstance : public TestInstance
   1333 {
   1334 public:
   1335 					MultisampleRenderPassTestInstance	(Context& context, TestConfig config);
   1336 					~MultisampleRenderPassTestInstance	(void);
   1337 
   1338 	tcu::TestStatus	iterate								(void);
   1339 
   1340 private:
   1341 	const VkFormat									m_srcFormat;
   1342 	const VkFormat									m_dstFormat;
   1343 	const deUint32									m_sampleCount;
   1344 	const deUint32									m_width;
   1345 	const deUint32									m_height;
   1346 
   1347 	const VkImageAspectFlags						m_srcImageAspect;
   1348 	const VkImageUsageFlags							m_srcImageUsage;
   1349 	const Unique<VkImage>							m_srcImage;
   1350 	const de::UniquePtr<Allocation>					m_srcImageMemory;
   1351 	const Unique<VkImageView>						m_srcImageView;
   1352 	const Unique<VkImageView>						m_srcPrimaryInputImageView;
   1353 	const Unique<VkImageView>						m_srcSecondaryInputImageView;
   1354 
   1355 	const std::vector<VkImageSp>					m_dstMultisampleImages;
   1356 	const std::vector<de::SharedPtr<Allocation> >	m_dstMultisampleImageMemory;
   1357 	const std::vector<VkImageViewSp>				m_dstMultisampleImageViews;
   1358 
   1359 	const std::vector<VkImageSp>					m_dstSinglesampleImages;
   1360 	const std::vector<de::SharedPtr<Allocation> >	m_dstSinglesampleImageMemory;
   1361 	const std::vector<VkImageViewSp>				m_dstSinglesampleImageViews;
   1362 
   1363 	const std::vector<VkBufferSp>					m_dstBuffers;
   1364 	const std::vector<de::SharedPtr<Allocation> >	m_dstBufferMemory;
   1365 
   1366 	const Unique<VkRenderPass>						m_renderPass;
   1367 	const Unique<VkFramebuffer>						m_framebuffer;
   1368 
   1369 	const Unique<VkPipelineLayout>					m_renderPipelineLayout;
   1370 	const Unique<VkPipeline>						m_renderPipeline;
   1371 
   1372 	const Unique<VkDescriptorSetLayout>				m_splitDescriptorSetLayout;
   1373 	const Unique<VkPipelineLayout>					m_splitPipelineLayout;
   1374 	const std::vector<VkPipelineSp>					m_splitPipelines;
   1375 	const Unique<VkDescriptorPool>					m_splitDescriptorPool;
   1376 	const Unique<VkDescriptorSet>					m_splitDescriptorSet;
   1377 
   1378 	const Unique<VkCommandPool>						m_commandPool;
   1379 	tcu::ResultCollector							m_resultCollector;
   1380 };
   1381 
   1382 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
   1383 	: TestInstance					(context)
   1384 	, m_srcFormat					(config.format)
   1385 	, m_dstFormat					(getDstFormat(config.format))
   1386 	, m_sampleCount					(config.sampleCount)
   1387 	, m_width						(32u)
   1388 	, m_height						(32u)
   1389 
   1390 	, m_srcImageAspect				(getImageAspectFlags(m_srcFormat))
   1391 	, m_srcImageUsage				(getSrcImageUsage(m_srcFormat))
   1392 	, m_srcImage					(createImage(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_srcFormat, sampleCountBitFromomSampleCount(m_sampleCount), m_srcImageUsage, m_width, m_height))
   1393 	, m_srcImageMemory				(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), *m_srcImage))
   1394 	, m_srcImageView				(createImageAttachmentView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
   1395 	, m_srcPrimaryInputImageView	(createSrcPrimaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
   1396 	, m_srcSecondaryInputImageView	(createSrcSecondaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
   1397 
   1398 	, m_dstMultisampleImages		(createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
   1399 	, m_dstMultisampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstMultisampleImages))
   1400 	, m_dstMultisampleImageViews	(createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstMultisampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
   1401 
   1402 	, m_dstSinglesampleImages		(createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
   1403 	, m_dstSinglesampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstSinglesampleImages))
   1404 	, m_dstSinglesampleImageViews	(createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstSinglesampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
   1405 
   1406 	, m_dstBuffers					(createBuffers(context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
   1407 	, m_dstBufferMemory				(createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstBuffers))
   1408 
   1409 	, m_renderPass					(createRenderPass(context.getDeviceInterface(), context.getDevice(), m_srcFormat, m_dstFormat, m_sampleCount))
   1410 	, m_framebuffer					(createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_srcImageView, m_dstMultisampleImageViews, m_dstSinglesampleImageViews, m_width, m_height))
   1411 
   1412 	, m_renderPipelineLayout		(createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
   1413 	, m_renderPipeline				(createRenderPipeline(context.getDeviceInterface(), context.getDevice(), m_srcFormat, *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
   1414 
   1415 	, m_splitDescriptorSetLayout	(createSplitDescriptorSetLayout(context.getDeviceInterface(), context.getDevice(), m_srcFormat))
   1416 	, m_splitPipelineLayout			(createSplitPipelineLayout(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorSetLayout))
   1417 	, m_splitPipelines				(createSplitPipelines(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_splitPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
   1418 	, m_splitDescriptorPool			(createSplitDescriptorPool(context.getDeviceInterface(), context.getDevice()))
   1419 	, m_splitDescriptorSet			(createSplitDescriptorSet(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorPool, *m_splitDescriptorSetLayout, *m_srcPrimaryInputImageView, *m_srcSecondaryInputImageView))
   1420 	, m_commandPool					(createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
   1421 {
   1422 }
   1423 
   1424 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
   1425 {
   1426 }
   1427 
   1428 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
   1429 {
   1430 	const DeviceInterface&			vkd				(m_context.getDeviceInterface());
   1431 	const VkDevice					device			(m_context.getDevice());
   1432 	const Unique<VkCommandBuffer>	commandBuffer	(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
   1433 
   1434 	{
   1435 		const VkCommandBufferBeginInfo beginInfo =
   1436 		{
   1437 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
   1438 			DE_NULL,
   1439 
   1440 			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
   1441 			DE_NULL
   1442 		};
   1443 
   1444 		VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
   1445 	}
   1446 
   1447 	{
   1448 		const VkRenderPassBeginInfo beginInfo =
   1449 		{
   1450 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
   1451 			DE_NULL,
   1452 
   1453 			*m_renderPass,
   1454 			*m_framebuffer,
   1455 
   1456 			{
   1457 				{ 0u, 0u },
   1458 				{ m_width, m_height }
   1459 			},
   1460 
   1461 			0u,
   1462 			DE_NULL
   1463 		};
   1464 		vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
   1465 
   1466 		// Stencil needs to be cleared if it exists.
   1467 		if (tcu::hasStencilComponent(mapVkFormat(m_srcFormat).order))
   1468 		{
   1469 			const VkClearAttachment clearAttachment =
   1470 			{
   1471 				VK_IMAGE_ASPECT_STENCIL_BIT,						// VkImageAspectFlags	aspectMask;
   1472 				0,													// deUint32				colorAttachment;
   1473 				makeClearValueDepthStencil(0, 0)					// VkClearValue			clearValue;
   1474 			};
   1475 
   1476 			const VkClearRect clearRect =
   1477 			{
   1478 				{
   1479 					{ 0u, 0u },
   1480 					{ m_width, m_height }
   1481 				},
   1482 				0,													// deUint32	baseArrayLayer;
   1483 				1													// deUint32	layerCount;
   1484 			};
   1485 
   1486 			vkd.cmdClearAttachments(*commandBuffer, 1, &clearAttachment, 1, &clearRect);
   1487 		}
   1488 	}
   1489 
   1490 	vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
   1491 
   1492 	for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
   1493 	{
   1494 		vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(sampleNdx), &sampleNdx);
   1495 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
   1496 	}
   1497 
   1498 	for (deUint32 splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++)
   1499 	{
   1500 		vkd.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
   1501 
   1502 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_splitPipelines[splitPipelineNdx]);
   1503 		vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_splitPipelineLayout, 0u, 1u,  &*m_splitDescriptorSet, 0u, DE_NULL);
   1504 		vkd.cmdPushConstants(*commandBuffer, *m_splitPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(splitPipelineNdx), &splitPipelineNdx);
   1505 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
   1506 	}
   1507 
   1508 	vkd.cmdEndRenderPass(*commandBuffer);
   1509 
   1510 	// Memory barriers between rendering and copies
   1511 	{
   1512 		std::vector<VkImageMemoryBarrier> barriers;
   1513 
   1514 		for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
   1515 		{
   1516 			const VkImageMemoryBarrier barrier =
   1517 			{
   1518 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
   1519 				DE_NULL,
   1520 
   1521 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
   1522 				VK_ACCESS_TRANSFER_READ_BIT,
   1523 
   1524 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1525 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1526 
   1527 				VK_QUEUE_FAMILY_IGNORED,
   1528 				VK_QUEUE_FAMILY_IGNORED,
   1529 
   1530 				**m_dstSinglesampleImages[dstNdx],
   1531 				{
   1532 					VK_IMAGE_ASPECT_COLOR_BIT,
   1533 					0u,
   1534 					1u,
   1535 					0u,
   1536 					1u
   1537 				}
   1538 			};
   1539 
   1540 			barriers.push_back(barrier);
   1541 		}
   1542 
   1543 		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]);
   1544 	}
   1545 
   1546 	// Copy image memory to buffers
   1547 	for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
   1548 	{
   1549 		const VkBufferImageCopy region =
   1550 		{
   1551 			0u,
   1552 			0u,
   1553 			0u,
   1554 			{
   1555 				VK_IMAGE_ASPECT_COLOR_BIT,
   1556 				0u,
   1557 				0u,
   1558 				1u,
   1559 			},
   1560 			{ 0u, 0u, 0u },
   1561 			{ m_width, m_height, 1u }
   1562 		};
   1563 
   1564 		vkd.cmdCopyImageToBuffer(*commandBuffer, **m_dstSinglesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_dstBuffers[dstNdx], 1u, &region);
   1565 	}
   1566 
   1567 	// Memory barriers between copies and host access
   1568 	{
   1569 		std::vector<VkBufferMemoryBarrier> barriers;
   1570 
   1571 		for (size_t dstNdx = 0; dstNdx < m_dstBuffers.size(); dstNdx++)
   1572 		{
   1573 			const VkBufferMemoryBarrier barrier =
   1574 			{
   1575 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
   1576 				DE_NULL,
   1577 
   1578 				VK_ACCESS_TRANSFER_WRITE_BIT,
   1579 				VK_ACCESS_HOST_READ_BIT,
   1580 
   1581 				VK_QUEUE_FAMILY_IGNORED,
   1582 				VK_QUEUE_FAMILY_IGNORED,
   1583 
   1584 				**m_dstBuffers[dstNdx],
   1585 				0u,
   1586 				VK_WHOLE_SIZE
   1587 			};
   1588 
   1589 			barriers.push_back(barrier);
   1590 		}
   1591 
   1592 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0], 0u, DE_NULL);
   1593 	}
   1594 
   1595 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
   1596 
   1597 	{
   1598 		const VkSubmitInfo submitInfo =
   1599 		{
   1600 			VK_STRUCTURE_TYPE_SUBMIT_INFO,
   1601 			DE_NULL,
   1602 
   1603 			0u,
   1604 			DE_NULL,
   1605 			DE_NULL,
   1606 
   1607 			1u,
   1608 			&*commandBuffer,
   1609 
   1610 			0u,
   1611 			DE_NULL
   1612 		};
   1613 
   1614 		VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u));
   1615 
   1616 		VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue()));
   1617 	}
   1618 
   1619 	{
   1620 		const tcu::TextureFormat		format			(mapVkFormat(m_dstFormat));
   1621 		const tcu::TextureFormat		srcFormat		(mapVkFormat(m_srcFormat));
   1622 		const bool						hasDepth		(tcu::hasDepthComponent(srcFormat.order));
   1623 		const bool						hasStencil		(tcu::hasStencilComponent(srcFormat.order));
   1624 
   1625 		for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
   1626 		{
   1627 			const std::string					name		("Sample" + de::toString(sampleNdx));
   1628 			const void* const					ptr			(m_dstBufferMemory[sampleNdx]->getHostPtr());
   1629 			const tcu::ConstPixelBufferAccess	access		(format, m_width, m_height, 1, ptr);
   1630 			tcu::TextureLevel					reference	(format, m_width, m_height);
   1631 
   1632 			if (hasDepth || hasStencil)
   1633 			{
   1634 				if (hasDepth)
   1635 				{
   1636 					for (deUint32 y = 0; y < m_height; y++)
   1637 					for (deUint32 x = 0; x < m_width; x++)
   1638 					{
   1639 						const deUint32	x1				= x ^ sampleNdx;
   1640 						const deUint32	y1				= y ^ sampleNdx;
   1641 						const float		range			= 1.0f;
   1642 						float			depth			= 0.0f;
   1643 						deUint32		divider			= 2;
   1644 
   1645 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1646 						for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
   1647 						{
   1648 							depth += (range / (float)divider)
   1649 									* (((bitNdx % 2 == 0 ? x1 : y1) & (0x1u << (bitNdx / 2u))) == 0u ? 0u : 1u);
   1650 							divider *= 2;
   1651 						}
   1652 
   1653 						reference.getAccess().setPixel(Vec4(depth, 0.0f, 0.0f, 0.0f), x, y);
   1654 					}
   1655 				}
   1656 				if (hasStencil)
   1657 				{
   1658 					for (deUint32 y = 0; y < m_height; y++)
   1659 					for (deUint32 x = 0; x < m_width; x++)
   1660 					{
   1661 						const deUint32	stencil	= sampleNdx + 1u;
   1662 
   1663 						if (hasDepth)
   1664 						{
   1665 							const Vec4 src (reference.getAccess().getPixel(x, y));
   1666 
   1667 							reference.getAccess().setPixel(Vec4(src.x(), (float)stencil, 0.0f, 0.0f), x, y);
   1668 						}
   1669 						else
   1670 							reference.getAccess().setPixel(Vec4((float)stencil, 0.0f, 0.0f, 0.0f), x, y);
   1671 					}
   1672 				}
   1673 				{
   1674 					const Vec4 threshold (hasDepth ? (1.0f / 1024.0f) : 0.0f, 0.0f, 0.0f, 0.0f);
   1675 
   1676 					if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
   1677 						m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1678 				}
   1679 			}
   1680 			else
   1681 			{
   1682 				const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
   1683 
   1684 				switch (channelClass)
   1685 				{
   1686 					case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1687 					{
   1688 						const UVec4		bits			(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1689 						const UVec4		minValue		(0);
   1690 						const UVec4		range			(UVec4(1u) << tcu::min(bits, UVec4(31)));
   1691 						const int		componentCount	(tcu::getNumUsedChannels(format.order));
   1692 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   1693 
   1694 						for (deUint32 y = 0; y < m_height; y++)
   1695 						for (deUint32 x = 0; x < m_width; x++)
   1696 						{
   1697 							const deUint32	x1				= x ^ sampleNdx;
   1698 							const deUint32	y1				= y ^ sampleNdx;
   1699 							UVec4			color			(minValue);
   1700 							deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   1701 							deUint32		nextSrcBit		= 0;
   1702 							deUint32		divider			= 2;
   1703 
   1704 							// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1705 							while (nextSrcBit < de::min(bitSize, 10u))
   1706 							{
   1707 								for (int compNdx = 0; compNdx < componentCount; compNdx++)
   1708 								{
   1709 									if (dstBitsUsed[compNdx] > bits[compNdx])
   1710 										continue;
   1711 
   1712 									color[compNdx] += (range[compNdx] / divider)
   1713 													* (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
   1714 
   1715 									nextSrcBit++;
   1716 									dstBitsUsed[compNdx]++;
   1717 								}
   1718 
   1719 								divider *= 2;
   1720 							}
   1721 
   1722 							reference.getAccess().setPixel(color, x, y);
   1723 						}
   1724 
   1725 						if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
   1726 							m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1727 
   1728 						break;
   1729 					}
   1730 
   1731 					case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1732 					{
   1733 						const UVec4		bits			(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1734 						const IVec4		minValue		(0);
   1735 						const IVec4		range			((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
   1736 						const int		componentCount	(tcu::getNumUsedChannels(format.order));
   1737 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   1738 
   1739 						for (deUint32 y = 0; y < m_height; y++)
   1740 						for (deUint32 x = 0; x < m_width; x++)
   1741 						{
   1742 							const deUint32	x1				= x ^ sampleNdx;
   1743 							const deUint32	y1				= y ^ sampleNdx;
   1744 							IVec4			color			(minValue);
   1745 							deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   1746 							deUint32		nextSrcBit		= 0;
   1747 							deUint32		divider			= 2;
   1748 
   1749 							// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1750 							while (nextSrcBit < de::min(bitSize, 10u))
   1751 							{
   1752 								for (int compNdx = 0; compNdx < componentCount; compNdx++)
   1753 								{
   1754 									if (dstBitsUsed[compNdx] > bits[compNdx])
   1755 										continue;
   1756 
   1757 									color[compNdx] += (range[compNdx] / divider)
   1758 													* (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
   1759 
   1760 									nextSrcBit++;
   1761 									dstBitsUsed[compNdx]++;
   1762 								}
   1763 
   1764 								divider *= 2;
   1765 							}
   1766 
   1767 							reference.getAccess().setPixel(color, x, y);
   1768 						}
   1769 
   1770 						if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
   1771 							m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1772 
   1773 						break;
   1774 					}
   1775 
   1776 					case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1777 					case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1778 					case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1779 					{
   1780 						const tcu::TextureFormatInfo	info			(tcu::getTextureFormatInfo(format));
   1781 						const UVec4						bits			(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1782 						const Vec4						minLimit		(-65536.0);
   1783 						const Vec4						maxLimit		(65536.0);
   1784 						const Vec4						minValue		(tcu::max(info.valueMin, minLimit));
   1785 						const Vec4						range			(tcu::min(info.valueMax, maxLimit) - minValue);
   1786 						const int						componentCount	(tcu::getNumUsedChannels(format.order));
   1787 						const deUint32					bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   1788 
   1789 						for (deUint32 y = 0; y < m_height; y++)
   1790 						for (deUint32 x = 0; x < m_width; x++)
   1791 						{
   1792 							const deUint32	x1				= x ^ sampleNdx;
   1793 							const deUint32	y1				= y ^ sampleNdx;
   1794 							Vec4			color			(minValue);
   1795 							deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   1796 							deUint32		nextSrcBit		= 0;
   1797 							deUint32		divider			= 2;
   1798 
   1799 							// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1800 							while (nextSrcBit < de::min(bitSize, 10u))
   1801 							{
   1802 								for (int compNdx = 0; compNdx < componentCount; compNdx++)
   1803 								{
   1804 									if (dstBitsUsed[compNdx] > bits[compNdx])
   1805 										continue;
   1806 
   1807 									color[compNdx] += (range[compNdx] / (float)divider)
   1808 													* (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
   1809 
   1810 									nextSrcBit++;
   1811 									dstBitsUsed[compNdx]++;
   1812 								}
   1813 
   1814 								divider *= 2;
   1815 							}
   1816 
   1817 							if (tcu::isSRGB(format))
   1818 								reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
   1819 							else
   1820 								reference.getAccess().setPixel(color, x, y);
   1821 						}
   1822 
   1823 						if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
   1824 						{
   1825 							// Convert target format ulps to float ulps and allow 64ulp differences
   1826 							const UVec4 threshold (64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>())));
   1827 
   1828 							if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
   1829 								m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1830 						}
   1831 						else
   1832 						{
   1833 							// Allow error of 4 times the minimum presentable difference
   1834 							const Vec4 threshold (4.0f * 1.0f / ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()) - 1u).cast<float>());
   1835 
   1836 							if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
   1837 								m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1838 						}
   1839 
   1840 						break;
   1841 					}
   1842 
   1843 					default:
   1844 						DE_FATAL("Unknown channel class");
   1845 				}
   1846 			}
   1847 		}
   1848 	}
   1849 
   1850 	return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
   1851 }
   1852 
   1853 struct Programs
   1854 {
   1855 	void init (vk::SourceCollections& dst, TestConfig config) const
   1856 	{
   1857 		const tcu::TextureFormat		format			(mapVkFormat(config.format));
   1858 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
   1859 
   1860 		dst.glslSources.add("quad-vert") << glu::VertexSource(
   1861 			"#version 450\n"
   1862 			"out gl_PerVertex {\n"
   1863 			"\tvec4 gl_Position;\n"
   1864 			"};\n"
   1865 			"highp float;\n"
   1866 			"void main (void) {\n"
   1867 			"\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
   1868 			"\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
   1869 			"}\n");
   1870 
   1871 		if (tcu::hasDepthComponent(format.order))
   1872 		{
   1873 			const Vec4			minValue		(0.0f);
   1874 			const Vec4			range			(1.0f);
   1875 			std::ostringstream	fragmentShader;
   1876 
   1877 			fragmentShader <<
   1878 				"#version 450\n"
   1879 				"layout(push_constant) uniform PushConstant {\n"
   1880 				"\thighp uint sampleIndex;\n"
   1881 				"} pushConstants;\n"
   1882 				"void main (void)\n"
   1883 				"{\n"
   1884 				"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   1885 				"\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
   1886 				"\thighp float depth;\n"
   1887 				"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
   1888 				"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
   1889 
   1890 			fragmentShader << "\tdepth = "  << minValue[0] << ";\n";
   1891 
   1892 			{
   1893 				deUint32 divider = 2;
   1894 
   1895 				// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1896 				for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
   1897 				{
   1898 					fragmentShader <<
   1899 							"\tdepth += " << (range[0] / (float)divider)
   1900 							<< " * float(bitfieldExtract(" << (bitNdx % 2 == 0 ? "x" : "y") << ", " << (bitNdx / 2) << ", 1));\n";
   1901 
   1902 					divider *= 2;
   1903 				}
   1904 			}
   1905 
   1906 			fragmentShader <<
   1907 				"\tgl_FragDepth = depth;\n"
   1908 				"}\n";
   1909 
   1910 			dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
   1911 		}
   1912 		else if (tcu::hasStencilComponent(format.order))
   1913 		{
   1914 			dst.glslSources.add("quad-frag") << glu::FragmentSource(
   1915 				"#version 450\n"
   1916 				"layout(push_constant) uniform PushConstant {\n"
   1917 				"\thighp uint sampleIndex;\n"
   1918 				"} pushConstants;\n"
   1919 				"void main (void)\n"
   1920 				"{\n"
   1921 				"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   1922 				"\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
   1923 				"}\n");
   1924 		}
   1925 		else
   1926 		{
   1927 			switch (channelClass)
   1928 			{
   1929 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1930 				{
   1931 					const UVec4	bits		(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1932 					const UVec4 minValue	(0);
   1933 					const UVec4 range		(UVec4(1u) << tcu::min(bits, UVec4(31)));
   1934 					std::ostringstream		fragmentShader;
   1935 
   1936 					fragmentShader <<
   1937 						"#version 450\n"
   1938 						"layout(location = 0) out highp uvec4 o_color;\n"
   1939 						"layout(push_constant) uniform PushConstant {\n"
   1940 						"\thighp uint sampleIndex;\n"
   1941 						"} pushConstants;\n"
   1942 						"void main (void)\n"
   1943 						"{\n"
   1944 						"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   1945 						"\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
   1946 						"\thighp uint color[4];\n"
   1947 						"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
   1948 						"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
   1949 
   1950 					for (int ndx = 0; ndx < 4; ndx++)
   1951 						fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
   1952 
   1953 					{
   1954 						const int		componentCount	= tcu::getNumUsedChannels(format.order);
   1955 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   1956 						deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   1957 						deUint32		nextSrcBit		= 0;
   1958 						deUint32		divider			= 2;
   1959 
   1960 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1961 						while (nextSrcBit < de::min(bitSize, 10u))
   1962 						{
   1963 							for (int compNdx = 0; compNdx < componentCount; compNdx++)
   1964 							{
   1965 								if (dstBitsUsed[compNdx] > bits[compNdx])
   1966 									continue;
   1967 
   1968 								fragmentShader <<
   1969 										"\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
   1970 										<< " * bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1);\n";
   1971 
   1972 								nextSrcBit++;
   1973 								dstBitsUsed[compNdx]++;
   1974 							}
   1975 
   1976 							divider *= 2;
   1977 						}
   1978 					}
   1979 
   1980 					fragmentShader <<
   1981 						"\to_color = uvec4(color[0], color[1], color[2], color[3]);\n"
   1982 						"}\n";
   1983 
   1984 					dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
   1985 					break;
   1986 				}
   1987 
   1988 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1989 				{
   1990 					const UVec4	bits		(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1991 					const IVec4 minValue	(0);
   1992 					const IVec4 range		((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
   1993 					const IVec4 maxV		((UVec4(1u) << (bits - UVec4(1u))).cast<deInt32>());
   1994 					const IVec4 clampMax	(maxV - 1);
   1995 					const IVec4 clampMin	(-maxV);
   1996 					std::ostringstream		fragmentShader;
   1997 
   1998 					fragmentShader <<
   1999 						"#version 450\n"
   2000 						"layout(location = 0) out highp ivec4 o_color;\n"
   2001 						"layout(push_constant) uniform PushConstant {\n"
   2002 						"\thighp uint sampleIndex;\n"
   2003 						"} pushConstants;\n"
   2004 						"void main (void)\n"
   2005 						"{\n"
   2006 						"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   2007 						"\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
   2008 						"\thighp int color[4];\n"
   2009 						"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
   2010 						"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
   2011 
   2012 					for (int ndx = 0; ndx < 4; ndx++)
   2013 						fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
   2014 
   2015 					{
   2016 						const int		componentCount	= tcu::getNumUsedChannels(format.order);
   2017 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   2018 						deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   2019 						deUint32		nextSrcBit		= 0;
   2020 						deUint32		divider			= 2;
   2021 
   2022 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   2023 						while (nextSrcBit < de::min(bitSize, 10u))
   2024 						{
   2025 							for (int compNdx = 0; compNdx < componentCount; compNdx++)
   2026 							{
   2027 								if (dstBitsUsed[compNdx] > bits[compNdx])
   2028 									continue;
   2029 
   2030 								fragmentShader <<
   2031 										"\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
   2032 										<< " * int(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
   2033 
   2034 								nextSrcBit++;
   2035 								dstBitsUsed[compNdx]++;
   2036 							}
   2037 
   2038 							divider *= 2;
   2039 						}
   2040 					}
   2041 
   2042 					// The spec doesn't define whether signed-integers are clamped on output,
   2043 					// so we'll clamp them explicitly to have well-defined outputs.
   2044 					fragmentShader <<
   2045 						"\to_color = clamp(ivec4(color[0], color[1], color[2], color[3]), " <<
   2046 						"ivec4" << clampMin << ", ivec4" << clampMax << ");\n" <<
   2047 						"}\n";
   2048 
   2049 					dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
   2050 					break;
   2051 				}
   2052 
   2053 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   2054 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   2055 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   2056 				{
   2057 					const tcu::TextureFormatInfo	info			(tcu::getTextureFormatInfo(format));
   2058 					const UVec4						bits			(tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>());
   2059 					const Vec4						minLimit		(-65536.0);
   2060 					const Vec4						maxLimit		(65536.0);
   2061 					const Vec4						minValue		(tcu::max(info.valueMin, minLimit));
   2062 					const Vec4						range			(tcu::min(info.valueMax, maxLimit) - minValue);
   2063 					std::ostringstream				fragmentShader;
   2064 
   2065 					fragmentShader <<
   2066 						"#version 450\n"
   2067 						"layout(location = 0) out highp vec4 o_color;\n"
   2068 						"layout(push_constant) uniform PushConstant {\n"
   2069 						"\thighp uint sampleIndex;\n"
   2070 						"} pushConstants;\n"
   2071 						"void main (void)\n"
   2072 						"{\n"
   2073 						"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   2074 						"\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
   2075 						"\thighp float color[4];\n"
   2076 						"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
   2077 						"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
   2078 
   2079 					for (int ndx = 0; ndx < 4; ndx++)
   2080 						fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
   2081 
   2082 					{
   2083 						const int		componentCount	= tcu::getNumUsedChannels(format.order);
   2084 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   2085 						deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   2086 						deUint32		nextSrcBit		= 0;
   2087 						deUint32		divider			= 2;
   2088 
   2089 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   2090 						while (nextSrcBit < de::min(bitSize, 10u))
   2091 						{
   2092 							for (int compNdx = 0; compNdx < componentCount; compNdx++)
   2093 							{
   2094 								if (dstBitsUsed[compNdx] > bits[compNdx])
   2095 									continue;
   2096 
   2097 								fragmentShader <<
   2098 										"\tcolor[" << compNdx << "] += " << (range[compNdx] / (float)divider)
   2099 										<< " * float(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
   2100 
   2101 								nextSrcBit++;
   2102 								dstBitsUsed[compNdx]++;
   2103 							}
   2104 
   2105 							divider *= 2;
   2106 						}
   2107 					}
   2108 
   2109 					fragmentShader <<
   2110 						"\to_color = vec4(color[0], color[1], color[2], color[3]);\n"
   2111 						"}\n";
   2112 
   2113 					dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
   2114 					break;
   2115 				}
   2116 
   2117 				default:
   2118 					DE_FATAL("Unknown channel class");
   2119 			}
   2120 		}
   2121 
   2122 		if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
   2123 		{
   2124 			std::ostringstream splitShader;
   2125 
   2126 			splitShader <<
   2127 				"#version 450\n";
   2128 
   2129 			if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
   2130 			{
   2131 				splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n"
   2132 							<< "layout(input_attachment_index = 0, set = 0, binding = 1) uniform highp usubpassInputMS i_stencil;\n";
   2133 			}
   2134 			else if (tcu::hasDepthComponent(format.order))
   2135 				splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n";
   2136 			else if (tcu::hasStencilComponent(format.order))
   2137 				splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp usubpassInputMS i_stencil;\n";
   2138 
   2139 			splitShader <<
   2140 				"layout(push_constant) uniform PushConstant {\n"
   2141 				"\thighp uint splitSubpassIndex;\n"
   2142 				"} pushConstants;\n";
   2143 
   2144 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
   2145 			{
   2146 				if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
   2147 					splitShader << "layout(location = " << attachmentNdx << ") out highp vec2 o_color" << attachmentNdx << ";\n";
   2148 				else
   2149 					splitShader << "layout(location = " << attachmentNdx << ") out highp float o_color" << attachmentNdx << ";\n";
   2150 			}
   2151 
   2152 			splitShader <<
   2153 				"void main (void)\n"
   2154 				"{\n";
   2155 
   2156 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
   2157 			{
   2158 				if (tcu::hasDepthComponent(format.order))
   2159 					splitShader << "\thighp float depth" << attachmentNdx << " = subpassLoad(i_depth, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
   2160 
   2161 				if (tcu::hasStencilComponent(format.order))
   2162 					splitShader << "\thighp uint stencil" << attachmentNdx << " = subpassLoad(i_stencil, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
   2163 
   2164 				if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
   2165 					splitShader << "\to_color" << attachmentNdx << " = vec2(depth" << attachmentNdx << ", float(stencil" << attachmentNdx << "));\n";
   2166 				else if (tcu::hasDepthComponent(format.order))
   2167 					splitShader << "\to_color" << attachmentNdx << " = float(depth" << attachmentNdx << ");\n";
   2168 				else if (tcu::hasStencilComponent(format.order))
   2169 					splitShader << "\to_color" << attachmentNdx << " = float(stencil" << attachmentNdx << ");\n";
   2170 			}
   2171 
   2172 			splitShader <<
   2173 				"}\n";
   2174 
   2175 			dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
   2176 		}
   2177 		else
   2178 		{
   2179 			std::string subpassType;
   2180 			std::string outputType;
   2181 
   2182 			switch (channelClass)
   2183 			{
   2184 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   2185 					subpassType	= "usubpassInputMS";
   2186 					outputType	= "uvec4";
   2187 					break;
   2188 
   2189 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   2190 					subpassType	= "isubpassInputMS";
   2191 					outputType	= "ivec4";
   2192 					break;
   2193 
   2194 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   2195 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   2196 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   2197 					subpassType	= "subpassInputMS";
   2198 					outputType	= "vec4";
   2199 					break;
   2200 
   2201 				default:
   2202 					DE_FATAL("Unknown channel class");
   2203 			}
   2204 
   2205 			std::ostringstream splitShader;
   2206 			splitShader <<
   2207 				"#version 450\n"
   2208 				"layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp " << subpassType << " i_color;\n"
   2209 				"layout(push_constant) uniform PushConstant {\n"
   2210 				"\thighp uint splitSubpassIndex;\n"
   2211 				"} pushConstants;\n";
   2212 
   2213 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
   2214 				splitShader << "layout(location = " << attachmentNdx << ") out highp " << outputType << " o_color" << attachmentNdx << ";\n";
   2215 
   2216 			splitShader <<
   2217 				"void main (void)\n"
   2218 				"{\n";
   2219 
   2220 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
   2221 				splitShader << "\to_color" << attachmentNdx << " = subpassLoad(i_color, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u));\n";
   2222 
   2223 			splitShader <<
   2224 				"}\n";
   2225 
   2226 			dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
   2227 		}
   2228 	}
   2229 };
   2230 
   2231 std::string formatToName (VkFormat format)
   2232 {
   2233 	const std::string	formatStr	= de::toString(format);
   2234 	const std::string	prefix		= "VK_FORMAT_";
   2235 
   2236 	DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
   2237 
   2238 	return de::toLower(formatStr.substr(prefix.length()));
   2239 }
   2240 
   2241 void initTests (tcu::TestCaseGroup* group)
   2242 {
   2243 	static const VkFormat	formats[]	=
   2244 	{
   2245 		VK_FORMAT_R5G6B5_UNORM_PACK16,
   2246 		VK_FORMAT_R8_UNORM,
   2247 		VK_FORMAT_R8_SNORM,
   2248 		VK_FORMAT_R8_UINT,
   2249 		VK_FORMAT_R8_SINT,
   2250 		VK_FORMAT_R8G8_UNORM,
   2251 		VK_FORMAT_R8G8_SNORM,
   2252 		VK_FORMAT_R8G8_UINT,
   2253 		VK_FORMAT_R8G8_SINT,
   2254 		VK_FORMAT_R8G8B8A8_UNORM,
   2255 		VK_FORMAT_R8G8B8A8_SNORM,
   2256 		VK_FORMAT_R8G8B8A8_UINT,
   2257 		VK_FORMAT_R8G8B8A8_SINT,
   2258 		VK_FORMAT_R8G8B8A8_SRGB,
   2259 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
   2260 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
   2261 		VK_FORMAT_A8B8G8R8_UINT_PACK32,
   2262 		VK_FORMAT_A8B8G8R8_SINT_PACK32,
   2263 		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
   2264 		VK_FORMAT_B8G8R8A8_UNORM,
   2265 		VK_FORMAT_B8G8R8A8_SRGB,
   2266 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
   2267 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
   2268 		VK_FORMAT_A2B10G10R10_UINT_PACK32,
   2269 		VK_FORMAT_R16_UNORM,
   2270 		VK_FORMAT_R16_SNORM,
   2271 		VK_FORMAT_R16_UINT,
   2272 		VK_FORMAT_R16_SINT,
   2273 		VK_FORMAT_R16_SFLOAT,
   2274 		VK_FORMAT_R16G16_UNORM,
   2275 		VK_FORMAT_R16G16_SNORM,
   2276 		VK_FORMAT_R16G16_UINT,
   2277 		VK_FORMAT_R16G16_SINT,
   2278 		VK_FORMAT_R16G16_SFLOAT,
   2279 		VK_FORMAT_R16G16B16A16_UNORM,
   2280 		VK_FORMAT_R16G16B16A16_SNORM,
   2281 		VK_FORMAT_R16G16B16A16_UINT,
   2282 		VK_FORMAT_R16G16B16A16_SINT,
   2283 		VK_FORMAT_R16G16B16A16_SFLOAT,
   2284 		VK_FORMAT_R32_UINT,
   2285 		VK_FORMAT_R32_SINT,
   2286 		VK_FORMAT_R32_SFLOAT,
   2287 		VK_FORMAT_R32G32_UINT,
   2288 		VK_FORMAT_R32G32_SINT,
   2289 		VK_FORMAT_R32G32_SFLOAT,
   2290 		VK_FORMAT_R32G32B32A32_UINT,
   2291 		VK_FORMAT_R32G32B32A32_SINT,
   2292 		VK_FORMAT_R32G32B32A32_SFLOAT,
   2293 
   2294 		VK_FORMAT_D16_UNORM,
   2295 		VK_FORMAT_X8_D24_UNORM_PACK32,
   2296 		VK_FORMAT_D32_SFLOAT,
   2297 		VK_FORMAT_S8_UINT,
   2298 		VK_FORMAT_D16_UNORM_S8_UINT,
   2299 		VK_FORMAT_D24_UNORM_S8_UINT,
   2300 		VK_FORMAT_D32_SFLOAT_S8_UINT
   2301 	};
   2302 	const deUint32			sampleCounts[] =
   2303 	{
   2304 		2u, 4u, 8u, 16u, 32u
   2305 	};
   2306 	tcu::TestContext&		testCtx		(group->getTestContext());
   2307 
   2308 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
   2309 	{
   2310 		const VkFormat					format		(formats[formatNdx]);
   2311 		const std::string				formatName	(formatToName(format));
   2312 		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
   2313 
   2314 		for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
   2315 		{
   2316 			const deUint32		sampleCount	(sampleCounts[sampleCountNdx]);
   2317 			const std::string	testName	("samples_" + de::toString(sampleCount));
   2318 
   2319 			formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount)));
   2320 		}
   2321 
   2322 		group->addChild(formatGroup.release());
   2323 	}
   2324 }
   2325 
   2326 } // anonymous
   2327 
   2328 tcu::TestCaseGroup* createRenderPassMultisampleTests (tcu::TestContext& testCtx)
   2329 {
   2330 	return createTestGroup(testCtx, "multisample", "Multisample render pass tests", initTests);
   2331 }
   2332 
   2333 } // vkt
   2334