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 									   VkRenderPass										renderPass,
    715 									   VkPipelineLayout									pipelineLayout,
    716 									   const vk::ProgramCollection<vk::ProgramBinary>&	binaryCollection,
    717 									   deUint32											width,
    718 									   deUint32											height,
    719 									   deUint32											sampleCount)
    720 {
    721 	const Unique<VkShaderModule>	vertexShaderModule			(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
    722 	const Unique<VkShaderModule>	fragmentShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
    723 	const VkSpecializationInfo		emptyShaderSpecializations	=
    724 	{
    725 		0u,
    726 		DE_NULL,
    727 
    728 		0u,
    729 		DE_NULL
    730 	};
    731 	// Disable blending
    732 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
    733 	{
    734 		VK_FALSE,
    735 		VK_BLEND_FACTOR_SRC_ALPHA,
    736 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
    737 		VK_BLEND_OP_ADD,
    738 		VK_BLEND_FACTOR_ONE,
    739 		VK_BLEND_FACTOR_ONE,
    740 		VK_BLEND_OP_ADD,
    741 		VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
    742 	};
    743 	const VkPipelineShaderStageCreateInfo shaderStages[2] =
    744 	{
    745 		{
    746 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
    747 			DE_NULL,
    748 			(VkPipelineShaderStageCreateFlags)0u,
    749 			VK_SHADER_STAGE_VERTEX_BIT,
    750 			*vertexShaderModule,
    751 			"main",
    752 			&emptyShaderSpecializations
    753 		},
    754 		{
    755 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
    756 			DE_NULL,
    757 			(VkPipelineShaderStageCreateFlags)0u,
    758 			VK_SHADER_STAGE_FRAGMENT_BIT,
    759 			*fragmentShaderModule,
    760 			"main",
    761 			&emptyShaderSpecializations
    762 		}
    763 	};
    764 	const VkPipelineVertexInputStateCreateInfo vertexInputState =
    765 	{
    766 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
    767 		DE_NULL,
    768 		(VkPipelineVertexInputStateCreateFlags)0u,
    769 
    770 		0u,
    771 		DE_NULL,
    772 
    773 		0u,
    774 		DE_NULL
    775 	};
    776 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
    777 	{
    778 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
    779 		DE_NULL,
    780 
    781 		(VkPipelineInputAssemblyStateCreateFlags)0u,
    782 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
    783 		VK_FALSE
    784 	};
    785 	const VkViewport viewport =
    786 	{
    787 		0.0f,  0.0f,
    788 		(float)width, (float)height,
    789 
    790 		0.0f, 1.0f
    791 	};
    792 	const VkRect2D scissor =
    793 	{
    794 		{ 0u, 0u },
    795 		{ width, height }
    796 	};
    797 	const VkPipelineViewportStateCreateInfo viewportState =
    798 	{
    799 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
    800 		DE_NULL,
    801 		(VkPipelineViewportStateCreateFlags)0u,
    802 
    803 		1u,
    804 		&viewport,
    805 
    806 		1u,
    807 		&scissor
    808 	};
    809 	const VkPipelineRasterizationStateCreateInfo rasterState =
    810 	{
    811 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
    812 		DE_NULL,
    813 		(VkPipelineRasterizationStateCreateFlags)0u,
    814 		VK_TRUE,
    815 		VK_FALSE,
    816 		VK_POLYGON_MODE_FILL,
    817 		VK_CULL_MODE_NONE,
    818 		VK_FRONT_FACE_COUNTER_CLOCKWISE,
    819 		VK_FALSE,
    820 		0.0f,
    821 		0.0f,
    822 		0.0f,
    823 		1.0f
    824 	};
    825 	const VkPipelineMultisampleStateCreateInfo multisampleState =
    826 	{
    827 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
    828 		DE_NULL,
    829 		(VkPipelineMultisampleStateCreateFlags)0u,
    830 
    831 		sampleCountBitFromomSampleCount(sampleCount),
    832 		VK_FALSE,
    833 		0.0f,
    834 		DE_NULL,
    835 		VK_FALSE,
    836 		VK_FALSE,
    837 	};
    838 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
    839 	{
    840 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
    841 		DE_NULL,
    842 		(VkPipelineDepthStencilStateCreateFlags)0u,
    843 
    844 		VK_TRUE,
    845 		VK_TRUE,
    846 		VK_COMPARE_OP_ALWAYS,
    847 		VK_FALSE,
    848 		VK_TRUE,
    849 		{
    850 			VK_STENCIL_OP_KEEP,
    851 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
    852 			VK_STENCIL_OP_KEEP,
    853 			VK_COMPARE_OP_ALWAYS,
    854 			~0u,
    855 			~0u,
    856 			0xFFu / (sampleCount + 1)
    857 		},
    858 		{
    859 			VK_STENCIL_OP_KEEP,
    860 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
    861 			VK_STENCIL_OP_KEEP,
    862 			VK_COMPARE_OP_ALWAYS,
    863 			~0u,
    864 			~0u,
    865 			0xFFu / (sampleCount + 1)
    866 		},
    867 
    868 		0.0f,
    869 		1.0f
    870 	};
    871 	const VkPipelineColorBlendStateCreateInfo blendState =
    872 	{
    873 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
    874 		DE_NULL,
    875 		(VkPipelineColorBlendStateCreateFlags)0u,
    876 
    877 		VK_FALSE,
    878 		VK_LOGIC_OP_COPY,
    879 		1u,
    880 		&attachmentBlendState,
    881 		{ 0.0f, 0.0f, 0.0f, 0.0f }
    882 	};
    883 	const VkGraphicsPipelineCreateInfo createInfo =
    884 	{
    885 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
    886 		DE_NULL,
    887 		(VkPipelineCreateFlags)0u,
    888 
    889 		2,
    890 		shaderStages,
    891 
    892 		&vertexInputState,
    893 		&inputAssemblyState,
    894 		DE_NULL,
    895 		&viewportState,
    896 		&rasterState,
    897 		&multisampleState,
    898 		&depthStencilState,
    899 		&blendState,
    900 		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,
    901 		pipelineLayout,
    902 
    903 		renderPass,
    904 		0u,
    905 		DE_NULL,
    906 		0u
    907 	};
    908 
    909 	return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
    910 }
    911 
    912 Move<VkDescriptorSetLayout> createSplitDescriptorSetLayout (const DeviceInterface&	vkd,
    913 															VkDevice				device,
    914 															VkFormat				vkFormat)
    915 {
    916 	const tcu::TextureFormat				format		(mapVkFormat(vkFormat));
    917 	const bool								hasDepth	(tcu::hasDepthComponent(format.order));
    918 	const bool								hasStencil	(tcu::hasStencilComponent(format.order));
    919 	const VkDescriptorSetLayoutBinding		bindings[]	=
    920 	{
    921 		{
    922 			0u,
    923 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
    924 			1u,
    925 			VK_SHADER_STAGE_FRAGMENT_BIT,
    926 			DE_NULL
    927 		},
    928 		{
    929 			1u,
    930 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
    931 			1u,
    932 			VK_SHADER_STAGE_FRAGMENT_BIT,
    933 			DE_NULL
    934 		}
    935 	};
    936 	const VkDescriptorSetLayoutCreateInfo	createInfo	=
    937 	{
    938 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
    939 		DE_NULL,
    940 		0u,
    941 
    942 		hasDepth && hasStencil ? 2u : 1u,
    943 		bindings
    944 	};
    945 
    946 	return createDescriptorSetLayout(vkd, device, &createInfo);
    947 }
    948 
    949 Move<VkPipelineLayout> createSplitPipelineLayout (const DeviceInterface&	vkd,
    950 												  VkDevice					device,
    951 												  VkDescriptorSetLayout		descriptorSetLayout)
    952 {
    953 	const VkPushConstantRange			pushConstant			=
    954 	{
    955 		VK_SHADER_STAGE_FRAGMENT_BIT,
    956 		0u,
    957 		4u
    958 	};
    959 	const VkPipelineLayoutCreateInfo	createInfo	=
    960 	{
    961 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
    962 		DE_NULL,
    963 		(vk::VkPipelineLayoutCreateFlags)0,
    964 
    965 		1u,
    966 		&descriptorSetLayout,
    967 
    968 		1u,
    969 		&pushConstant
    970 	};
    971 
    972 	return createPipelineLayout(vkd, device, &createInfo);
    973 }
    974 
    975 Move<VkPipeline> createSplitPipeline (const DeviceInterface&							vkd,
    976 									  VkDevice											device,
    977 									  VkRenderPass										renderPass,
    978 									  deUint32											subpassIndex,
    979 									  VkPipelineLayout									pipelineLayout,
    980 									  const vk::ProgramCollection<vk::ProgramBinary>&	binaryCollection,
    981 									  deUint32											width,
    982 									  deUint32											height,
    983 									  deUint32											sampleCount)
    984 {
    985 	const Unique<VkShaderModule>	vertexShaderModule			(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
    986 	const Unique<VkShaderModule>	fragmentShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-split-frag"), 0u));
    987 	const VkSpecializationInfo		emptyShaderSpecializations	=
    988 	{
    989 		0u,
    990 		DE_NULL,
    991 
    992 		0u,
    993 		DE_NULL
    994 	};
    995 	// Disable blending
    996 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
    997 	{
    998 		VK_FALSE,
    999 		VK_BLEND_FACTOR_SRC_ALPHA,
   1000 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
   1001 		VK_BLEND_OP_ADD,
   1002 		VK_BLEND_FACTOR_ONE,
   1003 		VK_BLEND_FACTOR_ONE,
   1004 		VK_BLEND_OP_ADD,
   1005 		VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
   1006 	};
   1007 	const std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates (de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount), attachmentBlendState);
   1008 	const VkPipelineShaderStageCreateInfo shaderStages[2] =
   1009 	{
   1010 		{
   1011 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
   1012 			DE_NULL,
   1013 			(VkPipelineShaderStageCreateFlags)0u,
   1014 			VK_SHADER_STAGE_VERTEX_BIT,
   1015 			*vertexShaderModule,
   1016 			"main",
   1017 			&emptyShaderSpecializations
   1018 		},
   1019 		{
   1020 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
   1021 			DE_NULL,
   1022 			(VkPipelineShaderStageCreateFlags)0u,
   1023 			VK_SHADER_STAGE_FRAGMENT_BIT,
   1024 			*fragmentShaderModule,
   1025 			"main",
   1026 			&emptyShaderSpecializations
   1027 		}
   1028 	};
   1029 	const VkPipelineVertexInputStateCreateInfo vertexInputState =
   1030 	{
   1031 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
   1032 		DE_NULL,
   1033 		(VkPipelineVertexInputStateCreateFlags)0u,
   1034 
   1035 		0u,
   1036 		DE_NULL,
   1037 
   1038 		0u,
   1039 		DE_NULL
   1040 	};
   1041 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
   1042 	{
   1043 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
   1044 		DE_NULL,
   1045 
   1046 		(VkPipelineInputAssemblyStateCreateFlags)0u,
   1047 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
   1048 		VK_FALSE
   1049 	};
   1050 	const VkViewport viewport =
   1051 	{
   1052 		0.0f,  0.0f,
   1053 		(float)width, (float)height,
   1054 
   1055 		0.0f, 1.0f
   1056 	};
   1057 	const VkRect2D scissor =
   1058 	{
   1059 		{ 0u, 0u },
   1060 		{ width, height }
   1061 	};
   1062 	const VkPipelineViewportStateCreateInfo viewportState =
   1063 	{
   1064 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
   1065 		DE_NULL,
   1066 		(VkPipelineViewportStateCreateFlags)0u,
   1067 
   1068 		1u,
   1069 		&viewport,
   1070 
   1071 		1u,
   1072 		&scissor
   1073 	};
   1074 	const VkPipelineRasterizationStateCreateInfo rasterState =
   1075 	{
   1076 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
   1077 		DE_NULL,
   1078 		(VkPipelineRasterizationStateCreateFlags)0u,
   1079 		VK_TRUE,
   1080 		VK_FALSE,
   1081 		VK_POLYGON_MODE_FILL,
   1082 		VK_CULL_MODE_NONE,
   1083 		VK_FRONT_FACE_COUNTER_CLOCKWISE,
   1084 		VK_FALSE,
   1085 		0.0f,
   1086 		0.0f,
   1087 		0.0f,
   1088 		1.0f
   1089 	};
   1090 	const VkPipelineMultisampleStateCreateInfo multisampleState =
   1091 	{
   1092 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
   1093 		DE_NULL,
   1094 		(VkPipelineMultisampleStateCreateFlags)0u,
   1095 
   1096 		sampleCountBitFromomSampleCount(sampleCount),
   1097 		VK_FALSE,
   1098 		0.0f,
   1099 		DE_NULL,
   1100 		VK_FALSE,
   1101 		VK_FALSE,
   1102 	};
   1103 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
   1104 	{
   1105 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
   1106 		DE_NULL,
   1107 		(VkPipelineDepthStencilStateCreateFlags)0u,
   1108 
   1109 		VK_FALSE,
   1110 		VK_FALSE,
   1111 		VK_COMPARE_OP_ALWAYS,
   1112 		VK_FALSE,
   1113 		VK_FALSE,
   1114 		{
   1115 			VK_STENCIL_OP_REPLACE,
   1116 			VK_STENCIL_OP_REPLACE,
   1117 			VK_STENCIL_OP_REPLACE,
   1118 			VK_COMPARE_OP_ALWAYS,
   1119 			~0u,
   1120 			~0u,
   1121 			0x0u
   1122 		},
   1123 		{
   1124 			VK_STENCIL_OP_REPLACE,
   1125 			VK_STENCIL_OP_REPLACE,
   1126 			VK_STENCIL_OP_REPLACE,
   1127 			VK_COMPARE_OP_ALWAYS,
   1128 			~0u,
   1129 			~0u,
   1130 			0x0u
   1131 		},
   1132 
   1133 		0.0f,
   1134 		1.0f
   1135 	};
   1136 	const VkPipelineColorBlendStateCreateInfo blendState =
   1137 	{
   1138 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
   1139 		DE_NULL,
   1140 		(VkPipelineColorBlendStateCreateFlags)0u,
   1141 
   1142 		VK_FALSE,
   1143 		VK_LOGIC_OP_COPY,
   1144 
   1145 		(deUint32)attachmentBlendStates.size(),
   1146 		&attachmentBlendStates[0],
   1147 
   1148 		{ 0.0f, 0.0f, 0.0f, 0.0f }
   1149 	};
   1150 	const VkGraphicsPipelineCreateInfo createInfo =
   1151 	{
   1152 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
   1153 		DE_NULL,
   1154 		(VkPipelineCreateFlags)0u,
   1155 
   1156 		2,
   1157 		shaderStages,
   1158 
   1159 		&vertexInputState,
   1160 		&inputAssemblyState,
   1161 		DE_NULL,
   1162 		&viewportState,
   1163 		&rasterState,
   1164 		&multisampleState,
   1165 		&depthStencilState,
   1166 		&blendState,
   1167 		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,
   1168 		pipelineLayout,
   1169 
   1170 		renderPass,
   1171 		subpassIndex,
   1172 		DE_NULL,
   1173 		0u
   1174 	};
   1175 
   1176 	return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
   1177 }
   1178 
   1179 vector<VkPipeline> createSplitPipelines (const DeviceInterface&								vkd,
   1180 										 VkDevice											device,
   1181 										 VkRenderPass										renderPass,
   1182 										 VkPipelineLayout									pipelineLayout,
   1183 										 const vk::ProgramCollection<vk::ProgramBinary>&	binaryCollection,
   1184 										 deUint32											width,
   1185 										 deUint32											height,
   1186 										 deUint32											sampleCount)
   1187 {
   1188 	vector<VkPipeline> pipelines (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT), (VkPipeline)0u);
   1189 
   1190 	try
   1191 	{
   1192 		for (size_t ndx = 0; ndx < pipelines.size(); ndx++)
   1193 			pipelines[ndx] = createSplitPipeline(vkd, device, renderPass, (deUint32)(ndx + 1), pipelineLayout, binaryCollection, width, height, sampleCount).disown();
   1194 	}
   1195 	catch (...)
   1196 	{
   1197 		for (size_t ndx = 0; ndx < pipelines.size(); ndx++)
   1198 			vkd.destroyPipeline(device, pipelines[ndx], DE_NULL);
   1199 
   1200 		throw;
   1201 	}
   1202 
   1203 	return pipelines;
   1204 }
   1205 
   1206 Move<VkDescriptorPool> createSplitDescriptorPool (const DeviceInterface&	vkd,
   1207 												  VkDevice					device)
   1208 {
   1209 	const VkDescriptorPoolSize			size		=
   1210 	{
   1211 		VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2u
   1212 	};
   1213 	const VkDescriptorPoolCreateInfo	createInfo	=
   1214 	{
   1215 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
   1216 		DE_NULL,
   1217 		VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
   1218 
   1219 
   1220 		2u,
   1221 		1u,
   1222 		&size
   1223 	};
   1224 
   1225 	return createDescriptorPool(vkd, device, &createInfo);
   1226 }
   1227 
   1228 Move<VkDescriptorSet> createSplitDescriptorSet (const DeviceInterface&	vkd,
   1229 												VkDevice				device,
   1230 												VkDescriptorPool		pool,
   1231 												VkDescriptorSetLayout	layout,
   1232 												VkImageView				primaryImageView,
   1233 												VkImageView				secondaryImageView)
   1234 {
   1235 	const VkDescriptorSetAllocateInfo	allocateInfo	=
   1236 	{
   1237 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   1238 		DE_NULL,
   1239 
   1240 		pool,
   1241 		1u,
   1242 		&layout
   1243 	};
   1244 	Move<VkDescriptorSet> set (allocateDescriptorSet(vkd, device, &allocateInfo));
   1245 
   1246 	{
   1247 		const VkDescriptorImageInfo	imageInfos[]	=
   1248 		{
   1249 			{
   1250 				(VkSampler)0u,
   1251 				primaryImageView,
   1252 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
   1253 			},
   1254 			{
   1255 				(VkSampler)0u,
   1256 				secondaryImageView,
   1257 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
   1258 			}
   1259 		};
   1260 		const VkWriteDescriptorSet	writes[]	=
   1261 		{
   1262 			{
   1263 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
   1264 				DE_NULL,
   1265 
   1266 				*set,
   1267 				0u,
   1268 				0u,
   1269 				1u,
   1270 				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
   1271 				&imageInfos[0],
   1272 				DE_NULL,
   1273 				DE_NULL
   1274 			},
   1275 			{
   1276 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
   1277 				DE_NULL,
   1278 
   1279 				*set,
   1280 				1u,
   1281 				0u,
   1282 				1u,
   1283 				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
   1284 				&imageInfos[1],
   1285 				DE_NULL,
   1286 				DE_NULL
   1287 			}
   1288 		};
   1289 		const deUint32	count	= secondaryImageView != (VkImageView)0
   1290 								? 2u
   1291 								: 1u;
   1292 
   1293 		vkd.updateDescriptorSets(device, count, writes, 0u, DE_NULL);
   1294 	}
   1295 	return set;
   1296 }
   1297 
   1298 struct TestConfig
   1299 {
   1300 				TestConfig		(VkFormat	format_,
   1301 								 deUint32	sampleCount_)
   1302 		: format		(format_)
   1303 		, sampleCount	(sampleCount_)
   1304 	{
   1305 	}
   1306 
   1307 	VkFormat	format;
   1308 	deUint32	sampleCount;
   1309 };
   1310 
   1311 VkImageUsageFlags getSrcImageUsage (VkFormat vkFormat)
   1312 {
   1313 	const tcu::TextureFormat	format		(mapVkFormat(vkFormat));
   1314 	const bool					hasDepth	(tcu::hasDepthComponent(format.order));
   1315 	const bool					hasStencil	(tcu::hasStencilComponent(format.order));
   1316 
   1317 	if (hasDepth || hasStencil)
   1318 		return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
   1319 	else
   1320 		return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
   1321 }
   1322 
   1323 VkFormat getDstFormat (VkFormat vkFormat)
   1324 {
   1325 	const tcu::TextureFormat	format		(mapVkFormat(vkFormat));
   1326 	const bool					hasDepth	(tcu::hasDepthComponent(format.order));
   1327 	const bool					hasStencil	(tcu::hasStencilComponent(format.order));
   1328 
   1329 	if (hasDepth && hasStencil)
   1330 		return VK_FORMAT_R32G32_SFLOAT;
   1331 	else if (hasDepth || hasStencil)
   1332 		return VK_FORMAT_R32_SFLOAT;
   1333 	else
   1334 		return vkFormat;
   1335 }
   1336 
   1337 
   1338 class MultisampleRenderPassTestInstance : public TestInstance
   1339 {
   1340 public:
   1341 					MultisampleRenderPassTestInstance	(Context& context, TestConfig config);
   1342 					~MultisampleRenderPassTestInstance	(void);
   1343 
   1344 	tcu::TestStatus	iterate								(void);
   1345 
   1346 private:
   1347 	const VkFormat									m_srcFormat;
   1348 	const VkFormat									m_dstFormat;
   1349 	const deUint32									m_sampleCount;
   1350 	const deUint32									m_width;
   1351 	const deUint32									m_height;
   1352 
   1353 	const VkImageAspectFlags						m_srcImageAspect;
   1354 	const VkImageUsageFlags							m_srcImageUsage;
   1355 	const Unique<VkImage>							m_srcImage;
   1356 	const de::UniquePtr<Allocation>					m_srcImageMemory;
   1357 	const Unique<VkImageView>						m_srcImageView;
   1358 	const Unique<VkImageView>						m_srcPrimaryInputImageView;
   1359 	const Unique<VkImageView>						m_srcSecondaryInputImageView;
   1360 
   1361 	const std::vector<VkImageSp>					m_dstMultisampleImages;
   1362 	const std::vector<de::SharedPtr<Allocation> >	m_dstMultisampleImageMemory;
   1363 	const std::vector<VkImageViewSp>				m_dstMultisampleImageViews;
   1364 
   1365 	const std::vector<VkImageSp>					m_dstSinglesampleImages;
   1366 	const std::vector<de::SharedPtr<Allocation> >	m_dstSinglesampleImageMemory;
   1367 	const std::vector<VkImageViewSp>				m_dstSinglesampleImageViews;
   1368 
   1369 	const std::vector<VkBufferSp>					m_dstBuffers;
   1370 	const std::vector<de::SharedPtr<Allocation> >	m_dstBufferMemory;
   1371 
   1372 	const Unique<VkRenderPass>						m_renderPass;
   1373 	const Unique<VkFramebuffer>						m_framebuffer;
   1374 
   1375 	const Unique<VkPipelineLayout>					m_renderPipelineLayout;
   1376 	const Unique<VkPipeline>						m_renderPipeline;
   1377 
   1378 	const Unique<VkDescriptorSetLayout>				m_splitDescriptorSetLayout;
   1379 	const Unique<VkPipelineLayout>					m_splitPipelineLayout;
   1380 	const vector<VkPipeline>						m_splitPipelines;
   1381 	const Unique<VkDescriptorPool>					m_splitDescriptorPool;
   1382 	const Unique<VkDescriptorSet>					m_splitDescriptorSet;
   1383 
   1384 	const Unique<VkCommandPool>						m_commandPool;
   1385 	tcu::ResultCollector							m_resultCollector;
   1386 };
   1387 
   1388 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
   1389 	: TestInstance					(context)
   1390 	, m_srcFormat					(config.format)
   1391 	, m_dstFormat					(getDstFormat(config.format))
   1392 	, m_sampleCount					(config.sampleCount)
   1393 	, m_width						(32u)
   1394 	, m_height						(32u)
   1395 
   1396 	, m_srcImageAspect				(getImageAspectFlags(m_srcFormat))
   1397 	, m_srcImageUsage				(getSrcImageUsage(m_srcFormat))
   1398 	, m_srcImage					(createImage(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_srcFormat, sampleCountBitFromomSampleCount(m_sampleCount), m_srcImageUsage, m_width, m_height))
   1399 	, m_srcImageMemory				(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), *m_srcImage))
   1400 	, m_srcImageView				(createImageAttachmentView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
   1401 	, m_srcPrimaryInputImageView	(createSrcPrimaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
   1402 	, m_srcSecondaryInputImageView	(createSrcSecondaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
   1403 
   1404 	, m_dstMultisampleImages		(createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
   1405 	, m_dstMultisampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstMultisampleImages))
   1406 	, m_dstMultisampleImageViews	(createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstMultisampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
   1407 
   1408 	, m_dstSinglesampleImages		(createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
   1409 	, m_dstSinglesampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstSinglesampleImages))
   1410 	, m_dstSinglesampleImageViews	(createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstSinglesampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
   1411 
   1412 	, m_dstBuffers					(createBuffers(context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
   1413 	, m_dstBufferMemory				(createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstBuffers))
   1414 
   1415 	, m_renderPass					(createRenderPass(context.getDeviceInterface(), context.getDevice(), m_srcFormat, m_dstFormat, m_sampleCount))
   1416 	, m_framebuffer					(createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_srcImageView, m_dstMultisampleImageViews, m_dstSinglesampleImageViews, m_width, m_height))
   1417 
   1418 	, m_renderPipelineLayout		(createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
   1419 	, m_renderPipeline				(createRenderPipeline(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
   1420 
   1421 	, m_splitDescriptorSetLayout	(createSplitDescriptorSetLayout(context.getDeviceInterface(), context.getDevice(), m_srcFormat))
   1422 	, m_splitPipelineLayout			(createSplitPipelineLayout(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorSetLayout))
   1423 	, m_splitPipelines				(createSplitPipelines(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_splitPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
   1424 	, m_splitDescriptorPool			(createSplitDescriptorPool(context.getDeviceInterface(), context.getDevice()))
   1425 	, m_splitDescriptorSet			(createSplitDescriptorSet(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorPool, *m_splitDescriptorSetLayout, *m_srcPrimaryInputImageView, *m_srcSecondaryInputImageView))
   1426 	, m_commandPool					(createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
   1427 {
   1428 }
   1429 
   1430 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
   1431 {
   1432 }
   1433 
   1434 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
   1435 {
   1436 	const DeviceInterface&			vkd				(m_context.getDeviceInterface());
   1437 	const VkDevice					device			(m_context.getDevice());
   1438 	const Unique<VkCommandBuffer>	commandBuffer	(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
   1439 
   1440 	{
   1441 		const VkCommandBufferBeginInfo beginInfo =
   1442 		{
   1443 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
   1444 			DE_NULL,
   1445 
   1446 			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
   1447 			DE_NULL
   1448 		};
   1449 
   1450 		VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
   1451 	}
   1452 
   1453 	{
   1454 		const VkRenderPassBeginInfo beginInfo =
   1455 		{
   1456 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
   1457 			DE_NULL,
   1458 
   1459 			*m_renderPass,
   1460 			*m_framebuffer,
   1461 
   1462 			{
   1463 				{ 0u, 0u },
   1464 				{ m_width, m_height }
   1465 			},
   1466 
   1467 			0u,
   1468 			DE_NULL
   1469 		};
   1470 		vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
   1471 	}
   1472 
   1473 	vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
   1474 
   1475 	for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
   1476 	{
   1477 		vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(sampleNdx), &sampleNdx);
   1478 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
   1479 	}
   1480 
   1481 	for (deUint32 splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++)
   1482 	{
   1483 		vkd.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
   1484 
   1485 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_splitPipelines[splitPipelineNdx]);
   1486 		vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_splitPipelineLayout, 0u, 1u,  &*m_splitDescriptorSet, 0u, DE_NULL);
   1487 		vkd.cmdPushConstants(*commandBuffer, *m_splitPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(splitPipelineNdx), &splitPipelineNdx);
   1488 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
   1489 	}
   1490 
   1491 	vkd.cmdEndRenderPass(*commandBuffer);
   1492 
   1493 	// Memory barriers between rendering and copies
   1494 	{
   1495 		std::vector<VkImageMemoryBarrier> barriers;
   1496 
   1497 		for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
   1498 		{
   1499 			const VkImageMemoryBarrier barrier =
   1500 			{
   1501 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
   1502 				DE_NULL,
   1503 
   1504 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
   1505 				VK_ACCESS_TRANSFER_READ_BIT,
   1506 
   1507 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1508 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1509 
   1510 				VK_QUEUE_FAMILY_IGNORED,
   1511 				VK_QUEUE_FAMILY_IGNORED,
   1512 
   1513 				**m_dstSinglesampleImages[dstNdx],
   1514 				{
   1515 					VK_IMAGE_ASPECT_COLOR_BIT,
   1516 					0u,
   1517 					1u,
   1518 					0u,
   1519 					1u
   1520 				}
   1521 			};
   1522 
   1523 			barriers.push_back(barrier);
   1524 		}
   1525 
   1526 		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]);
   1527 	}
   1528 
   1529 	// Copy image memory to buffers
   1530 	for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
   1531 	{
   1532 		const VkBufferImageCopy region =
   1533 		{
   1534 			0u,
   1535 			0u,
   1536 			0u,
   1537 			{
   1538 				VK_IMAGE_ASPECT_COLOR_BIT,
   1539 				0u,
   1540 				0u,
   1541 				1u,
   1542 			},
   1543 			{ 0u, 0u, 0u },
   1544 			{ m_width, m_height, 1u }
   1545 		};
   1546 
   1547 		vkd.cmdCopyImageToBuffer(*commandBuffer, **m_dstSinglesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_dstBuffers[dstNdx], 1u, &region);
   1548 	}
   1549 
   1550 	// Memory barriers between copies and host access
   1551 	{
   1552 		std::vector<VkBufferMemoryBarrier> barriers;
   1553 
   1554 		for (size_t dstNdx = 0; dstNdx < m_dstBuffers.size(); dstNdx++)
   1555 		{
   1556 			const VkBufferMemoryBarrier barrier =
   1557 			{
   1558 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
   1559 				DE_NULL,
   1560 
   1561 				VK_ACCESS_TRANSFER_WRITE_BIT,
   1562 				VK_ACCESS_HOST_READ_BIT,
   1563 
   1564 				VK_QUEUE_FAMILY_IGNORED,
   1565 				VK_QUEUE_FAMILY_IGNORED,
   1566 
   1567 				**m_dstBuffers[dstNdx],
   1568 				0u,
   1569 				VK_WHOLE_SIZE
   1570 			};
   1571 
   1572 			barriers.push_back(barrier);
   1573 		}
   1574 
   1575 		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);
   1576 	}
   1577 
   1578 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
   1579 
   1580 	{
   1581 		const VkSubmitInfo submitInfo =
   1582 		{
   1583 			VK_STRUCTURE_TYPE_SUBMIT_INFO,
   1584 			DE_NULL,
   1585 
   1586 			0u,
   1587 			DE_NULL,
   1588 			DE_NULL,
   1589 
   1590 			1u,
   1591 			&*commandBuffer,
   1592 
   1593 			0u,
   1594 			DE_NULL
   1595 		};
   1596 
   1597 		VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u));
   1598 
   1599 		VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue()));
   1600 	}
   1601 
   1602 	{
   1603 		const tcu::TextureFormat		format			(mapVkFormat(m_dstFormat));
   1604 		const tcu::TextureFormat		srcFormat		(mapVkFormat(m_srcFormat));
   1605 		const bool						hasDepth		(tcu::hasDepthComponent(srcFormat.order));
   1606 		const bool						hasStencil		(tcu::hasStencilComponent(srcFormat.order));
   1607 
   1608 		for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
   1609 		{
   1610 			const std::string					name		("Sample" + de::toString(sampleNdx));
   1611 			const void* const					ptr			(m_dstBufferMemory[sampleNdx]->getHostPtr());
   1612 			const tcu::ConstPixelBufferAccess	access		(format, m_width, m_height, 1, ptr);
   1613 			tcu::TextureLevel					reference	(format, m_width, m_height);
   1614 
   1615 			if (hasDepth || hasStencil)
   1616 			{
   1617 				if (hasDepth)
   1618 				{
   1619 					for (deUint32 y = 0; y < m_height; y++)
   1620 					for (deUint32 x = 0; x < m_width; x++)
   1621 					{
   1622 						const deUint32	x1				= x ^ sampleNdx;
   1623 						const deUint32	y1				= y ^ sampleNdx;
   1624 						const float		range			= 1.0f;
   1625 						float			depth			= 0.0f;
   1626 						deUint32		divider			= 2;
   1627 
   1628 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1629 						for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
   1630 						{
   1631 							depth += (range / (float)divider)
   1632 									* (((bitNdx % 2 == 0 ? x1 : y1) & (0x1u << (bitNdx / 2u))) == 0u ? 0u : 1u);
   1633 							divider *= 2;
   1634 						}
   1635 
   1636 						reference.getAccess().setPixel(Vec4(depth, 0.0f, 0.0f, 0.0f), x, y);
   1637 					}
   1638 				}
   1639 				if (hasStencil)
   1640 				{
   1641 					for (deUint32 y = 0; y < m_height; y++)
   1642 					for (deUint32 x = 0; x < m_width; x++)
   1643 					{
   1644 						const deUint32	stencil	= sampleNdx + 1u;
   1645 
   1646 						if (hasDepth)
   1647 						{
   1648 							const Vec4 src (reference.getAccess().getPixel(x, y));
   1649 
   1650 							reference.getAccess().setPixel(Vec4(src.x(), (float)stencil, 0.0f, 0.0f), x, y);
   1651 						}
   1652 						else
   1653 							reference.getAccess().setPixel(Vec4((float)stencil, 0.0f, 0.0f, 0.0f), x, y);
   1654 					}
   1655 				}
   1656 				{
   1657 					const Vec4 threshold (hasDepth ? (1.0f / 1024.0f) : 0.0f, 0.0f, 0.0f, 0.0f);
   1658 
   1659 					if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
   1660 						m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1661 				}
   1662 			}
   1663 			else
   1664 			{
   1665 				const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
   1666 
   1667 				switch (channelClass)
   1668 				{
   1669 					case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1670 					{
   1671 						const UVec4		bits			(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1672 						const UVec4		minValue		(0);
   1673 						const UVec4		range			(UVec4(1u) << tcu::min(bits, UVec4(31)));
   1674 						const int		componentCount	(tcu::getNumUsedChannels(format.order));
   1675 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   1676 
   1677 						for (deUint32 y = 0; y < m_height; y++)
   1678 						for (deUint32 x = 0; x < m_width; x++)
   1679 						{
   1680 							const deUint32	x1				= x ^ sampleNdx;
   1681 							const deUint32	y1				= y ^ sampleNdx;
   1682 							UVec4			color			(minValue);
   1683 							deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   1684 							deUint32		nextSrcBit		= 0;
   1685 							deUint32		divider			= 2;
   1686 
   1687 							// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1688 							while (nextSrcBit < de::min(bitSize, 10u))
   1689 							{
   1690 								for (int compNdx = 0; compNdx < componentCount; compNdx++)
   1691 								{
   1692 									if (dstBitsUsed[compNdx] > bits[compNdx])
   1693 										continue;
   1694 
   1695 									color[compNdx] += (range[compNdx] / divider)
   1696 													* (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
   1697 
   1698 									nextSrcBit++;
   1699 									dstBitsUsed[compNdx]++;
   1700 								}
   1701 
   1702 								divider *= 2;
   1703 							}
   1704 
   1705 							reference.getAccess().setPixel(color, x, y);
   1706 						}
   1707 
   1708 						if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
   1709 							m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1710 
   1711 						break;
   1712 					}
   1713 
   1714 					case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1715 					{
   1716 						const UVec4		bits			(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1717 						const IVec4		minValue		(0);
   1718 						const IVec4		range			((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
   1719 						const int		componentCount	(tcu::getNumUsedChannels(format.order));
   1720 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   1721 
   1722 						for (deUint32 y = 0; y < m_height; y++)
   1723 						for (deUint32 x = 0; x < m_width; x++)
   1724 						{
   1725 							const deUint32	x1				= x ^ sampleNdx;
   1726 							const deUint32	y1				= y ^ sampleNdx;
   1727 							IVec4			color			(minValue);
   1728 							deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   1729 							deUint32		nextSrcBit		= 0;
   1730 							deUint32		divider			= 2;
   1731 
   1732 							// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1733 							while (nextSrcBit < de::min(bitSize, 10u))
   1734 							{
   1735 								for (int compNdx = 0; compNdx < componentCount; compNdx++)
   1736 								{
   1737 									if (dstBitsUsed[compNdx] > bits[compNdx])
   1738 										continue;
   1739 
   1740 									color[compNdx] += (range[compNdx] / divider)
   1741 													* (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
   1742 
   1743 									nextSrcBit++;
   1744 									dstBitsUsed[compNdx]++;
   1745 								}
   1746 
   1747 								divider *= 2;
   1748 							}
   1749 
   1750 							reference.getAccess().setPixel(color, x, y);
   1751 						}
   1752 
   1753 						if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
   1754 							m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1755 
   1756 						break;
   1757 					}
   1758 
   1759 					case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1760 					case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1761 					case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1762 					{
   1763 						const tcu::TextureFormatInfo	info			(tcu::getTextureFormatInfo(format));
   1764 						const UVec4						bits			(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1765 						const Vec4						minLimit		(-65536.0);
   1766 						const Vec4						maxLimit		(65536.0);
   1767 						const Vec4						minValue		(tcu::max(info.valueMin, minLimit));
   1768 						const Vec4						range			(tcu::min(info.valueMax, maxLimit) - minValue);
   1769 						const int						componentCount	(tcu::getNumUsedChannels(format.order));
   1770 						const deUint32					bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   1771 
   1772 						for (deUint32 y = 0; y < m_height; y++)
   1773 						for (deUint32 x = 0; x < m_width; x++)
   1774 						{
   1775 							const deUint32	x1				= x ^ sampleNdx;
   1776 							const deUint32	y1				= y ^ sampleNdx;
   1777 							Vec4			color			(minValue);
   1778 							deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   1779 							deUint32		nextSrcBit		= 0;
   1780 							deUint32		divider			= 2;
   1781 
   1782 							// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1783 							while (nextSrcBit < de::min(bitSize, 10u))
   1784 							{
   1785 								for (int compNdx = 0; compNdx < componentCount; compNdx++)
   1786 								{
   1787 									if (dstBitsUsed[compNdx] > bits[compNdx])
   1788 										continue;
   1789 
   1790 									color[compNdx] += (range[compNdx] / (float)divider)
   1791 													* (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
   1792 
   1793 									nextSrcBit++;
   1794 									dstBitsUsed[compNdx]++;
   1795 								}
   1796 
   1797 								divider *= 2;
   1798 							}
   1799 
   1800 							if (tcu::isSRGB(format))
   1801 								reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
   1802 							else
   1803 								reference.getAccess().setPixel(color, x, y);
   1804 						}
   1805 
   1806 						if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
   1807 						{
   1808 							// Convert target format ulps to float ulps and allow 64ulp differences
   1809 							const UVec4 threshold (64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>())));
   1810 
   1811 							if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
   1812 								m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1813 						}
   1814 						else
   1815 						{
   1816 							// Allow error of 4 times the minimum presentable difference
   1817 							const Vec4 threshold (4.0f * 1.0f / ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()) - 1u).cast<float>());
   1818 
   1819 							if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
   1820 								m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
   1821 						}
   1822 
   1823 						break;
   1824 					}
   1825 
   1826 					default:
   1827 						DE_FATAL("Unknown channel class");
   1828 				}
   1829 			}
   1830 		}
   1831 	}
   1832 
   1833 	return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
   1834 }
   1835 
   1836 struct Programs
   1837 {
   1838 	void init (vk::SourceCollections& dst, TestConfig config) const
   1839 	{
   1840 		const tcu::TextureFormat		format			(mapVkFormat(config.format));
   1841 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
   1842 
   1843 		dst.glslSources.add("quad-vert") << glu::VertexSource(
   1844 			"#version 450\n"
   1845 			"out gl_PerVertex {\n"
   1846 			"\tvec4 gl_Position;\n"
   1847 			"};\n"
   1848 			"highp float;\n"
   1849 			"void main (void) {\n"
   1850 			"\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
   1851 			"\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
   1852 			"}\n");
   1853 
   1854 		if (tcu::hasDepthComponent(format.order))
   1855 		{
   1856 			const Vec4			minValue		(0.0f);
   1857 			const Vec4			range			(1.0f);
   1858 			std::ostringstream	fragmentShader;
   1859 
   1860 			fragmentShader <<
   1861 				"#version 450\n"
   1862 				"layout(push_constant) uniform PushConstant {\n"
   1863 				"\thighp uint sampleIndex;\n"
   1864 				"} pushConstants;\n"
   1865 				"void main (void)\n"
   1866 				"{\n"
   1867 				"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   1868 				"\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
   1869 				"\thighp float depth;\n"
   1870 				"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
   1871 				"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
   1872 
   1873 			fragmentShader << "\tdepth = "  << minValue[0] << ";\n";
   1874 
   1875 			{
   1876 				deUint32 divider = 2;
   1877 
   1878 				// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1879 				for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
   1880 				{
   1881 					fragmentShader <<
   1882 							"\tdepth += " << (range[0] / (float)divider)
   1883 							<< " * float(bitfieldExtract(" << (bitNdx % 2 == 0 ? "x" : "y") << ", " << (bitNdx / 2) << ", 1));\n";
   1884 
   1885 					divider *= 2;
   1886 				}
   1887 			}
   1888 
   1889 			fragmentShader <<
   1890 				"\tgl_FragDepth = depth;\n"
   1891 				"}\n";
   1892 
   1893 			dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
   1894 		}
   1895 		else if (tcu::hasStencilComponent(format.order))
   1896 		{
   1897 			dst.glslSources.add("quad-frag") << glu::FragmentSource(
   1898 				"#version 450\n"
   1899 				"layout(push_constant) uniform PushConstant {\n"
   1900 				"\thighp uint sampleIndex;\n"
   1901 				"} pushConstants;\n"
   1902 				"void main (void)\n"
   1903 				"{\n"
   1904 				"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   1905 				"\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
   1906 				"}\n");
   1907 		}
   1908 		else
   1909 		{
   1910 			switch (channelClass)
   1911 			{
   1912 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1913 				{
   1914 					const UVec4	bits		(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1915 					const UVec4 minValue	(0);
   1916 					const UVec4 range		(UVec4(1u) << tcu::min(bits, UVec4(31)));
   1917 					std::ostringstream		fragmentShader;
   1918 
   1919 					fragmentShader <<
   1920 						"#version 450\n"
   1921 						"layout(location = 0) out highp uvec4 o_color;\n"
   1922 						"layout(push_constant) uniform PushConstant {\n"
   1923 						"\thighp uint sampleIndex;\n"
   1924 						"} pushConstants;\n"
   1925 						"void main (void)\n"
   1926 						"{\n"
   1927 						"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   1928 						"\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
   1929 						"\thighp uint color[4];\n"
   1930 						"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
   1931 						"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
   1932 
   1933 					for (int ndx = 0; ndx < 4; ndx++)
   1934 						fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
   1935 
   1936 					{
   1937 						const int		componentCount	= tcu::getNumUsedChannels(format.order);
   1938 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   1939 						deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   1940 						deUint32		nextSrcBit		= 0;
   1941 						deUint32		divider			= 2;
   1942 
   1943 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   1944 						while (nextSrcBit < de::min(bitSize, 10u))
   1945 						{
   1946 							for (int compNdx = 0; compNdx < componentCount; compNdx++)
   1947 							{
   1948 								if (dstBitsUsed[compNdx] > bits[compNdx])
   1949 									continue;
   1950 
   1951 								fragmentShader <<
   1952 										"\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
   1953 										<< " * bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1);\n";
   1954 
   1955 								nextSrcBit++;
   1956 								dstBitsUsed[compNdx]++;
   1957 							}
   1958 
   1959 							divider *= 2;
   1960 						}
   1961 					}
   1962 
   1963 					fragmentShader <<
   1964 						"\to_color = uvec4(color[0], color[1], color[2], color[3]);\n"
   1965 						"}\n";
   1966 
   1967 					dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
   1968 					break;
   1969 				}
   1970 
   1971 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1972 				{
   1973 					const UVec4	bits		(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
   1974 					const IVec4 minValue	(0);
   1975 					const IVec4 range		((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
   1976 					std::ostringstream		fragmentShader;
   1977 
   1978 					fragmentShader <<
   1979 						"#version 450\n"
   1980 						"layout(location = 0) out highp ivec4 o_color;\n"
   1981 						"layout(push_constant) uniform PushConstant {\n"
   1982 						"\thighp uint sampleIndex;\n"
   1983 						"} pushConstants;\n"
   1984 						"void main (void)\n"
   1985 						"{\n"
   1986 						"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   1987 						"\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
   1988 						"\thighp int color[4];\n"
   1989 						"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
   1990 						"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
   1991 
   1992 					for (int ndx = 0; ndx < 4; ndx++)
   1993 						fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
   1994 
   1995 					{
   1996 						const int		componentCount	= tcu::getNumUsedChannels(format.order);
   1997 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   1998 						deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   1999 						deUint32		nextSrcBit		= 0;
   2000 						deUint32		divider			= 2;
   2001 
   2002 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   2003 						while (nextSrcBit < de::min(bitSize, 10u))
   2004 						{
   2005 							for (int compNdx = 0; compNdx < componentCount; compNdx++)
   2006 							{
   2007 								if (dstBitsUsed[compNdx] > bits[compNdx])
   2008 									continue;
   2009 
   2010 								fragmentShader <<
   2011 										"\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
   2012 										<< " * int(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
   2013 
   2014 								nextSrcBit++;
   2015 								dstBitsUsed[compNdx]++;
   2016 							}
   2017 
   2018 							divider *= 2;
   2019 						}
   2020 					}
   2021 
   2022 					fragmentShader <<
   2023 						"\to_color = ivec4(color[0], color[1], color[2], color[3]);\n"
   2024 						"}\n";
   2025 
   2026 					dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
   2027 					break;
   2028 				}
   2029 
   2030 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   2031 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   2032 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   2033 				{
   2034 					const tcu::TextureFormatInfo	info			(tcu::getTextureFormatInfo(format));
   2035 					const UVec4						bits			(tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>());
   2036 					const Vec4						minLimit		(-65536.0);
   2037 					const Vec4						maxLimit		(65536.0);
   2038 					const Vec4						minValue		(tcu::max(info.valueMin, minLimit));
   2039 					const Vec4						range			(tcu::min(info.valueMax, maxLimit) - minValue);
   2040 					std::ostringstream				fragmentShader;
   2041 
   2042 					fragmentShader <<
   2043 						"#version 450\n"
   2044 						"layout(location = 0) out highp vec4 o_color;\n"
   2045 						"layout(push_constant) uniform PushConstant {\n"
   2046 						"\thighp uint sampleIndex;\n"
   2047 						"} pushConstants;\n"
   2048 						"void main (void)\n"
   2049 						"{\n"
   2050 						"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
   2051 						"\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
   2052 						"\thighp float color[4];\n"
   2053 						"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
   2054 						"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
   2055 
   2056 					for (int ndx = 0; ndx < 4; ndx++)
   2057 						fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
   2058 
   2059 					{
   2060 						const int		componentCount	= tcu::getNumUsedChannels(format.order);
   2061 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
   2062 						deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
   2063 						deUint32		nextSrcBit		= 0;
   2064 						deUint32		divider			= 2;
   2065 
   2066 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
   2067 						while (nextSrcBit < de::min(bitSize, 10u))
   2068 						{
   2069 							for (int compNdx = 0; compNdx < componentCount; compNdx++)
   2070 							{
   2071 								if (dstBitsUsed[compNdx] > bits[compNdx])
   2072 									continue;
   2073 
   2074 								fragmentShader <<
   2075 										"\tcolor[" << compNdx << "] += " << (range[compNdx] / (float)divider)
   2076 										<< " * float(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
   2077 
   2078 								nextSrcBit++;
   2079 								dstBitsUsed[compNdx]++;
   2080 							}
   2081 
   2082 							divider *= 2;
   2083 						}
   2084 					}
   2085 
   2086 					fragmentShader <<
   2087 						"\to_color = vec4(color[0], color[1], color[2], color[3]);\n"
   2088 						"}\n";
   2089 
   2090 					dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
   2091 					break;
   2092 				}
   2093 
   2094 				default:
   2095 					DE_FATAL("Unknown channel class");
   2096 			}
   2097 		}
   2098 
   2099 		if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
   2100 		{
   2101 			std::ostringstream splitShader;
   2102 
   2103 			splitShader <<
   2104 				"#version 450\n";
   2105 
   2106 			if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
   2107 			{
   2108 				splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n"
   2109 							<< "layout(input_attachment_index = 0, set = 0, binding = 1) uniform highp usubpassInputMS i_stencil;\n";
   2110 			}
   2111 			else if (tcu::hasDepthComponent(format.order))
   2112 				splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n";
   2113 			else if (tcu::hasStencilComponent(format.order))
   2114 				splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp usubpassInputMS i_stencil;\n";
   2115 
   2116 			splitShader <<
   2117 				"layout(push_constant) uniform PushConstant {\n"
   2118 				"\thighp uint splitSubpassIndex;\n"
   2119 				"} pushConstants;\n";
   2120 
   2121 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
   2122 			{
   2123 				if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
   2124 					splitShader << "layout(location = " << attachmentNdx << ") out highp vec2 o_color" << attachmentNdx << ";\n";
   2125 				else
   2126 					splitShader << "layout(location = " << attachmentNdx << ") out highp float o_color" << attachmentNdx << ";\n";
   2127 			}
   2128 
   2129 			splitShader <<
   2130 				"void main (void)\n"
   2131 				"{\n";
   2132 
   2133 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
   2134 			{
   2135 				if (tcu::hasDepthComponent(format.order))
   2136 					splitShader << "\thighp float depth" << attachmentNdx << " = subpassLoad(i_depth, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
   2137 
   2138 				if (tcu::hasStencilComponent(format.order))
   2139 					splitShader << "\thighp uint stencil" << attachmentNdx << " = subpassLoad(i_stencil, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
   2140 
   2141 				if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
   2142 					splitShader << "\to_color" << attachmentNdx << " = vec2(depth" << attachmentNdx << ", float(stencil" << attachmentNdx << "));\n";
   2143 				else if (tcu::hasDepthComponent(format.order))
   2144 					splitShader << "\to_color" << attachmentNdx << " = float(depth" << attachmentNdx << ");\n";
   2145 				else if (tcu::hasStencilComponent(format.order))
   2146 					splitShader << "\to_color" << attachmentNdx << " = float(stencil" << attachmentNdx << ");\n";
   2147 			}
   2148 
   2149 			splitShader <<
   2150 				"}\n";
   2151 
   2152 			dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
   2153 		}
   2154 		else
   2155 		{
   2156 			std::string subpassType;
   2157 			std::string outputType;
   2158 
   2159 			switch (channelClass)
   2160 			{
   2161 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   2162 					subpassType	= "usubpassInputMS";
   2163 					outputType	= "uvec4";
   2164 					break;
   2165 
   2166 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   2167 					subpassType	= "isubpassInputMS";
   2168 					outputType	= "ivec4";
   2169 					break;
   2170 
   2171 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   2172 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   2173 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   2174 					subpassType	= "subpassInputMS";
   2175 					outputType	= "vec4";
   2176 					break;
   2177 
   2178 				default:
   2179 					DE_FATAL("Unknown channel class");
   2180 			}
   2181 
   2182 			std::ostringstream splitShader;
   2183 			splitShader <<
   2184 				"#version 450\n"
   2185 				"layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp " << subpassType << " i_color;\n"
   2186 				"layout(push_constant) uniform PushConstant {\n"
   2187 				"\thighp uint splitSubpassIndex;\n"
   2188 				"} pushConstants;\n";
   2189 
   2190 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
   2191 				splitShader << "layout(location = " << attachmentNdx << ") out highp " << outputType << " o_color" << attachmentNdx << ";\n";
   2192 
   2193 			splitShader <<
   2194 				"void main (void)\n"
   2195 				"{\n";
   2196 
   2197 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
   2198 				splitShader << "\to_color" << attachmentNdx << " = subpassLoad(i_color, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u));\n";
   2199 
   2200 			splitShader <<
   2201 				"}\n";
   2202 
   2203 			dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
   2204 		}
   2205 	}
   2206 };
   2207 
   2208 std::string formatToName (VkFormat format)
   2209 {
   2210 	const std::string	formatStr	= de::toString(format);
   2211 	const std::string	prefix		= "VK_FORMAT_";
   2212 
   2213 	DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
   2214 
   2215 	return de::toLower(formatStr.substr(prefix.length()));
   2216 }
   2217 
   2218 void initTests (tcu::TestCaseGroup* group)
   2219 {
   2220 	static const VkFormat	formats[]	=
   2221 	{
   2222 		VK_FORMAT_R5G6B5_UNORM_PACK16,
   2223 		VK_FORMAT_R8_UNORM,
   2224 		VK_FORMAT_R8_SNORM,
   2225 		VK_FORMAT_R8_UINT,
   2226 		VK_FORMAT_R8_SINT,
   2227 		VK_FORMAT_R8G8_UNORM,
   2228 		VK_FORMAT_R8G8_SNORM,
   2229 		VK_FORMAT_R8G8_UINT,
   2230 		VK_FORMAT_R8G8_SINT,
   2231 		VK_FORMAT_R8G8B8A8_UNORM,
   2232 		VK_FORMAT_R8G8B8A8_SNORM,
   2233 		VK_FORMAT_R8G8B8A8_UINT,
   2234 		VK_FORMAT_R8G8B8A8_SINT,
   2235 		VK_FORMAT_R8G8B8A8_SRGB,
   2236 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
   2237 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
   2238 		VK_FORMAT_A8B8G8R8_UINT_PACK32,
   2239 		VK_FORMAT_A8B8G8R8_SINT_PACK32,
   2240 		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
   2241 		VK_FORMAT_B8G8R8A8_UNORM,
   2242 		VK_FORMAT_B8G8R8A8_SRGB,
   2243 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
   2244 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
   2245 		VK_FORMAT_A2B10G10R10_UINT_PACK32,
   2246 		VK_FORMAT_R16_UNORM,
   2247 		VK_FORMAT_R16_SNORM,
   2248 		VK_FORMAT_R16_UINT,
   2249 		VK_FORMAT_R16_SINT,
   2250 		VK_FORMAT_R16_SFLOAT,
   2251 		VK_FORMAT_R16G16_UNORM,
   2252 		VK_FORMAT_R16G16_SNORM,
   2253 		VK_FORMAT_R16G16_UINT,
   2254 		VK_FORMAT_R16G16_SINT,
   2255 		VK_FORMAT_R16G16_SFLOAT,
   2256 		VK_FORMAT_R16G16B16A16_UNORM,
   2257 		VK_FORMAT_R16G16B16A16_SNORM,
   2258 		VK_FORMAT_R16G16B16A16_UINT,
   2259 		VK_FORMAT_R16G16B16A16_SINT,
   2260 		VK_FORMAT_R16G16B16A16_SFLOAT,
   2261 		VK_FORMAT_R32_UINT,
   2262 		VK_FORMAT_R32_SINT,
   2263 		VK_FORMAT_R32_SFLOAT,
   2264 		VK_FORMAT_R32G32_UINT,
   2265 		VK_FORMAT_R32G32_SINT,
   2266 		VK_FORMAT_R32G32_SFLOAT,
   2267 		VK_FORMAT_R32G32B32A32_UINT,
   2268 		VK_FORMAT_R32G32B32A32_SINT,
   2269 		VK_FORMAT_R32G32B32A32_SFLOAT,
   2270 
   2271 		VK_FORMAT_D16_UNORM,
   2272 		VK_FORMAT_X8_D24_UNORM_PACK32,
   2273 		VK_FORMAT_D32_SFLOAT,
   2274 		VK_FORMAT_S8_UINT,
   2275 		VK_FORMAT_D16_UNORM_S8_UINT,
   2276 		VK_FORMAT_D24_UNORM_S8_UINT,
   2277 		VK_FORMAT_D32_SFLOAT_S8_UINT
   2278 	};
   2279 	const deUint32			sampleCounts[] =
   2280 	{
   2281 		2u, 4u, 8u, 16u, 32u
   2282 	};
   2283 	tcu::TestContext&		testCtx		(group->getTestContext());
   2284 
   2285 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
   2286 	{
   2287 		const VkFormat					format		(formats[formatNdx]);
   2288 		const std::string				formatName	(formatToName(format));
   2289 		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
   2290 
   2291 		for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
   2292 		{
   2293 			const deUint32		sampleCount	(sampleCounts[sampleCountNdx]);
   2294 			const std::string	testName	("samples_" + de::toString(sampleCount));
   2295 
   2296 			formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount)));
   2297 		}
   2298 
   2299 		group->addChild(formatGroup.release());
   2300 	}
   2301 }
   2302 
   2303 } // anonymous
   2304 
   2305 tcu::TestCaseGroup* createRenderPassMultisampleTests (tcu::TestContext& testCtx)
   2306 {
   2307 	return createTestGroup(testCtx, "multisample", "Multisample render pass tests", initTests);
   2308 }
   2309 
   2310 } // vkt
   2311