Home | History | Annotate | Download | only in geometry
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2016 The Khronos Group Inc.
      6  * Copyright (c) 2014 The Android Open Source Project
      7  *
      8  * Licensed under the Apache License, Version 2.0 (the "License");
      9  * you may not use this file except in compliance with the License.
     10  * You may obtain a copy of the License at
     11  *
     12  *      http://www.apache.org/licenses/LICENSE-2.0
     13  *
     14  * Unless required by applicable law or agreed to in writing, software
     15  * distributed under the License is distributed on an "AS IS" BASIS,
     16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17  * See the License for the specific language governing permissions and
     18  * limitations under the License.
     19  *
     20  *//*!
     21  * \file
     22  * \brief Geometry shader layered rendering tests
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktGeometryLayeredRenderingTests.hpp"
     26 #include "vktTestCase.hpp"
     27 #include "vktTestCaseUtil.hpp"
     28 #include "vktGeometryTestsUtil.hpp"
     29 
     30 #include "vkPrograms.hpp"
     31 #include "vkStrUtil.hpp"
     32 #include "vkQueryUtil.hpp"
     33 #include "vkMemUtil.hpp"
     34 #include "vkRefUtil.hpp"
     35 #include "vkBarrierUtil.hpp"
     36 #include "vkTypeUtil.hpp"
     37 #include "vkImageUtil.hpp"
     38 #include "vkBuilderUtil.hpp"
     39 #include "vkCmdUtil.hpp"
     40 #include "vkObjUtil.hpp"
     41 
     42 #include "deStringUtil.hpp"
     43 #include "deUniquePtr.hpp"
     44 
     45 #include "tcuTextureUtil.hpp"
     46 #include "tcuVectorUtil.hpp"
     47 #include "tcuTestLog.hpp"
     48 
     49 namespace vkt
     50 {
     51 namespace geometry
     52 {
     53 namespace
     54 {
     55 using namespace vk;
     56 using de::MovePtr;
     57 using de::UniquePtr;
     58 using tcu::Vec4;
     59 using tcu::IVec3;
     60 
     61 enum TestType
     62 {
     63 	TEST_TYPE_DEFAULT_LAYER,					// !< draw to default layer
     64 	TEST_TYPE_SINGLE_LAYER,						// !< draw to single layer
     65 	TEST_TYPE_ALL_LAYERS,						// !< draw all layers
     66 	TEST_TYPE_DIFFERENT_CONTENT,				// !< draw different content to different layers
     67 	TEST_TYPE_LAYER_ID,							// !< draw to all layers, verify gl_Layer fragment input
     68 	TEST_TYPE_INVOCATION_PER_LAYER,				// !< draw to all layers, one invocation per layer
     69 	TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,	// !< draw to all layers, multiple invocations write to multiple layers
     70 	TEST_TYPE_LAYERED_READBACK,					// !< draw to two layers multiple times
     71 };
     72 
     73 struct ImageParams
     74 {
     75 	VkImageViewType		viewType;
     76 	VkExtent3D			size;
     77 	deUint32			numLayers;
     78 };
     79 
     80 struct TestParams
     81 {
     82 	TestType			testType;
     83 	ImageParams			image;
     84 };
     85 
     86 static const float s_colors[][4] =
     87 {
     88 	{ 1.0f, 1.0f, 1.0f, 1.0f },		// white
     89 	{ 1.0f, 0.0f, 0.0f, 1.0f },		// red
     90 	{ 0.0f, 1.0f, 0.0f, 1.0f },		// green
     91 	{ 0.0f, 0.0f, 1.0f, 1.0f },		// blue
     92 	{ 1.0f, 1.0f, 0.0f, 1.0f },		// yellow
     93 	{ 1.0f, 0.0f, 1.0f, 1.0f },		// magenta
     94 };
     95 
     96 tcu::Vec4 scaleColor(const tcu::Vec4& color, float factor)
     97 {
     98 	return tcu::Vec4(color[0] * factor,
     99 					 color[1] * factor,
    100 					 color[2] * factor,
    101 					 color[3]);
    102 }
    103 
    104 deUint32 getTargetLayer (const ImageParams& imageParams)
    105 {
    106 	if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
    107 		return imageParams.size.depth / 2;
    108 	else
    109 		return imageParams.numLayers / 2;
    110 }
    111 
    112 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
    113 {
    114 	std::string s(getImageViewTypeName(imageViewType));
    115 	return de::toLower(s.substr(19));
    116 }
    117 
    118 VkImageType getImageType (const VkImageViewType viewType)
    119 {
    120 	switch (viewType)
    121 	{
    122 		case VK_IMAGE_VIEW_TYPE_1D:
    123 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
    124 			return VK_IMAGE_TYPE_1D;
    125 
    126 		case VK_IMAGE_VIEW_TYPE_2D:
    127 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
    128 		case VK_IMAGE_VIEW_TYPE_CUBE:
    129 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
    130 			return VK_IMAGE_TYPE_2D;
    131 
    132 		case VK_IMAGE_VIEW_TYPE_3D:
    133 			return VK_IMAGE_TYPE_3D;
    134 
    135 		default:
    136 			DE_ASSERT(0);
    137 			return VK_IMAGE_TYPE_LAST;
    138 	}
    139 }
    140 
    141 VkFormat getStencilBufferFormat(VkFormat depthStencilImageFormat)
    142 {
    143 	const tcu::TextureFormat tcuFormat = mapVkFormat(depthStencilImageFormat);
    144 	const VkFormat result = (tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS) ? VK_FORMAT_S8_UINT : VK_FORMAT_UNDEFINED;
    145 
    146 	DE_ASSERT(result != VK_FORMAT_UNDEFINED);
    147 
    148 	return result;
    149 }
    150 
    151 inline bool isCubeImageViewType (const VkImageViewType viewType)
    152 {
    153 	return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
    154 }
    155 
    156 void checkImageFormatProperties (const InstanceInterface&	vki,
    157 								 const VkPhysicalDevice&	physDevice,
    158 								 const VkImageType&			imageType,
    159 								 const VkImageTiling&		imageTiling,
    160 								 const VkImageUsageFlags	imageUsageFlags,
    161 								 const VkImageCreateFlags	imageCreateFlags,
    162 								 const VkFormat				format,
    163 								 const VkExtent3D&			requiredSize,
    164 								 const deUint32				requiredLayers)
    165 {
    166 	VkImageFormatProperties	imageFormatProperties;
    167 	VkResult				result;
    168 
    169 	deMemset(&imageFormatProperties, 0, sizeof(imageFormatProperties));
    170 
    171 	result = vki.getPhysicalDeviceImageFormatProperties(physDevice, format, imageType, imageTiling, imageUsageFlags, imageCreateFlags, &imageFormatProperties);
    172 
    173 	if (result									!= VK_SUCCESS			||
    174 		imageFormatProperties.maxArrayLayers	<  requiredLayers		||
    175 		imageFormatProperties.maxExtent.height	<  requiredSize.height	||
    176 		imageFormatProperties.maxExtent.width	<  requiredSize.width	||
    177 		imageFormatProperties.maxExtent.depth	<  requiredSize.depth)
    178 	{
    179 		TCU_THROW(NotSupportedError, "Depth/stencil format is not supported");
    180 	}
    181 }
    182 
    183 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
    184 {
    185 	const VkImageCreateInfo imageParams =
    186 	{
    187 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
    188 		DE_NULL,										// const void*				pNext;
    189 		flags,											// VkImageCreateFlags		flags;
    190 		type,											// VkImageType				imageType;
    191 		format,											// VkFormat					format;
    192 		size,											// VkExtent3D				extent;
    193 		1u,												// deUint32					mipLevels;
    194 		numLayers,										// deUint32					arrayLayers;
    195 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
    196 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
    197 		usage,											// VkImageUsageFlags		usage;
    198 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
    199 		0u,												// deUint32					queueFamilyIndexCount;
    200 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
    201 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
    202 	};
    203 	return imageParams;
    204 }
    205 
    206 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
    207 								   const VkDevice			device,
    208 								   const VkFormat			colorFormat,
    209 								   const VkFormat			dsFormat,
    210 								   const bool				useDepthStencil)
    211 {
    212 	return vk::makeRenderPass(vk, device, colorFormat, useDepthStencil ? dsFormat : VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
    213 }
    214 
    215 
    216 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
    217 									   const VkDevice				device,
    218 									   const VkPipelineLayout		pipelineLayout,
    219 									   const VkRenderPass			renderPass,
    220 									   const VkShaderModule			vertexModule,
    221 									   const VkShaderModule			geometryModule,
    222 									   const VkShaderModule			fragmentModule,
    223 									   const VkExtent2D				renderSize,
    224 									   const bool					useDepthStencil = false)
    225 {
    226 	const std::vector<VkViewport>			viewports						(1, makeViewport(renderSize));
    227 	const std::vector<VkRect2D>				scissors						(1, makeRect2D(renderSize));
    228 
    229 	const VkStencilOpState					stencilOpState					= makeStencilOpState(
    230 		VK_STENCIL_OP_KEEP,					// stencil fail
    231 		VK_STENCIL_OP_INCREMENT_AND_CLAMP,	// depth & stencil pass
    232 		VK_STENCIL_OP_KEEP,					// depth only fail
    233 		VK_COMPARE_OP_ALWAYS,				// compare op
    234 		~0u,								// compare mask
    235 		~0u,								// write mask
    236 		0u);								// reference
    237 
    238 	VkPipelineDepthStencilStateCreateInfo	pipelineDepthStencilStateInfo	=
    239 	{
    240 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType                           sType;
    241 		DE_NULL,													// const void*                               pNext;
    242 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags    flags;
    243 		useDepthStencil ? VK_TRUE : VK_FALSE,						// VkBool32                                  depthTestEnable;
    244 		useDepthStencil ? VK_TRUE : VK_FALSE,						// VkBool32                                  depthWriteEnable;
    245 		VK_COMPARE_OP_LESS,											// VkCompareOp                               depthCompareOp;
    246 		VK_FALSE,													// VkBool32                                  depthBoundsTestEnable;
    247 		useDepthStencil ? VK_TRUE : VK_FALSE,						// VkBool32                                  stencilTestEnable;
    248 		stencilOpState,												// VkStencilOpState                          front;
    249 		stencilOpState,												// VkStencilOpState                          back;
    250 		0.0f,														// float                                     minDepthBounds;
    251 		1.0f														// float                                     maxDepthBounds;
    252 	};
    253 
    254 	return vk::makeGraphicsPipeline(vk,									// const DeviceInterface&                        vk
    255 									device,								// const VkDevice                                device
    256 									pipelineLayout,						// const VkPipelineLayout                        pipelineLayout
    257 									vertexModule,						// const VkShaderModule                          vertexShaderModule
    258 									DE_NULL,							// const VkShaderModule                          tessellationControlModule
    259 									DE_NULL,							// const VkShaderModule                          tessellationEvalModule
    260 									geometryModule,						// const VkShaderModule                          geometryShaderModule
    261 									fragmentModule,						// const VkShaderModule                          fragmentShaderModule
    262 									renderPass,							// const VkRenderPass                            renderPass
    263 									viewports,							// const std::vector<VkViewport>&                viewports
    264 									scissors,							// const std::vector<VkRect2D>&                  scissors
    265 									VK_PRIMITIVE_TOPOLOGY_POINT_LIST,	// const VkPrimitiveTopology                     topology
    266 									0u,									// const deUint32                                subpass
    267 									0u,									// const deUint32                                patchControlPoints
    268 									DE_NULL,							// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
    269 									DE_NULL,							// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
    270 									DE_NULL,							// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
    271 									&pipelineDepthStencilStateInfo);	// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
    272 }
    273 
    274 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&	vk,
    275 									 const VkDevice			device,
    276 									 const VkRenderPass		renderPass,
    277 									 const VkImageView*		pAttachments,
    278 									 const deUint32			attachmentsCount,
    279 									 const deUint32			width,
    280 									 const deUint32			height,
    281 									 const deUint32			layers)
    282 {
    283 	const VkFramebufferCreateInfo framebufferInfo = {
    284 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
    285 		DE_NULL,										// const void*                                 pNext;
    286 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
    287 		renderPass,										// VkRenderPass                                renderPass;
    288 		attachmentsCount,								// uint32_t                                    attachmentCount;
    289 		pAttachments,									// const VkImageView*                          pAttachments;
    290 		width,											// uint32_t                                    width;
    291 		height,											// uint32_t                                    height;
    292 		layers,											// uint32_t                                    layers;
    293 	};
    294 
    295 	return createFramebuffer(vk, device, &framebufferInfo);
    296 }
    297 
    298 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
    299 class LayeredImageAccess
    300 {
    301 public:
    302 	static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
    303 	{
    304 		if (type == VK_IMAGE_TYPE_1D)
    305 			return LayeredImageAccess(format, size.width, numLayers, pData);
    306 		else
    307 			return LayeredImageAccess(type, format, size, numLayers, pData);
    308 	}
    309 
    310 	inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
    311 	{
    312 		return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
    313 	}
    314 
    315 	inline int getNumLayersOrSlices (void) const
    316 	{
    317 		return m_layers;
    318 	}
    319 
    320 private:
    321 	// Specialized for 1D images.
    322 	LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
    323 		: m_width		(static_cast<int>(width))
    324 		, m_height		(1)
    325 		, m_1dModifier	(1)
    326 		, m_layers		(numLayers)
    327 		, m_wholeImage	(tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
    328 	{
    329 	}
    330 
    331 	LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
    332 		: m_width		(static_cast<int>(size.width))
    333 		, m_height		(static_cast<int>(size.height))
    334 		, m_1dModifier	(0)
    335 		, m_layers		(static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
    336 		, m_wholeImage	(tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
    337 	{
    338 	}
    339 
    340 	const int							m_width;
    341 	const int							m_height;
    342 	const int							m_1dModifier;
    343 	const int							m_layers;
    344 	const tcu::ConstPixelBufferAccess	m_wholeImage;
    345 };
    346 
    347 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
    348 {
    349 	return tcu::allEqual(
    350 				tcu::lessThan(tcu::abs(colorA - colorB), threshold),
    351 				tcu::BVec4(true, true, true, true));
    352 }
    353 
    354 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor)
    355 {
    356 	DE_ASSERT(rowWidthRatio > 0.0f);
    357 
    358 	const Vec4				black				(0.0f, 0.0f, 0.0f, 1.0f);
    359 	const Vec4				green				(0.0f, 1.0f, 0.0f, 1.0f);
    360 	const Vec4				red					(1.0f, 0.0f, 0.0f, 1.0f);
    361 	const Vec4				threshold			(0.02f);
    362 	const int				barLength			= static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
    363 	const int				barLengthThreshold	= 1;
    364 	tcu::TextureLevel		errorMask			(image.getFormat(), image.getWidth(), image.getHeight());
    365 	tcu::PixelBufferAccess	errorMaskAccess		= errorMask.getAccess();
    366 
    367 	tcu::clear(errorMask.getAccess(), green);
    368 
    369 	log << tcu::TestLog::Message
    370 		<< "Expecting all pixels with distance less or equal to (about) " << barLength
    371 		<< " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
    372 		<< tcu::TestLog::EndMessage;
    373 
    374 	bool allPixelsOk = true;
    375 
    376 	for (int y = 0; y < image.getHeight(); ++y)
    377 	for (int x = 0; x < image.getWidth();  ++x)
    378 	{
    379 		const Vec4	color		= image.getPixel(x, y);
    380 		const bool	isBlack		= compareColors(color, black, threshold);
    381 		const bool	isColor		= compareColors(color, barColor, threshold);
    382 
    383 		bool isOk;
    384 
    385 		if (x <= barLength - barLengthThreshold)
    386 			isOk = isColor;
    387 		else if (x >= barLength + barLengthThreshold)
    388 			isOk = isBlack;
    389 		else
    390 			isOk = isColor || isBlack;
    391 
    392 		allPixelsOk &= isOk;
    393 
    394 		if (!isOk)
    395 			errorMaskAccess.setPixel(red, x, y);
    396 	}
    397 
    398 	if (allPixelsOk)
    399 	{
    400 		log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
    401 			<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
    402 			<< tcu::TestLog::Image("Layer", "Layer", image)
    403 			<< tcu::TestLog::EndImageSet;
    404 		return true;
    405 	}
    406 	else
    407 	{
    408 		log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
    409 			<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
    410 			<< tcu::TestLog::Image("Layer",		"Layer",	image)
    411 			<< tcu::TestLog::Image("ErrorMask",	"Errors",	errorMask)
    412 			<< tcu::TestLog::EndImageSet;
    413 		return false;
    414 	}
    415 
    416 	log << tcu::TestLog::Image("LayerContent", "Layer content", image);
    417 
    418 	return allPixelsOk;
    419 }
    420 
    421 static bool verifyImageMultipleBars (tcu::TestLog&						log,
    422 									 const tcu::ConstPixelBufferAccess	image,
    423 									 const float*						barWidthRatios,
    424 									 const tcu::Vec4*					barValues,
    425 									 const int							barsCount,
    426 									 const int							numUsedChannels,
    427 									 const std::string&					imageTypeName)
    428 {
    429 	const Vec4					green				(0.0f, 1.0f, 0.0f, 1.0f);
    430 	const Vec4					red					(1.0f, 0.0f, 0.0f, 1.0f);
    431 	const Vec4					threshold			(0.02f);
    432 	const tcu::TextureFormat	errorMaskFormat		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8));
    433 	tcu::TextureLevel			errorMask			(errorMaskFormat, image.getWidth(), image.getHeight());
    434 	tcu::PixelBufferAccess		errorMaskAccess		= errorMask.getAccess();
    435 	bool						allPixelsOk			= true;
    436 
    437 	DE_ASSERT(barsCount > 0);
    438 
    439 	tcu::clear(errorMask.getAccess(), green);
    440 
    441 	// Format information message
    442 	{
    443 		int					leftBorder	= 0;
    444 		int					rightBorder	= 0;
    445 		std::ostringstream	str;
    446 
    447 		for (int barNdx = 0; barNdx < barsCount; ++barNdx)
    448 		{
    449 			leftBorder	= rightBorder;
    450 			rightBorder	= static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
    451 
    452 			DE_ASSERT(leftBorder < rightBorder);
    453 
    454 			str << std::endl << " [" << leftBorder << "," <<rightBorder << "): ";
    455 
    456 			switch (numUsedChannels)
    457 			{
    458 				case 1:	str << barValues[barNdx][0];	break;
    459 				case 4:	str << barValues[barNdx];		break;
    460 				default: DE_ASSERT(false);				break;
    461 			}
    462 		}
    463 
    464 		log << tcu::TestLog::Message
    465 			<< "Expecting " + imageTypeName + " values depending x-axis position to be of following values: "
    466 			<< str.str()
    467 			<< tcu::TestLog::EndMessage;
    468 	}
    469 
    470 	for (int x = 0; x < image.getWidth();  ++x)
    471 	{
    472 		tcu::Vec4	expectedValue	= barValues[0];
    473 
    474 		for (int barNdx = 0; barNdx < barsCount; ++barNdx)
    475 		{
    476 			const int rightBorder	= static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
    477 
    478 			if (x < rightBorder)
    479 			{
    480 				expectedValue = barValues[barNdx];
    481 
    482 				break;
    483 			}
    484 		}
    485 
    486 		for (int y = 0; y < image.getHeight(); ++y)
    487 		{
    488 			const tcu::Vec4	realValue	= image.getPixel(x, y);
    489 			bool			isOk		= false;
    490 
    491 			switch (numUsedChannels)
    492 			{
    493 				case 1:	isOk = fabs(realValue[0] - expectedValue[0]) < threshold[0];	break;
    494 				case 4:	isOk = compareColors(realValue, expectedValue, threshold);		break;
    495 				default: DE_ASSERT(false);												break;
    496 			}
    497 
    498 			if (!isOk)
    499 				errorMaskAccess.setPixel(red, x, y);
    500 
    501 			allPixelsOk = allPixelsOk && isOk;
    502 		}
    503 	}
    504 
    505 	if (allPixelsOk)
    506 	{
    507 		log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
    508 			<< tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
    509 			<< tcu::TestLog::Image("Layer", "Layer", image)
    510 			<< tcu::TestLog::EndImageSet;
    511 	}
    512 	else
    513 	{
    514 		log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
    515 			<< tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
    516 			<< tcu::TestLog::Image("Layer",		"Layer",	image)
    517 			<< tcu::TestLog::Image("ErrorMask",	"Errors",	errorMask)
    518 			<< tcu::TestLog::EndImageSet;
    519 	}
    520 
    521 	return allPixelsOk;
    522 }
    523 
    524 static void convertDepthToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage)
    525 {
    526 	for (int y = 0; y < inputImage.getHeight(); y++)
    527 	for (int x = 0; x < inputImage.getWidth(); x++)
    528 	{
    529 		const float		depth	= inputImage.getPixDepth(x, y);
    530 		const tcu::Vec4	color	= tcu::Vec4(depth, depth, depth, 1.0f);
    531 
    532 		outputImage.setPixel(color, x, y);
    533 	}
    534 }
    535 
    536 static void convertStencilToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage, int maxValue)
    537 {
    538 	for (int y = 0; y < inputImage.getHeight(); y++)
    539 	for (int x = 0; x < inputImage.getWidth(); x++)
    540 	{
    541 		const int		stencilInt	= inputImage.getPixStencil(x, y);
    542 		const float		stencil		= (stencilInt < maxValue) ? float(stencilInt) / float(maxValue) : 1.0f;
    543 		const tcu::Vec4	color		= tcu::Vec4(stencil, stencil, stencil, 1.0f);
    544 
    545 		outputImage.setPixel(color, x, y);
    546 	}
    547 }
    548 
    549 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
    550 {
    551 	log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
    552 
    553 	const Vec4	black		(0.0f, 0.0f, 0.0f, 1.0f);
    554 	const Vec4	threshold	(0.02f);
    555 
    556 	for (int y = 0; y < image.getHeight(); ++y)
    557 	for (int x = 0; x < image.getWidth();  ++x)
    558 	{
    559 		const Vec4 color = image.getPixel(x, y);
    560 
    561 		if (!compareColors(color, black, threshold))
    562 		{
    563 			log	<< tcu::TestLog::Message
    564 				<< "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
    565 				<< tcu::TestLog::EndMessage
    566 				<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
    567 				<< tcu::TestLog::Image("Layer", "Layer", image)
    568 				<< tcu::TestLog::EndImageSet;
    569 			return false;
    570 		}
    571 	}
    572 
    573 	log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
    574 
    575 	return true;
    576 }
    577 
    578 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers, const bool depthCheck, const bool stencilCheck)
    579 {
    580 	const Vec4	white				(1.0f, 1.0f, 1.0f, 1.0f);
    581 	const int	targetLayer			= numLayers / 2;
    582 	const float	variableBarRatio	= static_cast<float>(layerNdx) / static_cast<float>(numLayers);
    583 
    584 	switch (testType)
    585 	{
    586 		case TEST_TYPE_DEFAULT_LAYER:
    587 			if (layerNdx == 0)
    588 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
    589 			else
    590 				return verifyEmptyImage(log, image);
    591 
    592 		case TEST_TYPE_SINGLE_LAYER:
    593 			if (layerNdx == targetLayer)
    594 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
    595 			else
    596 				return verifyEmptyImage(log, image);
    597 
    598 		case TEST_TYPE_ALL_LAYERS:
    599 		case TEST_TYPE_INVOCATION_PER_LAYER:
    600 			return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
    601 
    602 		case TEST_TYPE_DIFFERENT_CONTENT:
    603 		case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
    604 			if (layerNdx == 0)
    605 				return verifyEmptyImage(log, image);
    606 			else
    607 				return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
    608 
    609 		case TEST_TYPE_LAYER_ID:
    610 		{
    611 			// This code must be in sync with the fragment shader.
    612 			const tcu::Vec4 layerColor( (layerNdx    % 2) == 1 ? 1.0f : 0.5f,
    613 									   ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
    614 									     layerNdx         == 0 ? 1.0f : 0.0f,
    615 																 1.0f);
    616 			return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
    617 		}
    618 
    619 		case TEST_TYPE_LAYERED_READBACK:
    620 		{
    621 			const float	barWidthRatios[]	= { 0.25f, 0.5f, 1.0f };
    622 			const int	barsCount			= DE_LENGTH_OF_ARRAY(barWidthRatios);
    623 			bool		result				= false;
    624 
    625 			if (depthCheck)
    626 			{
    627 				const std::string		checkType				= "Depth";
    628 				const float				pass0depth				= static_cast<float>(layerNdx + 1) / static_cast<float>(2 * numLayers);
    629 				const float				pass1depth				= static_cast<float>(layerNdx + 0) / static_cast<float>(2 * numLayers);
    630 				const tcu::Vec4			barDepths[barsCount]	= { tcu::Vec4(pass1depth), tcu::Vec4(pass0depth), tcu::Vec4(1.0f) };
    631 				tcu::TextureLevel		depthAsColorBuffer		(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
    632 				tcu::PixelBufferAccess	depthAsColor			(depthAsColorBuffer);
    633 				const int				numUsedChannels			(tcu::getNumUsedChannels(depthAsColor.getFormat().order));
    634 
    635 				convertDepthToColorBufferAccess(image, depthAsColor);
    636 
    637 				result = verifyImageMultipleBars(log, depthAsColor, barWidthRatios, barDepths, barsCount, numUsedChannels, checkType);
    638 			}
    639 			else if (stencilCheck)
    640 			{
    641 				const std::string		checkType				= "Stencil";
    642 				const int				maxStencilValue			= 4;
    643 				const float				pass0stencil			= static_cast<float>(1.0f / maxStencilValue);
    644 				const float				pass1stencil			= static_cast<float>(2.0f / maxStencilValue);
    645 				const tcu::Vec4			barStencils[barsCount]	= { tcu::Vec4(pass1stencil), tcu::Vec4(pass0stencil), tcu::Vec4(0.0f) };
    646 				tcu::TextureLevel		stencilAsColorBuffer	(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
    647 				tcu::PixelBufferAccess	stencilAsColor			(stencilAsColorBuffer);
    648 				const int				numUsedChannels			(tcu::getNumUsedChannels(stencilAsColor.getFormat().order));
    649 
    650 				convertStencilToColorBufferAccess(image, stencilAsColor, maxStencilValue);
    651 
    652 				result = verifyImageMultipleBars(log, stencilAsColor, barWidthRatios, barStencils, barsCount, numUsedChannels, checkType);
    653 			}
    654 			else
    655 			{
    656 				const std::string		checkType				= "Color";
    657 				const tcu::Vec4			baseColor				(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
    658 				const tcu::Vec4			barColors[barsCount]	= { scaleColor(baseColor, 1.00f), scaleColor(baseColor, 0.50f), scaleColor(baseColor, 0.25f) };
    659 				const int				numUsedChannels			(tcu::getNumUsedChannels(image.getFormat().order));
    660 
    661 				result = verifyImageMultipleBars(log, image, barWidthRatios, barColors, barsCount, numUsedChannels, checkType);
    662 			}
    663 
    664 			return result;
    665 		}
    666 
    667 		default:
    668 			DE_ASSERT(0);
    669 			return false;
    670 	};
    671 }
    672 
    673 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
    674 {
    675 	std::ostringstream str;
    676 	const int numCubeFaces = 6;
    677 
    678 	if (isCubeImageViewType(viewType))
    679 		str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
    680 	else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
    681 		str << "slice z = " << layer;
    682 	else
    683 		str << "layer " << layer;
    684 
    685 	return str.str();
    686 }
    687 
    688 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat imageFormat, const void* resultData, const bool depthCheck = false, const bool stencilCheck = false)
    689 {
    690 	const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), imageFormat, params.image.size, params.image.numLayers, resultData);
    691 
    692 	int numGoodLayers = 0;
    693 
    694 	for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
    695 	{
    696 		const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
    697 
    698 		log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
    699 
    700 		if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices(), depthCheck, stencilCheck))
    701 			++numGoodLayers;
    702 	}
    703 
    704 	return numGoodLayers == image.getNumLayersOrSlices();
    705 }
    706 
    707 std::string toGlsl (const Vec4& v)
    708 {
    709 	std::ostringstream str;
    710 	str << "vec4(";
    711 	for (int i = 0; i < 4; ++i)
    712 		str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
    713 	str << ")";
    714 	return str.str();
    715 }
    716 
    717 void initPrograms (SourceCollections& programCollection, const TestParams params)
    718 {
    719 	const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_LAYERED_READBACK);
    720 
    721 	// Vertex shader
    722 	{
    723 		std::ostringstream src;
    724 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    725 			<< "\n"
    726 			<< "void main(void)\n"
    727 			<< "{\n"
    728 			<< "}\n";
    729 
    730 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
    731 	}
    732 
    733 	// Geometry shader
    734 	{
    735 		const int numLayers		= static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
    736 
    737 		const int maxVertices	= (params.testType == TEST_TYPE_DIFFERENT_CONTENT)																						? (numLayers + 1) * numLayers :
    738 								  (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID || params.testType == TEST_TYPE_LAYERED_READBACK)	? numLayers * 4 :
    739 								  (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)																			? 6 : 4;
    740 
    741 		std::ostringstream src;
    742 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    743 			<< "\n";
    744 
    745 		if (params.testType == TEST_TYPE_LAYERED_READBACK)
    746 			src << "layout(binding = 0) readonly uniform Input {\n"
    747 				<< "    int pass;\n"
    748 				<< "} uInput;\n\n";
    749 
    750 		if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
    751 			src << "layout(points, invocations = " << numLayers << ") in;\n";
    752 		else
    753 			src << "layout(points) in;\n";
    754 
    755 		src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
    756 			<< "\n"
    757 			<< (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
    758 			<< "out gl_PerVertex {\n"
    759 			<< "    vec4 gl_Position;\n"
    760 			<< "};\n"
    761 			<< "\n"
    762 			<< "void main(void)\n"
    763 			<< "{\n";
    764 
    765 		std::ostringstream colorTable;
    766 		{
    767 			const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
    768 
    769 			colorTable << "    const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
    770 
    771 			const std::string padding(colorTable.str().length(), ' ');
    772 
    773 			for (int i = 0; i < numColors; ++i)
    774 				colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
    775 
    776 			colorTable << ");\n";
    777 		}
    778 
    779 		if (params.testType == TEST_TYPE_DEFAULT_LAYER)
    780 		{
    781 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
    782 				<< "    EmitVertex();\n"
    783 				<< "\n"
    784 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
    785 				<< "    EmitVertex();\n"
    786 				<< "\n"
    787 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
    788 				<< "    EmitVertex();\n"
    789 				<< "\n"
    790 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
    791 				<< "    EmitVertex();\n";
    792 		}
    793 		else if (params.testType == TEST_TYPE_SINGLE_LAYER)
    794 		{
    795 			const deUint32 targetLayer = getTargetLayer(params.image);
    796 
    797 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
    798 				<< "    gl_Layer    = " << targetLayer << ";\n"
    799 				<< "    EmitVertex();\n"
    800 				<< "\n"
    801 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
    802 				<< "    gl_Layer    = " << targetLayer << ";\n"
    803 				<< "    EmitVertex();\n"
    804 				<< "\n"
    805 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
    806 				<< "    gl_Layer    = " << targetLayer << ";\n"
    807 				<< "    EmitVertex();\n"
    808 				<< "\n"
    809 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
    810 				<< "    gl_Layer    = " << targetLayer << ";\n"
    811 				<< "    EmitVertex();\n";
    812 		}
    813 		else if (params.testType == TEST_TYPE_ALL_LAYERS)
    814 		{
    815 			src << colorTable.str()
    816 				<< "\n"
    817 				<< "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
    818 				<< "        const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
    819 				<< "\n"
    820 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
    821 				<< "        gl_Layer    = layerNdx;\n"
    822 				<< "        vert_color  = colors[colorNdx];\n"
    823 				<< "        EmitVertex();\n"
    824 				<< "\n"
    825 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
    826 				<< "        gl_Layer    = layerNdx;\n"
    827 				<< "        vert_color  = colors[colorNdx];\n"
    828 				<< "        EmitVertex();\n"
    829 				<< "\n"
    830 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
    831 				<< "        gl_Layer    = layerNdx;\n"
    832 				<< "        vert_color  = colors[colorNdx];\n"
    833 				<< "        EmitVertex();\n"
    834 				<< "\n"
    835 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
    836 				<< "        gl_Layer    = layerNdx;\n"
    837 				<< "        vert_color  = colors[colorNdx];\n"
    838 				<< "        EmitVertex();\n"
    839 				<< "        EndPrimitive();\n"
    840 				<< "    };\n";
    841 		}
    842 		else if (params.testType == TEST_TYPE_LAYER_ID)
    843 		{
    844 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
    845 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
    846 				<< "        gl_Layer    = layerNdx;\n"
    847 				<< "        EmitVertex();\n"
    848 				<< "\n"
    849 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
    850 				<< "        gl_Layer    = layerNdx;\n"
    851 				<< "        EmitVertex();\n"
    852 				<< "\n"
    853 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
    854 				<< "        gl_Layer    = layerNdx;\n"
    855 				<< "        EmitVertex();\n"
    856 				<< "\n"
    857 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
    858 				<< "        gl_Layer    = layerNdx;\n"
    859 				<< "        EmitVertex();\n"
    860 				<< "        EndPrimitive();\n"
    861 				<< "    };\n";
    862 		}
    863 		else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
    864 		{
    865 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
    866 				<< "        for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
    867 				<< "            const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
    868 				<< "\n"
    869 				<< "            gl_Position = vec4(posX,  1.0, 0.0, 1.0);\n"
    870 				<< "            gl_Layer    = layerNdx;\n"
    871 				<< "            EmitVertex();\n"
    872 				<< "\n"
    873 				<< "            gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
    874 				<< "            gl_Layer    = layerNdx;\n"
    875 				<< "            EmitVertex();\n"
    876 				<< "        }\n"
    877 				<< "        EndPrimitive();\n"
    878 				<< "    }\n";
    879 		}
    880 		else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
    881 		{
    882 			src << colorTable.str()
    883 				<< "    const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
    884 				<< "\n"
    885 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
    886 				<< "    gl_Layer    = gl_InvocationID;\n"
    887 				<< "    vert_color  = colors[colorNdx];\n"
    888 				<< "    EmitVertex();\n"
    889 				<< "\n"
    890 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
    891 				<< "    gl_Layer    = gl_InvocationID;\n"
    892 				<< "    vert_color  = colors[colorNdx];\n"
    893 				<< "    EmitVertex();\n"
    894 				<< "\n"
    895 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
    896 				<< "    gl_Layer    = gl_InvocationID;\n"
    897 				<< "    vert_color  = colors[colorNdx];\n"
    898 				<< "    EmitVertex();\n"
    899 				<< "\n"
    900 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
    901 				<< "    gl_Layer    = gl_InvocationID;\n"
    902 				<< "    vert_color  = colors[colorNdx];\n"
    903 				<< "    EmitVertex();\n"
    904 				<< "    EndPrimitive();\n";
    905 		}
    906 		else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
    907 		{
    908 			src << "    const int   layerA = gl_InvocationID;\n"
    909 				<< "    const int   layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
    910 				<< "    const float aEnd   = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
    911 				<< "    const float bEnd   = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
    912 				<< "\n"
    913 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
    914 				<< "    gl_Layer    = layerA;\n"
    915 				<< "    EmitVertex();\n"
    916 				<< "\n"
    917 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
    918 				<< "    gl_Layer    = layerA;\n"
    919 				<< "    EmitVertex();\n"
    920 				<< "\n"
    921 				<< "    gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
    922 				<< "    gl_Layer    = layerA;\n"
    923 				<< "    EmitVertex();\n"
    924 				<< "    EndPrimitive();\n"
    925 				<< "\n"
    926 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
    927 				<< "    gl_Layer    = layerB;\n"
    928 				<< "    EmitVertex();\n"
    929 				<< "\n"
    930 				<< "    gl_Position = vec4(bEnd,  1.0, 0.0, 1.0);\n"
    931 				<< "    gl_Layer    = layerB;\n"
    932 				<< "    EmitVertex();\n"
    933 				<< "\n"
    934 				<< "    gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
    935 				<< "    gl_Layer    = layerB;\n"
    936 				<< "    EmitVertex();\n"
    937 				<< "    EndPrimitive();\n";
    938 		}
    939 		else if (params.testType == TEST_TYPE_LAYERED_READBACK)
    940 		{
    941 			src << colorTable.str()
    942 				<< "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
    943 				<< "        const int   colorNdx   = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
    944 				<< "        const vec3  passColor0 = (uInput.pass == 0 ? 0.5 :  1.0) * vec3(colors[colorNdx]);\n"
    945 				<< "        const vec4  passColor  = vec4(passColor0, 1.0);\n"
    946 				<< "        const float posX       = (uInput.pass == 0 ? 0.0 : -0.5);\n"
    947 				<< "        const float posZ       = float(layerNdx + 1 - uInput.pass) / float(" << 2*numLayers << ");\n"
    948 				<< "\n"
    949 				<< "        gl_Position = vec4(-1.0, -1.0, posZ, 1.0);\n"
    950 				<< "        gl_Layer    = layerNdx;\n"
    951 				<< "        vert_color  = passColor;\n"
    952 				<< "        EmitVertex();\n"
    953 				<< "\n"
    954 				<< "        gl_Position = vec4(-1.0,  1.0, posZ, 1.0);\n"
    955 				<< "        gl_Layer    = layerNdx;\n"
    956 				<< "        vert_color  = passColor;\n"
    957 				<< "        EmitVertex();\n"
    958 				<< "\n"
    959 				<< "        gl_Position = vec4(posX, -1.0, posZ, 1.0);\n"
    960 				<< "        gl_Layer    = layerNdx;\n"
    961 				<< "        vert_color  = passColor;\n"
    962 				<< "        EmitVertex();\n"
    963 				<< "\n"
    964 				<< "        gl_Position = vec4(posX,  1.0, posZ, 1.0);\n"
    965 				<< "        gl_Layer    = layerNdx;\n"
    966 				<< "        vert_color  = passColor;\n"
    967 				<< "        EmitVertex();\n"
    968 				<< "\n"
    969 				<< "        EndPrimitive();\n"
    970 				<< "    }\n";
    971 		}
    972 		else
    973 			DE_ASSERT(0);
    974 
    975 		src <<	"}\n";	// end main
    976 
    977 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
    978 	}
    979 
    980 	// Fragment shader
    981 	{
    982 		std::ostringstream src;
    983 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    984 			<< "\n"
    985 			<< "layout(location = 0) out vec4 o_color;\n"
    986 			<< (geomOutputColor ? "layout(location = 0) in  vec4 vert_color;\n" : "")
    987 			<< "\n"
    988 			<< "void main(void)\n"
    989 			<< "{\n";
    990 
    991 		if (params.testType == TEST_TYPE_LAYER_ID)
    992 		{
    993 			// This code must be in sync with verifyLayerContent()
    994 			src << "    o_color = vec4( (gl_Layer    % 2) == 1 ? 1.0 : 0.5,\n"
    995 				<< "                   ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
    996 				<< "                     gl_Layer         == 0 ? 1.0 : 0.0,\n"
    997 				<< "                                             1.0);\n";
    998 		}
    999 		else if (geomOutputColor)
   1000 			src << "    o_color = vert_color;\n";
   1001 		else
   1002 			src << "    o_color = vec4(1.0);\n";
   1003 
   1004 		src << "}\n";
   1005 
   1006 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
   1007 	}
   1008 }
   1009 
   1010 tcu::TestStatus test (Context& context, const TestParams params)
   1011 {
   1012 	if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
   1013 		(!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1")))
   1014 		TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
   1015 
   1016 	const DeviceInterface&			vk						= context.getDeviceInterface();
   1017 	const InstanceInterface&		vki						= context.getInstanceInterface();
   1018 	const VkDevice					device					= context.getDevice();
   1019 	const VkPhysicalDevice			physDevice				= context.getPhysicalDevice();
   1020 	const deUint32					queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
   1021 	const VkQueue					queue					= context.getUniversalQueue();
   1022 	Allocator&						allocator				= context.getDefaultAllocator();
   1023 
   1024 	checkGeometryShaderSupport(vki, physDevice);
   1025 
   1026 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
   1027 	const deUint32					numLayers				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
   1028 	const Vec4						clearColor				= Vec4(0.0f, 0.0f, 0.0f, 1.0f);
   1029 	const VkDeviceSize				colorBufferSize			= params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * tcu::getPixelSize(mapVkFormat(colorFormat));
   1030 	const VkImageCreateFlags		imageCreateFlags		= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
   1031 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
   1032 	const VkImageViewType			viewType				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
   1033 
   1034 	const Unique<VkImage>			colorImage				(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
   1035 																					 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
   1036 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
   1037 	const Unique<VkImageView>		colorAttachment			(makeImageView			(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
   1038 
   1039 	const Unique<VkBuffer>			colorBuffer				(makeBuffer				(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
   1040 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
   1041 
   1042 	const Unique<VkShaderModule>	vertexModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0u));
   1043 	const Unique<VkShaderModule>	geometryModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("geom"), 0u));
   1044 	const Unique<VkShaderModule>	fragmentModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("frag"), 0u));
   1045 
   1046 	const Unique<VkRenderPass>		renderPass				(makeRenderPass			(vk, device, colorFormat));
   1047 	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer		(vk, device, *renderPass, &*colorAttachment, 1u, params.image.size.width,  params.image.size.height, numLayers));
   1048 	const Unique<VkPipelineLayout>	pipelineLayout			(makePipelineLayout		(vk, device));
   1049 	const Unique<VkPipeline>		pipeline				(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
   1050 																					 makeExtent2D(params.image.size.width, params.image.size.height)));
   1051 	const Unique<VkCommandPool>		cmdPool					(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
   1052 	const Unique<VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
   1053 
   1054 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
   1055 
   1056 	beginCommandBuffer(vk, *cmdBuffer);
   1057 
   1058 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor);
   1059 
   1060 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
   1061 	vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
   1062 	endRenderPass(vk, *cmdBuffer);
   1063 
   1064 	// Prepare color image for copy
   1065 	{
   1066 		const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
   1067 		const VkImageMemoryBarrier		barriers[] =
   1068 		{
   1069 			{
   1070 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
   1071 				DE_NULL,										// const void*				pNext;
   1072 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			outputMask;
   1073 				VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags			inputMask;
   1074 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			oldLayout;
   1075 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout			newLayout;
   1076 				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
   1077 				VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
   1078 				*colorImage,									// VkImage					image;
   1079 				colorSubresourceRange,							// VkImageSubresourceRange	subresourceRange;
   1080 			},
   1081 		};
   1082 
   1083 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
   1084 			0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
   1085 	}
   1086 	// Color image -> host buffer
   1087 	{
   1088 		const VkBufferImageCopy region =
   1089 		{
   1090 			0ull,																						// VkDeviceSize                bufferOffset;
   1091 			0u,																							// uint32_t                    bufferRowLength;
   1092 			0u,																							// uint32_t                    bufferImageHeight;
   1093 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers),		// VkImageSubresourceLayers    imageSubresource;
   1094 			makeOffset3D(0, 0, 0),																		// VkOffset3D                  imageOffset;
   1095 			params.image.size,																			// VkExtent3D                  imageExtent;
   1096 		};
   1097 
   1098 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
   1099 	}
   1100 	// Buffer write barrier
   1101 	{
   1102 		const VkBufferMemoryBarrier barriers[] =
   1103 		{
   1104 			{
   1105 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
   1106 				DE_NULL,										// const void*        pNext;
   1107 				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags      srcAccessMask;
   1108 				VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
   1109 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
   1110 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
   1111 				*colorBuffer,									// VkBuffer           buffer;
   1112 				0ull,											// VkDeviceSize       offset;
   1113 				VK_WHOLE_SIZE,									// VkDeviceSize       size;
   1114 			},
   1115 		};
   1116 
   1117 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
   1118 			0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
   1119 	}
   1120 
   1121 	endCommandBuffer(vk, *cmdBuffer);
   1122 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
   1123 
   1124 	invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
   1125 
   1126 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
   1127 		return tcu::TestStatus::fail("Rendered images are incorrect");
   1128 	else
   1129 		return tcu::TestStatus::pass("OK");
   1130 }
   1131 
   1132 tcu::TestStatus testLayeredReadBack (Context& context, const TestParams params)
   1133 {
   1134 	if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
   1135 		(!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1")))
   1136 		TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
   1137 
   1138 	const DeviceInterface&				vk					= context.getDeviceInterface();
   1139 	const InstanceInterface&			vki					= context.getInstanceInterface();
   1140 	const VkDevice						device				= context.getDevice();
   1141 	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
   1142 	const deUint32						queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
   1143 	const VkQueue						queue				= context.getUniversalQueue();
   1144 	Allocator&							allocator			= context.getDefaultAllocator();
   1145 
   1146 	checkGeometryShaderSupport(vki, physDevice);
   1147 
   1148 	const size_t						passCount			= 2;
   1149 	const deUint32						numLayers			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
   1150 	const VkImageCreateFlags			imageCreateFlags	= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
   1151 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
   1152 	const VkImageViewType				viewType			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
   1153 	const VkImageType					imageType			= getImageType(params.image.viewType);
   1154 	const VkExtent2D					imageExtent2D		= makeExtent2D(params.image.size.width, params.image.size.height);
   1155 
   1156 	const VkFormat						colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
   1157 	const deUint32						colorImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
   1158 	const VkDeviceSize					colorBufferSize		= params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * colorImagePixelSize;
   1159 	const VkImageUsageFlags				colorImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
   1160 
   1161 	const bool							dsUsed				= (VK_IMAGE_VIEW_TYPE_3D != params.image.viewType);
   1162 	const VkFormat						dsFormat			= VK_FORMAT_D24_UNORM_S8_UINT;
   1163 	const deUint32						dsImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(dsFormat)));
   1164 	const VkImageUsageFlags				dsImageUsage		= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
   1165 	const VkImageAspectFlags			dsAspectFlags		= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
   1166 	const VkDeviceSize					depthBufferSize		= params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * dsImagePixelSize;
   1167 
   1168 	const VkFormat						stencilBufferFormat	= getStencilBufferFormat(dsFormat);
   1169 	const deUint32						stencilPixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(stencilBufferFormat)));
   1170 	const VkDeviceSize					stencilBufferSize	= params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * stencilPixelSize;
   1171 
   1172 	checkImageFormatProperties(vki, physDevice, imageType, VK_IMAGE_TILING_OPTIMAL, dsImageUsage, imageCreateFlags, dsFormat, params.image.size, params.image.numLayers);
   1173 
   1174 	const Unique<VkImage>				colorImage			(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, imageType, colorFormat, params.image.size, params.image.numLayers, colorImageUsage)));
   1175 	const UniquePtr<Allocation>			colorImageAlloc		(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
   1176 	const Unique<VkImageView>			colorAttachment		(makeImageView			(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
   1177 	const Unique<VkBuffer>				colorBuffer			(makeBuffer				(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
   1178 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
   1179 
   1180 	const Unique<VkImage>				dsImage				(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, imageType, dsFormat, params.image.size, params.image.numLayers, dsImageUsage)));
   1181 	const UniquePtr<Allocation>			dsImageAlloc		(bindImage				(vk, device, allocator, *dsImage, MemoryRequirement::Any));
   1182 	const Unique<VkImageView>			dsAttachment		(makeImageView			(vk, device, *dsImage, viewType, dsFormat, makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers)));
   1183 	const Unique<VkBuffer>				depthBuffer			(makeBuffer				(vk, device, makeBufferCreateInfo(depthBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
   1184 	const UniquePtr<Allocation>			depthBufferAlloc	(bindBuffer				(vk, device, allocator, *depthBuffer, MemoryRequirement::HostVisible));
   1185 	const Unique<VkBuffer>				stencilBuffer		(makeBuffer				(vk, device, makeBufferCreateInfo(stencilBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
   1186 	const UniquePtr<Allocation>			stencilBufferAlloc	(bindBuffer				(vk, device, allocator, *stencilBuffer, MemoryRequirement::HostVisible));
   1187 
   1188 	const VkImageView					attachments[]		= {*colorAttachment, *dsAttachment};
   1189 	const deUint32						attachmentsCount	= dsUsed ? DE_LENGTH_OF_ARRAY(attachments) : 1u;
   1190 
   1191 	const Unique<VkShaderModule>		vertexModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0u));
   1192 	const Unique<VkShaderModule>		geometryModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("geom"), 0u));
   1193 	const Unique<VkShaderModule>		fragmentModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("frag"), 0u));
   1194 
   1195 	const Unique<VkRenderPass>			renderPass			(makeRenderPass			(vk, device, colorFormat, dsFormat, dsUsed));
   1196 	const Unique<VkFramebuffer>			framebuffer			(makeFramebuffer		(vk, device, *renderPass, attachments, attachmentsCount, params.image.size.width, params.image.size.height, numLayers));
   1197 
   1198 	const Move<VkDescriptorPool>		descriptorPool		= DescriptorPoolBuilder()
   1199 															  .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, passCount)
   1200 															  .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, passCount);
   1201 	const Move<VkDescriptorSetLayout>	descriptorSetLayout	= DescriptorSetLayoutBuilder()
   1202 															  .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
   1203 															  .build(vk, device);
   1204 	const Move<VkDescriptorSet>			descriptorSet[]		=
   1205 	{
   1206 		makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
   1207 		makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
   1208 	};
   1209 
   1210 	const size_t						uniformBufSize		= sizeof(deUint32);
   1211 	const VkBufferCreateInfo			uniformBufCI		= makeBufferCreateInfo(uniformBufSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
   1212 	const Move<VkBuffer>				uniformBuf[]		= { createBuffer(vk, device, &uniformBufCI), createBuffer(vk, device, &uniformBufCI) };
   1213 	const MovePtr<Allocation>			uniformBufAlloc[]	=
   1214 	{
   1215 		allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[0]), MemoryRequirement::HostVisible),
   1216 		allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[1]), MemoryRequirement::HostVisible),
   1217 	};
   1218 	const VkDescriptorBufferInfo		uniformBufDesc[]	=
   1219 	{
   1220 		makeDescriptorBufferInfo(*uniformBuf[0], 0ull, uniformBufSize),
   1221 		makeDescriptorBufferInfo(*uniformBuf[1], 0ull, uniformBufSize),
   1222 	};
   1223 
   1224 	const Unique<VkPipelineLayout>		pipelineLayout		(makePipelineLayout		(vk, device, *descriptorSetLayout));
   1225 	const Unique<VkPipeline>			pipeline			(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, imageExtent2D, dsUsed));
   1226 	const Unique<VkCommandPool>			cmdPool				(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
   1227 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
   1228 	const VkImageSubresourceRange		colorSubresRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
   1229 	const VkImageSubresourceRange		dsSubresRange		= makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, params.image.numLayers);
   1230 	const VkImageMemoryBarrier			colorPassBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
   1231 																VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
   1232 	const VkImageMemoryBarrier			dsPassBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
   1233 																VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
   1234 	std::string							result;
   1235 
   1236 	beginCommandBuffer(vk, *cmdBuffer);
   1237 	{
   1238 		const VkImageMemoryBarrier		colorBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
   1239 																				 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *colorImage, colorSubresRange);
   1240 		const VkImageMemoryBarrier		dsBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
   1241 																				 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *dsImage, dsSubresRange);
   1242 
   1243 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
   1244 
   1245 		if (dsUsed)
   1246 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
   1247 
   1248 		for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
   1249 		{
   1250 			const deUint32		imageDepth	= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx :       0u;
   1251 			const deUint32		layer		= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ?       0u : layerNdx;
   1252 			const VkOffset3D	imageOffset = makeOffset3D(0u, 0u, imageDepth);
   1253 			const VkExtent3D	imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
   1254 
   1255 			// Clear color image with initial value
   1256 			{
   1257 				const tcu::Vec4					clearColor				= scaleColor(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)], 0.25f);
   1258 				const deUint32					bufferSliceSize			= params.image.size.width * params.image.size.height * colorImagePixelSize;
   1259 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
   1260 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
   1261 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
   1262 
   1263 				fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, clearColor);
   1264 				vk.cmdCopyBufferToImage(*cmdBuffer, *colorBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
   1265 			}
   1266 
   1267 			// Clear depth image with initial value
   1268 			if (dsUsed)
   1269 			{
   1270 				const float						depthValue				= 1.0f;
   1271 				const deUint32					bufferSliceSize			= params.image.size.width * params.image.size.height * dsImagePixelSize;
   1272 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
   1273 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, layer, 1u);
   1274 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
   1275 
   1276 				fillBuffer(vk, device, *depthBufferAlloc, bufferOffset, bufferSliceSize, dsFormat, depthValue);
   1277 				vk.cmdCopyBufferToImage(*cmdBuffer, *depthBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
   1278 			}
   1279 
   1280 			// Clear stencil image with initial value
   1281 			if (dsUsed)
   1282 			{
   1283 				const deUint8					stencilValue			= 0;
   1284 				const deUint32					bufferSliceSize			= params.image.size.width * params.image.size.height * stencilPixelSize;
   1285 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
   1286 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layer, 1u);
   1287 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
   1288 				deUint8*						bufferStart				= static_cast<deUint8*>((*stencilBufferAlloc).getHostPtr());
   1289 				deUint8*						bufferLayerStart		= &bufferStart[bufferOffset];
   1290 
   1291 				deMemset(bufferLayerStart, stencilValue, bufferSliceSize);
   1292 				flushMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset() + bufferOffset, bufferSliceSize);
   1293 				vk.cmdCopyBufferToImage(*cmdBuffer, *stencilBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
   1294 			}
   1295 		}
   1296 	}
   1297 	// Change images layouts
   1298 	{
   1299 		const VkImageMemoryBarrier		colorBarrier	= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
   1300 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
   1301 		const VkImageMemoryBarrier		dsBarrier		= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
   1302 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
   1303 
   1304 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
   1305 
   1306 		if (dsUsed)
   1307 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
   1308 	}
   1309 
   1310 	for (deUint32 pass = 0; pass < passCount; ++pass)
   1311 	{
   1312 		DE_ASSERT(sizeof(pass) == uniformBufSize);
   1313 
   1314 		VK_CHECK(vk.bindBufferMemory(device, *uniformBuf[pass], uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset()));
   1315 		deMemcpy(uniformBufAlloc[pass]->getHostPtr(), &pass, uniformBufSize);
   1316 		flushMappedMemoryRange(vk, device, uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset(), uniformBufSize);
   1317 
   1318 		DescriptorSetUpdateBuilder()
   1319 			.writeSingle(*descriptorSet[pass], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufDesc[pass])
   1320 			.update(vk, device);
   1321 
   1322 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet[pass], 0u, DE_NULL);
   1323 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(imageExtent2D));
   1324 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
   1325 		vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
   1326 		endRenderPass(vk, *cmdBuffer);
   1327 
   1328 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorPassBarrier);
   1329 
   1330 		if (dsUsed)
   1331 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsPassBarrier);
   1332 	}
   1333 	endCommandBuffer(vk, *cmdBuffer);
   1334 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
   1335 
   1336 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
   1337 	zeroBuffer(vk, device, *depthBufferAlloc, depthBufferSize);
   1338 	zeroBuffer(vk, device, *stencilBufferAlloc, stencilBufferSize);
   1339 
   1340 	beginCommandBuffer(vk, *cmdBuffer);
   1341 	{
   1342 		// Copy color image
   1343 		{
   1344 			const VkImageMemoryBarrier	preCopyBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
   1345 															VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorImage, colorSubresRange);
   1346 			const VkBufferImageCopy		region			= makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers));
   1347 			const VkBufferMemoryBarrier	postCopyBarrier	= makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
   1348 
   1349 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
   1350 			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
   1351 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
   1352 		}
   1353 
   1354 		// Depth/Stencil image copy
   1355 		if (dsUsed)
   1356 		{
   1357 			const VkImageMemoryBarrier	preCopyBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
   1358 																VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dsImage, dsSubresRange);
   1359 			const VkBufferImageCopy		depthCopyRegion		= makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, params.image.numLayers));
   1360 			const VkBufferImageCopy		stencilCopyRegion	= makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, params.image.numLayers));
   1361 			const VkBufferMemoryBarrier	postCopyBarriers[]	=
   1362 			{
   1363 				makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *depthBuffer, 0ull, VK_WHOLE_SIZE),
   1364 				makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *stencilBuffer, 0ull, VK_WHOLE_SIZE),
   1365 			};
   1366 
   1367 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
   1368 			vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *depthBuffer, 1u, &depthCopyRegion);
   1369 			vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *stencilBuffer, 1u, &stencilCopyRegion);
   1370 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(postCopyBarriers), postCopyBarriers, DE_NULL, 0u);
   1371 		}
   1372 	}
   1373 	endCommandBuffer(vk, *cmdBuffer);
   1374 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
   1375 
   1376 	invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
   1377 	invalidateMappedMemoryRange(vk, device, depthBufferAlloc->getMemory(), depthBufferAlloc->getOffset(), depthBufferSize);
   1378 	invalidateMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset(), stencilBufferSize);
   1379 
   1380 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
   1381 		result += " Color";
   1382 
   1383 	if (dsUsed)
   1384 	{
   1385 		if (!verifyResults(context.getTestContext().getLog(), params, dsFormat, depthBufferAlloc->getHostPtr(), true, false))
   1386 			result += " Depth";
   1387 
   1388 		if (!verifyResults(context.getTestContext().getLog(), params, stencilBufferFormat, stencilBufferAlloc->getHostPtr(), false, true))
   1389 			result += " Stencil";
   1390 	}
   1391 
   1392 	if (result.empty())
   1393 		return tcu::TestStatus::pass("OK");
   1394 	else
   1395 		return tcu::TestStatus::fail("Following parts of image are incorrect:" + result);
   1396 }
   1397 
   1398 } // anonymous
   1399 
   1400 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
   1401 {
   1402 	MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
   1403 
   1404 	const struct
   1405 	{
   1406 		TestType		test;
   1407 		const char*		name;
   1408 		const char*		description;
   1409 	} testTypes[] =
   1410 	{
   1411 		{ TEST_TYPE_DEFAULT_LAYER,					"render_to_default_layer",			"Render to the default layer"															},
   1412 		{ TEST_TYPE_SINGLE_LAYER,					"render_to_one",					"Render to one layer"																	},
   1413 		{ TEST_TYPE_ALL_LAYERS,						"render_to_all",					"Render to all layers"																	},
   1414 		{ TEST_TYPE_DIFFERENT_CONTENT,				"render_different_content",			"Render different data to different layers"												},
   1415 		{ TEST_TYPE_LAYER_ID,						"fragment_layer",					"Read gl_Layer in fragment shader"														},
   1416 		{ TEST_TYPE_INVOCATION_PER_LAYER,			"invocation_per_layer",				"Render to multiple layers with multiple invocations, one invocation per layer"			},
   1417 		{ TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,	"multiple_layers_per_invocation",	"Render to multiple layers with multiple invocations, multiple layers per invocation",	},
   1418 		{ TEST_TYPE_LAYERED_READBACK,				"readback",							"Render to multiple layers with two passes to check LOAD_OP_LOAD capability"			},
   1419 	};
   1420 
   1421 	const ImageParams imageParams[] =
   1422 	{
   1423 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		{ 64,  1, 1 },	4	},
   1424 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		{ 64, 64, 1 },	4	},
   1425 		{ VK_IMAGE_VIEW_TYPE_CUBE,			{ 64, 64, 1 },	6	},
   1426 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	{ 64, 64, 1 },	2*6	},
   1427 		{ VK_IMAGE_VIEW_TYPE_3D,			{ 64, 64, 8 },	1	}
   1428 	};
   1429 
   1430 	for (int imageParamNdx = 0; imageParamNdx < DE_LENGTH_OF_ARRAY(imageParams); ++imageParamNdx)
   1431 	{
   1432 		MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParams[imageParamNdx].viewType).c_str(), ""));
   1433 
   1434 		for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
   1435 		{
   1436 			const TestParams params =
   1437 			{
   1438 				testTypes[testTypeNdx].test,
   1439 				imageParams[imageParamNdx],
   1440 			};
   1441 
   1442 			if (testTypes[testTypeNdx].test == TEST_TYPE_LAYERED_READBACK)
   1443 				addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, testLayeredReadBack, params);
   1444 			else
   1445 				addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
   1446 		}
   1447 
   1448 		group->addChild(viewTypeGroup.release());
   1449 	}
   1450 
   1451 	return group.release();
   1452 }
   1453 
   1454 } // geometry
   1455 } // vkt
   1456