1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015-2016 The Khronos Group Inc.
6 * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Vulkan Copies And Blitting Tests
23 *//*--------------------------------------------------------------------*/
24
25#include "vktApiCopiesAndBlittingTests.hpp"
26
27#include "deStringUtil.hpp"
28#include "deUniquePtr.hpp"
29
30#include "tcuImageCompare.hpp"
31#include "tcuTexture.hpp"
32#include "tcuTextureUtil.hpp"
33#include "tcuVectorType.hpp"
34#include "tcuVectorUtil.hpp"
35#include "tcuTestLog.hpp"
36#include "tcuTexLookupVerifier.hpp"
37
38#include "vkImageUtil.hpp"
39#include "vkMemUtil.hpp"
40#include "vkPrograms.hpp"
41#include "vkQueryUtil.hpp"
42#include "vkRefUtil.hpp"
43#include "vktTestCase.hpp"
44#include "vktTestCaseUtil.hpp"
45#include "vktTestGroupUtil.hpp"
46#include "vkTypeUtil.hpp"
47
48#include <set>
49
50namespace vkt
51{
52
53namespace api
54{
55
56namespace
57{
58enum MirrorMode
59{
60	MIRROR_MODE_NONE = 0,
61	MIRROR_MODE_X = (1<<0),
62	MIRROR_MODE_Y = (1<<1),
63	MIRROR_MODE_XY = MIRROR_MODE_X | MIRROR_MODE_Y,
64
65	MIRROR_MODE_LAST
66};
67
68enum AllocationKind
69{
70	ALLOCATION_KIND_SUBALLOCATED,
71	ALLOCATION_KIND_DEDICATED,
72};
73
74template <typename Type>
75class BinaryCompare
76{
77public:
78	bool operator() (const Type& a, const Type& b) const
79	{
80		return deMemCmp(&a, &b, sizeof(Type)) < 0;
81	}
82};
83
84typedef std::set<vk::VkFormat, BinaryCompare<vk::VkFormat> >	FormatSet;
85
86FormatSet dedicatedAllocationImageToImageFormatsToTestSet;
87FormatSet dedicatedAllocationBlittingFormatsToTestSet;
88
89using namespace vk;
90
91VkImageAspectFlags getAspectFlags (tcu::TextureFormat format)
92{
93	VkImageAspectFlags	aspectFlag	= 0;
94	aspectFlag |= (tcu::hasDepthComponent(format.order)? VK_IMAGE_ASPECT_DEPTH_BIT : 0);
95	aspectFlag |= (tcu::hasStencilComponent(format.order)? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
96
97	if (!aspectFlag)
98		aspectFlag = VK_IMAGE_ASPECT_COLOR_BIT;
99
100	return aspectFlag;
101}
102
103// This is effectively same as vk::isFloatFormat(mapTextureFormat(format))
104// except that it supports some formats that are not mappable to VkFormat.
105// When we are checking combined depth and stencil formats, each aspect is
106// checked separately, and in some cases we construct PBA with a format that
107// is not mappable to VkFormat.
108bool isFloatFormat (tcu::TextureFormat format)
109{
110	return tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
111}
112
113union CopyRegion
114{
115	VkBufferCopy		bufferCopy;
116	VkImageCopy			imageCopy;
117	VkBufferImageCopy	bufferImageCopy;
118	VkImageBlit			imageBlit;
119	VkImageResolve		imageResolve;
120};
121
122struct ImageParms
123{
124	VkImageType		imageType;
125	VkFormat		format;
126	VkExtent3D		extent;
127	VkImageLayout	operationLayout;
128};
129
130struct TestParams
131{
132	union Data
133	{
134		struct Buffer
135		{
136			VkDeviceSize	size;
137		} buffer;
138
139		ImageParms	image;
140	} src, dst;
141
142	std::vector<CopyRegion>	regions;
143
144	union
145	{
146		VkFilter				filter;
147		VkSampleCountFlagBits	samples;
148	};
149
150	AllocationKind	allocationKind;
151	deUint32		mipLevels;
152	deBool			singleCommand;
153
154	TestParams (void)
155	{
156		mipLevels		= 1u;
157		singleCommand	= DE_TRUE;
158	}
159};
160
161de::MovePtr<Allocation> allocateBuffer (const InstanceInterface&	vki,
162										const DeviceInterface&		vkd,
163										const VkPhysicalDevice&		physDevice,
164										const VkDevice				device,
165										const VkBuffer&				buffer,
166										const MemoryRequirement		requirement,
167										Allocator&					allocator,
168										AllocationKind				allocationKind)
169{
170	switch (allocationKind)
171	{
172		case ALLOCATION_KIND_SUBALLOCATED:
173		{
174			const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer);
175
176			return allocator.allocate(memoryRequirements, requirement);
177		}
178
179		case ALLOCATION_KIND_DEDICATED:
180		{
181			return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
182		}
183
184		default:
185		{
186			TCU_THROW(InternalError, "Invalid allocation kind");
187		}
188	}
189}
190
191de::MovePtr<Allocation> allocateImage (const InstanceInterface&		vki,
192									   const DeviceInterface&		vkd,
193									   const VkPhysicalDevice&		physDevice,
194									   const VkDevice				device,
195									   const VkImage&				image,
196									   const MemoryRequirement		requirement,
197									   Allocator&					allocator,
198									   AllocationKind				allocationKind)
199{
200	switch (allocationKind)
201	{
202		case ALLOCATION_KIND_SUBALLOCATED:
203		{
204			const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image);
205
206			return allocator.allocate(memoryRequirements, requirement);
207		}
208
209		case ALLOCATION_KIND_DEDICATED:
210		{
211			return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
212		}
213
214		default:
215		{
216			TCU_THROW(InternalError, "Invalid allocation kind");
217		}
218	}
219}
220
221
222inline deUint32 getArraySize(const ImageParms& parms)
223{
224	return (parms.imageType == VK_IMAGE_TYPE_2D) ? parms.extent.depth : 1u;
225}
226
227inline VkExtent3D getExtent3D(const ImageParms& parms)
228{
229	const VkExtent3D		extent					=
230	{
231		parms.extent.width,
232		parms.extent.height,
233		(parms.imageType == VK_IMAGE_TYPE_2D) ? 1u : parms.extent.depth
234	};
235	return extent;
236}
237
238const tcu::TextureFormat mapCombinedToDepthTransferFormat (const tcu::TextureFormat& combinedFormat)
239{
240	tcu::TextureFormat format;
241	switch (combinedFormat.type)
242	{
243		case tcu::TextureFormat::UNSIGNED_INT_16_8_8:
244			format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
245			break;
246		case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:
247			format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8_REV);
248			break;
249		case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
250			format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
251			break;
252		default:
253			DE_ASSERT(false);
254			break;
255	}
256	return format;
257}
258
259class CopiesAndBlittingTestInstance : public vkt::TestInstance
260{
261public:
262										CopiesAndBlittingTestInstance		(Context&	context,
263																			 TestParams	testParams);
264	virtual tcu::TestStatus				iterate								(void) = 0;
265
266	enum FillMode
267	{
268		FILL_MODE_GRADIENT = 0,
269		FILL_MODE_WHITE,
270		FILL_MODE_RED,
271		FILL_MODE_MULTISAMPLE,
272
273		FILL_MODE_LAST
274	};
275
276protected:
277	const TestParams					m_params;
278
279	Move<VkCommandPool>					m_cmdPool;
280	Move<VkCommandBuffer>				m_cmdBuffer;
281	Move<VkFence>						m_fence;
282	de::MovePtr<tcu::TextureLevel>		m_sourceTextureLevel;
283	de::MovePtr<tcu::TextureLevel>		m_destinationTextureLevel;
284	de::MovePtr<tcu::TextureLevel>		m_expectedTextureLevel[16];
285
286	VkCommandBufferBeginInfo			m_cmdBufferBeginInfo;
287
288	void								generateBuffer						(tcu::PixelBufferAccess buffer, int width, int height, int depth = 1, FillMode = FILL_MODE_GRADIENT);
289	virtual void						generateExpectedResult				(void);
290	void								uploadBuffer						(tcu::ConstPixelBufferAccess bufferAccess, const Allocation& bufferAlloc);
291	void								uploadImage							(const tcu::ConstPixelBufferAccess& src, VkImage dst, const ImageParms& parms, const deUint32 mipLevels = 1u);
292	virtual tcu::TestStatus				checkTestResult						(tcu::ConstPixelBufferAccess result);
293	virtual void						copyRegionToTextureLevel			(tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region) = 0;
294	deUint32							calculateSize						(tcu::ConstPixelBufferAccess src) const
295										{
296											return src.getWidth() * src.getHeight() * src.getDepth() * tcu::getPixelSize(src.getFormat());
297										}
298
299	de::MovePtr<tcu::TextureLevel>		readImage							(vk::VkImage				image,
300																			 const ImageParms&			imageParms,
301																			 const deUint32				mipLevel = 0u);
302	void								submitCommandsAndWait				(const DeviceInterface&		vk,
303																			const VkDevice				device,
304																			const VkQueue				queue,
305																			const VkCommandBuffer&		cmdBuffer);
306
307private:
308	void								uploadImageAspect					(const tcu::ConstPixelBufferAccess&	src,
309																			 const VkImage&						dst,
310																			 const ImageParms&					parms,
311																			 const deUint32						mipLevels = 1u);
312	void								readImageAspect						(vk::VkImage						src,
313																			 const tcu::PixelBufferAccess&		dst,
314																			 const ImageParms&					parms,
315																			 const deUint32						mipLevel = 0u);
316};
317
318CopiesAndBlittingTestInstance::CopiesAndBlittingTestInstance (Context& context, TestParams testParams)
319	: vkt::TestInstance	(context)
320	, m_params			(testParams)
321{
322	const DeviceInterface&		vk					= context.getDeviceInterface();
323	const VkDevice				vkDevice			= context.getDevice();
324	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
325
326	if (m_params.allocationKind == ALLOCATION_KIND_DEDICATED)
327	{
328		if (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_dedicated_allocation"))
329			TCU_THROW(NotSupportedError, "VK_KHR_dedicated_allocation is not supported");
330	}
331
332	// Create command pool
333	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
334
335	// Create command buffer
336	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
337
338	// Create fence
339	m_fence = createFence(vk, vkDevice);
340}
341
342void CopiesAndBlittingTestInstance::generateBuffer (tcu::PixelBufferAccess buffer, int width, int height, int depth, FillMode mode)
343{
344	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(buffer.getFormat().type);
345	tcu::Vec4						maxValue		(1.0f);
346
347	if (buffer.getFormat().order == tcu::TextureFormat::S)
348	{
349		// Stencil-only is stored in the first component. Stencil is always 8 bits.
350		maxValue.x() = 1 << 8;
351	}
352	else if (buffer.getFormat().order == tcu::TextureFormat::DS)
353	{
354		// In a combined format, fillWithComponentGradients expects stencil in the fourth component.
355		maxValue.w() = 1 << 8;
356	}
357	else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
358	{
359		// The tcu::Vectors we use as pixels are 32-bit, so clamp to that.
360		const tcu::IVec4	bits	= tcu::min(tcu::getTextureFormatBitDepth(buffer.getFormat()), tcu::IVec4(32));
361		const int			signBit	= (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? 1 : 0);
362
363		for (int i = 0; i < 4; ++i)
364		{
365			if (bits[i] != 0)
366				maxValue[i] = static_cast<float>((deUint64(1) << (bits[i] - signBit)) - 1);
367		}
368	}
369
370	if (mode == FILL_MODE_GRADIENT)
371	{
372		tcu::fillWithComponentGradients(buffer, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), maxValue);
373		return;
374	}
375
376	const tcu::Vec4		redColor	(maxValue.x(),	0.0,			0.0,			maxValue.w());
377	const tcu::Vec4		greenColor	(0.0,			maxValue.y(),	0.0,			maxValue.w());
378	const tcu::Vec4		blueColor	(0.0,			0.0,			maxValue.z(),	maxValue.w());
379	const tcu::Vec4		whiteColor	(maxValue.x(),	maxValue.y(),	maxValue.z(),	maxValue.w());
380
381	for (int z = 0; z < depth;  ++z)
382	for (int y = 0; y < height; ++y)
383	for (int x = 0; x < width;  ++x)
384	{
385		switch (mode)
386		{
387			case FILL_MODE_WHITE:
388				if (tcu::isCombinedDepthStencilType(buffer.getFormat().type))
389				{
390					buffer.setPixDepth(1.0f, x, y, z);
391					if (tcu::hasStencilComponent(buffer.getFormat().order))
392						buffer.setPixStencil(255, x, y, z);
393				}
394				else
395					buffer.setPixel(whiteColor, x, y, z);
396				break;
397
398			case FILL_MODE_RED:
399				if (tcu::isCombinedDepthStencilType(buffer.getFormat().type))
400				{
401					buffer.setPixDepth(redColor[0], x, y, z);
402					if (tcu::hasStencilComponent(buffer.getFormat().order))
403						buffer.setPixStencil((int)redColor[3], x, y, z);
404				}
405				else
406					buffer.setPixel(redColor, x, y, z);
407				break;
408
409			case FILL_MODE_MULTISAMPLE:
410			{
411				float xScaled = static_cast<float>(x) / static_cast<float>(width);
412				float yScaled = static_cast<float>(y) / static_cast<float>(height);
413				buffer.setPixel((xScaled == yScaled) ? tcu::Vec4(0.0, 0.5, 0.5, 1.0) : ((xScaled > yScaled) ? greenColor : blueColor), x, y, z);
414				break;
415			}
416
417			default:
418				break;
419		}
420	}
421}
422
423void CopiesAndBlittingTestInstance::uploadBuffer (tcu::ConstPixelBufferAccess bufferAccess, const Allocation& bufferAlloc)
424{
425	const DeviceInterface&		vk			= m_context.getDeviceInterface();
426	const VkDevice				vkDevice	= m_context.getDevice();
427	const deUint32				bufferSize	= calculateSize(bufferAccess);
428
429	// Write buffer data
430	deMemcpy(bufferAlloc.getHostPtr(), bufferAccess.getDataPtr(), bufferSize);
431	flushMappedMemoryRange(vk, vkDevice, bufferAlloc.getMemory(), bufferAlloc.getOffset(), bufferSize);
432}
433
434void CopiesAndBlittingTestInstance::uploadImageAspect (const tcu::ConstPixelBufferAccess& imageAccess, const VkImage& image, const ImageParms& parms, const deUint32 mipLevels)
435{
436	const InstanceInterface&		vki					= m_context.getInstanceInterface();
437	const DeviceInterface&			vk					= m_context.getDeviceInterface();
438	const VkPhysicalDevice			vkPhysDevice		= m_context.getPhysicalDevice();
439	const VkDevice					vkDevice			= m_context.getDevice();
440	const VkQueue					queue				= m_context.getUniversalQueue();
441	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
442	Allocator&						memAlloc			= m_context.getDefaultAllocator();
443	Move<VkBuffer>					buffer;
444	const deUint32					bufferSize			= calculateSize(imageAccess);
445	de::MovePtr<Allocation>			bufferAlloc;
446	const deUint32					arraySize			= getArraySize(parms);
447	const VkExtent3D				imageExtent			= getExtent3D(parms);
448	std::vector <VkBufferImageCopy>	copyRegions;
449
450	// Create source buffer
451	{
452		const VkBufferCreateInfo	bufferParams		=
453		{
454			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
455			DE_NULL,									// const void*			pNext;
456			0u,											// VkBufferCreateFlags	flags;
457			bufferSize,									// VkDeviceSize			size;
458			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
459			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
460			1u,											// deUint32				queueFamilyIndexCount;
461			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
462		};
463
464		buffer		= createBuffer(vk, vkDevice, &bufferParams);
465		bufferAlloc = allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *buffer, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind);
466		VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
467	}
468
469	// Barriers for copying buffer to image
470	const VkBufferMemoryBarrier		preBufferBarrier	=
471	{
472		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType	sType;
473		DE_NULL,										// const void*		pNext;
474		VK_ACCESS_HOST_WRITE_BIT,						// VkAccessFlags	srcAccessMask;
475		VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags	dstAccessMask;
476		VK_QUEUE_FAMILY_IGNORED,						// deUint32			srcQueueFamilyIndex;
477		VK_QUEUE_FAMILY_IGNORED,						// deUint32			dstQueueFamilyIndex;
478		*buffer,										// VkBuffer			buffer;
479		0u,												// VkDeviceSize		offset;
480		bufferSize										// VkDeviceSize		size;
481	};
482
483	const VkImageAspectFlags		formatAspect		= getAspectFlags(mapVkFormat(parms.format));
484	const bool						skipPreImageBarrier	= formatAspect == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) &&
485														  getAspectFlags(imageAccess.getFormat()) == VK_IMAGE_ASPECT_STENCIL_BIT;
486	const VkImageMemoryBarrier		preImageBarrier		=
487	{
488		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
489		DE_NULL,										// const void*				pNext;
490		0u,												// VkAccessFlags			srcAccessMask;
491		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
492		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
493		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout;
494		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
495		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
496		image,											// VkImage					image;
497		{												// VkImageSubresourceRange	subresourceRange;
498			formatAspect,	// VkImageAspectFlags	aspect;
499			0u,				// deUint32				baseMipLevel;
500			mipLevels,		// deUint32				mipLevels;
501			0u,				// deUint32				baseArraySlice;
502			arraySize,		// deUint32				arraySize;
503		}
504	};
505
506	const VkImageMemoryBarrier		postImageBarrier	=
507	{
508		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
509		DE_NULL,										// const void*				pNext;
510		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
511		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
512		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			oldLayout;
513		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout;
514		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
515		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
516		image,											// VkImage					image;
517		{												// VkImageSubresourceRange	subresourceRange;
518			formatAspect,				// VkImageAspectFlags	aspect;
519			0u,							// deUint32				baseMipLevel;
520			mipLevels,					// deUint32				mipLevels;
521			0u,							// deUint32				baseArraySlice;
522			arraySize,					// deUint32				arraySize;
523		}
524	};
525
526	for (deUint32 mipLevelNdx = 0; mipLevelNdx < mipLevels; mipLevelNdx++)
527	{
528		const VkExtent3D		copyExtent	=
529		{
530			imageExtent.width	>> mipLevelNdx,
531			imageExtent.height	>> mipLevelNdx,
532			imageExtent.depth
533		};
534
535		const VkBufferImageCopy	copyRegion	=
536		{
537			0u,												// VkDeviceSize				bufferOffset;
538			(deUint32)imageAccess.getWidth(),				// deUint32					bufferRowLength;
539			(deUint32)imageAccess.getHeight(),				// deUint32					bufferImageHeight;
540			{
541				getAspectFlags(imageAccess.getFormat()),		// VkImageAspectFlags	aspect;
542				mipLevelNdx,									// deUint32				mipLevel;
543				0u,												// deUint32				baseArrayLayer;
544				arraySize,										// deUint32				layerCount;
545			},												// VkImageSubresourceLayers	imageSubresource;
546			{ 0, 0, 0 },									// VkOffset3D				imageOffset;
547			copyExtent										// VkExtent3D				imageExtent;
548		};
549
550		copyRegions.push_back(copyRegion);
551	}
552
553	// Write buffer data
554	deMemcpy(bufferAlloc->getHostPtr(), imageAccess.getDataPtr(), bufferSize);
555	flushMappedMemoryRange(vk, vkDevice, bufferAlloc->getMemory(), bufferAlloc->getOffset(), bufferSize);
556
557	// Copy buffer to image
558	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
559	{
560		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
561		DE_NULL,												// const void*						pNext;
562		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
563		(const VkCommandBufferInheritanceInfo*)DE_NULL,
564	};
565
566	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
567	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL,
568						  1, &preBufferBarrier, (skipPreImageBarrier ? 0 : 1), (skipPreImageBarrier ? DE_NULL : &preImageBarrier));
569	vk.cmdCopyBufferToImage(*m_cmdBuffer, *buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copyRegions.size(), &copyRegions[0]);
570	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
571	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
572
573	submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer);
574}
575
576void CopiesAndBlittingTestInstance::uploadImage (const tcu::ConstPixelBufferAccess& src, VkImage dst, const ImageParms& parms, const deUint32 mipLevels)
577{
578	if (tcu::isCombinedDepthStencilType(src.getFormat().type))
579	{
580		if (tcu::hasDepthComponent(src.getFormat().order))
581		{
582			tcu::TextureLevel	depthTexture	(mapCombinedToDepthTransferFormat(src.getFormat()), src.getWidth(), src.getHeight(), src.getDepth());
583			tcu::copy(depthTexture.getAccess(), tcu::getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_DEPTH));
584			uploadImageAspect(depthTexture.getAccess(), dst, parms);
585		}
586
587		if (tcu::hasStencilComponent(src.getFormat().order))
588		{
589			tcu::TextureLevel	stencilTexture	(tcu::getEffectiveDepthStencilTextureFormat(src.getFormat(), tcu::Sampler::MODE_STENCIL), src.getWidth(), src.getHeight(), src.getDepth());
590			tcu::copy(stencilTexture.getAccess(), tcu::getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_STENCIL));
591			uploadImageAspect(stencilTexture.getAccess(), dst, parms);
592		}
593	}
594	else
595		uploadImageAspect(src, dst, parms, mipLevels);
596}
597
598tcu::TestStatus CopiesAndBlittingTestInstance::checkTestResult (tcu::ConstPixelBufferAccess result)
599{
600	const tcu::ConstPixelBufferAccess	expected	= m_expectedTextureLevel[0]->getAccess();
601
602	if (isFloatFormat(result.getFormat()))
603	{
604		const tcu::Vec4	threshold (0.0f);
605		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expected, result, threshold, tcu::COMPARE_LOG_RESULT))
606			return tcu::TestStatus::fail("CopiesAndBlitting test");
607	}
608	else
609	{
610		const tcu::UVec4 threshold (0u);
611		if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expected, result, threshold, tcu::COMPARE_LOG_RESULT))
612			return tcu::TestStatus::fail("CopiesAndBlitting test");
613	}
614
615	return tcu::TestStatus::pass("CopiesAndBlitting test");
616}
617
618void CopiesAndBlittingTestInstance::generateExpectedResult (void)
619{
620	const tcu::ConstPixelBufferAccess	src	= m_sourceTextureLevel->getAccess();
621	const tcu::ConstPixelBufferAccess	dst	= m_destinationTextureLevel->getAccess();
622
623	m_expectedTextureLevel[0]	= de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth()));
624	tcu::copy(m_expectedTextureLevel[0]->getAccess(), dst);
625
626	for (deUint32 i = 0; i < m_params.regions.size(); i++)
627		copyRegionToTextureLevel(src, m_expectedTextureLevel[0]->getAccess(), m_params.regions[i]);
628}
629
630class CopiesAndBlittingTestCase : public vkt::TestCase
631{
632public:
633							CopiesAndBlittingTestCase	(tcu::TestContext&			testCtx,
634														 const std::string&			name,
635														 const std::string&			description)
636								: vkt::TestCase	(testCtx, name, description)
637							{}
638
639	virtual TestInstance*	createInstance				(Context&					context) const = 0;
640};
641
642void CopiesAndBlittingTestInstance::readImageAspect (vk::VkImage					image,
643													 const tcu::PixelBufferAccess&	dst,
644													 const ImageParms&				imageParms,
645													 const deUint32					mipLevel)
646{
647	const InstanceInterface&	vki					= m_context.getInstanceInterface();
648	const DeviceInterface&		vk					= m_context.getDeviceInterface();
649	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
650	const VkDevice				device				= m_context.getDevice();
651	const VkQueue				queue				= m_context.getUniversalQueue();
652	Allocator&					allocator			= m_context.getDefaultAllocator();
653
654	Move<VkBuffer>				buffer;
655	de::MovePtr<Allocation>		bufferAlloc;
656	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
657	const VkDeviceSize			pixelDataSize		= calculateSize(dst);
658
659	const VkExtent3D			imageExtent			=
660	{
661		(deUint32)dst.getWidth(),
662		(deUint32)dst.getHeight(),
663		(imageParms.imageType == VK_IMAGE_TYPE_3D) ? (deUint32)dst.getDepth() : 1,
664	};
665
666	// Create destination buffer
667	{
668		const VkBufferCreateInfo			bufferParams			=
669		{
670			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
671			DE_NULL,									// const void*			pNext;
672			0u,											// VkBufferCreateFlags	flags;
673			pixelDataSize,								// VkDeviceSize			size;
674			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
675			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
676			1u,											// deUint32				queueFamilyIndexCount;
677			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
678		};
679
680		buffer		= createBuffer(vk, device, &bufferParams);
681		bufferAlloc = allocateBuffer(vki, vk, physDevice, device, *buffer, MemoryRequirement::HostVisible, allocator, m_params.allocationKind);
682		VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
683
684		deMemset(bufferAlloc->getHostPtr(), 0, static_cast<size_t>(pixelDataSize));
685		flushMappedMemoryRange(vk, device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), pixelDataSize);
686	}
687
688	// Barriers for copying image to buffer
689	const VkImageAspectFlags				formatAspect			= getAspectFlags(mapVkFormat(imageParms.format));
690	const VkImageMemoryBarrier				imageBarrier			=
691	{
692		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
693		DE_NULL,									// const void*				pNext;
694		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
695		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
696		imageParms.operationLayout,					// VkImageLayout			oldLayout;
697		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
698		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
699		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
700		image,										// VkImage					image;
701		{											// VkImageSubresourceRange	subresourceRange;
702			formatAspect,			// VkImageAspectFlags	aspectMask;
703			mipLevel,				// deUint32				baseMipLevel;
704			1u,						// deUint32				mipLevels;
705			0u,						// deUint32				baseArraySlice;
706			getArraySize(imageParms)// deUint32				arraySize;
707		}
708	};
709
710	const VkBufferMemoryBarrier				bufferBarrier			=
711	{
712		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
713		DE_NULL,									// const void*		pNext;
714		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
715		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
716		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
717		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
718		*buffer,									// VkBuffer			buffer;
719		0u,											// VkDeviceSize		offset;
720		pixelDataSize								// VkDeviceSize		size;
721	};
722
723	const VkImageMemoryBarrier				postImageBarrier		=
724	{
725		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
726		DE_NULL,									// const void*				pNext;
727		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			srcAccessMask;
728		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
729		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			oldLayout;
730		imageParms.operationLayout,					// VkImageLayout			newLayout;
731		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
732		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
733		image,										// VkImage					image;
734		{
735			formatAspect,								// VkImageAspectFlags	aspectMask;
736			mipLevel,									// deUint32				baseMipLevel;
737			1u,											// deUint32				mipLevels;
738			0u,											// deUint32				baseArraySlice;
739			getArraySize(imageParms)					// deUint32				arraySize;
740		}											// VkImageSubresourceRange	subresourceRange;
741	};
742
743	// Copy image to buffer
744	const VkImageAspectFlags	aspect			= getAspectFlags(dst.getFormat());
745	const VkBufferImageCopy		copyRegion		=
746	{
747		0u,									// VkDeviceSize				bufferOffset;
748		(deUint32)dst.getWidth(),			// deUint32					bufferRowLength;
749		(deUint32)dst.getHeight(),			// deUint32					bufferImageHeight;
750		{
751			aspect,								// VkImageAspectFlags		aspect;
752			mipLevel,							// deUint32					mipLevel;
753			0u,									// deUint32					baseArrayLayer;
754			getArraySize(imageParms),			// deUint32					layerCount;
755		},									// VkImageSubresourceLayers	imageSubresource;
756		{ 0, 0, 0 },						// VkOffset3D				imageOffset;
757		imageExtent							// VkExtent3D				imageExtent;
758	};
759
760	const VkCommandBufferBeginInfo			cmdBufferBeginInfo		=
761	{
762		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
763		DE_NULL,												// const void*						pNext;
764		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
765		(const VkCommandBufferInheritanceInfo*)DE_NULL,
766	};
767
768	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
769	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
770	vk.cmdCopyImageToBuffer(*m_cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1u, &copyRegion);
771	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT|VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 1, &postImageBarrier);
772	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
773
774	submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
775
776	// Read buffer data
777	invalidateMappedMemoryRange(vk, device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), pixelDataSize);
778	tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferAlloc->getHostPtr()));
779}
780
781void CopiesAndBlittingTestInstance::submitCommandsAndWait (const DeviceInterface& vk, const VkDevice device, const VkQueue queue, const VkCommandBuffer& cmdBuffer)
782{
783	const VkSubmitInfo						submitInfo				=
784	{
785		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
786		DE_NULL,						// const void*				pNext;
787		0u,								// deUint32					waitSemaphoreCount;
788		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
789		(const VkPipelineStageFlags*)DE_NULL,
790		1u,								// deUint32					commandBufferCount;
791		&cmdBuffer,						// const VkCommandBuffer*	pCommandBuffers;
792		0u,								// deUint32					signalSemaphoreCount;
793		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
794	};
795
796	VK_CHECK(vk.resetFences(device, 1, &m_fence.get()));
797	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
798	VK_CHECK(vk.waitForFences(device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
799}
800
801de::MovePtr<tcu::TextureLevel> CopiesAndBlittingTestInstance::readImage	(vk::VkImage		image,
802																		 const ImageParms&	parms,
803																		 const deUint32		mipLevel)
804{
805	const tcu::TextureFormat		imageFormat	= mapVkFormat(parms.format);
806	de::MovePtr<tcu::TextureLevel>	resultLevel	(new tcu::TextureLevel(imageFormat, parms.extent.width >> mipLevel, parms.extent.height >> mipLevel, parms.extent.depth));
807
808	if (tcu::isCombinedDepthStencilType(imageFormat.type))
809	{
810		if (tcu::hasDepthComponent(imageFormat.order))
811		{
812			tcu::TextureLevel	depthTexture	(mapCombinedToDepthTransferFormat(imageFormat), parms.extent.width, parms.extent.height, parms.extent.depth);
813			readImageAspect(image, depthTexture.getAccess(), parms);
814			tcu::copy(tcu::getEffectiveDepthStencilAccess(resultLevel->getAccess(), tcu::Sampler::MODE_DEPTH), depthTexture.getAccess());
815		}
816
817		if (tcu::hasStencilComponent(imageFormat.order))
818		{
819			tcu::TextureLevel	stencilTexture	(tcu::getEffectiveDepthStencilTextureFormat(imageFormat, tcu::Sampler::MODE_STENCIL), parms.extent.width, parms.extent.height, parms.extent.depth);
820			readImageAspect(image, stencilTexture.getAccess(), parms);
821			tcu::copy(tcu::getEffectiveDepthStencilAccess(resultLevel->getAccess(), tcu::Sampler::MODE_STENCIL), stencilTexture.getAccess());
822		}
823	}
824	else
825		readImageAspect(image, resultLevel->getAccess(), parms, mipLevel);
826
827	return resultLevel;
828}
829
830// Copy from image to image.
831
832class CopyImageToImage : public CopiesAndBlittingTestInstance
833{
834public:
835										CopyImageToImage			(Context&	context,
836																	 TestParams params);
837	virtual tcu::TestStatus				iterate						(void);
838
839protected:
840	virtual tcu::TestStatus				checkTestResult				(tcu::ConstPixelBufferAccess result = tcu::ConstPixelBufferAccess());
841
842private:
843	Move<VkImage>						m_source;
844	de::MovePtr<Allocation>				m_sourceImageAlloc;
845	Move<VkImage>						m_destination;
846	de::MovePtr<Allocation>				m_destinationImageAlloc;
847
848	virtual void						copyRegionToTextureLevel	(tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region);
849};
850
851CopyImageToImage::CopyImageToImage (Context& context, TestParams params)
852	: CopiesAndBlittingTestInstance(context, params)
853{
854	const InstanceInterface&	vki					= context.getInstanceInterface();
855	const DeviceInterface&		vk					= context.getDeviceInterface();
856	const VkPhysicalDevice		vkPhysDevice		= context.getPhysicalDevice();
857	const VkDevice				vkDevice			= context.getDevice();
858	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
859	Allocator&					memAlloc			= context.getDefaultAllocator();
860
861	if ((m_params.dst.image.imageType == VK_IMAGE_TYPE_3D && m_params.src.image.imageType == VK_IMAGE_TYPE_2D) ||
862		(m_params.dst.image.imageType == VK_IMAGE_TYPE_2D && m_params.src.image.imageType == VK_IMAGE_TYPE_3D))
863	{
864		if (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1"))
865			TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
866	}
867
868	VkImageFormatProperties properties;
869	if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(),
870																				m_params.src.image.format,
871																				m_params.src.image.imageType,
872																				VK_IMAGE_TILING_OPTIMAL,
873																				VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
874																				0,
875																				&properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) ||
876		(context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(),
877																				m_params.dst.image.format,
878																				m_params.dst.image.imageType,
879																				VK_IMAGE_TILING_OPTIMAL,
880																				VK_IMAGE_USAGE_TRANSFER_DST_BIT,
881																				0,
882																				&properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
883	{
884		TCU_THROW(NotSupportedError, "Format not supported");
885	}
886
887	// Create source image
888	{
889		const VkImageCreateInfo	sourceImageParams		=
890		{
891			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
892			DE_NULL,								// const void*			pNext;
893			0u,										// VkImageCreateFlags	flags;
894			m_params.src.image.imageType,			// VkImageType			imageType;
895			m_params.src.image.format,				// VkFormat				format;
896			getExtent3D(m_params.src.image),		// VkExtent3D			extent;
897			1u,										// deUint32				mipLevels;
898			getArraySize(m_params.src.image),		// deUint32				arraySize;
899			VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
900			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
901			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
902				VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
903			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
904			1u,										// deUint32				queueFamilyCount;
905			&queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
906			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
907		};
908
909		m_source				= createImage(vk, vkDevice, &sourceImageParams);
910		m_sourceImageAlloc		= allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
911		VK_CHECK(vk.bindImageMemory(vkDevice, *m_source, m_sourceImageAlloc->getMemory(), m_sourceImageAlloc->getOffset()));
912	}
913
914	// Create destination image
915	{
916		const VkImageCreateInfo	destinationImageParams	=
917		{
918			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
919			DE_NULL,								// const void*			pNext;
920			0u,										// VkImageCreateFlags	flags;
921			m_params.dst.image.imageType,			// VkImageType			imageType;
922			m_params.dst.image.format,				// VkFormat				format;
923			getExtent3D(m_params.dst.image),		// VkExtent3D			extent;
924			1u,										// deUint32				mipLevels;
925			getArraySize(m_params.dst.image),		// deUint32				arraySize;
926			VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
927			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
928			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
929				VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
930			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
931			1u,										// deUint32				queueFamilyCount;
932			&queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
933			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
934		};
935
936		m_destination			= createImage(vk, vkDevice, &destinationImageParams);
937		m_destinationImageAlloc	= allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
938		VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset()));
939	}
940}
941
942tcu::TestStatus CopyImageToImage::iterate (void)
943{
944	const tcu::TextureFormat	srcTcuFormat		= mapVkFormat(m_params.src.image.format);
945	const tcu::TextureFormat	dstTcuFormat		= mapVkFormat(m_params.dst.image.format);
946
947	m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(srcTcuFormat,
948																				(int)m_params.src.image.extent.width,
949																				(int)m_params.src.image.extent.height,
950																				(int)m_params.src.image.extent.depth));
951	generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.src.image.extent.depth, FILL_MODE_RED);
952	m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dstTcuFormat,
953																				(int)m_params.dst.image.extent.width,
954																				(int)m_params.dst.image.extent.height,
955																				(int)m_params.dst.image.extent.depth));
956	generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth, FILL_MODE_GRADIENT);
957	generateExpectedResult();
958
959	uploadImage(m_sourceTextureLevel->getAccess(), m_source.get(), m_params.src.image);
960	uploadImage(m_destinationTextureLevel->getAccess(), m_destination.get(), m_params.dst.image);
961
962	const DeviceInterface&		vk					= m_context.getDeviceInterface();
963	const VkDevice				vkDevice			= m_context.getDevice();
964	const VkQueue				queue				= m_context.getUniversalQueue();
965
966	std::vector<VkImageCopy>	imageCopies;
967	for (deUint32 i = 0; i < m_params.regions.size(); i++)
968	{
969		const VkImageCopy& ic = m_params.regions[i].imageCopy;
970		imageCopies.push_back(ic);
971	}
972
973	const VkImageMemoryBarrier	imageBarriers[]		=
974	{
975		// source image
976		{
977			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
978			DE_NULL,									// const void*				pNext;
979			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
980			VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
981			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
982			m_params.src.image.operationLayout,			// VkImageLayout			newLayout;
983			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
984			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
985			m_source.get(),								// VkImage					image;
986			{											// VkImageSubresourceRange	subresourceRange;
987				getAspectFlags(srcTcuFormat),	// VkImageAspectFlags	aspectMask;
988				0u,								// deUint32				baseMipLevel;
989				1u,								// deUint32				mipLevels;
990				0u,								// deUint32				baseArraySlice;
991				getArraySize(m_params.src.image)// deUint32				arraySize;
992			}
993		},
994		// destination image
995		{
996			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
997			DE_NULL,									// const void*				pNext;
998			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
999			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
1000			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
1001			m_params.dst.image.operationLayout,			// VkImageLayout			newLayout;
1002			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1003			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
1004			m_destination.get(),						// VkImage					image;
1005			{											// VkImageSubresourceRange	subresourceRange;
1006				getAspectFlags(dstTcuFormat),	// VkImageAspectFlags	aspectMask;
1007				0u,								// deUint32				baseMipLevel;
1008				1u,								// deUint32				mipLevels;
1009				0u,								// deUint32				baseArraySlice;
1010				getArraySize(m_params.dst.image)// deUint32				arraySize;
1011			}
1012		},
1013	};
1014
1015	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
1016	{
1017		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
1018		DE_NULL,												// const void*						pNext;
1019		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
1020		(const VkCommandBufferInheritanceInfo*)DE_NULL,
1021	};
1022
1023	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1024	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
1025	vk.cmdCopyImage(*m_cmdBuffer, m_source.get(), m_params.src.image.operationLayout, m_destination.get(), m_params.dst.image.operationLayout, (deUint32)imageCopies.size(), imageCopies.data());
1026	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1027
1028	submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer);
1029
1030	de::MovePtr<tcu::TextureLevel>	resultTextureLevel	= readImage(*m_destination, m_params.dst.image);
1031
1032	return checkTestResult(resultTextureLevel->getAccess());
1033}
1034
1035tcu::TestStatus CopyImageToImage::checkTestResult (tcu::ConstPixelBufferAccess result)
1036{
1037	const tcu::Vec4	fThreshold (0.0f);
1038	const tcu::UVec4 uThreshold (0u);
1039
1040	if (tcu::isCombinedDepthStencilType(result.getFormat().type))
1041	{
1042		if (tcu::hasDepthComponent(result.getFormat().order))
1043		{
1044			const tcu::Sampler::DepthStencilMode	mode				= tcu::Sampler::MODE_DEPTH;
1045			const tcu::ConstPixelBufferAccess		depthResult			= tcu::getEffectiveDepthStencilAccess(result, mode);
1046			const tcu::ConstPixelBufferAccess		expectedResult		= tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[0]->getAccess(), mode);
1047
1048			if (isFloatFormat(result.getFormat()))
1049			{
1050				if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, depthResult, fThreshold, tcu::COMPARE_LOG_RESULT))
1051					return tcu::TestStatus::fail("CopiesAndBlitting test");
1052			}
1053			else
1054			{
1055				if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, depthResult, uThreshold, tcu::COMPARE_LOG_RESULT))
1056					return tcu::TestStatus::fail("CopiesAndBlitting test");
1057			}
1058		}
1059
1060		if (tcu::hasStencilComponent(result.getFormat().order))
1061		{
1062			const tcu::Sampler::DepthStencilMode	mode				= tcu::Sampler::MODE_STENCIL;
1063			const tcu::ConstPixelBufferAccess		stencilResult		= tcu::getEffectiveDepthStencilAccess(result, mode);
1064			const tcu::ConstPixelBufferAccess		expectedResult		= tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[0]->getAccess(), mode);
1065
1066			if (isFloatFormat(result.getFormat()))
1067			{
1068				if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, stencilResult, fThreshold, tcu::COMPARE_LOG_RESULT))
1069					return tcu::TestStatus::fail("CopiesAndBlitting test");
1070			}
1071			else
1072			{
1073				if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, stencilResult, uThreshold, tcu::COMPARE_LOG_RESULT))
1074					return tcu::TestStatus::fail("CopiesAndBlitting test");
1075			}
1076		}
1077	}
1078	else
1079	{
1080		if (isFloatFormat(result.getFormat()))
1081		{
1082			if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", m_expectedTextureLevel[0]->getAccess(), result, fThreshold, tcu::COMPARE_LOG_RESULT))
1083				return tcu::TestStatus::fail("CopiesAndBlitting test");
1084		}
1085		else if (isSnormFormat(mapTextureFormat(result.getFormat())))
1086		{
1087			// There may be an ambiguity between two possible binary representations of 1.0.
1088			// Get rid of that by expanding the data to floats and re-normalizing again.
1089
1090			tcu::TextureLevel resultSnorm	(result.getFormat(), result.getWidth(), result.getHeight(), result.getDepth());
1091			{
1092				tcu::TextureLevel resultFloat	(tcu::TextureFormat(resultSnorm.getFormat().order, tcu::TextureFormat::FLOAT), resultSnorm.getWidth(), resultSnorm.getHeight(), resultSnorm.getDepth());
1093
1094				tcu::copy(resultFloat.getAccess(), result);
1095				tcu::copy(resultSnorm, resultFloat.getAccess());
1096			}
1097
1098			tcu::TextureLevel expectedSnorm	(m_expectedTextureLevel[0]->getFormat(), m_expectedTextureLevel[0]->getWidth(), m_expectedTextureLevel[0]->getHeight(), m_expectedTextureLevel[0]->getDepth());
1099
1100			{
1101				tcu::TextureLevel expectedFloat	(tcu::TextureFormat(expectedSnorm.getFormat().order, tcu::TextureFormat::FLOAT), expectedSnorm.getWidth(), expectedSnorm.getHeight(), expectedSnorm.getDepth());
1102
1103				tcu::copy(expectedFloat.getAccess(), m_expectedTextureLevel[0]->getAccess());
1104				tcu::copy(expectedSnorm, expectedFloat.getAccess());
1105			}
1106
1107			if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedSnorm.getAccess(), resultSnorm.getAccess(), uThreshold, tcu::COMPARE_LOG_RESULT))
1108				return tcu::TestStatus::fail("CopiesAndBlitting test");
1109		}
1110		else
1111		{
1112			if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", m_expectedTextureLevel[0]->getAccess(), result, uThreshold, tcu::COMPARE_LOG_RESULT))
1113				return tcu::TestStatus::fail("CopiesAndBlitting test");
1114		}
1115	}
1116
1117	return tcu::TestStatus::pass("CopiesAndBlitting test");
1118}
1119
1120void CopyImageToImage::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region)
1121{
1122	VkOffset3D	srcOffset	= region.imageCopy.srcOffset;
1123	VkOffset3D	dstOffset	= region.imageCopy.dstOffset;
1124	VkExtent3D	extent		= region.imageCopy.extent;
1125
1126	if (m_params.src.image.imageType == VK_IMAGE_TYPE_3D && m_params.dst.image.imageType == VK_IMAGE_TYPE_2D)
1127	{
1128		dstOffset.z = srcOffset.z;
1129		extent.depth = std::max(region.imageCopy.extent.depth, region.imageCopy.dstSubresource.layerCount);
1130	}
1131	if (m_params.src.image.imageType == VK_IMAGE_TYPE_2D && m_params.dst.image.imageType == VK_IMAGE_TYPE_3D)
1132	{
1133		srcOffset.z = dstOffset.z;
1134		extent.depth = std::max(region.imageCopy.extent.depth, region.imageCopy.srcSubresource.layerCount);
1135	}
1136
1137
1138	if (tcu::isCombinedDepthStencilType(src.getFormat().type))
1139	{
1140		DE_ASSERT(src.getFormat() == dst.getFormat());
1141
1142		// Copy depth.
1143		if (tcu::hasDepthComponent(src.getFormat().order))
1144		{
1145			const tcu::ConstPixelBufferAccess	srcSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_DEPTH);
1146			const tcu::PixelBufferAccess		dstSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_DEPTH);
1147			tcu::copy(dstSubRegion, srcSubRegion);
1148		}
1149
1150		// Copy stencil.
1151		if (tcu::hasStencilComponent(src.getFormat().order))
1152		{
1153			const tcu::ConstPixelBufferAccess	srcSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_STENCIL);
1154			const tcu::PixelBufferAccess		dstSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth), tcu::Sampler::MODE_STENCIL);
1155			tcu::copy(dstSubRegion, srcSubRegion);
1156		}
1157	}
1158	else
1159	{
1160		const tcu::ConstPixelBufferAccess	srcSubRegion		= tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth);
1161		// CopyImage acts like a memcpy. Replace the destination format with the srcformat to use a memcpy.
1162		const tcu::PixelBufferAccess		dstWithSrcFormat	(srcSubRegion.getFormat(), dst.getSize(), dst.getDataPtr());
1163		const tcu::PixelBufferAccess		dstSubRegion		= tcu::getSubregion(dstWithSrcFormat, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth);
1164
1165		tcu::copy(dstSubRegion, srcSubRegion);
1166	}
1167}
1168
1169class CopyImageToImageTestCase : public vkt::TestCase
1170{
1171public:
1172							CopyImageToImageTestCase	(tcu::TestContext&				testCtx,
1173														 const std::string&				name,
1174														 const std::string&				description,
1175														 const TestParams				params)
1176								: vkt::TestCase	(testCtx, name, description)
1177								, m_params		(params)
1178							{}
1179
1180	virtual TestInstance*	createInstance				(Context&						context) const
1181							{
1182								return new CopyImageToImage(context, m_params);
1183							}
1184private:
1185	TestParams				m_params;
1186};
1187
1188// Copy from buffer to buffer.
1189
1190class CopyBufferToBuffer : public CopiesAndBlittingTestInstance
1191{
1192public:
1193								CopyBufferToBuffer			(Context& context, TestParams params);
1194	virtual tcu::TestStatus		iterate						(void);
1195private:
1196	virtual void				copyRegionToTextureLevel	(tcu::ConstPixelBufferAccess, tcu::PixelBufferAccess, CopyRegion);
1197	Move<VkBuffer>				m_source;
1198	de::MovePtr<Allocation>		m_sourceBufferAlloc;
1199	Move<VkBuffer>				m_destination;
1200	de::MovePtr<Allocation>		m_destinationBufferAlloc;
1201};
1202
1203CopyBufferToBuffer::CopyBufferToBuffer (Context& context, TestParams params)
1204	: CopiesAndBlittingTestInstance	(context, params)
1205{
1206	const InstanceInterface&	vki					= context.getInstanceInterface();
1207	const DeviceInterface&		vk					= context.getDeviceInterface();
1208	const VkPhysicalDevice		vkPhysDevice		= context.getPhysicalDevice();
1209	const VkDevice				vkDevice			= context.getDevice();
1210	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1211	Allocator&					memAlloc			= context.getDefaultAllocator();
1212
1213	// Create source buffer
1214	{
1215		const VkBufferCreateInfo	sourceBufferParams		=
1216		{
1217			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1218			DE_NULL,									// const void*			pNext;
1219			0u,											// VkBufferCreateFlags	flags;
1220			m_params.src.buffer.size,					// VkDeviceSize			size;
1221			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
1222			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1223			1u,											// deUint32				queueFamilyIndexCount;
1224			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
1225		};
1226
1227		m_source				= createBuffer(vk, vkDevice, &sourceBufferParams);
1228		m_sourceBufferAlloc		= allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind);
1229		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_source, m_sourceBufferAlloc->getMemory(), m_sourceBufferAlloc->getOffset()));
1230	}
1231
1232	// Create destination buffer
1233	{
1234		const VkBufferCreateInfo	destinationBufferParams	=
1235		{
1236			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1237			DE_NULL,									// const void*			pNext;
1238			0u,											// VkBufferCreateFlags	flags;
1239			m_params.dst.buffer.size,					// VkDeviceSize			size;
1240			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
1241			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1242			1u,											// deUint32				queueFamilyIndexCount;
1243			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
1244		};
1245
1246		m_destination				= createBuffer(vk, vkDevice, &destinationBufferParams);
1247		m_destinationBufferAlloc	= allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind);
1248		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_destination, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset()));
1249	}
1250}
1251
1252tcu::TestStatus CopyBufferToBuffer::iterate (void)
1253{
1254	const int srcLevelWidth		= (int)(m_params.src.buffer.size/4); // Here the format is VK_FORMAT_R32_UINT, we need to divide the buffer size by 4
1255	m_sourceTextureLevel		= de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R32_UINT), srcLevelWidth, 1));
1256	generateBuffer(m_sourceTextureLevel->getAccess(), srcLevelWidth, 1, 1, FILL_MODE_RED);
1257
1258	const int dstLevelWidth		= (int)(m_params.dst.buffer.size/4);
1259	m_destinationTextureLevel	= de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R32_UINT), dstLevelWidth, 1));
1260	generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1, FILL_MODE_WHITE);
1261
1262	generateExpectedResult();
1263
1264	uploadBuffer(m_sourceTextureLevel->getAccess(), *m_sourceBufferAlloc);
1265	uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
1266
1267	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1268	const VkDevice				vkDevice	= m_context.getDevice();
1269	const VkQueue				queue		= m_context.getUniversalQueue();
1270
1271	const VkBufferMemoryBarrier		srcBufferBarrier	=
1272	{
1273		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1274		DE_NULL,									// const void*		pNext;
1275		VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
1276		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
1277		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1278		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1279		*m_source,									// VkBuffer			buffer;
1280		0u,											// VkDeviceSize		offset;
1281		m_params.src.buffer.size					// VkDeviceSize		size;
1282	};
1283
1284	const VkBufferMemoryBarrier		dstBufferBarrier	=
1285	{
1286		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1287		DE_NULL,									// const void*		pNext;
1288		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
1289		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
1290		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1291		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1292		*m_destination,								// VkBuffer			buffer;
1293		0u,											// VkDeviceSize		offset;
1294		m_params.dst.buffer.size					// VkDeviceSize		size;
1295	};
1296
1297	std::vector<VkBufferCopy>		bufferCopies;
1298	for (deUint32 i = 0; i < m_params.regions.size(); i++)
1299		bufferCopies.push_back(m_params.regions[i].bufferCopy);
1300
1301	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
1302	{
1303		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
1304		DE_NULL,												// const void*						pNext;
1305		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
1306		(const VkCommandBufferInheritanceInfo*)DE_NULL,
1307	};
1308
1309	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1310	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &srcBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1311	vk.cmdCopyBuffer(*m_cmdBuffer, m_source.get(), m_destination.get(), (deUint32)m_params.regions.size(), &bufferCopies[0]);
1312	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1313	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1314	submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer);
1315
1316
1317
1318	// Read buffer data
1319	de::MovePtr<tcu::TextureLevel>	resultLevel		(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R32_UINT), dstLevelWidth, 1));
1320	invalidateMappedMemoryRange(vk, vkDevice, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset(), m_params.dst.buffer.size);
1321	tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr()));
1322
1323	return checkTestResult(resultLevel->getAccess());
1324}
1325
1326void CopyBufferToBuffer::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region)
1327{
1328	deMemcpy((deUint8*) dst.getDataPtr() + region.bufferCopy.dstOffset,
1329			 (deUint8*) src.getDataPtr() + region.bufferCopy.srcOffset,
1330			 (size_t)region.bufferCopy.size);
1331}
1332
1333class BufferToBufferTestCase : public vkt::TestCase
1334{
1335public:
1336							BufferToBufferTestCase	(tcu::TestContext&	testCtx,
1337													 const std::string&	name,
1338													 const std::string&	description,
1339													 const TestParams	params)
1340								: vkt::TestCase	(testCtx, name, description)
1341								, m_params		(params)
1342							{}
1343
1344	virtual TestInstance*	createInstance			(Context& context) const
1345							{
1346								return new CopyBufferToBuffer(context, m_params);
1347							}
1348private:
1349	TestParams				m_params;
1350};
1351
1352// Copy from image to buffer.
1353
1354class CopyImageToBuffer : public CopiesAndBlittingTestInstance
1355{
1356public:
1357								CopyImageToBuffer			(Context&	context,
1358															 TestParams	testParams);
1359	virtual tcu::TestStatus		iterate						(void);
1360private:
1361	virtual void				copyRegionToTextureLevel	(tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region);
1362
1363	tcu::TextureFormat			m_textureFormat;
1364	VkDeviceSize				m_bufferSize;
1365
1366	Move<VkImage>				m_source;
1367	de::MovePtr<Allocation>		m_sourceImageAlloc;
1368	Move<VkBuffer>				m_destination;
1369	de::MovePtr<Allocation>		m_destinationBufferAlloc;
1370};
1371
1372CopyImageToBuffer::CopyImageToBuffer (Context& context, TestParams testParams)
1373	: CopiesAndBlittingTestInstance(context, testParams)
1374	, m_textureFormat(mapVkFormat(testParams.src.image.format))
1375	, m_bufferSize(m_params.dst.buffer.size * tcu::getPixelSize(m_textureFormat))
1376{
1377	const InstanceInterface&	vki					= context.getInstanceInterface();
1378	const DeviceInterface&		vk					= context.getDeviceInterface();
1379	const VkPhysicalDevice		vkPhysDevice		= context.getPhysicalDevice();
1380	const VkDevice				vkDevice			= context.getDevice();
1381	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1382	Allocator&					memAlloc			= context.getDefaultAllocator();
1383
1384	// Create source image
1385	{
1386		const VkImageCreateInfo		sourceImageParams		=
1387		{
1388			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
1389			DE_NULL,								// const void*			pNext;
1390			0u,										// VkImageCreateFlags	flags;
1391			m_params.src.image.imageType,			// VkImageType			imageType;
1392			m_params.src.image.format,				// VkFormat				format;
1393			getExtent3D(m_params.src.image),		// VkExtent3D			extent;
1394			1u,										// deUint32				mipLevels;
1395			getArraySize(m_params.src.image),		// deUint32				arraySize;
1396			VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
1397			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
1398			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1399				VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
1400			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1401			1u,										// deUint32				queueFamilyCount;
1402			&queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
1403			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
1404		};
1405
1406		m_source			= createImage(vk, vkDevice, &sourceImageParams);
1407		m_sourceImageAlloc	= allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
1408		VK_CHECK(vk.bindImageMemory(vkDevice, *m_source, m_sourceImageAlloc->getMemory(), m_sourceImageAlloc->getOffset()));
1409	}
1410
1411	// Create destination buffer
1412	{
1413		const VkBufferCreateInfo	destinationBufferParams	=
1414		{
1415			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1416			DE_NULL,									// const void*			pNext;
1417			0u,											// VkBufferCreateFlags	flags;
1418			m_bufferSize,								// VkDeviceSize			size;
1419			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
1420			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1421			1u,											// deUint32				queueFamilyIndexCount;
1422			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
1423		};
1424
1425		m_destination				= createBuffer(vk, vkDevice, &destinationBufferParams);
1426		m_destinationBufferAlloc	= allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind);
1427		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_destination, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset()));
1428	}
1429}
1430
1431tcu::TestStatus CopyImageToBuffer::iterate (void)
1432{
1433	m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat,
1434																				m_params.src.image.extent.width,
1435																				m_params.src.image.extent.height,
1436																				m_params.src.image.extent.depth));
1437	generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.src.image.extent.depth);
1438	m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat, (int)m_params.dst.buffer.size, 1));
1439	generateBuffer(m_destinationTextureLevel->getAccess(), (int)m_params.dst.buffer.size, 1, 1);
1440
1441	generateExpectedResult();
1442
1443	uploadImage(m_sourceTextureLevel->getAccess(), *m_source, m_params.src.image);
1444	uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
1445
1446	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1447	const VkDevice				vkDevice	= m_context.getDevice();
1448	const VkQueue				queue		= m_context.getUniversalQueue();
1449
1450	// Barriers for copying image to buffer
1451	const VkImageMemoryBarrier		imageBarrier		=
1452	{
1453		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1454		DE_NULL,									// const void*				pNext;
1455		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
1456		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
1457		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
1458		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
1459		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1460		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
1461		*m_source,									// VkImage					image;
1462		{											// VkImageSubresourceRange	subresourceRange;
1463			getAspectFlags(m_textureFormat),	// VkImageAspectFlags	aspectMask;
1464			0u,								// deUint32				baseMipLevel;
1465			1u,								// deUint32				mipLevels;
1466			0u,								// deUint32				baseArraySlice;
1467			1u								// deUint32				arraySize;
1468		}
1469	};
1470
1471	const VkBufferMemoryBarrier		bufferBarrier		=
1472	{
1473		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1474		DE_NULL,									// const void*		pNext;
1475		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
1476		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
1477		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1478		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1479		*m_destination,								// VkBuffer			buffer;
1480		0u,											// VkDeviceSize		offset;
1481		m_bufferSize								// VkDeviceSize		size;
1482	};
1483
1484	// Copy from image to buffer
1485	std::vector<VkBufferImageCopy>	bufferImageCopies;
1486	for (deUint32 i = 0; i < m_params.regions.size(); i++)
1487		bufferImageCopies.push_back(m_params.regions[i].bufferImageCopy);
1488
1489	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
1490	{
1491		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
1492		DE_NULL,												// const void*						pNext;
1493		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
1494		(const VkCommandBufferInheritanceInfo*)DE_NULL,
1495	};
1496
1497	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1498	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
1499	vk.cmdCopyImageToBuffer(*m_cmdBuffer, m_source.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_destination.get(), (deUint32)m_params.regions.size(), &bufferImageCopies[0]);
1500	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1501	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1502
1503	submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer);
1504
1505	// Read buffer data
1506	de::MovePtr<tcu::TextureLevel>	resultLevel		(new tcu::TextureLevel(m_textureFormat, (int)m_params.dst.buffer.size, 1));
1507	invalidateMappedMemoryRange(vk, vkDevice, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset(), m_bufferSize);
1508	tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr()));
1509
1510	return checkTestResult(resultLevel->getAccess());
1511}
1512
1513class CopyImageToBufferTestCase : public vkt::TestCase
1514{
1515public:
1516							CopyImageToBufferTestCase	(tcu::TestContext&		testCtx,
1517														 const std::string&		name,
1518														 const std::string&		description,
1519														 const TestParams		params)
1520								: vkt::TestCase	(testCtx, name, description)
1521								, m_params		(params)
1522							{}
1523
1524	virtual TestInstance*	createInstance				(Context&				context) const
1525							{
1526								return new CopyImageToBuffer(context, m_params);
1527							}
1528private:
1529	TestParams				m_params;
1530};
1531
1532void CopyImageToBuffer::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region)
1533{
1534	deUint32			rowLength	= region.bufferImageCopy.bufferRowLength;
1535	if (!rowLength)
1536		rowLength = region.bufferImageCopy.imageExtent.width;
1537
1538	deUint32			imageHeight	= region.bufferImageCopy.bufferImageHeight;
1539	if (!imageHeight)
1540		imageHeight = region.bufferImageCopy.imageExtent.height;
1541
1542	const int			texelSize	= src.getFormat().getPixelSize();
1543	const VkExtent3D	extent		= region.bufferImageCopy.imageExtent;
1544	const VkOffset3D	srcOffset	= region.bufferImageCopy.imageOffset;
1545	const int			texelOffset	= (int) region.bufferImageCopy.bufferOffset / texelSize;
1546
1547	for (deUint32 z = 0; z < extent.depth; z++)
1548	{
1549		for (deUint32 y = 0; y < extent.height; y++)
1550		{
1551			int									texelIndex		= texelOffset + (z * imageHeight + y) *	rowLength;
1552			const tcu::ConstPixelBufferAccess	srcSubRegion	= tcu::getSubregion(src, srcOffset.x, srcOffset.y + y, srcOffset.z + z,
1553																					region.bufferImageCopy.imageExtent.width, 1, 1);
1554			const tcu::PixelBufferAccess		dstSubRegion	= tcu::getSubregion(dst, texelIndex, 0, region.bufferImageCopy.imageExtent.width, 1);
1555			tcu::copy(dstSubRegion, srcSubRegion);
1556		}
1557	}
1558}
1559
1560// Copy from buffer to image.
1561
1562class CopyBufferToImage : public CopiesAndBlittingTestInstance
1563{
1564public:
1565								CopyBufferToImage			(Context&	context,
1566															 TestParams	testParams);
1567	virtual tcu::TestStatus		iterate						(void);
1568private:
1569	virtual void				copyRegionToTextureLevel	(tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region);
1570
1571	tcu::TextureFormat			m_textureFormat;
1572	VkDeviceSize				m_bufferSize;
1573
1574	Move<VkBuffer>				m_source;
1575	de::MovePtr<Allocation>		m_sourceBufferAlloc;
1576	Move<VkImage>				m_destination;
1577	de::MovePtr<Allocation>		m_destinationImageAlloc;
1578};
1579
1580CopyBufferToImage::CopyBufferToImage (Context& context, TestParams testParams)
1581	: CopiesAndBlittingTestInstance(context, testParams)
1582	, m_textureFormat(mapVkFormat(testParams.dst.image.format))
1583	, m_bufferSize(m_params.src.buffer.size * tcu::getPixelSize(m_textureFormat))
1584{
1585	const InstanceInterface&	vki					= context.getInstanceInterface();
1586	const DeviceInterface&		vk					= context.getDeviceInterface();
1587	const VkPhysicalDevice		vkPhysDevice		= context.getPhysicalDevice();
1588	const VkDevice				vkDevice			= context.getDevice();
1589	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1590	Allocator&					memAlloc			= context.getDefaultAllocator();
1591
1592	// Create source buffer
1593	{
1594		const VkBufferCreateInfo	sourceBufferParams		=
1595		{
1596			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1597			DE_NULL,									// const void*			pNext;
1598			0u,											// VkBufferCreateFlags	flags;
1599			m_bufferSize,								// VkDeviceSize			size;
1600			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
1601			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1602			1u,											// deUint32				queueFamilyIndexCount;
1603			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
1604		};
1605
1606		m_source				= createBuffer(vk, vkDevice, &sourceBufferParams);
1607		m_sourceBufferAlloc		= allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind);
1608		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_source, m_sourceBufferAlloc->getMemory(), m_sourceBufferAlloc->getOffset()));
1609	}
1610
1611	// Create destination image
1612	{
1613		const VkImageCreateInfo		destinationImageParams	=
1614		{
1615			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
1616			DE_NULL,								// const void*			pNext;
1617			0u,										// VkImageCreateFlags	flags;
1618			m_params.dst.image.imageType,			// VkImageType			imageType;
1619			m_params.dst.image.format,				// VkFormat				format;
1620			getExtent3D(m_params.dst.image),		// VkExtent3D			extent;
1621			1u,										// deUint32				mipLevels;
1622			getArraySize(m_params.dst.image),		// deUint32				arraySize;
1623			VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
1624			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
1625			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1626				VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
1627			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1628			1u,										// deUint32				queueFamilyCount;
1629			&queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
1630			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
1631		};
1632
1633		m_destination			= createImage(vk, vkDevice, &destinationImageParams);
1634		m_destinationImageAlloc	= allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
1635		VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset()));
1636	}
1637}
1638
1639tcu::TestStatus CopyBufferToImage::iterate (void)
1640{
1641	m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat, (int)m_params.src.buffer.size, 1));
1642	generateBuffer(m_sourceTextureLevel->getAccess(), (int)m_params.src.buffer.size, 1, 1);
1643	m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(m_textureFormat,
1644																					m_params.dst.image.extent.width,
1645																					m_params.dst.image.extent.height,
1646																					m_params.dst.image.extent.depth));
1647
1648	generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth);
1649
1650	generateExpectedResult();
1651
1652	uploadBuffer(m_sourceTextureLevel->getAccess(), *m_sourceBufferAlloc);
1653	uploadImage(m_destinationTextureLevel->getAccess(), *m_destination, m_params.dst.image);
1654
1655	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1656	const VkDevice				vkDevice	= m_context.getDevice();
1657	const VkQueue				queue		= m_context.getUniversalQueue();
1658
1659	const VkImageMemoryBarrier	imageBarrier	=
1660	{
1661		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1662		DE_NULL,									// const void*				pNext;
1663		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
1664		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
1665		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
1666		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			newLayout;
1667		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1668		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
1669		*m_destination,								// VkImage					image;
1670		{											// VkImageSubresourceRange	subresourceRange;
1671			getAspectFlags(m_textureFormat),	// VkImageAspectFlags	aspectMask;
1672			0u,								// deUint32				baseMipLevel;
1673			1u,								// deUint32				mipLevels;
1674			0u,								// deUint32				baseArraySlice;
1675			1u								// deUint32				arraySize;
1676		}
1677	};
1678
1679	// Copy from buffer to image
1680	std::vector<VkBufferImageCopy>		bufferImageCopies;
1681	for (deUint32 i = 0; i < m_params.regions.size(); i++)
1682		bufferImageCopies.push_back(m_params.regions[i].bufferImageCopy);
1683
1684	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
1685	{
1686		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
1687		DE_NULL,												// const void*						pNext;
1688		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
1689		(const VkCommandBufferInheritanceInfo*)DE_NULL,
1690	};
1691
1692	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1693	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
1694	vk.cmdCopyBufferToImage(*m_cmdBuffer, m_source.get(), m_destination.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)m_params.regions.size(), bufferImageCopies.data());
1695	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1696
1697	submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer);
1698
1699	de::MovePtr<tcu::TextureLevel>	resultLevel	= readImage(*m_destination, m_params.dst.image);
1700
1701	return checkTestResult(resultLevel->getAccess());
1702}
1703
1704class CopyBufferToImageTestCase : public vkt::TestCase
1705{
1706public:
1707							CopyBufferToImageTestCase	(tcu::TestContext&		testCtx,
1708														 const std::string&		name,
1709														 const std::string&		description,
1710														 const TestParams		params)
1711								: vkt::TestCase	(testCtx, name, description)
1712								, m_params		(params)
1713							{}
1714
1715	virtual					~CopyBufferToImageTestCase	(void) {}
1716
1717	virtual TestInstance*	createInstance				(Context&				context) const
1718							{
1719								return new CopyBufferToImage(context, m_params);
1720							}
1721private:
1722	TestParams				m_params;
1723};
1724
1725void CopyBufferToImage::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region)
1726{
1727	deUint32			rowLength	= region.bufferImageCopy.bufferRowLength;
1728	if (!rowLength)
1729		rowLength = region.bufferImageCopy.imageExtent.width;
1730
1731	deUint32			imageHeight	= region.bufferImageCopy.bufferImageHeight;
1732	if (!imageHeight)
1733		imageHeight = region.bufferImageCopy.imageExtent.height;
1734
1735	const int			texelSize	= dst.getFormat().getPixelSize();
1736	const VkExtent3D	extent		= region.bufferImageCopy.imageExtent;
1737	const VkOffset3D	dstOffset	= region.bufferImageCopy.imageOffset;
1738	const int			texelOffset	= (int) region.bufferImageCopy.bufferOffset / texelSize;
1739
1740	for (deUint32 z = 0; z < extent.depth; z++)
1741	{
1742		for (deUint32 y = 0; y < extent.height; y++)
1743		{
1744			int									texelIndex		= texelOffset + (z * imageHeight + y) *	rowLength;
1745			const tcu::ConstPixelBufferAccess	srcSubRegion	= tcu::getSubregion(src, texelIndex, 0, region.bufferImageCopy.imageExtent.width, 1);
1746			const tcu::PixelBufferAccess		dstSubRegion	= tcu::getSubregion(dst, dstOffset.x, dstOffset.y + y, dstOffset.z + z,
1747																					region.bufferImageCopy.imageExtent.width, 1, 1);
1748			tcu::copy(dstSubRegion, srcSubRegion);
1749		}
1750	}
1751}
1752
1753// Copy from image to image with scaling.
1754
1755class BlittingImages : public CopiesAndBlittingTestInstance
1756{
1757public:
1758										BlittingImages					(Context&	context,
1759																		 TestParams params);
1760	virtual tcu::TestStatus				iterate							(void);
1761protected:
1762	virtual tcu::TestStatus				checkTestResult					(tcu::ConstPixelBufferAccess result);
1763	virtual void						copyRegionToTextureLevel		(tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region);
1764	virtual void						generateExpectedResult			(void);
1765private:
1766	bool								checkLinearFilteredResult		(const tcu::ConstPixelBufferAccess&	result,
1767																		 const tcu::ConstPixelBufferAccess&	clampedReference,
1768																		 const tcu::ConstPixelBufferAccess&	unclampedReference,
1769																		 const tcu::TextureFormat&			sourceFormat);
1770	bool								checkNearestFilteredResult		(const tcu::ConstPixelBufferAccess&	result,
1771																		 const tcu::ConstPixelBufferAccess& source);
1772
1773	Move<VkImage>						m_source;
1774	de::MovePtr<Allocation>				m_sourceImageAlloc;
1775	Move<VkImage>						m_destination;
1776	de::MovePtr<Allocation>				m_destinationImageAlloc;
1777
1778	de::MovePtr<tcu::TextureLevel>		m_unclampedExpectedTextureLevel;
1779};
1780
1781BlittingImages::BlittingImages (Context& context, TestParams params)
1782	: CopiesAndBlittingTestInstance(context, params)
1783{
1784	const InstanceInterface&	vki					= context.getInstanceInterface();
1785	const DeviceInterface&		vk					= context.getDeviceInterface();
1786	const VkPhysicalDevice		vkPhysDevice		= context.getPhysicalDevice();
1787	const VkDevice				vkDevice			= context.getDevice();
1788	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1789	Allocator&					memAlloc			= context.getDefaultAllocator();
1790
1791	VkImageFormatProperties properties;
1792	if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(),
1793																				m_params.src.image.format,
1794																				VK_IMAGE_TYPE_2D,
1795																				VK_IMAGE_TILING_OPTIMAL,
1796																				VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1797																				0,
1798																				&properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) ||
1799		(context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(),
1800																				m_params.dst.image.format,
1801																				VK_IMAGE_TYPE_2D,
1802																				VK_IMAGE_TILING_OPTIMAL,
1803																				VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1804																				0,
1805																				&properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
1806	{
1807		TCU_THROW(NotSupportedError, "Format not supported");
1808	}
1809
1810	VkFormatProperties srcFormatProperties;
1811	context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), m_params.src.image.format, &srcFormatProperties);
1812	if (!(srcFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT))
1813	{
1814		TCU_THROW(NotSupportedError, "Format feature blit source not supported");
1815	}
1816
1817	VkFormatProperties dstFormatProperties;
1818	context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), m_params.dst.image.format, &dstFormatProperties);
1819	if (!(dstFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT))
1820	{
1821		TCU_THROW(NotSupportedError, "Format feature blit destination not supported");
1822	}
1823
1824	if (m_params.filter == VK_FILTER_LINEAR)
1825	{
1826		if (!(srcFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
1827			TCU_THROW(NotSupportedError, "Source format feature sampled image filter linear not supported");
1828		if (!(dstFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
1829			TCU_THROW(NotSupportedError, "Destination format feature sampled image filter linear not supported");
1830	}
1831
1832	// Create source image
1833	{
1834		const VkImageCreateInfo		sourceImageParams		=
1835		{
1836			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
1837			DE_NULL,								// const void*			pNext;
1838			0u,										// VkImageCreateFlags	flags;
1839			m_params.src.image.imageType,			// VkImageType			imageType;
1840			m_params.src.image.format,				// VkFormat				format;
1841			getExtent3D(m_params.src.image),		// VkExtent3D			extent;
1842			1u,										// deUint32				mipLevels;
1843			getArraySize(m_params.src.image),		// deUint32				arraySize;
1844			VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
1845			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
1846			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1847				VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
1848			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1849			1u,										// deUint32				queueFamilyCount;
1850			&queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
1851			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
1852		};
1853
1854		m_source = createImage(vk, vkDevice, &sourceImageParams);
1855		m_sourceImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
1856		VK_CHECK(vk.bindImageMemory(vkDevice, *m_source, m_sourceImageAlloc->getMemory(), m_sourceImageAlloc->getOffset()));
1857	}
1858
1859	// Create destination image
1860	{
1861		const VkImageCreateInfo		destinationImageParams	=
1862		{
1863			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
1864			DE_NULL,								// const void*			pNext;
1865			0u,										// VkImageCreateFlags	flags;
1866			m_params.dst.image.imageType,			// VkImageType			imageType;
1867			m_params.dst.image.format,				// VkFormat				format;
1868			getExtent3D(m_params.dst.image),		// VkExtent3D			extent;
1869			1u,										// deUint32				mipLevels;
1870			getArraySize(m_params.dst.image),		// deUint32				arraySize;
1871			VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
1872			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
1873			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1874				VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
1875			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1876			1u,										// deUint32				queueFamilyCount;
1877			&queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
1878			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
1879		};
1880
1881		m_destination = createImage(vk, vkDevice, &destinationImageParams);
1882		m_destinationImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
1883		VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset()));
1884	}
1885}
1886
1887tcu::TestStatus BlittingImages::iterate (void)
1888{
1889	const tcu::TextureFormat	srcTcuFormat		= mapVkFormat(m_params.src.image.format);
1890	const tcu::TextureFormat	dstTcuFormat		= mapVkFormat(m_params.dst.image.format);
1891	m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(srcTcuFormat,
1892																				m_params.src.image.extent.width,
1893																				m_params.src.image.extent.height,
1894																				m_params.src.image.extent.depth));
1895	generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.src.image.extent.depth, FILL_MODE_GRADIENT);
1896	m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dstTcuFormat,
1897																					 (int)m_params.dst.image.extent.width,
1898																					 (int)m_params.dst.image.extent.height,
1899																					 (int)m_params.dst.image.extent.depth));
1900	generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth, FILL_MODE_WHITE);
1901	generateExpectedResult();
1902
1903	uploadImage(m_sourceTextureLevel->getAccess(), m_source.get(), m_params.src.image);
1904	uploadImage(m_destinationTextureLevel->getAccess(), m_destination.get(), m_params.dst.image);
1905
1906	const DeviceInterface&		vk					= m_context.getDeviceInterface();
1907	const VkDevice				vkDevice			= m_context.getDevice();
1908	const VkQueue				queue				= m_context.getUniversalQueue();
1909
1910	std::vector<VkImageBlit>	regions;
1911	for (deUint32 i = 0; i < m_params.regions.size(); i++)
1912		regions.push_back(m_params.regions[i].imageBlit);
1913
1914	// Barriers for copying image to buffer
1915	const VkImageMemoryBarrier		srcImageBarrier		=
1916	{
1917		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1918		DE_NULL,									// const void*				pNext;
1919		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
1920		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
1921		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
1922		m_params.src.image.operationLayout,			// VkImageLayout			newLayout;
1923		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1924		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
1925		m_source.get(),								// VkImage					image;
1926		{											// VkImageSubresourceRange	subresourceRange;
1927			getAspectFlags(srcTcuFormat),	// VkImageAspectFlags	aspectMask;
1928			0u,								// deUint32				baseMipLevel;
1929			1u,								// deUint32				mipLevels;
1930			0u,								// deUint32				baseArraySlice;
1931			1u								// deUint32				arraySize;
1932		}
1933	};
1934
1935	const VkImageMemoryBarrier		dstImageBarrier		=
1936	{
1937		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1938		DE_NULL,									// const void*				pNext;
1939		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
1940		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
1941		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
1942		m_params.dst.image.operationLayout,			// VkImageLayout			newLayout;
1943		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1944		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
1945		m_destination.get(),						// VkImage					image;
1946		{											// VkImageSubresourceRange	subresourceRange;
1947			getAspectFlags(dstTcuFormat),	// VkImageAspectFlags	aspectMask;
1948			0u,								// deUint32				baseMipLevel;
1949			1u,								// deUint32				mipLevels;
1950			0u,								// deUint32				baseArraySlice;
1951			1u								// deUint32				arraySize;
1952		}
1953	};
1954
1955	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
1956	{
1957		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
1958		DE_NULL,												// const void*						pNext;
1959		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
1960		(const VkCommandBufferInheritanceInfo*)DE_NULL,
1961	};
1962
1963	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1964	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &srcImageBarrier);
1965	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &dstImageBarrier);
1966	vk.cmdBlitImage(*m_cmdBuffer, m_source.get(), m_params.src.image.operationLayout, m_destination.get(), m_params.dst.image.operationLayout, (deUint32)m_params.regions.size(), &regions[0], m_params.filter);
1967	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1968	submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer);
1969
1970	de::MovePtr<tcu::TextureLevel> resultTextureLevel = readImage(*m_destination, m_params.dst.image);
1971
1972	return checkTestResult(resultTextureLevel->getAccess());
1973}
1974
1975static float calculateFloatConversionError (int srcBits)
1976{
1977	if (srcBits > 0)
1978	{
1979		const int	clampedBits	= de::clamp<int>(srcBits, 0, 32);
1980		const float	srcMaxValue	= de::max((float)(1ULL<<clampedBits) - 1.0f, 1.0f);
1981		const float	error		= 1.0f / srcMaxValue;
1982
1983		return de::clamp<float>(error, 0.0f, 1.0f);
1984	}
1985	else
1986		return 1.0f;
1987}
1988
1989tcu::Vec4 getFormatThreshold (const tcu::TextureFormat& format)
1990{
1991	tcu::Vec4 threshold(0.01f);
1992
1993	switch (format.type)
1994	{
1995	case tcu::TextureFormat::HALF_FLOAT:
1996		threshold = tcu::Vec4(0.005f);
1997		break;
1998
1999	case tcu::TextureFormat::FLOAT:
2000	case tcu::TextureFormat::FLOAT64:
2001		threshold = tcu::Vec4(0.001f);
2002		break;
2003
2004	case tcu::TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
2005		threshold = tcu::Vec4(0.02f, 0.02f, 0.0625f, 1.0f);
2006		break;
2007
2008	case tcu::TextureFormat::UNSIGNED_INT_999_E5_REV:
2009		threshold = tcu::Vec4(0.05f, 0.05f, 0.05f, 1.0f);
2010		break;
2011
2012	default:
2013		const tcu::IVec4 bits = tcu::getTextureFormatMantissaBitDepth(format);
2014		threshold = tcu::Vec4(calculateFloatConversionError(bits.x()),
2015				      calculateFloatConversionError(bits.y()),
2016				      calculateFloatConversionError(bits.z()),
2017				      calculateFloatConversionError(bits.w()));
2018	}
2019
2020	// Return value matching the channel order specified by the format
2021	if (format.order == tcu::TextureFormat::BGR || format.order == tcu::TextureFormat::BGRA)
2022		return threshold.swizzle(2, 1, 0, 3);
2023	else
2024		return threshold;
2025}
2026
2027bool BlittingImages::checkLinearFilteredResult (const tcu::ConstPixelBufferAccess&	result,
2028												const tcu::ConstPixelBufferAccess&	clampedExpected,
2029												const tcu::ConstPixelBufferAccess&	unclampedExpected,
2030												const tcu::TextureFormat&			srcFormat)
2031{
2032	tcu::TestLog&				log			(m_context.getTestContext().getLog());
2033	const tcu::TextureFormat	dstFormat	= result.getFormat();
2034	bool						isOk		= false;
2035
2036	log << tcu::TestLog::Section("ClampedSourceImage", "Region with clamped edges on source image.");
2037
2038	if (isFloatFormat(dstFormat))
2039	{
2040		const bool		srcIsSRGB	= tcu::isSRGB(srcFormat);
2041		const tcu::Vec4	srcMaxDiff	= getFormatThreshold(srcFormat) * tcu::Vec4(srcIsSRGB ? 2.0f : 1.0f);
2042		const tcu::Vec4	dstMaxDiff	= getFormatThreshold(dstFormat);
2043		const tcu::Vec4	threshold	= tcu::max(srcMaxDiff, dstMaxDiff);
2044
2045		isOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", clampedExpected, result, threshold, tcu::COMPARE_LOG_RESULT);
2046		log << tcu::TestLog::EndSection;
2047
2048		if (!isOk)
2049		{
2050			log << tcu::TestLog::Section("NonClampedSourceImage", "Region with non-clamped edges on source image.");
2051			isOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", unclampedExpected, result, threshold, tcu::COMPARE_LOG_RESULT);
2052			log << tcu::TestLog::EndSection;
2053		}
2054	}
2055	else
2056	{
2057		tcu::UVec4	threshold;
2058		// Calculate threshold depending on channel width of destination format.
2059		const tcu::IVec4	bitDepth	= tcu::getTextureFormatBitDepth(dstFormat);
2060		for (deUint32 i = 0; i < 4; ++i)
2061			threshold[i] = de::max( (0x1 << bitDepth[i]) / 256, 1);
2062
2063		isOk = tcu::intThresholdCompare(log, "Compare", "Result comparsion", clampedExpected, result, threshold, tcu::COMPARE_LOG_RESULT);
2064		log << tcu::TestLog::EndSection;
2065
2066		if (!isOk)
2067		{
2068			log << tcu::TestLog::Section("NonClampedSourceImage", "Region with non-clamped edges on source image.");
2069			isOk = tcu::intThresholdCompare(log, "Compare", "Result comparsion", unclampedExpected, result, threshold, tcu::COMPARE_LOG_RESULT);
2070			log << tcu::TestLog::EndSection;
2071		}
2072	}
2073
2074	return isOk;
2075}
2076
2077//! Utility to encapsulate coordinate computation and loops.
2078struct CompareEachPixelInEachRegion
2079{
2080	virtual		 ~CompareEachPixelInEachRegion  (void) {}
2081	virtual bool compare						(const void* pUserData, const int x, const int y, const tcu::Vec2& srcNormCoord) const = 0;
2082
2083	bool forEach (const void*						pUserData,
2084				  const std::vector<CopyRegion>&	regions,
2085				  const int							sourceWidth,
2086				  const int							sourceHeight,
2087				  const tcu::PixelBufferAccess&		errorMask) const
2088	{
2089		bool compareOk = true;
2090
2091		for (std::vector<CopyRegion>::const_iterator regionIter = regions.begin(); regionIter != regions.end(); ++regionIter)
2092		{
2093			const VkImageBlit& blit = regionIter->imageBlit;
2094
2095			const int	dx		= deSign32(blit.dstOffsets[1].x - blit.dstOffsets[0].x);
2096			const int	dy		= deSign32(blit.dstOffsets[1].y - blit.dstOffsets[0].y);
2097			const float	xScale	= static_cast<float>(blit.srcOffsets[1].x - blit.srcOffsets[0].x) / static_cast<float>(blit.dstOffsets[1].x - blit.dstOffsets[0].x);
2098			const float	yScale	= static_cast<float>(blit.srcOffsets[1].y - blit.srcOffsets[0].y) / static_cast<float>(blit.dstOffsets[1].y - blit.dstOffsets[0].y);
2099			const float srcInvW	= 1.0f / static_cast<float>(sourceWidth);
2100			const float srcInvH	= 1.0f / static_cast<float>(sourceHeight);
2101
2102			for (int y = blit.dstOffsets[0].y; y < blit.dstOffsets[1].y; y += dy)
2103			for (int x = blit.dstOffsets[0].x; x < blit.dstOffsets[1].x; x += dx)
2104			{
2105				const tcu::Vec2 srcNormCoord
2106				(
2107					(xScale * (static_cast<float>(x - blit.dstOffsets[0].x) + 0.5f) + static_cast<float>(blit.srcOffsets[0].x)) * srcInvW,
2108					(yScale * (static_cast<float>(y - blit.dstOffsets[0].y) + 0.5f) + static_cast<float>(blit.srcOffsets[0].y)) * srcInvH
2109				);
2110
2111				if (!compare(pUserData, x, y, srcNormCoord))
2112				{
2113					errorMask.setPixel(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
2114					compareOk = false;
2115				}
2116			}
2117		}
2118		return compareOk;
2119	}
2120};
2121
2122tcu::Vec4 getFloatOrFixedPointFormatThreshold (const tcu::TextureFormat& format)
2123{
2124	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(format.type);
2125	const tcu::IVec4				bitDepth		= tcu::getTextureFormatBitDepth(format);
2126
2127	if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
2128	{
2129		return getFormatThreshold(format);
2130	}
2131	else if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
2132			 channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
2133	{
2134		const bool	isSigned	= (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
2135		const float	range		= isSigned ? 1.0f - (-1.0f)
2136										   : 1.0f -   0.0f;
2137
2138		tcu::Vec4 v;
2139		for (int i = 0; i < 4; ++i)
2140		{
2141			if (bitDepth[i] == 0)
2142				v[i] = 1.0f;
2143			else
2144				v[i] = range / static_cast<float>((1 << bitDepth[i]) - 1);
2145		}
2146		return v;
2147	}
2148	else
2149	{
2150		DE_ASSERT(0);
2151		return tcu::Vec4();
2152	}
2153}
2154
2155bool floatNearestBlitCompare (const tcu::ConstPixelBufferAccess&	source,
2156							  const tcu::ConstPixelBufferAccess&	result,
2157							  const tcu::PixelBufferAccess&			errorMask,
2158							  const std::vector<CopyRegion>&		regions)
2159{
2160	const tcu::Sampler		sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
2161	tcu::LookupPrecision	precision;
2162
2163	{
2164		const tcu::IVec4	dstBitDepth	= tcu::getTextureFormatBitDepth(result.getFormat());
2165		const tcu::Vec4		srcMaxDiff	= getFloatOrFixedPointFormatThreshold(source.getFormat());
2166		const tcu::Vec4		dstMaxDiff	= getFloatOrFixedPointFormatThreshold(result.getFormat());
2167
2168		precision.colorMask		 = tcu::notEqual(dstBitDepth, tcu::IVec4(0));
2169		precision.colorThreshold = tcu::max(srcMaxDiff, dstMaxDiff);
2170	}
2171
2172	const struct Capture
2173	{
2174		const tcu::ConstPixelBufferAccess&	source;
2175		const tcu::ConstPixelBufferAccess&	result;
2176		const tcu::Sampler&					sampler;
2177		const tcu::LookupPrecision&			precision;
2178		const bool							isSRGB;
2179	} capture =
2180	{
2181		source, result, sampler, precision, tcu::isSRGB(result.getFormat())
2182	};
2183
2184	const struct Loop : CompareEachPixelInEachRegion
2185	{
2186		Loop (void) {}
2187
2188		bool compare (const void* pUserData, const int x, const int y, const tcu::Vec2& srcNormCoord) const
2189		{
2190			const Capture&					c					= *static_cast<const Capture*>(pUserData);
2191			const tcu::TexLookupScaleMode	lookupScaleDontCare	= tcu::TEX_LOOKUP_SCALE_MINIFY;
2192			tcu::Vec4						dstColor			= c.result.getPixel(x, y);
2193
2194			// TexLookupVerifier performs a conversion to linear space, so we have to as well
2195			if (c.isSRGB)
2196				dstColor = tcu::sRGBToLinear(dstColor);
2197
2198			return tcu::isLevel2DLookupResultValid(c.source, c.sampler, lookupScaleDontCare, c.precision, srcNormCoord, 0, dstColor);
2199		}
2200	} loop;
2201
2202	return loop.forEach(&capture, regions, source.getWidth(), source.getHeight(), errorMask);
2203}
2204
2205bool intNearestBlitCompare (const tcu::ConstPixelBufferAccess&	source,
2206							const tcu::ConstPixelBufferAccess&	result,
2207							const tcu::PixelBufferAccess&		errorMask,
2208							const std::vector<CopyRegion>&		regions)
2209{
2210	const tcu::Sampler		sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
2211	tcu::IntLookupPrecision	precision;
2212
2213	{
2214		const tcu::IVec4	srcBitDepth	= tcu::getTextureFormatBitDepth(source.getFormat());
2215		const tcu::IVec4	dstBitDepth	= tcu::getTextureFormatBitDepth(result.getFormat());
2216
2217		for (deUint32 i = 0; i < 4; ++i) {
2218			precision.colorThreshold[i]	= de::max(de::max(srcBitDepth[i] / 8, dstBitDepth[i] / 8), 1);
2219			precision.colorMask[i]		= dstBitDepth[i] != 0;
2220		}
2221	}
2222
2223	// Prepare a source image with a matching (converted) pixel format. Ideally, we would've used a wrapper that
2224	// does the conversion on the fly without wasting memory, but this approach is more straightforward.
2225	tcu::TextureLevel				convertedSourceTexture	(result.getFormat(), source.getWidth(), source.getHeight());
2226	const tcu::PixelBufferAccess	convertedSource			= convertedSourceTexture.getAccess();
2227
2228	for (int y = 0; y < source.getHeight(); ++y)
2229	for (int x = 0; x < source.getWidth();  ++x)
2230		convertedSource.setPixel(source.getPixelInt(x, y), x, y);	// will be clamped to max. representable value
2231
2232	const struct Capture
2233	{
2234		const tcu::ConstPixelBufferAccess&	source;
2235		const tcu::ConstPixelBufferAccess&	result;
2236		const tcu::Sampler&					sampler;
2237		const tcu::IntLookupPrecision&		precision;
2238	} capture =
2239	{
2240		convertedSource, result, sampler, precision
2241	};
2242
2243	const struct Loop : CompareEachPixelInEachRegion
2244	{
2245		Loop (void) {}
2246
2247		bool compare (const void* pUserData, const int x, const int y, const tcu::Vec2& srcNormCoord) const
2248		{
2249			const Capture&					c					= *static_cast<const Capture*>(pUserData);
2250			const tcu::TexLookupScaleMode	lookupScaleDontCare	= tcu::TEX_LOOKUP_SCALE_MINIFY;
2251			const tcu::IVec4				dstColor			= c.result.getPixelInt(x, y);
2252
2253			return tcu::isLevel2DLookupResultValid(c.source, c.sampler, lookupScaleDontCare, c.precision, srcNormCoord, 0, dstColor);
2254		}
2255	} loop;
2256
2257	return loop.forEach(&capture, regions, source.getWidth(), source.getHeight(), errorMask);
2258}
2259
2260bool BlittingImages::checkNearestFilteredResult (const tcu::ConstPixelBufferAccess&	result,
2261												 const tcu::ConstPixelBufferAccess& source)
2262{
2263	tcu::TestLog&					log				(m_context.getTestContext().getLog());
2264	const tcu::TextureFormat		dstFormat		= result.getFormat();
2265	const tcu::TextureChannelClass	dstChannelClass = tcu::getTextureChannelClass(dstFormat.type);
2266
2267	tcu::TextureLevel		errorMaskStorage	(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), result.getWidth(), result.getHeight());
2268	tcu::PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
2269	tcu::Vec4				pixelBias			(0.0f, 0.0f, 0.0f, 0.0f);
2270	tcu::Vec4				pixelScale			(1.0f, 1.0f, 1.0f, 1.0f);
2271	bool					ok					= false;
2272
2273	tcu::clear(errorMask, tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0));
2274
2275	if (dstChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ||
2276		dstChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
2277	{
2278		ok = intNearestBlitCompare(source, result, errorMask, m_params.regions);
2279	}
2280	else
2281		ok = floatNearestBlitCompare(source, result, errorMask, m_params.regions);
2282
2283	if (result.getFormat() != tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))
2284		tcu::computePixelScaleBias(result, pixelScale, pixelBias);
2285
2286	if (!ok)
2287	{
2288		log << tcu::TestLog::ImageSet("Compare", "Result comparsion")
2289			<< tcu::TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
2290			<< tcu::TestLog::Image("ErrorMask",	"Error mask", errorMask)
2291			<< tcu::TestLog::EndImageSet;
2292	}
2293	else
2294	{
2295		log << tcu::TestLog::ImageSet("Compare", "Result comparsion")
2296			<< tcu::TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
2297			<< tcu::TestLog::EndImageSet;
2298	}
2299
2300	return ok;
2301}
2302
2303tcu::TestStatus BlittingImages::checkTestResult (tcu::ConstPixelBufferAccess result)
2304{
2305	DE_ASSERT(m_params.filter == VK_FILTER_NEAREST || m_params.filter == VK_FILTER_LINEAR);
2306	const std::string failMessage("Result image is incorrect");
2307
2308	if (m_params.filter == VK_FILTER_LINEAR)
2309	{
2310		if (tcu::isCombinedDepthStencilType(result.getFormat().type))
2311		{
2312			if (tcu::hasDepthComponent(result.getFormat().order))
2313			{
2314				const tcu::Sampler::DepthStencilMode	mode				= tcu::Sampler::MODE_DEPTH;
2315				const tcu::ConstPixelBufferAccess		depthResult			= tcu::getEffectiveDepthStencilAccess(result, mode);
2316				const tcu::ConstPixelBufferAccess		clampedExpected		= tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[0]->getAccess(), mode);
2317				const tcu::ConstPixelBufferAccess		unclampedExpected	= tcu::getEffectiveDepthStencilAccess(m_unclampedExpectedTextureLevel->getAccess(), mode);
2318				const tcu::TextureFormat				sourceFormat		= tcu::getEffectiveDepthStencilTextureFormat(mapVkFormat(m_params.src.image.format), mode);
2319
2320				if (!checkLinearFilteredResult(depthResult, clampedExpected, unclampedExpected, sourceFormat))
2321					return tcu::TestStatus::fail(failMessage);
2322			}
2323
2324			if (tcu::hasStencilComponent(result.getFormat().order))
2325			{
2326				const tcu::Sampler::DepthStencilMode	mode				= tcu::Sampler::MODE_STENCIL;
2327				const tcu::ConstPixelBufferAccess		stencilResult		= tcu::getEffectiveDepthStencilAccess(result, mode);
2328				const tcu::ConstPixelBufferAccess		clampedExpected		= tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[0]->getAccess(), mode);
2329				const tcu::ConstPixelBufferAccess		unclampedExpected	= tcu::getEffectiveDepthStencilAccess(m_unclampedExpectedTextureLevel->getAccess(), mode);
2330				const tcu::TextureFormat				sourceFormat		= tcu::getEffectiveDepthStencilTextureFormat(mapVkFormat(m_params.src.image.format), mode);
2331
2332				if (!checkLinearFilteredResult(stencilResult, clampedExpected, unclampedExpected, sourceFormat))
2333					return tcu::TestStatus::fail(failMessage);
2334			}
2335		}
2336		else
2337		{
2338			const tcu::TextureFormat	sourceFormat	= mapVkFormat(m_params.src.image.format);
2339
2340			if (!checkLinearFilteredResult(result, m_expectedTextureLevel[0]->getAccess(), m_unclampedExpectedTextureLevel->getAccess(), sourceFormat))
2341				return tcu::TestStatus::fail(failMessage);
2342		}
2343	}
2344	else // NEAREST filtering
2345	{
2346		if (tcu::isCombinedDepthStencilType(result.getFormat().type))
2347		{
2348			if (tcu::hasDepthComponent(result.getFormat().order))
2349			{
2350				const tcu::Sampler::DepthStencilMode	mode			= tcu::Sampler::MODE_DEPTH;
2351				const tcu::ConstPixelBufferAccess		depthResult		= tcu::getEffectiveDepthStencilAccess(result, mode);
2352				const tcu::ConstPixelBufferAccess		depthSource		= tcu::getEffectiveDepthStencilAccess(m_sourceTextureLevel->getAccess(), mode);
2353
2354				if (!checkNearestFilteredResult(depthResult, depthSource))
2355					return tcu::TestStatus::fail(failMessage);
2356			}
2357
2358			if (tcu::hasStencilComponent(result.getFormat().order))
2359			{
2360				const tcu::Sampler::DepthStencilMode	mode			= tcu::Sampler::MODE_STENCIL;
2361				const tcu::ConstPixelBufferAccess		stencilResult	= tcu::getEffectiveDepthStencilAccess(result, mode);
2362				const tcu::ConstPixelBufferAccess		stencilSource	= tcu::getEffectiveDepthStencilAccess(m_sourceTextureLevel->getAccess(), mode);
2363
2364				if (!checkNearestFilteredResult(stencilResult, stencilSource))
2365					return tcu::TestStatus::fail(failMessage);
2366			}
2367		}
2368		else
2369		{
2370			if (!checkNearestFilteredResult(result, m_sourceTextureLevel->getAccess()))
2371				return tcu::TestStatus::fail(failMessage);
2372		}
2373	}
2374
2375	return tcu::TestStatus::pass("Pass");
2376}
2377
2378tcu::Vec4 linearToSRGBIfNeeded (const tcu::TextureFormat& format, const tcu::Vec4& color)
2379{
2380	return isSRGB(format) ? linearToSRGB(color) : color;
2381}
2382
2383void scaleFromWholeSrcBuffer (const tcu::PixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const VkOffset3D regionOffset, const VkOffset3D regionExtent, tcu::Sampler::FilterMode filter)
2384{
2385	DE_ASSERT(filter == tcu::Sampler::LINEAR);
2386	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1);
2387
2388	tcu::Sampler sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
2389					filter, filter, 0.0f, false);
2390
2391	float sX = (float)regionExtent.x / (float)dst.getWidth();
2392	float sY = (float)regionExtent.y / (float)dst.getHeight();
2393
2394	for (int y = 0; y < dst.getHeight(); y++)
2395	for (int x = 0; x < dst.getWidth(); x++)
2396		dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample2D(sampler, filter, (float)regionOffset.x + ((float)x+0.5f)*sX, (float)regionOffset.y + ((float)y+0.5f)*sY, 0)), x, y);
2397}
2398
2399void blit (const tcu::PixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::Sampler::FilterMode filter, const MirrorMode mirrorMode)
2400{
2401	DE_ASSERT(filter == tcu::Sampler::NEAREST || filter == tcu::Sampler::LINEAR);
2402
2403	tcu::Sampler sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
2404						 filter, filter, 0.0f, false);
2405
2406	const float sX = (float)src.getWidth() / (float)dst.getWidth();
2407	const float sY = (float)src.getHeight() / (float)dst.getHeight();
2408	const float sZ = (float)src.getDepth() / (float)dst.getDepth();
2409
2410	tcu::Mat2 rotMatrix;
2411	rotMatrix(0,0) = (mirrorMode & MIRROR_MODE_X) ? -1.0f : 1.0f;
2412	rotMatrix(0,1) = 0.0f;
2413	rotMatrix(1,0) = 0.0f;
2414	rotMatrix(1,1) = (mirrorMode & MIRROR_MODE_Y) ? -1.0f : 1.0f;
2415
2416	const int xOffset = (mirrorMode & MIRROR_MODE_X) ? dst.getWidth() - 1 : 0;
2417	const int yOffset = (mirrorMode & MIRROR_MODE_Y) ? dst.getHeight() - 1 : 0;
2418
2419	if (dst.getDepth() == 1 && src.getDepth() == 1)
2420	{
2421		for (int y = 0; y < dst.getHeight(); ++y)
2422		for (int x = 0; x < dst.getWidth(); ++x)
2423		{
2424			const tcu::Vec2 xy = rotMatrix * tcu::Vec2((float)x,(float)y);
2425			dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample2D(sampler, filter, ((float)x+0.5f)*sX, ((float)y+0.5f)*sY, 0)), (int)round(xy[0]) + xOffset, (int)round(xy[1]) + yOffset);
2426		}
2427	}
2428	else
2429	{
2430		for (int z = 0; z < dst.getDepth(); ++z)
2431		for (int y = 0; y < dst.getHeight(); ++y)
2432		for (int x = 0; x < dst.getWidth(); ++x)
2433		{
2434			const tcu::Vec2 xy = rotMatrix * tcu::Vec2((float)x,(float)y);
2435			dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample3D(sampler, filter, ((float)x+0.5f)*sX, ((float)y+0.5f)*sY, ((float)z+0.5f)*sZ)), (int)round(xy[0]) + xOffset, (int)round(xy[1]) + yOffset, z);
2436		}
2437	}
2438}
2439
2440void flipCoordinates (CopyRegion& region, const MirrorMode mirrorMode)
2441{
2442	const VkOffset3D dstOffset0 = region.imageBlit.dstOffsets[0];
2443	const VkOffset3D dstOffset1 = region.imageBlit.dstOffsets[1];
2444	const VkOffset3D srcOffset0 = region.imageBlit.srcOffsets[0];
2445	const VkOffset3D srcOffset1 = region.imageBlit.srcOffsets[1];
2446
2447	if (mirrorMode > MIRROR_MODE_NONE && mirrorMode < MIRROR_MODE_LAST)
2448	{
2449		//sourceRegion
2450		region.imageBlit.srcOffsets[0].x = std::min(srcOffset0.x, srcOffset1.x);
2451		region.imageBlit.srcOffsets[0].y = std::min(srcOffset0.y, srcOffset1.y);
2452
2453		region.imageBlit.srcOffsets[1].x = std::max(srcOffset0.x, srcOffset1.x);
2454		region.imageBlit.srcOffsets[1].y = std::max(srcOffset0.y, srcOffset1.y);
2455
2456		//destinationRegion
2457		region.imageBlit.dstOffsets[0].x = std::min(dstOffset0.x, dstOffset1.x);
2458		region.imageBlit.dstOffsets[0].y = std::min(dstOffset0.y, dstOffset1.y);
2459
2460		region.imageBlit.dstOffsets[1].x = std::max(dstOffset0.x, dstOffset1.x);
2461		region.imageBlit.dstOffsets[1].y = std::max(dstOffset0.y, dstOffset1.y);
2462	}
2463}
2464
2465MirrorMode getMirrorMode(const VkOffset3D x1, const VkOffset3D x2)
2466{
2467	if (x1.x >= x2.x && x1.y >= x2.y)
2468	{
2469		return MIRROR_MODE_XY;
2470	}
2471	else if (x1.x <= x2.x && x1.y <= x2.y)
2472	{
2473		return MIRROR_MODE_NONE;
2474	}
2475	else if (x1.x <= x2.x && x1.y >= x2.y)
2476	{
2477		return MIRROR_MODE_Y;
2478	}
2479	else if (x1.x >= x2.x && x1.y <= x2.y)
2480	{
2481		return MIRROR_MODE_X;
2482	}
2483	return MIRROR_MODE_LAST;
2484}
2485
2486MirrorMode getMirrorMode(const VkOffset3D s1, const VkOffset3D s2, const VkOffset3D d1, const VkOffset3D d2)
2487{
2488	const MirrorMode source		 = getMirrorMode(s1, s2);
2489	const MirrorMode destination = getMirrorMode(d1, d2);
2490
2491	if (source == destination)
2492	{
2493		return MIRROR_MODE_NONE;
2494	}
2495	else if ((source == MIRROR_MODE_XY && destination == MIRROR_MODE_X)	  || (destination == MIRROR_MODE_XY && source == MIRROR_MODE_X) ||
2496			 (source == MIRROR_MODE_Y && destination == MIRROR_MODE_NONE) || (destination == MIRROR_MODE_Y && source == MIRROR_MODE_NONE))
2497	{
2498		return MIRROR_MODE_Y;
2499	}
2500	else if ((source == MIRROR_MODE_XY && destination == MIRROR_MODE_Y)	  || (destination == MIRROR_MODE_XY && source == MIRROR_MODE_Y) ||
2501			 (source == MIRROR_MODE_X && destination == MIRROR_MODE_NONE) || (destination == MIRROR_MODE_X && source == MIRROR_MODE_NONE))
2502	{
2503		return MIRROR_MODE_X;
2504	}
2505	else if ((source == MIRROR_MODE_XY && destination == MIRROR_MODE_NONE) || (destination == MIRROR_MODE_XY && source == MIRROR_MODE_NONE))
2506	{
2507		return MIRROR_MODE_XY;
2508	}
2509	return MIRROR_MODE_LAST;
2510}
2511
2512void BlittingImages::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region)
2513{
2514	const MirrorMode mirrorMode = getMirrorMode(region.imageBlit.srcOffsets[0],
2515												region.imageBlit.srcOffsets[1],
2516												region.imageBlit.dstOffsets[0],
2517												region.imageBlit.dstOffsets[1]);
2518
2519	flipCoordinates(region, mirrorMode);
2520
2521	const VkOffset3D					srcOffset		= region.imageBlit.srcOffsets[0];
2522	const VkOffset3D					srcExtent		=
2523	{
2524		region.imageBlit.srcOffsets[1].x - srcOffset.x,
2525		region.imageBlit.srcOffsets[1].y - srcOffset.y,
2526		region.imageBlit.srcOffsets[1].z - srcOffset.z
2527	};
2528	const VkOffset3D					dstOffset		= region.imageBlit.dstOffsets[0];
2529	const VkOffset3D					dstExtent		=
2530	{
2531		region.imageBlit.dstOffsets[1].x - dstOffset.x,
2532		region.imageBlit.dstOffsets[1].y - dstOffset.y,
2533		region.imageBlit.dstOffsets[1].z - dstOffset.z
2534	};
2535	const tcu::Sampler::FilterMode		filter			= (m_params.filter == VK_FILTER_LINEAR) ? tcu::Sampler::LINEAR : tcu::Sampler::NEAREST;
2536
2537	if (tcu::isCombinedDepthStencilType(src.getFormat().type))
2538	{
2539		DE_ASSERT(src.getFormat() == dst.getFormat());
2540		// Scale depth.
2541		if (tcu::hasDepthComponent(src.getFormat().order))
2542		{
2543			const tcu::ConstPixelBufferAccess	srcSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcExtent.x, srcExtent.y), tcu::Sampler::MODE_DEPTH);
2544			const tcu::PixelBufferAccess		dstSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_DEPTH);
2545			tcu::scale(dstSubRegion, srcSubRegion, filter);
2546
2547			if (filter == tcu::Sampler::LINEAR)
2548			{
2549				const tcu::ConstPixelBufferAccess	depthSrc			= getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_DEPTH);
2550				const tcu::PixelBufferAccess		unclampedSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(m_unclampedExpectedTextureLevel->getAccess(), dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_DEPTH);
2551				scaleFromWholeSrcBuffer(unclampedSubRegion, depthSrc, srcOffset, srcExtent, filter);
2552			}
2553		}
2554
2555		// Scale stencil.
2556		if (tcu::hasStencilComponent(src.getFormat().order))
2557		{
2558			const tcu::ConstPixelBufferAccess	srcSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcExtent.x, srcExtent.y), tcu::Sampler::MODE_STENCIL);
2559			const tcu::PixelBufferAccess		dstSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_STENCIL);
2560			blit(dstSubRegion, srcSubRegion, filter, mirrorMode);
2561
2562			if (filter == tcu::Sampler::LINEAR)
2563			{
2564				const tcu::ConstPixelBufferAccess	stencilSrc			= getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_STENCIL);
2565				const tcu::PixelBufferAccess		unclampedSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(m_unclampedExpectedTextureLevel->getAccess(), dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_STENCIL);
2566				scaleFromWholeSrcBuffer(unclampedSubRegion, stencilSrc, srcOffset, srcExtent, filter);
2567			}
2568		}
2569	}
2570	else
2571	{
2572		const tcu::ConstPixelBufferAccess	srcSubRegion	= tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcExtent.x, srcExtent.y);
2573		const tcu::PixelBufferAccess		dstSubRegion	= tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y);
2574		blit(dstSubRegion, srcSubRegion, filter, mirrorMode);
2575
2576		if (filter == tcu::Sampler::LINEAR)
2577		{
2578			const tcu::PixelBufferAccess	unclampedSubRegion	= tcu::getSubregion(m_unclampedExpectedTextureLevel->getAccess(), dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y);
2579			scaleFromWholeSrcBuffer(unclampedSubRegion, src, srcOffset, srcExtent, filter);
2580		}
2581	}
2582}
2583
2584void BlittingImages::generateExpectedResult (void)
2585{
2586	const tcu::ConstPixelBufferAccess	src	= m_sourceTextureLevel->getAccess();
2587	const tcu::ConstPixelBufferAccess	dst	= m_destinationTextureLevel->getAccess();
2588
2589	m_expectedTextureLevel[0]		= de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth()));
2590	tcu::copy(m_expectedTextureLevel[0]->getAccess(), dst);
2591
2592	if (m_params.filter == VK_FILTER_LINEAR)
2593	{
2594		m_unclampedExpectedTextureLevel	= de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth()));
2595		tcu::copy(m_unclampedExpectedTextureLevel->getAccess(), dst);
2596	}
2597
2598	for (deUint32 i = 0; i < m_params.regions.size(); i++)
2599	{
2600		CopyRegion region = m_params.regions[i];
2601		copyRegionToTextureLevel(src, m_expectedTextureLevel[0]->getAccess(), region);
2602	}
2603}
2604
2605class BlitImageTestCase : public vkt::TestCase
2606{
2607public:
2608							BlitImageTestCase		(tcu::TestContext&				testCtx,
2609													 const std::string&				name,
2610													 const std::string&				description,
2611													 const TestParams				params)
2612								: vkt::TestCase	(testCtx, name, description)
2613								, m_params		(params)
2614							{}
2615
2616	virtual TestInstance*	createInstance			(Context&						context) const
2617							{
2618								return new BlittingImages(context, m_params);
2619							}
2620private:
2621	TestParams				m_params;
2622};
2623
2624class BlittingMipmaps : public CopiesAndBlittingTestInstance
2625{
2626public:
2627										BlittingMipmaps					(Context&   context,
2628																		 TestParams params);
2629	virtual tcu::TestStatus				iterate							(void);
2630protected:
2631	virtual tcu::TestStatus				checkTestResult					(tcu::ConstPixelBufferAccess result = tcu::ConstPixelBufferAccess());
2632	virtual void						copyRegionToTextureLevel		(tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region);
2633	virtual void						generateExpectedResult			(void);
2634private:
2635	bool								checkLinearFilteredResult		(void);
2636	bool								checkNearestFilteredResult		(void);
2637
2638	Move<VkImage>						m_source;
2639	de::MovePtr<Allocation>				m_sourceImageAlloc;
2640	Move<VkImage>						m_destination;
2641	de::MovePtr<Allocation>				m_destinationImageAlloc;
2642
2643	de::MovePtr<tcu::TextureLevel>		m_unclampedExpectedTextureLevel[16];
2644};
2645
2646BlittingMipmaps::BlittingMipmaps (Context& context, TestParams params)
2647	: CopiesAndBlittingTestInstance (context, params)
2648{
2649	const InstanceInterface&	vki					= context.getInstanceInterface();
2650	const DeviceInterface&		vk					= context.getDeviceInterface();
2651	const VkPhysicalDevice		vkPhysDevice		= context.getPhysicalDevice();
2652	const VkDevice				vkDevice			= context.getDevice();
2653	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
2654	Allocator&					memAlloc			= context.getDefaultAllocator();
2655
2656	{
2657		VkImageFormatProperties	properties;
2658		if (context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(),
2659																				   m_params.src.image.format,
2660																				   VK_IMAGE_TYPE_2D,
2661																				   VK_IMAGE_TILING_OPTIMAL,
2662																				   VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2663																				   0,
2664																				   &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
2665		{
2666			TCU_THROW(NotSupportedError, "Format not supported");
2667		}
2668		else if ((m_params.src.image.extent.width	> properties.maxExtent.width)	||
2669				 (m_params.src.image.extent.height	> properties.maxExtent.height)	||
2670				 (m_params.src.image.extent.depth	> properties.maxExtent.depth))
2671		{
2672			TCU_THROW(NotSupportedError, "Image size not supported");
2673		}
2674	}
2675
2676	{
2677		VkImageFormatProperties	properties;
2678		if (context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(),
2679																				   m_params.dst.image.format,
2680																				   VK_IMAGE_TYPE_2D,
2681																				   VK_IMAGE_TILING_OPTIMAL,
2682																				   VK_IMAGE_USAGE_TRANSFER_DST_BIT,
2683																				   0,
2684																				   &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
2685		{
2686			TCU_THROW(NotSupportedError, "Format not supported");
2687		}
2688		else if ((m_params.dst.image.extent.width	> properties.maxExtent.width)	||
2689				 (m_params.dst.image.extent.height	> properties.maxExtent.height)	||
2690				 (m_params.dst.image.extent.depth	> properties.maxExtent.depth))
2691		{
2692			TCU_THROW(NotSupportedError, "Image size not supported");
2693		}
2694		else if (m_params.mipLevels > properties.maxMipLevels)
2695		{
2696			TCU_THROW(NotSupportedError, "Number of mip levels not supported");
2697		}
2698	}
2699
2700	const VkFormatProperties	srcFormatProperties	= getPhysicalDeviceFormatProperties (vki, vkPhysDevice, m_params.src.image.format);
2701	if (!(srcFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT))
2702	{
2703		TCU_THROW(NotSupportedError, "Format feature blit source not supported");
2704	}
2705
2706	const VkFormatProperties	dstFormatProperties	= getPhysicalDeviceFormatProperties (vki, vkPhysDevice, m_params.dst.image.format);
2707	if (!(dstFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT))
2708	{
2709		TCU_THROW(NotSupportedError, "Format feature blit destination not supported");
2710	}
2711
2712	if (m_params.filter == VK_FILTER_LINEAR)
2713	{
2714		if (!(srcFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
2715			TCU_THROW(NotSupportedError, "Source format feature sampled image filter linear not supported");
2716		if (!(dstFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
2717			TCU_THROW(NotSupportedError, "Destination format feature sampled image filter linear not supported");
2718	}
2719
2720	// Create source image
2721	{
2722		const VkImageCreateInfo		sourceImageParams		=
2723		{
2724			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
2725			DE_NULL,								// const void*			pNext;
2726			0u,										// VkImageCreateFlags	flags;
2727			m_params.src.image.imageType,			// VkImageType			imageType;
2728			m_params.src.image.format,				// VkFormat				format;
2729			getExtent3D(m_params.src.image),		// VkExtent3D			extent;
2730			1u,										// deUint32				mipLevels;
2731			getArraySize(m_params.src.image),		// deUint32				arraySize;
2732			VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
2733			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
2734			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2735				VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
2736			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
2737			1u,										// deUint32				queueFamilyCount;
2738			&queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
2739			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
2740		};
2741
2742		m_source = createImage(vk, vkDevice, &sourceImageParams);
2743		m_sourceImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_source, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
2744		VK_CHECK(vk.bindImageMemory(vkDevice, *m_source, m_sourceImageAlloc->getMemory(), m_sourceImageAlloc->getOffset()));
2745	}
2746
2747	// Create destination image
2748	{
2749		const VkImageCreateInfo		destinationImageParams  =
2750		{
2751			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
2752			DE_NULL,								// const void*			pNext;
2753			0u,										// VkImageCreateFlags	flags;
2754			m_params.dst.image.imageType,			// VkImageType			imageType;
2755			m_params.dst.image.format,				// VkFormat				format;
2756			getExtent3D(m_params.dst.image),		// VkExtent3D			extent;
2757			m_params.mipLevels,						// deUint32				mipLevels;
2758			getArraySize(m_params.dst.image),		// deUint32				arraySize;
2759			VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
2760			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
2761			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2762				VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
2763			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
2764			1u,										// deUint32				queueFamilyCount;
2765			&queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
2766			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
2767		};
2768
2769		m_destination = createImage(vk, vkDevice, &destinationImageParams);
2770		m_destinationImageAlloc = allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
2771		VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset()));
2772	}
2773}
2774
2775tcu::TestStatus BlittingMipmaps::iterate (void)
2776{
2777	const tcu::TextureFormat	srcTcuFormat		= mapVkFormat(m_params.src.image.format);
2778	const tcu::TextureFormat	dstTcuFormat		= mapVkFormat(m_params.dst.image.format);
2779	m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(srcTcuFormat,
2780																				m_params.src.image.extent.width,
2781																				m_params.src.image.extent.height,
2782																				m_params.src.image.extent.depth));
2783	generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.src.image.extent.depth, FILL_MODE_GRADIENT);
2784	m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dstTcuFormat,
2785																						(int)m_params.dst.image.extent.width,
2786																						(int)m_params.dst.image.extent.height,
2787																						(int)m_params.dst.image.extent.depth));
2788	generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth, FILL_MODE_WHITE);
2789	generateExpectedResult();
2790
2791	uploadImage(m_sourceTextureLevel->getAccess(), m_source.get(), m_params.src.image);
2792
2793	uploadImage(m_destinationTextureLevel->getAccess(), m_destination.get(), m_params.dst.image, m_params.mipLevels);
2794
2795	const DeviceInterface&		vk					= m_context.getDeviceInterface();
2796	const VkDevice				vkDevice			= m_context.getDevice();
2797	const VkQueue				queue				= m_context.getUniversalQueue();
2798
2799	std::vector<VkImageBlit>	regions;
2800	for (deUint32 i = 0; i < m_params.regions.size(); i++)
2801		regions.push_back(m_params.regions[i].imageBlit);
2802
2803	// Copy source image to mip level 0 when generating mipmaps with multiple blit commands
2804	if (!m_params.singleCommand)
2805		uploadImage(m_sourceTextureLevel->getAccess(), m_destination.get(), m_params.dst.image, 1u);
2806
2807	const VkCommandBufferBeginInfo  cmdBufferBeginInfo  =
2808	{
2809		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
2810		DE_NULL,												// const void*						pNext;
2811		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
2812		(const VkCommandBufferInheritanceInfo*)DE_NULL,
2813	};
2814
2815	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
2816
2817	// Blit all mip levels with a single blit command
2818	if (m_params.singleCommand)
2819	{
2820		{
2821			// Source image layout
2822			const VkImageMemoryBarrier		srcImageBarrier		=
2823			{
2824				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
2825				DE_NULL,									// const void*				pNext;
2826				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
2827				VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
2828				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
2829				m_params.src.image.operationLayout,			// VkImageLayout			newLayout;
2830				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
2831				VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
2832				m_source.get(),								// VkImage					image;
2833				{											// VkImageSubresourceRange	subresourceRange;
2834					getAspectFlags(srcTcuFormat),	// VkImageAspectFlags   aspectMask;
2835					0u,								// deUint32				baseMipLevel;
2836					1u,								// deUint32				mipLevels;
2837					0u,								// deUint32				baseArraySlice;
2838					1u								// deUint32				arraySize;
2839				}
2840			};
2841
2842			// Destination image layout
2843			const VkImageMemoryBarrier		dstImageBarrier		=
2844			{
2845				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
2846				DE_NULL,									// const void*				pNext;
2847				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
2848				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
2849				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
2850				m_params.dst.image.operationLayout,			// VkImageLayout			newLayout;
2851				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
2852				VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
2853				m_destination.get(),						// VkImage					image;
2854				{											// VkImageSubresourceRange	subresourceRange;
2855					getAspectFlags(dstTcuFormat),	// VkImageAspectFlags   aspectMask;
2856					0u,								// deUint32				baseMipLevel;
2857					m_params.mipLevels,				// deUint32				mipLevels;
2858					0u,								// deUint32				baseArraySlice;
2859					1u								// deUint32				arraySize;
2860				}
2861			};
2862
2863			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &srcImageBarrier);
2864			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &dstImageBarrier);
2865			vk.cmdBlitImage(*m_cmdBuffer, m_source.get(), m_params.src.image.operationLayout, m_destination.get(), m_params.dst.image.operationLayout, (deUint32)regions.size(), &regions[0], m_params.filter);
2866		}
2867	}
2868	// Blit mip levels with multiple blit commands
2869	else
2870	{
2871		// Prepare all mip levels for reading
2872		{
2873			const VkImageMemoryBarrier		preImageBarrier		=
2874			{
2875				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
2876				DE_NULL,									// const void*				pNext;
2877				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
2878				VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
2879				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
2880				m_params.src.image.operationLayout,			// VkImageLayout			newLayout;
2881				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
2882				VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
2883				m_destination.get(),						// VkImage					image;
2884				{											// VkImageSubresourceRange	subresourceRange;
2885					getAspectFlags(dstTcuFormat),	// VkImageAspectFlags	aspectMask;
2886					0u,								// deUint32				baseMipLevel;
2887					VK_REMAINING_MIP_LEVELS,		// deUint32				mipLevels;
2888					0u,								// deUint32				baseArraySlice;
2889					1u								// deUint32				arraySize;
2890				}
2891			};
2892
2893			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
2894		}
2895
2896		for (deUint32 regionNdx = 0u; regionNdx < (deUint32)regions.size(); regionNdx++)
2897		{
2898			const deUint32					mipLevel			= regions[regionNdx].dstSubresource.mipLevel;
2899
2900			// Prepare single mip level for writing
2901			const VkImageMemoryBarrier		preImageBarrier		=
2902			{
2903				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
2904				DE_NULL,									// const void*					pNext;
2905				VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			srcAccessMask;
2906				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
2907				m_params.src.image.operationLayout,			// VkImageLayout			oldLayout;
2908				m_params.dst.image.operationLayout,			// VkImageLayout			newLayout;
2909				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
2910				VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
2911				m_destination.get(),						// VkImage					image;
2912				{											// VkImageSubresourceRange	subresourceRange;
2913					getAspectFlags(dstTcuFormat),	// VkImageAspectFlags	aspectMask;
2914					mipLevel,						// deUint32				baseMipLevel;
2915					1u,								// deUint32				mipLevels;
2916					0u,								// deUint32				baseArraySlice;
2917					1u								// deUint32				arraySize;
2918				}
2919			};
2920
2921			// Prepare single mip level for reading
2922			const VkImageMemoryBarrier		postImageBarrier	=
2923			{
2924				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
2925				DE_NULL,									// const void*				pNext;
2926				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
2927				VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
2928				m_params.dst.image.operationLayout,			// VkImageLayout			oldLayout;
2929				m_params.src.image.operationLayout,			// VkImageLayout			newLayout;
2930				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
2931				VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
2932				m_destination.get(),						// VkImage					image;
2933				{											// VkImageSubresourceRange	subresourceRange;
2934					getAspectFlags(dstTcuFormat),	// VkImageAspectFlags	aspectMask;
2935					mipLevel,						// deUint32				baseMipLevel;
2936					1u,								// deUint32				mipLevels;
2937					0u,								// deUint32				baseArraySlice;
2938					1u								// deUint32				arraySize;
2939				}
2940			};
2941
2942			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
2943			vk.cmdBlitImage(*m_cmdBuffer, m_destination.get(), m_params.src.image.operationLayout, m_destination.get(), m_params.dst.image.operationLayout, 1u, &regions[regionNdx], m_params.filter);
2944			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
2945		}
2946
2947		// Prepare all mip levels for writing
2948		{
2949			const VkImageMemoryBarrier		postImageBarrier		=
2950			{
2951				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
2952				DE_NULL,									// const void*				pNext;
2953				VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			srcAccessMask;
2954				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
2955				m_params.src.image.operationLayout,			// VkImageLayout			oldLayout;
2956				m_params.dst.image.operationLayout,			// VkImageLayout			newLayout;
2957				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
2958				VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
2959				m_destination.get(),						// VkImage					image;
2960				{											// VkImageSubresourceRange	subresourceRange;
2961					getAspectFlags(dstTcuFormat),	// VkImageAspectFlags	aspectMask;
2962					0u,								// deUint32				baseMipLevel;
2963					VK_REMAINING_MIP_LEVELS,		// deUint32				mipLevels;
2964					0u,								// deUint32				baseArraySlice;
2965					1u								// deUint32				arraySize;
2966				}
2967			};
2968
2969			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
2970		}
2971	}
2972
2973	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
2974	submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer);
2975
2976	return checkTestResult();
2977}
2978
2979bool BlittingMipmaps::checkLinearFilteredResult (void)
2980{
2981	tcu::TestLog&				log				(m_context.getTestContext().getLog());
2982	bool						allLevelsOk		= true;
2983
2984	for (deUint32 mipLevelNdx = 0u; mipLevelNdx < m_params.mipLevels; mipLevelNdx++)
2985	{
2986		de::MovePtr<tcu::TextureLevel>			resultLevel			= readImage(*m_destination, m_params.dst.image, mipLevelNdx);
2987		const tcu::ConstPixelBufferAccess&		resultAccess		= resultLevel->getAccess();
2988
2989		const tcu::Sampler::DepthStencilMode	mode				= tcu::hasDepthComponent(resultAccess.getFormat().order)	?   tcu::Sampler::MODE_DEPTH :
2990																	  tcu::hasStencilComponent(resultAccess.getFormat().order)  ?   tcu::Sampler::MODE_STENCIL :
2991																																	tcu::Sampler::MODE_LAST;
2992		const tcu::ConstPixelBufferAccess		result				= tcu::hasDepthComponent(resultAccess.getFormat().order)	?   getEffectiveDepthStencilAccess(resultAccess, mode) :
2993																	  tcu::hasStencilComponent(resultAccess.getFormat().order)  ?   getEffectiveDepthStencilAccess(resultAccess, mode) :
2994																																	resultAccess;
2995		const tcu::ConstPixelBufferAccess		clampedLevel		= tcu::hasDepthComponent(resultAccess.getFormat().order)	?   getEffectiveDepthStencilAccess(m_expectedTextureLevel[mipLevelNdx]->getAccess(), mode) :
2996																	  tcu::hasStencilComponent(resultAccess.getFormat().order)  ?   getEffectiveDepthStencilAccess(m_expectedTextureLevel[mipLevelNdx]->getAccess(), mode) :
2997																																	m_expectedTextureLevel[mipLevelNdx]->getAccess();
2998		const tcu::ConstPixelBufferAccess		unclampedLevel		= tcu::hasDepthComponent(resultAccess.getFormat().order)	?   getEffectiveDepthStencilAccess(m_unclampedExpectedTextureLevel[mipLevelNdx]->getAccess(), mode) :
2999																	  tcu::hasStencilComponent(resultAccess.getFormat().order)  ?   getEffectiveDepthStencilAccess(m_unclampedExpectedTextureLevel[mipLevelNdx]->getAccess(), mode) :
3000																																	m_unclampedExpectedTextureLevel[mipLevelNdx]->getAccess();
3001		const tcu::TextureFormat				srcFormat			= tcu::hasDepthComponent(resultAccess.getFormat().order)	?   tcu::getEffectiveDepthStencilTextureFormat(mapVkFormat(m_params.src.image.format), mode) :
3002																	  tcu::hasStencilComponent(resultAccess.getFormat().order)  ?   tcu::getEffectiveDepthStencilTextureFormat(mapVkFormat(m_params.src.image.format), mode) :
3003																																	mapVkFormat(m_params.src.image.format);
3004
3005		const tcu::TextureFormat				dstFormat			= result.getFormat();
3006		bool									singleLevelOk		= false;
3007		std::vector <CopyRegion>				mipLevelRegions;
3008
3009		for (size_t regionNdx = 0u; regionNdx < m_params.regions.size(); regionNdx++)
3010			if (m_params.regions.at(regionNdx).imageBlit.dstSubresource.mipLevel == mipLevelNdx)
3011				mipLevelRegions.push_back(m_params.regions.at(regionNdx));
3012
3013		log << tcu::TestLog::Section("ClampedSourceImage", "Region with clamped edges on source image.");
3014
3015		if (isFloatFormat(dstFormat))
3016		{
3017			const bool		srcIsSRGB   = tcu::isSRGB(srcFormat);
3018			const tcu::Vec4 srcMaxDiff  = getFormatThreshold(srcFormat) * tcu::Vec4(srcIsSRGB ? 2.0f : 1.0f);
3019			const tcu::Vec4 dstMaxDiff  = getFormatThreshold(dstFormat);
3020			const tcu::Vec4 threshold   = tcu::max(srcMaxDiff, dstMaxDiff);
3021
3022			singleLevelOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", clampedLevel, result, threshold, tcu::COMPARE_LOG_RESULT);
3023			log << tcu::TestLog::EndSection;
3024
3025			if (!singleLevelOk)
3026			{
3027				log << tcu::TestLog::Section("NonClampedSourceImage", "Region with non-clamped edges on source image.");
3028				singleLevelOk = tcu::floatThresholdCompare(log, "Compare", "Result comparsion", unclampedLevel, result, threshold, tcu::COMPARE_LOG_RESULT);
3029				log << tcu::TestLog::EndSection;
3030			}
3031		}
3032		else
3033		{
3034			tcu::UVec4  threshold;
3035			// Calculate threshold depending on channel width of destination format.
3036			const tcu::IVec4	bitDepth	= tcu::getTextureFormatBitDepth(dstFormat);
3037			for (deUint32 i = 0; i < 4; ++i)
3038				threshold[i] = de::max( (0x1 << bitDepth[i]) / 256, 1);
3039
3040			singleLevelOk = tcu::intThresholdCompare(log, "Compare", "Result comparsion", clampedLevel, result, threshold, tcu::COMPARE_LOG_RESULT);
3041			log << tcu::TestLog::EndSection;
3042
3043			if (!singleLevelOk)
3044			{
3045				log << tcu::TestLog::Section("NonClampedSourceImage", "Region with non-clamped edges on source image.");
3046				singleLevelOk = tcu::intThresholdCompare(log, "Compare", "Result comparsion", unclampedLevel, result, threshold, tcu::COMPARE_LOG_RESULT);
3047				log << tcu::TestLog::EndSection;
3048			}
3049		}
3050		allLevelsOk &= singleLevelOk;
3051	}
3052
3053	return allLevelsOk;
3054}
3055
3056bool BlittingMipmaps::checkNearestFilteredResult (void)
3057{
3058	bool						allLevelsOk		= true;
3059	tcu::TestLog&				log				(m_context.getTestContext().getLog());
3060
3061	for (deUint32 mipLevelNdx = 0u; mipLevelNdx < m_params.mipLevels; mipLevelNdx++)
3062	{
3063		de::MovePtr<tcu::TextureLevel>			resultLevel			= readImage(*m_destination, m_params.dst.image, mipLevelNdx);
3064		const tcu::ConstPixelBufferAccess&		resultAccess		= resultLevel->getAccess();
3065
3066		const tcu::Sampler::DepthStencilMode	mode				= tcu::hasDepthComponent(resultAccess.getFormat().order)	?   tcu::Sampler::MODE_DEPTH :
3067																	  tcu::hasStencilComponent(resultAccess.getFormat().order)  ?   tcu::Sampler::MODE_STENCIL :
3068																																	tcu::Sampler::MODE_LAST;
3069		const tcu::ConstPixelBufferAccess		result				= tcu::hasDepthComponent(resultAccess.getFormat().order)	?   getEffectiveDepthStencilAccess(resultAccess, mode) :
3070																	  tcu::hasStencilComponent(resultAccess.getFormat().order)  ?   getEffectiveDepthStencilAccess(resultAccess, mode) :
3071																																	resultAccess;
3072		const tcu::ConstPixelBufferAccess		source				= (m_params.singleCommand || mipLevelNdx == 0) ?			//  Read from source image
3073																	  tcu::hasDepthComponent(resultAccess.getFormat().order)	?   tcu::getEffectiveDepthStencilAccess(m_sourceTextureLevel->getAccess(), mode) :
3074																	  tcu::hasStencilComponent(resultAccess.getFormat().order)  ?   tcu::getEffectiveDepthStencilAccess(m_sourceTextureLevel->getAccess(), mode) :
3075																																	m_sourceTextureLevel->getAccess()
3076																																//  Read from destination image
3077																	: tcu::hasDepthComponent(resultAccess.getFormat().order)	?   tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[mipLevelNdx - 1u]->getAccess(), mode) :
3078																	  tcu::hasStencilComponent(resultAccess.getFormat().order)  ?   tcu::getEffectiveDepthStencilAccess(m_expectedTextureLevel[mipLevelNdx - 1u]->getAccess(), mode) :
3079																																	m_expectedTextureLevel[mipLevelNdx - 1u]->getAccess();
3080		const tcu::TextureFormat				dstFormat			= result.getFormat();
3081		const tcu::TextureChannelClass			dstChannelClass		= tcu::getTextureChannelClass(dstFormat.type);
3082		bool									singleLevelOk		= false;
3083		std::vector <CopyRegion>				mipLevelRegions;
3084
3085		for (size_t regionNdx = 0u; regionNdx < m_params.regions.size(); regionNdx++)
3086			if (m_params.regions.at(regionNdx).imageBlit.dstSubresource.mipLevel == mipLevelNdx)
3087				mipLevelRegions.push_back(m_params.regions.at(regionNdx));
3088
3089		tcu::TextureLevel				errorMaskStorage	(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), result.getWidth(), result.getHeight());
3090		tcu::PixelBufferAccess			errorMask			= errorMaskStorage.getAccess();
3091		tcu::Vec4						pixelBias			(0.0f, 0.0f, 0.0f, 0.0f);
3092		tcu::Vec4						pixelScale			(1.0f, 1.0f, 1.0f, 1.0f);
3093
3094		tcu::clear(errorMask, tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0));
3095
3096		if (dstChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ||
3097			dstChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
3098		{
3099			singleLevelOk = intNearestBlitCompare(source, result, errorMask, mipLevelRegions);
3100		}
3101		else
3102			singleLevelOk = floatNearestBlitCompare(source, result, errorMask, mipLevelRegions);
3103
3104		if (dstFormat != tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))
3105			tcu::computePixelScaleBias(result, pixelScale, pixelBias);
3106
3107		if (!singleLevelOk)
3108		{
3109			log << tcu::TestLog::ImageSet("Compare", "Result comparsion, level " + de::toString(mipLevelNdx))
3110				<< tcu::TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
3111				<< tcu::TestLog::Image("Reference", "Reference", source, pixelScale, pixelBias)
3112				<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask)
3113				<< tcu::TestLog::EndImageSet;
3114		}
3115		else
3116		{
3117			log << tcu::TestLog::ImageSet("Compare", "Result comparsion, level " + de::toString(mipLevelNdx))
3118				<< tcu::TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
3119				<< tcu::TestLog::EndImageSet;
3120		}
3121
3122		allLevelsOk &= singleLevelOk;
3123	}
3124
3125	return allLevelsOk;
3126}
3127
3128tcu::TestStatus BlittingMipmaps::checkTestResult (tcu::ConstPixelBufferAccess result)
3129{
3130	DE_UNREF(result);
3131	DE_ASSERT(m_params.filter == VK_FILTER_NEAREST || m_params.filter == VK_FILTER_LINEAR);
3132	const std::string failMessage("Result image is incorrect");
3133
3134	if (m_params.filter == VK_FILTER_LINEAR)
3135	{
3136		if (!checkLinearFilteredResult())
3137			return tcu::TestStatus::fail(failMessage);
3138	}
3139	else // NEAREST filtering
3140	{
3141		if (!checkNearestFilteredResult())
3142			return tcu::TestStatus::fail(failMessage);
3143	}
3144
3145	return tcu::TestStatus::pass("Pass");
3146}
3147
3148void BlittingMipmaps::copyRegionToTextureLevel (tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region)
3149{
3150	const MirrorMode mirrorMode = getMirrorMode(region.imageBlit.srcOffsets[0],
3151												region.imageBlit.srcOffsets[1],
3152												region.imageBlit.dstOffsets[0],
3153												region.imageBlit.dstOffsets[1]);
3154
3155	flipCoordinates(region, mirrorMode);
3156
3157	const VkOffset3D					srcOffset		= region.imageBlit.srcOffsets[0];
3158	const VkOffset3D					srcExtent		=
3159	{
3160		region.imageBlit.srcOffsets[1].x - srcOffset.x,
3161		region.imageBlit.srcOffsets[1].y - srcOffset.y,
3162		region.imageBlit.srcOffsets[1].z - srcOffset.z
3163	};
3164	const VkOffset3D					dstOffset		= region.imageBlit.dstOffsets[0];
3165	const VkOffset3D					dstExtent		=
3166	{
3167		region.imageBlit.dstOffsets[1].x - dstOffset.x,
3168		region.imageBlit.dstOffsets[1].y - dstOffset.y,
3169		region.imageBlit.dstOffsets[1].z - dstOffset.z
3170	};
3171	const tcu::Sampler::FilterMode		filter			= (m_params.filter == VK_FILTER_LINEAR) ? tcu::Sampler::LINEAR : tcu::Sampler::NEAREST;
3172
3173	if (tcu::isCombinedDepthStencilType(src.getFormat().type))
3174	{
3175		DE_ASSERT(src.getFormat() == dst.getFormat());
3176		// Scale depth.
3177		if (tcu::hasDepthComponent(src.getFormat().order))
3178		{
3179			const tcu::ConstPixelBufferAccess	srcSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcExtent.x, srcExtent.y), tcu::Sampler::MODE_DEPTH);
3180			const tcu::PixelBufferAccess		dstSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_DEPTH);
3181			tcu::scale(dstSubRegion, srcSubRegion, filter);
3182
3183			if (filter == tcu::Sampler::LINEAR)
3184			{
3185				const tcu::ConstPixelBufferAccess	depthSrc			= getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_DEPTH);
3186				const tcu::PixelBufferAccess		unclampedSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(m_unclampedExpectedTextureLevel[0]->getAccess(), dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_DEPTH);
3187				scaleFromWholeSrcBuffer(unclampedSubRegion, depthSrc, srcOffset, srcExtent, filter);
3188			}
3189		}
3190
3191		// Scale stencil.
3192		if (tcu::hasStencilComponent(src.getFormat().order))
3193		{
3194			const tcu::ConstPixelBufferAccess	srcSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcExtent.x, srcExtent.y), tcu::Sampler::MODE_STENCIL);
3195			const tcu::PixelBufferAccess		dstSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_STENCIL);
3196			blit(dstSubRegion, srcSubRegion, filter, mirrorMode);
3197
3198			if (filter == tcu::Sampler::LINEAR)
3199			{
3200				const tcu::ConstPixelBufferAccess	stencilSrc			= getEffectiveDepthStencilAccess(src, tcu::Sampler::MODE_STENCIL);
3201				const tcu::PixelBufferAccess		unclampedSubRegion	= getEffectiveDepthStencilAccess(tcu::getSubregion(m_unclampedExpectedTextureLevel[0]->getAccess(), dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y), tcu::Sampler::MODE_STENCIL);
3202				scaleFromWholeSrcBuffer(unclampedSubRegion, stencilSrc, srcOffset, srcExtent, filter);
3203			}
3204		}
3205	}
3206	else
3207	{
3208		const tcu::ConstPixelBufferAccess	srcSubRegion	= tcu::getSubregion(src, srcOffset.x, srcOffset.y, srcExtent.x, srcExtent.y);
3209		const tcu::PixelBufferAccess		dstSubRegion	= tcu::getSubregion(dst, dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y);
3210		blit(dstSubRegion, srcSubRegion, filter, mirrorMode);
3211
3212		if (filter == tcu::Sampler::LINEAR)
3213		{
3214			const tcu::PixelBufferAccess	unclampedSubRegion	= tcu::getSubregion(m_unclampedExpectedTextureLevel[0]->getAccess(), dstOffset.x, dstOffset.y, dstExtent.x, dstExtent.y);
3215			scaleFromWholeSrcBuffer(unclampedSubRegion, src, srcOffset, srcExtent, filter);
3216		}
3217	}
3218}
3219
3220void BlittingMipmaps::generateExpectedResult (void)
3221{
3222	const tcu::ConstPixelBufferAccess	src	= m_sourceTextureLevel->getAccess();
3223	const tcu::ConstPixelBufferAccess	dst	= m_destinationTextureLevel->getAccess();
3224
3225	for (deUint32 mipLevelNdx = 0u; mipLevelNdx < m_params.mipLevels; mipLevelNdx++)
3226		m_expectedTextureLevel[mipLevelNdx] = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth() >> mipLevelNdx, dst.getHeight() >> mipLevelNdx, dst.getDepth()));
3227
3228	tcu::copy(m_expectedTextureLevel[0]->getAccess(), src);
3229
3230	if (m_params.filter == VK_FILTER_LINEAR)
3231	{
3232		for (deUint32 mipLevelNdx = 0u; mipLevelNdx < m_params.mipLevels; mipLevelNdx++)
3233			m_unclampedExpectedTextureLevel[mipLevelNdx] = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth() >> mipLevelNdx, dst.getHeight() >> mipLevelNdx, dst.getDepth()));
3234
3235		tcu::copy(m_unclampedExpectedTextureLevel[0]->getAccess(), dst);
3236	}
3237
3238	for (deUint32 i = 0; i < m_params.regions.size(); i++)
3239	{
3240		CopyRegion region = m_params.regions[i];
3241		copyRegionToTextureLevel(m_expectedTextureLevel[m_params.regions[i].imageBlit.srcSubresource.mipLevel]->getAccess(), m_expectedTextureLevel[m_params.regions[i].imageBlit.dstSubresource.mipLevel]->getAccess(), region);
3242	}
3243}
3244
3245class BlitMipmapTestCase : public vkt::TestCase
3246{
3247public:
3248							BlitMipmapTestCase		(tcu::TestContext&				testCtx,
3249													 const std::string&				name,
3250													 const std::string&				description,
3251													 const TestParams				params)
3252								: vkt::TestCase	(testCtx, name, description)
3253								, m_params		(params)
3254							{}
3255
3256	virtual TestInstance*	createInstance			(Context&						context) const
3257							{
3258								return new BlittingMipmaps(context, m_params);
3259							}
3260private:
3261	TestParams				m_params;
3262};
3263
3264// Resolve image to image.
3265
3266enum ResolveImageToImageOptions{NO_OPTIONAL_OPERATION, COPY_MS_IMAGE_TO_MS_IMAGE, COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE};
3267class ResolveImageToImage : public CopiesAndBlittingTestInstance
3268{
3269public:
3270												ResolveImageToImage			(Context&							context,
3271																			 TestParams							params,
3272																			 const ResolveImageToImageOptions	options);
3273	virtual tcu::TestStatus						iterate						(void);
3274protected:
3275	virtual tcu::TestStatus						checkTestResult				(tcu::ConstPixelBufferAccess result = tcu::ConstPixelBufferAccess());
3276	void										copyMSImageToMSImage		(void);
3277private:
3278	Move<VkImage>								m_multisampledImage;
3279	de::MovePtr<Allocation>						m_multisampledImageAlloc;
3280
3281	Move<VkImage>								m_destination;
3282	de::MovePtr<Allocation>						m_destinationImageAlloc;
3283
3284	Move<VkImage>								m_multisampledCopyImage;
3285	de::MovePtr<Allocation>						m_multisampledCopyImageAlloc;
3286
3287	const ResolveImageToImageOptions			m_options;
3288
3289	virtual void								copyRegionToTextureLevel	(tcu::ConstPixelBufferAccess	src,
3290																			 tcu::PixelBufferAccess			dst,
3291																			 CopyRegion						region);
3292};
3293
3294ResolveImageToImage::ResolveImageToImage (Context& context, TestParams params, const ResolveImageToImageOptions options)
3295	: CopiesAndBlittingTestInstance	(context, params)
3296	, m_options						(options)
3297{
3298	const VkSampleCountFlagBits	rasterizationSamples	= m_params.samples;
3299
3300	if (!(context.getDeviceProperties().limits.framebufferColorSampleCounts & rasterizationSamples))
3301		throw tcu::NotSupportedError("Unsupported number of rasterization samples");
3302
3303	const InstanceInterface&	vki						= context.getInstanceInterface();
3304	const DeviceInterface&		vk						= context.getDeviceInterface();
3305	const VkPhysicalDevice		vkPhysDevice			= context.getPhysicalDevice();
3306	const VkDevice				vkDevice				= context.getDevice();
3307	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
3308	Allocator&					memAlloc				= m_context.getDefaultAllocator();
3309
3310	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
3311	Move<VkRenderPass>			renderPass;
3312
3313	Move<VkShaderModule>		vertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
3314	Move<VkShaderModule>		fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
3315	std::vector<tcu::Vec4>		vertices;
3316
3317	Move<VkBuffer>				vertexBuffer;
3318	de::MovePtr<Allocation>		vertexBufferAlloc;
3319
3320	Move<VkPipelineLayout>		pipelineLayout;
3321	Move<VkPipeline>			graphicsPipeline;
3322
3323	VkImageFormatProperties properties;
3324	if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(),
3325																				m_params.src.image.format,
3326																				m_params.src.image.imageType,
3327																				VK_IMAGE_TILING_OPTIMAL,
3328																				VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0,
3329																				&properties) == VK_ERROR_FORMAT_NOT_SUPPORTED) ||
3330		(context.getInstanceInterface().getPhysicalDeviceImageFormatProperties (context.getPhysicalDevice(),
3331																				m_params.dst.image.format,
3332																				m_params.dst.image.imageType,
3333																				VK_IMAGE_TILING_OPTIMAL,
3334																				VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0,
3335																				&properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
3336	{
3337		TCU_THROW(NotSupportedError, "Format not supported");
3338	}
3339
3340	// Create color image.
3341	{
3342		VkImageCreateInfo	colorImageParams	=
3343		{
3344			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
3345			DE_NULL,																// const void*				pNext;
3346			0u,																		// VkImageCreateFlags		flags;
3347			m_params.src.image.imageType,											// VkImageType				imageType;
3348			m_params.src.image.format,												// VkFormat					format;
3349			getExtent3D(m_params.src.image),										// VkExtent3D				extent;
3350			1u,																		// deUint32					mipLevels;
3351			getArraySize(m_params.src.image),										// deUint32					arrayLayers;
3352			rasterizationSamples,													// VkSampleCountFlagBits	samples;
3353			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
3354			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage;
3355			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
3356			1u,																		// deUint32					queueFamilyIndexCount;
3357			&queueFamilyIndex,														// const deUint32*			pQueueFamilyIndices;
3358			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout			initialLayout;
3359		};
3360
3361		m_multisampledImage						= createImage(vk, vkDevice, &colorImageParams);
3362
3363		// Allocate and bind color image memory.
3364		m_multisampledImageAlloc				= allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_multisampledImage, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
3365		VK_CHECK(vk.bindImageMemory(vkDevice, *m_multisampledImage, m_multisampledImageAlloc->getMemory(), m_multisampledImageAlloc->getOffset()));
3366
3367		switch (m_options)
3368		{
3369			case COPY_MS_IMAGE_TO_MS_IMAGE:
3370			{
3371				colorImageParams.usage			= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3372				m_multisampledCopyImage			= createImage(vk, vkDevice, &colorImageParams);
3373				// Allocate and bind color image memory.
3374				m_multisampledCopyImageAlloc	= allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_multisampledCopyImage, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
3375				VK_CHECK(vk.bindImageMemory(vkDevice, *m_multisampledCopyImage, m_multisampledCopyImageAlloc->getMemory(), m_multisampledCopyImageAlloc->getOffset()));
3376				break;
3377			}
3378
3379			case COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE:
3380			{
3381				colorImageParams.usage			= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3382				colorImageParams.arrayLayers	= getArraySize(m_params.dst.image);
3383				m_multisampledCopyImage			= createImage(vk, vkDevice, &colorImageParams);
3384				// Allocate and bind color image memory.
3385				m_multisampledCopyImageAlloc	= allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_multisampledCopyImage, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
3386				VK_CHECK(vk.bindImageMemory(vkDevice, *m_multisampledCopyImage, m_multisampledCopyImageAlloc->getMemory(), m_multisampledCopyImageAlloc->getOffset()));
3387				break;
3388			}
3389
3390			default :
3391				break;
3392		}
3393	}
3394
3395	// Create destination image.
3396	{
3397		const VkImageCreateInfo	destinationImageParams	=
3398		{
3399			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
3400			DE_NULL,								// const void*			pNext;
3401			0u,										// VkImageCreateFlags	flags;
3402			m_params.dst.image.imageType,			// VkImageType			imageType;
3403			m_params.dst.image.format,				// VkFormat				format;
3404			getExtent3D(m_params.dst.image),		// VkExtent3D			extent;
3405			1u,										// deUint32				mipLevels;
3406			getArraySize(m_params.dst.image),		// deUint32				arraySize;
3407			VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
3408			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
3409			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
3410				VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
3411			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
3412			1u,										// deUint32				queueFamilyCount;
3413			&queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
3414			VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
3415		};
3416
3417		m_destination			= createImage(vk, vkDevice, &destinationImageParams);
3418		m_destinationImageAlloc	= allocateImage(vki, vk, vkPhysDevice, vkDevice, *m_destination, MemoryRequirement::Any, memAlloc, m_params.allocationKind);
3419		VK_CHECK(vk.bindImageMemory(vkDevice, *m_destination, m_destinationImageAlloc->getMemory(), m_destinationImageAlloc->getOffset()));
3420	}
3421
3422	// Barriers for copying image to buffer
3423	VkImageMemoryBarrier		srcImageBarrier		=
3424	{
3425		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
3426		DE_NULL,									// const void*				pNext;
3427		0u,											// VkAccessFlags			srcAccessMask;
3428		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
3429		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			oldLayout;
3430		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
3431		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
3432		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
3433		m_multisampledImage.get(),					// VkImage					image;
3434		{											// VkImageSubresourceRange	subresourceRange;
3435			VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspectFlags	aspectMask;
3436			0u,									// deUint32				baseMipLevel;
3437			1u,									// deUint32				mipLevels;
3438			0u,									// deUint32				baseArraySlice;
3439			getArraySize(m_params.src.image)	// deUint32				arraySize;
3440		}
3441	};
3442
3443		// Create render pass.
3444	{
3445		const VkAttachmentDescription	attachmentDescriptions[1]	=
3446		{
3447			{
3448				0u,											// VkAttachmentDescriptionFlags		flags;
3449				m_params.src.image.format,					// VkFormat							format;
3450				rasterizationSamples,						// VkSampleCountFlagBits			samples;
3451				VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp;
3452				VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
3453				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
3454				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
3455				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout;
3456				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout;
3457			},
3458		};
3459
3460		const VkAttachmentReference		colorAttachmentReference	=
3461		{
3462			0u,													// deUint32			attachment;
3463			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
3464		};
3465
3466		const VkSubpassDescription		subpassDescription			=
3467		{
3468			0u,									// VkSubpassDescriptionFlags	flags;
3469			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint			pipelineBindPoint;
3470			0u,									// deUint32						inputAttachmentCount;
3471			DE_NULL,							// const VkAttachmentReference*	pInputAttachments;
3472			1u,									// deUint32						colorAttachmentCount;
3473			&colorAttachmentReference,			// const VkAttachmentReference*	pColorAttachments;
3474			DE_NULL,							// const VkAttachmentReference*	pResolveAttachments;
3475			DE_NULL,							// const VkAttachmentReference*	pDepthStencilAttachment;
3476			0u,									// deUint32						preserveAttachmentCount;
3477			DE_NULL								// const VkAttachmentReference*	pPreserveAttachments;
3478		};
3479
3480		const VkRenderPassCreateInfo	renderPassParams			=
3481		{
3482			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
3483			DE_NULL,									// const void*						pNext;
3484			0u,											// VkRenderPassCreateFlags			flags;
3485			1u,											// deUint32							attachmentCount;
3486			attachmentDescriptions,						// const VkAttachmentDescription*	pAttachments;
3487			1u,											// deUint32							subpassCount;
3488			&subpassDescription,						// const VkSubpassDescription*		pSubpasses;
3489			0u,											// deUint32							dependencyCount;
3490			DE_NULL										// const VkSubpassDependency*		pDependencies;
3491		};
3492
3493		renderPass	= createRenderPass(vk, vkDevice, &renderPassParams);
3494	}
3495
3496	// Create pipeline layout
3497	{
3498		const VkPipelineLayoutCreateInfo	pipelineLayoutParams	=
3499		{
3500			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
3501			DE_NULL,											// const void*						pNext;
3502			0u,													// VkPipelineLayoutCreateFlags		flags;
3503			0u,													// deUint32							setLayoutCount;
3504			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
3505			0u,													// deUint32							pushConstantRangeCount;
3506			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
3507		};
3508
3509		pipelineLayout	= createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
3510	}
3511
3512	// Create upper half triangle.
3513	{
3514		const tcu::Vec4	a	(-1.0, -1.0, 0.0, 1.0);
3515		const tcu::Vec4	b	(1.0, -1.0, 0.0, 1.0);
3516		const tcu::Vec4	c	(1.0, 1.0, 0.0, 1.0);
3517		// Add triangle.
3518		vertices.push_back(a);
3519		vertices.push_back(c);
3520		vertices.push_back(b);
3521	}
3522
3523	// Create vertex buffer.
3524	{
3525		const VkDeviceSize			vertexDataSize		= vertices.size() * sizeof(tcu::Vec4);
3526		const VkBufferCreateInfo	vertexBufferParams	=
3527		{
3528			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
3529			DE_NULL,									// const void*			pNext;
3530			0u,											// VkBufferCreateFlags	flags;
3531			vertexDataSize,								// VkDeviceSize			size;
3532			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
3533			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
3534			1u,											// deUint32				queueFamilyIndexCount;
3535			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
3536		};
3537
3538		vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
3539		vertexBufferAlloc	= allocateBuffer(vki, vk, vkPhysDevice, vkDevice, *vertexBuffer, MemoryRequirement::HostVisible, memAlloc, m_params.allocationKind);
3540		VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset()));
3541
3542		// Load vertices into vertex buffer.
3543		deMemcpy(vertexBufferAlloc->getHostPtr(), vertices.data(), (size_t)vertexDataSize);
3544		flushMappedMemoryRange(vk, vkDevice, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexDataSize);
3545	}
3546
3547	{
3548		Move<VkFramebuffer>		framebuffer;
3549		Move<VkImageView>		sourceAttachmentView;
3550
3551		// Create color attachment view.
3552		{
3553			const VkImageViewCreateInfo	colorAttachmentViewParams	=
3554			{
3555				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,				// VkStructureType			sType;
3556				DE_NULL,												// const void*				pNext;
3557				0u,														// VkImageViewCreateFlags	flags;
3558				*m_multisampledImage,									// VkImage					image;
3559				VK_IMAGE_VIEW_TYPE_2D,									// VkImageViewType			viewType;
3560				m_params.src.image.format,								// VkFormat					format;
3561				componentMappingRGBA,									// VkComponentMapping		components;
3562				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
3563			};
3564			sourceAttachmentView	= createImageView(vk, vkDevice, &colorAttachmentViewParams);
3565		}
3566
3567		// Create framebuffer
3568		{
3569			const VkImageView				attachments[1]		=
3570			{
3571					*sourceAttachmentView,
3572			};
3573
3574			const VkFramebufferCreateInfo	framebufferParams	=
3575			{
3576					VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
3577					DE_NULL,											// const void*					pNext;
3578					0u,													// VkFramebufferCreateFlags		flags;
3579					*renderPass,										// VkRenderPass					renderPass;
3580					1u,													// deUint32						attachmentCount;
3581					attachments,										// const VkImageView*			pAttachments;
3582					m_params.src.image.extent.width,					// deUint32						width;
3583					m_params.src.image.extent.height,					// deUint32						height;
3584					1u													// deUint32						layers;
3585			};
3586
3587			framebuffer	= createFramebuffer(vk, vkDevice, &framebufferParams);
3588		}
3589
3590		// Create pipeline
3591		{
3592			const VkPipelineShaderStageCreateInfo			shaderStageParams[2]				=
3593			{
3594				{
3595					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
3596					DE_NULL,													// const void*							pNext;
3597					0u,															// VkPipelineShaderStageCreateFlags		flags;
3598					VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
3599					*vertexShaderModule,										// VkShaderModule						module;
3600					"main",														// const char*							pName;
3601					DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
3602				},
3603				{
3604					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
3605					DE_NULL,													// const void*							pNext;
3606					0u,															// VkPipelineShaderStageCreateFlags		flags;
3607					VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
3608					*fragmentShaderModule,										// VkShaderModule						module;
3609					"main",														// const char*							pName;
3610					DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
3611				}
3612			};
3613
3614			const VkVertexInputBindingDescription			vertexInputBindingDescription		=
3615			{
3616					0u,									// deUint32				binding;
3617					sizeof(tcu::Vec4),					// deUint32				stride;
3618					VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	inputRate;
3619			};
3620
3621			const VkVertexInputAttributeDescription			vertexInputAttributeDescriptions[1]	=
3622			{
3623				{
3624					0u,									// deUint32	location;
3625					0u,									// deUint32	binding;
3626					VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
3627					0u									// deUint32	offset;
3628				}
3629			};
3630
3631			const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams				=
3632			{
3633				VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
3634				DE_NULL,													// const void*								pNext;
3635				0u,															// VkPipelineVertexInputStateCreateFlags	flags;
3636				1u,															// deUint32									vertexBindingDescriptionCount;
3637				&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
3638				1u,															// deUint32									vertexAttributeDescriptionCount;
3639				vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
3640			};
3641
3642			const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams			=
3643			{
3644				VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
3645				DE_NULL,														// const void*								pNext;
3646				0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
3647				VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
3648				false															// VkBool32									primitiveRestartEnable;
3649			};
3650
3651			const VkViewport	viewport	=
3652			{
3653				0.0f,									// float	x;
3654				0.0f,									// float	y;
3655				(float)m_params.src.image.extent.width,	// float	width;
3656				(float)m_params.src.image.extent.height,// float	height;
3657				0.0f,									// float	minDepth;
3658				1.0f									// float	maxDepth;
3659			};
3660
3661			const VkRect2D		scissor		=
3662			{
3663				{ 0, 0 },																// VkOffset2D	offset;
3664				{ m_params.src.image.extent.width, m_params.src.image.extent.height }	// VkExtent2D	extent;
3665			};
3666
3667			const VkPipelineViewportStateCreateInfo			viewportStateParams		=
3668			{
3669				VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType						sType;
3670				DE_NULL,												// const void*							pNext;
3671				0u,														// VkPipelineViewportStateCreateFlags	flags;
3672				1u,														// deUint32								viewportCount;
3673				&viewport,												// const VkViewport*					pViewports;
3674				1u,														// deUint32								scissorCount;
3675				&scissor												// const VkRect2D*						pScissors;
3676			};
3677
3678			const VkPipelineRasterizationStateCreateInfo	rasterStateParams		=
3679			{
3680				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
3681				DE_NULL,													// const void*								pNext;
3682				0u,															// VkPipelineRasterizationStateCreateFlags	flags;
3683				false,														// VkBool32									depthClampEnable;
3684				false,														// VkBool32									rasterizerDiscardEnable;
3685				VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode;
3686				VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode;
3687				VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
3688				VK_FALSE,													// VkBool32									depthBiasEnable;
3689				0.0f,														// float									depthBiasConstantFactor;
3690				0.0f,														// float									depthBiasClamp;
3691				0.0f,														// float									depthBiasSlopeFactor;
3692				1.0f														// float									lineWidth;
3693			};
3694
3695			const VkPipelineMultisampleStateCreateInfo	multisampleStateParams		=
3696			{
3697				VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
3698				DE_NULL,													// const void*								pNext;
3699				0u,															// VkPipelineMultisampleStateCreateFlags	flags;
3700				rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
3701				VK_FALSE,													// VkBool32									sampleShadingEnable;
3702				0.0f,														// float									minSampleShading;
3703				DE_NULL,													// const VkSampleMask*						pSampleMask;
3704				VK_FALSE,													// VkBool32									alphaToCoverageEnable;
3705				VK_FALSE													// VkBool32									alphaToOneEnable;
3706			};
3707
3708			const VkPipelineColorBlendAttachmentState	colorBlendAttachmentState	=
3709			{
3710				false,							// VkBool32			blendEnable;
3711				VK_BLEND_FACTOR_ONE,			// VkBlend			srcBlendColor;
3712				VK_BLEND_FACTOR_ZERO,			// VkBlend			destBlendColor;
3713				VK_BLEND_OP_ADD,				// VkBlendOp		blendOpColor;
3714				VK_BLEND_FACTOR_ONE,			// VkBlend			srcBlendAlpha;
3715				VK_BLEND_FACTOR_ZERO,			// VkBlend			destBlendAlpha;
3716				VK_BLEND_OP_ADD,				// VkBlendOp		blendOpAlpha;
3717				(VK_COLOR_COMPONENT_R_BIT |
3718				VK_COLOR_COMPONENT_G_BIT |
3719				VK_COLOR_COMPONENT_B_BIT |
3720				VK_COLOR_COMPONENT_A_BIT)		// VkChannelFlags	channelWriteMask;
3721			};
3722
3723			const VkPipelineColorBlendStateCreateInfo	colorBlendStateParams	=
3724			{
3725				VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
3726				DE_NULL,													// const void*									pNext;
3727				0u,															// VkPipelineColorBlendStateCreateFlags			flags;
3728				false,														// VkBool32										logicOpEnable;
3729				VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
3730				1u,															// deUint32										attachmentCount;
3731				&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
3732				{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
3733			};
3734
3735			const VkGraphicsPipelineCreateInfo			graphicsPipelineParams	=
3736			{
3737				VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
3738				DE_NULL,											// const void*										pNext;
3739				0u,													// VkPipelineCreateFlags							flags;
3740				2u,													// deUint32											stageCount;
3741				shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
3742				&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
3743				&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
3744				DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
3745				&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
3746				&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
3747				&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
3748				DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
3749				&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
3750				DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
3751				*pipelineLayout,									// VkPipelineLayout									layout;
3752				*renderPass,										// VkRenderPass										renderPass;
3753				0u,													// deUint32											subpass;
3754				0u,													// VkPipeline										basePipelineHandle;
3755				0u													// deInt32											basePipelineIndex;
3756			};
3757
3758			graphicsPipeline	= createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
3759		}
3760
3761		// Create command buffer
3762		{
3763			const VkCommandBufferBeginInfo cmdBufferBeginInfo =
3764			{
3765				VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
3766				DE_NULL,										// const void*						pNext;
3767				0u,												// VkCommandBufferUsageFlags		flags;
3768				(const VkCommandBufferInheritanceInfo*)DE_NULL,
3769			};
3770
3771			const VkClearValue clearValues[1] =
3772			{
3773				makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f),
3774			};
3775
3776			const VkRenderPassBeginInfo renderPassBeginInfo =
3777			{
3778				VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
3779				DE_NULL,												// const void*			pNext;
3780				*renderPass,											// VkRenderPass			renderPass;
3781				*framebuffer,											// VkFramebuffer		framebuffer;
3782				{
3783					{ 0, 0 },
3784					{ m_params.src.image.extent.width, m_params.src.image.extent.height }
3785				},														// VkRect2D				renderArea;
3786				1u,														// deUint32				clearValueCount;
3787				clearValues												// const VkClearValue*	pClearValues;
3788			};
3789
3790			VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
3791			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &srcImageBarrier);
3792			vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
3793
3794			const VkDeviceSize	vertexBufferOffset	= 0u;
3795
3796			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
3797			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
3798			vk.cmdDraw(*m_cmdBuffer, (deUint32)vertices.size(), 1, 0, 0);
3799
3800			vk.cmdEndRenderPass(*m_cmdBuffer);
3801			VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
3802		}
3803
3804		// Queue submit.
3805		{
3806			const VkQueue	queue	= m_context.getUniversalQueue();
3807			submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer);
3808		}
3809	}
3810}
3811
3812tcu::TestStatus ResolveImageToImage::iterate (void)
3813{
3814	const tcu::TextureFormat		srcTcuFormat		= mapVkFormat(m_params.src.image.format);
3815	const tcu::TextureFormat		dstTcuFormat		= mapVkFormat(m_params.dst.image.format);
3816
3817	// upload the destination image
3818	m_destinationTextureLevel	= de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dstTcuFormat,
3819																			(int)m_params.dst.image.extent.width,
3820																			(int)m_params.dst.image.extent.height,
3821																			(int)m_params.dst.image.extent.depth));
3822	generateBuffer(m_destinationTextureLevel->getAccess(), m_params.dst.image.extent.width, m_params.dst.image.extent.height, m_params.dst.image.extent.depth);
3823	uploadImage(m_destinationTextureLevel->getAccess(), m_destination.get(), m_params.dst.image);
3824
3825	m_sourceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(srcTcuFormat,
3826																	(int)m_params.src.image.extent.width,
3827																	(int)m_params.src.image.extent.height,
3828																	(int)m_params.dst.image.extent.depth));
3829
3830	generateBuffer(m_sourceTextureLevel->getAccess(), m_params.src.image.extent.width, m_params.src.image.extent.height, m_params.dst.image.extent.depth, FILL_MODE_MULTISAMPLE);
3831	generateExpectedResult();
3832
3833	switch (m_options)
3834	{
3835		case COPY_MS_IMAGE_TO_MS_IMAGE:
3836		case COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE:
3837			copyMSImageToMSImage();
3838			break;
3839		default:
3840			break;
3841	}
3842
3843	const DeviceInterface&			vk					= m_context.getDeviceInterface();
3844	const VkDevice					vkDevice			= m_context.getDevice();
3845	const VkQueue					queue				= m_context.getUniversalQueue();
3846
3847	std::vector<VkImageResolve>		imageResolves;
3848	for (deUint32 i = 0; i < m_params.regions.size(); i++)
3849		imageResolves.push_back(m_params.regions[i].imageResolve);
3850
3851	const VkImageMemoryBarrier	imageBarriers[]		=
3852	{
3853		// source image
3854		{
3855			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
3856			DE_NULL,									// const void*				pNext;
3857			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			srcAccessMask;
3858			VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
3859			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
3860			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
3861			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
3862			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
3863			m_multisampledImage.get(),					// VkImage					image;
3864			{											// VkImageSubresourceRange	subresourceRange;
3865				getAspectFlags(srcTcuFormat),		// VkImageAspectFlags	aspectMask;
3866				0u,									// deUint32				baseMipLevel;
3867				1u,									// deUint32				mipLevels;
3868				0u,									// deUint32				baseArraySlice;
3869				getArraySize(m_params.src.image)	// deUint32				arraySize;
3870			}
3871		},
3872		// destination image
3873		{
3874			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
3875			DE_NULL,									// const void*				pNext;
3876			0u,											// VkAccessFlags			srcAccessMask;
3877			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
3878			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
3879			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			newLayout;
3880			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
3881			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
3882			m_destination.get(),						// VkImage					image;
3883			{											// VkImageSubresourceRange	subresourceRange;
3884				getAspectFlags(dstTcuFormat),		// VkImageAspectFlags	aspectMask;
3885				0u,									// deUint32				baseMipLevel;
3886				1u,									// deUint32				mipLevels;
3887				0u,									// deUint32				baseArraySlice;
3888				getArraySize(m_params.dst.image)	// deUint32				arraySize;
3889			}
3890		},
3891	};
3892
3893	const VkImageMemoryBarrier postImageBarrier =
3894	{
3895		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
3896		DE_NULL,								// const void*				pNext;
3897		VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			srcAccessMask;
3898		VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
3899		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			oldLayout;
3900		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout;
3901		VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
3902		VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
3903		m_destination.get(),					// VkImage					image;
3904		{										// VkImageSubresourceRange	subresourceRange;
3905			getAspectFlags(dstTcuFormat),		// VkImageAspectFlags		aspectMask;
3906			0u,									// deUint32					baseMipLevel;
3907			1u,									// deUint32					mipLevels;
3908			0u,									// deUint32					baseArraySlice;
3909			getArraySize(m_params.dst.image)	// deUint32					arraySize;
3910		}
3911	};
3912
3913	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
3914	{
3915		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
3916		DE_NULL,												// const void*						pNext;
3917		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
3918		(const VkCommandBufferInheritanceInfo*)DE_NULL,
3919	};
3920
3921	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
3922	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
3923	vk.cmdResolveImage(*m_cmdBuffer, m_multisampledImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_destination.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)m_params.regions.size(), imageResolves.data());
3924	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
3925	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
3926	submitCommandsAndWait(vk, vkDevice, queue, *m_cmdBuffer);
3927
3928	de::MovePtr<tcu::TextureLevel>	resultTextureLevel	= readImage(*m_destination, m_params.dst.image);
3929
3930	return checkTestResult(resultTextureLevel->getAccess());
3931}
3932
3933tcu::TestStatus ResolveImageToImage::checkTestResult (tcu::ConstPixelBufferAccess result)
3934{
3935	const tcu::ConstPixelBufferAccess	expected		= m_expectedTextureLevel[0]->getAccess();
3936	const float							fuzzyThreshold	= 0.01f;
3937
3938	for (int arrayLayerNdx = 0; arrayLayerNdx < (int)getArraySize(m_params.dst.image); ++arrayLayerNdx)
3939	{
3940		const tcu::ConstPixelBufferAccess	expectedSub	= getSubregion (expected, 0, 0, arrayLayerNdx, expected.getWidth(), expected.getHeight(), 1u);
3941		const tcu::ConstPixelBufferAccess	resultSub	= getSubregion (result, 0, 0, arrayLayerNdx, result.getWidth(), result.getHeight(), 1u);
3942		if (!tcu::fuzzyCompare(m_context.getTestContext().getLog(), "Compare", "Result comparsion", expectedSub, resultSub, fuzzyThreshold, tcu::COMPARE_LOG_RESULT))
3943			return tcu::TestStatus::fail("CopiesAndBlitting test");
3944	}
3945
3946	return tcu::TestStatus::pass("CopiesAndBlitting test");
3947}
3948
3949void ResolveImageToImage::copyRegionToTextureLevel(tcu::ConstPixelBufferAccess src, tcu::PixelBufferAccess dst, CopyRegion region)
3950{
3951	VkOffset3D srcOffset	= region.imageResolve.srcOffset;
3952			srcOffset.z		= region.imageResolve.srcSubresource.baseArrayLayer;
3953	VkOffset3D dstOffset	= region.imageResolve.dstOffset;
3954			dstOffset.z		= region.imageResolve.dstSubresource.baseArrayLayer;
3955	VkExtent3D extent		= region.imageResolve.extent;
3956
3957	const tcu::ConstPixelBufferAccess	srcSubRegion		= getSubregion (src, srcOffset.x, srcOffset.y, srcOffset.z, extent.width, extent.height, extent.depth);
3958	// CopyImage acts like a memcpy. Replace the destination format with the srcformat to use a memcpy.
3959	const tcu::PixelBufferAccess		dstWithSrcFormat	(srcSubRegion.getFormat(), dst.getSize(), dst.getDataPtr());
3960	const tcu::PixelBufferAccess		dstSubRegion		= getSubregion (dstWithSrcFormat, dstOffset.x, dstOffset.y, dstOffset.z, extent.width, extent.height, extent.depth);
3961
3962	tcu::copy(dstSubRegion, srcSubRegion);
3963}
3964
3965void ResolveImageToImage::copyMSImageToMSImage (void)
3966{
3967	const DeviceInterface&			vk					= m_context.getDeviceInterface();
3968	const VkDevice					vkDevice			= m_context.getDevice();
3969	const VkQueue					queue				= m_context.getUniversalQueue();
3970	const tcu::TextureFormat		srcTcuFormat		= mapVkFormat(m_params.src.image.format);
3971	std::vector<VkImageCopy>		imageCopies;
3972
3973	for (deUint32 layerNdx = 0; layerNdx < getArraySize(m_params.dst.image); ++layerNdx)
3974	{
3975		const VkImageSubresourceLayers	sourceSubresourceLayers	=
3976		{
3977			getAspectFlags(srcTcuFormat),	// VkImageAspectFlags	aspectMask;
3978			0u,								// uint32_t				mipLevel;
3979			0u,								// uint32_t				baseArrayLayer;
3980			1u								// uint32_t				layerCount;
3981		};
3982
3983		const VkImageSubresourceLayers	destinationSubresourceLayers	=
3984		{
3985			getAspectFlags(srcTcuFormat),	// VkImageAspectFlags	aspectMask;//getAspectFlags(dstTcuFormat)
3986			0u,								// uint32_t				mipLevel;
3987			layerNdx,						// uint32_t				baseArrayLayer;
3988			1u								// uint32_t				layerCount;
3989		};
3990
3991		const VkImageCopy				imageCopy	=
3992		{
3993			sourceSubresourceLayers,			// VkImageSubresourceLayers	srcSubresource;
3994			{0, 0, 0},							// VkOffset3D				srcOffset;
3995			destinationSubresourceLayers,		// VkImageSubresourceLayers	dstSubresource;
3996			{0, 0, 0},							// VkOffset3D				dstOffset;
3997			 getExtent3D(m_params.src.image),	// VkExtent3D				extent;
3998		};
3999		imageCopies.push_back(imageCopy);
4000	}
4001
4002	const VkImageMemoryBarrier		imageBarriers[]		=
4003	{
4004		// source image
4005		{
4006			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
4007			DE_NULL,									// const void*				pNext;
4008			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			srcAccessMask;
4009			VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
4010			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
4011			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
4012			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
4013			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
4014			m_multisampledImage.get(),					// VkImage					image;
4015			{											// VkImageSubresourceRange	subresourceRange;
4016				getAspectFlags(srcTcuFormat),		// VkImageAspectFlags	aspectMask;
4017				0u,									// deUint32				baseMipLevel;
4018				1u,									// deUint32				mipLevels;
4019				0u,									// deUint32				baseArraySlice;
4020				getArraySize(m_params.src.image)	// deUint32				arraySize;
4021			}
4022		},
4023		// destination image
4024		{
4025			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
4026			DE_NULL,									// const void*				pNext;
4027			0,											// VkAccessFlags			srcAccessMask;
4028			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
4029			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			oldLayout;
4030			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			newLayout;
4031			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
4032			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
4033			m_multisampledCopyImage.get(),				// VkImage					image;
4034			{											// VkImageSubresourceRange	subresourceRange;
4035				getAspectFlags(srcTcuFormat),		// VkImageAspectFlags	aspectMask;
4036				0u,									// deUint32				baseMipLevel;
4037				1u,									// deUint32				mipLevels;
4038				0u,									// deUint32				baseArraySlice;
4039				getArraySize(m_params.dst.image)	// deUint32				arraySize;
4040			}
4041		},
4042	};
4043
4044	const VkImageMemoryBarrier	postImageBarriers		=
4045	// source image
4046	{
4047		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
4048		DE_NULL,									// const void*				pNext;
4049		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
4050		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
4051		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
4052		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
4053		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
4054		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
4055		m_multisampledCopyImage.get(),				// VkImage					image;
4056		{											// VkImageSubresourceRange	subresourceRange;
4057			getAspectFlags(srcTcuFormat),		// VkImageAspectFlags	aspectMask;
4058			0u,									// deUint32				baseMipLevel;
4059			1u,									// deUint32				mipLevels;
4060			0u,									// deUint32				baseArraySlice;
4061			getArraySize(m_params.dst.image)	// deUint32				arraySize;
4062		}
4063	};
4064
4065	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
4066	{
4067		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
4068		DE_NULL,												// const void*						pNext;
4069		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
4070		(const VkCommandBufferInheritanceInfo*)DE_NULL,
4071	};
4072
4073	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
4074	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
4075	vk.cmdCopyImage(*m_cmdBuffer, m_multisampledImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_multisampledCopyImage.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)imageCopies.size(), imageCopies.data());
4076	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarriers);
4077	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
4078
4079	submitCommandsAndWait (vk, vkDevice, queue, *m_cmdBuffer);
4080
4081	m_multisampledImage = m_multisampledCopyImage;
4082}
4083
4084class ResolveImageToImageTestCase : public vkt::TestCase
4085{
4086public:
4087							ResolveImageToImageTestCase	(tcu::TestContext&					testCtx,
4088														 const std::string&					name,
4089														 const std::string&					description,
4090														 const TestParams					params,
4091														 const ResolveImageToImageOptions	options = NO_OPTIONAL_OPERATION)
4092								: vkt::TestCase	(testCtx, name, description)
4093								, m_params		(params)
4094								, m_options		(options)
4095							{}
4096	virtual	void			initPrograms				(SourceCollections&		programCollection) const;
4097
4098	virtual TestInstance*	createInstance				(Context&				context) const
4099							{
4100								return new ResolveImageToImage(context, m_params, m_options);
4101							}
4102private:
4103	TestParams							m_params;
4104	const ResolveImageToImageOptions	m_options;
4105};
4106
4107void ResolveImageToImageTestCase::initPrograms (SourceCollections& programCollection) const
4108{
4109	programCollection.glslSources.add("vert") << glu::VertexSource(
4110		"#version 310 es\n"
4111		"layout (location = 0) in highp vec4 a_position;\n"
4112		"void main()\n"
4113		"{\n"
4114		"	gl_Position = a_position;\n"
4115		"}\n");
4116
4117
4118	programCollection.glslSources.add("frag") << glu::FragmentSource(
4119		"#version 310 es\n"
4120		"layout (location = 0) out highp vec4 o_color;\n"
4121		"void main()\n"
4122		"{\n"
4123		"	o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
4124		"}\n");
4125}
4126
4127std::string getSampleCountCaseName (VkSampleCountFlagBits sampleFlag)
4128{
4129	return de::toLower(de::toString(getSampleCountFlagsStr(sampleFlag)).substr(16));
4130}
4131
4132std::string getFormatCaseName (VkFormat format)
4133{
4134	return de::toLower(de::toString(getFormatStr(format)).substr(10));
4135}
4136
4137std::string getImageLayoutCaseName (VkImageLayout layout)
4138{
4139	switch (layout)
4140	{
4141		case VK_IMAGE_LAYOUT_GENERAL:
4142			return "general";
4143		case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
4144		case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
4145			return "optimal";
4146		default:
4147			DE_ASSERT(false);
4148			return "";
4149	}
4150}
4151
4152const deInt32					defaultSize				= 64;
4153const deInt32					defaultHalfSize			= defaultSize / 2;
4154const deInt32					defaultFourthSize		= defaultSize / 4;
4155const VkExtent3D				defaultExtent			= {defaultSize, defaultSize, 1};
4156const VkExtent3D				defaultHalfExtent		= {defaultHalfSize, defaultHalfSize, 1};
4157
4158const VkImageSubresourceLayers	defaultSourceLayer		=
4159{
4160	VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
4161	0u,							// uint32_t				mipLevel;
4162	0u,							// uint32_t				baseArrayLayer;
4163	1u,							// uint32_t				layerCount;
4164};
4165
4166void addImageToImageSimpleTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
4167{
4168	tcu::TestContext& testCtx	= group->getTestContext();
4169
4170	{
4171		TestParams	params;
4172		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
4173		params.src.image.format				= VK_FORMAT_R8G8B8A8_UINT;
4174		params.src.image.extent				= defaultExtent;
4175		params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4176		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
4177		params.dst.image.format				= VK_FORMAT_R8G8B8A8_UINT;
4178		params.dst.image.extent				= defaultExtent;
4179		params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4180		params.allocationKind				= allocationKind;
4181
4182		{
4183			const VkImageCopy				testCopy	=
4184			{
4185				defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
4186				{0, 0, 0},			// VkOffset3D				srcOffset;
4187				defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
4188				{0, 0, 0},			// VkOffset3D				dstOffset;
4189				defaultExtent,		// VkExtent3D				extent;
4190			};
4191
4192			CopyRegion	imageCopy;
4193			imageCopy.imageCopy	= testCopy;
4194
4195			params.regions.push_back(imageCopy);
4196		}
4197
4198		group->addChild(new CopyImageToImageTestCase(testCtx, "whole_image", "Whole image", params));
4199	}
4200
4201	{
4202		TestParams	params;
4203		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
4204		params.src.image.format				= VK_FORMAT_R8G8B8A8_UINT;
4205		params.src.image.extent				= defaultExtent;
4206		params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4207		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
4208		params.dst.image.format				= VK_FORMAT_R32_UINT;
4209		params.dst.image.extent				= defaultExtent;
4210		params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4211		params.allocationKind				= allocationKind;
4212
4213		{
4214			const VkImageCopy				testCopy	=
4215			{
4216				defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
4217				{0, 0, 0},			// VkOffset3D				srcOffset;
4218				defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
4219				{0, 0, 0},			// VkOffset3D				dstOffset;
4220				defaultExtent,		// VkExtent3D				extent;
4221			};
4222
4223			CopyRegion	imageCopy;
4224			imageCopy.imageCopy	= testCopy;
4225
4226			params.regions.push_back(imageCopy);
4227		}
4228
4229		group->addChild(new CopyImageToImageTestCase(testCtx, "whole_image_diff_fromat", "Whole image with different format", params));
4230	}
4231
4232	{
4233		TestParams	params;
4234		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
4235		params.src.image.format				= VK_FORMAT_R8G8B8A8_UINT;
4236		params.src.image.extent				= defaultExtent;
4237		params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4238		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
4239		params.dst.image.format				= VK_FORMAT_R8G8B8A8_UINT;
4240		params.dst.image.extent				= defaultExtent;
4241		params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4242		params.allocationKind				= allocationKind;
4243
4244		{
4245			const VkImageCopy				testCopy	=
4246			{
4247				defaultSourceLayer,									// VkImageSubresourceLayers	srcSubresource;
4248				{0, 0, 0},											// VkOffset3D				srcOffset;
4249				defaultSourceLayer,									// VkImageSubresourceLayers	dstSubresource;
4250				{defaultFourthSize, defaultFourthSize / 2, 0},		// VkOffset3D				dstOffset;
4251				{defaultFourthSize / 2, defaultFourthSize / 2, 1},	// VkExtent3D				extent;
4252			};
4253
4254			CopyRegion	imageCopy;
4255			imageCopy.imageCopy	= testCopy;
4256
4257			params.regions.push_back(imageCopy);
4258		}
4259
4260		group->addChild(new CopyImageToImageTestCase(testCtx, "partial_image", "Partial image", params));
4261	}
4262
4263	{
4264		TestParams	params;
4265		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
4266		params.src.image.format				= VK_FORMAT_D32_SFLOAT;
4267		params.src.image.extent				= defaultExtent;
4268		params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4269		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
4270		params.dst.image.format				= VK_FORMAT_D32_SFLOAT;
4271		params.dst.image.extent				= defaultExtent;
4272		params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4273		params.allocationKind				= allocationKind;
4274
4275		{
4276			const VkImageSubresourceLayers  sourceLayer =
4277			{
4278				VK_IMAGE_ASPECT_DEPTH_BIT,	// VkImageAspectFlags	aspectMask;
4279				0u,							// uint32_t				mipLevel;
4280				0u,							// uint32_t				baseArrayLayer;
4281				1u							// uint32_t				layerCount;
4282			};
4283			const VkImageCopy				testCopy	=
4284			{
4285				sourceLayer,										// VkImageSubresourceLayers	srcSubresource;
4286				{0, 0, 0},											// VkOffset3D				srcOffset;
4287				sourceLayer,										// VkImageSubresourceLayers	dstSubresource;
4288				{defaultFourthSize, defaultFourthSize / 2, 0},		// VkOffset3D				dstOffset;
4289				{defaultFourthSize / 2, defaultFourthSize / 2, 1},	// VkExtent3D				extent;
4290			};
4291
4292			CopyRegion	imageCopy;
4293			imageCopy.imageCopy	= testCopy;
4294
4295			params.regions.push_back(imageCopy);
4296		}
4297
4298		group->addChild(new CopyImageToImageTestCase(testCtx, "depth", "With depth", params));
4299	}
4300
4301	{
4302		TestParams	params;
4303		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
4304		params.src.image.format				= VK_FORMAT_S8_UINT;
4305		params.src.image.extent				= defaultExtent;
4306		params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4307		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
4308		params.dst.image.format				= VK_FORMAT_S8_UINT;
4309		params.dst.image.extent				= defaultExtent;
4310		params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4311		params.allocationKind				= allocationKind;
4312
4313		{
4314			const VkImageSubresourceLayers  sourceLayer =
4315			{
4316				VK_IMAGE_ASPECT_STENCIL_BIT,	// VkImageAspectFlags	aspectMask;
4317				0u,								// uint32_t				mipLevel;
4318				0u,								// uint32_t				baseArrayLayer;
4319				1u								// uint32_t				layerCount;
4320			};
4321			const VkImageCopy				testCopy	=
4322			{
4323				sourceLayer,										// VkImageSubresourceLayers	srcSubresource;
4324				{0, 0, 0},											// VkOffset3D				srcOffset;
4325				sourceLayer,										// VkImageSubresourceLayers	dstSubresource;
4326				{defaultFourthSize, defaultFourthSize / 2, 0},		// VkOffset3D				dstOffset;
4327				{defaultFourthSize / 2, defaultFourthSize / 2, 1},	// VkExtent3D				extent;
4328			};
4329
4330			CopyRegion	imageCopy;
4331			imageCopy.imageCopy	= testCopy;
4332
4333			params.regions.push_back(imageCopy);
4334		}
4335
4336		group->addChild(new CopyImageToImageTestCase(testCtx, "stencil", "With stencil", params));
4337	}
4338}
4339
4340struct CopyColorTestParams
4341{
4342	TestParams		params;
4343	const VkFormat*	compatibleFormats;
4344};
4345
4346void addImageToImageAllFormatsColorSrcFormatDstFormatTests (tcu::TestCaseGroup* group, TestParams params)
4347{
4348	const VkImageLayout copySrcLayouts[]		=
4349	{
4350		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4351		VK_IMAGE_LAYOUT_GENERAL
4352	};
4353	const VkImageLayout copyDstLayouts[]		=
4354	{
4355		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4356		VK_IMAGE_LAYOUT_GENERAL
4357	};
4358
4359	for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(copySrcLayouts); ++srcLayoutNdx)
4360	{
4361		params.src.image.operationLayout = copySrcLayouts[srcLayoutNdx];
4362
4363		for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(copyDstLayouts); ++dstLayoutNdx)
4364		{
4365			params.dst.image.operationLayout = copyDstLayouts[dstLayoutNdx];
4366
4367			const std::string testName	= getImageLayoutCaseName(params.src.image.operationLayout) + "_" +
4368										  getImageLayoutCaseName(params.dst.image.operationLayout);
4369			const std::string description	= "From layout " + getImageLayoutCaseName(params.src.image.operationLayout) +
4370											  " to " + getImageLayoutCaseName(params.dst.image.operationLayout);
4371			group->addChild(new CopyImageToImageTestCase(group->getTestContext(), testName, description, params));
4372		}
4373	}
4374}
4375
4376bool isAllowedImageToImageAllFormatsColorSrcFormatTests(CopyColorTestParams& testParams)
4377{
4378	bool result = true;
4379
4380	if (testParams.params.allocationKind == ALLOCATION_KIND_DEDICATED)
4381	{
4382		DE_ASSERT(!dedicatedAllocationImageToImageFormatsToTestSet.empty());
4383
4384		result =
4385			de::contains(dedicatedAllocationImageToImageFormatsToTestSet, testParams.params.dst.image.format) ||
4386			de::contains(dedicatedAllocationImageToImageFormatsToTestSet, testParams.params.src.image.format);
4387	}
4388
4389	return result;
4390}
4391
4392void addImageToImageAllFormatsColorSrcFormatTests (tcu::TestCaseGroup* group, CopyColorTestParams testParams)
4393{
4394	for (int dstFormatIndex = 0; testParams.compatibleFormats[dstFormatIndex] != VK_FORMAT_UNDEFINED; ++dstFormatIndex)
4395	{
4396		testParams.params.dst.image.format = testParams.compatibleFormats[dstFormatIndex];
4397		if (!isSupportedByFramework(testParams.params.dst.image.format))
4398			continue;
4399
4400		if (!isAllowedImageToImageAllFormatsColorSrcFormatTests(testParams))
4401			continue;
4402
4403		const std::string description	= "Copy to destination format " + getFormatCaseName(testParams.params.dst.image.format);
4404		addTestGroup(group, getFormatCaseName(testParams.params.dst.image.format), description, addImageToImageAllFormatsColorSrcFormatDstFormatTests, testParams.params);
4405	}
4406}
4407
4408const VkFormat	compatibleFormats8Bit[]		=
4409{
4410	VK_FORMAT_R4G4_UNORM_PACK8,
4411	VK_FORMAT_R8_UNORM,
4412	VK_FORMAT_R8_SNORM,
4413	VK_FORMAT_R8_USCALED,
4414	VK_FORMAT_R8_SSCALED,
4415	VK_FORMAT_R8_UINT,
4416	VK_FORMAT_R8_SINT,
4417	VK_FORMAT_R8_SRGB,
4418
4419	VK_FORMAT_UNDEFINED
4420};
4421const VkFormat	compatibleFormats16Bit[]	=
4422{
4423	VK_FORMAT_R4G4B4A4_UNORM_PACK16,
4424	VK_FORMAT_B4G4R4A4_UNORM_PACK16,
4425	VK_FORMAT_R5G6B5_UNORM_PACK16,
4426	VK_FORMAT_B5G6R5_UNORM_PACK16,
4427	VK_FORMAT_R5G5B5A1_UNORM_PACK16,
4428	VK_FORMAT_B5G5R5A1_UNORM_PACK16,
4429	VK_FORMAT_A1R5G5B5_UNORM_PACK16,
4430	VK_FORMAT_R8G8_UNORM,
4431	VK_FORMAT_R8G8_SNORM,
4432	VK_FORMAT_R8G8_USCALED,
4433	VK_FORMAT_R8G8_SSCALED,
4434	VK_FORMAT_R8G8_UINT,
4435	VK_FORMAT_R8G8_SINT,
4436	VK_FORMAT_R8G8_SRGB,
4437	VK_FORMAT_R16_UNORM,
4438	VK_FORMAT_R16_SNORM,
4439	VK_FORMAT_R16_USCALED,
4440	VK_FORMAT_R16_SSCALED,
4441	VK_FORMAT_R16_UINT,
4442	VK_FORMAT_R16_SINT,
4443	VK_FORMAT_R16_SFLOAT,
4444
4445	VK_FORMAT_UNDEFINED
4446};
4447const VkFormat	compatibleFormats24Bit[]	=
4448{
4449	VK_FORMAT_R8G8B8_UNORM,
4450	VK_FORMAT_R8G8B8_SNORM,
4451	VK_FORMAT_R8G8B8_USCALED,
4452	VK_FORMAT_R8G8B8_SSCALED,
4453	VK_FORMAT_R8G8B8_UINT,
4454	VK_FORMAT_R8G8B8_SINT,
4455	VK_FORMAT_R8G8B8_SRGB,
4456	VK_FORMAT_B8G8R8_UNORM,
4457	VK_FORMAT_B8G8R8_SNORM,
4458	VK_FORMAT_B8G8R8_USCALED,
4459	VK_FORMAT_B8G8R8_SSCALED,
4460	VK_FORMAT_B8G8R8_UINT,
4461	VK_FORMAT_B8G8R8_SINT,
4462	VK_FORMAT_B8G8R8_SRGB,
4463
4464	VK_FORMAT_UNDEFINED
4465};
4466const VkFormat	compatibleFormats32Bit[]	=
4467{
4468	VK_FORMAT_R8G8B8A8_UNORM,
4469	VK_FORMAT_R8G8B8A8_SNORM,
4470	VK_FORMAT_R8G8B8A8_USCALED,
4471	VK_FORMAT_R8G8B8A8_SSCALED,
4472	VK_FORMAT_R8G8B8A8_UINT,
4473	VK_FORMAT_R8G8B8A8_SINT,
4474	VK_FORMAT_R8G8B8A8_SRGB,
4475	VK_FORMAT_B8G8R8A8_UNORM,
4476	VK_FORMAT_B8G8R8A8_SNORM,
4477	VK_FORMAT_B8G8R8A8_USCALED,
4478	VK_FORMAT_B8G8R8A8_SSCALED,
4479	VK_FORMAT_B8G8R8A8_UINT,
4480	VK_FORMAT_B8G8R8A8_SINT,
4481	VK_FORMAT_B8G8R8A8_SRGB,
4482	VK_FORMAT_A8B8G8R8_UNORM_PACK32,
4483	VK_FORMAT_A8B8G8R8_SNORM_PACK32,
4484	VK_FORMAT_A8B8G8R8_USCALED_PACK32,
4485	VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
4486	VK_FORMAT_A8B8G8R8_UINT_PACK32,
4487	VK_FORMAT_A8B8G8R8_SINT_PACK32,
4488	VK_FORMAT_A8B8G8R8_SRGB_PACK32,
4489	VK_FORMAT_A2R10G10B10_UNORM_PACK32,
4490	VK_FORMAT_A2R10G10B10_SNORM_PACK32,
4491	VK_FORMAT_A2R10G10B10_USCALED_PACK32,
4492	VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
4493	VK_FORMAT_A2R10G10B10_UINT_PACK32,
4494	VK_FORMAT_A2R10G10B10_SINT_PACK32,
4495	VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4496	VK_FORMAT_A2B10G10R10_SNORM_PACK32,
4497	VK_FORMAT_A2B10G10R10_USCALED_PACK32,
4498	VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
4499	VK_FORMAT_A2B10G10R10_UINT_PACK32,
4500	VK_FORMAT_A2B10G10R10_SINT_PACK32,
4501	VK_FORMAT_R16G16_UNORM,
4502	VK_FORMAT_R16G16_SNORM,
4503	VK_FORMAT_R16G16_USCALED,
4504	VK_FORMAT_R16G16_SSCALED,
4505	VK_FORMAT_R16G16_UINT,
4506	VK_FORMAT_R16G16_SINT,
4507	VK_FORMAT_R16G16_SFLOAT,
4508	VK_FORMAT_R32_UINT,
4509	VK_FORMAT_R32_SINT,
4510	VK_FORMAT_R32_SFLOAT,
4511
4512	VK_FORMAT_UNDEFINED
4513};
4514const VkFormat	compatibleFormats48Bit[]	=
4515{
4516	VK_FORMAT_R16G16B16_UNORM,
4517	VK_FORMAT_R16G16B16_SNORM,
4518	VK_FORMAT_R16G16B16_USCALED,
4519	VK_FORMAT_R16G16B16_SSCALED,
4520	VK_FORMAT_R16G16B16_UINT,
4521	VK_FORMAT_R16G16B16_SINT,
4522	VK_FORMAT_R16G16B16_SFLOAT,
4523
4524	VK_FORMAT_UNDEFINED
4525};
4526const VkFormat	compatibleFormats64Bit[]	=
4527{
4528	VK_FORMAT_R16G16B16A16_UNORM,
4529	VK_FORMAT_R16G16B16A16_SNORM,
4530	VK_FORMAT_R16G16B16A16_USCALED,
4531	VK_FORMAT_R16G16B16A16_SSCALED,
4532	VK_FORMAT_R16G16B16A16_UINT,
4533	VK_FORMAT_R16G16B16A16_SINT,
4534	VK_FORMAT_R16G16B16A16_SFLOAT,
4535	VK_FORMAT_R32G32_UINT,
4536	VK_FORMAT_R32G32_SINT,
4537	VK_FORMAT_R32G32_SFLOAT,
4538	VK_FORMAT_R64_UINT,
4539	VK_FORMAT_R64_SINT,
4540	VK_FORMAT_R64_SFLOAT,
4541
4542	VK_FORMAT_UNDEFINED
4543};
4544const VkFormat	compatibleFormats96Bit[]	=
4545{
4546	VK_FORMAT_R32G32B32_UINT,
4547	VK_FORMAT_R32G32B32_SINT,
4548	VK_FORMAT_R32G32B32_SFLOAT,
4549
4550	VK_FORMAT_UNDEFINED
4551};
4552const VkFormat	compatibleFormats128Bit[]	=
4553{
4554	VK_FORMAT_R32G32B32A32_UINT,
4555	VK_FORMAT_R32G32B32A32_SINT,
4556	VK_FORMAT_R32G32B32A32_SFLOAT,
4557	VK_FORMAT_R64G64_UINT,
4558	VK_FORMAT_R64G64_SINT,
4559	VK_FORMAT_R64G64_SFLOAT,
4560
4561	VK_FORMAT_UNDEFINED
4562};
4563const VkFormat	compatibleFormats192Bit[]	=
4564{
4565	VK_FORMAT_R64G64B64_UINT,
4566	VK_FORMAT_R64G64B64_SINT,
4567	VK_FORMAT_R64G64B64_SFLOAT,
4568
4569	VK_FORMAT_UNDEFINED
4570};
4571const VkFormat	compatibleFormats256Bit[]	=
4572{
4573	VK_FORMAT_R64G64B64A64_UINT,
4574	VK_FORMAT_R64G64B64A64_SINT,
4575	VK_FORMAT_R64G64B64A64_SFLOAT,
4576
4577	VK_FORMAT_UNDEFINED
4578};
4579
4580const VkFormat*	colorImageFormatsToTest[]	=
4581{
4582	compatibleFormats8Bit,
4583	compatibleFormats16Bit,
4584	compatibleFormats24Bit,
4585	compatibleFormats32Bit,
4586	compatibleFormats48Bit,
4587	compatibleFormats64Bit,
4588	compatibleFormats96Bit,
4589	compatibleFormats128Bit,
4590	compatibleFormats192Bit,
4591	compatibleFormats256Bit,
4592};
4593
4594const VkFormat	dedicatedAllocationImageToImageFormatsToTest[]	=
4595{
4596	// From compatibleFormats8Bit
4597	VK_FORMAT_R4G4_UNORM_PACK8,
4598	VK_FORMAT_R8_SRGB,
4599
4600	// From compatibleFormats16Bit
4601	VK_FORMAT_R4G4B4A4_UNORM_PACK16,
4602	VK_FORMAT_R16_SFLOAT,
4603
4604	// From compatibleFormats24Bit
4605	VK_FORMAT_R8G8B8_UNORM,
4606	VK_FORMAT_B8G8R8_SRGB,
4607
4608	// From compatibleFormats32Bit
4609	VK_FORMAT_R8G8B8A8_UNORM,
4610	VK_FORMAT_R32_SFLOAT,
4611
4612	// From compatibleFormats48Bit
4613	VK_FORMAT_R16G16B16_UNORM,
4614	VK_FORMAT_R16G16B16_SFLOAT,
4615
4616	// From compatibleFormats64Bit
4617	VK_FORMAT_R16G16B16A16_UNORM,
4618	VK_FORMAT_R64_SFLOAT,
4619
4620	// From compatibleFormats96Bit
4621	VK_FORMAT_R32G32B32_UINT,
4622	VK_FORMAT_R32G32B32_SFLOAT,
4623
4624	// From compatibleFormats128Bit
4625	VK_FORMAT_R32G32B32A32_UINT,
4626	VK_FORMAT_R64G64_SFLOAT,
4627
4628	// From compatibleFormats192Bit
4629	VK_FORMAT_R64G64B64_UINT,
4630	VK_FORMAT_R64G64B64_SFLOAT,
4631
4632	// From compatibleFormats256Bit
4633	VK_FORMAT_R64G64B64A64_UINT,
4634	VK_FORMAT_R64G64B64A64_SFLOAT,
4635};
4636
4637void addImageToImageAllFormatsColorTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
4638{
4639	TestParams	params;
4640	params.src.image.imageType	= VK_IMAGE_TYPE_2D;
4641	params.src.image.extent		= defaultExtent;
4642	params.dst.image.imageType	= VK_IMAGE_TYPE_2D;
4643	params.dst.image.extent		= defaultExtent;
4644	params.allocationKind		= allocationKind;
4645
4646	for (deInt32 i = 0; i < defaultSize; i += defaultFourthSize)
4647	{
4648		const VkImageCopy				testCopy =
4649		{
4650			defaultSourceLayer,								// VkImageSubresourceLayers	srcSubresource;
4651			{0, 0, 0},										// VkOffset3D				srcOffset;
4652			defaultSourceLayer,								// VkImageSubresourceLayers	dstSubresource;
4653			{i, defaultSize - i - defaultFourthSize, 0},	// VkOffset3D				dstOffset;
4654			{defaultFourthSize, defaultFourthSize, 1},		// VkExtent3D				extent;
4655		};
4656
4657		CopyRegion	imageCopy;
4658		imageCopy.imageCopy = testCopy;
4659
4660		params.regions.push_back(imageCopy);
4661	}
4662
4663	if (allocationKind == ALLOCATION_KIND_DEDICATED)
4664	{
4665		const int numOfColorImageFormatsToTestFilter = DE_LENGTH_OF_ARRAY(colorImageFormatsToTest);
4666		for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTestFilter; ++compatibleFormatsIndex)
4667			dedicatedAllocationImageToImageFormatsToTestSet.insert(dedicatedAllocationImageToImageFormatsToTest[compatibleFormatsIndex]);
4668	}
4669
4670	const int numOfColorImageFormatsToTest = DE_LENGTH_OF_ARRAY(colorImageFormatsToTest);
4671	for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex)
4672	{
4673		const VkFormat*	compatibleFormats	= colorImageFormatsToTest[compatibleFormatsIndex];
4674		for (int srcFormatIndex = 0; compatibleFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex)
4675		{
4676			params.src.image.format = compatibleFormats[srcFormatIndex];
4677			if (!isSupportedByFramework(params.src.image.format))
4678				continue;
4679
4680			CopyColorTestParams	testParams;
4681			testParams.params				= params;
4682			testParams.compatibleFormats	= compatibleFormats;
4683
4684			const std::string description	= "Copy from source format " + getFormatCaseName(params.src.image.format);
4685			addTestGroup(group, getFormatCaseName(params.src.image.format), description, addImageToImageAllFormatsColorSrcFormatTests, testParams);
4686		}
4687	}
4688}
4689
4690void addImageToImageAllFormatsDepthStencilFormatsTests (tcu::TestCaseGroup* group, TestParams params)
4691{
4692	const VkImageLayout copySrcLayouts[]		=
4693	{
4694		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4695		VK_IMAGE_LAYOUT_GENERAL
4696	};
4697	const VkImageLayout copyDstLayouts[]		=
4698	{
4699		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4700		VK_IMAGE_LAYOUT_GENERAL
4701	};
4702
4703	for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(copySrcLayouts); ++srcLayoutNdx)
4704	{
4705		params.src.image.operationLayout = copySrcLayouts[srcLayoutNdx];
4706		for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(copyDstLayouts); ++dstLayoutNdx)
4707		{
4708			params.dst.image.operationLayout = copyDstLayouts[dstLayoutNdx];
4709
4710			const std::string testName		= getImageLayoutCaseName(params.src.image.operationLayout) + "_" +
4711											  getImageLayoutCaseName(params.dst.image.operationLayout);
4712			const std::string description	= "From layout " + getImageLayoutCaseName(params.src.image.operationLayout) +
4713											  " to " + getImageLayoutCaseName(params.dst.image.operationLayout);
4714			group->addChild(new CopyImageToImageTestCase(group->getTestContext(), testName, description, params));
4715		}
4716	}
4717}
4718
4719void addImageToImageAllFormatsDepthStencilTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
4720{
4721	const VkFormat	depthAndStencilFormats[]	=
4722	{
4723		VK_FORMAT_D16_UNORM,
4724		VK_FORMAT_X8_D24_UNORM_PACK32,
4725		VK_FORMAT_D32_SFLOAT,
4726		VK_FORMAT_S8_UINT,
4727		VK_FORMAT_D16_UNORM_S8_UINT,
4728		VK_FORMAT_D24_UNORM_S8_UINT,
4729		VK_FORMAT_D32_SFLOAT_S8_UINT,
4730	};
4731
4732	for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(depthAndStencilFormats); ++compatibleFormatsIndex)
4733	{
4734		TestParams	params;
4735		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
4736		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
4737		params.src.image.extent				= defaultExtent;
4738		params.dst.image.extent				= defaultExtent;
4739		params.src.image.format				= depthAndStencilFormats[compatibleFormatsIndex];
4740		params.dst.image.format				= params.src.image.format;
4741		params.allocationKind				= allocationKind;
4742
4743		const VkImageSubresourceLayers		defaultDepthSourceLayer		= { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, 1u };
4744		const VkImageSubresourceLayers		defaultStencilSourceLayer	= { VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u };
4745
4746		for (deInt32 i = 0; i < defaultSize; i += defaultFourthSize)
4747		{
4748			CopyRegion			copyRegion;
4749			const VkOffset3D	srcOffset	= {0, 0, 0};
4750			const VkOffset3D	dstOffset	= {i, defaultSize - i - defaultFourthSize, 0};
4751			const VkExtent3D	extent		= {defaultFourthSize, defaultFourthSize, 1};
4752
4753			if (tcu::hasDepthComponent(mapVkFormat(params.src.image.format).order))
4754			{
4755				const VkImageCopy				testCopy	=
4756				{
4757					defaultDepthSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
4758					srcOffset,					// VkOffset3D				srcOffset;
4759					defaultDepthSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
4760					dstOffset,					// VkOffset3D				dstOffset;
4761					extent,						// VkExtent3D				extent;
4762				};
4763
4764				copyRegion.imageCopy	= testCopy;
4765				params.regions.push_back(copyRegion);
4766			}
4767			if (tcu::hasStencilComponent(mapVkFormat(params.src.image.format).order))
4768			{
4769				const VkImageCopy				testCopy	=
4770				{
4771					defaultStencilSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
4772					srcOffset,					// VkOffset3D				srcOffset;
4773					defaultStencilSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
4774					dstOffset,					// VkOffset3D				dstOffset;
4775					extent,						// VkExtent3D				extent;
4776				};
4777
4778				copyRegion.imageCopy	= testCopy;
4779				params.regions.push_back(copyRegion);
4780			}
4781		}
4782
4783		const std::string testName		= getFormatCaseName(params.src.image.format) + "_" + getFormatCaseName(params.dst.image.format);
4784		const std::string description	= "Copy from " + getFormatCaseName(params.src.image.format) + " to " + getFormatCaseName(params.dst.image.format);
4785		addTestGroup(group, testName, description, addImageToImageAllFormatsDepthStencilFormatsTests, params);
4786	}
4787}
4788
4789void addImageToImageAllFormatsTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
4790{
4791	addTestGroup(group, "color", "Copy image to image with color formats", addImageToImageAllFormatsColorTests, allocationKind);
4792	addTestGroup(group, "depth_stencil", "Copy image to image with depth/stencil formats", addImageToImageAllFormatsDepthStencilTests, allocationKind);
4793}
4794
4795void addImageToImage3dImagesTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
4796{
4797	tcu::TestContext& testCtx	= group->getTestContext();
4798
4799	{
4800		TestParams	params3DTo2D;
4801		const deUint32	slicesLayers			= 16u;
4802		params3DTo2D.src.image.imageType		= VK_IMAGE_TYPE_3D;
4803		params3DTo2D.src.image.format			= VK_FORMAT_R8G8B8A8_UINT;
4804		params3DTo2D.src.image.extent			= defaultHalfExtent;
4805		params3DTo2D.src.image.extent.depth		= slicesLayers;
4806		params3DTo2D.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4807		params3DTo2D.dst.image.imageType		= VK_IMAGE_TYPE_2D;
4808		params3DTo2D.dst.image.format			= VK_FORMAT_R8G8B8A8_UINT;
4809		params3DTo2D.dst.image.extent			= defaultHalfExtent;
4810		params3DTo2D.dst.image.extent.depth		= slicesLayers;
4811		params3DTo2D.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4812		params3DTo2D.allocationKind				= allocationKind;
4813
4814		for (deUint32 slicesLayersNdx = 0; slicesLayersNdx < slicesLayers; ++slicesLayersNdx)
4815		{
4816			const VkImageSubresourceLayers	sourceLayer	=
4817			{
4818				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
4819				0u,							// uint32_t				mipLevel;
4820				0u,							// uint32_t				baseArrayLayer;
4821				1u							// uint32_t				layerCount;
4822			};
4823
4824			const VkImageSubresourceLayers	destinationLayer	=
4825			{
4826				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
4827				0u,							// uint32_t				mipLevel;
4828				slicesLayersNdx,			// uint32_t				baseArrayLayer;
4829				1u							// uint32_t				layerCount;
4830			};
4831
4832			const VkImageCopy				testCopy	=
4833			{
4834				sourceLayer,						// VkImageSubresourceLayers	srcSubresource;
4835				{0, 0, (deInt32)slicesLayersNdx},	// VkOffset3D					srcOffset;
4836				destinationLayer,					// VkImageSubresourceLayers	dstSubresource;
4837				{0, 0, 0},							// VkOffset3D					dstOffset;
4838				defaultHalfExtent,					// VkExtent3D					extent;
4839			};
4840
4841			CopyRegion	imageCopy;
4842			imageCopy.imageCopy	= testCopy;
4843
4844			params3DTo2D.regions.push_back(imageCopy);
4845		}
4846		group->addChild(new CopyImageToImageTestCase(testCtx, "3d_to_2d_by_slices", "copy 2d layers to 3d slices one by one", params3DTo2D));
4847	}
4848
4849	{
4850		TestParams	params2DTo3D;
4851		const deUint32	slicesLayers			= 16u;
4852		params2DTo3D.src.image.imageType		= VK_IMAGE_TYPE_2D;
4853		params2DTo3D.src.image.format			= VK_FORMAT_R8G8B8A8_UINT;
4854		params2DTo3D.src.image.extent			= defaultHalfExtent;
4855		params2DTo3D.src.image.extent.depth		= slicesLayers;
4856		params2DTo3D.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4857		params2DTo3D.dst.image.imageType		= VK_IMAGE_TYPE_3D;
4858		params2DTo3D.dst.image.format			= VK_FORMAT_R8G8B8A8_UINT;
4859		params2DTo3D.dst.image.extent			= defaultHalfExtent;
4860		params2DTo3D.dst.image.extent.depth		= slicesLayers;
4861		params2DTo3D.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4862		params2DTo3D.allocationKind				= allocationKind;
4863
4864		for (deUint32 slicesLayersNdx = 0; slicesLayersNdx < slicesLayers; ++slicesLayersNdx)
4865		{
4866			const VkImageSubresourceLayers	sourceLayer	=
4867			{
4868				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
4869				0u,							// uint32_t				mipLevel;
4870				slicesLayersNdx,			// uint32_t				baseArrayLayer;
4871				1u							// uint32_t				layerCount;
4872			};
4873
4874			const VkImageSubresourceLayers	destinationLayer	=
4875			{
4876				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
4877				0u,							// uint32_t				mipLevel;
4878				0u,							// uint32_t				baseArrayLayer;
4879				1u							// uint32_t				layerCount;
4880			};
4881
4882			const VkImageCopy				testCopy	=
4883			{
4884				sourceLayer,						// VkImageSubresourceLayers	srcSubresource;
4885				{0, 0, 0},							// VkOffset3D				srcOffset;
4886				destinationLayer,					// VkImageSubresourceLayers	dstSubresource;
4887				{0, 0, (deInt32)slicesLayersNdx},	// VkOffset3D				dstOffset;
4888				defaultHalfExtent,					// VkExtent3D				extent;
4889			};
4890
4891			CopyRegion	imageCopy;
4892			imageCopy.imageCopy	= testCopy;
4893
4894			params2DTo3D.regions.push_back(imageCopy);
4895		}
4896
4897		group->addChild(new CopyImageToImageTestCase(testCtx, "2d_to_3d_by_layers", "copy 3d slices to 2d layers one by one", params2DTo3D));
4898	}
4899
4900	{
4901		TestParams	params3DTo2D;
4902		const deUint32	slicesLayers			= 16u;
4903		params3DTo2D.src.image.imageType		= VK_IMAGE_TYPE_3D;
4904		params3DTo2D.src.image.format			= VK_FORMAT_R8G8B8A8_UINT;
4905		params3DTo2D.src.image.extent			= defaultHalfExtent;
4906		params3DTo2D.src.image.extent.depth		= slicesLayers;
4907		params3DTo2D.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4908		params3DTo2D.dst.image.imageType		= VK_IMAGE_TYPE_2D;
4909		params3DTo2D.dst.image.format			= VK_FORMAT_R8G8B8A8_UINT;
4910		params3DTo2D.dst.image.extent			= defaultHalfExtent;
4911		params3DTo2D.dst.image.extent.depth		= slicesLayers;
4912		params3DTo2D.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4913		params3DTo2D.allocationKind				= allocationKind;
4914
4915		{
4916			const VkImageSubresourceLayers	sourceLayer	=
4917			{
4918				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
4919				0u,							// uint32_t				mipLevel;
4920				0u,							// uint32_t				baseArrayLayer;
4921				1u							// uint32_t				layerCount;
4922			};
4923
4924			const VkImageSubresourceLayers	destinationLayer	=
4925			{
4926				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
4927				0u,							// uint32_t				mipLevel;
4928				0,							// uint32_t				baseArrayLayer;
4929				slicesLayers				// uint32_t				layerCount;
4930			};
4931
4932			const VkImageCopy				testCopy	=
4933			{
4934				sourceLayer,					// VkImageSubresourceLayers	srcSubresource;
4935				{0, 0, 0},						// VkOffset3D				srcOffset;
4936				destinationLayer,				// VkImageSubresourceLayers	dstSubresource;
4937				{0, 0, 0},						// VkOffset3D				dstOffset;
4938				params3DTo2D.src.image.extent	// VkExtent3D				extent;
4939			};
4940
4941			CopyRegion	imageCopy;
4942			imageCopy.imageCopy	= testCopy;
4943
4944			params3DTo2D.regions.push_back(imageCopy);
4945		}
4946		group->addChild(new CopyImageToImageTestCase(testCtx, "3d_to_2d_whole", "copy 3d slices to 2d layers all at once", params3DTo2D));
4947	}
4948
4949	{
4950		TestParams	params2DTo3D;
4951		const deUint32	slicesLayers			= 16u;
4952		params2DTo3D.src.image.imageType		= VK_IMAGE_TYPE_2D;
4953		params2DTo3D.src.image.format			= VK_FORMAT_R8G8B8A8_UINT;
4954		params2DTo3D.src.image.extent			= defaultHalfExtent;
4955		params2DTo3D.src.image.extent.depth		= slicesLayers;
4956		params2DTo3D.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4957		params2DTo3D.dst.image.imageType		= VK_IMAGE_TYPE_3D;
4958		params2DTo3D.dst.image.format			= VK_FORMAT_R8G8B8A8_UINT;
4959		params2DTo3D.dst.image.extent			= defaultHalfExtent;
4960		params2DTo3D.dst.image.extent.depth		= slicesLayers;
4961		params2DTo3D.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4962		params2DTo3D.allocationKind				= allocationKind;
4963
4964		{
4965			const VkImageSubresourceLayers	sourceLayer	=
4966			{
4967				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
4968				0u,							// uint32_t				mipLevel;
4969				0u,							// uint32_t				baseArrayLayer;
4970				slicesLayers				// uint32_t				layerCount;
4971			};
4972
4973			const VkImageSubresourceLayers	destinationLayer	=
4974			{
4975				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
4976				0u,							// uint32_t				mipLevel;
4977				0u,							// uint32_t				baseArrayLayer;
4978				1u							// uint32_t				layerCount;
4979			};
4980
4981			const VkImageCopy				testCopy	=
4982			{
4983				sourceLayer,					// VkImageSubresourceLayers	srcSubresource;
4984				{0, 0, 0},						// VkOffset3D				srcOffset;
4985				destinationLayer,				// VkImageSubresourceLayers	dstSubresource;
4986				{0, 0, 0},						// VkOffset3D				dstOffset;
4987				params2DTo3D.src.image.extent,	// VkExtent3D				extent;
4988			};
4989
4990			CopyRegion	imageCopy;
4991			imageCopy.imageCopy	= testCopy;
4992
4993			params2DTo3D.regions.push_back(imageCopy);
4994		}
4995
4996		group->addChild(new CopyImageToImageTestCase(testCtx, "2d_to_3d_whole", "copy 2d layers to 3d slices all at once", params2DTo3D));
4997	}
4998
4999	{
5000		TestParams	params3DTo2D;
5001		const deUint32	slicesLayers			= 16u;
5002		params3DTo2D.src.image.imageType		= VK_IMAGE_TYPE_3D;
5003		params3DTo2D.src.image.format			= VK_FORMAT_R8G8B8A8_UINT;
5004		params3DTo2D.src.image.extent			= defaultHalfExtent;
5005		params3DTo2D.src.image.extent.depth		= slicesLayers;
5006		params3DTo2D.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5007		params3DTo2D.dst.image.imageType		= VK_IMAGE_TYPE_2D;
5008		params3DTo2D.dst.image.format			= VK_FORMAT_R8G8B8A8_UINT;
5009		params3DTo2D.dst.image.extent			= defaultHalfExtent;
5010		params3DTo2D.dst.image.extent.depth		= slicesLayers;
5011		params3DTo2D.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5012		params3DTo2D.allocationKind				= allocationKind;
5013
5014		const deUint32 regionWidth				= defaultHalfExtent.width / slicesLayers -1;
5015		const deUint32 regionHeight				= defaultHalfExtent.height / slicesLayers -1 ;
5016
5017		for (deUint32 slicesLayersNdx = 0; slicesLayersNdx < slicesLayers; ++slicesLayersNdx)
5018		{
5019			const VkImageSubresourceLayers	sourceLayer	=
5020			{
5021				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
5022				0u,							// uint32_t				mipLevel;
5023				0u,							// uint32_t				baseArrayLayer;
5024				1u							// uint32_t				layerCount;
5025			};
5026
5027			const VkImageSubresourceLayers	destinationLayer	=
5028			{
5029					VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
5030					0u,								// uint32_t				mipLevel;
5031					slicesLayersNdx,				// uint32_t				baseArrayLayer;
5032					1u								// uint32_t				layerCount;
5033			};
5034
5035
5036			const VkImageCopy				testCopy	=
5037			{
5038				sourceLayer,															// VkImageSubresourceLayers	srcSubresource;
5039				{0, (deInt32)(regionHeight*slicesLayersNdx), (deInt32)slicesLayersNdx},	// VkOffset3D				srcOffset;
5040					destinationLayer,													// VkImageSubresourceLayers	dstSubresource;
5041					{(deInt32)(regionWidth*slicesLayersNdx), 0, 0},						// VkOffset3D				dstOffset;
5042					{
5043						(defaultHalfExtent.width - regionWidth*slicesLayersNdx),
5044						(defaultHalfExtent.height - regionHeight*slicesLayersNdx),
5045						1
5046					}																	// VkExtent3D				extent;
5047			};
5048
5049			CopyRegion	imageCopy;
5050			imageCopy.imageCopy = testCopy;
5051			params3DTo2D.regions.push_back(imageCopy);
5052		}
5053		group->addChild(new CopyImageToImageTestCase(testCtx, "3d_to_2d_regions", "copy 3d slices regions to 2d layers", params3DTo2D));
5054	}
5055
5056	{
5057		TestParams	params2DTo3D;
5058		const deUint32	slicesLayers			= 16u;
5059		params2DTo3D.src.image.imageType		= VK_IMAGE_TYPE_2D;
5060		params2DTo3D.src.image.format			= VK_FORMAT_R8G8B8A8_UINT;
5061		params2DTo3D.src.image.extent			= defaultHalfExtent;
5062		params2DTo3D.src.image.extent.depth		= slicesLayers;
5063		params2DTo3D.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5064		params2DTo3D.dst.image.imageType		= VK_IMAGE_TYPE_3D;
5065		params2DTo3D.dst.image.format			= VK_FORMAT_R8G8B8A8_UINT;
5066		params2DTo3D.dst.image.extent			= defaultHalfExtent;
5067		params2DTo3D.dst.image.extent.depth		= slicesLayers;
5068		params2DTo3D.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5069		params2DTo3D.allocationKind				= allocationKind;
5070
5071		const deUint32 regionWidth				= defaultHalfExtent.width / slicesLayers -1;
5072		const deUint32 regionHeight				= defaultHalfExtent.height / slicesLayers -1 ;
5073
5074		for (deUint32 slicesLayersNdx = 0; slicesLayersNdx < slicesLayers; ++slicesLayersNdx)
5075		{
5076			const VkImageSubresourceLayers	sourceLayer	=
5077			{
5078				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
5079				0u,							// uint32_t				mipLevel;
5080				slicesLayersNdx,			// uint32_t				baseArrayLayer;
5081				1u							// uint32_t				layerCount;
5082			};
5083
5084			const VkImageSubresourceLayers	destinationLayer	=
5085			{
5086				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
5087				0u,							// uint32_t				mipLevel;
5088				0u,							// uint32_t				baseArrayLayer;
5089				1u							// uint32_t				layerCount;
5090			};
5091
5092			const VkImageCopy				testCopy	=
5093			{
5094				sourceLayer,																// VkImageSubresourceLayers	srcSubresource;
5095				{(deInt32)(regionWidth*slicesLayersNdx), 0, 0},								// VkOffset3D				srcOffset;
5096				destinationLayer,															// VkImageSubresourceLayers	dstSubresource;
5097				{0, (deInt32)(regionHeight*slicesLayersNdx), (deInt32)(slicesLayersNdx)},	// VkOffset3D				dstOffset;
5098				{
5099					defaultHalfExtent.width - regionWidth*slicesLayersNdx,
5100					defaultHalfExtent.height - regionHeight*slicesLayersNdx,
5101					1
5102				}																			// VkExtent3D				extent;
5103			};
5104
5105			CopyRegion	imageCopy;
5106			imageCopy.imageCopy	= testCopy;
5107
5108			params2DTo3D.regions.push_back(imageCopy);
5109		}
5110
5111		group->addChild(new CopyImageToImageTestCase(testCtx, "2d_to_3d_regions", "copy 2d layers regions to 3d slices", params2DTo3D));
5112	}
5113}
5114
5115void addImageToImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5116{
5117	addTestGroup(group, "simple_tests", "Copy from image to image simple tests", addImageToImageSimpleTests, allocationKind);
5118	addTestGroup(group, "all_formats", "Copy from image to image with all compatible formats", addImageToImageAllFormatsTests, allocationKind);
5119	addTestGroup(group, "3d_images", "Coping operations on 3d images", addImageToImage3dImagesTests, allocationKind);
5120}
5121
5122void addImageToBufferTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5123{
5124	tcu::TestContext& testCtx	= group->getTestContext();
5125
5126	{
5127		TestParams	params;
5128		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5129		params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5130		params.src.image.extent				= defaultExtent;
5131		params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5132		params.dst.buffer.size				= defaultSize * defaultSize;
5133		params.allocationKind				= allocationKind;
5134
5135		const VkBufferImageCopy	bufferImageCopy	=
5136		{
5137			0u,											// VkDeviceSize				bufferOffset;
5138			0u,											// uint32_t					bufferRowLength;
5139			0u,											// uint32_t					bufferImageHeight;
5140			defaultSourceLayer,							// VkImageSubresourceLayers	imageSubresource;
5141			{0, 0, 0},									// VkOffset3D				imageOffset;
5142			defaultExtent								// VkExtent3D				imageExtent;
5143		};
5144		CopyRegion	copyRegion;
5145		copyRegion.bufferImageCopy	= bufferImageCopy;
5146
5147		params.regions.push_back(copyRegion);
5148
5149		group->addChild(new CopyImageToBufferTestCase(testCtx, "whole", "Copy from image to buffer", params));
5150	}
5151
5152	{
5153		TestParams	params;
5154		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5155		params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5156		params.src.image.extent				= defaultExtent;
5157		params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5158		params.dst.buffer.size				= defaultSize * defaultSize;
5159		params.allocationKind				= allocationKind;
5160
5161		const VkBufferImageCopy	bufferImageCopy	=
5162		{
5163			defaultSize * defaultHalfSize,				// VkDeviceSize				bufferOffset;
5164			0u,											// uint32_t					bufferRowLength;
5165			0u,											// uint32_t					bufferImageHeight;
5166			defaultSourceLayer,							// VkImageSubresourceLayers	imageSubresource;
5167			{defaultFourthSize, defaultFourthSize, 0},	// VkOffset3D				imageOffset;
5168			defaultHalfExtent							// VkExtent3D				imageExtent;
5169		};
5170		CopyRegion	copyRegion;
5171		copyRegion.bufferImageCopy	= bufferImageCopy;
5172
5173		params.regions.push_back(copyRegion);
5174
5175		group->addChild(new CopyImageToBufferTestCase(testCtx, "buffer_offset", "Copy from image to buffer with buffer offset", params));
5176	}
5177
5178	{
5179		TestParams	params;
5180		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5181		params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5182		params.src.image.extent				= defaultExtent;
5183		params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5184		params.dst.buffer.size				= defaultSize * defaultSize;
5185		params.allocationKind				= allocationKind;
5186
5187		const int			pixelSize	= tcu::getPixelSize(mapVkFormat(params.src.image.format));
5188		const VkDeviceSize	bufferSize	= pixelSize * params.dst.buffer.size;
5189		const VkDeviceSize	offsetSize	= pixelSize * defaultFourthSize * defaultFourthSize;
5190		deUint32			divisor		= 1;
5191		for (VkDeviceSize offset = 0; offset < bufferSize - offsetSize; offset += offsetSize, ++divisor)
5192		{
5193			const deUint32			bufferRowLength		= defaultFourthSize;
5194			const deUint32			bufferImageHeight	= defaultFourthSize;
5195			const VkExtent3D		imageExtent			= {defaultFourthSize / divisor, defaultFourthSize, 1};
5196			DE_ASSERT(!bufferRowLength || bufferRowLength >= imageExtent.width);
5197			DE_ASSERT(!bufferImageHeight || bufferImageHeight >= imageExtent.height);
5198			DE_ASSERT(imageExtent.width * imageExtent.height *imageExtent.depth <= offsetSize);
5199
5200			CopyRegion				region;
5201			const VkBufferImageCopy	bufferImageCopy		=
5202			{
5203				offset,						// VkDeviceSize				bufferOffset;
5204				bufferRowLength,			// uint32_t					bufferRowLength;
5205				bufferImageHeight,			// uint32_t					bufferImageHeight;
5206				defaultSourceLayer,			// VkImageSubresourceLayers	imageSubresource;
5207				{0, 0, 0},					// VkOffset3D				imageOffset;
5208				imageExtent					// VkExtent3D				imageExtent;
5209			};
5210			region.bufferImageCopy	= bufferImageCopy;
5211			params.regions.push_back(region);
5212		}
5213
5214		group->addChild(new CopyImageToBufferTestCase(testCtx, "regions", "Copy from image to buffer with multiple regions", params));
5215	}
5216}
5217
5218void addBufferToImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5219{
5220	tcu::TestContext& testCtx	= group->getTestContext();
5221
5222	{
5223		TestParams	params;
5224		params.src.buffer.size				= defaultSize * defaultSize;
5225		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5226		params.dst.image.format				= VK_FORMAT_R8G8B8A8_UINT;
5227		params.dst.image.extent				= defaultExtent;
5228		params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5229		params.allocationKind				= allocationKind;
5230
5231		const VkBufferImageCopy	bufferImageCopy	=
5232		{
5233			0u,											// VkDeviceSize				bufferOffset;
5234			0u,											// uint32_t					bufferRowLength;
5235			0u,											// uint32_t					bufferImageHeight;
5236			defaultSourceLayer,							// VkImageSubresourceLayers	imageSubresource;
5237			{0, 0, 0},									// VkOffset3D				imageOffset;
5238			defaultExtent								// VkExtent3D				imageExtent;
5239		};
5240		CopyRegion	copyRegion;
5241		copyRegion.bufferImageCopy	= bufferImageCopy;
5242
5243		params.regions.push_back(copyRegion);
5244
5245		group->addChild(new CopyBufferToImageTestCase(testCtx, "whole", "Copy from buffer to image", params));
5246	}
5247
5248	{
5249		TestParams	params;
5250		params.src.buffer.size				= defaultSize * defaultSize;
5251		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5252		params.dst.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5253		params.dst.image.extent				= defaultExtent;
5254		params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5255		params.allocationKind				= allocationKind;
5256
5257		CopyRegion	region;
5258		deUint32	divisor	= 1;
5259		for (int offset = 0; (offset + defaultFourthSize / divisor < defaultSize) && (defaultFourthSize > divisor); offset += defaultFourthSize / divisor++)
5260		{
5261			const VkBufferImageCopy	bufferImageCopy	=
5262			{
5263				0u,																// VkDeviceSize				bufferOffset;
5264				0u,																// uint32_t					bufferRowLength;
5265				0u,																// uint32_t					bufferImageHeight;
5266				defaultSourceLayer,												// VkImageSubresourceLayers	imageSubresource;
5267				{offset, defaultHalfSize, 0},									// VkOffset3D				imageOffset;
5268				{defaultFourthSize / divisor, defaultFourthSize / divisor, 1}	// VkExtent3D				imageExtent;
5269			};
5270			region.bufferImageCopy	= bufferImageCopy;
5271			params.regions.push_back(region);
5272		}
5273
5274		group->addChild(new CopyBufferToImageTestCase(testCtx, "regions", "Copy from buffer to image with multiple regions", params));
5275	}
5276
5277	{
5278		TestParams	params;
5279		params.src.buffer.size				= defaultSize * defaultSize;
5280		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5281		params.dst.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5282		params.dst.image.extent				= defaultExtent;
5283		params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5284		params.allocationKind				= allocationKind;
5285
5286		const VkBufferImageCopy	bufferImageCopy	=
5287		{
5288			defaultFourthSize,							// VkDeviceSize				bufferOffset;
5289			defaultHalfSize + defaultFourthSize,		// uint32_t					bufferRowLength;
5290			defaultHalfSize + defaultFourthSize,		// uint32_t					bufferImageHeight;
5291			defaultSourceLayer,							// VkImageSubresourceLayers	imageSubresource;
5292			{defaultFourthSize, defaultFourthSize, 0},	// VkOffset3D				imageOffset;
5293			defaultHalfExtent							// VkExtent3D				imageExtent;
5294		};
5295		CopyRegion	copyRegion;
5296		copyRegion.bufferImageCopy	= bufferImageCopy;
5297
5298		params.regions.push_back(copyRegion);
5299
5300		group->addChild(new CopyBufferToImageTestCase(testCtx, "buffer_offset", "Copy from buffer to image with buffer offset", params));
5301	}
5302}
5303
5304void addBufferToBufferTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5305{
5306	tcu::TestContext&				testCtx					= group->getTestContext();
5307
5308	{
5309		TestParams			params;
5310		params.src.buffer.size	= defaultSize;
5311		params.dst.buffer.size	= defaultSize;
5312		params.allocationKind	= allocationKind;
5313
5314		const VkBufferCopy	bufferCopy	=
5315		{
5316			0u,				// VkDeviceSize	srcOffset;
5317			0u,				// VkDeviceSize	dstOffset;
5318			defaultSize,	// VkDeviceSize	size;
5319		};
5320
5321		CopyRegion	copyRegion;
5322		copyRegion.bufferCopy	= bufferCopy;
5323		params.regions.push_back(copyRegion);
5324
5325		group->addChild(new BufferToBufferTestCase(testCtx, "whole", "Whole buffer", params));
5326	}
5327
5328	// Filter is VK_FILTER_NEAREST.
5329	{
5330		TestParams			params;
5331		params.src.buffer.size	= defaultFourthSize;
5332		params.dst.buffer.size	= defaultFourthSize;
5333		params.allocationKind	= allocationKind;
5334
5335		const VkBufferCopy	bufferCopy	=
5336		{
5337			12u,	// VkDeviceSize	srcOffset;
5338			4u,		// VkDeviceSize	dstOffset;
5339			1u,		// VkDeviceSize	size;
5340		};
5341
5342		CopyRegion	copyRegion;
5343		copyRegion.bufferCopy = bufferCopy;
5344		params.regions.push_back(copyRegion);
5345
5346		group->addChild(new BufferToBufferTestCase(testCtx, "partial", "Partial", params));
5347	}
5348
5349	{
5350		const deUint32		size		= 16;
5351		TestParams			params;
5352		params.src.buffer.size	= size;
5353		params.dst.buffer.size	= size * (size + 1);
5354		params.allocationKind	= allocationKind;
5355
5356		// Copy region with size 1..size
5357		for (unsigned int i = 1; i <= size; i++)
5358		{
5359			const VkBufferCopy	bufferCopy	=
5360			{
5361				0,			// VkDeviceSize	srcOffset;
5362				i * size,	// VkDeviceSize	dstOffset;
5363				i,			// VkDeviceSize	size;
5364			};
5365
5366			CopyRegion	copyRegion;
5367			copyRegion.bufferCopy = bufferCopy;
5368			params.regions.push_back(copyRegion);
5369		}
5370
5371		group->addChild(new BufferToBufferTestCase(testCtx, "regions", "Multiple regions", params));
5372	}
5373}
5374
5375void addBlittingImageSimpleWholeTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5376{
5377	tcu::TestContext&	testCtx			= group->getTestContext();
5378	TestParams			params;
5379	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5380	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5381	params.src.image.extent				= defaultExtent;
5382	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5383	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5384	params.dst.image.extent				= defaultExtent;
5385	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5386	params.allocationKind				= allocationKind;
5387
5388	{
5389		const VkImageBlit				imageBlit =
5390		{
5391			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5392			{
5393				{ 0, 0, 0 },
5394				{ defaultSize, defaultSize, 1 }
5395			},					// VkOffset3D				srcOffsets[2];
5396
5397			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5398			{
5399				{ 0, 0, 0 },
5400				{ defaultSize, defaultSize, 1 }
5401			}					// VkOffset3D				dstOffset[2];
5402		};
5403
5404		CopyRegion	region;
5405		region.imageBlit = imageBlit;
5406		params.regions.push_back(region);
5407	}
5408
5409	// Filter is VK_FILTER_NEAREST.
5410	{
5411		params.filter					= VK_FILTER_NEAREST;
5412		const std::string description	= "Nearest filter";
5413
5414		params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM;
5415		group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params));
5416
5417		params.dst.image.format = VK_FORMAT_R32_SFLOAT;
5418		const std::string	descriptionOfRGBAToR32(description + " and different formats (R8G8B8A8 -> R32)");
5419		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params));
5420
5421		params.dst.image.format = VK_FORMAT_B8G8R8A8_UNORM;
5422		const std::string	descriptionOfRGBAToBGRA(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5423		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params));
5424	}
5425
5426	// Filter is VK_FILTER_LINEAR.
5427	{
5428		params.filter					= VK_FILTER_LINEAR;
5429		const std::string description	= "Linear filter";
5430
5431		params.dst.image.format = VK_FORMAT_R8G8B8A8_UNORM;
5432		group->addChild(new BlitImageTestCase(testCtx, "linear", description, params));
5433
5434		params.dst.image.format = VK_FORMAT_R32_SFLOAT;
5435		const std::string	descriptionOfRGBAToR32(description + " and different formats (R8G8B8A8 -> R32)");
5436		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params));
5437
5438		params.dst.image.format = VK_FORMAT_B8G8R8A8_UNORM;
5439		const std::string	descriptionOfRGBAToBGRA(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5440		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params));
5441	}
5442}
5443
5444void addBlittingImageSimpleMirrorXYTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5445{
5446	tcu::TestContext&	testCtx			= group->getTestContext();
5447	TestParams			params;
5448	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5449	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5450	params.src.image.extent				= defaultExtent;
5451	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5452	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5453	params.dst.image.extent				= defaultExtent;
5454	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5455	params.allocationKind				= allocationKind;
5456
5457	{
5458		const VkImageBlit				imageBlit	=
5459		{
5460			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5461			{
5462				{0, 0, 0},
5463				{defaultSize, defaultSize, 1}
5464			},					// VkOffset3D				srcOffsets[2];
5465
5466			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5467			{
5468				{defaultSize, defaultSize, 0},
5469				{0, 0, 1}
5470			}					// VkOffset3D				dstOffset[2];
5471		};
5472
5473		CopyRegion	region;
5474		region.imageBlit = imageBlit;
5475		params.regions.push_back(region);
5476	}
5477
5478	// Filter is VK_FILTER_NEAREST.
5479	{
5480		params.filter					= VK_FILTER_NEAREST;
5481		const std::string description	= "Nearest filter";
5482
5483		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5484		group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params));
5485
5486		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5487		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5488		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params));
5489
5490		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5491		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5492		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params));
5493	}
5494
5495	// Filter is VK_FILTER_LINEAR.
5496	{
5497		params.filter					= VK_FILTER_LINEAR;
5498		const std::string description	= "Linear filter";
5499
5500		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5501		group->addChild(new BlitImageTestCase(testCtx, "linear", description, params));
5502
5503		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5504		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5505		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params));
5506
5507		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5508		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5509		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params));
5510	}
5511}
5512
5513void addBlittingImageSimpleMirrorXTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5514{
5515	tcu::TestContext&	testCtx			= group->getTestContext();
5516	TestParams			params;
5517	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5518	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5519	params.src.image.extent				= defaultExtent;
5520	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5521	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5522	params.dst.image.extent				= defaultExtent;
5523	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5524	params.allocationKind				= allocationKind;
5525
5526	{
5527		const VkImageBlit				imageBlit	=
5528		{
5529			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5530			{
5531				{0, 0, 0},
5532				{defaultSize, defaultSize, 1}
5533			},					// VkOffset3D				srcOffsets[2];
5534
5535			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5536			{
5537				{defaultSize, 0, 0},
5538				{0, defaultSize, 1}
5539			}					// VkOffset3D				dstOffset[2];
5540		};
5541
5542		CopyRegion	region;
5543		region.imageBlit = imageBlit;
5544		params.regions.push_back(region);
5545	}
5546
5547	// Filter is VK_FILTER_NEAREST.
5548	{
5549		params.filter					= VK_FILTER_NEAREST;
5550		const std::string description	= "Nearest filter";
5551
5552		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5553		group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params));
5554
5555		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5556		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5557		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params));
5558
5559		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5560		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5561		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params));
5562	}
5563
5564	// Filter is VK_FILTER_LINEAR.
5565	{
5566		params.filter					= VK_FILTER_LINEAR;
5567		const std::string description	= "Linear filter";
5568
5569		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5570		group->addChild(new BlitImageTestCase(testCtx, "linear", description, params));
5571
5572		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5573		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5574		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params));
5575
5576		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5577		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5578		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params));
5579	}
5580}
5581
5582void addBlittingImageSimpleMirrorYTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5583{
5584	tcu::TestContext&	testCtx			= group->getTestContext();
5585	TestParams			params;
5586	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5587	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5588	params.src.image.extent				= defaultExtent;
5589	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5590	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5591	params.dst.image.extent				= defaultExtent;
5592	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5593	params.allocationKind				= allocationKind;
5594
5595	{
5596		const VkImageBlit				imageBlit	=
5597		{
5598			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5599			{
5600				{0, 0, 0},
5601				{defaultSize, defaultSize, 1}
5602			},					// VkOffset3D				srcOffsets[2];
5603
5604			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5605			{
5606				{0, defaultSize, 0},
5607				{defaultSize, 0, 1}
5608			}					// VkOffset3D				dstOffset[2];
5609		};
5610
5611		CopyRegion	region;
5612		region.imageBlit = imageBlit;
5613		params.regions.push_back(region);
5614	}
5615
5616	// Filter is VK_FILTER_NEAREST.
5617	{
5618		params.filter					= VK_FILTER_NEAREST;
5619		const std::string description	= "Nearest filter";
5620
5621		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5622		group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params));
5623
5624		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5625		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5626		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params));
5627
5628		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5629		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5630		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params));
5631	}
5632
5633	// Filter is VK_FILTER_LINEAR.
5634	{
5635		params.filter					= VK_FILTER_LINEAR;
5636		const std::string description	= "Linear filter";
5637
5638		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5639		group->addChild(new BlitImageTestCase(testCtx, "linear", description, params));
5640
5641		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5642		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5643		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params));
5644
5645		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5646		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5647		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params));
5648	}
5649}
5650
5651void addBlittingImageSimpleMirrorSubregionsTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5652{
5653	tcu::TestContext&	testCtx			= group->getTestContext();
5654	TestParams			params;
5655	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5656	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5657	params.src.image.extent				= defaultExtent;
5658	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5659	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5660	params.dst.image.extent				= defaultExtent;
5661	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5662	params.allocationKind				= allocationKind;
5663
5664	// No mirroring.
5665	{
5666		const VkImageBlit				imageBlit	=
5667		{
5668			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5669			{
5670				{0, 0, 0},
5671				{defaultHalfSize, defaultHalfSize, 1}
5672			},					// VkOffset3D				srcOffsets[2];
5673
5674			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5675			{
5676				{0, 0, 0},
5677				{defaultHalfSize, defaultHalfSize, 1}
5678			}					// VkOffset3D				dstOffset[2];
5679		};
5680
5681		CopyRegion	region;
5682		region.imageBlit = imageBlit;
5683		params.regions.push_back(region);
5684	}
5685
5686	// Flipping y coordinates.
5687	{
5688		const VkImageBlit				imageBlit	=
5689		{
5690			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5691			{
5692				{defaultHalfSize, 0, 0},
5693				{defaultSize, defaultHalfSize, 1}
5694			},					// VkOffset3D				srcOffsets[2];
5695
5696			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5697			{
5698				{defaultHalfSize, defaultHalfSize, 0},
5699				{defaultSize, 0, 1}
5700			}					// VkOffset3D				dstOffset[2];
5701		};
5702		CopyRegion	region;
5703		region.imageBlit = imageBlit;
5704		params.regions.push_back(region);
5705	}
5706
5707	// Flipping x coordinates.
5708	{
5709		const VkImageBlit				imageBlit	=
5710		{
5711			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5712			{
5713				{0, defaultHalfSize, 0},
5714				{defaultHalfSize, defaultSize, 1}
5715			},					// VkOffset3D				srcOffsets[2];
5716
5717			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5718			{
5719				{defaultHalfSize, defaultHalfSize, 0},
5720				{0, defaultSize, 1}
5721			}					// VkOffset3D				dstOffset[2];
5722		};
5723
5724		CopyRegion	region;
5725		region.imageBlit = imageBlit;
5726		params.regions.push_back(region);
5727	}
5728
5729	// Flipping x and y coordinates.
5730	{
5731		const VkImageBlit				imageBlit	=
5732		{
5733			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5734			{
5735				{defaultHalfSize, defaultHalfSize, 0},
5736				{defaultSize, defaultSize, 1}
5737			},					// VkOffset3D				srcOffsets[2];
5738
5739			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5740			{
5741				{defaultSize, defaultSize, 0},
5742				{defaultHalfSize, defaultHalfSize, 1}
5743			}					// VkOffset3D				dstOffset[2];
5744		};
5745
5746		CopyRegion	region;
5747		region.imageBlit = imageBlit;
5748		params.regions.push_back(region);
5749	}
5750
5751	// Filter is VK_FILTER_NEAREST.
5752	{
5753		params.filter					= VK_FILTER_NEAREST;
5754		const std::string description	= "Nearest filter";
5755
5756		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5757		group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params));
5758
5759		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5760		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5761		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params));
5762
5763		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5764		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5765		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params));
5766	}
5767
5768	// Filter is VK_FILTER_LINEAR.
5769	{
5770		params.filter					= VK_FILTER_LINEAR;
5771		const std::string description	= "Linear filter";
5772
5773		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5774		group->addChild(new BlitImageTestCase(testCtx, "linear", description, params));
5775
5776		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5777		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5778		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params));
5779
5780		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5781		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5782		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params));
5783	}
5784}
5785
5786void addBlittingImageSimpleScalingWhole1Tests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5787{
5788	tcu::TestContext&	testCtx			= group->getTestContext();
5789	TestParams			params;
5790	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5791	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5792	params.src.image.extent				= defaultExtent;
5793	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5794	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5795	params.dst.image.extent				= defaultHalfExtent;
5796	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5797	params.allocationKind				= allocationKind;
5798
5799	{
5800		const VkImageBlit				imageBlit	=
5801		{
5802			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5803			{
5804				{0, 0, 0},
5805				{defaultSize, defaultSize, 1}
5806			},					// VkOffset3D					srcOffsets[2];
5807
5808			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5809			{
5810				{0, 0, 0},
5811				{defaultHalfSize, defaultHalfSize, 1}
5812			}					// VkOffset3D					dstOffset[2];
5813		};
5814
5815		CopyRegion	region;
5816		region.imageBlit	= imageBlit;
5817		params.regions.push_back(region);
5818	}
5819
5820	// Filter is VK_FILTER_NEAREST.
5821	{
5822		params.filter					= VK_FILTER_NEAREST;
5823		const std::string description	= "Nearest filter";
5824
5825		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5826		group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params));
5827
5828		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5829		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5830		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params));
5831
5832		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5833		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5834		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params));
5835	}
5836
5837	// Filter is VK_FILTER_LINEAR.
5838	{
5839		params.filter					= VK_FILTER_LINEAR;
5840		const std::string description	= "Linear filter";
5841
5842		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5843		group->addChild(new BlitImageTestCase(testCtx, "linear", description, params));
5844
5845		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5846		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)" );
5847		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params));
5848
5849		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5850		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5851		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params));
5852	}
5853}
5854
5855void addBlittingImageSimpleScalingWhole2Tests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5856{
5857	tcu::TestContext&	testCtx			= group->getTestContext();
5858	TestParams			params;
5859	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5860	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5861	params.src.image.extent				= defaultHalfExtent;
5862	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5863	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5864	params.dst.image.extent				= defaultExtent;
5865	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5866	params.allocationKind				= allocationKind;
5867
5868	{
5869		const VkImageBlit				imageBlit	=
5870		{
5871			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5872			{
5873				{0, 0, 0},
5874				{defaultHalfSize, defaultHalfSize, 1}
5875			},					// VkOffset3D					srcOffsets[2];
5876
5877			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5878			{
5879				{0, 0, 0},
5880				{defaultSize, defaultSize, 1}
5881			}					// VkOffset3D					dstOffset[2];
5882		};
5883
5884		CopyRegion	region;
5885		region.imageBlit	= imageBlit;
5886		params.regions.push_back(region);
5887	}
5888
5889	// Filter is VK_FILTER_NEAREST.
5890	{
5891		params.filter					= VK_FILTER_NEAREST;
5892		const std::string description	= "Nearest filter";
5893
5894		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5895		group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params));
5896
5897		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5898		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5899		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params));
5900
5901		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5902		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5903		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params));
5904	}
5905
5906	// Filter is VK_FILTER_LINEAR.
5907	{
5908		params.filter					= VK_FILTER_LINEAR;
5909		const std::string description	= "Linear filter";
5910
5911		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5912		group->addChild(new BlitImageTestCase(testCtx, "linear", description, params));
5913
5914		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5915		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5916		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params));
5917
5918		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5919		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5920		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params));
5921	}
5922}
5923
5924void addBlittingImageSimpleScalingAndOffsetTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5925{
5926	tcu::TestContext&	testCtx			= group->getTestContext();
5927	TestParams			params;
5928	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5929	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5930	params.src.image.extent				= defaultExtent;
5931	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
5932	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
5933	params.dst.image.extent				= defaultExtent;
5934	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
5935	params.allocationKind				= allocationKind;
5936
5937	{
5938		const VkImageBlit				imageBlit	=
5939		{
5940			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
5941			{
5942				{defaultFourthSize, defaultFourthSize, 0},
5943				{defaultFourthSize*3, defaultFourthSize*3, 1}
5944			},					// VkOffset3D					srcOffsets[2];
5945
5946			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
5947			{
5948				{0, 0, 0},
5949				{defaultSize, defaultSize, 1}
5950			}					// VkOffset3D					dstOffset[2];
5951		};
5952
5953		CopyRegion	region;
5954		region.imageBlit	= imageBlit;
5955		params.regions.push_back(region);
5956	}
5957
5958	// Filter is VK_FILTER_NEAREST.
5959	{
5960		params.filter					= VK_FILTER_NEAREST;
5961		const std::string description	= "Nearest filter";
5962
5963		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5964		group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params));
5965
5966		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5967		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5968		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params));
5969
5970		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5971		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5972		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params));
5973	}
5974
5975	// Filter is VK_FILTER_LINEAR.
5976	{
5977		params.filter					= VK_FILTER_LINEAR;
5978		const std::string description	= "Linear filter";
5979
5980		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
5981		group->addChild(new BlitImageTestCase(testCtx, "linear", description, params));
5982
5983		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
5984		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
5985		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params));
5986
5987		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
5988		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
5989		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params));
5990	}
5991}
5992
5993void addBlittingImageSimpleWithoutScalingPartialTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
5994{
5995	tcu::TestContext&	testCtx			= group->getTestContext();
5996	TestParams			params;
5997	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
5998	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
5999	params.src.image.extent				= defaultExtent;
6000	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
6001	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
6002	params.dst.image.extent				= defaultExtent;
6003	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
6004	params.allocationKind				= allocationKind;
6005
6006	{
6007		CopyRegion	region;
6008		for (int i = 0; i < defaultSize; i += defaultFourthSize)
6009		{
6010			const VkImageBlit			imageBlit	=
6011			{
6012				defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
6013				{
6014					{defaultSize - defaultFourthSize - i, defaultSize - defaultFourthSize - i, 0},
6015					{defaultSize - i, defaultSize - i, 1}
6016				},					// VkOffset3D					srcOffsets[2];
6017
6018				defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
6019				{
6020					{i, i, 0},
6021					{i + defaultFourthSize, i + defaultFourthSize, 1}
6022				}					// VkOffset3D					dstOffset[2];
6023			};
6024			region.imageBlit	= imageBlit;
6025			params.regions.push_back(region);
6026		}
6027	}
6028
6029	// Filter is VK_FILTER_NEAREST.
6030	{
6031		params.filter					= VK_FILTER_NEAREST;
6032		const std::string description	= "Nearest filter";
6033
6034		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
6035		group->addChild(new BlitImageTestCase(testCtx, "nearest", description, params));
6036
6037
6038		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
6039		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
6040		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToR32, params));
6041
6042		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
6043		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
6044		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_nearest", descriptionOfRGBAToBGRA, params));
6045	}
6046
6047	// Filter is VK_FILTER_LINEAR.
6048	{
6049		params.filter					= VK_FILTER_LINEAR;
6050		const std::string description	= "Linear filter";
6051
6052		params.dst.image.format	= VK_FORMAT_R8G8B8A8_UNORM;
6053		group->addChild(new BlitImageTestCase(testCtx, "linear", description, params));
6054
6055		params.dst.image.format	= VK_FORMAT_R32_SFLOAT;
6056		const std::string	descriptionOfRGBAToR32	(description + " and different formats (R8G8B8A8 -> R32)");
6057		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToR32, params));
6058
6059		params.dst.image.format	= VK_FORMAT_B8G8R8A8_UNORM;
6060		const std::string	descriptionOfRGBAToBGRA	(description + " and different formats (R8G8B8A8 -> B8G8R8A8)");
6061		group->addChild(new BlitImageTestCase(testCtx, getFormatCaseName(params.dst.image.format) + "_linear", descriptionOfRGBAToBGRA, params));
6062	}
6063}
6064
6065void addBlittingImageSimpleTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6066{
6067	addTestGroup(group, "whole", "Blit without scaling (whole)", addBlittingImageSimpleWholeTests, allocationKind);
6068	addTestGroup(group, "mirror_xy", "Flipping x and y coordinates (whole)", addBlittingImageSimpleMirrorXYTests, allocationKind);
6069	addTestGroup(group, "mirror_x", "Flipping x coordinates (whole)", addBlittingImageSimpleMirrorXTests, allocationKind);
6070	addTestGroup(group, "mirror_y", "Flipping y coordinates (whole)", addBlittingImageSimpleMirrorYTests, allocationKind);
6071	addTestGroup(group, "mirror_subregions", "Mirroring subregions in image (no flip, y flip, x flip, xy flip)", addBlittingImageSimpleMirrorSubregionsTests, allocationKind);
6072	addTestGroup(group, "scaling_whole1", "Blit with scaling (whole, src extent bigger)", addBlittingImageSimpleScalingWhole1Tests, allocationKind);
6073	addTestGroup(group, "scaling_whole2", "Blit with scaling (whole, dst extent bigger)", addBlittingImageSimpleScalingWhole2Tests, allocationKind);
6074	addTestGroup(group, "scaling_and_offset", "Blit with scaling and offset (whole, dst extent bigger)", addBlittingImageSimpleScalingAndOffsetTests, allocationKind);
6075	addTestGroup(group, "without_scaling_partial", "Blit without scaling (partial)", addBlittingImageSimpleWithoutScalingPartialTests, allocationKind);
6076}
6077
6078struct BlitColorTestParams
6079{
6080	TestParams		params;
6081	const VkFormat*	compatibleFormats;
6082	bool			onlyNearest;
6083};
6084
6085bool isAllowedBlittingAllFormatsColorSrcFormatTests(const BlitColorTestParams& testParams)
6086{
6087	bool result = true;
6088
6089	if (testParams.params.allocationKind == ALLOCATION_KIND_DEDICATED)
6090	{
6091		DE_ASSERT(!dedicatedAllocationBlittingFormatsToTestSet.empty());
6092
6093		result =
6094			de::contains(dedicatedAllocationBlittingFormatsToTestSet, testParams.params.dst.image.format) ||
6095			de::contains(dedicatedAllocationBlittingFormatsToTestSet, testParams.params.src.image.format);
6096	}
6097
6098	return result;
6099}
6100
6101
6102void addBlittingImageAllFormatsColorSrcFormatDstFormatTests (tcu::TestCaseGroup* group, BlitColorTestParams testParams)
6103{
6104	tcu::TestContext& testCtx				= group->getTestContext();
6105
6106	const VkImageLayout blitSrcLayouts[]	=
6107	{
6108		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
6109		VK_IMAGE_LAYOUT_GENERAL
6110	};
6111	const VkImageLayout blitDstLayouts[]	=
6112	{
6113		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
6114		VK_IMAGE_LAYOUT_GENERAL
6115	};
6116
6117	for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(blitSrcLayouts); ++srcLayoutNdx)
6118	{
6119		testParams.params.src.image.operationLayout = blitSrcLayouts[srcLayoutNdx];
6120		for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(blitDstLayouts); ++dstLayoutNdx)
6121		{
6122			testParams.params.dst.image.operationLayout = blitDstLayouts[dstLayoutNdx];
6123
6124			testParams.params.filter			= VK_FILTER_NEAREST;
6125			const std::string testName			= getImageLayoutCaseName(testParams.params.src.image.operationLayout) + "_" +
6126												  getImageLayoutCaseName(testParams.params.dst.image.operationLayout);
6127			const std::string description		= "Blit from layout " + getImageLayoutCaseName(testParams.params.src.image.operationLayout) +
6128												  " to " + getImageLayoutCaseName(testParams.params.dst.image.operationLayout);
6129			group->addChild(new BlitImageTestCase(testCtx, testName + "_nearest", description, testParams.params));
6130
6131			if (!testParams.onlyNearest)
6132			{
6133				testParams.params.filter		= VK_FILTER_LINEAR;
6134				group->addChild(new BlitImageTestCase(testCtx, testName + "_linear", description, testParams.params));
6135			}
6136		}
6137	}
6138}
6139
6140void addBlittingImageAllFormatsColorSrcFormatTests (tcu::TestCaseGroup* group, BlitColorTestParams testParams)
6141{
6142	for (int dstFormatIndex = 0; testParams.compatibleFormats[dstFormatIndex] != VK_FORMAT_UNDEFINED; ++dstFormatIndex)
6143	{
6144		testParams.params.dst.image.format	= testParams.compatibleFormats[dstFormatIndex];
6145		if (!isSupportedByFramework(testParams.params.dst.image.format))
6146			continue;
6147
6148		if (!isAllowedBlittingAllFormatsColorSrcFormatTests(testParams))
6149			continue;
6150
6151		const std::string description	= "Blit destination format " + getFormatCaseName(testParams.params.dst.image.format);
6152		addTestGroup(group, getFormatCaseName(testParams.params.dst.image.format), description, addBlittingImageAllFormatsColorSrcFormatDstFormatTests, testParams);
6153	}
6154}
6155
6156const VkFormat	compatibleFormatsUInts[]	=
6157{
6158	VK_FORMAT_R8_UINT,
6159	VK_FORMAT_R8G8_UINT,
6160	VK_FORMAT_R8G8B8_UINT,
6161	VK_FORMAT_B8G8R8_UINT,
6162	VK_FORMAT_R8G8B8A8_UINT,
6163	VK_FORMAT_B8G8R8A8_UINT,
6164	VK_FORMAT_A8B8G8R8_UINT_PACK32,
6165	VK_FORMAT_A2R10G10B10_UINT_PACK32,
6166	VK_FORMAT_A2B10G10R10_UINT_PACK32,
6167	VK_FORMAT_R16_UINT,
6168	VK_FORMAT_R16G16_UINT,
6169	VK_FORMAT_R16G16B16_UINT,
6170	VK_FORMAT_R16G16B16A16_UINT,
6171	VK_FORMAT_R32_UINT,
6172	VK_FORMAT_R32G32_UINT,
6173	VK_FORMAT_R32G32B32_UINT,
6174	VK_FORMAT_R32G32B32A32_UINT,
6175	VK_FORMAT_R64_UINT,
6176	VK_FORMAT_R64G64_UINT,
6177	VK_FORMAT_R64G64B64_UINT,
6178	VK_FORMAT_R64G64B64A64_UINT,
6179
6180	VK_FORMAT_UNDEFINED
6181};
6182const VkFormat	compatibleFormatsSInts[]	=
6183{
6184	VK_FORMAT_R8_SINT,
6185	VK_FORMAT_R8G8_SINT,
6186	VK_FORMAT_R8G8B8_SINT,
6187	VK_FORMAT_B8G8R8_SINT,
6188	VK_FORMAT_R8G8B8A8_SINT,
6189	VK_FORMAT_B8G8R8A8_SINT,
6190	VK_FORMAT_A8B8G8R8_SINT_PACK32,
6191	VK_FORMAT_A2R10G10B10_SINT_PACK32,
6192	VK_FORMAT_A2B10G10R10_SINT_PACK32,
6193	VK_FORMAT_R16_SINT,
6194	VK_FORMAT_R16G16_SINT,
6195	VK_FORMAT_R16G16B16_SINT,
6196	VK_FORMAT_R16G16B16A16_SINT,
6197	VK_FORMAT_R32_SINT,
6198	VK_FORMAT_R32G32_SINT,
6199	VK_FORMAT_R32G32B32_SINT,
6200	VK_FORMAT_R32G32B32A32_SINT,
6201	VK_FORMAT_R64_SINT,
6202	VK_FORMAT_R64G64_SINT,
6203	VK_FORMAT_R64G64B64_SINT,
6204	VK_FORMAT_R64G64B64A64_SINT,
6205
6206	VK_FORMAT_UNDEFINED
6207};
6208const VkFormat	compatibleFormatsFloats[]	=
6209{
6210	VK_FORMAT_R4G4_UNORM_PACK8,
6211	VK_FORMAT_R4G4B4A4_UNORM_PACK16,
6212	VK_FORMAT_B4G4R4A4_UNORM_PACK16,
6213	VK_FORMAT_R5G6B5_UNORM_PACK16,
6214	VK_FORMAT_B5G6R5_UNORM_PACK16,
6215	VK_FORMAT_R5G5B5A1_UNORM_PACK16,
6216	VK_FORMAT_B5G5R5A1_UNORM_PACK16,
6217	VK_FORMAT_A1R5G5B5_UNORM_PACK16,
6218	VK_FORMAT_R8_UNORM,
6219	VK_FORMAT_R8_SNORM,
6220	VK_FORMAT_R8_USCALED,
6221	VK_FORMAT_R8_SSCALED,
6222	VK_FORMAT_R8G8_UNORM,
6223	VK_FORMAT_R8G8_SNORM,
6224	VK_FORMAT_R8G8_USCALED,
6225	VK_FORMAT_R8G8_SSCALED,
6226	VK_FORMAT_R8G8B8_UNORM,
6227	VK_FORMAT_R8G8B8_SNORM,
6228	VK_FORMAT_R8G8B8_USCALED,
6229	VK_FORMAT_R8G8B8_SSCALED,
6230	VK_FORMAT_B8G8R8_UNORM,
6231	VK_FORMAT_B8G8R8_SNORM,
6232	VK_FORMAT_B8G8R8_USCALED,
6233	VK_FORMAT_B8G8R8_SSCALED,
6234	VK_FORMAT_R8G8B8A8_UNORM,
6235	VK_FORMAT_R8G8B8A8_SNORM,
6236	VK_FORMAT_R8G8B8A8_USCALED,
6237	VK_FORMAT_R8G8B8A8_SSCALED,
6238	VK_FORMAT_B8G8R8A8_UNORM,
6239	VK_FORMAT_B8G8R8A8_SNORM,
6240	VK_FORMAT_B8G8R8A8_USCALED,
6241	VK_FORMAT_B8G8R8A8_SSCALED,
6242	VK_FORMAT_A8B8G8R8_UNORM_PACK32,
6243	VK_FORMAT_A8B8G8R8_SNORM_PACK32,
6244	VK_FORMAT_A8B8G8R8_USCALED_PACK32,
6245	VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
6246	VK_FORMAT_A2R10G10B10_UNORM_PACK32,
6247	VK_FORMAT_A2R10G10B10_SNORM_PACK32,
6248	VK_FORMAT_A2R10G10B10_USCALED_PACK32,
6249	VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
6250	VK_FORMAT_A2B10G10R10_UNORM_PACK32,
6251	VK_FORMAT_A2B10G10R10_SNORM_PACK32,
6252	VK_FORMAT_A2B10G10R10_USCALED_PACK32,
6253	VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
6254	VK_FORMAT_R16_UNORM,
6255	VK_FORMAT_R16_SNORM,
6256	VK_FORMAT_R16_USCALED,
6257	VK_FORMAT_R16_SSCALED,
6258	VK_FORMAT_R16_SFLOAT,
6259	VK_FORMAT_R16G16_UNORM,
6260	VK_FORMAT_R16G16_SNORM,
6261	VK_FORMAT_R16G16_USCALED,
6262	VK_FORMAT_R16G16_SSCALED,
6263	VK_FORMAT_R16G16_SFLOAT,
6264	VK_FORMAT_R16G16B16_UNORM,
6265	VK_FORMAT_R16G16B16_SNORM,
6266	VK_FORMAT_R16G16B16_USCALED,
6267	VK_FORMAT_R16G16B16_SSCALED,
6268	VK_FORMAT_R16G16B16_SFLOAT,
6269	VK_FORMAT_R16G16B16A16_UNORM,
6270	VK_FORMAT_R16G16B16A16_SNORM,
6271	VK_FORMAT_R16G16B16A16_USCALED,
6272	VK_FORMAT_R16G16B16A16_SSCALED,
6273	VK_FORMAT_R16G16B16A16_SFLOAT,
6274	VK_FORMAT_R32_SFLOAT,
6275	VK_FORMAT_R32G32_SFLOAT,
6276	VK_FORMAT_R32G32B32_SFLOAT,
6277	VK_FORMAT_R32G32B32A32_SFLOAT,
6278	VK_FORMAT_R64_SFLOAT,
6279	VK_FORMAT_R64G64_SFLOAT,
6280	VK_FORMAT_R64G64B64_SFLOAT,
6281	VK_FORMAT_R64G64B64A64_SFLOAT,
6282	VK_FORMAT_B10G11R11_UFLOAT_PACK32,
6283	VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
6284//	VK_FORMAT_BC1_RGB_UNORM_BLOCK,
6285//	VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
6286//	VK_FORMAT_BC2_UNORM_BLOCK,
6287//	VK_FORMAT_BC3_UNORM_BLOCK,
6288//	VK_FORMAT_BC4_UNORM_BLOCK,
6289//	VK_FORMAT_BC4_SNORM_BLOCK,
6290//	VK_FORMAT_BC5_UNORM_BLOCK,
6291//	VK_FORMAT_BC5_SNORM_BLOCK,
6292//	VK_FORMAT_BC6H_UFLOAT_BLOCK,
6293//	VK_FORMAT_BC6H_SFLOAT_BLOCK,
6294//	VK_FORMAT_BC7_UNORM_BLOCK,
6295//	VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
6296//	VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
6297//	VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
6298//	VK_FORMAT_EAC_R11_UNORM_BLOCK,
6299//	VK_FORMAT_EAC_R11_SNORM_BLOCK,
6300//	VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
6301//	VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
6302//	VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
6303//	VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
6304//	VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
6305//	VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
6306//	VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
6307//	VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
6308//	VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
6309//	VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
6310//	VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
6311//	VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
6312//	VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
6313//	VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
6314//	VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
6315//	VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
6316
6317	VK_FORMAT_UNDEFINED
6318};
6319const VkFormat	compatibleFormatsSrgb[]		=
6320{
6321	VK_FORMAT_R8_SRGB,
6322	VK_FORMAT_R8G8_SRGB,
6323	VK_FORMAT_R8G8B8_SRGB,
6324	VK_FORMAT_B8G8R8_SRGB,
6325	VK_FORMAT_R8G8B8A8_SRGB,
6326	VK_FORMAT_B8G8R8A8_SRGB,
6327	VK_FORMAT_A8B8G8R8_SRGB_PACK32,
6328//	VK_FORMAT_BC1_RGB_SRGB_BLOCK,
6329//	VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
6330//	VK_FORMAT_BC2_SRGB_BLOCK,
6331//	VK_FORMAT_BC3_SRGB_BLOCK,
6332//	VK_FORMAT_BC7_SRGB_BLOCK,
6333//	VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
6334//	VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
6335//	VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
6336//	VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
6337//	VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
6338//	VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
6339//	VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
6340//	VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
6341//	VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
6342//	VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
6343//	VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
6344//	VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
6345//	VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
6346//	VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
6347//	VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
6348//	VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
6349//	VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
6350
6351	VK_FORMAT_UNDEFINED
6352};
6353
6354const VkFormat	dedicatedAllocationBlittingFormatsToTest[]	=
6355{
6356	// compatibleFormatsUInts
6357	VK_FORMAT_R8_UINT,
6358	VK_FORMAT_R64G64B64A64_UINT,
6359
6360	// compatibleFormatsSInts
6361	VK_FORMAT_R8_SINT,
6362	VK_FORMAT_R64G64B64A64_SINT,
6363
6364	// compatibleFormatsFloats
6365	VK_FORMAT_R4G4_UNORM_PACK8,
6366	VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
6367
6368	// compatibleFormatsSrgb
6369	VK_FORMAT_R8_SRGB,
6370	VK_FORMAT_A8B8G8R8_SRGB_PACK32,
6371};
6372
6373void addBlittingImageAllFormatsColorTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6374{
6375	const struct {
6376		const VkFormat*	compatibleFormats;
6377		const bool		onlyNearest;
6378	}	colorImageFormatsToTestBlit[]			=
6379	{
6380		{ compatibleFormatsUInts,	true	},
6381		{ compatibleFormatsSInts,	true	},
6382		{ compatibleFormatsFloats,	false	},
6383		{ compatibleFormatsSrgb,	false	},
6384	};
6385
6386	const int	numOfColorImageFormatsToTest		= DE_LENGTH_OF_ARRAY(colorImageFormatsToTestBlit);
6387
6388	TestParams	params;
6389	params.src.image.imageType	= VK_IMAGE_TYPE_2D;
6390	params.src.image.extent		= defaultExtent;
6391	params.dst.image.imageType	= VK_IMAGE_TYPE_2D;
6392	params.dst.image.extent		= defaultExtent;
6393	params.allocationKind		= allocationKind;
6394
6395	CopyRegion	region;
6396	for (int i = 0, j = 1; (i + defaultFourthSize / j < defaultSize) && (defaultFourthSize > j); i += defaultFourthSize / j++)
6397	{
6398		const VkImageBlit			imageBlit	=
6399		{
6400			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
6401			{
6402				{0, 0, 0},
6403				{defaultSize, defaultSize, 1}
6404			},					// VkOffset3D					srcOffsets[2];
6405
6406			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
6407			{
6408				{i, 0, 0},
6409				{i + defaultFourthSize / j, defaultFourthSize / j, 1}
6410			}					// VkOffset3D					dstOffset[2];
6411		};
6412		region.imageBlit	= imageBlit;
6413		params.regions.push_back(region);
6414	}
6415	for (int i = 0; i < defaultSize; i += defaultFourthSize)
6416	{
6417		const VkImageBlit			imageBlit	=
6418		{
6419			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
6420			{
6421				{i, i, 0},
6422				{i + defaultFourthSize, i + defaultFourthSize, 1}
6423			},					// VkOffset3D					srcOffsets[2];
6424
6425			defaultSourceLayer,	// VkImageSubresourceLayers	dstSubresource;
6426			{
6427				{i, defaultSize / 2, 0},
6428				{i + defaultFourthSize, defaultSize / 2 + defaultFourthSize, 1}
6429			}					// VkOffset3D					dstOffset[2];
6430		};
6431		region.imageBlit	= imageBlit;
6432		params.regions.push_back(region);
6433	}
6434
6435	if (allocationKind == ALLOCATION_KIND_DEDICATED)
6436	{
6437		const int numOfColorImageFormatsToTestFilter = DE_LENGTH_OF_ARRAY(dedicatedAllocationBlittingFormatsToTest);
6438		for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTestFilter; ++compatibleFormatsIndex)
6439			dedicatedAllocationBlittingFormatsToTestSet.insert(dedicatedAllocationBlittingFormatsToTest[compatibleFormatsIndex]);
6440	}
6441
6442	for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex)
6443	{
6444		const VkFormat*	compatibleFormats	= colorImageFormatsToTestBlit[compatibleFormatsIndex].compatibleFormats;
6445		const bool		onlyNearest			= colorImageFormatsToTestBlit[compatibleFormatsIndex].onlyNearest;
6446		for (int srcFormatIndex = 0; compatibleFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex)
6447		{
6448			params.src.image.format	= compatibleFormats[srcFormatIndex];
6449			if (!isSupportedByFramework(params.src.image.format))
6450				continue;
6451
6452			BlitColorTestParams		testParams;
6453			testParams.params				= params;
6454			testParams.compatibleFormats	= compatibleFormats;
6455			testParams.onlyNearest			= onlyNearest;
6456
6457			const std::string description	= "Blit source format " + getFormatCaseName(params.src.image.format);
6458			addTestGroup(group, getFormatCaseName(params.src.image.format), description, addBlittingImageAllFormatsColorSrcFormatTests, testParams);
6459		}
6460	}
6461}
6462
6463void addBlittingImageAllFormatsDepthStencilFormatsTests (tcu::TestCaseGroup* group, TestParams params)
6464{
6465	const VkImageLayout blitSrcLayouts[]	=
6466	{
6467		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
6468		VK_IMAGE_LAYOUT_GENERAL
6469	};
6470	const VkImageLayout blitDstLayouts[]	=
6471	{
6472		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
6473		VK_IMAGE_LAYOUT_GENERAL
6474	};
6475
6476	for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(blitSrcLayouts); ++srcLayoutNdx)
6477	{
6478		params.src.image.operationLayout	= blitSrcLayouts[srcLayoutNdx];
6479
6480		for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(blitDstLayouts); ++dstLayoutNdx)
6481		{
6482			params.dst.image.operationLayout	= blitDstLayouts[dstLayoutNdx];
6483			params.filter						= VK_FILTER_NEAREST;
6484
6485			const std::string testName		= getImageLayoutCaseName(params.src.image.operationLayout) + "_" +
6486											  getImageLayoutCaseName(params.dst.image.operationLayout);
6487			const std::string description	= "Blit from " + getImageLayoutCaseName(params.src.image.operationLayout) +
6488											  " to " + getImageLayoutCaseName(params.dst.image.operationLayout);
6489
6490			group->addChild(new BlitImageTestCase(group->getTestContext(), testName + "_nearest", description, params));
6491		}
6492	}
6493}
6494
6495void addBlittingImageAllFormatsDepthStencilTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6496{
6497	const VkFormat	depthAndStencilFormats[]	=
6498	{
6499		VK_FORMAT_D16_UNORM,
6500		VK_FORMAT_X8_D24_UNORM_PACK32,
6501		VK_FORMAT_D32_SFLOAT,
6502		VK_FORMAT_S8_UINT,
6503		VK_FORMAT_D16_UNORM_S8_UINT,
6504		VK_FORMAT_D24_UNORM_S8_UINT,
6505		VK_FORMAT_D32_SFLOAT_S8_UINT,
6506	};
6507
6508	const VkImageSubresourceLayers	defaultDepthSourceLayer		= { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, 1u };
6509	const VkImageSubresourceLayers	defaultStencilSourceLayer	= { VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u };
6510
6511	for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < DE_LENGTH_OF_ARRAY(depthAndStencilFormats); ++compatibleFormatsIndex)
6512	{
6513		TestParams	params;
6514		params.src.image.imageType			= VK_IMAGE_TYPE_2D;
6515		params.src.image.extent				= defaultExtent;
6516		params.src.image.format				= depthAndStencilFormats[compatibleFormatsIndex];
6517		params.dst.image.extent				= defaultExtent;
6518		params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
6519		params.dst.image.format				= params.src.image.format;
6520		params.allocationKind				= allocationKind;
6521
6522		CopyRegion	region;
6523		for (int i = 0, j = 1; (i + defaultFourthSize / j < defaultSize) && (defaultFourthSize > j); i += defaultFourthSize / j++)
6524		{
6525			const VkOffset3D	srcOffset0	= {0, 0, 0};
6526			const VkOffset3D	srcOffset1	= {defaultSize, defaultSize, 1};
6527			const VkOffset3D	dstOffset0	= {i, 0, 0};
6528			const VkOffset3D	dstOffset1	= {i + defaultFourthSize / j, defaultFourthSize / j, 1};
6529
6530			if (tcu::hasDepthComponent(mapVkFormat(params.src.image.format).order))
6531			{
6532				const VkImageBlit			imageBlit	=
6533				{
6534					defaultDepthSourceLayer,		// VkImageSubresourceLayers	srcSubresource;
6535					{ srcOffset0 , srcOffset1 },	// VkOffset3D					srcOffsets[2];
6536					defaultDepthSourceLayer,		// VkImageSubresourceLayers	dstSubresource;
6537					{ dstOffset0 , dstOffset1 },	// VkOffset3D					dstOffset[2];
6538				};
6539				region.imageBlit	= imageBlit;
6540				params.regions.push_back(region);
6541			}
6542			if (tcu::hasStencilComponent(mapVkFormat(params.src.image.format).order))
6543			{
6544				const VkImageBlit			imageBlit	=
6545				{
6546					defaultStencilSourceLayer,		// VkImageSubresourceLayers	srcSubresource;
6547					{ srcOffset0 , srcOffset1 },	// VkOffset3D					srcOffsets[2];
6548					defaultStencilSourceLayer,		// VkImageSubresourceLayers	dstSubresource;
6549					{ dstOffset0 , dstOffset1 },	// VkOffset3D					dstOffset[2];
6550				};
6551				region.imageBlit	= imageBlit;
6552				params.regions.push_back(region);
6553			}
6554		}
6555		for (int i = 0; i < defaultSize; i += defaultFourthSize)
6556		{
6557			const VkOffset3D	srcOffset0	= {i, i, 0};
6558			const VkOffset3D	srcOffset1	= {i + defaultFourthSize, i + defaultFourthSize, 1};
6559			const VkOffset3D	dstOffset0	= {i, defaultSize / 2, 0};
6560			const VkOffset3D	dstOffset1	= {i + defaultFourthSize, defaultSize / 2 + defaultFourthSize, 1};
6561
6562			if (tcu::hasDepthComponent(mapVkFormat(params.src.image.format).order))
6563			{
6564				const VkImageBlit			imageBlit	=
6565				{
6566					defaultDepthSourceLayer,		// VkImageSubresourceLayers	srcSubresource;
6567					{ srcOffset0, srcOffset1 },		// VkOffset3D					srcOffsets[2];
6568					defaultDepthSourceLayer,		// VkImageSubresourceLayers	dstSubresource;
6569					{ dstOffset0, dstOffset1 }		// VkOffset3D					dstOffset[2];
6570				};
6571				region.imageBlit	= imageBlit;
6572				params.regions.push_back(region);
6573			}
6574			if (tcu::hasStencilComponent(mapVkFormat(params.src.image.format).order))
6575			{
6576				const VkImageBlit			imageBlit	=
6577				{
6578					defaultStencilSourceLayer,		// VkImageSubresourceLayers	srcSubresource;
6579					{ srcOffset0, srcOffset1 },		// VkOffset3D					srcOffsets[2];
6580					defaultStencilSourceLayer,		// VkImageSubresourceLayers	dstSubresource;
6581					{ dstOffset0, dstOffset1 }		// VkOffset3D					dstOffset[2];
6582				};
6583				region.imageBlit	= imageBlit;
6584				params.regions.push_back(region);
6585			}
6586		}
6587
6588		const std::string testName		= getFormatCaseName(params.src.image.format) + "_" +
6589										  getFormatCaseName(params.dst.image.format);
6590		const std::string description	= "Blit from " + getFormatCaseName(params.src.image.format) +
6591										  " to " + getFormatCaseName(params.dst.image.format);
6592		addTestGroup(group, testName, description, addBlittingImageAllFormatsDepthStencilFormatsTests, params);
6593	}
6594}
6595
6596void addBlittingImageAllFormatsMipmapFormatTests (tcu::TestCaseGroup* group, BlitColorTestParams testParams)
6597{
6598	tcu::TestContext& testCtx				= group->getTestContext();
6599
6600	const VkImageLayout blitSrcLayouts[]	=
6601	{
6602		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
6603		VK_IMAGE_LAYOUT_GENERAL
6604	};
6605	const VkImageLayout blitDstLayouts[]	=
6606	{
6607		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
6608		VK_IMAGE_LAYOUT_GENERAL
6609	};
6610
6611	for (int srcLayoutNdx = 0u; srcLayoutNdx < DE_LENGTH_OF_ARRAY(blitSrcLayouts); ++srcLayoutNdx)
6612	{
6613		testParams.params.src.image.operationLayout = blitSrcLayouts[srcLayoutNdx];
6614		for (int dstLayoutNdx = 0u; dstLayoutNdx < DE_LENGTH_OF_ARRAY(blitDstLayouts); ++dstLayoutNdx)
6615		{
6616			testParams.params.dst.image.operationLayout = blitDstLayouts[dstLayoutNdx];
6617
6618			testParams.params.filter			= VK_FILTER_NEAREST;
6619			const std::string testName			= getImageLayoutCaseName(testParams.params.src.image.operationLayout) + "_" +
6620												  getImageLayoutCaseName(testParams.params.dst.image.operationLayout);
6621			const std::string description		= "Blit from layout " + getImageLayoutCaseName(testParams.params.src.image.operationLayout) +
6622												  " to " + getImageLayoutCaseName(testParams.params.dst.image.operationLayout);
6623			group->addChild(new BlitMipmapTestCase(testCtx, testName + "_nearest", description, testParams.params));
6624
6625			if (!testParams.onlyNearest)
6626			{
6627				testParams.params.filter		= VK_FILTER_LINEAR;
6628				group->addChild(new BlitMipmapTestCase(testCtx, testName + "_linear", description, testParams.params));
6629			}
6630		}
6631	}
6632}
6633
6634void addBlittingImageAllFormatsBaseLevelMipmapTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6635{
6636	const struct
6637	{
6638		const VkFormat* const	compatibleFormats;
6639		const bool				onlyNearest;
6640	}	colorImageFormatsToTestBlit[]			=
6641	{
6642		{ compatibleFormatsUInts,	true	},
6643		{ compatibleFormatsSInts,	true	},
6644		{ compatibleFormatsFloats,	false	},
6645		{ compatibleFormatsSrgb,	false	},
6646	};
6647
6648	const int	numOfColorImageFormatsToTest		= DE_LENGTH_OF_ARRAY(colorImageFormatsToTestBlit);
6649
6650	TestParams	params;
6651	params.src.image.imageType	= VK_IMAGE_TYPE_2D;
6652	params.src.image.extent		= defaultExtent;
6653	params.dst.image.imageType	= VK_IMAGE_TYPE_2D;
6654	params.dst.image.extent		= defaultExtent;
6655	params.allocationKind		= allocationKind;
6656	params.mipLevels			= deLog2Floor32(deMinu32(defaultExtent.width, defaultExtent.height)) + 1u;
6657	params.singleCommand		= DE_TRUE;
6658
6659	CopyRegion	region;
6660	for (deUint32 mipLevelNdx = 0u; mipLevelNdx < params.mipLevels; mipLevelNdx++)
6661	{
6662		VkImageSubresourceLayers	destLayer	= defaultSourceLayer;
6663		destLayer.mipLevel = mipLevelNdx;
6664
6665		const VkImageBlit			imageBlit	=
6666		{
6667			defaultSourceLayer,	// VkImageSubresourceLayers	srcSubresource;
6668			{
6669				{0, 0, 0},
6670				{defaultSize, defaultSize, 1}
6671			},					// VkOffset3D					srcOffsets[2];
6672
6673			destLayer,			// VkImageSubresourceLayers	dstSubresource;
6674			{
6675				{0, 0, 0},
6676				{defaultSize >> mipLevelNdx, defaultSize >> mipLevelNdx, 1}
6677			}					// VkOffset3D					dstOffset[2];
6678		};
6679		region.imageBlit	= imageBlit;
6680		params.regions.push_back(region);
6681	}
6682
6683	if (allocationKind == ALLOCATION_KIND_DEDICATED)
6684	{
6685		const int numOfColorImageFormatsToTestFilter = DE_LENGTH_OF_ARRAY(dedicatedAllocationBlittingFormatsToTest);
6686		for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTestFilter; ++compatibleFormatsIndex)
6687			dedicatedAllocationBlittingFormatsToTestSet.insert(dedicatedAllocationBlittingFormatsToTest[compatibleFormatsIndex]);
6688	}
6689
6690	for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex)
6691	{
6692		const VkFormat*	compatibleFormats	= colorImageFormatsToTestBlit[compatibleFormatsIndex].compatibleFormats;
6693		const bool		onlyNearest			= colorImageFormatsToTestBlit[compatibleFormatsIndex].onlyNearest;
6694		for (int srcFormatIndex = 0; compatibleFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex)
6695		{
6696			params.src.image.format	= compatibleFormats[srcFormatIndex];
6697			params.dst.image.format	= compatibleFormats[srcFormatIndex];
6698
6699			if (!isSupportedByFramework(params.src.image.format))
6700				continue;
6701
6702			BlitColorTestParams		testParams;
6703			testParams.params				= params;
6704			testParams.compatibleFormats	= compatibleFormats;
6705			testParams.onlyNearest			= onlyNearest;
6706
6707			const std::string description	= "Blit source format " + getFormatCaseName(params.src.image.format);
6708			addTestGroup(group, getFormatCaseName(params.src.image.format), description, addBlittingImageAllFormatsMipmapFormatTests, testParams);
6709		}
6710	}
6711}
6712
6713void addBlittingImageAllFormatsPreviousLevelMipmapTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6714{
6715	const struct
6716	{
6717		const VkFormat* const	compatibleFormats;
6718		const bool				onlyNearest;
6719	}	colorImageFormatsToTestBlit[]			=
6720	{
6721		{ compatibleFormatsUInts,	true	},
6722		{ compatibleFormatsSInts,	true	},
6723		{ compatibleFormatsFloats,	false	},
6724		{ compatibleFormatsSrgb,	false	},
6725	};
6726
6727	const int	numOfColorImageFormatsToTest		= DE_LENGTH_OF_ARRAY(colorImageFormatsToTestBlit);
6728
6729	TestParams	params;
6730	params.src.image.imageType	= VK_IMAGE_TYPE_2D;
6731	params.src.image.extent		= defaultExtent;
6732	params.dst.image.imageType	= VK_IMAGE_TYPE_2D;
6733	params.dst.image.extent		= defaultExtent;
6734	params.allocationKind		= allocationKind;
6735	params.mipLevels			= deLog2Floor32(deMinu32(defaultExtent.width, defaultExtent.height)) + 1u;
6736	params.singleCommand		= DE_FALSE;
6737
6738	CopyRegion	region;
6739	for (deUint32 mipLevelNdx = 1u; mipLevelNdx < params.mipLevels; mipLevelNdx++)
6740	{
6741		VkImageSubresourceLayers	srcLayer	= defaultSourceLayer;
6742		VkImageSubresourceLayers	destLayer	= defaultSourceLayer;
6743
6744		srcLayer.mipLevel	= mipLevelNdx - 1u;
6745		destLayer.mipLevel	= mipLevelNdx;
6746
6747		const VkImageBlit			imageBlit	=
6748		{
6749			srcLayer,			// VkImageSubresourceLayers	srcSubresource;
6750			{
6751				{0, 0, 0},
6752				{defaultSize >> (mipLevelNdx - 1u), defaultSize >> (mipLevelNdx - 1u), 1}
6753			},					// VkOffset3D					srcOffsets[2];
6754
6755			destLayer,			// VkImageSubresourceLayers	dstSubresource;
6756			{
6757				{0, 0, 0},
6758				{defaultSize >> mipLevelNdx, defaultSize >> mipLevelNdx, 1}
6759			}					// VkOffset3D					dstOffset[2];
6760		};
6761		region.imageBlit	= imageBlit;
6762		params.regions.push_back(region);
6763	}
6764
6765	if (allocationKind == ALLOCATION_KIND_DEDICATED)
6766	{
6767		const int numOfColorImageFormatsToTestFilter = DE_LENGTH_OF_ARRAY(dedicatedAllocationBlittingFormatsToTest);
6768		for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTestFilter; ++compatibleFormatsIndex)
6769			dedicatedAllocationBlittingFormatsToTestSet.insert(dedicatedAllocationBlittingFormatsToTest[compatibleFormatsIndex]);
6770	}
6771
6772	for (int compatibleFormatsIndex = 0; compatibleFormatsIndex < numOfColorImageFormatsToTest; ++compatibleFormatsIndex)
6773	{
6774		const VkFormat*	compatibleFormats	= colorImageFormatsToTestBlit[compatibleFormatsIndex].compatibleFormats;
6775		const bool		onlyNearest			= colorImageFormatsToTestBlit[compatibleFormatsIndex].onlyNearest;
6776		for (int srcFormatIndex = 0; compatibleFormats[srcFormatIndex] != VK_FORMAT_UNDEFINED; ++srcFormatIndex)
6777		{
6778			params.src.image.format	= compatibleFormats[srcFormatIndex];
6779			params.dst.image.format	= compatibleFormats[srcFormatIndex];
6780
6781			if (!isSupportedByFramework(params.src.image.format))
6782				continue;
6783
6784			BlitColorTestParams		testParams;
6785			testParams.params				= params;
6786			testParams.compatibleFormats	= compatibleFormats;
6787			testParams.onlyNearest			= onlyNearest;
6788
6789			const std::string description	= "Blit source format " + getFormatCaseName(params.src.image.format);
6790			addTestGroup(group, getFormatCaseName(params.src.image.format), description, addBlittingImageAllFormatsMipmapFormatTests, testParams);
6791		}
6792	}
6793}
6794
6795void addBlittingImageAllFormatsMipmapTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6796{
6797	addTestGroup(group, "from_base_level", "Generate all mipmap levels from base level", addBlittingImageAllFormatsBaseLevelMipmapTests, allocationKind);
6798	addTestGroup(group, "from_previous_level", "Generate next mipmap level from previous level", addBlittingImageAllFormatsPreviousLevelMipmapTests, allocationKind);
6799}
6800
6801void addBlittingImageAllFormatsTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6802{
6803	addTestGroup(group, "color", "Blitting image with color formats", addBlittingImageAllFormatsColorTests, allocationKind);
6804	addTestGroup(group, "depth_stencil", "Blitting image with depth/stencil formats", addBlittingImageAllFormatsDepthStencilTests, allocationKind);
6805	addTestGroup(group, "generate_mipmaps", "Generating mipmaps with vkCmdBlitImage()", addBlittingImageAllFormatsMipmapTests, allocationKind);
6806}
6807
6808void addBlittingImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6809{
6810	addTestGroup(group, "simple_tests", "Blitting image simple tests", addBlittingImageSimpleTests, allocationKind);
6811	addTestGroup(group, "all_formats", "Blitting image with all compatible formats", addBlittingImageAllFormatsTests, allocationKind);
6812}
6813
6814const VkSampleCountFlagBits	samples[]		=
6815{
6816	VK_SAMPLE_COUNT_2_BIT,
6817	VK_SAMPLE_COUNT_4_BIT,
6818	VK_SAMPLE_COUNT_8_BIT,
6819	VK_SAMPLE_COUNT_16_BIT,
6820	VK_SAMPLE_COUNT_32_BIT,
6821	VK_SAMPLE_COUNT_64_BIT
6822};
6823const VkExtent3D			resolveExtent	= {256u, 256u, 1};
6824
6825void addResolveImageWholeTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6826{
6827	TestParams	params;
6828	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
6829	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
6830	params.src.image.extent				= resolveExtent;
6831	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
6832	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
6833	params.dst.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
6834	params.dst.image.extent				= resolveExtent;
6835	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
6836	params.allocationKind				= allocationKind;
6837
6838	{
6839		const VkImageSubresourceLayers	sourceLayer	=
6840		{
6841			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
6842			0u,							// uint32_t				mipLevel;
6843			0u,							// uint32_t				baseArrayLayer;
6844			1u							// uint32_t				layerCount;
6845		};
6846		const VkImageResolve			testResolve	=
6847		{
6848			sourceLayer,	// VkImageSubresourceLayers	srcSubresource;
6849			{0, 0, 0},		// VkOffset3D				srcOffset;
6850			sourceLayer,	// VkImageSubresourceLayers	dstSubresource;
6851			{0, 0, 0},		// VkOffset3D				dstOffset;
6852			resolveExtent,	// VkExtent3D				extent;
6853		};
6854
6855		CopyRegion	imageResolve;
6856		imageResolve.imageResolve	= testResolve;
6857		params.regions.push_back(imageResolve);
6858	}
6859
6860	for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex)
6861	{
6862		params.samples					= samples[samplesIndex];
6863		const std::string description	= "With " + getSampleCountCaseName(samples[samplesIndex]);
6864		group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params));
6865	}
6866}
6867
6868void addResolveImagePartialTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6869{
6870	TestParams	params;
6871	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
6872	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
6873	params.src.image.extent				= resolveExtent;
6874	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
6875	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
6876	params.dst.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
6877	params.dst.image.extent				= resolveExtent;
6878	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
6879	params.allocationKind				= allocationKind;
6880
6881	{
6882		const VkImageSubresourceLayers	sourceLayer	=
6883		{
6884			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
6885			0u,							// uint32_t				mipLevel;
6886			0u,							// uint32_t				baseArrayLayer;
6887			1u							// uint32_t				layerCount;
6888		};
6889		const VkImageResolve			testResolve	=
6890		{
6891			sourceLayer,	// VkImageSubresourceLayers	srcSubresource;
6892			{0, 0, 0},		// VkOffset3D				srcOffset;
6893			sourceLayer,	// VkImageSubresourceLayers	dstSubresource;
6894			{64u, 64u, 0},		// VkOffset3D				dstOffset;
6895			{128u, 128u, 1u},	// VkExtent3D				extent;
6896		};
6897
6898		CopyRegion	imageResolve;
6899		imageResolve.imageResolve = testResolve;
6900		params.regions.push_back(imageResolve);
6901	}
6902
6903	for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex)
6904	{
6905		params.samples					= samples[samplesIndex];
6906		const std::string description	= "With " + getSampleCountCaseName(samples[samplesIndex]);
6907		group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params));
6908	}
6909}
6910
6911void addResolveImageWithRegionsTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6912{
6913	TestParams	params;
6914	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
6915	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
6916	params.src.image.extent				= resolveExtent;
6917	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
6918	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
6919	params.dst.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
6920	params.dst.image.extent				= resolveExtent;
6921	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
6922	params.allocationKind				= allocationKind;
6923
6924	{
6925		const VkImageSubresourceLayers	sourceLayer	=
6926		{
6927			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
6928			0u,							// uint32_t				mipLevel;
6929			0u,							// uint32_t				baseArrayLayer;
6930			1u							// uint32_t				layerCount;
6931		};
6932
6933		for (int i = 0; i < 256; i += 64)
6934		{
6935			const VkImageResolve			testResolve	=
6936			{
6937				sourceLayer,	// VkImageSubresourceLayers	srcSubresource;
6938				{i, i, 0},		// VkOffset3D				srcOffset;
6939				sourceLayer,	// VkImageSubresourceLayers	dstSubresource;
6940				{i, 0, 0},		// VkOffset3D				dstOffset;
6941				{64u, 64u, 1u},	// VkExtent3D				extent;
6942			};
6943
6944			CopyRegion	imageResolve;
6945			imageResolve.imageResolve = testResolve;
6946			params.regions.push_back(imageResolve);
6947		}
6948	}
6949
6950	for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex)
6951	{
6952		params.samples					= samples[samplesIndex];
6953		const std::string description	= "With " + getSampleCountCaseName(samples[samplesIndex]);
6954		group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params));
6955	}
6956}
6957
6958void addResolveImageWholeCopyBeforeResolvingTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
6959{
6960	TestParams	params;
6961	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
6962	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
6963	params.src.image.extent				= defaultExtent;
6964	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
6965	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
6966	params.dst.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
6967	params.dst.image.extent				= defaultExtent;
6968	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
6969	params.allocationKind				= allocationKind;
6970
6971	{
6972		const VkImageSubresourceLayers	sourceLayer	=
6973		{
6974			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
6975			0u,							// uint32_t				mipLevel;
6976			0u,							// uint32_t				baseArrayLayer;
6977			1u							// uint32_t				layerCount;
6978		};
6979
6980		const VkImageResolve			testResolve	=
6981		{
6982			sourceLayer,		// VkImageSubresourceLayers	srcSubresource;
6983			{0, 0, 0},			// VkOffset3D				srcOffset;
6984			sourceLayer,		// VkImageSubresourceLayers	dstSubresource;
6985			{0, 0, 0},			// VkOffset3D				dstOffset;
6986			defaultExtent,		// VkExtent3D				extent;
6987		};
6988
6989		CopyRegion	imageResolve;
6990		imageResolve.imageResolve	= testResolve;
6991		params.regions.push_back(imageResolve);
6992	}
6993
6994	for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex)
6995	{
6996		params.samples					= samples[samplesIndex];
6997		const std::string description	= "With " + getSampleCountCaseName(samples[samplesIndex]);
6998		group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params, COPY_MS_IMAGE_TO_MS_IMAGE));
6999	}
7000}
7001
7002void addResolveImageWholeArrayImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
7003{
7004	TestParams	params;
7005	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
7006	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
7007	params.src.image.extent				= defaultExtent;
7008	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
7009	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
7010	params.dst.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
7011	params.dst.image.extent				= defaultExtent;
7012	params.dst.image.extent.depth		= 5u;
7013	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
7014	params.allocationKind				= allocationKind;
7015
7016	for (deUint32 layerNdx=0; layerNdx < params.dst.image.extent.depth; ++layerNdx)
7017	{
7018		const VkImageSubresourceLayers	sourceLayer	=
7019		{
7020			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
7021			0u,								// uint32_t				mipLevel;
7022			layerNdx,						// uint32_t				baseArrayLayer;
7023			1u								// uint32_t				layerCount;
7024		};
7025
7026		const VkImageResolve			testResolve	=
7027		{
7028			sourceLayer,		// VkImageSubresourceLayers	srcSubresource;
7029			{0, 0, 0},			// VkOffset3D				srcOffset;
7030			sourceLayer,		// VkImageSubresourceLayers	dstSubresource;
7031			{0, 0, 0},			// VkOffset3D				dstOffset;
7032			defaultExtent,		// VkExtent3D				extent;
7033		};
7034
7035		CopyRegion	imageResolve;
7036		imageResolve.imageResolve	= testResolve;
7037		params.regions.push_back(imageResolve);
7038	}
7039
7040	for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex)
7041	{
7042		params.samples					= samples[samplesIndex];
7043		const std::string description	= "With " + getSampleCountCaseName(samples[samplesIndex]);
7044		group->addChild(new ResolveImageToImageTestCase(group->getTestContext(), getSampleCountCaseName(samples[samplesIndex]), description, params, COPY_MS_IMAGE_TO_ARRAY_MS_IMAGE));
7045	}
7046}
7047
7048void addResolveImageDiffImageSizeTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
7049{
7050	tcu::TestContext&	testCtx			= group->getTestContext();
7051	TestParams			params;
7052	params.src.image.imageType			= VK_IMAGE_TYPE_2D;
7053	params.src.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
7054	params.src.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
7055	params.dst.image.imageType			= VK_IMAGE_TYPE_2D;
7056	params.dst.image.format				= VK_FORMAT_R8G8B8A8_UNORM;
7057	params.dst.image.operationLayout	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
7058	params.allocationKind				= allocationKind;
7059
7060	{
7061		const VkImageSubresourceLayers	sourceLayer	=
7062		{
7063			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
7064			0u,							// uint32_t				mipLevel;
7065			0u,							// uint32_t				baseArrayLayer;
7066			1u							// uint32_t				layerCount;
7067		};
7068		const VkImageResolve			testResolve	=
7069		{
7070			sourceLayer,	// VkImageSubresourceLayers	srcSubresource;
7071			{0, 0, 0},		// VkOffset3D				srcOffset;
7072			sourceLayer,	// VkImageSubresourceLayers	dstSubresource;
7073			{0, 0, 0},		// VkOffset3D				dstOffset;
7074			resolveExtent,	// VkExtent3D				extent;
7075		};
7076		CopyRegion	imageResolve;
7077		imageResolve.imageResolve	= testResolve;
7078		params.regions.push_back(imageResolve);
7079	}
7080
7081	const VkExtent3D imageExtents[]		=
7082	{
7083		{ resolveExtent.width + 10,	resolveExtent.height,		resolveExtent.depth },
7084		{ resolveExtent.width,		resolveExtent.height * 2,	resolveExtent.depth },
7085		{ resolveExtent.width,		resolveExtent.height,		resolveExtent.depth + 10 }
7086	};
7087
7088	for (int srcImageExtentIndex = 0; srcImageExtentIndex < DE_LENGTH_OF_ARRAY(imageExtents); ++srcImageExtentIndex)
7089	{
7090		const VkExtent3D&	srcImageSize	= imageExtents[srcImageExtentIndex];
7091		params.src.image.extent				= srcImageSize;
7092		params.dst.image.extent				= resolveExtent;
7093		for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex)
7094		{
7095			params.samples	= samples[samplesIndex];
7096			std::ostringstream testName;
7097			testName << "src_" << srcImageSize.width << "_" << srcImageSize.height << "_" << srcImageSize.depth << "_" << getSampleCountCaseName(samples[samplesIndex]);
7098			std::ostringstream description;
7099			description << "With " << getSampleCountCaseName(samples[samplesIndex]) << " and source image size ("
7100						<< srcImageSize.width << ", " << srcImageSize.height << ", " << srcImageSize.depth << ")";
7101			group->addChild(new ResolveImageToImageTestCase(testCtx, testName.str(), description.str(), params));
7102		}
7103	}
7104	for (int dstImageExtentIndex = 0; dstImageExtentIndex < DE_LENGTH_OF_ARRAY(imageExtents); ++dstImageExtentIndex)
7105	{
7106		const VkExtent3D&	dstImageSize	= imageExtents[dstImageExtentIndex];
7107		params.src.image.extent				= resolveExtent;
7108		params.dst.image.extent				= dstImageSize;
7109		for (int samplesIndex = 0; samplesIndex < DE_LENGTH_OF_ARRAY(samples); ++samplesIndex)
7110		{
7111			params.samples	= samples[samplesIndex];
7112			std::ostringstream testName;
7113			testName << "dst_" << dstImageSize.width << "_" << dstImageSize.height << "_" << dstImageSize.depth << "_" << getSampleCountCaseName(samples[samplesIndex]);
7114			std::ostringstream description;
7115			description << "With " << getSampleCountCaseName(samples[samplesIndex]) << " and destination image size ("
7116						<< dstImageSize.width << ", " << dstImageSize.height << ", " << dstImageSize.depth << ")";
7117			group->addChild(new ResolveImageToImageTestCase(testCtx, testName.str(), description.str(), params));
7118		}
7119	}
7120}
7121
7122void addResolveImageTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
7123{
7124	addTestGroup(group, "whole", "Resolve from image to image (whole)", addResolveImageWholeTests, allocationKind);
7125	addTestGroup(group, "partial", "Resolve from image to image (partial)", addResolveImagePartialTests, allocationKind);
7126	addTestGroup(group, "with_regions", "Resolve from image to image (with regions)", addResolveImageWithRegionsTests, allocationKind);
7127	addTestGroup(group, "whole_copy_before_resolving", "Resolve from image to image (whole copy before resolving)", addResolveImageWholeCopyBeforeResolvingTests, allocationKind);
7128	addTestGroup(group, "whole_array_image", "Resolve from image to image (whole array image)", addResolveImageWholeArrayImageTests, allocationKind);
7129	addTestGroup(group, "diff_image_size", "Resolve from image to image of different size", addResolveImageDiffImageSizeTests, allocationKind);
7130}
7131
7132void addCopiesAndBlittingTests (tcu::TestCaseGroup* group, AllocationKind allocationKind)
7133{
7134	addTestGroup(group, "image_to_image", "Copy from image to image", addImageToImageTests, allocationKind);
7135	addTestGroup(group, "image_to_buffer", "Copy from image to buffer", addImageToBufferTests, allocationKind);
7136	addTestGroup(group, "buffer_to_image", "Copy from buffer to image", addBufferToImageTests, allocationKind);
7137	addTestGroup(group, "buffer_to_buffer", "Copy from buffer to buffer", addBufferToBufferTests, allocationKind);
7138	addTestGroup(group, "blit_image", "Blitting image", addBlittingImageTests, allocationKind);
7139	addTestGroup(group, "resolve_image", "Resolve image", addResolveImageTests, allocationKind);
7140}
7141
7142void addCoreCopiesAndBlittingTests (tcu::TestCaseGroup* group)
7143{
7144	addCopiesAndBlittingTests(group, ALLOCATION_KIND_SUBALLOCATED);
7145}
7146
7147void addDedicatedAllocationCopiesAndBlittingTests (tcu::TestCaseGroup* group)
7148{
7149	addCopiesAndBlittingTests(group, ALLOCATION_KIND_DEDICATED);
7150}
7151
7152} // anonymous
7153
7154tcu::TestCaseGroup* createCopiesAndBlittingTests (tcu::TestContext& testCtx)
7155{
7156	de::MovePtr<tcu::TestCaseGroup>	copiesAndBlittingTests(new tcu::TestCaseGroup(testCtx, "copy_and_blit", "Copies And Blitting Tests"));
7157
7158	copiesAndBlittingTests->addChild(createTestGroup(testCtx, "core",					"Core Copies And Blitting Tests",								addCoreCopiesAndBlittingTests));
7159	copiesAndBlittingTests->addChild(createTestGroup(testCtx, "dedicated_allocation",	"Copies And Blitting Tests For Dedicated Memory Allocation",	addDedicatedAllocationCopiesAndBlittingTests));
7160
7161	return copiesAndBlittingTests.release();
7162}
7163
7164} // api
7165} // vkt
7166